summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorKévin THIERRY <kevin.thierry@open.eurogiciel.org>2014-12-23 09:30:24 +0100
committerKévin THIERRY <kevin.thierry@open.eurogiciel.org>2014-12-23 09:30:24 +0100
commit317dbdb79761ef65e45c7358cfc7571c6afa54ad (patch)
treed6e8d59029aea04ca4a0579fb1c19c3e493af78f /Source
parent297c63fa65327491a2b50e521b661c5835a19fe4 (diff)
downloadcmake-317dbdb79761ef65e45c7358cfc7571c6afa54ad.tar.gz
cmake-317dbdb79761ef65e45c7358cfc7571c6afa54ad.tar.bz2
cmake-317dbdb79761ef65e45c7358cfc7571c6afa54ad.zip
Imported Upstream version 2.8.12.2upstream/2.8.12.2sandbox/kevinthierry/upstream
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt28
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx141
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.h6
-rw-r--r--Source/CPack/cmCPackDocumentVariables.cxx4
-rw-r--r--Source/CPack/cmCPackGenerator.cxx2
-rw-r--r--Source/CTest/cmCTestBatchTestHandler.cxx2
-rw-r--r--Source/CTest/cmCTestBuildCommand.cxx3
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx26
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx27
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx122
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.h15
-rw-r--r--Source/CTest/cmCTestRunTest.cxx22
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx2
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx14
-rw-r--r--Source/CTest/cmCTestTestHandler.h2
-rw-r--r--Source/CTest/cmParseGTMCoverage.cxx4
-rw-r--r--Source/CTest/cmProcess.cxx8
-rw-r--r--Source/CursesDialog/CMakeLists.txt2
-rw-r--r--Source/CursesDialog/form/frm_driver.c6
-rw-r--r--Source/CursesDialog/form/fty_enum.c2
-rw-r--r--Source/CursesDialog/form/fty_ipv4.c2
-rw-r--r--Source/CursesDialog/form/fty_regex.c2
-rw-r--r--Source/QtDialog/CMakeLists.txt18
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx163
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h6
-rw-r--r--Source/QtDialog/CMakeSetupDialog.ui5
-rw-r--r--Source/QtDialog/QCMakeCacheView.cxx2
-rw-r--r--Source/cmAddCompileOptionsCommand.cxx28
-rw-r--r--Source/cmAddCompileOptionsCommand.h71
-rw-r--r--Source/cmAddDefinitionsCommand.h4
-rw-r--r--Source/cmAddDependenciesCommand.cxx7
-rw-r--r--Source/cmAddExecutableCommand.cxx72
-rw-r--r--Source/cmAddExecutableCommand.h13
-rw-r--r--Source/cmAddLibraryCommand.cxx80
-rw-r--r--Source/cmAddLibraryCommand.h13
-rw-r--r--Source/cmAddSubDirectoryCommand.h2
-rw-r--r--Source/cmAddTestCommand.h3
-rw-r--r--Source/cmBootstrapCommands1.cxx91
-rw-r--r--Source/cmBootstrapCommands2.cxx (renamed from Source/cmBootstrapCommands.cxx)74
-rw-r--r--Source/cmBuildCommand.cxx4
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.cxx126
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.h102
-rw-r--r--Source/cmCPluginAPI.cxx5
-rw-r--r--Source/cmCTest.cxx15
-rw-r--r--Source/cmCTest.h1
-rw-r--r--Source/cmCacheManager.cxx6
-rw-r--r--Source/cmCacheManager.h2
-rw-r--r--Source/cmCommandArgumentLexer.cxx30
-rw-r--r--Source/cmCommandArgumentLexer.in.l1
-rw-r--r--Source/cmCommandArgumentParser.y1
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx4
-rw-r--r--Source/cmCommands.cxx6
-rw-r--r--Source/cmCommands.h5
-rw-r--r--Source/cmComputeLinkInformation.cxx92
-rw-r--r--Source/cmComputeLinkInformation.h3
-rw-r--r--Source/cmComputeTargetDepends.cxx2
-rw-r--r--Source/cmConfigure.cmake.h.in2
-rw-r--r--Source/cmCoreTryCompile.cxx426
-rw-r--r--Source/cmCustomCommand.cxx28
-rw-r--r--Source/cmCustomCommand.h1
-rw-r--r--Source/cmDependsC.cxx18
-rw-r--r--Source/cmDependsFortranLexer.cxx40
-rw-r--r--Source/cmDependsFortranLexer.in.l1
-rw-r--r--Source/cmDependsFortranParser.y1
-rw-r--r--Source/cmDependsJavaLexer.cxx30
-rw-r--r--Source/cmDependsJavaLexer.in.l1
-rw-r--r--Source/cmDependsJavaParser.cxx16
-rw-r--r--Source/cmDependsJavaParser.y1
-rw-r--r--Source/cmDocumentCompileDefinitions.h2
-rw-r--r--Source/cmDocumentGeneratorExpressions.h25
-rw-r--r--Source/cmDocumentVariables.cxx367
-rw-r--r--Source/cmDocumentation.cxx4
-rw-r--r--Source/cmELF.cxx7
-rw-r--r--Source/cmEnableLanguageCommand.h17
-rw-r--r--Source/cmExportBuildFileGenerator.cxx34
-rw-r--r--Source/cmExportBuildFileGenerator.h2
-rw-r--r--Source/cmExportCommand.cxx13
-rw-r--r--Source/cmExportCommand.h7
-rw-r--r--Source/cmExportFileGenerator.cxx124
-rw-r--r--Source/cmExportFileGenerator.h18
-rw-r--r--Source/cmExportInstallFileGenerator.cxx84
-rw-r--r--Source/cmExportInstallFileGenerator.h2
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx25
-rw-r--r--Source/cmExportTryCompileFileGenerator.h2
-rw-r--r--Source/cmExprLexer.cxx30
-rw-r--r--Source/cmExprLexer.in.l1
-rw-r--r--Source/cmExprParser.cxx16
-rw-r--r--Source/cmExprParser.y1
-rw-r--r--Source/cmExprParserHelper.cxx4
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx18
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx33
-rw-r--r--Source/cmExtraEclipseCDT4Generator.h1
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx33
-rw-r--r--Source/cmFileCommand.cxx86
-rw-r--r--Source/cmFileCommand.h19
-rw-r--r--Source/cmFunctionCommand.cxx2
-rw-r--r--Source/cmGeneratorExpression.cxx55
-rw-r--r--Source/cmGeneratorExpression.h3
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx52
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h26
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.cxx151
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.h48
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx586
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h8
-rw-r--r--Source/cmGeneratorExpressionParser.cxx20
-rw-r--r--Source/cmGeneratorTarget.cxx63
-rw-r--r--Source/cmGeneratorTarget.h8
-rw-r--r--Source/cmGetCMakePropertyCommand.cxx2
-rw-r--r--Source/cmGetFilenameComponentCommand.cxx2
-rw-r--r--Source/cmGetFilenameComponentCommand.h3
-rw-r--r--Source/cmGetPropertyCommand.cxx15
-rw-r--r--Source/cmGetTargetPropertyCommand.cxx25
-rw-r--r--Source/cmGlobalGenerator.cxx186
-rw-r--r--Source/cmGlobalGenerator.h26
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx235
-rw-r--r--Source/cmGlobalNinjaGenerator.h42
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx8
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h3
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx63
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h11
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx97
-rw-r--r--Source/cmGlobalVisualStudio11Generator.h4
-rw-r--r--Source/cmGlobalVisualStudio12Generator.cxx19
-rw-r--r--Source/cmGlobalVisualStudio12Generator.h8
-rw-r--r--Source/cmGlobalVisualStudio6Generator.cxx3
-rw-r--r--Source/cmGlobalVisualStudio6Generator.h1
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx11
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx38
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h9
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx26
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h5
-rw-r--r--Source/cmGlobalVisualStudio9Generator.cxx7
-rw-r--r--Source/cmGlobalVisualStudio9Generator.h2
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx6
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h1
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx348
-rw-r--r--Source/cmGlobalXCodeGenerator.h3
-rw-r--r--Source/cmIDEOptions.cxx5
-rw-r--r--Source/cmIDEOptions.h1
-rw-r--r--Source/cmIfCommand.cxx40
-rw-r--r--Source/cmIncludeCommand.cxx2
-rw-r--r--Source/cmIncludeCommand.h9
-rw-r--r--Source/cmInstallCommand.cxx59
-rw-r--r--Source/cmInstallCommand.h10
-rw-r--r--Source/cmInstallCommandArguments.cxx34
-rw-r--r--Source/cmInstallCommandArguments.h13
-rw-r--r--Source/cmInstallExportGenerator.cxx3
-rw-r--r--Source/cmInstallExportGenerator.h3
-rw-r--r--Source/cmInstallTargetGenerator.cxx96
-rw-r--r--Source/cmListFileCache.cxx222
-rw-r--r--Source/cmListFileCache.h17
-rw-r--r--Source/cmListFileLexer.c441
-rw-r--r--Source/cmListFileLexer.h1
-rw-r--r--Source/cmListFileLexer.in.l27
-rw-r--r--Source/cmLocalGenerator.cxx219
-rw-r--r--Source/cmLocalGenerator.h18
-rw-r--r--Source/cmLocalNinjaGenerator.cxx25
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx13
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx178
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx106
-rw-r--r--Source/cmLocalVisualStudio7Generator.h2
-rw-r--r--Source/cmLocalXCodeGenerator.cxx9
-rw-r--r--Source/cmLocalXCodeGenerator.h1
-rw-r--r--Source/cmMacroCommand.cxx2
-rw-r--r--Source/cmMakefile.cxx294
-rw-r--r--Source/cmMakefile.h48
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx17
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx35
-rw-r--r--Source/cmMakefileTargetGenerator.cxx63
-rw-r--r--Source/cmMakefileTargetGenerator.h1
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.cxx3
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx111
-rw-r--r--Source/cmNinjaTargetGenerator.cxx81
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx19
-rw-r--r--Source/cmOSXBundleGenerator.cxx123
-rw-r--r--Source/cmOSXBundleGenerator.h24
-rw-r--r--Source/cmOrderDirectories.cxx35
-rw-r--r--Source/cmPolicies.cxx78
-rw-r--r--Source/cmPolicies.h4
-rw-r--r--Source/cmProjectCommand.h8
-rw-r--r--Source/cmQtAutomoc.cxx241
-rw-r--r--Source/cmQtAutomoc.h5
-rw-r--r--Source/cmSetPropertyCommand.cxx11
-rw-r--r--Source/cmSetTargetPropertiesCommand.cxx5
-rw-r--r--Source/cmSetTargetPropertiesCommand.h2
-rw-r--r--Source/cmSourceFile.cxx4
-rw-r--r--Source/cmStringCommand.cxx42
-rw-r--r--Source/cmStringCommand.h6
-rw-r--r--Source/cmSubdirCommand.cxx2
-rw-r--r--Source/cmSystemTools.cxx101
-rw-r--r--Source/cmSystemTools.h19
-rw-r--r--Source/cmTarget.cxx1432
-rw-r--r--Source/cmTarget.h119
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.cxx2
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.h2
-rw-r--r--Source/cmTargetCompileOptionsCommand.cxx62
-rw-r--r--Source/cmTargetCompileOptionsCommand.h90
-rw-r--r--Source/cmTargetExport.h3
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.cxx34
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.h16
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx177
-rw-r--r--Source/cmTargetLinkLibrariesCommand.h63
-rw-r--r--Source/cmTargetPropCommandBase.cxx69
-rw-r--r--Source/cmTargetPropCommandBase.h13
-rw-r--r--Source/cmTest.cxx2
-rw-r--r--Source/cmTryCompileCommand.h14
-rw-r--r--Source/cmVS10LinkFlagTable.h2
-rw-r--r--Source/cmVS11LinkFlagTable.h2
-rw-r--r--Source/cmVS12LinkFlagTable.h2
-rw-r--r--Source/cmVariableWatch.cxx51
-rw-r--r--Source/cmVariableWatch.h20
-rw-r--r--Source/cmVariableWatchCommand.cxx175
-rw-r--r--Source/cmVariableWatchCommand.h17
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx267
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h4
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx9
-rw-r--r--Source/cmVisualStudioGeneratorOptions.h6
-rw-r--r--Source/cmVisualStudioSlnData.cxx62
-rw-r--r--Source/cmVisualStudioSlnData.h58
-rw-r--r--Source/cmVisualStudioSlnParser.cxx712
-rw-r--r--Source/cmVisualStudioSlnParser.h118
-rw-r--r--Source/cmVisualStudioWCEPlatformParser.cxx8
-rw-r--r--Source/cmWhileCommand.cxx4
-rw-r--r--Source/cmWin32ProcessExecution.cxx2
-rw-r--r--Source/cmWin32ProcessExecution.h2
-rw-r--r--Source/cm_sha2.c12
-rw-r--r--Source/cmake.cxx56
-rw-r--r--Source/cmake.h8
-rw-r--r--Source/cmakemain.cxx19
-rw-r--r--Source/cmakewizard.cxx11
-rw-r--r--Source/cmcldeps.cxx35
-rw-r--r--Source/ctest.cxx9
-rw-r--r--Source/kwsys/CMakeLists.txt96
-rw-r--r--Source/kwsys/CommandLineArguments.hxx.in10
-rw-r--r--Source/kwsys/RegularExpression.cxx114
-rw-r--r--Source/kwsys/SharedForward.h.in2
-rw-r--r--Source/kwsys/SystemInformation.cxx384
-rw-r--r--Source/kwsys/SystemInformation.hxx.in10
-rw-r--r--Source/kwsys/SystemTools.cxx287
-rw-r--r--Source/kwsys/SystemTools.hxx.in9
-rw-r--r--Source/kwsys/auto_ptr.hxx.in18
-rw-r--r--Source/kwsys/hashtable.hxx.in18
-rw-r--r--Source/kwsys/kwsysPlatformTests.cmake3
-rw-r--r--Source/kwsys/kwsysPlatformTestsCXX.cxx67
-rw-r--r--Source/kwsys/testDynamicLoader.cxx4
-rw-r--r--Source/kwsys/testIOS.cxx2
-rw-r--r--Source/kwsys/testSystemInformation.cxx25
249 files changed, 10159 insertions, 2871 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index f0519fe7c..8412e3e86 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -11,7 +11,11 @@
#=============================================================================
include(CheckIncludeFile)
# Check if we can build support for ELF parsing.
-CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H)
+if(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD")
+ CHECK_INCLUDE_FILES("stdint.h;elf_abi.h" HAVE_ELF_H)
+else()
+ CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H)
+endif()
if(HAVE_ELF_H)
set(CMAKE_USE_ELF_PARSER 1)
else()
@@ -113,7 +117,8 @@ endif()
set(SRCS
cmStandardIncludes.cxx
cmArchiveWrite.cxx
- cmBootstrapCommands.cxx
+ cmBootstrapCommands1.cxx
+ cmBootstrapCommands2.cxx
cmCacheManager.cxx
cmCacheManager.h
cmCommands.cxx
@@ -359,6 +364,10 @@ if (WIN32)
cmLocalVisualStudio7Generator.h
cmLocalVisualStudioGenerator.cxx
cmLocalVisualStudioGenerator.h
+ cmVisualStudioSlnData.h
+ cmVisualStudioSlnData.cxx
+ cmVisualStudioSlnParser.h
+ cmVisualStudioSlnParser.cxx
cmVisualStudioWCEPlatformParser.h
cmVisualStudioWCEPlatformParser.cxx
cmWin32ProcessExecution.cxx
@@ -385,7 +394,7 @@ if(WIN32 AND NOT CYGWIN AND NOT BORLAND)
set_source_files_properties(cmcldeps.cxx PROPERTIES COMPILE_DEFINITIONS _WIN32_WINNT=0x0501)
add_executable(cmcldeps cmcldeps.cxx)
target_link_libraries(cmcldeps CMakeLib)
- install_targets(/bin cmcldeps)
+ install(TARGETS cmcldeps DESTINATION bin)
endif()
# create a library used by the command line and the GUI
@@ -539,12 +548,13 @@ endif()
add_executable(cmake cmakemain.cxx)
target_link_libraries(cmake CMakeLib)
-# Build special executable for running programs on Windows 98
+# Build special executable for running programs on Windows 98.
+# Included on any Windows (unconditional packaging required!).
if(WIN32)
if(NOT UNIX)
add_executable(cmw9xcom cmw9xcom.cxx)
target_link_libraries(cmw9xcom CMakeLib)
- install_targets(/bin cmw9xcom)
+ install(TARGETS cmw9xcom DESTINATION bin)
endif()
endif()
@@ -570,11 +580,9 @@ endif()
include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
-install_targets(/bin cmake)
-install_targets(/bin ctest)
-install_targets(/bin cpack)
+install(TARGETS cmake ctest cpack DESTINATION bin)
if(APPLE)
- install_targets(/bin cmakexbuild)
+ install(TARGETS cmakexbuild DESTINATION bin)
endif()
-install_files(${CMAKE_DATA_DIR}/include cmCPluginAPI.h)
+install(FILES cmCPluginAPI.h DESTINATION ${CMAKE_DATA_DIR}/include)
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index a8b890775..fd315ce6c 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,6 +1,6 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 2)
set(CMake_VERSION_MINOR 8)
-set(CMake_VERSION_PATCH 11)
+set(CMake_VERSION_PATCH 12)
set(CMake_VERSION_TWEAK 2)
#set(CMake_VERSION_RC 0)
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index e8b0ea971..cc9dec7b8 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -100,6 +100,11 @@ bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles)
command << " -nologo";
command << " -out " << QuotePath(packageFileNames.at(0));
command << " -ext WixUIExtension";
+ const char* const cultures = GetOption("CPACK_WIX_CULTURES");
+ if(cultures)
+ {
+ command << " -cultures:" << cultures;
+ }
command << " " << objectFiles;
return RunWiXCommand(command.str());
@@ -224,6 +229,9 @@ bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON");
CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER");
CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG");
+ SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER",
+ GetOption("CPACK_PACKAGE_NAME"));
+ CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER");
return true;
}
@@ -339,25 +347,114 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
featureDefinitions.BeginElement("FeatureRef");
featureDefinitions.AddAttribute("Id", "ProductFeature");
+ const char *cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES");
+ std::vector<std::string> cpackPkgExecutables;
+ std::string regKey;
+ if ( cpackPackageExecutables )
+ {
+ cmSystemTools::ExpandListArgument(cpackPackageExecutables,
+ cpackPkgExecutables);
+ if ( cpackPkgExecutables.size() % 2 != 0 )
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPACK_PACKAGE_EXECUTABLES should contain pairs of <executable> and "
+ "<icon name>." << std::endl);
+ cpackPkgExecutables.clear();
+ }
+
+ const char *cpackVendor = GetOption("CPACK_PACKAGE_VENDOR");
+ const char *cpackPkgName = GetOption("CPACK_PACKAGE_NAME");
+ if (!cpackVendor || !cpackPkgName)
+ {
+ cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_PACKAGE_VENDOR and "
+ "CPACK_PACKAGE_NAME must be defined for shortcut creation" << std::endl);
+ cpackPkgExecutables.clear();
+ }
+ else
+ {
+ regKey = std::string("Software/") + cpackVendor + "/" + cpackPkgName;
+ }
+ }
+
+ std::vector<std::string> dirIdExecutables;
AddDirectoryAndFileDefinitons(
toplevel, "INSTALL_ROOT",
directoryDefinitions, fileDefinitions, featureDefinitions,
- directoryCounter, fileCounter);
+ directoryCounter, fileCounter, cpackPkgExecutables, dirIdExecutables);
- featureDefinitions.EndElement();
- featureDefinitions.EndElement();
- fileDefinitions.EndElement();
+ directoryDefinitions.EndElement();
+ directoryDefinitions.EndElement();
- for(size_t i = 1; i < install_root.size(); ++i)
+ if (dirIdExecutables.size() > 0 && dirIdExecutables.size() % 3 == 0)
{
- directoryDefinitions.EndElement();
- }
+ fileDefinitions.BeginElement("DirectoryRef");
+ fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER");
+ fileDefinitions.BeginElement("Component");
+ fileDefinitions.AddAttribute("Id", "SHORTCUT");
+ fileDefinitions.AddAttribute("Guid", "*");
- directoryDefinitions.EndElement();
- directoryDefinitions.EndElement();
+ std::vector<std::string>::iterator it;
+ for ( it = dirIdExecutables.begin() ;
+ it != dirIdExecutables.end();
+ ++it)
+ {
+ std::string fileName = *it++;
+ std::string iconName = *it++;
+ std::string directoryId = *it;
+
+ fileDefinitions.BeginElement("Shortcut");
+ std::string shortcutName = fileName; // the iconName is mor likely to contain blanks early on
+ std::string::size_type const dotPos = shortcutName.find('.');
+ if(std::string::npos == dotPos)
+ { shortcutName = shortcutName.substr(0, dotPos); }
+ fileDefinitions.AddAttribute("Id", "SHORTCUT_" + shortcutName);
+ fileDefinitions.AddAttribute("Name", iconName);
+ std::string target = "[" + directoryId + "]" + fileName;
+ fileDefinitions.AddAttribute("Target", target);
+ fileDefinitions.AddAttribute("WorkingDirectory", directoryId);
+ fileDefinitions.EndElement();
+ }
+ fileDefinitions.BeginElement("Shortcut");
+ fileDefinitions.AddAttribute("Id", "UNINSTALL");
+ std::string pkgName = GetOption("CPACK_PACKAGE_NAME");
+ fileDefinitions.AddAttribute("Name", "Uninstall " + pkgName);
+ fileDefinitions.AddAttribute("Description", "Uninstalls " + pkgName);
+ fileDefinitions.AddAttribute("Target", "[SystemFolder]msiexec.exe");
+ fileDefinitions.AddAttribute("Arguments", "/x [ProductCode]");
+ fileDefinitions.EndElement();
+ fileDefinitions.BeginElement("RemoveFolder");
+ fileDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER");
+ fileDefinitions.AddAttribute("On", "uninstall");
+ fileDefinitions.EndElement();
+ fileDefinitions.BeginElement("RegistryValue");
+ fileDefinitions.AddAttribute("Root", "HKCU");
+ fileDefinitions.AddAttribute("Key", regKey);
+ fileDefinitions.AddAttribute("Name", "installed");
+ fileDefinitions.AddAttribute("Type", "integer");
+ fileDefinitions.AddAttribute("Value", "1");
+ fileDefinitions.AddAttribute("KeyPath", "yes");
+
+ featureDefinitions.BeginElement("ComponentRef");
+ featureDefinitions.AddAttribute("Id", "SHORTCUT");
+ featureDefinitions.EndElement();
+ directoryDefinitions.BeginElement("Directory");
+ directoryDefinitions.AddAttribute("Id", "ProgramMenuFolder");
+ directoryDefinitions.BeginElement("Directory");
+ directoryDefinitions.AddAttribute("Id", "PROGRAM_MENU_FOLDER");
+ const char *startMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER");
+ directoryDefinitions.AddAttribute("Name", startMenuFolder);
+ }
+
+ featureDefinitions.EndElement();
+ featureDefinitions.EndElement();
+ fileDefinitions.EndElement();
directoryDefinitions.EndElement();
std::string wixTemplate = FindTemplate("WIX.template.in");
+ if(GetOption("CPACK_WIX_TEMPLATE") != 0)
+ {
+ wixTemplate = GetOption("CPACK_WIX_TEMPLATE");
+ }
if(wixTemplate.empty())
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -435,7 +532,9 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
cmWIXSourceWriter& fileDefinitions,
cmWIXSourceWriter& featureDefinitions,
size_t& directoryCounter,
- size_t& fileCounter)
+ size_t& fileCounter,
+ const std::vector<std::string>& pkgExecutables,
+ std::vector<std::string>& dirIdExecutables)
{
cmsys::Directory dir;
dir.Load(topdir.c_str());
@@ -467,8 +566,9 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
fileDefinitions,
featureDefinitions,
directoryCounter,
- fileCounter);
-
+ fileCounter,
+ pkgExecutables,
+ dirIdExecutables);
directoryDefinitions.EndElement();
}
else
@@ -499,6 +599,23 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
featureDefinitions.BeginElement("ComponentRef");
featureDefinitions.AddAttribute("Id", componentId);
featureDefinitions.EndElement();
+
+ std::vector<std::string>::const_iterator it;
+ for (it = pkgExecutables.begin() ;
+ it != pkgExecutables.end() ;
+ ++it)
+ {
+ std::string execName = *it++;
+ std::string iconName = *it;
+
+ if (cmSystemTools::LowerCase(fileName) ==
+ cmSystemTools::LowerCase(execName) + ".exe")
+ {
+ dirIdExecutables.push_back(fileName);
+ dirIdExecutables.push_back(iconName);
+ dirIdExecutables.push_back(directoryId);
+ }
+ }
}
}
}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
index 0e95d70f6..aaccf9d46 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.h
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -83,7 +83,11 @@ private:
cmWIXSourceWriter& fileDefinitions,
cmWIXSourceWriter& featureDefinitions,
size_t& directoryCounter,
- size_t& fileCounter);
+ size_t& fileCounter,
+ const std::vector<std::string>& pkgExecutables,
+ std::vector<std::string>& dirIdExecutables
+ );
+
bool RequireOption(const std::string& name, std::string& value) const;
diff --git a/Source/CPack/cmCPackDocumentVariables.cxx b/Source/CPack/cmCPackDocumentVariables.cxx
index 6a841fa8d..8b16ae985 100644
--- a/Source/CPack/cmCPackDocumentVariables.cxx
+++ b/Source/CPack/cmCPackDocumentVariables.cxx
@@ -28,7 +28,7 @@ void cmCPackDocumentVariables::DefineVariables(cmake* cm)
" the so-called top level directory. The purpose of"
" is to include (set to 1 or ON or TRUE) the top level directory"
" in the package or not (set to 0 or OFF or FALSE).\n"
- "Each CPack generator as a built-in default value for this"
+ "Each CPack generator has a built-in default value for this"
" variable. E.g. Archive generators (ZIP, TGZ, ...) includes"
" the top level whereas RPM or DEB don't. The user may override"
" the default value by setting this variable.\n"
@@ -60,7 +60,7 @@ void cmCPackDocumentVariables::DefineVariables(cmake* cm)
"It is usually invoked like this:\n"
" make DESTDIR=/home/john install\n"
"which will install the concerned software using the"
- " installation prefix, e.g. \"/usr/local\" pre-pended with "
+ " installation prefix, e.g. \"/usr/local\" prepended with "
"the DESTDIR value which finally gives \"/home/john/usr/local\"."
" When preparing a package, CPack first installs the items to be "
"packaged in a local (to the build tree) directory by using the "
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index 7cc152269..3c685bd9d 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -638,7 +638,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
= this->MakefileMap->GetDefinition("CMAKE_MAKE_PROGRAM");
std::string buildCommand
= globalGenerator->GenerateBuildCommand(cmakeMakeProgram,
- installProjectName.c_str(), 0,
+ installProjectName.c_str(), 0, 0,
globalGenerator->GetPreinstallTargetName(),
buildConfig, false, false);
cmCPackLogger(cmCPackLog::LOG_DEBUG,
diff --git a/Source/CTest/cmCTestBatchTestHandler.cxx b/Source/CTest/cmCTestBatchTestHandler.cxx
index a22c7be41..934481b88 100644
--- a/Source/CTest/cmCTestBatchTestHandler.cxx
+++ b/Source/CTest/cmCTestBatchTestHandler.cxx
@@ -89,7 +89,7 @@ void cmCTestBatchTestHandler::WriteTestCommand(int test, std::fstream& fout)
command = cmSystemTools::ConvertToOutputPath(command.c_str());
//Prepends memcheck args to our command string if this is a memcheck
- this->TestHandler->GenerateTestCommand(processArgs);
+ this->TestHandler->GenerateTestCommand(processArgs, test);
processArgs.push_back(command);
for(std::vector<std::string>::iterator arg = processArgs.begin();
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index f4d38cef1..1f63185c1 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -130,10 +130,11 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
cmakeBuildConfiguration = config;
}
+ std::string dir = this->CTest->GetCTestConfiguration("BuildDirectory");
std::string buildCommand
= this->GlobalGenerator->
GenerateBuildCommand(cmakeMakeProgram,
- cmakeProjectName,
+ cmakeProjectName, dir.c_str(),
cmakeBuildAdditionalFlags, cmakeBuildTarget,
cmakeBuildConfiguration, true, false);
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index d6d39a98f..db33cb68e 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -31,32 +31,6 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
cmSystemTools::ExpandListArgument(this->Values[ctc_OPTIONS], options);
}
- if ( this->Values[ct_BUILD] )
- {
- this->CTest->SetCTestConfiguration("BuildDirectory",
- cmSystemTools::CollapseFullPath(
- this->Values[ct_BUILD]).c_str());
- }
- else
- {
- this->CTest->SetCTestConfiguration("BuildDirectory",
- cmSystemTools::CollapseFullPath(
- this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY")).c_str());
- }
-
- if ( this->Values[ct_SOURCE] )
- {
- this->CTest->SetCTestConfiguration("SourceDirectory",
- cmSystemTools::CollapseFullPath(
- this->Values[ct_SOURCE]).c_str());
- }
- else
- {
- this->CTest->SetCTestConfiguration("SourceDirectory",
- cmSystemTools::CollapseFullPath(
- this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY")).c_str());
- }
-
if ( this->CTest->GetCTestConfiguration("BuildDirectory").empty() )
{
this->SetError("Build directory not specified. Either use BUILD "
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 453e32ce2..2e2feb047 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -70,19 +70,6 @@ bool cmCTestHandlerCommand
this->CTest->SetConfigType(ctestConfigType);
}
- cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
- cmCTestGenericHandler* handler = this->InitializeHandler();
- if ( !handler )
- {
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Cannot instantiate test handler " << this->GetName()
- << std::endl);
- return false;
- }
-
- handler->SetAppendXML(this->AppendXML);
-
- handler->PopulateCustomVectors(this->Makefile);
if ( this->Values[ct_BUILD] )
{
this->CTest->SetCTestConfiguration("BuildDirectory",
@@ -119,6 +106,20 @@ bool cmCTestHandlerCommand
cmSystemTools::CollapseFullPath(
this->Makefile->GetSafeDefinition("CTEST_SOURCE_DIRECTORY")).c_str());
}
+
+ cmCTestLog(this->CTest, DEBUG, "Initialize handler" << std::endl;);
+ cmCTestGenericHandler* handler = this->InitializeHandler();
+ if ( !handler )
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Cannot instantiate test handler " << this->GetName()
+ << std::endl);
+ return false;
+ }
+
+ handler->SetAppendXML(this->AppendXML);
+
+ handler->PopulateCustomVectors(this->Makefile);
if ( this->Values[ct_SUBMIT_INDEX] )
{
if(!this->CTest->GetDropSiteCDash() && this->CTest->GetDartVersion() <= 1)
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 80218ad38..3ae2ac6a7 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -43,8 +43,7 @@ static CatToErrorType cmCTestMemCheckBoundsChecker[] = {
{0,0}
};
-// parse the xml file storing the installed version of Xcode on
-// the machine
+// parse the xml file containing the results of last BoundsChecker run
class cmBoundsCheckerParser : public cmXMLParser
{
public:
@@ -201,6 +200,7 @@ void cmCTestMemCheckHandler::Initialize()
this->CustomMaximumPassedTestOutputSize = 0;
this->CustomMaximumFailedTestOutputSize = 0;
this->MemoryTester = "";
+ this->MemoryTesterDynamicOptions.clear();
this->MemoryTesterOptions.clear();
this->MemoryTesterStyle = UNKNOWN;
this->MemoryTesterOutputFile = "";
@@ -243,12 +243,28 @@ int cmCTestMemCheckHandler::PostProcessHandler()
//----------------------------------------------------------------------
void cmCTestMemCheckHandler::GenerateTestCommand(
- std::vector<std::string>& args)
+ std::vector<std::string>& args, int test)
{
std::vector<cmStdString>::size_type pp;
- std::string memcheckcommand = "";
- memcheckcommand
+ cmStdString index;
+ cmOStringStream stream;
+ std::string memcheckcommand
= cmSystemTools::ConvertToOutputPath(this->MemoryTester.c_str());
+ stream << test;
+ index = stream.str();
+ for ( pp = 0; pp < this->MemoryTesterDynamicOptions.size(); pp ++ )
+ {
+ cmStdString arg = this->MemoryTesterDynamicOptions[pp];
+ cmStdString::size_type pos = arg.find("??");
+ if (pos != cmStdString::npos)
+ {
+ arg.replace(pos, 2, index);
+ }
+ args.push_back(arg);
+ memcheckcommand += " \"";
+ memcheckcommand += arg;
+ memcheckcommand += "\"";
+ }
for ( pp = 0; pp < this->MemoryTesterOptions.size(); pp ++ )
{
args.push_back(this->MemoryTesterOptions[pp]);
@@ -461,13 +477,6 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
return false;
}
- if ( this->MemoryTester[0] == '\"' &&
- this->MemoryTester[this->MemoryTester.size()-1] == '\"' )
- {
- this->MemoryTester
- = this->MemoryTester.substr(1, this->MemoryTester.size()-2);
- }
-
// Setup the options
std::string memoryTesterOptions;
if ( this->CTest->GetCTestConfiguration(
@@ -486,18 +495,19 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
= cmSystemTools::ParseArguments(memoryTesterOptions.c_str());
this->MemoryTesterOutputFile
- = this->CTest->GetBinaryDir() + "/Testing/Temporary/MemoryChecker.log";
+ = this->CTest->GetBinaryDir()
+ + "/Testing/Temporary/MemoryChecker.??.log";
switch ( this->MemoryTesterStyle )
{
case cmCTestMemCheckHandler::VALGRIND:
+ {
if ( this->MemoryTesterOptions.empty() )
{
this->MemoryTesterOptions.push_back("-q");
this->MemoryTesterOptions.push_back("--tool=memcheck");
this->MemoryTesterOptions.push_back("--leak-check=yes");
this->MemoryTesterOptions.push_back("--show-reachable=yes");
- this->MemoryTesterOptions.push_back("--workaround-gcc296-bugs=yes");
this->MemoryTesterOptions.push_back("--num-callers=50");
}
if ( this->CTest->GetCTestConfiguration(
@@ -516,7 +526,11 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
+ this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
this->MemoryTesterOptions.push_back(suppressions);
}
+ std::string outputFile = "--log-file="
+ + this->MemoryTesterOutputFile;
+ this->MemoryTesterDynamicOptions.push_back(outputFile);
break;
+ }
case cmCTestMemCheckHandler::PURIFY:
{
std::string outputFile;
@@ -542,19 +556,19 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
outputFile = "-log-file=";
#endif
outputFile += this->MemoryTesterOutputFile;
- this->MemoryTesterOptions.push_back(outputFile);
+ this->MemoryTesterDynamicOptions.push_back(outputFile);
break;
}
case cmCTestMemCheckHandler::BOUNDS_CHECKER:
{
this->BoundsCheckerXMLFile = this->MemoryTesterOutputFile;
std::string dpbdFile = this->CTest->GetBinaryDir()
- + "/Testing/Temporary/MemoryChecker.DPbd";
+ + "/Testing/Temporary/MemoryChecker.??.DPbd";
this->BoundsCheckerDPBDFile = dpbdFile;
- this->MemoryTesterOptions.push_back("/B");
- this->MemoryTesterOptions.push_back(dpbdFile);
- this->MemoryTesterOptions.push_back("/X");
- this->MemoryTesterOptions.push_back(this->MemoryTesterOutputFile);
+ this->MemoryTesterDynamicOptions.push_back("/B");
+ this->MemoryTesterDynamicOptions.push_back(dpbdFile);
+ this->MemoryTesterDynamicOptions.push_back("/X");
+ this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile);
this->MemoryTesterOptions.push_back("/M");
break;
}
@@ -902,25 +916,23 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
// This method puts the bounds checker output file into the output
// for the test
void
-cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res)
+cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res,
+ int test)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"PostProcessBoundsCheckerTest for : "
<< res.Name.c_str() << std::endl);
- if ( !cmSystemTools::FileExists(this->MemoryTesterOutputFile.c_str()) )
+ cmStdString ofile = testOutputFileName(test);
+ if ( ofile.empty() )
{
- std::string log = "Cannot find memory tester output file: "
- + this->MemoryTesterOutputFile;
- cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
return;
}
// put a scope around this to close ifs so the file can be removed
{
- std::ifstream ifs(this->MemoryTesterOutputFile.c_str());
+ std::ifstream ifs(ofile.c_str());
if ( !ifs )
{
- std::string log = "Cannot read memory tester output file: "
- + this->MemoryTesterOutputFile;
+ std::string log = "Cannot read memory tester output file: " + ofile;
cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
return;
}
@@ -943,23 +955,39 @@ cmCTestMemCheckHandler::PostProcessBoundsCheckerTest(cmCTestTestResult& res)
}
void
-cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res)
+cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res,
+ int test)
{
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"PostProcessPurifyTest for : "
<< res.Name.c_str() << std::endl);
- if ( !cmSystemTools::FileExists(this->MemoryTesterOutputFile.c_str()) )
+ appendMemTesterOutput(res, test);
+}
+
+void
+cmCTestMemCheckHandler::PostProcessValgrindTest(cmCTestTestResult& res,
+ int test)
+{
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+ "PostProcessValgrindTest for : "
+ << res.Name.c_str() << std::endl);
+ appendMemTesterOutput(res, test);
+}
+
+void
+cmCTestMemCheckHandler::appendMemTesterOutput(cmCTestTestResult& res,
+ int test)
+{
+ cmStdString ofile = testOutputFileName(test);
+
+ if ( ofile.empty() )
{
- std::string log = "Cannot find memory tester output file: "
- + this->MemoryTesterOutputFile;
- cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
return;
}
- std::ifstream ifs(this->MemoryTesterOutputFile.c_str());
+ std::ifstream ifs(ofile.c_str());
if ( !ifs )
{
- std::string log = "Cannot read memory tester output file: "
- + this->MemoryTesterOutputFile;
+ std::string log = "Cannot read memory tester output file: " + ofile;
cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
return;
}
@@ -970,3 +998,25 @@ cmCTestMemCheckHandler::PostProcessPurifyTest(cmCTestTestResult& res)
res.Output += "\n";
}
}
+
+cmStdString
+cmCTestMemCheckHandler::testOutputFileName(int test)
+{
+ cmStdString index;
+ cmOStringStream stream;
+ stream << test;
+ index = stream.str();
+ cmStdString ofile = this->MemoryTesterOutputFile;
+ cmStdString::size_type pos = ofile.find("??");
+ ofile.replace(pos, 2, index);
+
+ if ( !cmSystemTools::FileExists(ofile.c_str()) )
+ {
+ std::string log = "Cannot find memory tester output file: "
+ + ofile;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, log.c_str() << std::endl);
+ ofile = "";
+ }
+
+ return ofile;
+}
diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h
index 1e81c893b..040d2e092 100644
--- a/Source/CTest/cmCTestMemCheckHandler.h
+++ b/Source/CTest/cmCTestMemCheckHandler.h
@@ -37,7 +37,7 @@ public:
protected:
virtual int PreProcessHandler();
virtual int PostProcessHandler();
- virtual void GenerateTestCommand(std::vector<std::string>& args);
+ virtual void GenerateTestCommand(std::vector<std::string>& args, int test);
private:
@@ -89,6 +89,7 @@ private:
std::string BoundsCheckerDPBDFile;
std::string BoundsCheckerXMLFile;
std::string MemoryTester;
+ std::vector<cmStdString> MemoryTesterDynamicOptions;
std::vector<cmStdString> MemoryTesterOptions;
int MemoryTesterStyle;
std::string MemoryTesterOutputFile;
@@ -117,8 +118,16 @@ private:
bool ProcessMemCheckBoundsCheckerOutput(const std::string& str,
std::string& log, int* results);
- void PostProcessPurifyTest(cmCTestTestResult& res);
- void PostProcessBoundsCheckerTest(cmCTestTestResult& res);
+ void PostProcessPurifyTest(cmCTestTestResult& res, int test);
+ void PostProcessBoundsCheckerTest(cmCTestTestResult& res, int test);
+ void PostProcessValgrindTest(cmCTestTestResult& res, int test);
+
+ ///! append MemoryTesterOutputFile to the test log
+ void appendMemTesterOutput(cmCTestTestHandler::cmCTestTestResult& res,
+ int test);
+
+ ///! generate the output filename for the given test index
+ cmStdString testOutputFileName(int test);
};
#endif
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 5eabf3fbe..0e2fa41b9 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -166,6 +166,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
{
found = true;
reason = "Required regular expression found.";
+ break;
}
}
if ( !found )
@@ -196,6 +197,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
reason += passIt->second;
reason += "]";
forceFail = true;
+ break;
}
}
}
@@ -384,13 +386,19 @@ void cmCTestRunTest::MemCheckPostProcess()
<< this->TestResult.Name.c_str() << std::endl);
cmCTestMemCheckHandler * handler = static_cast<cmCTestMemCheckHandler*>
(this->TestHandler);
- if(handler->MemoryTesterStyle == cmCTestMemCheckHandler::BOUNDS_CHECKER)
- {
- handler->PostProcessBoundsCheckerTest(this->TestResult);
- }
- else if(handler->MemoryTesterStyle == cmCTestMemCheckHandler::PURIFY)
+ switch ( handler->MemoryTesterStyle )
{
- handler->PostProcessPurifyTest(this->TestResult);
+ case cmCTestMemCheckHandler::VALGRIND:
+ handler->PostProcessValgrindTest(this->TestResult, this->Index);
+ break;
+ case cmCTestMemCheckHandler::PURIFY:
+ handler->PostProcessPurifyTest(this->TestResult, this->Index);
+ break;
+ case cmCTestMemCheckHandler::BOUNDS_CHECKER:
+ handler->PostProcessBoundsCheckerTest(this->TestResult, this->Index);
+ break;
+ default:
+ break;
}
}
@@ -516,7 +524,7 @@ void cmCTestRunTest::ComputeArguments()
= cmSystemTools::ConvertToOutputPath(this->ActualCommand.c_str());
//Prepends memcheck args to our command string
- this->TestHandler->GenerateTestCommand(this->Arguments);
+ this->TestHandler->GenerateTestCommand(this->Arguments, this->Index);
for(std::vector<std::string>::iterator i = this->Arguments.begin();
i != this->Arguments.end(); ++i)
{
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 142bb4613..941d34877 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -120,7 +120,7 @@ static size_t
cmCTestSubmitHandlerWriteMemoryCallback(void *ptr, size_t size, size_t nmemb,
void *data)
{
- register int realsize = (int)(size * nmemb);
+ int realsize = (int)(size * nmemb);
cmCTestSubmitHandlerVectorOfChar *vec
= static_cast<cmCTestSubmitHandlerVectorOfChar*>(data);
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index e7491bba3..497774d1b 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -82,7 +82,6 @@ bool cmCTestSubdirCommand
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
for ( it = args.begin(); it != args.end(); ++ it )
{
- cmSystemTools::ChangeDirectory(cwd.c_str());
std::string fname;
if(cmSystemTools::FileIsFullPath(it->c_str()))
@@ -116,7 +115,6 @@ bool cmCTestSubdirCommand
else
{
// No CTestTestfile? Who cares...
- cmSystemTools::ChangeDirectory(cwd.c_str());
continue;
}
fname += "/";
@@ -133,6 +131,7 @@ bool cmCTestSubdirCommand
return false;
}
}
+ cmSystemTools::ChangeDirectory(cwd.c_str());
return true;
}
@@ -1108,7 +1107,7 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<cmStdString> &passed,
}
//----------------------------------------------------------------------
-void cmCTestTestHandler::GenerateTestCommand(std::vector<std::string>&)
+void cmCTestTestHandler::GenerateTestCommand(std::vector<std::string>&, int)
{
}
@@ -1303,10 +1302,9 @@ int cmCTestTestHandler::ExecuteCommands(std::vector<cmStdString>& vec)
for ( it = vec.begin(); it != vec.end(); ++it )
{
int retVal = 0;
- std::string cmd = cmSystemTools::ConvertToOutputPath(it->c_str());
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " << cmd
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Run command: " << *it
<< std::endl);
- if ( !cmSystemTools::RunSingleCommand(cmd.c_str(), 0, &retVal, 0,
+ if ( !cmSystemTools::RunSingleCommand(it->c_str(), 0, &retVal, 0,
cmSystemTools::OUTPUT_MERGE
/*this->Verbose*/) || retVal != 0 )
{
@@ -1363,7 +1361,7 @@ void cmCTestTestHandler
tempPath += filename;
attempted.push_back(tempPath);
attemptedConfigs.push_back(ctest->GetConfigType());
- // If the file is an OSX bundle then the configtyp
+ // If the file is an OSX bundle then the configtype
// will be at the start of the path
tempPath = ctest->GetConfigType();
tempPath += "/";
@@ -1374,7 +1372,7 @@ void cmCTestTestHandler
}
else
{
- // no config specified to try some options
+ // no config specified - try some options...
tempPath = filepath;
tempPath += "Release/";
tempPath += filename;
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 8e59e5915..93b793b20 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -153,7 +153,7 @@ protected:
// compute a final test list
virtual int PreProcessHandler();
virtual int PostProcessHandler();
- virtual void GenerateTestCommand(std::vector<std::string>& args);
+ virtual void GenerateTestCommand(std::vector<std::string>& args, int test);
int ExecuteCommands(std::vector<cmStdString>& vec);
void WriteTestResultHeader(std::ostream& os, cmCTestTestResult* result);
diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx
index 5dfcfe50a..6b4adb4bd 100644
--- a/Source/CTest/cmParseGTMCoverage.cxx
+++ b/Source/CTest/cmParseGTMCoverage.cxx
@@ -98,7 +98,7 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file)
bool found = this->FindMumpsFile(routine, filepath);
if(found)
{
- int lineoffset;
+ int lineoffset = 0;
if(this->FindFunctionInMumpsFile(filepath,
function,
lineoffset))
@@ -106,8 +106,8 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file)
cmCTestCoverageHandlerContainer::SingleFileCoverageVector&
coverageVector = this->Coverage.TotalCoverage[filepath];
coverageVector[lineoffset + linenumber] += count;
+ lastoffset = lineoffset;
}
- lastoffset = lineoffset;
}
else
{
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 000bc8503..167b992c9 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -175,6 +175,14 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout)
// Record exit information.
this->ExitValue = cmsysProcess_GetExitValue(this->Process);
this->TotalTime = cmSystemTools::GetTime() - this->StartTime;
+ // Because of a processor clock scew the runtime may become slightly
+ // negative. If someone changed the system clock while the process was
+ // running this may be even more. Make sure not to report a negative
+ // duration here.
+ if (this->TotalTime <= 0.0)
+ {
+ this->TotalTime = 0.0;
+ }
// std::cerr << "Time to run: " << this->TotalTime << "\n";
return cmsysProcess_Pipe_None;
}
diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt
index 96e28b491..5efc2fb1a 100644
--- a/Source/CursesDialog/CMakeLists.txt
+++ b/Source/CursesDialog/CMakeLists.txt
@@ -34,4 +34,4 @@ add_executable(ccmake ${CURSES_SRCS} )
target_link_libraries(ccmake CMakeLib)
target_link_libraries(ccmake cmForm)
-install_targets(/bin ccmake)
+install(TARGETS ccmake DESTINATION bin)
diff --git a/Source/CursesDialog/form/frm_driver.c b/Source/CursesDialog/form/frm_driver.c
index f234722f3..b9611bf10 100644
--- a/Source/CursesDialog/form/frm_driver.c
+++ b/Source/CursesDialog/form/frm_driver.c
@@ -176,7 +176,7 @@ static int FE_Delete_Previous(FORM *);
#define Address_Of_Current_Position_In_Buffer(form) \
Address_Of_Current_Position_In_Nth_Buffer(form,0)
-/* Logic to decide wether or not a field is actually a field with
+/* Logic to decide whether or not a field is actually a field with
vertical or horizontal scrolling */
#define Is_Scroll_Field(field) \
(((field)->drows > (field)->rows) || \
@@ -2100,7 +2100,7 @@ static int Insert_String(FORM *form, int row, char *txt, int len)
| the wrapping.
|
| Return Values : E_OK - no wrapping required or wrapping
-| was successfull
+| was successful
| E_REQUEST_DENIED -
| E_SYSTEM_ERROR - some system error
+--------------------------------------------------------------------------*/
@@ -3825,7 +3825,7 @@ int set_field_buffer(FIELD * field, int buffer, const char * value)
(int)(1 + (vlen-len)/((field->rows+field->nrow)*field->cols))))
RETURN(E_SYSTEM_ERROR);
- /* in this case we also have to check, wether or not the remaining
+ /* in this case we also have to check, whether or not the remaining
characters in value are also printable for buffer 0. */
if (buffer==0)
{
diff --git a/Source/CursesDialog/form/fty_enum.c b/Source/CursesDialog/form/fty_enum.c
index 8fc4cd7b6..59058a98c 100644
--- a/Source/CursesDialog/form/fty_enum.c
+++ b/Source/CursesDialog/form/fty_enum.c
@@ -101,7 +101,7 @@ static void Free_Enum_Type(void * argp)
| const unsigned char * buf,
| bool ccase )
|
-| Description : Check wether or not the text in 'buf' matches the
+| Description : Check whether or not the text in 'buf' matches the
| text in 's', at least partial.
|
| Return Values : NOMATCH - buffer doesn't match
diff --git a/Source/CursesDialog/form/fty_ipv4.c b/Source/CursesDialog/form/fty_ipv4.c
index 4ac8a50ec..c855af655 100644
--- a/Source/CursesDialog/form/fty_ipv4.c
+++ b/Source/CursesDialog/form/fty_ipv4.c
@@ -30,7 +30,7 @@ static bool Check_IPV4_Field(FIELD * field, const void * argp)
{
char *bp = field_buffer(field,0);
int num = 0, len;
- unsigned int d1, d2, d3, d4;
+ unsigned int d1=256, d2=256, d3=256, d4=256;
argp=0; /* Silence unused parameter warning. */
diff --git a/Source/CursesDialog/form/fty_regex.c b/Source/CursesDialog/form/fty_regex.c
index 0af1cef17..f90e0c108 100644
--- a/Source/CursesDialog/form/fty_regex.c
+++ b/Source/CursesDialog/form/fty_regex.c
@@ -40,7 +40,7 @@ static char *RegEx_Error(int code)
return 0;
}
-#define INIT register char *sp = RegEx_Init(instring);
+#define INIT char *sp = RegEx_Init(instring);
#define GETC() (*sp++)
#define PEEKC() (*sp)
#define UNGETC(c) (--sp)
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 1684fb229..ef252944e 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -11,6 +11,9 @@
#=============================================================================
project(QtDialog)
+if(POLICY CMP0020)
+ cmake_policy(SET CMP0020 NEW) # Drop when CMake >= 2.8.11 required
+endif()
find_package(Qt5Widgets QUIET)
if (Qt5Widgets_FOUND)
include_directories(${Qt5Widgets_INCLUDE_DIRS})
@@ -29,6 +32,11 @@ if (Qt5Widgets_FOUND)
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
+
+ if(WIN32 AND TARGET Qt5::Core)
+ get_property(_Qt5_Core_LOCATION TARGET Qt5::Core PROPERTY LOCATION)
+ get_filename_component(Qt_BIN_DIR "${_Qt5_Core_LOCATION}" PATH)
+ endif()
else()
set(QT_MIN_VERSION "4.4.0")
find_package(Qt4 REQUIRED)
@@ -38,6 +46,13 @@ else()
endif()
include(${QT_USE_FILE})
+
+ if(WIN32 AND EXISTS "${QT_QMAKE_EXECUTABLE}")
+ get_filename_component(_Qt_BIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH)
+ if(EXISTS "${_Qt_BIN_DIR}/QtCore4.dll")
+ set(Qt_BIN_DIR ${_Qt_BIN_DIR})
+ endif()
+ endif()
endif()
set(SRCS
@@ -91,6 +106,9 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS})
target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${QT_LIBRARIES})
+if(Qt_BIN_DIR)
+ set_property(TARGET cmake-gui PROPERTY Qt_BIN_DIR ${Qt_BIN_DIR})
+endif()
if(APPLE)
set_target_properties(cmake-gui PROPERTIES
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index c0dde1c2c..4d62f7263 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -28,6 +28,7 @@
#include <QShortcut>
#include <QKeySequence>
#include <QMacInstallDialog.h>
+#include <QInputDialog>
#include "QCMake.h"
#include "QCMakeCacheView.h"
@@ -122,6 +123,22 @@ CMakeSetupDialog::CMakeSetupDialog()
QObject::connect(this->InstallForCommandLineAction, SIGNAL(triggered(bool)),
this, SLOT(doInstallForCommandLine()));
#endif
+ ToolsMenu->addSeparator();
+ ToolsMenu->addAction(tr("&Find in Output..."),
+ this, SLOT(doOutputFindDialog()),
+ QKeySequence::Find);
+ ToolsMenu->addAction(tr("Find Next"),
+ this, SLOT(doOutputFindNext()),
+ QKeySequence::FindNext);
+ ToolsMenu->addAction(tr("Find Previous"),
+ this, SLOT(doOutputFindPrev()),
+ QKeySequence::FindPrevious);
+ ToolsMenu->addAction(tr("Goto Next Error"),
+ this, SLOT(doOutputErrorNext()),
+ QKeySequence(Qt::Key_F8)); // in Visual Studio
+ new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Period),
+ this, SLOT(doOutputErrorNext())); // in Eclipse
+
QMenu* OptionsMenu = this->menuBar()->addMenu(tr("&Options"));
this->SuppressDevWarningsAction =
OptionsMenu->addAction(tr("&Suppress dev Warnings (-Wno-dev)"));
@@ -154,10 +171,6 @@ CMakeSetupDialog::CMakeSetupDialog()
QObject::connect(a, SIGNAL(triggered(bool)),
this, SLOT(doHelp()));
- QShortcut* filterShortcut = new QShortcut(QKeySequence::Find, this);
- QObject::connect(filterShortcut, SIGNAL(activated()),
- this, SLOT(startSearch()));
-
this->setAcceptDrops(true);
// get the saved binary directories
@@ -172,6 +185,10 @@ CMakeSetupDialog::CMakeSetupDialog()
this->Output->setFont(outputFont);
this->ErrorFormat.setForeground(QBrush(Qt::red));
+ this->Output->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(this->Output, SIGNAL(customContextMenuRequested(const QPoint&)),
+ this, SLOT(doOutputContextMenu(const QPoint &)));
+
// start the cmake worker thread
this->CMakeThread = new QCMakeThread(this);
QObject::connect(this->CMakeThread, SIGNAL(cmakeInitialized()),
@@ -637,7 +654,13 @@ void CMakeSetupDialog::showProgress(const QString& /*msg*/, float percent)
void CMakeSetupDialog::error(const QString& msg)
{
this->Output->setCurrentCharFormat(this->ErrorFormat);
- this->Output->append(msg);
+ //QTextEdit will terminate the msg with a ParagraphSeparator, but it also replaces
+ //all newlines with ParagraphSeparators. By replacing the newlines by ourself, one
+ //error msg will be one paragraph.
+ QString paragraph(msg);
+ paragraph.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ this->Output->append(paragraph);
+
}
void CMakeSetupDialog::message(const QString& msg)
@@ -1149,4 +1172,134 @@ void CMakeSetupDialog::setSearchFilter(const QString& str)
this->CacheValues->setSearchFilter(str);
}
+void CMakeSetupDialog::doOutputContextMenu(const QPoint &pt)
+{
+ QMenu *menu = this->Output->createStandardContextMenu();
+
+ menu->addSeparator();
+ menu->addAction(tr("Find..."),
+ this, SLOT(doOutputFindDialog()), QKeySequence::Find);
+ menu->addAction(tr("Find Next"),
+ this, SLOT(doOutputFindNext()), QKeySequence::FindNext);
+ menu->addAction(tr("Find Previous"),
+ this, SLOT(doOutputFindPrev()), QKeySequence::FindPrevious);
+ menu->addSeparator();
+ menu->addAction(tr("Goto Next Error"),
+ this, SLOT(doOutputErrorNext()), QKeySequence(Qt::Key_F8));
+
+ menu->exec(this->Output->mapToGlobal(pt));
+ delete menu;
+}
+
+void CMakeSetupDialog::doOutputFindDialog()
+{
+ QStringList strings(this->FindHistory);
+
+ QString selection = this->Output->textCursor().selectedText();
+ if (!selection.isEmpty() &&
+ !selection.contains(QChar::ParagraphSeparator) &&
+ !selection.contains(QChar::LineSeparator))
+ {
+ strings.push_front(selection);
+ }
+
+ bool ok;
+ QString search = QInputDialog::getItem(this, tr("Find in Output"),
+ tr("Find:"), strings, 0, true, &ok);
+ if (ok && !search.isEmpty())
+ {
+ if (!this->FindHistory.contains(search))
+ {
+ this->FindHistory.push_front(search);
+ }
+ doOutputFindNext();
+ }
+}
+
+void CMakeSetupDialog::doOutputFindPrev()
+{
+ doOutputFindNext(false);
+}
+
+void CMakeSetupDialog::doOutputFindNext(bool directionForward)
+{
+ if (this->FindHistory.isEmpty())
+ {
+ doOutputFindDialog(); //will re-call this function again
+ return;
+ }
+
+ QString search = this->FindHistory.front();
+
+ QTextCursor cursor = this->Output->textCursor();
+ QTextDocument* document = this->Output->document();
+ QTextDocument::FindFlags flags;
+ if (!directionForward)
+ {
+ flags |= QTextDocument::FindBackward;
+ }
+
+ cursor = document->find(search, cursor, flags);
+
+ if (cursor.isNull())
+ {
+ // first search found nothing, wrap around and search again
+ cursor = this->Output->textCursor();
+ cursor.movePosition(directionForward ? QTextCursor::Start
+ : QTextCursor::End);
+ cursor = document->find(search, cursor, flags);
+ }
+
+ if (cursor.hasSelection())
+ {
+ this->Output->setTextCursor(cursor);
+ }
+}
+
+void CMakeSetupDialog::doOutputErrorNext()
+{
+ QTextCursor cursor = this->Output->textCursor();
+ bool atEnd = false;
+ // move cursor out of current error-block
+ if (cursor.blockCharFormat() == this->ErrorFormat)
+ {
+ atEnd = !cursor.movePosition(QTextCursor::NextBlock);
+ }
+
+ // move cursor to next error-block
+ while (cursor.blockCharFormat() != this->ErrorFormat && !atEnd)
+ {
+ atEnd = !cursor.movePosition(QTextCursor::NextBlock);
+ }
+
+ if (atEnd)
+ {
+ // first search found nothing, wrap around and search again
+ atEnd = !cursor.movePosition(QTextCursor::Start);
+
+ // move cursor to next error-block
+ while (cursor.blockCharFormat() != this->ErrorFormat && !atEnd)
+ {
+ atEnd = !cursor.movePosition(QTextCursor::NextBlock);
+ }
+ }
+
+ if (!atEnd)
+ {
+ cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
+
+ QTextCharFormat selectionFormat;
+ selectionFormat.setBackground(Qt::yellow);
+ QTextEdit::ExtraSelection extraSelection = {cursor, selectionFormat};
+ this->Output->setExtraSelections(QList<QTextEdit::ExtraSelection>()
+ << extraSelection);
+
+ // make the whole error-block visible
+ this->Output->setTextCursor(cursor);
+
+ // remove the selection to see the extraSelection
+ cursor.setPosition(cursor.anchor());
+ this->Output->setTextCursor(cursor);
+ }
+}
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index 259967580..963c7d12e 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -77,6 +77,11 @@ protected slots:
bool doConfigureInternal();
bool doGenerateInternal();
void exitLoop(int);
+ void doOutputContextMenu(const QPoint &);
+ void doOutputFindDialog();
+ void doOutputFindNext(bool directionForward = true);
+ void doOutputFindPrev();
+ void doOutputErrorNext();
protected:
@@ -106,6 +111,7 @@ protected:
QTextCharFormat MessageFormat;
QStringList AddVariableCompletions;
+ QStringList FindHistory;
QEventLoop LocalLoop;
diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui
index dc8ee3fbd..98da249d5 100644
--- a/Source/QtDialog/CMakeSetupDialog.ui
+++ b/Source/QtDialog/CMakeSetupDialog.ui
@@ -107,7 +107,10 @@
</sizepolicy>
</property>
<property name="text">
- <string>Search:</string>
+ <string>S&amp;earch:</string>
+ </property>
+ <property name="buddy">
+ <cstring>Search</cstring>
</property>
</widget>
</item>
diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx
index 6006758c7..bae6a30a7 100644
--- a/Source/QtDialog/QCMakeCacheView.cxx
+++ b/Source/QtDialog/QCMakeCacheView.cxx
@@ -177,7 +177,7 @@ QModelIndex QCMakeCacheView::moveCursor(CursorAction act,
void QCMakeCacheView::setShowAdvanced(bool s)
{
#if QT_VERSION >= 040300
- // new 4.3 api that needs to be called. what about an older Qt?
+ // new 4.3 API that needs to be called. what about an older Qt?
this->SearchFilter->invalidate();
#endif
diff --git a/Source/cmAddCompileOptionsCommand.cxx b/Source/cmAddCompileOptionsCommand.cxx
new file mode 100644
index 000000000..a6c3c005c
--- /dev/null
+++ b/Source/cmAddCompileOptionsCommand.cxx
@@ -0,0 +1,28 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2013 Stephen Kelly <steveire@gmail.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmAddCompileOptionsCommand.h"
+
+bool cmAddCompileOptionsCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+ if(args.size() < 1 )
+ {
+ return true;
+ }
+
+ for(std::vector<std::string>::const_iterator i = args.begin();
+ i != args.end(); ++i)
+ {
+ this->Makefile->AddCompileOption(i->c_str());
+ }
+ return true;
+}
diff --git a/Source/cmAddCompileOptionsCommand.h b/Source/cmAddCompileOptionsCommand.h
new file mode 100644
index 000000000..e9bbf2816
--- /dev/null
+++ b/Source/cmAddCompileOptionsCommand.h
@@ -0,0 +1,71 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2013 Stephen Kelly <steveire@gmail.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmAddCompileOptionsCommand_h
+#define cmAddCompileOptionsCommand_h
+
+#include "cmCommand.h"
+#include "cmDocumentGeneratorExpressions.h"
+
+class cmAddCompileOptionsCommand : public cmCommand
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ virtual cmCommand* Clone()
+ {
+ return new cmAddCompileOptionsCommand;
+ }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ virtual bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus &status);
+
+ /**
+ * The name of the command as specified in CMakeList.txt.
+ */
+ virtual const char* GetName() const {return "add_compile_options";}
+
+ /**
+ * Succinct documentation.
+ */
+ virtual const char* GetTerseDocumentation() const
+ {
+ return "Adds options to the compilation of source files.";
+ }
+
+ /**
+ * More documentation.
+ */
+ virtual const char* GetFullDocumentation() const
+ {
+ return
+ " add_compile_options(<option> ...)\n"
+ "Adds options to the compiler command line for sources in the "
+ "current directory and below. This command can be used to add any "
+ "options, but alternative commands exist to add preprocessor "
+ "definitions or include directories. "
+ "See documentation of the directory and target COMPILE_OPTIONS "
+ "properties for details. "
+ "Arguments to add_compile_options may use \"generator "
+ "expressions\" with the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ ;
+ }
+
+ cmTypeMacro(cmAddCompileOptionsCommand, cmCommand);
+};
+
+#endif
diff --git a/Source/cmAddDefinitionsCommand.h b/Source/cmAddDefinitionsCommand.h
index 7bb37674d..ff2c4a038 100644
--- a/Source/cmAddDefinitionsCommand.h
+++ b/Source/cmAddDefinitionsCommand.h
@@ -63,7 +63,7 @@ public:
"but it was originally intended to add preprocessor definitions. "
"Flags beginning in -D or /D that look like preprocessor definitions "
"are automatically added to the COMPILE_DEFINITIONS property for "
- "the current directory. Definitions with non-trival values may be "
+ "the current directory. Definitions with non-trivial values may be "
"left in the set of flags instead of being converted for reasons of "
"backwards compatibility. See documentation of the directory, "
"target, and source file COMPILE_DEFINITIONS properties for details "
@@ -73,8 +73,6 @@ public:
}
cmTypeMacro(cmAddDefinitionsCommand, cmCommand);
-private:
- bool ParseDefinition(std::string const& def);
};
diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx
index 04a304e39..e4d7f7f1e 100644
--- a/Source/cmAddDependenciesCommand.cxx
+++ b/Source/cmAddDependenciesCommand.cxx
@@ -24,6 +24,13 @@ bool cmAddDependenciesCommand
}
std::string target_name = args[0];
+ if(this->Makefile->IsAlias(target_name.c_str()))
+ {
+ cmOStringStream e;
+ e << "Cannot add target-level dependencies to alias target \""
+ << target_name << "\".\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ }
if(cmTarget* target = this->Makefile->FindTargetToUse(target_name.c_str()))
{
std::vector<std::string>::const_iterator s = args.begin();
diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx
index 6dd8e5c64..578525969 100644
--- a/Source/cmAddExecutableCommand.cxx
+++ b/Source/cmAddExecutableCommand.cxx
@@ -30,6 +30,7 @@ bool cmAddExecutableCommand
bool excludeFromAll = false;
bool importTarget = false;
bool importGlobal = false;
+ bool isAlias = false;
while ( s != args.end() )
{
if (*s == "WIN32")
@@ -57,6 +58,11 @@ bool cmAddExecutableCommand
++s;
importGlobal = true;
}
+ else if(*s == "ALIAS")
+ {
+ ++s;
+ isAlias = true;
+ }
else
{
break;
@@ -83,6 +89,72 @@ bool cmAddExecutableCommand
}
return false;
}
+ if (isAlias)
+ {
+ if(!cmGeneratorExpression::IsValidTargetName(exename.c_str()))
+ {
+ this->SetError(("Invalid name for ALIAS: " + exename).c_str());
+ return false;
+ }
+ if(excludeFromAll)
+ {
+ this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
+ return false;
+ }
+ if(importTarget || importGlobal)
+ {
+ this->SetError("IMPORTED with ALIAS is not allowed.");
+ return false;
+ }
+ if(args.size() != 3)
+ {
+ cmOStringStream e;
+ e << "ALIAS requires exactly one target argument.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
+ const char *aliasedName = s->c_str();
+ if(this->Makefile->IsAlias(aliasedName))
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << exename
+ << "\" because target \"" << aliasedName << "\" is itself an ALIAS.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ cmTarget *aliasedTarget =
+ this->Makefile->FindTargetToUse(aliasedName, true);
+ if(!aliasedTarget)
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << exename
+ << "\" because target \"" << aliasedName << "\" does not already "
+ "exist.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ cmTarget::TargetType type = aliasedTarget->GetType();
+ if(type != cmTarget::EXECUTABLE)
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << exename
+ << "\" because target \"" << aliasedName << "\" is not an "
+ "executable.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ if(aliasedTarget->IsImported())
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << exename
+ << "\" because target \"" << aliasedName << "\" is IMPORTED.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ this->Makefile->AddAlias(exename.c_str(), aliasedTarget);
+ return true;
+ }
// Handle imported target creation.
if(importTarget)
diff --git a/Source/cmAddExecutableCommand.h b/Source/cmAddExecutableCommand.h
index 1e9f9b3be..2774ce841 100644
--- a/Source/cmAddExecutableCommand.h
+++ b/Source/cmAddExecutableCommand.h
@@ -107,6 +107,19 @@ public:
"(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) "
"which specifies the location of the main executable file on disk. "
"See documentation of the IMPORTED_* properties for more information."
+ "\n"
+ "The signature\n"
+ " add_executable(<name> ALIAS <target>)\n"
+ "creates an alias, such that <name> can be used to refer to <target> "
+ "in subsequent commands. The <name> does not appear in the generated "
+ "buildsystem as a make target. The <target> may not be an IMPORTED "
+ "target or an ALIAS. Alias targets can be used as linkable targets, "
+ "targets to read properties from, executables for custom commands and "
+ "custom targets. They can also be tested for existance with the "
+ "regular if(TARGET) subcommand. The <name> may not be used to modify "
+ "properties of <target>, that is, it may not be used as the operand of "
+ "set_property, set_target_properties, target_link_libraries etc. An "
+ "ALIAS target may not be installed of exported."
;
}
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index fd39eec02..cbc6ed1e9 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -43,6 +43,7 @@ bool cmAddLibraryCommand
// the type of library. Otherwise, it is treated as a source or
// source list name. There may be two keyword arguments, check for them
bool haveSpecifiedType = false;
+ bool isAlias = false;
while ( s != args.end() )
{
std::string libType = *s;
@@ -76,6 +77,11 @@ bool cmAddLibraryCommand
type = cmTarget::UNKNOWN_LIBRARY;
haveSpecifiedType = true;
}
+ else if(libType == "ALIAS")
+ {
+ ++s;
+ isAlias = true;
+ }
else if(*s == "EXCLUDE_FROM_ALL")
{
++s;
@@ -96,6 +102,80 @@ bool cmAddLibraryCommand
break;
}
}
+ if (isAlias)
+ {
+ if(!cmGeneratorExpression::IsValidTargetName(libName.c_str()))
+ {
+ this->SetError(("Invalid name for ALIAS: " + libName).c_str());
+ return false;
+ }
+ if(excludeFromAll)
+ {
+ this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
+ return false;
+ }
+ if(importTarget || importGlobal)
+ {
+ this->SetError("IMPORTED with ALIAS is not allowed.");
+ return false;
+ }
+ if(args.size() != 3)
+ {
+ cmOStringStream e;
+ e << "ALIAS requires exactly one target argument.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
+ const char *aliasedName = s->c_str();
+ if(this->Makefile->IsAlias(aliasedName))
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << libName
+ << "\" because target \"" << aliasedName << "\" is itself an ALIAS.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ cmTarget *aliasedTarget =
+ this->Makefile->FindTargetToUse(aliasedName, true);
+ if(!aliasedTarget)
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << libName
+ << "\" because target \"" << aliasedName << "\" does not already "
+ "exist.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ cmTarget::TargetType aliasedType = aliasedTarget->GetType();
+ if(aliasedType != cmTarget::SHARED_LIBRARY
+ && aliasedType != cmTarget::STATIC_LIBRARY
+ && aliasedType != cmTarget::MODULE_LIBRARY
+ && aliasedType != cmTarget::OBJECT_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << libName
+ << "\" because target \"" << aliasedName << "\" is not a library.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ if(aliasedTarget->IsImported())
+ {
+ cmOStringStream e;
+ e << "cannot create ALIAS target \"" << libName
+ << "\" because target \"" << aliasedName << "\" is IMPORTED.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ this->Makefile->AddAlias(libName.c_str(), aliasedTarget);
+ return true;
+ }
+
+ if(importTarget && excludeFromAll)
+ {
+ this->SetError("excludeFromAll with IMPORTED target makes no sense.");
+ return false;
+ }
/* ideally we should check whether for the linker language of the target
CMAKE_${LANG}_CREATE_SHARED_LIBRARY is defined and if not default to
diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h
index e5f27cb51..59354b0f5 100644
--- a/Source/cmAddLibraryCommand.h
+++ b/Source/cmAddLibraryCommand.h
@@ -138,6 +138,19 @@ public:
"Some native build systems may not like targets that have only "
"object files, so consider adding at least one real source file "
"to any target that references $<TARGET_OBJECTS:objlib>."
+ "\n"
+ "The signature\n"
+ " add_library(<name> ALIAS <target>)\n"
+ "creates an alias, such that <name> can be used to refer to <target> "
+ "in subsequent commands. The <name> does not appear in the generated "
+ "buildsystem as a make target. The <target> may not be an IMPORTED "
+ "target or an ALIAS. Alias targets can be used as linkable targets, "
+ "targets to read properties from. They can also be tested for "
+ "existance with the "
+ "regular if(TARGET) subcommand. The <name> may not be used to modify "
+ "properties of <target>, that is, it may not be used as the operand of "
+ "set_property, set_target_properties, target_link_libraries etc. An "
+ "ALIAS target may not be installed of exported."
;
}
diff --git a/Source/cmAddSubDirectoryCommand.h b/Source/cmAddSubDirectoryCommand.h
index fa322b0c4..e7f907c3f 100644
--- a/Source/cmAddSubDirectoryCommand.h
+++ b/Source/cmAddSubDirectoryCommand.h
@@ -61,7 +61,7 @@ public:
" add_subdirectory(source_dir [binary_dir] \n"
" [EXCLUDE_FROM_ALL])\n"
"Add a subdirectory to the build. The source_dir specifies the "
- "directory in which the source CmakeLists.txt and code files are "
+ "directory in which the source CMakeLists.txt and code files are "
"located. If it is a relative "
"path it will be evaluated with respect to the current "
"directory (the typical usage), but it may also be an absolute path. "
diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h
index 6a0cd9d2e..ec7fda3f3 100644
--- a/Source/cmAddTestCommand.h
+++ b/Source/cmAddTestCommand.h
@@ -71,6 +71,9 @@ public:
" add_test(NAME <name> [CONFIGURATIONS [Debug|Release|...]]\n"
" [WORKING_DIRECTORY dir]\n"
" COMMAND <command> [arg1 [arg2 ...]])\n"
+ "Add a test called <name>. "
+ "The test name may not contain spaces, quotes, or other characters "
+ "special in CMake syntax. "
"If COMMAND specifies an executable target (created by "
"add_executable) it will automatically be replaced by the location "
"of the executable created at build time. "
diff --git a/Source/cmBootstrapCommands1.cxx b/Source/cmBootstrapCommands1.cxx
new file mode 100644
index 000000000..9093579dc
--- /dev/null
+++ b/Source/cmBootstrapCommands1.cxx
@@ -0,0 +1,91 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+// This file is used to compile all the commands
+// that CMake knows about at compile time.
+// This is sort of a boot strapping approach since you would
+// like to have CMake to build CMake.
+#include "cmCommands.h"
+#include "cmAddCustomCommandCommand.cxx"
+#include "cmAddCustomTargetCommand.cxx"
+#include "cmAddDefinitionsCommand.cxx"
+#include "cmAddDependenciesCommand.cxx"
+#include "cmAddExecutableCommand.cxx"
+#include "cmAddLibraryCommand.cxx"
+#include "cmAddSubDirectoryCommand.cxx"
+#include "cmAddTestCommand.cxx"
+#include "cmBreakCommand.cxx"
+#include "cmBuildCommand.cxx"
+#include "cmCMakeMinimumRequired.cxx"
+#include "cmCMakePolicyCommand.cxx"
+#include "cmCommandArgumentsHelper.cxx"
+#include "cmConfigureFileCommand.cxx"
+#include "cmCoreTryCompile.cxx"
+#include "cmCreateTestSourceList.cxx"
+#include "cmDefinePropertyCommand.cxx"
+#include "cmElseCommand.cxx"
+#include "cmEnableLanguageCommand.cxx"
+#include "cmEnableTestingCommand.cxx"
+#include "cmEndForEachCommand.cxx"
+#include "cmEndFunctionCommand.cxx"
+#include "cmEndIfCommand.cxx"
+#include "cmEndMacroCommand.cxx"
+#include "cmEndWhileCommand.cxx"
+#include "cmExecProgramCommand.cxx"
+#include "cmExecuteProcessCommand.cxx"
+#include "cmExternalMakefileProjectGenerator.cxx"
+#include "cmFindBase.cxx"
+#include "cmFindCommon.cxx"
+#include "cmFileCommand.cxx"
+#include "cmFindFileCommand.cxx"
+#include "cmFindLibraryCommand.cxx"
+#include "cmFindPackageCommand.cxx"
+#include "cmFindPathCommand.cxx"
+#include "cmFindProgramCommand.cxx"
+#include "cmForEachCommand.cxx"
+#include "cmFunctionCommand.cxx"
+
+void GetBootstrapCommands1(std::list<cmCommand*>& commands)
+{
+ commands.push_back(new cmAddCustomCommandCommand);
+ commands.push_back(new cmAddCustomTargetCommand);
+ commands.push_back(new cmAddDefinitionsCommand);
+ commands.push_back(new cmAddDependenciesCommand);
+ commands.push_back(new cmAddExecutableCommand);
+ commands.push_back(new cmAddLibraryCommand);
+ commands.push_back(new cmAddSubDirectoryCommand);
+ commands.push_back(new cmAddTestCommand);
+ commands.push_back(new cmBreakCommand);
+ commands.push_back(new cmBuildCommand);
+ commands.push_back(new cmCMakeMinimumRequired);
+ commands.push_back(new cmCMakePolicyCommand);
+ commands.push_back(new cmConfigureFileCommand);
+ commands.push_back(new cmCreateTestSourceList);
+ commands.push_back(new cmDefinePropertyCommand);
+ commands.push_back(new cmElseCommand);
+ commands.push_back(new cmEnableLanguageCommand);
+ commands.push_back(new cmEnableTestingCommand);
+ commands.push_back(new cmEndForEachCommand);
+ commands.push_back(new cmEndFunctionCommand);
+ commands.push_back(new cmEndIfCommand);
+ commands.push_back(new cmEndMacroCommand);
+ commands.push_back(new cmEndWhileCommand);
+ commands.push_back(new cmExecProgramCommand);
+ commands.push_back(new cmExecuteProcessCommand);
+ commands.push_back(new cmFileCommand);
+ commands.push_back(new cmFindFileCommand);
+ commands.push_back(new cmFindLibraryCommand);
+ commands.push_back(new cmFindPackageCommand);
+ commands.push_back(new cmFindPathCommand);
+ commands.push_back(new cmFindProgramCommand);
+ commands.push_back(new cmForEachCommand);
+ commands.push_back(new cmFunctionCommand);
+}
diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands2.cxx
index e3a2ad4e5..be72526ba 100644
--- a/Source/cmBootstrapCommands.cxx
+++ b/Source/cmBootstrapCommands2.cxx
@@ -14,44 +14,7 @@
// This is sort of a boot strapping approach since you would
// like to have CMake to build CMake.
#include "cmCommands.h"
-#include "cmAddCustomCommandCommand.cxx"
-#include "cmAddCustomTargetCommand.cxx"
-#include "cmAddDefinitionsCommand.cxx"
-#include "cmAddDependenciesCommand.cxx"
-#include "cmAddExecutableCommand.cxx"
-#include "cmAddLibraryCommand.cxx"
-#include "cmAddSubDirectoryCommand.cxx"
-#include "cmAddTestCommand.cxx"
-#include "cmBreakCommand.cxx"
-#include "cmBuildCommand.cxx"
-#include "cmCMakeMinimumRequired.cxx"
-#include "cmCMakePolicyCommand.cxx"
-#include "cmCommandArgumentsHelper.cxx"
-#include "cmConfigureFileCommand.cxx"
-#include "cmCoreTryCompile.cxx"
-#include "cmCreateTestSourceList.cxx"
-#include "cmDefinePropertyCommand.cxx"
-#include "cmElseCommand.cxx"
-#include "cmEnableLanguageCommand.cxx"
-#include "cmEnableTestingCommand.cxx"
-#include "cmEndForEachCommand.cxx"
-#include "cmEndFunctionCommand.cxx"
-#include "cmEndIfCommand.cxx"
-#include "cmEndMacroCommand.cxx"
-#include "cmEndWhileCommand.cxx"
-#include "cmExecProgramCommand.cxx"
-#include "cmExecuteProcessCommand.cxx"
-#include "cmExternalMakefileProjectGenerator.cxx"
-#include "cmFindBase.cxx"
-#include "cmFindCommon.cxx"
-#include "cmFileCommand.cxx"
-#include "cmFindFileCommand.cxx"
-#include "cmFindLibraryCommand.cxx"
-#include "cmFindPackageCommand.cxx"
-#include "cmFindPathCommand.cxx"
-#include "cmFindProgramCommand.cxx"
-#include "cmForEachCommand.cxx"
-#include "cmFunctionCommand.cxx"
+#include "cmGeneratorExpressionEvaluationFile.cxx"
#include "cmGetCMakePropertyCommand.cxx"
#include "cmGetDirectoryPropertyCommand.cxx"
#include "cmGetFilenameComponentCommand.cxx"
@@ -95,41 +58,8 @@
#include "cmUnsetCommand.cxx"
#include "cmWhileCommand.cxx"
-void GetBootstrapCommands(std::list<cmCommand*>& commands)
+void GetBootstrapCommands2(std::list<cmCommand*>& commands)
{
- commands.push_back(new cmAddCustomCommandCommand);
- commands.push_back(new cmAddCustomTargetCommand);
- commands.push_back(new cmAddDefinitionsCommand);
- commands.push_back(new cmAddDependenciesCommand);
- commands.push_back(new cmAddExecutableCommand);
- commands.push_back(new cmAddLibraryCommand);
- commands.push_back(new cmAddSubDirectoryCommand);
- commands.push_back(new cmAddTestCommand);
- commands.push_back(new cmBreakCommand);
- commands.push_back(new cmBuildCommand);
- commands.push_back(new cmCMakeMinimumRequired);
- commands.push_back(new cmCMakePolicyCommand);
- commands.push_back(new cmConfigureFileCommand);
- commands.push_back(new cmCreateTestSourceList);
- commands.push_back(new cmDefinePropertyCommand);
- commands.push_back(new cmElseCommand);
- commands.push_back(new cmEnableLanguageCommand);
- commands.push_back(new cmEnableTestingCommand);
- commands.push_back(new cmEndForEachCommand);
- commands.push_back(new cmEndFunctionCommand);
- commands.push_back(new cmEndIfCommand);
- commands.push_back(new cmEndMacroCommand);
- commands.push_back(new cmEndWhileCommand);
- commands.push_back(new cmExecProgramCommand);
- commands.push_back(new cmExecuteProcessCommand);
- commands.push_back(new cmFileCommand);
- commands.push_back(new cmFindFileCommand);
- commands.push_back(new cmFindLibraryCommand);
- commands.push_back(new cmFindPackageCommand);
- commands.push_back(new cmFindPathCommand);
- commands.push_back(new cmFindProgramCommand);
- commands.push_back(new cmForEachCommand);
- commands.push_back(new cmFunctionCommand);
commands.push_back(new cmGetCMakePropertyCommand);
commands.push_back(new cmGetDirectoryPropertyCommand);
commands.push_back(new cmGetFilenameComponentCommand);
diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx
index 91d55a5a2..b6e2569a5 100644
--- a/Source/cmBuildCommand.cxx
+++ b/Source/cmBuildCommand.cxx
@@ -122,7 +122,7 @@ bool cmBuildCommand
//
std::string makecommand = this->Makefile->GetLocalGenerator()
->GetGlobalGenerator()->GenerateBuildCommand
- (makeprogram, project_name, 0, target, configuration, true, false);
+ (makeprogram, project_name, 0, 0, target, configuration, true, false);
this->Makefile->AddDefinition(variable, makecommand.c_str());
@@ -153,7 +153,7 @@ bool cmBuildCommand
std::string makecommand = this->Makefile->GetLocalGenerator()
->GetGlobalGenerator()->GenerateBuildCommand
- (makeprogram.c_str(), this->Makefile->GetProjectName(), 0,
+ (makeprogram.c_str(), this->Makefile->GetProjectName(), 0, 0,
0, configType.c_str(), true, false);
if(cacheValue)
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
new file mode 100644
index 000000000..62f238369
--- /dev/null
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -0,0 +1,126 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2013 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmCMakeHostSystemInformationCommand.h"
+
+#include <cmsys/ios/sstream>
+
+// cmCMakeHostSystemInformation
+bool cmCMakeHostSystemInformationCommand
+::InitialPass(std::vector<std::string> const &args, cmExecutionStatus &)
+{
+ size_t current_index = 0;
+
+ if(args.size() < (current_index + 2) || args[current_index] != "RESULT")
+ {
+ this->SetError("missing RESULT specification.");
+ return false;
+ }
+
+ std::string variable = args[current_index + 1];
+ current_index += 2;
+
+ if(args.size() < (current_index + 2) || args[current_index] != "QUERY")
+ {
+ this->SetError("missing QUERY specification");
+ return false;
+ }
+
+ cmsys::SystemInformation info;
+ info.RunCPUCheck();
+ info.RunOSCheck();
+ info.RunMemoryCheck();
+
+ std::string result_list;
+ for(size_t i = current_index + 1; i < args.size(); ++i)
+ {
+ std::string key = args[i];
+ if(i != current_index + 1)
+ {
+ result_list += ";";
+ }
+ std::string value;
+ if(!this->GetValue(info, key, value)) return false;
+
+ result_list += value;
+ }
+
+ this->Makefile->AddDefinition(variable.c_str(), result_list.c_str());
+
+ return true;
+}
+
+bool cmCMakeHostSystemInformationCommand
+::GetValue(cmsys::SystemInformation &info,
+ std::string const& key, std::string &value)
+{
+ if(key == "NUMBER_OF_LOGICAL_CORES")
+ {
+ value = this->ValueToString(info.GetNumberOfLogicalCPU());
+ }
+ else if(key == "NUMBER_OF_PHYSICAL_CORES")
+ {
+ value = this->ValueToString(info.GetNumberOfPhysicalCPU());
+ }
+ else if(key == "HOSTNAME")
+ {
+ value = this->ValueToString(info.GetHostname());
+ }
+ else if(key == "FQDN")
+ {
+ value = this->ValueToString(info.GetFullyQualifiedDomainName());
+ }
+ else if(key == "TOTAL_VIRTUAL_MEMORY")
+ {
+ value = this->ValueToString(info.GetTotalVirtualMemory());
+ }
+ else if(key == "AVAILABLE_VIRTUAL_MEMORY")
+ {
+ value = this->ValueToString(info.GetAvailableVirtualMemory());
+ }
+ else if(key == "TOTAL_PHYSICAL_MEMORY")
+ {
+ value = this->ValueToString(info.GetTotalPhysicalMemory());
+ }
+ else if(key == "AVAILABLE_PHYSICAL_MEMORY")
+ {
+ value = this->ValueToString(info.GetAvailablePhysicalMemory());
+ }
+ else
+ {
+ std::string e = "does not recognize <key> " + key;
+ this->SetError(e.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+std::string cmCMakeHostSystemInformationCommand
+::ValueToString(size_t value) const
+{
+ cmsys_ios::stringstream tmp;
+ tmp << value;
+ return tmp.str();
+}
+
+std::string cmCMakeHostSystemInformationCommand
+::ValueToString(const char *value) const
+{
+ std::string safe_string = value ? value : "";
+ return safe_string;
+}
+
+std::string cmCMakeHostSystemInformationCommand
+::ValueToString(std::string const& value) const
+{
+ return value;
+}
diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h
new file mode 100644
index 000000000..d1b8700ff
--- /dev/null
+++ b/Source/cmCMakeHostSystemInformationCommand.h
@@ -0,0 +1,102 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2013 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmCMakeHostSystemInformationCommand_h
+#define cmCMakeHostSystemInformationCommand_h
+
+#include "cmCommand.h"
+
+#include <cmsys/SystemInformation.hxx>
+
+/** \class cmCMakeHostSystemInformationCommand
+ * \brief Query host system specific information
+ *
+ * cmCMakeHostSystemInformationCommand queries system information of
+ * the sytem on which CMake runs.
+ */
+class cmCMakeHostSystemInformationCommand : public cmCommand
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ virtual cmCommand* Clone()
+ {
+ return new cmCMakeHostSystemInformationCommand;
+ }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ virtual bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus &status);
+
+ /**
+ * This determines if the command is invoked when in script mode.
+ */
+ virtual bool IsScriptable() const { return true; }
+
+ /**
+ * The name of the command as specified in CMakeList.txt.
+ */
+ virtual const char* GetName() const
+ {
+ return "cmake_host_system_information";
+ }
+
+ /**
+ * Succinct documentation.
+ */
+ virtual const char* GetTerseDocumentation() const
+ {
+ return "Query host system specific information.";
+ }
+
+ /**
+ * More documentation.
+ */
+ virtual const char* GetFullDocumentation() const
+ {
+ return
+ " cmake_host_system_information(RESULT <variable> QUERY <key> ...)\n"
+ "Queries system information of the host system on which cmake runs. "
+ "One or more <key> can be provided to "
+ "select the information to be queried. "
+ "The list of queried values is stored in <variable>.\n"
+ "<key> can be one of the following values:\n"
+ " NUMBER_OF_LOGICAL_CORES = Number of logical cores.\n"
+ " NUMBER_OF_PHYSICAL_CORES = Number of physical cores.\n"
+ " HOSTNAME = Hostname.\n"
+ " FQDN = Fully qualified domain name.\n"
+ " TOTAL_VIRTUAL_MEMORY = "
+ "Total virtual memory in megabytes.\n"
+ " AVAILABLE_VIRTUAL_MEMORY = "
+ "Available virtual memory in megabytes.\n"
+ " TOTAL_PHYSICAL_MEMORY = "
+ "Total physical memory in megabytes.\n"
+ " AVAILABLE_PHYSICAL_MEMORY = "
+ "Available physical memory in megabytes.\n"
+ ;
+ }
+
+ cmTypeMacro(cmCMakeHostSystemInformationCommand, cmCommand);
+
+private:
+ bool GetValue(cmsys::SystemInformation &info,
+ std::string const& key, std::string &value);
+
+ std::string ValueToString(size_t value) const;
+ std::string ValueToString(const char *value) const;
+ std::string ValueToString(std::string const& value) const;
+};
+
+#endif
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index 48ae50e42..cb62f21e6 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -422,8 +422,9 @@ int CCONV cmExecuteCommand(void *arg, const char *name,
for(int i = 0; i < numArgs; ++i)
{
// Assume all arguments are quoted.
- lff.Arguments.push_back(cmListFileArgument(args[i], true,
- "[CMake-Plugin]", 0));
+ lff.Arguments.push_back(
+ cmListFileArgument(args[i], cmListFileArgument::Quoted,
+ "[CMake-Plugin]", 0));
}
cmExecutionStatus status;
return mf->ExecuteCommand(lff,status);
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 322a6a26f..14e1f5014 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -175,7 +175,7 @@ std::string cmCTest::GetCostDataFile()
static size_t
HTTPResponseCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
- register int realsize = (int)(size * nmemb);
+ int realsize = (int)(size * nmemb);
std::string *response
= static_cast<std::string*>(data);
@@ -294,6 +294,7 @@ cmCTest::cmCTest()
{
this->LabelSummary = true;
this->ParallelLevel = 1;
+ this->ParallelLevelSetInCli = false;
this->SubmitIndex = 0;
this->Failover = false;
this->BatchJobs = false;
@@ -1999,11 +2000,13 @@ void cmCTest::HandleCommandLineArguments(size_t &i,
i++;
int plevel = atoi(args[i].c_str());
this->SetParallelLevel(plevel);
+ this->ParallelLevelSetInCli = true;
}
else if(arg.find("-j") == 0)
{
int plevel = atoi(arg.substr(2).c_str());
this->SetParallelLevel(plevel);
+ this->ParallelLevelSetInCli = true;
}
if(this->CheckArgument(arg, "--no-compress-output"))
@@ -2398,6 +2401,14 @@ int cmCTest::Run(std::vector<std::string> &args, std::string* output)
}
} // the close of the for argument loop
+ if (!this->ParallelLevelSetInCli)
+ {
+ if (const char *parallel = cmSystemTools::GetEnv("CTEST_PARALLEL_LEVEL"))
+ {
+ int plevel = atoi(parallel);
+ this->SetParallelLevel(plevel);
+ }
+ }
// now what sould cmake do? if --build-and-test was specified then
// we run the build and test handler and return
@@ -2413,7 +2424,7 @@ int cmCTest::Run(std::vector<std::string> &args, std::string* output)
#endif
if(retv != 0)
{
- cmCTestLog(this, DEBUG, "build and test failing returing: " << retv
+ cmCTestLog(this, DEBUG, "build and test failing returning: " << retv
<< std::endl);
}
return retv;
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 587a6db51..5dd35ce41 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -485,6 +485,7 @@ private:
int MaxTestNameWidth;
int ParallelLevel;
+ bool ParallelLevelSetInCli;
int CompatibilityMode;
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 3d5b24b84..ed09545cb 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -491,7 +491,7 @@ bool cmCacheManager::SaveCache(const char* path)
<< "# The syntax for the file is as follows:\n"
<< "# KEY:TYPE=VALUE\n"
<< "# KEY is the name of a variable in the cache.\n"
- << "# TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT "
+ << "# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT "
"TYPE!." << std::endl
<< "# VALUE is the current value for the KEY.\n\n";
@@ -750,6 +750,10 @@ void cmCacheManager::AddCacheEntry(const char* key,
}
e.SetProperty("HELPSTRING", helpString? helpString :
"(This variable does not exist and should not be used)");
+ if (this->Cache[key].Value == e.Value)
+ {
+ this->CMakeInstance->UnwatchUnusedCli(key);
+ }
this->Cache[key] = e;
}
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index 4a5ee450f..a5e5eeeff 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -82,7 +82,7 @@ public:
{
this->Find(key);
}
- }
+ }
private:
CacheEntry const& GetEntry() const { return this->Position->second; }
CacheEntry& GetEntry() { return this->Position->second; }
diff --git a/Source/cmCommandArgumentLexer.cxx b/Source/cmCommandArgumentLexer.cxx
index 1d7140bb2..e68f6b5fd 100644
--- a/Source/cmCommandArgumentLexer.cxx
+++ b/Source/cmCommandArgumentLexer.cxx
@@ -730,9 +730,9 @@ extern int cmCommandArgument_yylex (yyscan_t yyscanner);
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
#line 64 "cmCommandArgumentLexer.in.l"
@@ -782,7 +782,7 @@ YY_DECL
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1082,9 +1082,9 @@ return 0; /* this should not happend but it should silence a warning */
static int yy_get_next_buffer (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = yyg->yytext_ptr;
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = yyg->yytext_ptr;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1216,15 +1216,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
+ yy_state_type yy_current_state;
+ char *yy_cp;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_current_state = yyg->yy_start;
for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1249,11 +1249,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
{
- register int yy_is_jam;
+ int yy_is_jam;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
- register char *yy_cp = yyg->yy_c_buf_p;
+ char *yy_cp = yyg->yy_c_buf_p;
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -2015,7 +2015,7 @@ int cmCommandArgument_yylex_destroy (yyscan_t yyscanner)
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
{
- register int i;
+ int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
@@ -2024,7 +2024,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
{
- register int n;
+ int n;
for ( n = 0; s[n]; ++n )
;
diff --git a/Source/cmCommandArgumentLexer.in.l b/Source/cmCommandArgumentLexer.in.l
index fdca61bfa..24a0eec85 100644
--- a/Source/cmCommandArgumentLexer.in.l
+++ b/Source/cmCommandArgumentLexer.in.l
@@ -22,6 +22,7 @@ Modify cmCommandArgumentLexer.cxx:
- add #include "cmStandardIncludes.h" to top of file
- put header block at top of file
- remove TABs
+ - remove use of the 'register' storage class specifier
- remove "yyscanner" argument from these methods:
yy_fatal_error, cmCommandArgument_yyalloc, cmCommandArgument_yyrealloc, cmCommandArgument_yyfree
- remove all YY_BREAK lines occurring right after return statements
diff --git a/Source/cmCommandArgumentParser.y b/Source/cmCommandArgumentParser.y
index 3e700c80b..48f5c8ecd 100644
--- a/Source/cmCommandArgumentParser.y
+++ b/Source/cmCommandArgumentParser.y
@@ -20,6 +20,7 @@ Run bison like this:
Modify cmCommandArgumentParser.cxx:
- remove TABs
+ - remove use of the 'register' storage class specifier
- put header block at top of file
*/
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index 2f26b0cd4..dbeeb0793 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -12,10 +12,10 @@
#include "cmCommandArgumentParserHelper.h"
#include "cmSystemTools.h"
-#include "cmCommandArgumentLexer.h"
-
#include "cmMakefile.h"
+#include "cmCommandArgumentLexer.h"
+
int cmCommandArgument_yyparse( yyscan_t yyscanner );
//
cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 227b22678..1e2a85cfb 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -11,8 +11,10 @@
============================================================================*/
#include "cmCommands.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
+#include "cmAddCompileOptionsCommand.cxx"
#include "cmAuxSourceDirectoryCommand.cxx"
#include "cmBuildNameCommand.cxx"
+#include "cmCMakeHostSystemInformationCommand.cxx"
#include "cmElseIfCommand.cxx"
#include "cmExportCommand.cxx"
#include "cmExportLibraryDependencies.cxx"
@@ -29,6 +31,7 @@
#include "cmSourceGroupCommand.cxx"
#include "cmSubdirDependsCommand.cxx"
#include "cmTargetCompileDefinitionsCommand.cxx"
+#include "cmTargetCompileOptionsCommand.cxx"
#include "cmTargetIncludeDirectoriesCommand.cxx"
#include "cmTargetPropCommandBase.cxx"
#include "cmUseMangledMesaCommand.cxx"
@@ -51,8 +54,10 @@ void GetPredefinedCommands(std::list<cmCommand*>&
)
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
+ commands.push_back(new cmAddCompileOptionsCommand);
commands.push_back(new cmAuxSourceDirectoryCommand);
commands.push_back(new cmBuildNameCommand);
+ commands.push_back(new cmCMakeHostSystemInformationCommand);
commands.push_back(new cmElseIfCommand);
commands.push_back(new cmExportCommand);
commands.push_back(new cmExportLibraryDependenciesCommand);
@@ -71,6 +76,7 @@ void GetPredefinedCommands(std::list<cmCommand*>&
commands.push_back(new cmSubdirDependsCommand);
commands.push_back(new cmTargetIncludeDirectoriesCommand);
commands.push_back(new cmTargetCompileDefinitionsCommand);
+ commands.push_back(new cmTargetCompileOptionsCommand);
commands.push_back(new cmUseMangledMesaCommand);
commands.push_back(new cmUtilitySourceCommand);
commands.push_back(new cmVariableRequiresCommand);
diff --git a/Source/cmCommands.h b/Source/cmCommands.h
index 096fc2006..c56673fed 100644
--- a/Source/cmCommands.h
+++ b/Source/cmCommands.h
@@ -16,12 +16,13 @@
class cmCommand;
/**
* Global function to return all compiled in commands.
- * To add a new command edit cmCommands.cxx or cmBootstrapCommands.cxx
+ * To add a new command edit cmCommands.cxx or cmBootstrapCommands[12].cxx
* and add your command.
* It is up to the caller to delete the commands created by this
* call.
*/
-void GetBootstrapCommands(std::list<cmCommand*>& commands);
+void GetBootstrapCommands1(std::list<cmCommand*>& commands);
+void GetBootstrapCommands2(std::list<cmCommand*>& commands);
void GetPredefinedCommands(std::list<cmCommand*>& commands);
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 896b50aa5..fb7b5b67d 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -499,7 +499,7 @@ bool cmComputeLinkInformation::Compute()
if(!this->LinkLanguage)
{
cmSystemTools::
- Error("CMake can not determine linker language for target:",
+ Error("CMake can not determine linker language for target: ",
this->Target->GetName());
return false;
}
@@ -882,7 +882,8 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
}
// Compute a regex to match link extensions.
- std::string libext = this->CreateExtensionRegex(this->LinkExtensions);
+ std::string libext = this->CreateExtensionRegex(this->LinkExtensions,
+ LinkUnknown);
// Create regex to remove any library extension.
std::string reg("(.*)");
@@ -916,7 +917,8 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
if(!this->StaticLinkExtensions.empty())
{
std::string reg_static = reg;
- reg_static += this->CreateExtensionRegex(this->StaticLinkExtensions);
+ reg_static += this->CreateExtensionRegex(this->StaticLinkExtensions,
+ LinkStatic);
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
fprintf(stderr, "static regex [%s]\n", reg_static.c_str());
#endif
@@ -928,7 +930,7 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
{
std::string reg_shared = reg;
this->SharedRegexString =
- this->CreateExtensionRegex(this->SharedLinkExtensions);
+ this->CreateExtensionRegex(this->SharedLinkExtensions, LinkShared);
reg_shared += this->SharedRegexString;
#ifdef CM_COMPUTE_LINK_INFO_DEBUG
fprintf(stderr, "shared regex [%s]\n", reg_shared.c_str());
@@ -966,7 +968,7 @@ void cmComputeLinkInformation::AddLinkExtension(const char* e, LinkType type)
//----------------------------------------------------------------------------
std::string
cmComputeLinkInformation
-::CreateExtensionRegex(std::vector<std::string> const& exts)
+::CreateExtensionRegex(std::vector<std::string> const& exts, LinkType type)
{
// Build a list of extension choices.
std::string libext = "(";
@@ -995,6 +997,10 @@ cmComputeLinkInformation
{
libext += "(\\.[0-9]+\\.[0-9]+)?";
}
+ else if(type == LinkShared)
+ {
+ libext += "(\\.[0-9]+)?";
+ }
libext += "$";
return libext;
@@ -1339,12 +1345,23 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
return;
}
+ std::string fw_path = this->SplitFramework.match(1);
+ std::string fw = this->SplitFramework.match(2);
+ std::string full_fw = fw_path;
+ full_fw += "/";
+ full_fw += fw;
+ full_fw += ".framework";
+ full_fw += "/";
+ full_fw += fw;
+
// Add the directory portion to the framework search path.
- this->AddFrameworkPath(this->SplitFramework.match(1));
+ this->AddFrameworkPath(fw_path);
+
+ // add runtime information
+ this->AddLibraryRuntimeInfo(full_fw);
// Add the item using the -framework option.
this->Items.push_back(Item("-framework", false));
- std::string fw = this->SplitFramework.match(2);
fw = this->LocalGenerator->EscapeForShell(fw.c_str());
this->Items.push_back(Item(fw, false));
}
@@ -1724,6 +1741,17 @@ void
cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath,
cmTarget* target)
{
+ // Ignore targets on Apple where install_name is not @rpath.
+ // The dependenty library can be found with other means such as
+ // @loader_path or full paths.
+ if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
+ {
+ if(!target->HasMacOSXRpath(this->Config))
+ {
+ return;
+ }
+ }
+
// Libraries with unknown type must be handled using just the file
// on disk.
if(target->GetType() == cmTarget::UNKNOWN_LIBRARY)
@@ -1756,25 +1784,61 @@ void
cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath)
{
// Get the name of the library from the file name.
+ bool is_shared_library = false;
std::string file = cmSystemTools::GetFilenameName(fullPath);
- if(!this->ExtractSharedLibraryName.find(file.c_str()))
+
+ if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
+ {
+ // Check that @rpath is part of the install name.
+ // If it isn't, return.
+ std::string soname;
+ if(!cmSystemTools::GuessLibraryInstallName(fullPath, soname))
+ {
+ return;
+ }
+
+ if(soname.find("@rpath") == std::string::npos)
+ {
+ return;
+ }
+ }
+
+ is_shared_library = this->ExtractSharedLibraryName.find(file.c_str());
+
+ if(!is_shared_library)
{
// On some platforms (AIX) a shared library may look static.
if(this->ArchivesMayBeShared)
{
- if(!this->ExtractStaticLibraryName.find(file.c_str()))
+ if(this->ExtractStaticLibraryName.find(file.c_str()))
{
- // This is not the name of a shared library or archive.
- return;
+ // This is the name of a shared library or archive.
+ is_shared_library = true;
}
}
- else
+ }
+
+ // It could be an Apple framework
+ if(!is_shared_library)
+ {
+ if(fullPath.find(".framework") != std::string::npos)
{
- // This is not the name of a shared library.
- return;
+ cmsys::RegularExpression splitFramework;
+ splitFramework.compile("^(.*)/(.*).framework/(.*)$");
+ if(splitFramework.find(fullPath) &&
+ (std::string::npos !=
+ splitFramework.match(3).find(splitFramework.match(2))))
+ {
+ is_shared_library = true;
+ }
}
}
+ if(!is_shared_library)
+ {
+ return;
+ }
+
// Include this library in the runtime path ordering.
this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath);
if(this->LinkWithRuntimePath)
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index 1a76922a5..e6ee87185 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -134,7 +134,8 @@ private:
bool OpenBSD;
void AddLinkPrefix(const char* p);
void AddLinkExtension(const char* e, LinkType type);
- std::string CreateExtensionRegex(std::vector<std::string> const& exts);
+ std::string CreateExtensionRegex(std::vector<std::string> const& exts,
+ LinkType type);
std::string NoCaseExpression(const char* str);
// Handling of link items.
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 8fd95b9cd..0829add20 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -282,6 +282,8 @@ void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
if(emitted.insert(*lib).second)
{
this->AddTargetDepend(depender_index, lib->c_str(), true);
+ this->AddInterfaceDepends(depender_index, lib->c_str(),
+ true, emitted);
}
}
}
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 114afd7b7..ab53b1d27 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -19,4 +19,4 @@
#cmakedefine CMAKE_STRICT
#define CMAKE_ROOT_DIR "${CMake_SOURCE_DIR}"
#define CMAKE_BUILD_DIR "${CMake_BINARY_DIR}"
-#define CMAKE_DATA_DIR "@CMAKE_DATA_DIR@"
+#define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@"
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 85e49a928..086f27a58 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -12,6 +12,7 @@
#include "cmCoreTryCompile.h"
#include "cmake.h"
#include "cmCacheManager.h"
+#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmExportTryCompileFileGenerator.h"
#include <cmsys/Directory.hxx>
@@ -23,150 +24,170 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
this->BinaryDirectory = argv[1].c_str();
this->OutputFile = "";
// which signature were we called with ?
- this->SrcFileSignature = false;
- unsigned int i;
+ this->SrcFileSignature = true;
const char* sourceDirectory = argv[2].c_str();
const char* projectName = 0;
const char* targetName = 0;
- char targetNameBuf[64];
- int extraArgs = 0;
-
- // look for CMAKE_FLAGS and store them
std::vector<std::string> cmakeFlags;
- for (i = 3; i < argv.size(); ++i)
- {
- if (argv[i] == "CMAKE_FLAGS")
- {
- // CMAKE_FLAGS is the first argument because we need an argv[0] that
- // is not used, so it matches regular command line parsing which has
- // the program name as arg 0
- for (; i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" &&
- argv[i] != "OUTPUT_VARIABLE" &&
- argv[i] != "LINK_LIBRARIES";
- ++i)
- {
- extraArgs++;
- cmakeFlags.push_back(argv[i]);
- }
- break;
- }
- }
-
- // look for OUTPUT_VARIABLE and store them
+ std::vector<std::string> compileDefs;
std::string outputVariable;
- for (i = 3; i < argv.size(); ++i)
+ std::string copyFile;
+ std::string copyFileError;
+ std::vector<cmTarget*> targets;
+ std::string libsToLink = " ";
+ bool useOldLinkLibs = true;
+ char targetNameBuf[64];
+ bool didOutputVariable = false;
+ bool didCopyFile = false;
+ bool didCopyFileError = false;
+ bool useSources = argv[2] == "SOURCES";
+ std::vector<std::string> sources;
+
+ enum Doing { DoingNone, DoingCMakeFlags, DoingCompileDefinitions,
+ DoingLinkLibraries, DoingOutputVariable, DoingCopyFile,
+ DoingCopyFileError, DoingSources };
+ Doing doing = useSources? DoingSources : DoingNone;
+ for(size_t i=3; i < argv.size(); ++i)
{
- if (argv[i] == "OUTPUT_VARIABLE")
+ if(argv[i] == "CMAKE_FLAGS")
{
- if ( argv.size() <= (i+1) )
- {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "OUTPUT_VARIABLE specified but there is no variable");
- return -1;
- }
- extraArgs += 2;
- outputVariable = argv[i+1];
- break;
+ doing = DoingCMakeFlags;
+ // CMAKE_FLAGS is the first argument because we need an argv[0] that
+ // is not used, so it matches regular command line parsing which has
+ // the program name as arg 0
+ cmakeFlags.push_back(argv[i]);
}
- }
-
- // look for COMPILE_DEFINITIONS and store them
- std::vector<std::string> compileFlags;
- for (i = 3; i < argv.size(); ++i)
- {
- if (argv[i] == "COMPILE_DEFINITIONS")
+ else if(argv[i] == "COMPILE_DEFINITIONS")
{
- extraArgs++;
- for (i = i + 1; i < argv.size() && argv[i] != "CMAKE_FLAGS" &&
- argv[i] != "OUTPUT_VARIABLE" &&
- argv[i] != "LINK_LIBRARIES";
- ++i)
- {
- extraArgs++;
- compileFlags.push_back(argv[i]);
- }
- break;
+ doing = DoingCompileDefinitions;
}
- }
-
- std::vector<cmTarget*> targets;
- std::string libsToLink = " ";
- bool useOldLinkLibs = true;
- for (i = 3; i < argv.size(); ++i)
- {
- if (argv[i] == "LINK_LIBRARIES")
+ else if(argv[i] == "LINK_LIBRARIES")
{
- if ( argv.size() <= (i+1) )
- {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "LINK_LIBRARIES specified but there is no content");
- return -1;
- }
- extraArgs++;
- ++i;
+ doing = DoingLinkLibraries;
useOldLinkLibs = false;
- for ( ; i < argv.size() && argv[i] != "CMAKE_FLAGS"
- && argv[i] != "COMPILE_DEFINITIONS" && argv[i] != "OUTPUT_VARIABLE";
- ++i)
+ }
+ else if(argv[i] == "OUTPUT_VARIABLE")
+ {
+ doing = DoingOutputVariable;
+ didOutputVariable = true;
+ }
+ else if(argv[i] == "COPY_FILE")
+ {
+ doing = DoingCopyFile;
+ didCopyFile = true;
+ }
+ else if(argv[i] == "COPY_FILE_ERROR")
+ {
+ doing = DoingCopyFileError;
+ didCopyFileError = true;
+ }
+ else if(doing == DoingCMakeFlags)
+ {
+ cmakeFlags.push_back(argv[i]);
+ }
+ else if(doing == DoingCompileDefinitions)
+ {
+ compileDefs.push_back(argv[i]);
+ }
+ else if(doing == DoingLinkLibraries)
+ {
+ libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" ";
+ if(cmTarget *tgt = this->Makefile->FindTargetToUse(argv[i].c_str()))
{
- extraArgs++;
- libsToLink += "\"" + cmSystemTools::TrimWhitespace(argv[i]) + "\" ";
- cmTarget *tgt = this->Makefile->FindTargetToUse(argv[i].c_str());
- if (!tgt)
- {
- continue;
- }
switch(tgt->GetType())
- {
- case cmTarget::SHARED_LIBRARY:
- case cmTarget::STATIC_LIBRARY:
- case cmTarget::UNKNOWN_LIBRARY:
- break;
- case cmTarget::EXECUTABLE:
- if (tgt->IsExecutableWithExports())
- {
+ {
+ case cmTarget::SHARED_LIBRARY:
+ case cmTarget::STATIC_LIBRARY:
+ case cmTarget::UNKNOWN_LIBRARY:
break;
- }
- default:
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "Only libraries may be used as try_compile IMPORTED "
- "LINK_LIBRARIES. Got " + std::string(tgt->GetName()) + " of "
- "type " + tgt->GetTargetTypeName(tgt->GetType()) + ".");
- return -1;
- }
- if (!tgt->IsImported())
+ case cmTarget::EXECUTABLE:
+ if (tgt->IsExecutableWithExports())
+ {
+ break;
+ }
+ default:
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "Only libraries may be used as try_compile IMPORTED "
+ "LINK_LIBRARIES. Got " + std::string(tgt->GetName()) + " of "
+ "type " + tgt->GetTargetTypeName(tgt->GetType()) + ".");
+ return -1;
+ }
+ if (tgt->IsImported())
{
- continue;
+ targets.push_back(tgt);
}
- targets.push_back(tgt);
}
- break;
+ }
+ else if(doing == DoingOutputVariable)
+ {
+ outputVariable = argv[i].c_str();
+ doing = DoingNone;
+ }
+ else if(doing == DoingCopyFile)
+ {
+ copyFile = argv[i].c_str();
+ doing = DoingNone;
+ }
+ else if(doing == DoingCopyFileError)
+ {
+ copyFileError = argv[i].c_str();
+ doing = DoingNone;
+ }
+ else if(doing == DoingSources)
+ {
+ sources.push_back(argv[i]);
+ }
+ else if(i == 3)
+ {
+ this->SrcFileSignature = false;
+ projectName = argv[i].c_str();
+ }
+ else if(i == 4 && !this->SrcFileSignature)
+ {
+ targetName = argv[i].c_str();
+ }
+ else
+ {
+ cmOStringStream m;
+ m << "try_compile given unknown argument \"" << argv[i] << "\".";
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str());
}
}
- // look for COPY_FILE
- std::string copyFile;
- for (i = 3; i < argv.size(); ++i)
+ if(didCopyFile && copyFile.empty())
{
- if (argv[i] == "COPY_FILE")
- {
- if ( argv.size() <= (i+1) )
- {
- this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "COPY_FILE specified but there is no variable");
- return -1;
- }
- extraArgs += 2;
- copyFile = argv[i+1];
- break;
- }
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "COPY_FILE must be followed by a file path");
+ return -1;
+ }
+
+ if(didCopyFileError && copyFileError.empty())
+ {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "COPY_FILE_ERROR must be followed by a variable name");
+ return -1;
+ }
+
+ if(didCopyFileError && !didCopyFile)
+ {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "COPY_FILE_ERROR may be used only with COPY_FILE");
+ return -1;
+ }
+
+ if(didOutputVariable && outputVariable.empty())
+ {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "OUTPUT_VARIABLE must be followed by a variable name");
+ return -1;
}
- // do we have a srcfile signature
- if (argv.size() - extraArgs == 3)
+ if(useSources && sources.empty())
{
- this->SrcFileSignature = true;
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "SOURCES must be followed by at least one source file");
+ return -1;
}
// compute the binary dir when TRY_COMPILE is called with a src file
@@ -179,10 +200,10 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
else
{
// only valid for srcfile signatures
- if (compileFlags.size())
+ if (compileDefs.size())
{
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
- "COMPILE_FLAGS specified on a srcdir type TRY_COMPILE");
+ "COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE");
return -1;
}
if (copyFile.size())
@@ -213,6 +234,44 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
std::string ccFile = this->BinaryDirectory + "/CMakeCache.txt";
cmSystemTools::RemoveFile(ccFile.c_str());
+ // Choose sources.
+ if(!useSources)
+ {
+ sources.push_back(argv[2]);
+ }
+
+ // Detect languages to enable.
+ cmLocalGenerator* lg = this->Makefile->GetLocalGenerator();
+ cmGlobalGenerator* gg = lg->GetGlobalGenerator();
+ std::set<std::string> testLangs;
+ for(std::vector<std::string>::iterator si = sources.begin();
+ si != sources.end(); ++si)
+ {
+ std::string ext = cmSystemTools::GetFilenameLastExtension(*si);
+ if(const char* lang = gg->GetLanguageFromExtension(ext.c_str()))
+ {
+ testLangs.insert(lang);
+ }
+ else
+ {
+ cmOStringStream err;
+ err << "Unknown extension \"" << ext << "\" for file\n"
+ << " " << *si << "\n"
+ << "try_compile() works only for enabled languages. "
+ << "Currently these are:\n ";
+ std::vector<std::string> langs;
+ gg->GetEnabledLanguages(langs);
+ for(std::vector<std::string>::iterator l = langs.begin();
+ l != langs.end(); ++l)
+ {
+ err << " " << *l;
+ }
+ err << "\nSee project() command to enable other languages.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, err.str());
+ return -1;
+ }
+ }
+
// we need to create a directory and CMakeLists file etc...
// first create the directories
sourceDirectory = this->BinaryDirectory.c_str();
@@ -229,10 +288,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
return -1;
}
- std::string source = argv[2];
- std::string ext = cmSystemTools::GetFilenameLastExtension(source);
- const char* lang =(this->Makefile->GetCMakeInstance()->GetGlobalGenerator()
- ->GetLanguageFromExtension(ext.c_str()));
const char* def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH");
fprintf(fout, "cmake_minimum_required(VERSION %u.%u.%u.%u)\n",
cmVersion::GetMajorVersion(), cmVersion::GetMinorVersion(),
@@ -242,67 +297,48 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
fprintf(fout, "SET(CMAKE_MODULE_PATH %s)\n", def);
}
- const char* rulesOverrideBase = "CMAKE_USER_MAKE_RULES_OVERRIDE";
- std::string rulesOverrideLang =
- rulesOverrideBase + (lang ? std::string("_") + lang : std::string(""));
- if(const char* rulesOverridePath =
- this->Makefile->GetDefinition(rulesOverrideLang.c_str()))
- {
- fprintf(fout, "SET(%s \"%s\")\n",
- rulesOverrideLang.c_str(), rulesOverridePath);
- }
- else if(const char* rulesOverridePath2 =
- this->Makefile->GetDefinition(rulesOverrideBase))
- {
- fprintf(fout, "SET(%s \"%s\")\n",
- rulesOverrideBase, rulesOverridePath2);
- }
-
- if(lang)
+ std::string projectLangs;
+ for(std::set<std::string>::iterator li = testLangs.begin();
+ li != testLangs.end(); ++li)
{
- fprintf(fout, "PROJECT(CMAKE_TRY_COMPILE %s)\n", lang);
- }
- else
- {
- fclose(fout);
- cmOStringStream err;
- err << "Unknown extension \"" << ext << "\" for file\n"
- << " " << source << "\n"
- << "try_compile() works only for enabled languages. "
- << "Currently these are:\n ";
- std::vector<std::string> langs;
- this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->
- GetEnabledLanguages(langs);
- for(std::vector<std::string>::iterator l = langs.begin();
- l != langs.end(); ++l)
+ projectLangs += " " + *li;
+ std::string rulesOverrideBase = "CMAKE_USER_MAKE_RULES_OVERRIDE";
+ std::string rulesOverrideLang = rulesOverrideBase + "_" + *li;
+ if(const char* rulesOverridePath =
+ this->Makefile->GetDefinition(rulesOverrideLang.c_str()))
{
- err << " " << *l;
+ fprintf(fout, "SET(%s \"%s\")\n",
+ rulesOverrideLang.c_str(), rulesOverridePath);
+ }
+ else if(const char* rulesOverridePath2 =
+ this->Makefile->GetDefinition(rulesOverrideBase.c_str()))
+ {
+ fprintf(fout, "SET(%s \"%s\")\n",
+ rulesOverrideBase.c_str(), rulesOverridePath2);
}
- err << "\nSee project() command to enable other languages.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, err.str());
- return -1;
}
- std::string langFlags = "CMAKE_";
- langFlags += lang;
- langFlags += "_FLAGS";
+ fprintf(fout, "PROJECT(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str());
fprintf(fout, "SET(CMAKE_VERBOSE_MAKEFILE 1)\n");
- fprintf(fout, "SET(CMAKE_%s_FLAGS \"", lang);
- const char* flags = this->Makefile->GetDefinition(langFlags.c_str());
- if(flags)
+ for(std::set<std::string>::iterator li = testLangs.begin();
+ li != testLangs.end(); ++li)
{
- fprintf(fout, " %s ", flags);
+ std::string langFlags = "CMAKE_" + *li + "_FLAGS";
+ const char* flags = this->Makefile->GetDefinition(langFlags.c_str());
+ fprintf(fout, "SET(CMAKE_%s_FLAGS %s)\n", li->c_str(),
+ lg->EscapeForCMake(flags?flags:"").c_str());
+ fprintf(fout, "SET(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
+ " ${COMPILE_DEFINITIONS}\")\n", li->c_str(), li->c_str());
}
- fprintf(fout, " ${COMPILE_DEFINITIONS}\")\n");
fprintf(fout, "INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES})\n");
fprintf(fout, "SET(CMAKE_SUPPRESS_REGENERATION 1)\n");
fprintf(fout, "LINK_DIRECTORIES(${LINK_DIRECTORIES})\n");
// handle any compile flags we need to pass on
- if (compileFlags.size())
+ if (compileDefs.size())
{
fprintf(fout, "ADD_DEFINITIONS( ");
- for (i = 0; i < compileFlags.size(); ++i)
+ for (size_t i = 0; i < compileDefs.size(); ++i)
{
- fprintf(fout,"%s ",compileFlags[i].c_str());
+ fprintf(fout,"%s ",compileDefs[i].c_str());
}
fprintf(fout, ")\n");
}
@@ -377,7 +413,19 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
fprintf(fout, "SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n",
this->BinaryDirectory.c_str());
/* Create the actual executable. */
- fprintf(fout, "ADD_EXECUTABLE(%s \"%s\")\n", targetName, source.c_str());
+ fprintf(fout, "ADD_EXECUTABLE(%s", targetName);
+ for(std::vector<std::string>::iterator si = sources.begin();
+ si != sources.end(); ++si)
+ {
+ fprintf(fout, " \"%s\"", si->c_str());
+
+ // Add dependencies on any non-temporary sources.
+ if(si->find("CMakeTmp") == si->npos)
+ {
+ this->Makefile->AddCMakeDependFile(*si);
+ }
+ }
+ fprintf(fout, ")\n");
if (useOldLinkLibs)
{
fprintf(fout,
@@ -391,22 +439,6 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
}
fclose(fout);
projectName = "CMAKE_TRY_COMPILE";
- // if the source is not in CMakeTmp
- if(source.find("CMakeTmp") == source.npos)
- {
- this->Makefile->AddCMakeDependFile(source.c_str());
- }
-
- }
- // else the srcdir bindir project target signature
- else
- {
- projectName = argv[3].c_str();
-
- if (argv.size() - extraArgs == 5)
- {
- targetName = argv[4].c_str();
- }
}
bool erroroc = cmSystemTools::GetErrorOccuredFlag();
@@ -438,6 +470,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
if (this->SrcFileSignature)
{
+ std::string copyFileErrorMessage;
this->FindOutputFile(targetName);
if ((res==0) && (copyFile.size()))
@@ -455,10 +488,23 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
{
emsg << this->FindErrorMessage.c_str();
}
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, emsg.str());
- return -1;
+ if(copyFileError.empty())
+ {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, emsg.str());
+ return -1;
+ }
+ else
+ {
+ copyFileErrorMessage = emsg.str();
+ }
}
}
+
+ if(!copyFileError.empty())
+ {
+ this->Makefile->AddDefinition(copyFileError.c_str(),
+ copyFileErrorMessage.c_str());
+ }
}
return res;
}
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index bd860ee6a..3620a3895 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -13,6 +13,8 @@
#include "cmMakefile.h"
+#include <cmsys/auto_ptr.hxx>
+
//----------------------------------------------------------------------------
cmCustomCommand::cmCustomCommand()
{
@@ -36,6 +38,32 @@ cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
}
//----------------------------------------------------------------------------
+cmCustomCommand& cmCustomCommand::operator=(cmCustomCommand const& r)
+{
+ if(this == &r)
+ {
+ return *this;
+ }
+
+ this->Outputs = r.Outputs;
+ this->Depends = r.Depends;
+ this->CommandLines = r.CommandLines;
+ this->HaveComment = r.HaveComment;
+ this->Comment = r.Comment;
+ this->WorkingDirectory = r.WorkingDirectory;
+ this->EscapeAllowMakeVars = r.EscapeAllowMakeVars;
+ this->EscapeOldStyle = r.EscapeOldStyle;
+ this->ImplicitDepends = r.ImplicitDepends;
+
+ cmsys::auto_ptr<cmListFileBacktrace>
+ newBacktrace(new cmListFileBacktrace(*r.Backtrace));
+ delete this->Backtrace;
+ this->Backtrace = newBacktrace.release();
+
+ return *this;
+}
+
+//----------------------------------------------------------------------------
cmCustomCommand::cmCustomCommand(cmMakefile* mf,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index dd92e34d7..e20d2bf40 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -27,6 +27,7 @@ public:
/** Default and copy constructors for STL containers. */
cmCustomCommand();
cmCustomCommand(const cmCustomCommand& r);
+ cmCustomCommand& operator=(cmCustomCommand const& r);
/** Main constructor specifies all information for the command. */
cmCustomCommand(cmMakefile* mf,
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 43b7b8a60..a252a1ab7 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -193,17 +193,8 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
// Construct the name of the file as if it were in the current
// include directory. Avoid using a leading "./".
- tempPathStr = "";
- if((*i) == ".")
- {
- tempPathStr += current.FileName;
- }
- else
- {
- tempPathStr += *i;
- tempPathStr+="/";
- tempPathStr+=current.FileName;
- }
+ tempPathStr =
+ cmSystemTools::CollapseCombinedPath(*i, current.FileName);
// Look for the file in this location.
if(cmSystemTools::FileExists(tempPathStr.c_str(), true))
@@ -458,9 +449,8 @@ void cmDependsC::Scan(std::istream& is, const char* directory,
// This was a double-quoted include with a relative path. We
// must check for the file in the directory containing the
// file we are scanning.
- entry.QuotedLocation = directory;
- entry.QuotedLocation += "/";
- entry.QuotedLocation += entry.FileName;
+ entry.QuotedLocation =
+ cmSystemTools::CollapseCombinedPath(directory, entry.FileName);
}
// Queue the file if it has not yet been encountered and it
diff --git a/Source/cmDependsFortranLexer.cxx b/Source/cmDependsFortranLexer.cxx
index b0d9a742d..924d9d2a9 100644
--- a/Source/cmDependsFortranLexer.cxx
+++ b/Source/cmDependsFortranLexer.cxx
@@ -913,9 +913,9 @@ extern int cmDependsFortran_yylex (yyscan_t yyscanner);
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
#line 71 "cmDependsFortranLexer.in.l"
@@ -966,7 +966,7 @@ YY_DECL
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1386,9 +1386,9 @@ ECHO;
static int yy_get_next_buffer (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = yyg->yytext_ptr;
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = yyg->yytext_ptr;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1520,8 +1520,8 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
+ yy_state_type yy_current_state;
+ char *yy_cp;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_current_state = yyg->yy_start;
@@ -1529,7 +1529,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1554,11 +1554,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
{
- register int yy_is_jam;
+ int yy_is_jam;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
- register char *yy_cp = yyg->yy_c_buf_p;
+ char *yy_cp = yyg->yy_c_buf_p;
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1576,9 +1576,9 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
return yy_is_jam ? 0 : yy_current_state;
}
- static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+ static void yyunput (int c, char * yy_bp , yyscan_t yyscanner)
{
- register char *yy_cp;
+ char *yy_cp;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_cp = yyg->yy_c_buf_p;
@@ -1589,10 +1589,10 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
{ /* need to shift things up to make room */
/* +2 for EOB chars. */
- register int number_to_move = yyg->yy_n_chars + 2;
- register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ int number_to_move = yyg->yy_n_chars + 2;
+ char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
- register char *source =
+ char *source =
&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
@@ -2359,7 +2359,7 @@ int cmDependsFortran_yylex_destroy (yyscan_t yyscanner)
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
{
- register int i;
+ int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
@@ -2368,7 +2368,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
{
- register int n;
+ int n;
for ( n = 0; s[n]; ++n )
;
diff --git a/Source/cmDependsFortranLexer.in.l b/Source/cmDependsFortranLexer.in.l
index 40e80b719..01488024e 100644
--- a/Source/cmDependsFortranLexer.in.l
+++ b/Source/cmDependsFortranLexer.in.l
@@ -30,6 +30,7 @@ Run flex like this:
Modify cmDependsFortranLexer.cxx:
- remove TABs
+ - remove use of the 'register' storage class specifier
- remove "yyscanner" argument from these methods:
yy_fatal_error, cmDependsFortran_yyalloc, cmDependsFortran_yyrealloc, cmDependsFortran_yyfree
- remove "yyscanner = NULL" from end of cmDependsFortran_yylex_destroy
diff --git a/Source/cmDependsFortranParser.y b/Source/cmDependsFortranParser.y
index 5681d698c..d814f3075 100644
--- a/Source/cmDependsFortranParser.y
+++ b/Source/cmDependsFortranParser.y
@@ -33,6 +33,7 @@ Run bison like this:
Modify cmDependsFortranParser.cxx:
- remove TABs
+ - remove use of the 'register' storage class specifier
- Remove the yyerrorlab block in range ["goto yyerrlab1", "yyerrlab1:"]
*/
diff --git a/Source/cmDependsJavaLexer.cxx b/Source/cmDependsJavaLexer.cxx
index 63cfebcd7..0af44b02e 100644
--- a/Source/cmDependsJavaLexer.cxx
+++ b/Source/cmDependsJavaLexer.cxx
@@ -904,9 +904,9 @@ extern int cmDependsJava_yylex (yyscan_t yyscanner);
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
#line 88 "cmDependsJavaLexer.in.l"
@@ -955,7 +955,7 @@ YY_DECL
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1604,9 +1604,9 @@ return 0; /* this should not happen but it silences a warning*/
static int yy_get_next_buffer (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = yyg->yytext_ptr;
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = yyg->yytext_ptr;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1730,15 +1730,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
+ yy_state_type yy_current_state;
+ char *yy_cp;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_current_state = yyg->yy_start;
for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1763,11 +1763,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
{
- register int yy_is_jam;
+ int yy_is_jam;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *yy_cp = yyg->yy_c_buf_p;
+ char *yy_cp = yyg->yy_c_buf_p;
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -2481,7 +2481,7 @@ int cmDependsJava_yylex_destroy (yyscan_t yyscanner)
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
{
- register int i;
+ int i;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
@@ -2491,7 +2491,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
{
- register int n;
+ int n;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
for ( n = 0; s[n]; ++n )
;
diff --git a/Source/cmDependsJavaLexer.in.l b/Source/cmDependsJavaLexer.in.l
index 9796ad52a..aa2f8a587 100644
--- a/Source/cmDependsJavaLexer.in.l
+++ b/Source/cmDependsJavaLexer.in.l
@@ -20,6 +20,7 @@ Run flex like this:
Modify cmDependsJavaLexer.c:
- remove TABs
+ - remove use of the 'register' storage class specifier
- remove "yyscanner" argument from these methods:
yy_fatal_error, cmDependsJava_yyalloc, cmDependsJava_yyrealloc, cmDependsJava_yyfree
- remove all YY_BREAK lines occurring right after return statements
diff --git a/Source/cmDependsJavaParser.cxx b/Source/cmDependsJavaParser.cxx
index 7f7c385da..586c0debe 100644
--- a/Source/cmDependsJavaParser.cxx
+++ b/Source/cmDependsJavaParser.cxx
@@ -446,7 +446,7 @@ union yyalloc
# define YYCOPY(To, From, Count) \
do \
{ \
- register YYSIZE_T yyi; \
+ YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(To)[yyi] = (From)[yyi]; \
} \
@@ -1821,7 +1821,7 @@ yystrlen (yystr)
const char *yystr;
# endif
{
- register const char *yys = yystr;
+ const char *yys = yystr;
while (*yys++ != '\0')
continue;
@@ -1846,8 +1846,8 @@ yystpcpy (yydest, yysrc)
const char *yysrc;
# endif
{
- register char *yyd = yydest;
- register const char *yys = yysrc;
+ char *yyd = yydest;
+ const char *yys = yysrc;
while ((*yyd++ = *yys++) != '\0')
continue;
@@ -1977,8 +1977,8 @@ YYSTYPE yylval;
/* Number of syntax errors so far. */
int yynerrs;
- register int yystate;
- register int yyn;
+ int yystate;
+ int yyn;
int yyresult;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
@@ -1996,12 +1996,12 @@ int yynerrs;
/* The state stack. */
short int yyssa[YYINITDEPTH];
short int *yyss = yyssa;
- register short int *yyssp;
+ short int *yyssp;
/* The semantic value stack. */
YYSTYPE yyvsa[YYINITDEPTH];
YYSTYPE *yyvs = yyvsa;
- register YYSTYPE *yyvsp;
+ YYSTYPE *yyvsp;
diff --git a/Source/cmDependsJavaParser.y b/Source/cmDependsJavaParser.y
index 53210b8ca..944d4b5ce 100644
--- a/Source/cmDependsJavaParser.y
+++ b/Source/cmDependsJavaParser.y
@@ -20,6 +20,7 @@ Run bison like this:
Modify cmDependsJavaParser.cxx:
- remove TABs
+ - remove use of the 'register' storage class specifier
- add __HP_aCC to the #if test for yyerrorlab warning suppression
*/
diff --git a/Source/cmDocumentCompileDefinitions.h b/Source/cmDocumentCompileDefinitions.h
index ef3b3e715..d15bd6dca 100644
--- a/Source/cmDocumentCompileDefinitions.h
+++ b/Source/cmDocumentCompileDefinitions.h
@@ -23,7 +23,7 @@
"in a (configured) header file. Then report the limitation. " \
"Known limitations include:\n" \
" # - broken almost everywhere\n" \
- " ; - broken in VS IDE and Borland Makefiles\n" \
+ " ; - broken in VS IDE 7.0 and Borland Makefiles\n" \
" , - broken in VS IDE\n" \
" % - broken in some cases in NMake\n" \
" & | - broken in some cases on MinGW\n" \
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 6cc3f25ae..46cd77eae 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -13,7 +13,7 @@
#define cmDocumentGeneratorExpressions_h
#define CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
- "Generator expressions are evaluted during build system generation " \
+ "Generator expressions are evaluated during build system generation " \
"to produce information specific to each build configuration. " \
"Valid expressions are:\n" \
" $<0:...> = empty string (ignores \"...\")\n" \
@@ -28,6 +28,8 @@
"strings which contain a ',' for example.\n" \
" $<SEMICOLON> = A literal ';'. Used to prevent " \
"list expansion on an argument with ';'.\n" \
+ " $<JOIN:list,...> = joins the list with the content of " \
+ "\"...\"\n" \
" $<TARGET_NAME:...> = Marks ... as being the name of a " \
"target. This is required if exporting targets to multiple " \
"dependent export sets. The '...' must be a literal name of a " \
@@ -38,6 +40,27 @@
"is exported using export(), or when the target is used by another " \
"target in the same buildsystem. Expands to the empty string " \
"otherwise.\n" \
+ " $<C_COMPILER_ID> = The CMake-id of the C compiler " \
+ "used.\n" \
+ " $<C_COMPILER_ID:comp> = '1' if the CMake-id of the C " \
+ "compiler matches comp, otherwise '0'.\n" \
+ " $<CXX_COMPILER_ID> = The CMake-id of the CXX compiler " \
+ "used.\n" \
+ " $<CXX_COMPILER_ID:comp> = '1' if the CMake-id of the CXX " \
+ "compiler matches comp, otherwise '0'.\n" \
+ " $<VERSION_GREATER:v1,v2> = '1' if v1 is a version greater than " \
+ "v2, else '0'.\n" \
+ " $<VERSION_LESS:v1,v2> = '1' if v1 is a version less than v2, " \
+ "else '0'.\n" \
+ " $<VERSION_EQUAL:v1,v2> = '1' if v1 is the same version as v2, " \
+ "else '0'.\n" \
+ " $<C_COMPILER_VERSION> = The version of the C compiler used.\n" \
+ " $<C_COMPILER_VERSION:ver> = '1' if the version of the C " \
+ "compiler matches ver, otherwise '0'.\n" \
+ " $<CXX_COMPILER_VERSION> = The version of the CXX compiler " \
+ "used.\n" \
+ " $<CXX_COMPILER_VERSION:ver> = '1' if the version of the CXX " \
+ "compiler matches ver, otherwise '0'.\n" \
" $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
" $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
" $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 61f9f5a25..c4f6216b6 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -10,7 +10,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_AR", cmProperty::VARIABLE,
"Name of archiving tool for static libraries.",
- "This specifies name of the program that creates archive "
+ "This specifies the name of the program that creates archive "
"or static libraries.",false,
"Variables that Provide Information");
@@ -19,7 +19,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"The full path to the cmake executable.",
"This is the full path to the CMake executable cmake which is "
"useful from custom commands that want to use the cmake -E "
- "option for portable system commands. "
+ "option for portable system commands. "
"(e.g. /usr/local/bin/cmake", false,
"Variables that Provide Information");
cm->DefineProperty
@@ -27,14 +27,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"The path to the top level of the build tree.",
"This is the full path to the top level of the current CMake "
"build tree. For an in-source build, this would be the same "
- "as CMAKE_SOURCE_DIR. ", false,
+ "as CMAKE_SOURCE_DIR.", false,
"Variables that Provide Information");
cm->DefineProperty
("CMAKE_SOURCE_DIR", cmProperty::VARIABLE,
"The path to the top level of the source tree.",
"This is the full path to the top level of the current CMake "
"source tree. For an in-source build, this would be the same "
- "as CMAKE_BINARY_DIR. ", false,
+ "as CMAKE_BINARY_DIR.", false,
"Variables that Provide Information");
cm->DefineProperty
("CMAKE_CURRENT_BINARY_DIR", cmProperty::VARIABLE,
@@ -42,7 +42,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"This the full path to the build directory that is currently "
"being processed by cmake. Each directory added by "
"add_subdirectory will create a binary directory in the build "
- "tree, and as it is being processed this variable will be set. "
+ "tree, and as it is being processed this variable will be set. "
"For in-source builds this is the current source directory "
"being processed.", false,
"Variables that Provide Information");
@@ -100,7 +100,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_SCRIPT_MODE_FILE", cmProperty::VARIABLE,
- "Full path to the -P script file currently being processed. ",
+ "Full path to the -P script file currently being processed.",
"When run in -P script mode, CMake sets this variable to the full "
"path of the script file. When run to configure a CMakeLists.txt "
"file, this variable is not set.", false,
@@ -108,14 +108,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_ARGC", cmProperty::VARIABLE,
- "Number of command line arguments passed to CMake in script mode. ",
+ "Number of command line arguments passed to CMake in script mode.",
"When run in -P script mode, CMake sets this variable to the number "
- "of command line arguments. See also CMAKE_ARGV0, 1, 2 ... ", false,
+ "of command line arguments. See also CMAKE_ARGV0, 1, 2 ...", false,
"Variables that Provide Information");
cm->DefineProperty
("CMAKE_ARGV0", cmProperty::VARIABLE,
- "Command line argument passed to CMake in script mode. ",
+ "Command line argument passed to CMake in script mode.",
"When run in -P script mode, CMake sets this variable to "
"the first command line argument. It then also sets CMAKE_ARGV1, "
"CMAKE_ARGV2, ... and so on, up to the number of command line arguments "
@@ -129,11 +129,11 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
" needed to build the output of CMake. If the "
"generator selected was Visual Studio 6, the "
"CMAKE_BUILD_TOOL will be set to msdev, for "
- "Unix makefiles it will be set to make or gmake, "
+ "Unix Makefiles it will be set to make or gmake, "
"and for Visual Studio 7 it set to devenv. For "
- "Nmake Makefiles the value is nmake. This can be "
+ "NMake Makefiles the value is nmake. This can be "
"useful for adding special flags and commands based"
- " on the final build environment. ", false,
+ " on the final build environment.", false,
"Variables that Provide Information");
cm->DefineProperty
("CMAKE_CROSSCOMPILING", cmProperty::VARIABLE,
@@ -152,7 +152,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_CACHE_MAJOR_VERSION", cmProperty::VARIABLE,
"Major version of CMake used to create the CMakeCache.txt file",
- "This is stores the major version of CMake used to "
+ "This stores the major version of CMake used to "
"write a CMake cache file. It is only different when "
"a different version of CMake is run on a previously "
"created cache file.", false,
@@ -160,7 +160,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_CACHE_MINOR_VERSION", cmProperty::VARIABLE,
"Minor version of CMake used to create the CMakeCache.txt file",
- "This is stores the minor version of CMake used to "
+ "This stores the minor version of CMake used to "
"write a CMake cache file. It is only different when "
"a different version of CMake is run on a previously "
"created cache file.", false,
@@ -169,7 +169,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_CACHE_PATCH_VERSION", cmProperty::VARIABLE,
"Patch version of CMake used to create the CMakeCache.txt file",
- "This is stores the patch version of CMake used to "
+ "This stores the patch version of CMake used to "
"write a CMake cache file. It is only different when "
"a different version of CMake is run on a previously "
"created cache file.", false,
@@ -270,12 +270,13 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_LINK_LIBRARY_SUFFIX", cmProperty::VARIABLE,
"The suffix for libraries that you link to.",
- "The suffix to use for the end of a library, .lib on Windows.",false,
+ "The suffix to use for the end of a library filename, .lib on Windows."
+ ,false,
"Variables that Provide Information");
cm->DefineProperty
("CMAKE_EXECUTABLE_SUFFIX", cmProperty::VARIABLE,
"The suffix for executables on this platform.",
- "The suffix to use for the end of an executable if any, "
+ "The suffix to use for the end of an executable filename if any, "
".exe on Windows."
"\n"
"CMAKE_EXECUTABLE_SUFFIX_<LANG> overrides this for language <LANG>."
@@ -344,11 +345,12 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_PARENT_LIST_FILE", cmProperty::VARIABLE,
- "Full path to the parent listfile of the one currently being processed.",
- "As CMake processes the listfiles in your project this "
- "variable will always be set to the listfile that included "
- "or somehow invoked the one currently being "
- "processed. See also CMAKE_CURRENT_LIST_FILE.",false,
+ "Full path to the CMake file that included the current one.",
+ "While processing a CMake file loaded by include() or find_package() "
+ "this variable contains the full path to the file including it. "
+ "The top of the include stack is always the CMakeLists.txt for the "
+ "current directory. "
+ "See also CMAKE_CURRENT_LIST_FILE.",false,
"Variables that Provide Information");
cm->DefineProperty
@@ -391,7 +393,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_SOURCE_DIR", cmProperty::VARIABLE,
"Source directory for project.",
- "This is the top level source directory for the project. "
+ "This is the top level source directory for the project. "
"It corresponds to the source directory given to "
"cmake-gui or ccmake.",false,
"Variables that Provide Information");
@@ -417,7 +419,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("PROJECT_NAME", cmProperty::VARIABLE,
"Name of the project given to the project command.",
"This is the name given to the most "
- "recent PROJECT command. ",false,
+ "recent PROJECT command.",false,
"Variables that Provide Information");
cm->DefineProperty
("PROJECT_SOURCE_DIR", cmProperty::VARIABLE,
@@ -452,8 +454,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
,false, "Variables that Provide Information");
cm->DefineProperty
("CMAKE_IMPORT_LIBRARY_SUFFIX", cmProperty::VARIABLE,
- "The suffix for import libraries that you link to.",
- "The suffix to use for the end of an import library if used "
+ "The suffix for import libraries that you link to.",
+ "The suffix to use for the end of an import library filename if used "
"on this platform."
"\n"
"CMAKE_IMPORT_LIBRARY_SUFFIX_<LANG> overrides this for language <LANG>."
@@ -468,7 +470,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_SHARED_LIBRARY_SUFFIX", cmProperty::VARIABLE,
"The suffix for shared libraries that you link to.",
- "The suffix to use for the end of a shared library, .dll on Windows."
+ "The suffix to use for the end of a shared library filename, "
+ ".dll on Windows."
"\n"
"CMAKE_SHARED_LIBRARY_SUFFIX_<LANG> overrides this for language <LANG>."
,false, "Variables that Provide Information");
@@ -482,7 +485,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_SHARED_MODULE_SUFFIX", cmProperty::VARIABLE,
"The suffix for shared libraries that you link to.",
- "The suffix to use for the end of a loadable module on this platform"
+ "The suffix to use for the end of a loadable module filename "
+ "on this platform"
"\n"
"CMAKE_SHARED_MODULE_SUFFIX_<LANG> overrides this for language <LANG>."
,false, "Variables that Provide Information");
@@ -496,7 +500,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_STATIC_LIBRARY_SUFFIX", cmProperty::VARIABLE,
"The suffix for static libraries that you link to.",
- "The suffix to use for the end of a static library, .lib on Windows."
+ "The suffix to use for the end of a static library filename, "
+ ".lib on Windows."
"\n"
"CMAKE_STATIC_LIBRARY_SUFFIX_<LANG> overrides this for language <LANG>."
,false, "Variables that Provide Information");
@@ -509,6 +514,13 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"analysis of libraries linked by a target.",
false,
"Variables that Provide Information");
+ cm->DefineProperty
+ ("CMAKE_MINIMUM_REQUIRED_VERSION", cmProperty::VARIABLE,
+ "Version specified to cmake_minimum_required command",
+ "Variable containing the VERSION component specified in the "
+ "cmake_minimum_required command.",
+ false,
+ "Variables that Provide Information");
// Variables defined by cmake, that change the behavior
@@ -538,7 +550,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"By default, automoc behaves exactly as described in the documentation "
"of the AUTOMOC target property. "
"When set to TRUE, it accepts more input and tries to find the correct "
- "input file for moc even if it differs from the documented behaviour. "
+ "input file for moc even if it differs from the documented behaviour. "
"In this mode it e.g. also checks whether a header file is intended to "
"be processed by moc when a \"foo.moc\" file has been included.\n"
"Relaxed mode has to be enabled for KDE4 compatibility.",
@@ -551,7 +563,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"If an install() command is used without the COMPONENT argument, "
"these files will be grouped into a default component. The name of this "
"default install component will be taken from this variable. "
- "It defaults to \"Unspecified\". ",
+ "It defaults to \"Unspecified\".",
false,
"Variables That Change Behavior");
@@ -577,26 +589,37 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_CONFIGURATION_TYPES", cmProperty::VARIABLE,
- "Specifies the available build types.",
- "This specifies what build types will be available such as "
- "Debug, Release, RelWithDebInfo etc. This has reasonable defaults "
- "on most platforms. But can be extended to provide other "
- "build types. See also CMAKE_BUILD_TYPE.",
- false,
+ "Specifies the available build types on multi-config generators.",
+ "This specifies what build types (configurations) will be available "
+ "such as Debug, Release, RelWithDebInfo etc. "
+ "This has reasonable defaults on most platforms, "
+ "but can be extended to provide other build types. "
+ "See also CMAKE_BUILD_TYPE for details of managing configuration data, "
+ "and CMAKE_CFG_INTDIR."
+ ,false,
"Variables That Change Behavior");
cm->DefineProperty
("CMAKE_BUILD_TYPE", cmProperty::VARIABLE,
- "Specifies the build type for make based generators.",
- "This specifies what build type will be built in this tree. "
- " Possible values are empty, Debug, Release, RelWithDebInfo"
- " and MinSizeRel. This variable is only supported for "
- "make based generators. If this variable is supported, "
- "then CMake will also provide initial values for the "
- "variables with the name "
- " CMAKE_C_FLAGS_[DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL]."
- " For example, if CMAKE_BUILD_TYPE is Debug, then "
- "CMAKE_C_FLAGS_DEBUG will be added to the CMAKE_C_FLAGS.",false,
+ "Specifies the build type on single-configuration generators.",
+ "This statically specifies what build type (configuration) "
+ "will be built in this build tree. Possible values are "
+ "empty, Debug, Release, RelWithDebInfo and MinSizeRel. "
+ "This variable is only meaningful to single-configuration generators "
+ "(such as make and Ninja) i.e. "
+ "those which choose a single configuration "
+ "when CMake runs to generate a build tree as opposed to "
+ "multi-configuration generators which offer selection of the build "
+ "configuration within the generated build environment. "
+ "There are many per-config properties and variables "
+ "(usually following clean SOME_VAR_<CONFIG> order conventions), "
+ "such as CMAKE_C_FLAGS_<CONFIG>, specified as uppercase: "
+ "CMAKE_C_FLAGS_[DEBUG|RELEASE|RELWITHDEBINFO|MINSIZEREL]. "
+ "For example, in a build tree configured "
+ "to build type Debug, CMake will see to having "
+ "CMAKE_C_FLAGS_DEBUG settings get added to the CMAKE_C_FLAGS settings. "
+ "See also CMAKE_CONFIGURATION_TYPES."
+ ,false,
"Variables That Change Behavior");
cm->DefineProperty
@@ -616,32 +639,36 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_INSTALL_PREFIX", cmProperty::VARIABLE,
"Install directory used by install.",
"If \"make install\" is invoked or INSTALL is built"
- ", this directory is pre-pended onto all install "
+ ", this directory is prepended onto all install "
"directories. This variable defaults to /usr/local"
" on UNIX and c:/Program Files on Windows.\n"
"On UNIX one can use the DESTDIR mechanism in order"
- " to relocate the whole installation. "
+ " to relocate the whole installation. "
"DESTDIR means DESTination DIRectory. It is "
"commonly used by makefile users "
- "in order to install software at non-default location. "
+ "in order to install software at non-default location. "
"It is usually invoked like this:\n"
" make DESTDIR=/home/john install\n"
"which will install the concerned software using the"
- " installation prefix, e.g. \"/usr/local\" pre-pended with "
+ " installation prefix, e.g. \"/usr/local\" prepended with "
"the DESTDIR value which finally gives \"/home/john/usr/local\".\n"
"WARNING: DESTDIR may not be used on Windows because installation"
" prefix usually contains a drive letter like in \"C:/Program Files\""
- " which cannot be pre-pended with some other prefix."
+ " which cannot be prepended with some other prefix."
+ "\n"
+ "The installation prefix is also added to CMAKE_SYSTEM_PREFIX_PATH "
+ "so that find_package, find_program, find_library, find_path, and "
+ "find_file will search the prefix for other software."
,false,
"Variables That Change Behavior");
cm->DefineProperty
("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY", cmProperty::VARIABLE,
"Don't make the install target depend on the all target.",
- "By default, the \"install\" target depends on the \"all\" target. "
+ "By default, the \"install\" target depends on the \"all\" target. "
"This has the effect, that when \"make install\" is invoked or INSTALL "
"is built, first the \"all\" target is built, then the installation "
- "starts. "
+ "starts. "
"If CMAKE_SKIP_INSTALL_ALL_DEPENDENCY is set to TRUE, this dependency "
"is not created, so the installation process will start immediately, "
"independent from whether the project has been completely built or not."
@@ -658,6 +685,23 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Variables That Change Behavior");
cm->DefineProperty
+ ("CMAKE_WARN_DEPRECATED", cmProperty::VARIABLE,
+ "Whether to issue deprecation warnings for macros and functions.",
+ "If TRUE, this can be used by macros and functions to issue "
+ "deprecation warnings. This variable is FALSE by default.",
+ false,
+ "Variables That Change Behavior");
+
+ cm->DefineProperty
+ ("CMAKE_ERROR_DEPRECATED", cmProperty::VARIABLE,
+ "Whether to issue deprecation errors for macros and functions.",
+ "If TRUE, this can be used by macros and functions to issue "
+ "fatal errors when deprecated macros or functions are used. This "
+ "variable is FALSE by default.",
+ false,
+ "Variables That Change Behavior");
+
+ cm->DefineProperty
("CMAKE_PREFIX_PATH", cmProperty::VARIABLE,
"Path used for searching by FIND_XXX(), with appropriate suffixes added.",
"Specifies a path which will be used by the FIND_XXX() commands. It "
@@ -709,7 +753,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"adds /bin to each of the directories in the path, FIND_LIBRARY() "
"appends /lib to each of the directories, and FIND_PATH() and "
"FIND_FILE() append /include . By default this contains the standard "
- "directories for the current system. It is NOT intended "
+ "directories for the current system and the CMAKE_INSTALL_PREFIX. "
+ "It is NOT intended "
"to be modified by the project, use CMAKE_PREFIX_PATH for this. See also "
"CMAKE_SYSTEM_INCLUDE_PATH, CMAKE_SYSTEM_LIBRARY_PATH, "
"CMAKE_SYSTEM_PROGRAM_PATH, and CMAKE_SYSTEM_IGNORE_PATH.", false,
@@ -724,9 +769,9 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"directories contain incompatible but possibly linkable libraries. For "
"example, on cross-compiled cluster environments, this allows a user to "
"ignore directories containing libraries meant for the front-end "
- "machine that modules like FindX11 (and others) would normally search. "
+ "machine that modules like FindX11 (and others) would normally search. "
"By default this contains a list of directories containing incompatible "
- "binaries for the host system. "
+ "binaries for the host system. "
"See also CMAKE_SYSTEM_PREFIX_PATH, CMAKE_SYSTEM_LIBRARY_PATH, "
"CMAKE_SYSTEM_INCLUDE_PATH, and CMAKE_SYSTEM_PROGRAM_PATH.", false,
"Variables That Change Behavior");
@@ -740,11 +785,11 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"directories contain incompatible but possibly linkable libraries. For "
"example, on cross-compiled cluster environments, this allows a user to "
"ignore directories containing libraries meant for the front-end "
- "machine that modules like FindX11 (and others) would normally search. "
- "By default this is empty; it is intended to be set by the project. "
+ "machine that modules like FindX11 (and others) would normally search. "
+ "By default this is empty; it is intended to be set by the project. "
"Note that CMAKE_IGNORE_PATH takes a list of directory names, NOT a "
"list of prefixes. If you want to ignore paths under prefixes (bin, "
- "include, lib, etc.), you'll need to specify them explicitly. "
+ "include, lib, etc.), you'll need to specify them explicitly. "
"See also CMAKE_PREFIX_PATH, CMAKE_LIBRARY_PATH, CMAKE_INCLUDE_PATH, "
"CMAKE_PROGRAM_PATH.", false,
"Variables That Change Behavior");
@@ -791,8 +836,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"although that package is installed.\n"
"This switch should be used during the initial CMake run. Otherwise if "
"the package has already been found in a previous CMake run, the "
- "variables which have been stored in the cache will still be there. "
- "In the case it is recommended to remove the cache variables for "
+ "variables which have been stored in the cache will still be there. "
+ "In that case it is recommended to remove the cache variables for "
"this package from the cache using the cache editor or cmake -U", false,
"Variables That Change Behavior");
@@ -878,7 +923,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_COLOR_MAKEFILE", cmProperty::VARIABLE,
"Enables color output when using the Makefile generator.",
- "When enabled, the generated Makefiles will produce colored output. "
+ "When enabled, the generated Makefiles will produce colored output. "
"Default is ON.",false,
"Variables That Change Behavior");
@@ -888,7 +933,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
" an ABSOLUTE DESTINATION path.",
"This variable is defined by CMake-generated cmake_install.cmake "
"scripts."
- " It can be used (read-only) by program or script that source those"
+ " It can be used (read-only) by programs or scripts that source those"
" install scripts. This is used by some CPack generators (e.g. RPM).",
false,
"Variables That Change Behavior");
@@ -898,7 +943,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Ask cmake_install.cmake script to warn each time a file with "
"absolute INSTALL DESTINATION is encountered.",
"This variable is used by CMake-generated cmake_install.cmake"
- " scripts. If ones set this variable to ON while running the"
+ " scripts. If one sets this variable to ON while running the"
" script, it may get warning messages from the script.", false,
"Variables That Change Behavior");
@@ -909,7 +954,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"The fatal error is emitted before the installation of "
"the offending file takes place."
" This variable is used by CMake-generated cmake_install.cmake"
- " scripts. If ones set this variable to ON while running the"
+ " scripts. If one sets this variable to ON while running the"
" script, it may get fatal error messages from the script.",false,
"Variables That Change Behavior");
@@ -918,9 +963,10 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Enables tracing output for target properties.",
"This variable can be populated with a list of properties to generate "
"debug output for when evaluating target properties. Currently it can "
- "only be used when evaluating the INCLUDE_DIRECTORIES target property. "
- "In that case, it outputs a backtrace for each include directory in "
- "the build. Default is unset.",false,"Variables That Change Behavior");
+ "only be used when evaluating the INCLUDE_DIRECTORIES, "
+ "COMPILE_DEFINITIONS and COMPILE_OPTIONS target properties. "
+ "In that case, it outputs a backtrace for each entry in the target "
+ "property. Default is unset.", false, "Variables That Change Behavior");
// Variables defined by CMake that describe the system
@@ -929,7 +975,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Name of system cmake is compiling for.",
"This variable is the composite of CMAKE_SYSTEM_NAME "
"and CMAKE_SYSTEM_VERSION, like this "
- "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_VERSION}. "
+ "${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_VERSION}. "
"If CMAKE_SYSTEM_VERSION is not set, then "
"CMAKE_SYSTEM is the same as CMAKE_SYSTEM_NAME.",false,
"Variables That Describe the System");
@@ -940,7 +986,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"which CMake is targeting. On systems that "
"have the uname command, this variable is set "
"to the output of uname -s. Linux, Windows, "
- " and Darwin for Mac OSX are the values found "
+ " and Darwin for Mac OS X are the values found "
" on the big three operating systems." ,false,
"Variables That Describe the System");
cm->DefineProperty
@@ -999,20 +1045,22 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("APPLE", cmProperty::VARIABLE,
- "True if running on Mac OSX.",
- "Set to true on Mac OSX.",false,
+ "True if running on Mac OS X.",
+ "Set to true on Mac OS X."
+ ,false,
"Variables That Describe the System");
cm->DefineProperty
("BORLAND", cmProperty::VARIABLE,
- "True if the borland compiler is being used.",
+ "True if the Borland compiler is being used.",
"This is set to true if the Borland compiler is being used.",false,
"Variables That Describe the System");
cm->DefineProperty
("CYGWIN", cmProperty::VARIABLE,
- "True for cygwin.",
- "Set to true when using CYGWIN.",false,
+ "True for Cygwin.",
+ "Set to true when using Cygwin."
+ ,false,
"Variables That Describe the System");
cm->DefineProperty
@@ -1111,8 +1159,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_HOST_APPLE", cmProperty::VARIABLE,
- "True for Apple OSXoperating systems.",
- "Set to true when the host system is Apple OSX.",
+ "True for Apple OS X operating systems.",
+ "Set to true when the host system is Apple OS X.",
false,
"Variables That Describe the System");
@@ -1126,7 +1174,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_HOST_WIN32", cmProperty::VARIABLE,
"True on windows systems, including win64.",
- "Set to true when the host system is Windows and on cygwin.",false,
+ "Set to true when the host system is Windows and on Cygwin."
+ ,false,
"Variables That Describe the System");
cm->DefineProperty
@@ -1147,6 +1196,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"The value must be an integer no less than 128.",false,
"Variables That Describe the System");
+ cm->DefineProperty
+ ("ENV", cmProperty::VARIABLE,
+ "Access environment variables.",
+ "Use the syntax $ENV{VAR} to read environment variable VAR. "
+ "See also the set() command to set ENV{VAR}."
+ ,false,
+ "Variables That Describe the System");
+
// Variables that affect the building of object files and
// targets.
//
@@ -1180,7 +1237,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_INSTALL_RPATH", cmProperty::VARIABLE,
"The rpath to use for installed targets.",
"A semicolon-separated list specifying the rpath "
- "to use in installed targets (for platforms that support it). "
+ "to use in installed targets (for platforms that support it). "
"This is used to initialize the target property "
"INSTALL_RPATH for all targets.",
false,
@@ -1191,7 +1248,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Add paths to linker search and installed rpath.",
"CMAKE_INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to true "
"will append directories in the linker search path and outside the "
- "project to the INSTALL_RPATH. "
+ "project to the INSTALL_RPATH. "
"This is used to initialize the target property "
"INSTALL_RPATH_USE_LINK_PATH for all targets.",
false,
@@ -1199,7 +1256,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_INSTALL_NAME_DIR", cmProperty::VARIABLE,
- "Mac OSX directory name for installed targets.",
+ "Mac OS X directory name for installed targets.",
"CMAKE_INSTALL_NAME_DIR is used to initialize the "
"INSTALL_NAME_DIR property on all targets. See that target "
"property for more information.",
@@ -1210,7 +1267,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_Fortran_FORMAT", cmProperty::VARIABLE,
"Set to FIXED or FREE to indicate the Fortran source layout.",
"This variable is used to initialize the Fortran_FORMAT "
- "property on all the targets. "
+ "property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1219,7 +1276,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_Fortran_MODULE_DIRECTORY", cmProperty::VARIABLE,
"Fortran module output directory.",
"This variable is used to initialize the "
- "Fortran_MODULE_DIRECTORY property on all the targets. "
+ "Fortran_MODULE_DIRECTORY property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1228,7 +1285,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_LIBRARY_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
"Where to put all the LIBRARY targets when built.",
"This variable is used to initialize the "
- "LIBRARY_OUTPUT_DIRECTORY property on all the targets. "
+ "LIBRARY_OUTPUT_DIRECTORY property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1237,7 +1294,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_ARCHIVE_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
"Where to put all the ARCHIVE targets when built.",
"This variable is used to initialize the "
- "ARCHIVE_OUTPUT_DIRECTORY property on all the targets. "
+ "ARCHIVE_OUTPUT_DIRECTORY property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1246,16 +1303,16 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_RUNTIME_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
"Where to put all the RUNTIME targets when built.",
"This variable is used to initialize the "
- "RUNTIME_OUTPUT_DIRECTORY property on all the targets. "
+ "RUNTIME_OUTPUT_DIRECTORY property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
cm->DefineProperty
("CMAKE_PDB_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
- "Where to put all the MS debug symbol files.",
+ "Where to put all the MS debug symbol files from linker.",
"This variable is used to initialize the "
- "PDB_OUTPUT_DIRECTORY property on all the targets. "
+ "PDB_OUTPUT_DIRECTORY property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1273,7 +1330,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_AUTOMOC", cmProperty::VARIABLE,
"Whether to handle moc automatically for Qt targets.",
"This variable is used to initialize the "
- "AUTOMOC property on all the targets. "
+ "AUTOMOC property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1282,7 +1339,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_AUTOMOC_MOC_OPTIONS", cmProperty::VARIABLE,
"Additional options for moc when using automoc (see CMAKE_AUTOMOC).",
"This variable is used to initialize the "
- "AUTOMOC_MOC_OPTIONS property on all the targets. "
+ "AUTOMOC_MOC_OPTIONS property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1359,45 +1416,91 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_EXE_LINKER_FLAGS", cmProperty::VARIABLE,
- "Linker flags used to create executables.",
- "Flags used by the linker when creating an executable.",false,
+ "Linker flags to be used to create executables.",
+ "These flags will be used by the linker when creating an executable."
+ ,false,
"Variables that Control the Build");
cm->DefineProperty
- ("CMAKE_EXE_LINKER_FLAGS_[CMAKE_BUILD_TYPE]", cmProperty::VARIABLE,
- "Flag used when linking an executable.",
+ ("CMAKE_EXE_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
+ "Flags to be used when linking an executable.",
"Same as CMAKE_C_FLAGS_* but used by the linker "
"when creating executables.",false,
"Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_MODULE_LINKER_FLAGS", cmProperty::VARIABLE,
+ "Linker flags to be used to create modules.",
+ "These flags will be used by the linker when creating a module."
+ ,false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_MODULE_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
+ "Flags to be used when linking a module.",
+ "Same as CMAKE_C_FLAGS_* but used by the linker "
+ "when creating modules.",false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_SHARED_LINKER_FLAGS", cmProperty::VARIABLE,
+ "Linker flags to be used to create shared libraries.",
+ "These flags will be used by the linker when creating a shared library."
+ ,false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_SHARED_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
+ "Flags to be used when linking a shared library.",
+ "Same as CMAKE_C_FLAGS_* but used by the linker "
+ "when creating shared libraries.",false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_STATIC_LINKER_FLAGS", cmProperty::VARIABLE,
+ "Linker flags to be used to create static libraries.",
+ "These flags will be used by the linker when creating a static library."
+ ,false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
+ ("CMAKE_STATIC_LINKER_FLAGS_<CONFIG>", cmProperty::VARIABLE,
+ "Flags to be used when linking a static library.",
+ "Same as CMAKE_C_FLAGS_* but used by the linker "
+ "when creating static libraries.",false,
+ "Variables that Control the Build");
+
cm->DefineProperty
("CMAKE_LIBRARY_PATH_FLAG", cmProperty::VARIABLE,
- "The flag used to add a library search path to a compiler.",
- "The flag used to specify a library directory to the compiler. "
+ "The flag to be used to add a library search path to a compiler.",
+ "The flag will be used to specify a library directory to the compiler. "
"On most compilers this is \"-L\".",false,
"Variables that Control the Build");
cm->DefineProperty
("CMAKE_LINK_DEF_FILE_FLAG ", cmProperty::VARIABLE,
- "Linker flag used to specify a .def file for dll creation.",
- "The flag used to add a .def file when creating "
- "a dll on Windows, this is only defined on Windows.",false,
+ "Linker flag to be used to specify a .def file for dll creation.",
+ "The flag will be used to add a .def file when creating "
+ "a dll on Windows; this is only defined on Windows."
+ ,false,
"Variables that Control the Build");
cm->DefineProperty
("CMAKE_LINK_LIBRARY_FLAG", cmProperty::VARIABLE,
- "Flag used to link a library into an executable.",
- "The flag used to specify a library to link to an executable. "
+ "Flag to be used to link a library into an executable.",
+ "The flag will be used to specify a library to link to an executable. "
"On most compilers this is \"-l\".",false,
"Variables that Control the Build");
cm->DefineProperty
("CMAKE_LINK_LIBRARY_FILE_FLAG", cmProperty::VARIABLE,
- "Flag used to link a library specified by a path to its file.",
- "The flag used before a library file path is given to the linker. "
+ "Flag to be used to link a library specified by a path to its file.",
+ "The flag will be used before a library file path is given to the "
+ "linker. "
"This is needed only on very few platforms.", false,
"Variables that Control the Build");
cm->DefineProperty
("CMAKE_USE_RELATIVE_PATHS", cmProperty::VARIABLE,
"Use relative paths (May not work!).",
- "If this is set to TRUE, then the CMake will use "
- "relative paths between the source and binary tree. "
+ "If this is set to TRUE, then CMake will use "
+ "relative paths between the source and binary tree. "
"This option does not work for more complicated "
"projects, and relative paths are used when possible. "
"In general, it is not possible to move CMake generated"
@@ -1431,7 +1534,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_LINK_INTERFACE_LIBRARIES", cmProperty::VARIABLE,
"Default value for LINK_INTERFACE_LIBRARIES of targets.",
"This variable is used to initialize the "
- "LINK_INTERFACE_LIBRARIES property on all the targets. "
+ "LINK_INTERFACE_LIBRARIES property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1439,7 +1542,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_WIN32_EXECUTABLE", cmProperty::VARIABLE,
"Default value for WIN32_EXECUTABLE of targets.",
"This variable is used to initialize the "
- "WIN32_EXECUTABLE property on all the targets. "
+ "WIN32_EXECUTABLE property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1447,7 +1550,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_MACOSX_BUNDLE", cmProperty::VARIABLE,
"Default value for MACOSX_BUNDLE of targets.",
"This variable is used to initialize the "
- "MACOSX_BUNDLE property on all the targets. "
+ "MACOSX_BUNDLE property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1455,7 +1558,23 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_POSITION_INDEPENDENT_CODE", cmProperty::VARIABLE,
"Default value for POSITION_INDEPENDENT_CODE of targets.",
"This variable is used to initialize the "
- "POSITION_INDEPENDENT_CODE property on all the targets. "
+ "POSITION_INDEPENDENT_CODE property on all the targets. "
+ "See that target property for additional information.",
+ false,
+ "Variables that Control the Build");
+ cm->DefineProperty
+ ("CMAKE_<LANG>_VISIBILITY_PRESET", cmProperty::VARIABLE,
+ "Default value for <LANG>_VISIBILITY_PRESET of targets.",
+ "This variable is used to initialize the "
+ "<LANG>_VISIBILITY_PRESET property on all the targets. "
+ "See that target property for additional information.",
+ false,
+ "Variables that Control the Build");
+ cm->DefineProperty
+ ("CMAKE_VISIBILITY_INLINES_HIDDEN", cmProperty::VARIABLE,
+ "Default value for VISIBILITY_INLINES_HIDDEN of targets.",
+ "This variable is used to initialize the "
+ "VISIBILITY_INLINES_HIDDEN property on all the targets. "
"See that target property for additional information.",
false,
"Variables that Control the Build");
@@ -1476,7 +1595,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_<LANG>_COMPILER", cmProperty::VARIABLE,
"The full path to the compiler for LANG.",
- "This is the command that will be used as the <LANG> compiler. "
+ "This is the command that will be used as the <LANG> compiler. "
"Once set, you can not change this variable.",false,
"Variables for Languages");
@@ -1552,7 +1671,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_COMPILER_IS_GNU<LANG>", cmProperty::VARIABLE,
"True if the compiler is GNU.",
"If the selected <LANG> compiler is the GNU "
- "compiler then this is TRUE, if not it is FALSE. "
+ "compiler then this is TRUE, if not it is FALSE. "
"Unlike the other per-language variables, this uses the GNU syntax for "
"identifying languages instead of the CMake syntax. Recognized values of "
"the <LANG> suffix are:\n"
@@ -1563,6 +1682,12 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Variables for Languages");
cm->DefineProperty
+ ("CMAKE_<LANG>_FLAGS", cmProperty::VARIABLE,
+ "Flags for all build types.",
+ "<LANG> flags used regardless of the value of CMAKE_BUILD_TYPE.",false,
+ "Variables for Languages");
+
+ cm->DefineProperty
("CMAKE_<LANG>_FLAGS_DEBUG", cmProperty::VARIABLE,
"Flags for Debug build type or configuration.",
"<LANG> flags used when CMAKE_BUILD_TYPE is Debug.",false,
@@ -1584,7 +1709,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_<LANG>_FLAGS_RELWITHDEBINFO", cmProperty::VARIABLE,
"Flags for RelWithDebInfo type or configuration.",
- "<LANG> flags used when CMAKE_BUILD_TYPE is RelWithDebInfo. "
+ "<LANG> flags used when CMAKE_BUILD_TYPE is RelWithDebInfo. "
"Short for Release With Debug Information.",false,
"Variables for Languages");
@@ -1592,7 +1717,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_<LANG>_COMPILE_OBJECT", cmProperty::VARIABLE,
"Rule variable to compile a single object file.",
"This is a rule variable that tells CMake how to "
- "compile a single object file for for the language <LANG>.",false,
+ "compile a single object file for the language <LANG>."
+ ,false,
"Variables for Languages");
cm->DefineProperty
@@ -1647,7 +1773,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_<LANG>_IGNORE_EXTENSIONS", cmProperty::VARIABLE,
"File extensions that should be ignored by the build.",
"This is a list of file extensions that may be "
- "part of a project for a given language but are not compiled. ",false,
+ "part of a project for a given language but are not compiled.",false,
"Variables for Languages");
cm->DefineProperty
@@ -1728,8 +1854,9 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_<LANG>_LINK_EXECUTABLE ", cmProperty::VARIABLE,
- "Rule variable to link and executable.",
- "Rule variable to link and executable for the given language.",false,
+ "Rule variable to link an executable.",
+ "Rule variable to link an executable for the given language."
+ ,false,
"Variables for Languages");
cm->DefineProperty
@@ -1743,7 +1870,9 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
("CMAKE_<LANG>_SOURCE_FILE_EXTENSIONS", cmProperty::VARIABLE,
"Extensions of source files for the given language.",
"This is the list of extensions for a "
- "given languages source files.",false,"Variables for Languages");
+ "given language's source files."
+ ,false,
+ "Variables for Languages");
cm->DefineProperty(
"CMAKE_<LANG>_COMPILER_LOADED", cmProperty::VARIABLE,
@@ -1799,8 +1928,6 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cmProperty::VARIABLE,0,0);
cm->DefineProperty("CMAKE_<LANG>_CREATE_PREPROCESSED_SOURCE",
cmProperty::VARIABLE,0,0);
- cm->DefineProperty("CMAKE_<LANG>_FLAGS",
- cmProperty::VARIABLE,0,0);
cm->DefineProperty("CMAKE_<LANG>_FLAGS_DEBUG_INIT",
cmProperty::VARIABLE,0,0);
cm->DefineProperty("CMAKE_<LANG>_FLAGS_INIT",
diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx
index debde3be9..4edacbb1a 100644
--- a/Source/cmDocumentation.cxx
+++ b/Source/cmDocumentation.cxx
@@ -53,7 +53,7 @@ static const char *cmModulesDocumentationDescription[][3] =
"This is the documentation for the modules and scripts coming with CMake. "
"Using these modules you can check the computer system for "
"installed software packages, features of the compiler and the "
- "existance of headers to name just a few.", 0},
+ "existence of headers to name just a few.", 0},
{0,0,0}
};
@@ -67,7 +67,7 @@ static const char *cmCustomModulesDocumentationDescription[][3] =
"This is the documentation for additional modules and scripts for CMake. "
"Using these modules you can check the computer system for "
"installed software packages, features of the compiler and the "
- "existance of headers to name just a few.", 0},
+ "existence of headers to name just a few.", 0},
{0,0,0}
};
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index 1158fc0c0..30de9a8a6 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -19,7 +19,12 @@
#include <cmsys/CPU.h>
// Include the ELF format information system header.
-#include <elf.h>
+#if defined(__OpenBSD__)
+# include <stdint.h>
+# include <elf_abi.h>
+#else
+# include <elf.h>
+#endif
#if defined(__sun)
# include <sys/link.h> // For dynamic section information
#endif
diff --git a/Source/cmEnableLanguageCommand.h b/Source/cmEnableLanguageCommand.h
index ee963f920..747448b3e 100644
--- a/Source/cmEnableLanguageCommand.h
+++ b/Source/cmEnableLanguageCommand.h
@@ -59,18 +59,21 @@ public:
virtual const char* GetFullDocumentation() const
{
return
- " enable_language(languageName [OPTIONAL] )\n"
+ " enable_language(<lang> [OPTIONAL] )\n"
"This command enables support for the named language in CMake. "
"This is the same as the project command but does not create "
"any of the extra variables that are created by the project command. "
"Example languages are CXX, C, Fortran. "
- "If OPTIONAL is used, use the CMAKE_<languageName>_COMPILER_WORKS "
- "variable to check whether the language has been enabled successfully."
"\n"
- "This command must be called on file scope (not inside a function) and "
- "the language enabled can only be used in the calling project or its "
- "subdirectories added by add_subdirectory(). Also note that at present, "
- "the OPTIONAL argument does not work.";
+ "This command must be called in file scope, not in a function call. "
+ "Furthermore, it must be called in the highest directory common to "
+ "all targets using the named language directly for compiling sources "
+ "or indirectly through link dependencies. "
+ "It is simplest to enable all needed languages in the top-level "
+ "directory of a project."
+ "\n"
+ "The OPTIONAL keyword is a placeholder for future implementation "
+ "and does not currently work.";
}
cmTypeMacro(cmEnableLanguageCommand, cmCommand);
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 7147f86be..cdc3316c4 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -30,7 +30,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
tei = this->Exports->begin();
tei != this->Exports->end(); ++tei)
{
- expectedTargets += sep + this->Namespace + (*tei)->GetName();
+ expectedTargets += sep + this->Namespace + (*tei)->GetExportName();
sep = " ";
cmTarget* te = *tei;
if(this->ExportedTargets.insert(te).second)
@@ -72,8 +72,20 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS", te,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties);
+ const bool newCMP0022Behavior =
+ te->GetPolicyStatusCMP0022() != cmPolicies::WARN
+ && te->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+ if (newCMP0022Behavior)
+ {
+ this->PopulateInterfaceLinkLibrariesProperty(te,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ }
this->PopulateCompatibleInterfaceProperties(te, properties);
this->GenerateInterfaceProperties(te, os, properties);
@@ -143,7 +155,7 @@ cmExportBuildFileGenerator
std::string prop = "IMPORTED_LOCATION";
prop += suffix;
std::string value;
- if(target->IsFrameworkOnApple() || target->IsAppBundleOnApple())
+ if(target->IsAppBundleOnApple())
{
value = target->GetFullPath(config, false);
}
@@ -189,7 +201,7 @@ cmExportBuildFileGenerator::HandleMissingTarget(
// Assume the target will be exported by another command.
// Append it with the export namespace.
link_libs += this->Namespace;
- link_libs += dependee->GetName();
+ link_libs += dependee->GetExportName();
}
//----------------------------------------------------------------------------
@@ -211,3 +223,19 @@ cmExportBuildFileGenerator
<< "consider using the APPEND option with multiple separate calls.";
this->ExportCommand->ErrorMessage = e.str();
}
+
+std::string
+cmExportBuildFileGenerator::InstallNameDir(cmTarget* target,
+ const std::string& config)
+{
+ std::string install_name_dir;
+
+ cmMakefile* mf = target->GetMakefile();
+ if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
+ {
+ install_name_dir =
+ target->GetInstallNameDirForBuildTree(config.c_str());
+ }
+
+ return install_name_dir;
+}
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 5e1be1648..3ffdf8b13 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -61,6 +61,8 @@ protected:
cmTarget* target,
ImportPropertyMap& properties);
+ std::string InstallNameDir(cmTarget* target, const std::string& config);
+
std::vector<cmTarget*> const* Exports;
cmExportCommand* ExportCommand;
};
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 1cc17545a..f059ceba6 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -30,6 +30,7 @@ cmExportCommand::cmExportCommand()
,Append(&Helper, "APPEND", &ArgumentGroup)
,Namespace(&Helper, "NAMESPACE", &ArgumentGroup)
,Filename(&Helper, "FILE", &ArgumentGroup)
+,ExportOld(&Helper, "EXPORT_LINK_INTERFACE_LIBRARIES", &ArgumentGroup)
{
// at first TARGETS
this->Targets.Follows(0);
@@ -113,6 +114,15 @@ bool cmExportCommand
currentTarget != this->Targets.GetVector().end();
++currentTarget)
{
+ if (this->Makefile->IsAlias(currentTarget->c_str()))
+ {
+ cmOStringStream e;
+ e << "given ALIAS target \"" << *currentTarget
+ << "\" which may not be exported.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
if(cmTarget* target =
this->Makefile->GetLocalGenerator()->
GetGlobalGenerator()->FindTarget(0, currentTarget->c_str()))
@@ -158,6 +168,7 @@ bool cmExportCommand
ebfg.SetAppendMode(this->Append.IsEnabled());
ebfg.SetExports(&targets);
ebfg.SetCommand(this);
+ ebfg.SetExportOld(this->ExportOld.IsEnabled());
// Compute the set of configurations exported.
std::vector<std::string> configurationTypes;
@@ -210,7 +221,7 @@ bool cmExportCommand::HandlePackage(std::vector<std::string> const& args)
else
{
cmOStringStream e;
- e << "PACKAGE given unknown argumsnt: " << args[i];
+ e << "PACKAGE given unknown argument: " << args[i];
this->SetError(e.str().c_str());
return false;
}
diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h
index ae67b4762..87c345284 100644
--- a/Source/cmExportCommand.h
+++ b/Source/cmExportCommand.h
@@ -63,7 +63,7 @@ public:
{
return
" export(TARGETS [target1 [target2 [...]]] [NAMESPACE <namespace>]\n"
- " [APPEND] FILE <filename>)\n"
+ " [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES])\n"
"Create a file <filename> that may be included by outside projects to "
"import targets from the current project's build tree. "
"This is useful during cross-compiling to build utility executables "
@@ -73,6 +73,10 @@ public:
"prepended to all target names written to the file. "
"If the APPEND option is given the generated code will be appended "
"to the file instead of overwriting it. "
+ "The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if present, causes the "
+ "contents of the properties matching "
+ "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? to be exported, when "
+ "policy CMP0022 is NEW. "
"If a library target is included in the export but "
"a target to which it links is not included the behavior is "
"unspecified."
@@ -104,6 +108,7 @@ private:
cmCAEnabler Append;
cmCAString Namespace;
cmCAString Filename;
+ cmCAEnabler ExportOld;
friend class cmExportBuildFileGenerator;
std::string ErrorMessage;
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 27ec56beb..14be5cd47 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -30,6 +30,7 @@
cmExportFileGenerator::cmExportFileGenerator()
{
this->AppendMode = false;
+ this->ExportOld = false;
}
//----------------------------------------------------------------------------
@@ -168,6 +169,43 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
}
}
+void cmExportFileGenerator::GenerateRequiredCMakeVersion(std::ostream& os,
+ const char *versionString)
+{
+ os << "if(CMAKE_VERSION VERSION_LESS " << versionString << ")\n"
+ " message(FATAL_ERROR \"This file relies on consumers using "
+ "CMake " << versionString << " or greater.\")\n"
+ "endif()\n\n";
+}
+
+//----------------------------------------------------------------------------
+bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
+ cmTarget *target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap &properties,
+ std::vector<std::string> &missingTargets)
+{
+ if(!target->IsLinkable())
+ {
+ return false;
+ }
+ const char *input = target->GetProperty("INTERFACE_LINK_LIBRARIES");
+ if (input)
+ {
+ std::string prepro = cmGeneratorExpression::Preprocess(input,
+ preprocessRule);
+ if (!prepro.empty())
+ {
+ this->ResolveTargetsInGeneratorExpressions(prepro, target,
+ missingTargets,
+ ReplaceFreeTargets);
+ properties["INTERFACE_LINK_LIBRARIES"] = prepro;
+ return true;
+ }
+ }
+ return false;
+}
+
//----------------------------------------------------------------------------
static bool isSubDirectory(const char* a, const char* b)
{
@@ -243,28 +281,55 @@ static bool checkInterfaceDirs(const std::string &prepro,
//----------------------------------------------------------------------------
void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
- cmTarget *target,
+ cmTargetExport *tei,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap &properties,
std::vector<std::string> &missingTargets)
{
+ cmTarget *target = tei->Target;
assert(preprocessRule == cmGeneratorExpression::InstallInterface);
const char *propName = "INTERFACE_INCLUDE_DIRECTORIES";
const char *input = target->GetProperty(propName);
- if (!input)
+
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ std::string dirs = tei->InterfaceIncludeDirectories;
+ this->ReplaceInstallPrefix(dirs);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(dirs);
+ std::string exportDirs = cge->Evaluate(target->GetMakefile(), 0,
+ false, target);
+
+ if (cge->GetHadContextSensitiveCondition())
{
+ cmMakefile* mf = target->GetMakefile();
+ cmOStringStream e;
+ e << "Target \"" << target->GetName() << "\" is installed with "
+ "INCLUDES DESTINATION set to a context sensitive path. Paths which "
+ "depend on the configuration, policy values or the link interface are "
+ "not supported. Consider using target_include_directories instead.";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
- if (!*input)
+
+ if (!input && exportDirs.empty())
+ {
+ return;
+ }
+ if ((input && !*input) && exportDirs.empty())
{
// Set to empty
properties[propName] = "";
return;
}
- std::string prepro = cmGeneratorExpression::Preprocess(input,
- preprocessRule);
+ std::string includes = (input?input:"");
+ const char* sep = input ? ";" : "";
+ includes += sep + exportDirs;
+ std::string prepro = cmGeneratorExpression::Preprocess(includes,
+ preprocessRule,
+ true);
if (!prepro.empty())
{
this->ResolveTargetsInGeneratorExpressions(prepro, target,
@@ -315,6 +380,16 @@ void getCompatibleInterfaceProperties(cmTarget *target,
{
cmComputeLinkInformation *info = target->GetLinkInformation(config);
+ if (!info)
+ {
+ cmMakefile* mf = target->GetMakefile();
+ cmOStringStream e;
+ e << "Exporting the target \"" << target->GetName() << "\" is not "
+ "allowed since its linker language cannot be determined";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ }
+
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
for(cmComputeLinkInformation::ItemVector::const_iterator li =
@@ -376,7 +451,7 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
if (!properties.empty())
{
std::string targetName = this->Namespace;
- targetName += target->GetName();
+ targetName += target->GetExportName();
os << "set_target_properties(" << targetName << " PROPERTIES\n";
for(ImportPropertyMap::const_iterator pi = properties.begin();
pi != properties.end(); ++pi)
@@ -407,7 +482,7 @@ cmExportFileGenerator::AddTargetNamespace(std::string &input,
}
if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
{
- input = this->Namespace + input;
+ input = this->Namespace + tgt->GetExportName();
}
else
{
@@ -560,6 +635,7 @@ cmExportFileGenerator
if (iface->ImplementationIsInterface)
{
+ // Policy CMP0022 must not be NEW.
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LIBRARIES",
iface->Libraries, properties, missingTargets);
@@ -583,6 +659,22 @@ cmExportFileGenerator
return;
}
+ const bool newCMP0022Behavior =
+ target->GetPolicyStatusCMP0022() != cmPolicies::WARN
+ && target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+
+ if(newCMP0022Behavior && !this->ExportOld)
+ {
+ cmMakefile *mf = target->GetMakefile();
+ cmOStringStream e;
+ e << "Target \"" << target->GetName() << "\" has policy CMP0022 enabled, "
+ "but also has old-style LINK_INTERFACE_LIBRARIES properties "
+ "populated, but it was exported without the "
+ "EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties";
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ }
+
if (!*propContent)
{
properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = "";
@@ -624,8 +716,12 @@ cmExportFileGenerator
std::string value;
if(target->HasSOName(config))
{
+ if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
+ {
+ value = this->InstallNameDir(target, config);
+ }
prop = "IMPORTED_SONAME";
- value = target->GetSOName(config);
+ value += target->GetSOName(config);
}
else
{
@@ -738,7 +834,9 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os,
const std::string &expectedTargets)
{
- os << "set(_targetsDefined)\n"
+ os << "# Protect against multiple inclusion, which would fail when already "
+ "imported targets are added once more.\n"
+ "set(_targetsDefined)\n"
"set(_targetsNotDefined)\n"
"set(_expectedTargets)\n"
"foreach(_expectedTarget " << expectedTargets << ")\n"
@@ -772,7 +870,8 @@ cmExportFileGenerator
{
// Construct the imported target name.
std::string targetName = this->Namespace;
- targetName += target->GetName();
+
+ targetName += target->GetExportName();
// Create the imported target.
os << "# Create imported target " << targetName << "\n";
@@ -835,7 +934,8 @@ cmExportFileGenerator
{
// Construct the imported target name.
std::string targetName = this->Namespace;
- targetName += target->GetName();
+
+ targetName += target->GetExportName();
// Set the import properties.
os << "# Import target \"" << targetName << "\" for configuration \""
@@ -954,7 +1054,7 @@ cmExportFileGenerator
{
// Construct the imported target name.
std::string targetName = this->Namespace;
- targetName += target->GetName();
+ targetName += target->GetExportName();
os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n"
"list(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " ";
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 9f958a234..9628b9681 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -15,6 +15,8 @@
#include "cmCommand.h"
#include "cmGeneratorExpression.h"
+class cmTargetExport;
+
/** \class cmExportFileGenerator
* \brief Generate a file exporting targets from a build or install tree.
*
@@ -35,6 +37,8 @@ public:
/** Set the namespace in which to place exported target names. */
void SetNamespace(const char* ns) { this->Namespace = ns; }
+ void SetExportOld(bool exportOld) { this->ExportOld = exportOld; }
+
/** Add a configuration to be exported. */
void AddConfiguration(const char* config);
@@ -101,6 +105,10 @@ protected:
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap &properties,
std::vector<std::string> &missingTargets);
+ bool PopulateInterfaceLinkLibrariesProperty(cmTarget *target,
+ cmGeneratorExpression::PreprocessContext,
+ ImportPropertyMap &properties,
+ std::vector<std::string> &missingTargets);
void PopulateInterfaceProperty(const char *propName, cmTarget *target,
ImportPropertyMap &properties);
void PopulateCompatibleInterfaceProperties(cmTarget *target,
@@ -108,7 +116,7 @@ protected:
void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
const ImportPropertyMap &properties);
void PopulateIncludeDirectoriesInterface(
- cmTarget *target,
+ cmTargetExport *target,
cmGeneratorExpression::PreprocessContext preprocessRule,
ImportPropertyMap &properties,
std::vector<std::string> &missingTargets);
@@ -128,9 +136,14 @@ protected:
std::vector<std::string> &missingTargets,
FreeTargetsReplace replace = NoReplaceFreeTargets);
+ void GenerateRequiredCMakeVersion(std::ostream& os,
+ const char *versionString);
+
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
+ bool ExportOld;
+
// The set of configurations to export.
std::vector<std::string> Configurations;
@@ -159,6 +172,9 @@ private:
std::vector<std::string> &missingTargets);
virtual void ReplaceInstallPrefix(std::string &input);
+
+ virtual std::string InstallNameDir(cmTarget* target,
+ const std::string& config) = 0;
};
#endif
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index ad12b5a13..c8b4a7985 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -39,7 +39,7 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
//----------------------------------------------------------------------------
bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{
- std::vector<cmTarget*> allTargets;
+ std::vector<cmTargetExport*> allTargets;
{
std::string expectedTargets;
std::string sep;
@@ -47,12 +47,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
{
- expectedTargets += sep + this->Namespace + (*tei)->Target->GetName();
+ expectedTargets += sep + this->Namespace + (*tei)->Target->GetExportName();
sep = " ";
- cmTargetExport const* te = *tei;
+ cmTargetExport * te = *tei;
if(this->ExportedTargets.insert(te->Target).second)
{
- allTargets.push_back(te->Target);
+ allTargets.push_back(te);
}
else
{
@@ -113,23 +113,46 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
std::vector<std::string> missingTargets;
+ bool require2_8_12 = false;
// Create all the imported targets.
- for(std::vector<cmTarget*>::const_iterator
+ for(std::vector<cmTargetExport*>::const_iterator
tei = allTargets.begin();
tei != allTargets.end(); ++tei)
{
- cmTarget* te = *tei;
+ cmTarget* te = (*tei)->Target;
this->GenerateImportTargetCode(os, te);
ImportPropertyMap properties;
- this->PopulateIncludeDirectoriesInterface(te,
+ this->PopulateIncludeDirectoriesInterface(*tei,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES",
+ te,
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS",
te,
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_OPTIONS",
+ te,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets);
+
+ const bool newCMP0022Behavior =
+ te->GetPolicyStatusCMP0022() != cmPolicies::WARN
+ && te->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+ if (newCMP0022Behavior)
+ {
+ if (this->PopulateInterfaceLinkLibrariesProperty(te,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets)
+ && !this->ExportOld)
+ {
+ require2_8_12 = true;
+ }
+ }
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties);
this->PopulateCompatibleInterfaceProperties(te, properties);
@@ -137,6 +160,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->GenerateInterfaceProperties(te, os, properties);
}
+ if (require2_8_12)
+ {
+ this->GenerateRequiredCMakeVersion(os, "2.8.12");
+ }
// Now load per-configuration properties for them.
os << "# Load information for each installed configuration.\n"
@@ -351,27 +378,7 @@ cmExportInstallFileGenerator
prop += suffix;
// Append the installed file name.
- if(target->IsFrameworkOnApple())
- {
- value += itgen->GetInstallFilename(target, config);
- value += ".framework/";
- value += itgen->GetInstallFilename(target, config);
- }
- else if(target->IsCFBundleOnApple())
- {
- const char *ext = target->GetProperty("BUNDLE_EXTENSION");
- if (!ext)
- {
- ext = "bundle";
- }
-
- value += itgen->GetInstallFilename(target, config);
- value += ".";
- value += ext;
- value += "/";
- value += itgen->GetInstallFilename(target, config);
- }
- else if(target->IsAppBundleOnApple())
+ if(target->IsAppBundleOnApple())
{
value += itgen->GetInstallFilename(target, config);
value += ".app/Contents/MacOS/";
@@ -395,13 +402,14 @@ cmExportInstallFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
cmMakefile* mf, cmTarget* depender, cmTarget* dependee)
{
- std::string name = dependee->GetName();
+ const std::string name = dependee->GetName();
std::vector<std::string> namespaces = this->FindNamespaces(mf, name);
int targetOccurrences = (int)namespaces.size();
if (targetOccurrences == 1)
{
std::string missingTarget = namespaces[0];
- missingTarget += name;
+
+ missingTarget += dependee->GetExportName();
link_libs += missingTarget;
missingTargets.push_back(missingTarget);
}
@@ -496,3 +504,19 @@ cmExportInstallFileGenerator
}
cmSystemTools::Error(e.str().c_str());
}
+
+std::string
+cmExportInstallFileGenerator::InstallNameDir(cmTarget* target,
+ const std::string&)
+{
+ std::string install_name_dir;
+
+ cmMakefile* mf = target->GetMakefile();
+ if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
+ {
+ install_name_dir =
+ target->GetInstallNameDirForInstallTree();
+ }
+
+ return install_name_dir;
+}
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 20dd57ad1..7c634a4d8 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -85,6 +85,8 @@ protected:
void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen);
+ std::string InstallNameDir(cmTarget* target, const std::string& config);
+
cmInstallExportGenerator* IEGen;
std::string ImportPrefix;
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index 75f2651ba..819ac371e 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -31,8 +31,10 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
ImportPropertyMap properties;
- this->FindTargets("INTERFACE_INCLUDE_DIRECTORIES", te, emittedDeps);
- this->FindTargets("INTERFACE_COMPILE_DEFINITIONS", te, emittedDeps);
+#define FIND_TARGETS(PROPERTY) \
+ this->FindTargets(#PROPERTY, te, emittedDeps);
+
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(FIND_TARGETS)
this->PopulateProperties(te, properties, emittedDeps);
@@ -91,7 +93,9 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget* target,
{
properties[i->first] = i->second.GetValue();
- if(i->first.find("IMPORTED_LINK_INTERFACE_LIBRARIES") == 0)
+ if(i->first.find("IMPORTED_LINK_INTERFACE_LIBRARIES") == 0
+ || i->first.find("IMPORTED_LINK_DEPENDENT_LIBRARIES") == 0
+ || i->first.find("INTERFACE_LINK_LIBRARIES") == 0)
{
const std::string libs = i->second.GetValue();
@@ -112,3 +116,18 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget* target,
}
}
}
+std::string
+cmExportTryCompileFileGenerator::InstallNameDir(cmTarget* target,
+ const std::string& config)
+{
+ std::string install_name_dir;
+
+ cmMakefile* mf = target->GetMakefile();
+ if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
+ {
+ install_name_dir =
+ target->GetInstallNameDirForBuildTree(config.c_str());
+ }
+
+ return install_name_dir;
+}
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index ed393abf4..91b4a6153 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -43,6 +43,8 @@ protected:
ImportPropertyMap& properties,
std::set<cmTarget*> &emitted);
+ std::string InstallNameDir(cmTarget* target,
+ const std::string& config);
private:
std::string FindTargets(const char *prop, cmTarget *tgt,
std::set<cmTarget*> &emitted);
diff --git a/Source/cmExprLexer.cxx b/Source/cmExprLexer.cxx
index 53dfca7c0..9947c77f1 100644
--- a/Source/cmExprLexer.cxx
+++ b/Source/cmExprLexer.cxx
@@ -693,9 +693,9 @@ extern int cmExpr_yylex (yyscan_t yyscanner);
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
#line 86 "/home/andy/vtk/CMake/Source/cmExprLexer.in.l"
@@ -745,7 +745,7 @@ YY_DECL
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -989,9 +989,9 @@ return 0; /* this should not happen but it silences a warning*/
static int yy_get_next_buffer (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = yyg->yytext_ptr;
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = yyg->yytext_ptr;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1116,15 +1116,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
+ yy_state_type yy_current_state;
+ char *yy_cp;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_current_state = yyg->yy_start;
for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1149,11 +1149,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
{
- register int yy_is_jam;
+ int yy_is_jam;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *yy_cp = yyg->yy_c_buf_p;
+ char *yy_cp = yyg->yy_c_buf_p;
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1867,7 +1867,7 @@ int cmExpr_yylex_destroy (yyscan_t yyscanner)
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
{
- register int i;
+ int i;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
@@ -1877,7 +1877,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
{
- register int n;
+ int n;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
for ( n = 0; s[n]; ++n )
;
diff --git a/Source/cmExprLexer.in.l b/Source/cmExprLexer.in.l
index f344b40ff..febd244fe 100644
--- a/Source/cmExprLexer.in.l
+++ b/Source/cmExprLexer.in.l
@@ -20,6 +20,7 @@ Run flex like this:
Modify cmExprLexer.cxx:
- remove TABs
+ - remove use of the 'register' storage class specifier
- remove "yyscanner" argument from these methods:
yy_fatal_error, cmExpr_yyalloc, cmExpr_yyrealloc, cmExpr_yyfree
- remove all YY_BREAK lines occurring right after return statements
diff --git a/Source/cmExprParser.cxx b/Source/cmExprParser.cxx
index 5c164a081..77880c0a3 100644
--- a/Source/cmExprParser.cxx
+++ b/Source/cmExprParser.cxx
@@ -267,7 +267,7 @@ union yyalloc
# define YYCOPY(To, From, Count) \
do \
{ \
- register YYSIZE_T yyi; \
+ YYSIZE_T yyi; \
for (yyi = 0; yyi < (Count); yyi++) \
(To)[yyi] = (From)[yyi]; \
} \
@@ -696,7 +696,7 @@ yystrlen (yystr)
const char *yystr;
# endif
{
- register const char *yys = yystr;
+ const char *yys = yystr;
while (*yys++ != '\0')
continue;
@@ -721,8 +721,8 @@ yystpcpy (yydest, yysrc)
const char *yysrc;
# endif
{
- register char *yyd = yydest;
- register const char *yys = yysrc;
+ char *yyd = yydest;
+ const char *yys = yysrc;
while ((*yyd++ = *yys++) != '\0')
continue;
@@ -852,8 +852,8 @@ YYSTYPE yylval;
/* Number of syntax errors so far. */
int yynerrs;
- register int yystate;
- register int yyn;
+ int yystate;
+ int yyn;
int yyresult;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
@@ -871,12 +871,12 @@ int yynerrs;
/* The state stack. */
short int yyssa[YYINITDEPTH];
short int *yyss = yyssa;
- register short int *yyssp;
+ short int *yyssp;
/* The semantic value stack. */
YYSTYPE yyvsa[YYINITDEPTH];
YYSTYPE *yyvs = yyvsa;
- register YYSTYPE *yyvsp;
+ YYSTYPE *yyvsp;
diff --git a/Source/cmExprParser.y b/Source/cmExprParser.y
index 317b0ba98..12c2e4806 100644
--- a/Source/cmExprParser.y
+++ b/Source/cmExprParser.y
@@ -20,6 +20,7 @@ Run bison like this:
Modify cmExprParser.cxx:
- remove TABs
+ - remove use of the 'register' storage class specifier
- add __HP_aCC to the #if test for yyerrorlab warning suppression
*/
diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx
index 9c1795ec2..cc35f84cd 100644
--- a/Source/cmExprParserHelper.cxx
+++ b/Source/cmExprParserHelper.cxx
@@ -12,10 +12,10 @@
#include "cmExprParserHelper.h"
#include "cmSystemTools.h"
-#include "cmExprLexer.h"
-
#include "cmMakefile.h"
+#include "cmExprLexer.h"
+
int cmExpr_yyparse( yyscan_t yyscanner );
//
cmExprParserHelper::cmExprParserHelper()
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index f6f4ceff3..dfbb1c0ad 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -621,19 +621,15 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
->GetGeneratorTarget(target);
// the compilerdefines for this target
- std::string cdefs = target->GetCompileDefinitions(buildType);
+ std::vector<std::string> cdefs;
+ target->GetCompileDefinitions(cdefs, buildType);
- if(!cdefs.empty())
+ // Expand the list.
+ for(std::vector<std::string>::const_iterator di = cdefs.begin();
+ di != cdefs.end(); ++di)
{
- // Expand the list.
- std::vector<std::string> defs;
- cmSystemTools::ExpandListArgument(cdefs.c_str(), defs);
- for(std::vector<std::string>::const_iterator di = defs.begin();
- di != defs.end(); ++di)
- {
- cmXMLSafe safedef(di->c_str());
- fout <<" <Add option=\"-D" << safedef.str() << "\" />\n";
- }
+ cmXMLSafe safedef(di->c_str());
+ fout <<" <Add option=\"-D" << safedef.str() << "\" />\n";
}
// the include directories for this target
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 97ab0863c..d80e775bf 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -39,6 +39,7 @@ cmExtraEclipseCDT4Generator
this->SupportsVirtualFolders = true;
this->GenerateLinkedResources = true;
+ this->SupportsGmakeErrorParser = true;
}
//----------------------------------------------------------------------------
@@ -50,7 +51,7 @@ void cmExtraEclipseCDT4Generator
entry.Full =
"Project files for Eclipse will be created in the top directory. "
"In out of source builds, a linked resource to the top level source "
- "directory will be created."
+ "directory will be created. "
"Additionally a hierarchy of makefiles is generated into the "
"build tree. The appropriate make program can build the project through "
"the default make target. A \"make install\" target is also provided.";
@@ -77,6 +78,10 @@ void cmExtraEclipseCDT4Generator::Generate()
{
this->SupportsVirtualFolders = false;
}
+ if (version < 3007) // 3.7 is Indigo
+ {
+ this->SupportsGmakeErrorParser = false;
+ }
}
}
@@ -403,8 +408,17 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile()
{
fout << "org.eclipse.cdt.core.ICCErrorParser;";
}
+
+ if (this->SupportsGmakeErrorParser)
+ {
+ fout << "org.eclipse.cdt.core.GmakeErrorParser;";
+ }
+ else
+ {
+ fout << "org.eclipse.cdt.core.MakeErrorParser;";
+ }
+
fout <<
- "org.eclipse.cdt.core.MakeErrorParser;"
"org.eclipse.cdt.core.GCCErrorParser;"
"org.eclipse.cdt.core.GASErrorParser;"
"org.eclipse.cdt.core.GLDErrorParser;"
@@ -540,12 +554,15 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(
fileIt != sFiles.end();
++fileIt)
{
- std::string linkName4 = linkName3;
- linkName4 += "/";
- linkName4 +=
- cmSystemTools::GetFilenameName((*fileIt)->GetFullPath());
- this->AppendLinkedResource(fout, linkName4,
- (*fileIt)->GetFullPath(), LinkToFile);
+ std::string fullPath = (*fileIt)->GetFullPath();
+ if (!cmSystemTools::FileIsDirectory(fullPath.c_str()))
+ {
+ std::string linkName4 = linkName3;
+ linkName4 += "/";
+ linkName4 += cmSystemTools::GetFilenameName(fullPath);
+ this->AppendLinkedResource(fout, linkName4,
+ fullPath, LinkToFile);
+ }
}
}
}
diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h
index 31ad68da9..b31cce74c 100644
--- a/Source/cmExtraEclipseCDT4Generator.h
+++ b/Source/cmExtraEclipseCDT4Generator.h
@@ -111,6 +111,7 @@ private:
bool GenerateSourceProject;
bool GenerateLinkedResources;
bool SupportsVirtualFolders;
+ bool SupportsGmakeErrorParser;
};
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index e4802d59e..523fca9aa 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -421,7 +421,7 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source,
std::vector<std::string> includes;
lg->GetIncludeDirectories(includes, gtgt, language, config);
std::string includeFlags =
- lg->GetIncludeFlags(includes, language, true); // full include paths
+ lg->GetIncludeFlags(includes, gtgt, language, true); // full include paths
lg->AppendFlags(flags, includeFlags.c_str());
}
@@ -429,35 +429,10 @@ cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source,
lg->AppendFlags(flags, makefile->GetDefineFlags());
// Add target-specific flags.
- if(target->GetProperty("COMPILE_FLAGS"))
- {
- std::string langIncludeExpr = "CMAKE_";
- langIncludeExpr += language;
- langIncludeExpr += "_FLAG_REGEX";
- const char* regex = makefile->GetDefinition(langIncludeExpr.c_str());
- if(regex)
- {
- cmsys::RegularExpression r(regex);
- std::vector<std::string> args;
- cmSystemTools::
- ParseWindowsCommandLine(target->GetProperty("COMPILE_FLAGS"), args);
- for(std::vector<std::string>::iterator i = args.begin();
- i != args.end(); ++i)
- {
- if(r.find(i->c_str()))
- {
- lg->AppendFlags(flags, i->c_str());
- }
- }
- }
- else
- {
- lg->AppendFlags(flags, target->GetProperty("COMPILE_FLAGS"));
- }
- }
+ lg->AddCompileOptions(flags, target, config, language);
// Add source file specific flags.
- lg->AppendFlags(flags, target->GetProperty("COMPILE_FLAGS"));
+ lg->AppendFlags(flags, source->GetProperty("COMPILE_FLAGS"));
// TODO: Handle Apple frameworks.
@@ -488,7 +463,7 @@ ComputeDefines(cmSourceFile *source, cmLocalGenerator* lg, cmTarget *target,
}
// Add preprocessor definitions for this target and configuration.
- lg->AppendDefines(defines, target->GetCompileDefinitions(config));
+ lg->AddCompileDefinitions(defines, target, config);
lg->AppendDefines(defines, source->GetProperty("COMPILE_DEFINITIONS"));
{
std::string defPropName = "COMPILE_DEFINITIONS_";
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 018ce7ecd..4446f7216 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -167,6 +167,10 @@ bool cmFileCommand
{
return this->HandleTimestampCommand(args);
}
+ else if ( subCommand == "GENERATE" )
+ {
+ return this->HandleGenerateCommand(args);
+ }
std::string e = "does not recognize sub-command "+subCommand;
this->SetError(e.c_str());
@@ -1970,7 +1974,7 @@ bool cmFileInstaller
else
{
cmOStringStream e;
- e << "Option TYPE given uknown value \"" << stype << "\".";
+ e << "Option TYPE given unknown value \"" << stype << "\".";
this->FileCommand->SetError(e.str().c_str());
return false;
}
@@ -1985,7 +1989,7 @@ bool cmFileInstaller::HandleInstallDestination()
// allow for / to be a valid destination
if ( destination.size() < 2 && destination != "/" )
{
- this->FileCommand->SetError("called with inapropriate arguments. "
+ this->FileCommand->SetError("called with inappropriate arguments. "
"No DESTINATION provided or .");
return false;
}
@@ -2485,7 +2489,7 @@ namespace {
cmWriteToFileCallback(void *ptr, size_t size, size_t nmemb,
void *data)
{
- register int realsize = (int)(size * nmemb);
+ int realsize = (int)(size * nmemb);
std::ofstream* fout = static_cast<std::ofstream*>(data);
const char* chPtr = static_cast<char*>(ptr);
fout->write(chPtr, realsize);
@@ -2497,7 +2501,7 @@ namespace {
cmWriteToMemoryCallback(void *ptr, size_t size, size_t nmemb,
void *data)
{
- register int realsize = (int)(size * nmemb);
+ int realsize = (int)(size * nmemb);
cmFileCommandVectorOfChar *vec
= static_cast<cmFileCommandVectorOfChar*>(data);
const char* chPtr = static_cast<char*>(ptr);
@@ -3250,6 +3254,80 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
}
//----------------------------------------------------------------------------
+void cmFileCommand::AddEvaluationFile(const std::string &inputName,
+ const std::string &outputExpr,
+ const std::string &condition,
+ bool inputIsContent
+ )
+{
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+
+ cmGeneratorExpression outputGe(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> outputCge
+ = outputGe.Parse(outputExpr);
+
+ cmGeneratorExpression conditionGe(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> conditionCge
+ = conditionGe.Parse(condition);
+
+ this->Makefile->GetLocalGenerator()
+ ->GetGlobalGenerator()->AddEvaluationFile(inputName,
+ outputCge,
+ this->Makefile,
+ conditionCge,
+ inputIsContent);
+}
+
+//----------------------------------------------------------------------------
+bool cmFileCommand::HandleGenerateCommand(
+ std::vector<std::string> const& args)
+{
+ if (args.size() < 5)
+ {
+ this->SetError("Incorrect arguments to GENERATE subcommand.");
+ return false;
+ }
+ if (args[1] != "OUTPUT")
+ {
+ this->SetError("Incorrect arguments to GENERATE subcommand.");
+ return false;
+ }
+ std::string condition;
+ if (args.size() > 5)
+ {
+ if (args[5] != "CONDITION")
+ {
+ this->SetError("Incorrect arguments to GENERATE subcommand.");
+ return false;
+ }
+ if (args.size() != 7)
+ {
+ this->SetError("Incorrect arguments to GENERATE subcommand.");
+ return false;
+ }
+ condition = args[6];
+ if (condition.empty())
+ {
+ this->SetError("CONDITION of sub-command GENERATE must not be empty if "
+ "specified.");
+ return false;
+ }
+ }
+ std::string output = args[2];
+ const bool inputIsContent = args[3] != "INPUT";
+ if (inputIsContent && args[3] != "CONTENT")
+ {
+ this->SetError("Incorrect arguments to GENERATE subcommand.");
+ return false;
+ }
+ std::string input = args[4];
+
+ this->AddEvaluationFile(input, output, condition, inputIsContent);
+ return true;
+}
+
+//----------------------------------------------------------------------------
bool cmFileCommand::HandleTimestampCommand(
std::vector<std::string> const& args)
{
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 5973fa732..aa755d1f5 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -88,6 +88,9 @@ public:
" file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n"
" [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n"
" file(TIMESTAMP filename variable [<format string>] [UTC])\n"
+ " file(GENERATE OUTPUT output_file\n"
+ " <INPUT input_file|CONTENT input_content>\n"
+ " [CONDITION expression])\n"
"WRITE will write a message into a file called 'filename'. It "
"overwrites the file if it already exists, and creates the file "
"if it does not exist. (If the file is a build input, use "
@@ -231,6 +234,15 @@ public:
"it prints status messages, and NO_SOURCE_PERMISSIONS is default. "
"Installation scripts generated by the install() command use this "
"signature (with some undocumented options for internal use)."
+ "\n"
+ "GENERATE will write an <output_file> with content from an "
+ "<input_file>, or from <input_content>. The output is generated "
+ "conditionally based on the content of the <condition>. The file is "
+ "written at CMake generate-time and the input may contain generator "
+ "expressions. The <condition>, <output_file> and <input_file> may "
+ "also contain generator expressions. The <condition> must evaluate to "
+ "either '0' or '1'. The <output_file> must evaluate to a unique name "
+ "among all configurations and among all invocations of file(GENERATE)."
// Undocumented INSTALL options:
// - RENAME <name>
// - OPTIONAL
@@ -269,6 +281,13 @@ protected:
bool HandleUploadCommand(std::vector<std::string> const& args);
bool HandleTimestampCommand(std::vector<std::string> const& args);
+ bool HandleGenerateCommand(std::vector<std::string> const& args);
+
+private:
+ void AddEvaluationFile(const std::string &inputName,
+ const std::string &outputExpr,
+ const std::string &condition,
+ bool inputIsContent);
};
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index 10b47b9e0..a126cd110 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -267,7 +267,7 @@ ShouldRemove(const cmListFileFunction& lff, cmMakefile &mf)
std::vector<std::string> expandedArguments;
mf.ExpandArguments(lff.Arguments, expandedArguments);
// if the endfunction has arguments then make sure
- // they match the ones in the openeing function command
+ // they match the ones in the opening function command
if ((expandedArguments.empty() ||
(expandedArguments[0] == this->Args[0])))
{
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index ab8bd137e..d73c72c10 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -192,11 +192,12 @@ static std::string stripAllGeneratorExpressions(const std::string &input)
std::string result;
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
+ int nestingLevel = 0;
while((pos = input.find("$<", lastPos)) != input.npos)
{
result += input.substr(lastPos, pos - lastPos);
pos += 2;
- int nestingLevel = 1;
+ nestingLevel = 1;
const char *c = input.c_str() + pos;
const char * const cStart = c;
for ( ; *c; ++c)
@@ -224,16 +225,42 @@ static std::string stripAllGeneratorExpressions(const std::string &input)
pos += traversed;
lastPos = pos;
}
- result += input.substr(lastPos);
+ if (nestingLevel == 0)
+ {
+ result += input.substr(lastPos);
+ }
return cmGeneratorExpression::StripEmptyListElements(result);
}
//----------------------------------------------------------------------------
+static void prefixItems(const std::string &content, std::string &result,
+ const std::string &prefix)
+{
+ std::vector<std::string> entries;
+ cmGeneratorExpression::Split(content, entries);
+ const char *sep = "";
+ for(std::vector<std::string>::const_iterator ei = entries.begin();
+ ei != entries.end(); ++ei)
+ {
+ result += sep;
+ sep = ";";
+ if (!cmSystemTools::FileIsFullPath(ei->c_str())
+ && cmGeneratorExpression::Find(*ei) == std::string::npos)
+ {
+ result += prefix;
+ }
+ result += *ei;
+ }
+}
+
+//----------------------------------------------------------------------------
static std::string stripExportInterface(const std::string &input,
- cmGeneratorExpression::PreprocessContext context)
+ cmGeneratorExpression::PreprocessContext context,
+ bool resolveRelative)
{
std::string result;
+ int nestingLevel = 0;
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
while (true)
@@ -263,7 +290,7 @@ static std::string stripExportInterface(const std::string &input,
const bool gotInstallInterface = input[pos + 2] == 'I';
pos += gotInstallInterface ? sizeof("$<INSTALL_INTERFACE:") - 1
: sizeof("$<BUILD_INTERFACE:") - 1;
- int nestingLevel = 1;
+ nestingLevel = 1;
const char *c = input.c_str() + pos;
const char * const cStart = c;
for ( ; *c; ++c)
@@ -289,7 +316,15 @@ static std::string stripExportInterface(const std::string &input,
else if(context == cmGeneratorExpression::InstallInterface
&& gotInstallInterface)
{
- result += input.substr(pos, c - cStart);
+ const std::string content = input.substr(pos, c - cStart);
+ if (resolveRelative)
+ {
+ prefixItems(content, result, "${_IMPORT_PREFIX}/");
+ }
+ else
+ {
+ result += content;
+ }
}
break;
}
@@ -304,7 +339,10 @@ static std::string stripExportInterface(const std::string &input,
pos += traversed;
lastPos = pos;
}
- result += input.substr(lastPos);
+ if (nestingLevel == 0)
+ {
+ result += input.substr(lastPos);
+ }
return cmGeneratorExpression::StripEmptyListElements(result);
}
@@ -380,7 +418,8 @@ void cmGeneratorExpression::Split(const std::string &input,
//----------------------------------------------------------------------------
std::string cmGeneratorExpression::Preprocess(const std::string &input,
- PreprocessContext context)
+ PreprocessContext context,
+ bool resolveRelative)
{
if (context == StripAllGeneratorExpressions)
{
@@ -388,7 +427,7 @@ std::string cmGeneratorExpression::Preprocess(const std::string &input,
}
else if (context == BuildInterface || context == InstallInterface)
{
- return stripExportInterface(input, context);
+ return stripExportInterface(input, context, resolveRelative);
}
assert(!"cmGeneratorExpression::Preprocess called with invalid args");
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 86b6f25df..c20f130c9 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -57,7 +57,8 @@ public:
};
static std::string Preprocess(const std::string &input,
- PreprocessContext context);
+ PreprocessContext context,
+ bool resolveRelative = false);
static void Split(const std::string &input,
std::vector<std::string> &output);
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 5cb50b9b8..92dc054c9 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -22,7 +22,7 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *parent)
: Parent(parent), Target(target), Property(property),
- Content(content), Backtrace(backtrace)
+ Content(content), Backtrace(backtrace), TransitivePropertiesOnly(false)
{
const cmGeneratorExpressionDAGChecker *top = this;
const cmGeneratorExpressionDAGChecker *p = this->Parent;
@@ -33,8 +33,13 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
}
this->CheckResult = this->checkGraph();
- if (CheckResult == DAG && (top->EvaluatingIncludeDirectories()
- || top->EvaluatingCompileDefinitions()))
+#define TEST_TRANSITIVE_PROPERTY_METHOD(METHOD) \
+ top->METHOD () ||
+
+ if (CheckResult == DAG && (
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(TEST_TRANSITIVE_PROPERTY_METHOD)
+ false)
+ )
{
std::map<cmStdString, std::set<cmStdString> >::const_iterator it
= top->Seen.find(target);
@@ -134,7 +139,21 @@ cmGeneratorExpressionDAGChecker::checkGraph() const
}
//----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries()
+bool cmGeneratorExpressionDAGChecker::GetTransitivePropertiesOnly()
+{
+ const cmGeneratorExpressionDAGChecker *top = this;
+ const cmGeneratorExpressionDAGChecker *parent = this->Parent;
+ while (parent)
+ {
+ top = parent;
+ parent = parent->Parent;
+ }
+
+ return top->TransitivePropertiesOnly;
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt)
{
const cmGeneratorExpressionDAGChecker *top = this;
const cmGeneratorExpressionDAGChecker *parent = this->Parent;
@@ -145,11 +164,18 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries()
}
const char *prop = top->Property.c_str();
+
+ if (tgt)
+ {
+ return top->Target == tgt && strcmp(prop, "LINK_LIBRARIES") == 0;
+ }
+
return (strcmp(prop, "LINK_LIBRARIES") == 0
|| strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0
|| strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0
|| strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 25) == 0
- || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0);
+ || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0)
+ || strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
}
//----------------------------------------------------------------------------
@@ -161,6 +187,14 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingIncludeDirectories() const
}
//----------------------------------------------------------------------------
+bool
+cmGeneratorExpressionDAGChecker::EvaluatingSystemIncludeDirectories() const
+{
+ const char *prop = this->Property.c_str();
+ return strcmp(prop, "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES") == 0;
+}
+
+//----------------------------------------------------------------------------
bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const
{
const char *prop = this->Property.c_str();
@@ -168,3 +202,11 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const
|| strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0
|| strncmp(prop, "COMPILE_DEFINITIONS_", 20) == 0);
}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::EvaluatingCompileOptions() const
+{
+ const char *prop = this->Property.c_str();
+ return (strcmp(prop, "COMPILE_OPTIONS") == 0
+ || strcmp(prop, "INTERFACE_COMPILE_OPTIONS") == 0 );
+}
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 62a5cdf38..0b7ef025c 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -16,6 +16,18 @@
#include "cmGeneratorExpressionEvaluator.h"
+#define CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(F) \
+ F(EvaluatingIncludeDirectories) \
+ F(EvaluatingSystemIncludeDirectories) \
+ F(EvaluatingCompileDefinitions) \
+ F(EvaluatingCompileOptions)
+
+#define CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(F) \
+ F(INTERFACE_INCLUDE_DIRECTORIES) \
+ F(INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) \
+ F(INTERFACE_COMPILE_DEFINITIONS) \
+ F(INTERFACE_COMPILE_OPTIONS)
+
//----------------------------------------------------------------------------
struct cmGeneratorExpressionDAGChecker
{
@@ -37,9 +49,16 @@ struct cmGeneratorExpressionDAGChecker
void reportError(cmGeneratorExpressionContext *context,
const std::string &expr);
- bool EvaluatingLinkLibraries();
- bool EvaluatingIncludeDirectories() const;
- bool EvaluatingCompileDefinitions() const;
+ bool EvaluatingLinkLibraries(const char *tgt = 0);
+
+#define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) \
+ bool METHOD () const;
+
+CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(DECLARE_TRANSITIVE_PROPERTY_METHOD)
+
+ bool GetTransitivePropertiesOnly();
+ void SetTransitivePropertiesOnly()
+ { this->TransitivePropertiesOnly = true; }
private:
Result checkGraph() const;
@@ -52,6 +71,7 @@ private:
const GeneratorExpressionContent * const Content;
const cmListFileBacktrace Backtrace;
Result CheckResult;
+ bool TransitivePropertiesOnly;
};
#endif
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
new file mode 100644
index 000000000..cab99ed04
--- /dev/null
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -0,0 +1,151 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2013 Stephen Kelly <steveire@gmail.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+
+#include "cmGeneratorExpressionEvaluationFile.h"
+
+#include "cmMakefile.h"
+
+#include <assert.h>
+
+//----------------------------------------------------------------------------
+cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile(
+ const std::string &input,
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr,
+ cmMakefile *makefile,
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
+ bool inputIsContent)
+ : Input(input),
+ OutputFileExpr(outputFileExpr),
+ Makefile(makefile),
+ Condition(condition),
+ InputIsContent(inputIsContent)
+{
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorExpressionEvaluationFile::Generate(const char *config,
+ cmCompiledGeneratorExpression* inputExpression,
+ std::map<std::string, std::string> &outputFiles)
+{
+ std::string rawCondition = this->Condition->GetInput();
+ if (!rawCondition.empty())
+ {
+ std::string condResult = this->Condition->Evaluate(this->Makefile, config);
+ if (condResult == "0")
+ {
+ return;
+ }
+ if (condResult != "1")
+ {
+ cmOStringStream e;
+ e << "Evaluation file condition \"" << rawCondition << "\" did "
+ "not evaluate to valid content. Got \"" << condResult << "\".";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
+ }
+
+ const std::string outputFileName
+ = this->OutputFileExpr->Evaluate(this->Makefile, config);
+ const std::string outputContent
+ = inputExpression->Evaluate(this->Makefile, config);
+
+ std::map<std::string, std::string>::iterator it
+ = outputFiles.find(outputFileName);
+
+ if(it != outputFiles.end())
+ {
+ if (it->second == outputContent)
+ {
+ return;
+ }
+ cmOStringStream e;
+ e << "Evaluation file to be written multiple times for different "
+ "configurations with different content:\n " << outputFileName;
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
+
+ this->Files.push_back(outputFileName);
+ outputFiles[outputFileName] = outputContent;
+
+ std::ofstream fout(outputFileName.c_str());
+
+ if(!fout)
+ {
+ cmOStringStream e;
+ e << "Evaluation file \"" << outputFileName << "\" cannot be written.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
+
+ fout << outputContent;
+
+ fout.close();
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorExpressionEvaluationFile::Generate()
+{
+ std::string inputContent;
+ if (this->InputIsContent)
+ {
+ inputContent = this->Input;
+ }
+ else
+ {
+ std::ifstream fin(this->Input.c_str());
+ if(!fin)
+ {
+ cmOStringStream e;
+ e << "Evaluation file \"" << this->Input << "\" cannot be read.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
+
+ std::string line;
+ std::string sep;
+ while(cmSystemTools::GetLineFromStream(fin, line))
+ {
+ inputContent += sep + line;
+ sep = "\n";
+ }
+ inputContent += sep;
+ }
+
+ cmListFileBacktrace lfbt = this->OutputFileExpr->GetBacktrace();
+ cmGeneratorExpression contentGE(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> inputExpression
+ = contentGE.Parse(inputContent);
+
+ std::map<std::string, std::string> outputFiles;
+
+ std::vector<std::string> allConfigs;
+ this->Makefile->GetConfigurations(allConfigs);
+
+ if (allConfigs.empty())
+ {
+ this->Generate(0, inputExpression.get(), outputFiles);
+ }
+ else
+ {
+ for(std::vector<std::string>::const_iterator li = allConfigs.begin();
+ li != allConfigs.end(); ++li)
+ {
+ this->Generate(li->c_str(), inputExpression.get(), outputFiles);
+ if(cmSystemTools::GetFatalErrorOccured())
+ {
+ return;
+ }
+ }
+ }
+}
diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h
new file mode 100644
index 000000000..20ee5cb2d
--- /dev/null
+++ b/Source/cmGeneratorExpressionEvaluationFile.h
@@ -0,0 +1,48 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2013 Stephen Kelly <steveire@gmail.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmGeneratorExpressionEvaluationFile_h
+#define cmGeneratorExpressionEvaluationFile_h
+
+#include "cmStandardIncludes.h"
+#include <cmsys/auto_ptr.hxx>
+
+#include "cmGeneratorExpression.h"
+
+//----------------------------------------------------------------------------
+class cmGeneratorExpressionEvaluationFile
+{
+public:
+ cmGeneratorExpressionEvaluationFile(const std::string &input,
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr,
+ cmMakefile *makefile,
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
+ bool inputIsContent);
+
+ void Generate();
+
+ std::vector<std::string> GetFiles() const { return this->Files; }
+
+private:
+ void Generate(const char *config,
+ cmCompiledGeneratorExpression* inputExpression,
+ std::map<std::string, std::string> &outputFiles);
+
+private:
+ const std::string Input;
+ const cmsys::auto_ptr<cmCompiledGeneratorExpression> OutputFileExpr;
+ cmMakefile *Makefile;
+ const cmsys::auto_ptr<cmCompiledGeneratorExpression> Condition;
+ std::vector<std::string> Files;
+ const bool InputIsContent;
+};
+
+#endif
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index a01a0f890..8b3135412 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -45,13 +45,18 @@ void reportError(cmGeneratorExpressionContext *context,
//----------------------------------------------------------------------------
struct cmGeneratorExpressionNode
{
+ enum {
+ DynamicParameters = 0,
+ OneOrMoreParameters = -1,
+ ZeroOrMoreParameters = -2
+ };
virtual ~cmGeneratorExpressionNode() {}
virtual bool GeneratesContent() const { return true; }
virtual bool RequiresLiteralInput() const { return false; }
- virtual bool AcceptsSingleArbitraryContentParameter() const
+ virtual bool AcceptsArbitraryContentParameter() const
{ return false; }
virtual int NumExpectedParameters() const { return 1; }
@@ -70,7 +75,7 @@ static const struct ZeroNode : public cmGeneratorExpressionNode
virtual bool GeneratesContent() const { return false; }
- virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *,
@@ -87,7 +92,7 @@ static const struct OneNode : public cmGeneratorExpressionNode
{
OneNode() {}
- virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *,
@@ -110,8 +115,7 @@ static const struct ZeroNode installInterfaceNode;
static const struct OP ## Node : public cmGeneratorExpressionNode \
{ \
OP ## Node () {} \
-/* We let -1 carry the meaning 'at least one' */ \
- virtual int NumExpectedParameters() const { return -1; } \
+ virtual int NumExpectedParameters() const { return OneOrMoreParameters; } \
\
std::string Evaluate(const std::vector<std::string> &parameters, \
cmGeneratorExpressionContext *context, \
@@ -243,6 +247,269 @@ static const struct SemicolonNode : public cmGeneratorExpressionNode
} semicolonNode;
//----------------------------------------------------------------------------
+struct CompilerIdNode : public cmGeneratorExpressionNode
+{
+ CompilerIdNode() {}
+
+ virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
+
+ std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *,
+ const std::string &lang) const
+ {
+ const char *compilerId = context->Makefile ?
+ context->Makefile->GetSafeDefinition((
+ "CMAKE_" + lang + "_COMPILER_ID").c_str()) : "";
+ if (parameters.size() == 0)
+ {
+ return compilerId ? compilerId : "";
+ }
+ cmsys::RegularExpression compilerIdValidator;
+ compilerIdValidator.compile("^[A-Za-z0-9_]*$");
+ if (!compilerIdValidator.find(parameters.begin()->c_str()))
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ if (!compilerId)
+ {
+ return parameters.front().empty() ? "1" : "0";
+ }
+
+ if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0)
+ {
+ return "1";
+ }
+ return "0";
+ }
+};
+
+//----------------------------------------------------------------------------
+static const struct CCompilerIdNode : public CompilerIdNode
+{
+ CCompilerIdNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if (parameters.size() != 0 && parameters.size() != 1)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<C_COMPILER_ID> expression requires one or two parameters");
+ return std::string();
+ }
+ if (!context->HeadTarget)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<C_COMPILER_ID> may only be used with targets. It may not "
+ "be used with add_custom_command.");
+ }
+ return this->EvaluateWithLanguage(parameters, context, content,
+ dagChecker, "C");
+ }
+} cCompilerIdNode;
+
+//----------------------------------------------------------------------------
+static const struct CXXCompilerIdNode : public CompilerIdNode
+{
+ CXXCompilerIdNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if (parameters.size() != 0 && parameters.size() != 1)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<CXX_COMPILER_ID> expression requires one or two parameters");
+ return std::string();
+ }
+ if (!context->HeadTarget)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<CXX_COMPILER_ID> may only be used with targets. It may not "
+ "be used with add_custom_command.");
+ }
+ return this->EvaluateWithLanguage(parameters, context, content,
+ dagChecker, "CXX");
+ }
+} cxxCompilerIdNode;
+
+//----------------------------------------------------------------------------
+struct CompilerVersionNode : public cmGeneratorExpressionNode
+{
+ CompilerVersionNode() {}
+
+ virtual int NumExpectedParameters() const { return ZeroOrMoreParameters; }
+
+ std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *,
+ const std::string &lang) const
+ {
+ const char *compilerVersion = context->Makefile ?
+ context->Makefile->GetSafeDefinition((
+ "CMAKE_" + lang + "_COMPILER_VERSION").c_str()) : "";
+ if (parameters.size() == 0)
+ {
+ return compilerVersion ? compilerVersion : "";
+ }
+
+ cmsys::RegularExpression compilerIdValidator;
+ compilerIdValidator.compile("^[0-9\\.]*$");
+ if (!compilerIdValidator.find(parameters.begin()->c_str()))
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ if (!compilerVersion)
+ {
+ return parameters.front().empty() ? "1" : "0";
+ }
+
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
+ parameters.begin()->c_str(),
+ compilerVersion) ? "1" : "0";
+ }
+};
+
+//----------------------------------------------------------------------------
+static const struct CCompilerVersionNode : public CompilerVersionNode
+{
+ CCompilerVersionNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if (parameters.size() != 0 && parameters.size() != 1)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<C_COMPILER_VERSION> expression requires one or two parameters");
+ return std::string();
+ }
+ if (!context->HeadTarget)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<C_COMPILER_VERSION> may only be used with targets. It may not "
+ "be used with add_custom_command.");
+ }
+ return this->EvaluateWithLanguage(parameters, context, content,
+ dagChecker, "C");
+ }
+} cCompilerVersionNode;
+
+//----------------------------------------------------------------------------
+static const struct CxxCompilerVersionNode : public CompilerVersionNode
+{
+ CxxCompilerVersionNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if (parameters.size() != 0 && parameters.size() != 1)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<CXX_COMPILER_VERSION> expression requires one or two "
+ "parameters");
+ return std::string();
+ }
+ if (!context->HeadTarget)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<CXX_COMPILER_VERSION> may only be used with targets. It may "
+ "not be used with add_custom_command.");
+ }
+ return this->EvaluateWithLanguage(parameters, context, content,
+ dagChecker, "CXX");
+ }
+} cxxCompilerVersionNode;
+
+
+//----------------------------------------------------------------------------
+static const struct VersionGreaterNode : public cmGeneratorExpressionNode
+{
+ VersionGreaterNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
+ parameters.front().c_str(),
+ parameters[1].c_str()) ? "1" : "0";
+ }
+} versionGreaterNode;
+
+//----------------------------------------------------------------------------
+static const struct VersionLessNode : public cmGeneratorExpressionNode
+{
+ VersionLessNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
+ parameters.front().c_str(),
+ parameters[1].c_str()) ? "1" : "0";
+ }
+} versionLessNode;
+
+//----------------------------------------------------------------------------
+static const struct VersionEqualNode : public cmGeneratorExpressionNode
+{
+ VersionEqualNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
+ parameters.front().c_str(),
+ parameters[1].c_str()) ? "1" : "0";
+ }
+} versionEqualNode;
+
+//----------------------------------------------------------------------------
+static const struct LinkOnlyNode : public cmGeneratorExpressionNode
+{
+ LinkOnlyNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if(!dagChecker->GetTransitivePropertiesOnly())
+ {
+ return parameters.front();
+ }
+ return "";
+ }
+} linkOnlyNode;
+
+//----------------------------------------------------------------------------
static const struct ConfigurationNode : public cmGeneratorExpressionNode
{
ConfigurationNode() {}
@@ -297,20 +564,67 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
const char* loc = 0;
const char* imp = 0;
std::string suffix;
- return context->CurrentTarget->GetMappedConfig(context->Config,
+ if (context->CurrentTarget->GetMappedConfig(context->Config,
&loc,
&imp,
- suffix) ? "1" : "0";
+ suffix))
+ {
+ // This imported target has an appropriate location
+ // for this (possibly mapped) config.
+ // Check if there is a proper config mapping for the tested config.
+ std::vector<std::string> mappedConfigs;
+ std::string mapProp = "MAP_IMPORTED_CONFIG_";
+ mapProp += cmSystemTools::UpperCase(context->Config);
+ if(const char* mapValue =
+ context->CurrentTarget->GetProperty(mapProp.c_str()))
+ {
+ cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue),
+ mappedConfigs);
+ return std::find(mappedConfigs.begin(), mappedConfigs.end(),
+ cmSystemTools::UpperCase(parameters.front()))
+ != mappedConfigs.end() ? "1" : "0";
+ }
+ }
}
return "0";
}
} configurationTestNode;
+static const struct JoinNode : public cmGeneratorExpressionNode
+{
+ JoinNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ std::string result;
+
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(parameters.front(), list);
+ std::string sep;
+ for(std::vector<std::string>::const_iterator li = list.begin();
+ li != list.end(); ++li)
+ {
+ result += sep + *li;
+ sep = parameters[1];
+ }
+ return result;
+ }
+} joinNode;
+
+#define TRANSITIVE_PROPERTY_NAME(PROPERTY) \
+ , #PROPERTY
//----------------------------------------------------------------------------
static const char* targetPropertyTransitiveWhitelist[] = {
- "INTERFACE_INCLUDE_DIRECTORIES"
- , "INTERFACE_COMPILE_DEFINITIONS"
+ 0
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
};
std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
@@ -373,7 +687,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
TargetPropertyNode() {}
// This node handles errors on parameter count itself.
- virtual int NumExpectedParameters() const { return -1; }
+ virtual int NumExpectedParameters() const { return OneOrMoreParameters; }
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
@@ -434,6 +748,18 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
"Target name not supported.");
return std::string();
}
+ if(propertyName == "ALIASED_TARGET")
+ {
+ if(context->Makefile->IsAlias(targetName.c_str()))
+ {
+ if(cmTarget* tgt =
+ context->Makefile->FindTargetToUse(targetName.c_str()))
+ {
+ return tgt->GetName();
+ }
+ }
+ return "";
+ }
target = context->Makefile->FindTargetToUse(
targetName.c_str());
@@ -475,6 +801,20 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
assert(target);
+ if (propertyName == "LINKER_LANGUAGE")
+ {
+ if (target->LinkLanguagePropagatesToDependents() &&
+ dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "LINKER_LANGUAGE target property can not be used while evaluating "
+ "link libraries for a static library");
+ return std::string();
+ }
+ const char *lang = target->GetLinkerLanguage(context->Config);
+ return lang ? lang : "";
+ }
+
cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
target->GetName(),
propertyName,
@@ -490,7 +830,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
// No error. We just skip cyclic references.
return std::string();
case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
- for (size_t i = 0;
+ for (size_t i = 1;
i < (sizeof(targetPropertyTransitiveWhitelist) /
sizeof(*targetPropertyTransitiveWhitelist));
++i)
@@ -518,8 +858,13 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
else
{
- assert(dagCheckerParent->EvaluatingIncludeDirectories()
- || dagCheckerParent->EvaluatingCompileDefinitions());
+#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) \
+ dagCheckerParent->METHOD () ||
+
+ assert(
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
+ ASSERT_TRANSITIVE_PROPERTY_METHOD)
+ false);
}
}
@@ -532,29 +877,39 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{
interfacePropertyName = "INTERFACE_INCLUDE_DIRECTORIES";
}
+ else if (propertyName == "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")
+ {
+ interfacePropertyName = "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES";
+ }
else if (propertyName == "INTERFACE_COMPILE_DEFINITIONS"
|| propertyName == "COMPILE_DEFINITIONS"
|| strncmp(propertyName.c_str(), "COMPILE_DEFINITIONS_", 20) == 0)
{
interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
}
+ else if (propertyName == "INTERFACE_COMPILE_OPTIONS"
+ || propertyName == "COMPILE_OPTIONS")
+ {
+ interfacePropertyName = "INTERFACE_COMPILE_OPTIONS";
+ }
cmTarget *headTarget = context->HeadTarget ? context->HeadTarget : target;
- const char **transBegin = targetPropertyTransitiveWhitelist;
+ const char **transBegin = targetPropertyTransitiveWhitelist + 1;
const char **transEnd = targetPropertyTransitiveWhitelist
+ (sizeof(targetPropertyTransitiveWhitelist) /
sizeof(*targetPropertyTransitiveWhitelist));
if (std::find_if(transBegin, transEnd,
TransitiveWhitelistCompare(propertyName)) != transEnd)
{
- const cmTarget::LinkInterface *iface = target->GetLinkInterface(
- context->Config,
- headTarget);
- if(iface)
+
+ std::vector<std::string> libs;
+ target->GetTransitivePropertyLinkLibraries(context->Config,
+ headTarget, libs);
+ if (!libs.empty())
{
linkedTargetsContent =
- getLinkedTargetsContent(iface->Libraries, target,
+ getLinkedTargetsContent(libs, target,
headTarget,
context, &dagChecker,
interfacePropertyName);
@@ -607,7 +962,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
return linkedTargetsContent;
}
- for (size_t i = 0;
+ for (size_t i = 1;
i < (sizeof(targetPropertyTransitiveWhitelist) /
sizeof(*targetPropertyTransitiveWhitelist));
++i)
@@ -645,7 +1000,7 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode
virtual bool GeneratesContent() const { return true; }
- virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
virtual bool RequiresLiteralInput() const { return true; }
std::string Evaluate(const std::vector<std::string> &parameters,
@@ -662,10 +1017,13 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode
//----------------------------------------------------------------------------
static const char* targetPolicyWhitelist[] = {
- "CMP0003"
- , "CMP0004"
- , "CMP0008"
- , "CMP0020"
+ 0
+#define TARGET_POLICY_STRING(POLICY) \
+ , #POLICY
+
+ CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
+
+#undef TARGET_POLICY_STRING
};
cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy)
@@ -676,10 +1034,7 @@ cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy)
return tgt->GetPolicyStatus ## POLICY (); \
} \
- RETURN_POLICY(CMP0003)
- RETURN_POLICY(CMP0004)
- RETURN_POLICY(CMP0008)
- RETURN_POLICY(CMP0020)
+ CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY)
#undef RETURN_POLICY
@@ -695,10 +1050,7 @@ cmPolicies::PolicyID policyForString(const char *policy_id)
return cmPolicies:: POLICY_ID; \
} \
- RETURN_POLICY_ID(CMP0003)
- RETURN_POLICY_ID(CMP0004)
- RETURN_POLICY_ID(CMP0008)
- RETURN_POLICY_ID(CMP0020)
+ CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID)
#undef RETURN_POLICY_ID
@@ -728,7 +1080,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode
context->HadContextSensitiveCondition = true;
- for (size_t i = 0;
+ for (size_t i = 1;
i < (sizeof(targetPolicyWhitelist) /
sizeof(*targetPolicyWhitelist));
++i)
@@ -754,8 +1106,17 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode
}
reportError(context, content->GetOriginalExpression(),
"$<TARGET_POLICY:prop> may only be used with a limited number of "
- "policies. Currently it may be used with policies CMP0003, CMP0004, "
- "CMP0008 and CMP0020."
+ "policies. Currently it may be used with the following policies:\n"
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+#define TARGET_POLICY_LIST_ITEM(POLICY) \
+ " * " STRINGIFY(POLICY) "\n"
+
+ CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
+
+#undef TARGET_POLICY_LIST_ITEM
);
return std::string();
}
@@ -898,7 +1259,7 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
+ cmGeneratorExpressionDAGChecker *dagChecker) const
{
// Lookup the referenced target.
std::string name = *parameters.begin();
@@ -916,13 +1277,20 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
"No target \"" + name + "\"");
return std::string();
}
- if(target->GetType() >= cmTarget::UTILITY &&
+ if(target->GetType() >= cmTarget::OBJECT_LIBRARY &&
target->GetType() != cmTarget::UNKNOWN_LIBRARY)
{
::reportError(context, content->GetOriginalExpression(),
"Target \"" + name + "\" is not an executable or library.");
return std::string();
}
+ if (dagChecker && dagChecker->EvaluatingLinkLibraries(name.c_str()))
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Expressions which require the linker language may not "
+ "be used while evaluating link libraries");
+ return std::string();
+ }
context->DependTargets.insert(target);
context->AllTargets.insert(target);
@@ -974,6 +1342,20 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &orNode;
else if (identifier == "NOT")
return &notNode;
+ else if (identifier == "C_COMPILER_ID")
+ return &cCompilerIdNode;
+ else if (identifier == "CXX_COMPILER_ID")
+ return &cxxCompilerIdNode;
+ else if (identifier == "VERSION_GREATER")
+ return &versionGreaterNode;
+ else if (identifier == "VERSION_LESS")
+ return &versionLessNode;
+ else if (identifier == "VERSION_EQUAL")
+ return &versionEqualNode;
+ else if (identifier == "C_COMPILER_VERSION")
+ return &cCompilerVersionNode;
+ else if (identifier == "CXX_COMPILER_VERSION")
+ return &cxxCompilerVersionNode;
else if (identifier == "CONFIGURATION")
return &configurationNode;
else if (identifier == "CONFIG")
@@ -1018,6 +1400,10 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &installInterfaceNode;
else if (identifier == "INSTALL_PREFIX")
return &installPrefixNode;
+ else if (identifier == "JOIN")
+ return &joinNode;
+ else if (identifier == "LINK_ONLY")
+ return &linkOnlyNode;
return 0;
}
@@ -1038,6 +1424,57 @@ std::string GeneratorExpressionContent::GetOriginalExpression() const
}
//----------------------------------------------------------------------------
+std::string GeneratorExpressionContent::ProcessArbitraryContent(
+ const cmGeneratorExpressionNode *node,
+ const std::string &identifier,
+ cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pit) const
+{
+ std::string result;
+
+ const
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pend = this->ParamChildren.end();
+ for ( ; pit != pend; ++pit)
+ {
+ std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
+ = pit->begin();
+ const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
+ = pit->end();
+ for ( ; it != end; ++it)
+ {
+ if (node->RequiresLiteralInput())
+ {
+ if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text)
+ {
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier + "> expression requires literal input.");
+ return std::string();
+ }
+ }
+ result += (*it)->Evaluate(context, dagChecker);
+ if (context->HadError)
+ {
+ return std::string();
+ }
+ }
+ if ((pit + 1) != pend)
+ {
+ result += ",";
+ }
+ }
+ if (node->RequiresLiteralInput())
+ {
+ std::vector<std::string> parameters;
+ parameters.push_back(result);
+ return node->Evaluate(parameters, context, this, dagChecker);
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------
std::string GeneratorExpressionContent::Evaluate(
cmGeneratorExpressionContext *context,
cmGeneratorExpressionDAGChecker *dagChecker) const
@@ -1069,7 +1506,8 @@ std::string GeneratorExpressionContent::Evaluate(
if (!node->GeneratesContent())
{
- if (node->AcceptsSingleArbitraryContentParameter())
+ if (node->NumExpectedParameters() == 1
+ && node->AcceptsArbitraryContentParameter())
{
if (this->ParamChildren.empty())
{
@@ -1086,50 +1524,12 @@ std::string GeneratorExpressionContent::Evaluate(
return std::string();
}
- if (node->AcceptsSingleArbitraryContentParameter())
+ if (node->NumExpectedParameters() == 1
+ && node->AcceptsArbitraryContentParameter())
{
- std::string result;
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
- pit = this->ParamChildren.begin();
- const
- std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
- pend = this->ParamChildren.end();
- for ( ; pit != pend; ++pit)
- {
- if (!result.empty())
- {
- result += ",";
- }
-
- std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
- = pit->begin();
- const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
- = pit->end();
- for ( ; it != end; ++it)
- {
- if (node->RequiresLiteralInput())
- {
- if ((*it)->GetType() != cmGeneratorExpressionEvaluator::Text)
- {
- reportError(context, this->GetOriginalExpression(),
- "$<" + identifier + "> expression requires literal input.");
- return std::string();
- }
- }
- result += (*it)->Evaluate(context, dagChecker);
- if (context->HadError)
- {
- return std::string();
- }
- }
- }
- if (node->RequiresLiteralInput())
- {
- std::vector<std::string> parameters;
- parameters.push_back(result);
- return node->Evaluate(parameters, context, this, dagChecker);
- }
- return result;
+ return this->ProcessArbitraryContent(node, identifier, context,
+ dagChecker,
+ this->ParamChildren.begin());
}
std::vector<std::string> parameters;
@@ -1150,12 +1550,15 @@ std::string GeneratorExpressionContent::EvaluateParameters(
cmGeneratorExpressionDAGChecker *dagChecker,
std::vector<std::string> &parameters) const
{
+ const int numExpected = node->NumExpectedParameters();
{
std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
pit = this->ParamChildren.begin();
const
std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
pend = this->ParamChildren.end();
+ const bool acceptsArbitraryContent
+ = node->AcceptsArbitraryContentParameter();
for ( ; pit != pend; ++pit)
{
std::string parameter;
@@ -1172,11 +1575,22 @@ std::string GeneratorExpressionContent::EvaluateParameters(
}
}
parameters.push_back(parameter);
+ if (acceptsArbitraryContent
+ && parameters.size() == (unsigned int)numExpected - 1)
+ {
+ assert(pit != pend);
+ std::string lastParam = this->ProcessArbitraryContent(node, identifier,
+ context,
+ dagChecker,
+ pit + 1);
+ parameters.push_back(lastParam);
+ return std::string();
+ }
}
}
- int numExpected = node->NumExpectedParameters();
- if ((numExpected != -1 && (unsigned int)numExpected != parameters.size()))
+ if ((numExpected > cmGeneratorExpressionNode::DynamicParameters
+ && (unsigned int)numExpected != parameters.size()))
{
if (numExpected == 0)
{
@@ -1201,7 +1615,8 @@ std::string GeneratorExpressionContent::EvaluateParameters(
return std::string();
}
- if (numExpected == -1 && parameters.empty())
+ if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters
+ && parameters.empty())
{
reportError(context, this->GetOriginalExpression(), "$<" + identifier
+ "> expression requires at least one parameter.");
@@ -1228,7 +1643,6 @@ GeneratorExpressionContent::~GeneratorExpressionContent()
deleteAll(this->IdentifierChildren);
typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
- typedef std::vector<cmGeneratorExpressionToken> TokenVector;
std::vector<EvaluatorVector>::const_iterator pit =
this->ParamChildren.begin();
const std::vector<EvaluatorVector>::const_iterator pend =
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index ce7ad69bb..218abf160 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -129,6 +129,14 @@ private:
cmGeneratorExpressionDAGChecker *dagChecker,
std::vector<std::string> &parameters) const;
+ std::string ProcessArbitraryContent(
+ const cmGeneratorExpressionNode *node,
+ const std::string &identifier,
+ cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pit) const;
+
private:
std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren;
std::vector<std::vector<cmGeneratorExpressionEvaluator*> > ParamChildren;
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index a619cecd0..e1fb8f1de 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -126,6 +126,9 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
commaTokens;
std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
+
+ bool emptyParamTermination = false;
+
if (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
{
@@ -133,6 +136,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
+ if(this->it == this->Tokens.end())
+ {
+ emptyParamTermination = true;
+ }
while (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
@@ -141,6 +148,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
+ if(this->it == this->Tokens.end())
+ {
+ emptyParamTermination = true;
+ }
}
while (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
@@ -164,6 +175,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
parameters.resize(parameters.size() + 1);
assert(this->it != this->Tokens.end());
++this->it;
+ if(this->it == this->Tokens.end())
+ {
+ emptyParamTermination = true;
+ }
}
while (this->it != this->Tokens.end() &&
this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
@@ -203,7 +218,10 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
assert(parameters.size() > commaTokens.size());
for ( ; pit != pend; ++pit, ++commaIt)
{
- extendResult(result, *pit);
+ if (!pit->empty() && !emptyParamTermination)
+ {
+ extendResult(result, *pit);
+ }
if (commaIt != commaTokens.end())
{
extendText(result, *commaIt);
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 335ba0f25..62ac2638d 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -48,6 +48,57 @@ const char *cmGeneratorTarget::GetProperty(const char *prop)
}
//----------------------------------------------------------------------------
+bool cmGeneratorTarget::IsSystemIncludeDirectory(const char *dir,
+ const char *config)
+{
+ std::string config_upper;
+ if(config && *config)
+ {
+ config_upper = cmSystemTools::UpperCase(config);
+ }
+
+ typedef std::map<std::string, std::vector<std::string> > IncludeCacheType;
+ IncludeCacheType::iterator iter =
+ this->SystemIncludesCache.find(config_upper);
+
+ if (iter == this->SystemIncludesCache.end())
+ {
+ std::vector<std::string> result;
+ for (std::set<cmStdString>::const_iterator
+ it = this->Target->GetSystemIncludeDirectories().begin();
+ it != this->Target->GetSystemIncludeDirectories().end(); ++it)
+ {
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", 0, 0);
+
+ cmSystemTools::ExpandListArgument(ge.Parse(*it)
+ ->Evaluate(this->Makefile,
+ config, false, this->Target,
+ &dagChecker), result);
+ }
+ for(std::vector<std::string>::iterator li = result.begin();
+ li != result.end(); ++li)
+ {
+ cmSystemTools::ConvertToUnixSlashes(*li);
+ }
+
+ IncludeCacheType::value_type entry(config_upper, result);
+ iter = this->SystemIncludesCache.insert(entry).first;
+ }
+
+ if (std::find(iter->second.begin(),
+ iter->second.end(), dir) != iter->second.end())
+ {
+ return true;
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------------
bool cmGeneratorTarget::GetPropertyAsBool(const char *prop)
{
return this->Target->GetPropertyAsBool(prop);
@@ -98,6 +149,18 @@ void cmGeneratorTarget::ClassifySources()
this->IDLSources.push_back(sf);
if(isObjLib) { badObjLib.push_back(sf); }
}
+ else if(ext == "resx")
+ {
+ // Build and save the name of the corresponding .h file
+ // This relationship will be used later when building the project files.
+ // Both names would have been auto generated from Visual Studio
+ // where the user supplied the file name and Visual Studio
+ // appended the suffix.
+ std::string resx = sf->GetFullPath();
+ std::string hFileName = resx.substr(0, resx.find_last_of(".")) + ".h";
+ this->ExpectedResxHeaders.insert(hFileName);
+ this->ResxSources.push_back(sf);
+ }
else if(header.find(sf->GetFullPath().c_str()))
{
this->HeaderSources.push_back(sf);
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index cbcd8a579..dedfa60aa 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -44,11 +44,15 @@ public:
std::vector<cmSourceFile*> ObjectSources;
std::vector<cmSourceFile*> ExternalObjects;
std::vector<cmSourceFile*> IDLSources;
+ std::vector<cmSourceFile*> ResxSources;
+
std::string ModuleDefinitionFile;
std::map<cmSourceFile const*, std::string> Objects;
std::set<cmSourceFile const*> ExplicitObjectName;
+ std::set<std::string> ExpectedResxHeaders;
+
/** Full path with trailing slash to the top-level directory
holding object files for this target. Includes the build
time config name placeholder if needed for the generator. */
@@ -68,10 +72,14 @@ public:
/** Get the include directories for this target. */
std::vector<std::string> GetIncludeDirectories(const char *config);
+ bool IsSystemIncludeDirectory(const char *dir, const char *config);
+
private:
void ClassifySources();
void LookupObjectLibraries();
+ std::map<std::string, std::vector<std::string> > SystemIncludesCache;
+
cmGeneratorTarget(cmGeneratorTarget const&);
void operator=(cmGeneratorTarget const&);
};
diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx
index 8bb54877e..e7ad91a36 100644
--- a/Source/cmGetCMakePropertyCommand.cxx
+++ b/Source/cmGetCMakePropertyCommand.cxx
@@ -11,6 +11,8 @@
============================================================================*/
#include "cmGetCMakePropertyCommand.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmake.h"
// cmGetCMakePropertyCommand
diff --git a/Source/cmGetFilenameComponentCommand.cxx b/Source/cmGetFilenameComponentCommand.cxx
index fd1ad601f..1d7fefcee 100644
--- a/Source/cmGetFilenameComponentCommand.cxx
+++ b/Source/cmGetFilenameComponentCommand.cxx
@@ -58,7 +58,7 @@ bool cmGetFilenameComponentCommand
}
std::string storeArgs;
std::string programArgs;
- if (args[2] == "PATH")
+ if (args[2] == "DIRECTORY" || args[2] == "PATH")
{
result = cmSystemTools::GetFilenamePath(filename);
}
diff --git a/Source/cmGetFilenameComponentCommand.h b/Source/cmGetFilenameComponentCommand.h
index f294daa0d..09af3325a 100644
--- a/Source/cmGetFilenameComponentCommand.h
+++ b/Source/cmGetFilenameComponentCommand.h
@@ -64,12 +64,13 @@ public:
return
" get_filename_component(<VAR> <FileName> <COMP> [CACHE])\n"
"Set <VAR> to a component of <FileName>, where <COMP> is one of:\n"
- " PATH = Directory without file name\n"
+ " DIRECTORY = Directory without file name\n"
" NAME = File name without directory\n"
" EXT = File name longest extension (.b.c from d/a.b.c)\n"
" NAME_WE = File name without directory or longest extension\n"
" ABSOLUTE = Full path to file\n"
" REALPATH = Full path to existing file with symlinks resolved\n"
+ " PATH = Legacy alias for DIRECTORY (use for CMake <= 2.8.11)\n"
"Paths are returned with forward slashes and have no trailing slahes. "
"The longest file extension is always considered. "
"If the optional CACHE argument is specified, the result variable is "
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 7d3335887..faba7cd35 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -13,6 +13,9 @@
#include "cmake.h"
#include "cmTest.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmSourceFile.h"
#include "cmPropertyDefinition.h"
//----------------------------------------------------------------------------
@@ -285,6 +288,18 @@ bool cmGetPropertyCommand::HandleTargetMode()
return false;
}
+ if(this->PropertyName == "ALIASED_TARGET")
+ {
+ if(this->Makefile->IsAlias(this->Name.c_str()))
+ {
+ if(cmTarget* target =
+ this->Makefile->FindTargetToUse(this->Name.c_str()))
+ {
+ return this->StoreResult(target->GetName());
+ }
+ }
+ return false;
+ }
if(cmTarget* target = this->Makefile->FindTargetToUse(this->Name.c_str()))
{
return this->StoreResult(target->GetProperty(this->PropertyName.c_str()));
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index 1947139c9..02f00a508 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -22,17 +22,30 @@ bool cmGetTargetPropertyCommand
}
std::string var = args[0].c_str();
const char* targetName = args[1].c_str();
+ const char *prop = 0;
- if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName))
+ if(args[2] == "ALIASED_TARGET")
{
- cmTarget& target = *tgt;
- const char *prop = target.GetProperty(args[2].c_str());
- if (prop)
+ if(this->Makefile->IsAlias(targetName))
{
- this->Makefile->AddDefinition(var.c_str(), prop);
- return true;
+ if(cmTarget* target =
+ this->Makefile->FindTargetToUse(targetName))
+ {
+ prop = target->GetName();
+ }
}
}
+ else if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName))
+ {
+ cmTarget& target = *tgt;
+ prop = target.GetProperty(args[2].c_str());
+ }
+
+ if (prop)
+ {
+ this->Makefile->AddDefinition(var.c_str(), prop);
+ return true;
+ }
this->Makefile->AddDefinition(var.c_str(), (var+"-NOTFOUND").c_str());
return true;
}
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index df1433105..f297c4abb 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -26,6 +26,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionEvaluationFile.h"
#include <cmsys/Directory.hxx>
@@ -69,6 +70,13 @@ cmGlobalGenerator::~cmGlobalGenerator()
{
delete this->LocalGenerators[i];
}
+ for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
+ li = this->EvaluationFiles.begin();
+ li != this->EvaluationFiles.end();
+ ++li)
+ {
+ delete *li;
+ }
this->LocalGenerators.clear();
if (this->ExtraGenerator)
@@ -407,7 +415,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
{
if(!mf->ReadListFile(0,fpath.c_str()))
{
- cmSystemTools::Error("Could not find cmake module file:",
+ cmSystemTools::Error("Could not find cmake module file: ",
fpath.c_str());
}
// if this file was found then the language was already determined
@@ -423,7 +431,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
{
if (this->CMakeInstance->GetIsInTryCompile())
{
- cmSystemTools::Error("This should not have happen. "
+ cmSystemTools::Error("This should not have happened. "
"If you see this message, you are probably "
"using a broken CMakeLists.txt file or a "
"problematic release of CMake");
@@ -437,7 +445,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
mf->GetModulesFile(determineCompiler.c_str());
if(!mf->ReadListFile(0,determineFile.c_str()))
{
- cmSystemTools::Error("Could not find cmake module file:",
+ cmSystemTools::Error("Could not find cmake module file: ",
determineFile.c_str());
}
needTestLanguage[lang] = true;
@@ -471,7 +479,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
fpath += "Compiler.cmake";
if(!mf->ReadListFile(0,fpath.c_str()))
{
- cmSystemTools::Error("Could not find cmake module file:",
+ cmSystemTools::Error("Could not find cmake module file: ",
fpath.c_str());
}
this->SetLanguageEnabledFlag(lang, mf);
@@ -490,7 +498,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
fpath = mf->GetModulesFile("CMakeSystemSpecificInformation.cmake");
if(!mf->ReadListFile(0,fpath.c_str()))
{
- cmSystemTools::Error("Could not find cmake module file:",
+ cmSystemTools::Error("Could not find cmake module file: ",
fpath.c_str());
}
}
@@ -516,12 +524,12 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
std::string informationFile = mf->GetModulesFile(fpath.c_str());
if (informationFile.empty())
{
- cmSystemTools::Error("Could not find cmake module file:",
+ cmSystemTools::Error("Could not find cmake module file: ",
fpath.c_str());
}
else if(!mf->ReadListFile(0, informationFile.c_str()))
{
- cmSystemTools::Error("Could not process cmake module file:",
+ cmSystemTools::Error("Could not process cmake module file: ",
informationFile.c_str());
}
}
@@ -560,7 +568,7 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
std::string ifpath = mf->GetModulesFile(testLang.c_str());
if(!mf->ReadListFile(0,ifpath.c_str()))
{
- cmSystemTools::Error("Could not find cmake module file:",
+ cmSystemTools::Error("Could not find cmake module file: ",
ifpath.c_str());
}
std::string compilerWorks = "CMAKE_";
@@ -840,6 +848,14 @@ void cmGlobalGenerator::Configure()
delete this->LocalGenerators[i];
}
this->LocalGenerators.clear();
+ for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
+ li = this->EvaluationFiles.begin();
+ li != this->EvaluationFiles.end();
+ ++li)
+ {
+ delete *li;
+ }
+ this->EvaluationFiles.clear();
this->TargetDependencies.clear();
this->TotalTargets.clear();
this->ImportedTargets.clear();
@@ -884,12 +900,28 @@ void cmGlobalGenerator::Configure()
if ( this->CMakeInstance->GetWorkingMode() == cmake::NORMAL_MODE)
{
- const char* msg = "Configuring done";
+ cmOStringStream msg;
if(cmSystemTools::GetErrorOccuredFlag())
{
- msg = "Configuring incomplete, errors occurred!";
+ msg << "Configuring incomplete, errors occurred!";
+ const char* logs[] = {"CMakeOutput.log", "CMakeError.log", 0};
+ for(const char** log = logs; *log; ++log)
+ {
+ std::string f = this->CMakeInstance->GetHomeOutputDirectory();
+ f += this->CMakeInstance->GetCMakeFilesDirectory();
+ f += "/";
+ f += *log;
+ if(cmSystemTools::FileExists(f.c_str()))
+ {
+ msg << "\nSee also \"" << f << "\".";
+ }
+ }
}
- this->CMakeInstance->UpdateProgress(msg, -1);
+ else
+ {
+ msg << "Configuring done";
+ }
+ this->CMakeInstance->UpdateProgress(msg.str().c_str(), -1);
}
}
@@ -932,6 +964,8 @@ void cmGlobalGenerator::Generate()
return;
}
+ this->FinalizeTargetCompileDefinitions();
+
// Iterate through all targets and set up automoc for those which have
// the AUTOMOC property set
this->CreateAutomocTargets();
@@ -955,7 +989,7 @@ void cmGlobalGenerator::Generate()
for ( tit = targets->begin(); tit != targets->end(); ++ tit )
{
- tit->second.AppendBuildInterfaceIncludes();
+ tit->second.AppendBuildInterfaceIncludes();
}
}
@@ -981,6 +1015,8 @@ void cmGlobalGenerator::Generate()
// Create per-target generator information.
this->CreateGeneratorTargets();
+ this->ProcessEvaluationFiles();
+
// Compute the inter-target dependencies.
if(!this->ComputeTargetDepends())
{
@@ -991,6 +1027,17 @@ void cmGlobalGenerator::Generate()
// it builds by default.
this->FillLocalGeneratorToTargetMap();
+ for (i = 0; i < this->LocalGenerators.size(); ++i)
+ {
+ cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
+ cmTargets* targets = &(mf->GetTargets());
+ for ( cmTargets::iterator it = targets->begin();
+ it != targets->end(); ++ it )
+ {
+ it->second.FinalizeSystemIncludeDirectories();
+ }
+ }
+
// Generate project files
for (i = 0; i < this->LocalGenerators.size(); ++i)
{
@@ -1051,6 +1098,7 @@ bool cmGlobalGenerator::CheckTargets()
target.GetType() == cmTarget::STATIC_LIBRARY ||
target.GetType() == cmTarget::SHARED_LIBRARY ||
target.GetType() == cmTarget::MODULE_LIBRARY ||
+ target.GetType() == cmTarget::OBJECT_LIBRARY ||
target.GetType() == cmTarget::UTILITY)
{
if(!target.FindSourceFiles())
@@ -1103,16 +1151,15 @@ void cmGlobalGenerator::CreateAutomocTargets()
}
//----------------------------------------------------------------------------
-void cmGlobalGenerator::CreateGeneratorTargets()
+void cmGlobalGenerator::FinalizeTargetCompileDefinitions()
{
// Construct per-target generator information.
for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
{
- cmGeneratorTargetsType generatorTargets;
-
cmMakefile *mf = this->LocalGenerators[i]->GetMakefile();
- const char *noconfig_compile_definitions =
- mf->GetProperty("COMPILE_DEFINITIONS");
+
+ const std::vector<cmValueWithOrigin> noconfig_compile_definitions =
+ mf->GetCompileDefinitionsEntries();
std::vector<std::string> configs;
mf->GetConfigurations(configs);
@@ -1123,8 +1170,13 @@ void cmGlobalGenerator::CreateGeneratorTargets()
{
cmTarget* t = &ti->second;
- {
- t->AppendProperty("COMPILE_DEFINITIONS", noconfig_compile_definitions);
+ for (std::vector<cmValueWithOrigin>::const_iterator it
+ = noconfig_compile_definitions.begin();
+ it != noconfig_compile_definitions.end(); ++it)
+ {
+ t->InsertCompileDefinition(*it);
+ }
+
for(std::vector<std::string>::const_iterator ci = configs.begin();
ci != configs.end(); ++ci)
{
@@ -1134,7 +1186,24 @@ void cmGlobalGenerator::CreateGeneratorTargets()
mf->GetProperty(defPropName.c_str()));
}
}
+ }
+}
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::CreateGeneratorTargets()
+{
+ // Construct per-target generator information.
+ for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
+ {
+ cmGeneratorTargetsType generatorTargets;
+
+ cmMakefile *mf = this->LocalGenerators[i]->GetMakefile();
+
+ cmTargets& targets = mf->GetTargets();
+ for(cmTargets::iterator ti = targets.begin();
+ ti != targets.end(); ++ti)
+ {
+ cmTarget* t = &ti->second;
cmGeneratorTarget* gt = new cmGeneratorTarget(t);
this->GeneratorTargets[t] = gt;
this->ComputeTargetObjects(gt);
@@ -1340,11 +1409,13 @@ int cmGlobalGenerator::TryCompile(const char *srcdir, const char *bindir,
std::string cmGlobalGenerator
::GenerateBuildCommand(const char* makeProgram, const char *projectName,
- const char* additionalOptions, const char *targetName,
- const char* config, bool ignoreErrors, bool)
+ const char *projectDir, const char* additionalOptions,
+ const char *targetName, const char* config,
+ bool ignoreErrors, bool)
{
- // Project name and config are not used yet.
+ // Project name & dir and config are not used yet.
(void)projectName;
+ (void)projectDir;
(void)config;
std::string makeCommand =
@@ -1411,7 +1482,7 @@ int cmGlobalGenerator::Build(
if (clean)
{
std::string cleanCommand =
- this->GenerateBuildCommand(makeCommandCSTR, projectName,
+ this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
0, "clean", config, false, fast);
if(output)
{
@@ -1443,7 +1514,7 @@ int cmGlobalGenerator::Build(
// now build
std::string makeCommand =
- this->GenerateBuildCommand(makeCommandCSTR, projectName,
+ this->GenerateBuildCommand(makeCommandCSTR, projectName, bindir,
extraOptions, target,
config, false, fast);
if(output)
@@ -1723,10 +1794,22 @@ cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
return 0;
}
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::AddAlias(const char *name, cmTarget *tgt)
+{
+ this->AliasTargets[name] = tgt;
+}
+
+//----------------------------------------------------------------------------
+bool cmGlobalGenerator::IsAlias(const char *name)
+{
+ return this->AliasTargets.find(name) != this->AliasTargets.end();
+}
//----------------------------------------------------------------------------
cmTarget*
-cmGlobalGenerator::FindTarget(const char* project, const char* name)
+cmGlobalGenerator::FindTarget(const char* project, const char* name,
+ bool excludeAliases)
{
// if project specific
if(project)
@@ -1734,7 +1817,8 @@ cmGlobalGenerator::FindTarget(const char* project, const char* name)
std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
for(unsigned int i = 0; i < gens->size(); ++i)
{
- cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name);
+ cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name,
+ excludeAliases);
if(ret)
{
return ret;
@@ -1744,6 +1828,15 @@ cmGlobalGenerator::FindTarget(const char* project, const char* name)
// if all projects/directories
else
{
+ if (!excludeAliases)
+ {
+ std::map<cmStdString, cmTarget*>::iterator ai
+ = this->AliasTargets.find(name);
+ if (ai != this->AliasTargets.end())
+ {
+ return ai->second;
+ }
+ }
std::map<cmStdString,cmTarget *>::iterator i =
this->TotalTargets.find ( name );
if ( i != this->TotalTargets.end() )
@@ -2558,3 +2651,44 @@ std::string cmGlobalGenerator::EscapeJSON(const std::string& s) {
}
return result;
}
+
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::AddEvaluationFile(const std::string &inputFile,
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> outputExpr,
+ cmMakefile *makefile,
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
+ bool inputIsContent)
+{
+ this->EvaluationFiles.push_back(
+ new cmGeneratorExpressionEvaluationFile(inputFile, outputExpr,
+ makefile, condition,
+ inputIsContent));
+}
+
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::ProcessEvaluationFiles()
+{
+ std::set<std::string> generatedFiles;
+ for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
+ li = this->EvaluationFiles.begin();
+ li != this->EvaluationFiles.end();
+ ++li)
+ {
+ (*li)->Generate();
+ if (cmSystemTools::GetFatalErrorOccured())
+ {
+ return;
+ }
+ std::vector<std::string> files = (*li)->GetFiles();
+ for(std::vector<std::string>::const_iterator fi = files.begin();
+ fi != files.end(); ++fi)
+ {
+ if (!generatedFiles.insert(*fi).second)
+ {
+ cmSystemTools::Error("File to be generated by multiple different "
+ "commands: ", fi->c_str());
+ return;
+ }
+ }
+ }
+}
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 11616e0d0..80916ae59 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -20,9 +20,11 @@
#include "cmSystemTools.h" // for cmSystemTools::OutputOption
#include "cmExportSetMap.h" // For cmExportSetMap
#include "cmGeneratorTarget.h"
+#include "cmGeneratorExpression.h"
class cmake;
class cmGeneratorTarget;
+class cmGeneratorExpressionEvaluationFile;
class cmMakefile;
class cmLocalGenerator;
class cmExternalMakefileProjectGenerator;
@@ -121,9 +123,10 @@ public:
virtual std::string GenerateBuildCommand(
const char* makeProgram,
- const char *projectName, const char* additionalOptions,
- const char *targetName,
- const char* config, bool ignoreErrors, bool fast);
+ const char *projectName, const char *projectDir,
+ const char* additionalOptions,
+ const char *targetName, const char* config,
+ bool ignoreErrors, bool fast);
///! Set the CMake instance
@@ -193,7 +196,11 @@ public:
void FindMakeProgram(cmMakefile*);
///! Find a target by name by searching the local generators.
- cmTarget* FindTarget(const char* project, const char* name);
+ cmTarget* FindTarget(const char* project, const char* name,
+ bool excludeAliases = false);
+
+ void AddAlias(const char *name, cmTarget *tgt);
+ bool IsAlias(const char *name);
/** Determine if a name resolves to a framework on disk or a built target
that is a framework. */
@@ -278,6 +285,14 @@ public:
static std::string EscapeJSON(const std::string& s);
+ void AddEvaluationFile(const std::string &inputFile,
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName,
+ cmMakefile *makefile,
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
+ bool inputIsContent);
+
+ void ProcessEvaluationFiles();
+
protected:
typedef std::vector<cmLocalGenerator*> GeneratorVector;
// for a project collect all its targets by following depend
@@ -336,7 +351,9 @@ protected:
// All targets in the entire project.
std::map<cmStdString,cmTarget *> TotalTargets;
+ std::map<cmStdString,cmTarget *> AliasTargets;
std::map<cmStdString,cmTarget *> ImportedTargets;
+ std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles;
virtual const char* GetPredefinedTargetsFolder();
virtual bool UseFolderProperty();
@@ -365,6 +382,7 @@ private:
void WriteSummary();
void WriteSummary(cmTarget* target);
+ void FinalizeTargetCompileDefinitions();
cmExternalMakefileProjectGenerator* ExtraGenerator;
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index fa277b1d1..1953546de 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -10,11 +10,12 @@
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpressionEvaluationFile.h"
+#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
-#include "cmGeneratedFileStream.h"
-#include "cmGeneratorTarget.h"
#include "cmVersion.h"
#include <algorithm>
@@ -140,8 +141,15 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
for(cmNinjaDeps::const_iterator i = explicitDeps.begin();
i != explicitDeps.end();
++i)
+ {
arguments << " " << EncodeIdent(EncodePath(*i), os);
+ //we need to track every dependency that comes in, since we are trying
+ //to find dependencies that are side effects of build commands
+ //
+ this->CombinedBuildExplicitDependencies.insert( EncodePath(*i) );
+ }
+
// Write implicit dependencies.
if(!implicitDeps.empty())
{
@@ -170,7 +178,10 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
build << "build";
for(cmNinjaDeps::const_iterator i = outputs.begin();
i != outputs.end(); ++i)
+ {
build << " " << EncodeIdent(EncodePath(*i), os);
+ this->CombinedBuildOutputs.insert( EncodePath(*i) );
+ }
build << ":";
// Write the rule.
@@ -208,14 +219,14 @@ void cmGlobalNinjaGenerator::WritePhonyBuild(std::ostream& os,
const cmNinjaDeps& orderOnlyDeps,
const cmNinjaVars& variables)
{
- cmGlobalNinjaGenerator::WriteBuild(os,
- comment,
- "phony",
- outputs,
- explicitDeps,
- implicitDeps,
- orderOnlyDeps,
- variables);
+ this->WriteBuild(os,
+ comment,
+ "phony",
+ outputs,
+ explicitDeps,
+ implicitDeps,
+ orderOnlyDeps,
+ variables);
}
void cmGlobalNinjaGenerator::AddCustomCommandRule()
@@ -251,14 +262,14 @@ cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
vars["COMMAND"] = cmd;
vars["DESC"] = EncodeLiteral(description);
- cmGlobalNinjaGenerator::WriteBuild(*this->BuildFileStream,
- comment,
- "CUSTOM_COMMAND",
- outputs,
- deps,
- cmNinjaDeps(),
- orderOnlyDeps,
- vars);
+ this->WriteBuild(*this->BuildFileStream,
+ comment,
+ "CUSTOM_COMMAND",
+ outputs,
+ deps,
+ cmNinjaDeps(),
+ orderOnlyDeps,
+ vars);
}
void
@@ -293,14 +304,14 @@ cmGlobalNinjaGenerator::WriteMacOSXContentBuild(const std::string& input,
deps.push_back(input);
cmNinjaVars vars;
- cmGlobalNinjaGenerator::WriteBuild(*this->BuildFileStream,
- "",
- "COPY_OSX_CONTENT",
- outputs,
- deps,
- cmNinjaDeps(),
- cmNinjaDeps(),
- cmNinjaVars());
+ this->WriteBuild(*this->BuildFileStream,
+ "",
+ "COPY_OSX_CONTENT",
+ outputs,
+ deps,
+ cmNinjaDeps(),
+ cmNinjaDeps(),
+ cmNinjaVars());
}
void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
@@ -478,6 +489,7 @@ void cmGlobalNinjaGenerator::Generate()
this->WriteAssumedSourceDependencies();
this->WriteTargetAliases(*this->BuildFileStream);
+ this->WriteUnknownExplicitDependencies(*this->BuildFileStream);
this->WriteBuiltinTargets(*this->BuildFileStream);
if (cmSystemTools::GetErrorOccuredFlag()) {
@@ -523,14 +535,16 @@ bool cmGlobalNinjaGenerator::UsingMinGW = false;
std::string cmGlobalNinjaGenerator
::GenerateBuildCommand(const char* makeProgram,
const char* projectName,
+ const char* projectDir,
const char* additionalOptions,
const char* targetName,
const char* config,
bool ignoreErrors,
bool fast)
{
- // Project name and config are not used yet.
+ // Project name & dir and config are not used yet.
(void)projectName;
+ (void)projectDir;
(void)config;
// Ninja does not have -i equivalent option yet.
(void)ignoreErrors;
@@ -810,13 +824,19 @@ cmGlobalNinjaGenerator
cmLocalNinjaGenerator *ng =
static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]);
+ // for frameworks, we want the real name, not smple name
+ // frameworks always appear versioned, and the build.ninja
+ // will always attempt to manage symbolic links instead
+ // of letting cmOSXBundleGenerator do it.
+ bool realname = target->IsFrameworkOnApple();
+
switch (target->GetType()) {
case cmTarget::EXECUTABLE:
case cmTarget::SHARED_LIBRARY:
case cmTarget::STATIC_LIBRARY:
case cmTarget::MODULE_LIBRARY:
outputs.push_back(ng->ConvertToNinjaPath(
- target->GetFullPath(configName).c_str()));
+ target->GetFullPath(configName, false, realname).c_str()));
break;
case cmTarget::OBJECT_LIBRARY:
@@ -885,7 +905,7 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
cmGlobalNinjaGenerator::WriteDivider(os);
os << "# Target aliases.\n\n";
- for (TargetAliasMap::iterator i = TargetAliases.begin();
+ for (TargetAliasMap::const_iterator i = TargetAliases.begin();
i != TargetAliases.end(); ++i) {
// Don't write ambiguous aliases.
if (!i->second)
@@ -894,13 +914,128 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
cmNinjaDeps deps;
this->AppendTargetOutputs(i->second, deps);
- cmGlobalNinjaGenerator::WritePhonyBuild(os,
- "",
- cmNinjaDeps(1, i->first),
- deps);
+ this->WritePhonyBuild(os,
+ "",
+ cmNinjaDeps(1, i->first),
+ deps);
}
}
+void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
+{
+ //now write out the unknown explicit dependencies.
+
+ //union the configured files, evaluations files and the CombinedBuildOutputs,
+ //and then difference with CombinedExplicitDependencies to find the explicit
+ //dependencies that we have no rule for
+
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ os << "# Unknown Build Time Dependencies.\n"
+ << "# Tell Ninja that they may appear as side effects of build rules\n"
+ << "# otherwise ordered by order-only dependencies.\n\n";
+
+ //get the list of files that cmake itself has generated as a
+ //product of configuration.
+ cmLocalNinjaGenerator *ng =
+ static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]);
+
+ std::set<std::string> knownDependencies;
+ for (std::vector<cmLocalGenerator *>::const_iterator i =
+ this->LocalGenerators.begin(); i != this->LocalGenerators.end(); ++i)
+ {
+ //get the vector of files created by this makefile and convert them
+ //to ninja paths, which are all relative in respect to the build directory
+ const std::vector<std::string>& files =
+ (*i)->GetMakefile()->GetOutputFiles();
+ typedef std::vector<std::string>::const_iterator vect_it;
+ for(vect_it j = files.begin(); j != files.end(); ++j)
+ {
+ knownDependencies.insert( ng->ConvertToNinjaPath( j->c_str() ) );
+ }
+ }
+
+ for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
+ li = this->EvaluationFiles.begin();
+ li != this->EvaluationFiles.end();
+ ++li)
+ {
+ //get all the files created by generator expressions and convert them
+ //to ninja paths
+ std::vector<std::string> files = (*li)->GetFiles();
+ typedef std::vector<std::string>::const_iterator vect_it;
+ for(vect_it j = files.begin(); j != files.end(); ++j)
+ {
+ knownDependencies.insert( ng->ConvertToNinjaPath( j->c_str() ) );
+ }
+ }
+
+ for(TargetAliasMap::const_iterator i= this->TargetAliases.begin();
+ i != this->TargetAliases.end();
+ ++i)
+ {
+ knownDependencies.insert( ng->ConvertToNinjaPath(i->first.c_str()) );
+ }
+
+ //remove all source files we know will exist.
+ typedef std::map<std::string, std::set<std::string> >::const_iterator map_it;
+ for(map_it i = this->AssumedSourceDependencies.begin();
+ i != this->AssumedSourceDependencies.end();
+ ++i)
+ {
+ knownDependencies.insert( ng->ConvertToNinjaPath(i->first.c_str()) );
+ }
+
+ //insert outputs from all WirteBuild commands
+ for(std::set<std::string>::iterator i = this->CombinedBuildOutputs.begin();
+ i != this->CombinedBuildOutputs.end(); ++i)
+ {
+ //these paths have already be encoded when added to CombinedBuildOutputs
+ knownDependencies.insert(*i);
+ }
+
+ //after we have combined the data into knownDependencies we have no need
+ //to keep this data around
+ this->CombinedBuildOutputs.clear();
+
+ //now we difference with CombinedBuildExplicitDependencies to find
+ //the list of items we know nothing about.
+ //We have encoded all the paths in CombinedBuildExplicitDependencies
+ //and knownDependencies so no matter if unix or windows paths they
+ //should all match now.
+
+ std::vector<std::string> unkownExplicitDepends;
+ this->CombinedBuildExplicitDependencies.erase("all");
+
+ std::set_difference(this->CombinedBuildExplicitDependencies.begin(),
+ this->CombinedBuildExplicitDependencies.end(),
+ knownDependencies.begin(),
+ knownDependencies.end(),
+ std::back_inserter(unkownExplicitDepends));
+
+
+ std::string const rootBuildDirectory =
+ this->GetCMakeInstance()->GetHomeOutputDirectory();
+ for (std::vector<std::string>::const_iterator
+ i = unkownExplicitDepends.begin();
+ i != unkownExplicitDepends.end();
+ ++i)
+ {
+ //verify the file is in the build directory
+ std::string const absDepPath = cmSystemTools::CollapseFullPath(
+ i->c_str(), rootBuildDirectory.c_str());
+ bool const inBuildDir = cmSystemTools::IsSubDirectory(absDepPath.c_str(),
+ rootBuildDirectory.c_str());
+ if(inBuildDir)
+ {
+ cmNinjaDeps deps(1,*i);
+ this->WritePhonyBuild(os,
+ "",
+ deps,
+ deps);
+ }
+ }
+}
+
void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
{
// Write headers.
@@ -918,10 +1053,10 @@ void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
cmNinjaDeps outputs;
outputs.push_back("all");
- cmGlobalNinjaGenerator::WritePhonyBuild(os,
- "The main all target.",
- outputs,
- this->AllDependencies);
+ this->WritePhonyBuild(os,
+ "The main all target.",
+ outputs,
+ this->AllDependencies);
cmGlobalNinjaGenerator::WriteDefault(os,
outputs,
@@ -965,19 +1100,19 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
implicitDeps.end());
implicitDeps.push_back("CMakeCache.txt");
- WriteBuild(os,
- "Re-run CMake if any of its inputs changed.",
- "RERUN_CMAKE",
- /*outputs=*/ cmNinjaDeps(1, NINJA_BUILD_FILE),
- /*explicitDeps=*/ cmNinjaDeps(),
- implicitDeps,
- /*orderOnlyDeps=*/ cmNinjaDeps(),
- /*variables=*/ cmNinjaVars());
-
- WritePhonyBuild(os,
- "A missing CMake input file is not an error.",
- implicitDeps,
- cmNinjaDeps());
+ this->WriteBuild(os,
+ "Re-run CMake if any of its inputs changed.",
+ "RERUN_CMAKE",
+ /*outputs=*/ cmNinjaDeps(1, NINJA_BUILD_FILE),
+ /*explicitDeps=*/ cmNinjaDeps(),
+ implicitDeps,
+ /*orderOnlyDeps=*/ cmNinjaDeps(),
+ /*variables=*/ cmNinjaVars());
+
+ this->WritePhonyBuild(os,
+ "A missing CMake input file is not an error.",
+ implicitDeps,
+ cmNinjaDeps());
}
std::string cmGlobalNinjaGenerator::ninjaCmd() const
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index c3df7d935..e046c7c96 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -77,27 +77,27 @@ public:
* It also writes the variables bound to this build statement.
* @warning no escaping of any kind is done here.
*/
- static void WriteBuild(std::ostream& os,
- const std::string& comment,
- const std::string& rule,
- const cmNinjaDeps& outputs,
- const cmNinjaDeps& explicitDeps,
- const cmNinjaDeps& implicitDeps,
- const cmNinjaDeps& orderOnlyDeps,
- const cmNinjaVars& variables,
- const std::string& rspfile = std::string(),
- int cmdLineLimit = -1);
+ void WriteBuild(std::ostream& os,
+ const std::string& comment,
+ const std::string& rule,
+ const cmNinjaDeps& outputs,
+ const cmNinjaDeps& explicitDeps,
+ const cmNinjaDeps& implicitDeps,
+ const cmNinjaDeps& orderOnlyDeps,
+ const cmNinjaVars& variables,
+ const std::string& rspfile = std::string(),
+ int cmdLineLimit = -1);
/**
* Helper to write a build statement with the special 'phony' rule.
*/
- static void WritePhonyBuild(std::ostream& os,
- const std::string& comment,
- const cmNinjaDeps& outputs,
- const cmNinjaDeps& explicitDeps,
- const cmNinjaDeps& implicitDeps = cmNinjaDeps(),
- const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps(),
- const cmNinjaVars& variables = cmNinjaVars());
+ void WritePhonyBuild(std::ostream& os,
+ const std::string& comment,
+ const cmNinjaDeps& outputs,
+ const cmNinjaDeps& explicitDeps,
+ const cmNinjaDeps& implicitDeps = cmNinjaDeps(),
+ const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps(),
+ const cmNinjaVars& variables = cmNinjaVars());
void WriteCustomCommandBuild(const std::string& command,
const std::string& description,
@@ -191,6 +191,7 @@ public:
/// Overloaded methods. @see cmGlobalGenerator::GenerateBuildCommand()
virtual std::string GenerateBuildCommand(const char* makeProgram,
const char* projectName,
+ const char* projectDir,
const char* additionalOptions,
const char* targetName,
const char* config,
@@ -320,6 +321,7 @@ private:
void WriteAssumedSourceDependencies();
void WriteTargetAliases(std::ostream& os);
+ void WriteUnknownExplicitDependencies(std::ostream& os);
void WriteBuiltinTargets(std::ostream& os);
void WriteTargetAll(std::ostream& os);
@@ -357,6 +359,12 @@ private:
/// The set of custom command outputs we have seen.
std::set<std::string> CustomCommandOutputs;
+ //The combined explicit dependencies of all build commands that the global
+ //generator has issued. When combined with CombinedBuildOutputs it allows
+ //us to detect the set of explicit dependencies that have
+ std::set<std::string> CombinedBuildExplicitDependencies;
+ std::set<std::string> CombinedBuildOutputs;
+
/// The mapping from source file to assumed dependencies.
std::map<std::string, std::set<std::string> > AssumedSourceDependencies;
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index e26cca940..88cd6e5f8 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -517,11 +517,13 @@ cmGlobalUnixMakefileGenerator3
std::string cmGlobalUnixMakefileGenerator3
::GenerateBuildCommand(const char* makeProgram, const char *projectName,
- const char* additionalOptions, const char *targetName,
- const char* config, bool ignoreErrors, bool fast)
+ const char *projectDir, const char* additionalOptions,
+ const char *targetName, const char* config,
+ bool ignoreErrors, bool fast)
{
- // Project name and config are not used yet.
+ // Project name & dir and config are not used yet.
(void)projectName;
+ (void)projectDir;
(void)config;
std::string makeCommand =
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 385cdc4a1..5e9dce3a6 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -107,7 +107,8 @@ public:
// change the build command for speed
virtual std::string GenerateBuildCommand
(const char* makeProgram,
- const char *projectName, const char* additionalOptions,
+ const char *projectName, const char *projectDir,
+ const char* additionalOptions,
const char *targetName,
const char* config, bool ignoreErrors, bool fast);
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index ee7c56fc6..b2a337cc6 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -14,6 +14,8 @@
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmVisualStudioSlnData.h"
+#include "cmVisualStudioSlnParser.h"
#include "cmake.h"
static const char vs10Win32generatorName[] = "Visual Studio 10";
@@ -28,17 +30,17 @@ public:
if(!strcmp(name, vs10Win32generatorName))
{
return new cmGlobalVisualStudio10Generator(
- vs10Win32generatorName, NULL, NULL);
+ name, NULL, NULL);
}
if(!strcmp(name, vs10Win64generatorName))
{
return new cmGlobalVisualStudio10Generator(
- vs10Win64generatorName, "x64", "CMAKE_FORCE_WIN64");
+ name, "x64", "CMAKE_FORCE_WIN64");
}
if(!strcmp(name, vs10IA64generatorName))
{
return new cmGlobalVisualStudio10Generator(
- vs10IA64generatorName, "Itanium", "CMAKE_FORCE_IA64");
+ name, "Itanium", "CMAKE_FORCE_IA64");
}
return 0;
}
@@ -67,9 +69,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory()
//----------------------------------------------------------------------------
cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
- const char* name, const char* architectureId,
+ const char* name, const char* platformName,
const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio8Generator(name, architectureId,
+ : cmGlobalVisualStudio8Generator(name, platformName,
additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS10FindMake.cmake";
@@ -77,6 +79,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
this->ExpressEdition = cmSystemTools::ReadRegistryValue(
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;"
"ProductDir", vc10Express, cmSystemTools::KeyWOW64_32);
+ this->MasmEnabled = false;
}
//----------------------------------------------------------------------------
@@ -159,13 +162,23 @@ void cmGlobalVisualStudio10Generator
::EnableLanguage(std::vector<std::string>const & lang,
cmMakefile *mf, bool optional)
{
- if(this->ArchitectureId == "Itanium" || this->ArchitectureId == "x64")
+ if(this->PlatformName == "Itanium" || this->PlatformName == "x64")
{
if(this->IsExpressEdition() && !this->Find64BitTools(mf))
{
return;
}
}
+
+ for(std::vector<std::string>::const_iterator it = lang.begin();
+ it != lang.end(); ++it)
+ {
+ if(*it == "ASM_MASM")
+ {
+ this->MasmEnabled = true;
+ }
+ }
+
cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
}
@@ -215,7 +228,7 @@ std::string cmGlobalVisualStudio10Generator::GetUserMacrosRegKeyBase()
std::string cmGlobalVisualStudio10Generator
::GenerateBuildCommand(const char* makeProgram,
- const char *projectName,
+ const char *projectName, const char *projectDir,
const char* additionalOptions, const char *targetName,
const char* config, bool ignoreErrors, bool fast)
{
@@ -230,7 +243,8 @@ std::string cmGlobalVisualStudio10Generator
lowerCaseCommand.find("VCExpress") != std::string::npos)
{
return cmGlobalVisualStudio7Generator::GenerateBuildCommand(makeProgram,
- projectName, additionalOptions, targetName, config, ignoreErrors, fast);
+ projectName, projectDir, additionalOptions, targetName, config,
+ ignoreErrors, fast);
}
// Otherwise, assume MSBuild command line, and construct accordingly.
@@ -258,9 +272,38 @@ std::string cmGlobalVisualStudio10Generator
}
else
{
+ std::string targetProject(targetName);
+ targetProject += ".vcxproj";
+ if (targetProject.find('/') == std::string::npos)
+ {
+ // it might be in a subdir
+ cmVisualStudioSlnParser parser;
+ cmSlnData slnData;
+ std::string slnFile;
+ if (projectDir && *projectDir)
+ {
+ slnFile = projectDir;
+ slnFile += '/';
+ slnFile += projectName;
+ }
+ else
+ {
+ slnFile = projectName;
+ }
+ if (parser.ParseFile(slnFile + ".sln", slnData,
+ cmVisualStudioSlnParser::DataGroupProjects))
+ {
+ if (cmSlnProjectEntry const* proj =
+ slnData.GetProjectByName(targetName))
+ {
+ targetProject = proj->GetRelativePath();
+ cmSystemTools::ConvertToUnixSlashes(targetProject);
+ }
+ }
+ }
+ makeCommand += " ";
+ makeCommand += targetProject;
makeCommand += " ";
- makeCommand += targetName;
- makeCommand += ".vcxproj ";
}
makeCommand += "/p:Configuration=";
if(config && strlen(config))
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 5926e0f21..31e122efe 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -25,14 +25,14 @@ class cmGlobalVisualStudio10Generator :
{
public:
cmGlobalVisualStudio10Generator(const char* name,
- const char* architectureId, const char* additionalPlatformDefinition);
+ const char* platformName, const char* additionalPlatformDefinition);
static cmGlobalGeneratorFactory* NewFactory();
virtual bool SetGeneratorToolset(std::string const& ts);
virtual std::string
GenerateBuildCommand(const char* makeProgram,
- const char *projectName,
+ const char *projectName, const char *projectDir,
const char* additionalOptions, const char *targetName,
const char* config, bool ignoreErrors, bool);
@@ -54,6 +54,9 @@ public:
/** Is the installed VS an Express edition? */
bool IsExpressEdition() const { return this->ExpressEdition; }
+ /** Is the Microsoft Assembler enabled? */
+ bool IsMasmEnabled() const { return this->MasmEnabled; }
+
/** The toolset name for the target platform. */
const char* GetPlatformToolset();
@@ -78,11 +81,15 @@ public:
void PathTooLong(cmTarget* target, cmSourceFile* sf,
std::string const& sfRel);
+
+ virtual const char* GetToolsVersion() { return "4.0"; }
+
protected:
virtual const char* GetIDEVersion() { return "10.0"; }
std::string PlatformToolset;
bool ExpressEdition;
+ bool MasmEnabled;
bool UseFolderProperty();
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index 624d01d69..8ae733165 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -13,31 +13,56 @@
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
-static const char vs11Win32generatorName[] = "Visual Studio 11";
-static const char vs11Win64generatorName[] = "Visual Studio 11 Win64";
-static const char vs11ARMgeneratorName[] = "Visual Studio 11 ARM";
+static const char vs11generatorName[] = "Visual Studio 11";
class cmGlobalVisualStudio11Generator::Factory
: public cmGlobalGeneratorFactory
{
public:
virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
- if(!strcmp(name, vs11Win32generatorName))
+ if(strstr(name, vs11generatorName) != name)
+ {
+ return 0;
+ }
+
+ const char* p = name + sizeof(vs11generatorName) - 1;
+ if(p[0] == '\0')
{
return new cmGlobalVisualStudio11Generator(
- vs11Win32generatorName, NULL, NULL);
+ name, NULL, NULL);
+ }
+
+ if(p[0] != ' ')
+ {
+ return 0;
}
- if(!strcmp(name, vs11Win64generatorName))
+
+ ++p;
+
+ if(!strcmp(p, "ARM"))
{
return new cmGlobalVisualStudio11Generator(
- vs11Win64generatorName, "x64", "CMAKE_FORCE_WIN64");
+ name, "ARM", NULL);
}
- if(!strcmp(name, vs11ARMgeneratorName))
+
+ if(!strcmp(p, "Win64"))
{
return new cmGlobalVisualStudio11Generator(
- vs11ARMgeneratorName, "ARM", NULL);
+ name, "x64", "CMAKE_FORCE_WIN64");
}
- return 0;
+
+ std::set<std::string> installedSDKs =
+ cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs();
+
+ if(installedSDKs.find(p) == installedSDKs.end())
+ {
+ return 0;
+ }
+
+ cmGlobalVisualStudio11Generator* ret =
+ new cmGlobalVisualStudio11Generator(name, p, NULL);
+ ret->WindowsCEVersion = "8.00";
+ return ret;
}
virtual void GetDocumentation(cmDocumentationEntry& entry) const {
@@ -51,9 +76,18 @@ public:
}
virtual void GetGenerators(std::vector<std::string>& names) const {
- names.push_back(vs11Win32generatorName);
- names.push_back(vs11Win64generatorName);
- names.push_back(vs11ARMgeneratorName); }
+ names.push_back(vs11generatorName);
+ names.push_back(vs11generatorName + std::string(" ARM"));
+ names.push_back(vs11generatorName + std::string(" Win64"));
+
+ std::set<std::string> installedSDKs =
+ cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs();
+ for(std::set<std::string>::const_iterator i =
+ installedSDKs.begin(); i != installedSDKs.end(); ++i)
+ {
+ names.push_back("Visual Studio 11 " + *i);
+ }
+ }
};
//----------------------------------------------------------------------------
@@ -64,9 +98,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory()
//----------------------------------------------------------------------------
cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator(
- const char* name, const char* architectureId,
+ const char* name, const char* platformName,
const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio10Generator(name, architectureId,
+ : cmGlobalVisualStudio10Generator(name, platformName,
additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS11FindMake.cmake";
@@ -109,3 +143,36 @@ bool cmGlobalVisualStudio11Generator::UseFolderProperty()
// Express editions in VS10 and earlier, but they are in VS11 Express.
return cmGlobalVisualStudio8Generator::UseFolderProperty();
}
+
+//----------------------------------------------------------------------------
+std::set<std::string>
+cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs()
+{
+ const char sdksKey[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"
+ "Windows CE Tools\\SDKs";
+
+ std::vector<std::string> subkeys;
+ cmSystemTools::GetRegistrySubKeys(sdksKey, subkeys,
+ cmSystemTools::KeyWOW64_32);
+
+ std::set<std::string> ret;
+ for(std::vector<std::string>::const_iterator i =
+ subkeys.begin(); i != subkeys.end(); ++i)
+ {
+ std::string key = sdksKey;
+ key += '\\';
+ key += *i;
+ key += ';';
+
+ std::string path;
+ if(cmSystemTools::ReadRegistryValue(key.c_str(),
+ path,
+ cmSystemTools::KeyWOW64_32) &&
+ !path.empty())
+ {
+ ret.insert(*i);
+ }
+ }
+
+ return ret;
+}
diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h
index 174f1ccb0..7cc7e69d9 100644
--- a/Source/cmGlobalVisualStudio11Generator.h
+++ b/Source/cmGlobalVisualStudio11Generator.h
@@ -21,7 +21,7 @@ class cmGlobalVisualStudio11Generator:
{
public:
cmGlobalVisualStudio11Generator(const char* name,
- const char* architectureId, const char* additionalPlatformDefinition);
+ const char* platformName, const char* additionalPlatformDefinition);
static cmGlobalGeneratorFactory* NewFactory();
virtual void WriteSLNHeader(std::ostream& fout);
@@ -34,7 +34,9 @@ public:
protected:
virtual const char* GetIDEVersion() { return "11.0"; }
bool UseFolderProperty();
+ static std::set<std::string> GetInstalledWindowsCESDKs();
private:
class Factory;
+ friend class Factory;
};
#endif
diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
index d77b84d2c..c56dfff15 100644
--- a/Source/cmGlobalVisualStudio12Generator.cxx
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -25,17 +25,17 @@ public:
if(!strcmp(name, vs12Win32generatorName))
{
return new cmGlobalVisualStudio12Generator(
- vs12Win32generatorName, NULL, NULL);
+ name, NULL, NULL);
}
if(!strcmp(name, vs12Win64generatorName))
{
return new cmGlobalVisualStudio12Generator(
- vs12Win64generatorName, "x64", "CMAKE_FORCE_WIN64");
+ name, "x64", "CMAKE_FORCE_WIN64");
}
if(!strcmp(name, vs12ARMgeneratorName))
{
return new cmGlobalVisualStudio12Generator(
- vs12ARMgeneratorName, "ARM", NULL);
+ name, "ARM", NULL);
}
return 0;
}
@@ -64,9 +64,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory()
//----------------------------------------------------------------------------
cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator(
- const char* name, const char* architectureId,
+ const char* name, const char* platformName,
const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio11Generator(name, architectureId,
+ : cmGlobalVisualStudio11Generator(name, platformName,
additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS12FindMake.cmake";
@@ -100,12 +100,3 @@ cmLocalGenerator *cmGlobalVisualStudio12Generator::CreateLocalGenerator()
lg->SetGlobalGenerator(this);
return lg;
}
-
-//----------------------------------------------------------------------------
-bool cmGlobalVisualStudio12Generator::UseFolderProperty()
-{
- // Intentionally skip over the parent class implementation and call the
- // grand-parent class's implementation. Folders are not supported by the
- // Express editions in VS10 and earlier, but they are in VS12 Express.
- return cmGlobalVisualStudio8Generator::UseFolderProperty();
-}
diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h
index 5844ee01e..8c8aeb1fd 100644
--- a/Source/cmGlobalVisualStudio12Generator.h
+++ b/Source/cmGlobalVisualStudio12Generator.h
@@ -21,7 +21,7 @@ class cmGlobalVisualStudio12Generator:
{
public:
cmGlobalVisualStudio12Generator(const char* name,
- const char* architectureId, const char* additionalPlatformDefinition);
+ const char* platformName, const char* additionalPlatformDefinition);
static cmGlobalGeneratorFactory* NewFactory();
virtual void WriteSLNHeader(std::ostream& fout);
@@ -31,9 +31,13 @@ public:
/** TODO: VS 12 user macro support. */
virtual std::string GetUserMacrosDirectory() { return ""; }
+
+ //in Visual Studio 2013 they detached the MSBuild tools version
+ //from the .Net Framework version and instead made it have it's own
+ //version number
+ virtual const char* GetToolsVersion() { return "12.0"; }
protected:
virtual const char* GetIDEVersion() { return "12.0"; }
- bool UseFolderProperty();
private:
class Factory;
};
diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx
index 9f3af71bb..b3fabdade 100644
--- a/Source/cmGlobalVisualStudio6Generator.cxx
+++ b/Source/cmGlobalVisualStudio6Generator.cxx
@@ -80,12 +80,15 @@ void cmGlobalVisualStudio6Generator::GenerateConfigurations(cmMakefile* mf)
std::string cmGlobalVisualStudio6Generator
::GenerateBuildCommand(const char* makeProgram,
const char *projectName,
+ const char *projectDir,
const char* additionalOptions,
const char *targetName,
const char* config,
bool ignoreErrors,
bool)
{
+ // Visual studio 6 doesn't need project dir
+ (void) projectDir;
// Ingoring errors is not implemented in visual studio 6
(void) ignoreErrors;
diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h
index 40149e911..6bd39ca9a 100644
--- a/Source/cmGlobalVisualStudio6Generator.h
+++ b/Source/cmGlobalVisualStudio6Generator.h
@@ -54,6 +54,7 @@ public:
*/
virtual std::string GenerateBuildCommand(const char* makeProgram,
const char *projectName,
+ const char *projectDir,
const char* additionalOptions,
const char *targetName,
const char* config,
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 2494f559c..51efc466c 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -16,7 +16,8 @@
#include "cmake.h"
//----------------------------------------------------------------------------
-cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator()
+cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator(
+ const char* platformName) : cmGlobalVisualStudio7Generator(platformName)
{
this->FindMakeProgramFile = "CMakeVS71FindMake.cmake";
this->ProjectConfigurationSectionName = "ProjectConfiguration";
@@ -281,20 +282,20 @@ void cmGlobalVisualStudio71Generator
const std::set<std::string>& configsPartOfDefaultBuild,
const char* platformMapping)
{
+ const char* platformName =
+ platformMapping ? platformMapping : this->GetPlatformName();
std::string guid = this->GetGUID(name);
for(std::vector<std::string>::iterator i = this->Configurations.begin();
i != this->Configurations.end(); ++i)
{
fout << "\t\t{" << guid << "}." << *i
- << ".ActiveCfg = " << *i << "|"
- << (platformMapping ? platformMapping : "Win32") << std::endl;
+ << ".ActiveCfg = " << *i << "|" << platformName << std::endl;
std::set<std::string>::const_iterator
ci = configsPartOfDefaultBuild.find(*i);
if(!(ci == configsPartOfDefaultBuild.end()))
{
fout << "\t\t{" << guid << "}." << *i
- << ".Build.0 = " << *i << "|"
- << (platformMapping ? platformMapping : "Win32") << std::endl;
+ << ".Build.0 = " << *i << "|" << platformName << std::endl;
}
}
}
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index 6d91f97fc..e136db7ea 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -23,7 +23,7 @@
class cmGlobalVisualStudio71Generator : public cmGlobalVisualStudio7Generator
{
public:
- cmGlobalVisualStudio71Generator();
+ cmGlobalVisualStudio71Generator(const char* platformName = NULL);
static cmGlobalGeneratorFactory* NewFactory() {
return new cmGlobalGeneratorSimpleFactory
<cmGlobalVisualStudio71Generator>(); }
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 63cbdb890..b47566561 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -17,9 +17,16 @@
#include "cmMakefile.h"
#include "cmake.h"
-cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator()
+cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(
+ const char* platformName)
{
this->FindMakeProgramFile = "CMakeVS7FindMake.cmake";
+
+ if (!platformName)
+ {
+ platformName = "Win32";
+ }
+ this->PlatformName = platformName;
}
@@ -31,6 +38,16 @@ void cmGlobalVisualStudio7Generator
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
mf->AddDefinition("CMAKE_GENERATOR_FC", "ifort");
this->AddPlatformDefinitions(mf);
+ if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
+ {
+ mf->AddCacheDefinition(
+ "CMAKE_CONFIGURATION_TYPES",
+ "Debug;Release;MinSizeRel;RelWithDebInfo",
+ "Semicolon separated list of supported configuration types, "
+ "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, "
+ "anything else will be ignored.",
+ cmCacheManager::STRING);
+ }
// Create list of configurations requested by user's cache, if any.
this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
@@ -56,10 +73,12 @@ void cmGlobalVisualStudio7Generator
std::string cmGlobalVisualStudio7Generator
::GenerateBuildCommand(const char* makeProgram,
- const char *projectName,
+ const char *projectName, const char *projectDir,
const char* additionalOptions, const char *targetName,
const char* config, bool ignoreErrors, bool)
{
+ // Visual studio 7 doesn't need project dir
+ (void) projectDir;
// Ingoring errors is not implemented in visual studio 6
(void) ignoreErrors;
@@ -132,6 +151,13 @@ cmLocalGenerator *cmGlobalVisualStudio7Generator::CreateLocalGenerator()
return lg;
}
+//----------------------------------------------------------------------------
+void cmGlobalVisualStudio7Generator::AddPlatformDefinitions(cmMakefile* mf)
+{
+ cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf);
+ mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName());
+}
+
void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf)
{
// process the configurations
@@ -589,20 +615,20 @@ void cmGlobalVisualStudio7Generator
const std::set<std::string>& configsPartOfDefaultBuild,
const char* platformMapping)
{
+ const char* platformName =
+ platformMapping ? platformMapping : this->GetPlatformName();
std::string guid = this->GetGUID(name);
for(std::vector<std::string>::iterator i = this->Configurations.begin();
i != this->Configurations.end(); ++i)
{
fout << "\t\t{" << guid << "}." << *i
- << ".ActiveCfg = " << *i << "|"
- << (platformMapping ? platformMapping : "Win32") << "\n";
+ << ".ActiveCfg = " << *i << "|" << platformName << "\n";
std::set<std::string>::const_iterator
ci = configsPartOfDefaultBuild.find(*i);
if(!(ci == configsPartOfDefaultBuild.end()))
{
fout << "\t\t{" << guid << "}." << *i
- << ".Build.0 = " << *i << "|"
- << (platformMapping ? platformMapping : "Win32") << "\n";
+ << ".Build.0 = " << *i << "|" << platformName << "\n";
}
}
}
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 6e786201b..4d22cff88 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -26,7 +26,7 @@ struct cmIDEFlagTable;
class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator
{
public:
- cmGlobalVisualStudio7Generator();
+ cmGlobalVisualStudio7Generator(const char* platformName = NULL);
static cmGlobalGeneratorFactory* NewFactory() {
return new cmGlobalGeneratorSimpleFactory
<cmGlobalVisualStudio7Generator>(); }
@@ -36,9 +36,14 @@ public:
return cmGlobalVisualStudio7Generator::GetActualName();}
static const char* GetActualName() {return "Visual Studio 7";}
+ ///! Get the name for the platform.
+ const char* GetPlatformName() const { return this->PlatformName.c_str(); }
+
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
+ virtual void AddPlatformDefinitions(cmMakefile* mf);
+
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
@@ -55,6 +60,7 @@ public:
*/
virtual std::string GenerateBuildCommand(const char* makeProgram,
const char *projectName,
+ const char *projectDir,
const char* additionalOptions,
const char *targetName,
const char* config,
@@ -152,6 +158,7 @@ protected:
// Set during OutputSLNFile with the name of the current project.
// There is one SLN file per project.
std::string CurrentProject;
+ std::string PlatformName;
};
#define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK"
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 864e8db02..e4244e062 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -57,8 +57,7 @@ public:
}
cmGlobalVisualStudio8Generator* ret = new cmGlobalVisualStudio8Generator(
- name, parser.GetArchitectureFamily(), NULL);
- ret->PlatformName = p;
+ name, p, NULL);
ret->WindowsCEVersion = parser.GetOSVersion();
return ret;
}
@@ -96,16 +95,14 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio8Generator::NewFactory()
//----------------------------------------------------------------------------
cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(
- const char* name, const char* architectureId,
+ const char* name, const char* platformName,
const char* additionalPlatformDefinition)
+ : cmGlobalVisualStudio71Generator(platformName)
{
this->FindMakeProgramFile = "CMakeVS8FindMake.cmake";
this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms";
this->Name = name;
- if (architectureId)
- {
- this->ArchitectureId = architectureId;
- }
+
if (additionalPlatformDefinition)
{
this->AdditionalPlatformDefinition = additionalPlatformDefinition;
@@ -113,20 +110,6 @@ cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(
}
//----------------------------------------------------------------------------
-const char* cmGlobalVisualStudio8Generator::GetPlatformName() const
-{
- if (!this->PlatformName.empty())
- {
- return this->PlatformName.c_str();
- }
- if (this->ArchitectureId == "X86")
- {
- return "Win32";
- }
- return this->ArchitectureId.c_str();
-}
-
-//----------------------------------------------------------------------------
///! Create a local generator appropriate to this Global Generator
cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator()
{
@@ -142,7 +125,6 @@ cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator()
void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf)
{
cmGlobalVisualStudio71Generator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName());
if(this->TargetsWindowsCE())
{
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index bcbd7a0bd..d18174275 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -24,14 +24,12 @@ class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator
{
public:
cmGlobalVisualStudio8Generator(const char* name,
- const char* architectureId, const char* additionalPlatformDefinition);
+ const char* platformName, const char* additionalPlatformDefinition);
static cmGlobalGeneratorFactory* NewFactory();
///! Get the name for the generator.
virtual const char* GetName() const {return this->Name.c_str();}
- const char* GetPlatformName() const;
-
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
@@ -87,7 +85,6 @@ protected:
const char* path, cmTarget &t);
std::string Name;
- std::string PlatformName;
std::string WindowsCEVersion;
private:
diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx
index 2082384e6..fba6ed1ee 100644
--- a/Source/cmGlobalVisualStudio9Generator.cxx
+++ b/Source/cmGlobalVisualStudio9Generator.cxx
@@ -62,8 +62,7 @@ public:
}
cmGlobalVisualStudio9Generator* ret = new cmGlobalVisualStudio9Generator(
- name, parser.GetArchitectureFamily(), NULL);
- ret->PlatformName = p;
+ name, p, NULL);
ret->WindowsCEVersion = parser.GetOSVersion();
return ret;
}
@@ -102,9 +101,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory()
//----------------------------------------------------------------------------
cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator(
- const char* name, const char* architectureId,
+ const char* name, const char* platformName,
const char* additionalPlatformDefinition)
- : cmGlobalVisualStudio8Generator(name, architectureId,
+ : cmGlobalVisualStudio8Generator(name, platformName,
additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS9FindMake.cmake";
diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h
index 1310a93ac..202aa8d12 100644
--- a/Source/cmGlobalVisualStudio9Generator.h
+++ b/Source/cmGlobalVisualStudio9Generator.h
@@ -25,7 +25,7 @@ class cmGlobalVisualStudio9Generator :
{
public:
cmGlobalVisualStudio9Generator(const char* name,
- const char* architectureId, const char* additionalPlatformDefinition);
+ const char* platformName, const char* additionalPlatformDefinition);
static cmGlobalGeneratorFactory* NewFactory();
///! create the correct local generator
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 808664d44..59310162c 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -21,7 +21,6 @@
//----------------------------------------------------------------------------
cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator()
{
- this->ArchitectureId = "X86";
this->AdditionalPlatformDefinition = NULL;
}
@@ -449,7 +448,7 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target)
}
}
- // Collext explicit util dependencies (add_dependencies).
+ // Collect explicit util dependencies (add_dependencies).
std::set<cmTarget*> utilDepends;
for(TargetDependSet::const_iterator di = depends.begin();
di != depends.end(); ++di)
@@ -499,9 +498,6 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target)
//----------------------------------------------------------------------------
void cmGlobalVisualStudioGenerator::AddPlatformDefinitions(cmMakefile* mf)
{
- mf->AddDefinition("MSVC_C_ARCHITECTURE_ID", this->ArchitectureId.c_str());
- mf->AddDefinition("MSVC_CXX_ARCHITECTURE_ID", this->ArchitectureId.c_str());
-
if(this->AdditionalPlatformDefinition)
{
mf->AddDefinition(this->AdditionalPlatformDefinition, "TRUE");
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 9d811706b..b665158c6 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -104,7 +104,6 @@ protected:
std::string GetUtilityDepend(cmTarget* target);
typedef std::map<cmTarget*, cmStdString> UtilityDependsMap;
UtilityDependsMap UtilityDepends;
- std::string ArchitectureId;
const char* AdditionalPlatformDefinition;
private:
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 3092abf95..c181c5926 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -260,6 +260,7 @@ void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const&
std::string cmGlobalXCodeGenerator
::GenerateBuildCommand(const char* makeProgram,
const char *projectName,
+ const char *projectDir,
const char* additionalOptions,
const char *targetName,
const char* config,
@@ -268,6 +269,7 @@ std::string cmGlobalXCodeGenerator
{
// Config is not used yet
(void) ignoreErrors;
+ (void) projectDir;
// now build the test
if(makeProgram == 0 || !strlen(makeProgram))
@@ -429,13 +431,16 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
// Add XCODE depend helper
std::string dir = mf->GetCurrentOutputDirectory();
- cmCustomCommandLine makecommand;
- makecommand.push_back("make");
- makecommand.push_back("-C");
- makecommand.push_back(dir.c_str());
- makecommand.push_back("-f");
- makecommand.push_back(this->CurrentXCodeHackMakefile.c_str());
- makecommand.push_back(""); // placeholder, see below
+ cmCustomCommandLine makeHelper;
+ if(this->XcodeVersion < 50)
+ {
+ makeHelper.push_back("make");
+ makeHelper.push_back("-C");
+ makeHelper.push_back(dir.c_str());
+ makeHelper.push_back("-f");
+ makeHelper.push_back(this->CurrentXCodeHackMakefile.c_str());
+ makeHelper.push_back(""); // placeholder, see below
+ }
// Add ZERO_CHECK
bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
@@ -475,17 +480,18 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
// run the depend check makefile as a post build rule
// this will make sure that when the next target is built
// things are up-to-date
- if((target.GetType() == cmTarget::EXECUTABLE ||
+ if(!makeHelper.empty() &&
+ (target.GetType() == cmTarget::EXECUTABLE ||
// Nope - no post-build for OBJECT_LIRBRARY
// target.GetType() == cmTarget::OBJECT_LIBRARY ||
target.GetType() == cmTarget::STATIC_LIBRARY ||
target.GetType() == cmTarget::SHARED_LIBRARY ||
target.GetType() == cmTarget::MODULE_LIBRARY))
{
- makecommand[makecommand.size()-1] =
+ makeHelper[makeHelper.size()-1] = // fill placeholder
this->PostBuildMakeTarget(target.GetName(), "$(CONFIGURATION)");
cmCustomCommandLines commandLines;
- commandLines.push_back(makecommand);
+ commandLines.push_back(makeHelper);
lg->GetMakefile()->AddCustomCommandToTarget(target.GetName(),
no_depends,
commandLines,
@@ -679,10 +685,6 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
{
// Add flags from target and source file properties.
std::string flags;
- if(cmtarget.GetProperty("COMPILE_FLAGS"))
- {
- lg->AppendFlags(flags, cmtarget.GetProperty("COMPILE_FLAGS"));
- }
const char* srcfmt = sf->GetProperty("Fortran_FORMAT");
switch(this->CurrentLocalGenerator->GetFortranFormat(srcfmt))
{
@@ -746,12 +748,6 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
}
}
- if(cmtarget.IsCFBundleOnApple())
- {
- cmtarget.SetProperty("PREFIX", "");
- cmtarget.SetProperty("SUFFIX", "");
- }
-
// Add the fileRef to the top level Resources group/folder if it is not
// already there.
//
@@ -839,7 +835,7 @@ GetSourcecodeValueFromFileExtension(const std::string& _ext,
// // Already specialized above or we leave sourcecode == "sourcecode"
// // which is probably the most correct choice. Extensionless headers,
// // for example... Or file types unknown to Xcode that do not map to a
- // // valid lastKnownFileType value.
+ // // valid explicitFileType value.
// }
return sourcecode;
@@ -881,8 +877,10 @@ cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
}
std::string sourcecode = GetSourcecodeValueFromFileExtension(ext, lang);
-
- fileRef->AddAttribute("lastKnownFileType",
+ const char* attribute = (sourcecode == "file.storyboard") ?
+ "lastKnownFileType" :
+ "explicitFileType";
+ fileRef->AddAttribute(attribute,
this->CreateString(sourcecode.c_str()));
// Store the file path relative to the top of the source tree.
@@ -1003,7 +1001,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
*i, cmtarget);
cmXCodeObject* fr = xsf->GetObject("fileRef");
cmXCodeObject* filetype =
- fr->GetObject()->GetObject("lastKnownFileType");
+ fr->GetObject()->GetObject("explicitFileType");
cmTarget::SourceFileFlags tsFlags =
cmtarget.GetTargetSourceFileFlags(*i);
@@ -1035,18 +1033,21 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
}
}
- // Add object library contents as external objects. (Equivalent to
- // the externalObjFiles above, except each one is not a cmSourceFile
- // within the target.)
- std::vector<std::string> objs;
- this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
- for(std::vector<std::string>::const_iterator
- oi = objs.begin(); oi != objs.end(); ++oi)
+ if(this->XcodeVersion < 50)
{
- std::string obj = *oi;
- cmXCodeObject* xsf =
- this->CreateXCodeSourceFileFromPath(obj, cmtarget, "");
- externalObjFiles.push_back(xsf);
+ // Add object library contents as external objects. (Equivalent to
+ // the externalObjFiles above, except each one is not a cmSourceFile
+ // within the target.)
+ std::vector<std::string> objs;
+ this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ std::string obj = *oi;
+ cmXCodeObject* xsf =
+ this->CreateXCodeSourceFileFromPath(obj, cmtarget, "");
+ externalObjFiles.push_back(xsf);
+ }
}
// some build phases only apply to bundles and/or frameworks
@@ -1319,8 +1320,40 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
= cmtarget.GetPreBuildCommands();
std::vector<cmCustomCommand> const & prelink
= cmtarget.GetPreLinkCommands();
- std::vector<cmCustomCommand> const & postbuild
+ std::vector<cmCustomCommand> postbuild
= cmtarget.GetPostBuildCommands();
+
+ if(cmtarget.GetType() == cmTarget::SHARED_LIBRARY &&
+ !cmtarget.IsFrameworkOnApple())
+ {
+ cmCustomCommandLines cmd;
+ cmd.resize(1);
+ cmd[0].push_back(this->CurrentMakefile->GetDefinition("CMAKE_COMMAND"));
+ cmd[0].push_back("-E");
+ cmd[0].push_back("cmake_symlink_library");
+ std::string str_file = "$<TARGET_FILE:";
+ str_file += cmtarget.GetName();
+ str_file += ">";
+ std::string str_so_file = "$<TARGET_SONAME_FILE:";
+ str_so_file += cmtarget.GetName();
+ str_so_file += ">";
+ std::string str_link_file = "$<TARGET_LINKER_FILE:";
+ str_link_file += cmtarget.GetName();
+ str_link_file += ">";
+ cmd[0].push_back(str_file);
+ cmd[0].push_back(str_so_file);
+ cmd[0].push_back(str_link_file);
+
+ cmCustomCommand command(this->CurrentMakefile,
+ std::vector<std::string>(),
+ std::vector<std::string>(),
+ cmd,
+ "Creating symlinks",
+ "");
+
+ postbuild.push_back(command);
+ }
+
std::vector<cmSourceFile*>const &classes = cmtarget.GetSourceFiles();
// add all the sources
std::vector<cmCustomCommand> commands;
@@ -1674,6 +1707,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
this->CurrentLocalGenerator->AddLanguageFlags(cflags, "C", configName);
this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target,
"C", configName);
+ this->CurrentLocalGenerator->
+ AddCompileOptions(cflags, &target, "C", configName);
}
// Add language-specific flags.
@@ -1682,11 +1717,17 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
// Add shared-library flags if needed.
this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target,
lang, configName);
+
+ this->CurrentLocalGenerator->AddVisibilityPresetFlags(flags, &target,
+ lang);
+
+ this->CurrentLocalGenerator->
+ AddCompileOptions(flags, &target, lang, configName);
}
else if(binary)
{
cmSystemTools::Error
- ("CMake can not determine linker language for target:",
+ ("CMake can not determine linker language for target: ",
target.GetName());
return;
}
@@ -1709,58 +1750,59 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
this->AppendDefines(ppDefs, exportMacro);
}
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
- this->AppendDefines(ppDefs,
- target.GetCompileDefinitions(configName).c_str());
+ std::vector<std::string> targetDefines;
+ target.GetCompileDefinitions(targetDefines, configName);
+ this->AppendDefines(ppDefs, targetDefines);
buildSettings->AddAttribute
("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());
+ std::string extraLinkOptionsVar;
std::string extraLinkOptions;
if(target.GetType() == cmTarget::EXECUTABLE)
{
- extraLinkOptions =
- this->CurrentMakefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
- std::string var = "CMAKE_EXE_LINKER_FLAGS_";
- var += cmSystemTools::UpperCase(configName);
- std::string val =
- this->CurrentMakefile->GetSafeDefinition(var.c_str());
- if(val.size())
- {
- extraLinkOptions += " ";
- extraLinkOptions += val;
- }
+ extraLinkOptionsVar = "CMAKE_EXE_LINKER_FLAGS";
}
- if(target.GetType() == cmTarget::SHARED_LIBRARY)
+ else if(target.GetType() == cmTarget::SHARED_LIBRARY)
+ {
+ extraLinkOptionsVar = "CMAKE_SHARED_LINKER_FLAGS";
+ }
+ else if(target.GetType() == cmTarget::MODULE_LIBRARY)
{
- extraLinkOptions = this->CurrentMakefile->
- GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
+ extraLinkOptionsVar = "CMAKE_MODULE_LINKER_FLAGS";
}
- if(target.GetType() == cmTarget::MODULE_LIBRARY)
+ if(extraLinkOptionsVar.size())
{
- extraLinkOptions = this->CurrentMakefile->
- GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
+ this->CurrentLocalGenerator
+ ->AddConfigVariableFlags(extraLinkOptions,
+ extraLinkOptionsVar.c_str(),
+ configName);
}
- const char* linkFlagsProp = "LINK_FLAGS";
if(target.GetType() == cmTarget::OBJECT_LIBRARY ||
target.GetType() == cmTarget::STATIC_LIBRARY)
{
- linkFlagsProp = "STATIC_LIBRARY_FLAGS";
+ this->CurrentLocalGenerator
+ ->GetStaticLibraryFlags(extraLinkOptions,
+ cmSystemTools::UpperCase(configName),
+ &target);
}
- const char* targetLinkFlags = target.GetProperty(linkFlagsProp);
- if(targetLinkFlags)
- {
- extraLinkOptions += " ";
- extraLinkOptions += targetLinkFlags;
- }
- if(configName && *configName)
+ else
{
- std::string linkFlagsVar = linkFlagsProp;
- linkFlagsVar += "_";
- linkFlagsVar += cmSystemTools::UpperCase(configName);
- if(const char* linkFlags = target.GetProperty(linkFlagsVar.c_str()))
+ const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
+ if(targetLinkFlags)
{
- extraLinkOptions += " ";
- extraLinkOptions += linkFlags;
+ this->CurrentLocalGenerator->
+ AppendFlags(extraLinkOptions, targetLinkFlags);
+ }
+ if(configName && *configName)
+ {
+ std::string linkFlagsVar = "LINK_FLAGS_";
+ linkFlagsVar += cmSystemTools::UpperCase(configName);
+ if(const char* linkFlags = target.GetProperty(linkFlagsVar.c_str()))
+ {
+ this->CurrentLocalGenerator->
+ AppendFlags(extraLinkOptions, linkFlags);
+ }
}
}
@@ -1797,9 +1839,34 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
std::string pnprefix;
std::string pnbase;
std::string pnsuffix;
-
target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
+ const char* version = target.GetProperty("VERSION");
+ const char* soversion = target.GetProperty("SOVERSION");
+ if(!target.HasSOName(configName) || target.IsFrameworkOnApple())
+ {
+ version = 0;
+ soversion = 0;
+ }
+ if(version && !soversion)
+ {
+ soversion = version;
+ }
+ if(!version && soversion)
+ {
+ version = soversion;
+ }
+
+ std::string realName = pnbase;
+ std::string soName = pnbase;
+ if(version && soversion)
+ {
+ realName += ".";
+ realName += version;
+ soName += ".";
+ soName += soversion;
+ }
+
// Set attributes to specify the proper name for the target.
std::string pndir = this->CurrentMakefile->GetCurrentOutputDirectory();
if(target.GetType() == cmTarget::STATIC_LIBRARY ||
@@ -1823,6 +1890,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
pndir = target.GetDirectory(configName);
}
+ if(target.IsFrameworkOnApple() || target.IsCFBundleOnApple())
+ {
+ pnprefix = "";
+ }
+
buildSettings->AddAttribute("EXECUTABLE_PREFIX",
this->CreateString(pnprefix.c_str()));
buildSettings->AddAttribute("EXECUTABLE_SUFFIX",
@@ -1852,7 +1924,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
// Store the product name for all target types.
buildSettings->AddAttribute("PRODUCT_NAME",
- this->CreateString(pnbase.c_str()));
+ this->CreateString(realName.c_str()));
buildSettings->AddAttribute("SYMROOT",
this->CreateString(pndir.c_str()));
@@ -1930,9 +2002,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
{
if(target.GetPropertyAsBool("FRAMEWORK"))
{
- std::string version = target.GetFrameworkVersion();
+ std::string fw_version = target.GetFrameworkVersion();
buildSettings->AddAttribute("FRAMEWORK_VERSION",
- this->CreateString(version.c_str()));
+ this->CreateString(fw_version.c_str()));
std::string plist = this->ComputeInfoPListLocation(target);
// Xcode will create the final version of Info.plist at build time,
@@ -2152,25 +2224,55 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
if(target.GetType() == cmTarget::SHARED_LIBRARY)
{
// Get the install_name directory for the build tree.
- install_name_dir = target.GetInstallNameDirForBuildTree(configName, true);
- if(install_name_dir.empty())
- {
- // Xcode will not pass the -install_name option at all if INSTALL_PATH
- // is not given or is empty. We must explicitly put the flag in the
- // link flags to create an install_name with just the library soname.
- extraLinkOptions += " -install_name ";
- extraLinkOptions += target.GetFullName(configName);
- }
- else
+ install_name_dir = target.GetInstallNameDirForBuildTree(configName);
+ // Xcode doesn't create the correct install_name in some cases.
+ // That is, if the INSTALL_PATH is empty, or if we have versioning
+ // of dylib libraries, we want to specify the install_name.
+ // This is done by adding a link flag to create an install_name
+ // with just the library soname.
+ std::string install_name;
+ if(!install_name_dir.empty())
{
// Convert to a path for the native build tool.
cmSystemTools::ConvertToUnixSlashes(install_name_dir);
- // do not escape spaces on this since it is only a single path
+ install_name += install_name_dir;
+ install_name += "/";
+ }
+ install_name += target.GetSOName(configName);
+
+ if((realName != soName) || install_name_dir.empty())
+ {
+ install_name_dir = "";
+ extraLinkOptions += " -install_name ";
+ extraLinkOptions += XCodeEscapePath(install_name.c_str());
}
}
buildSettings->AddAttribute("INSTALL_PATH",
this->CreateString(install_name_dir.c_str()));
+ // Create the LD_RUNPATH_SEARCH_PATHS
+ cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
+ if(pcli)
+ {
+ std::string search_paths;
+ std::vector<std::string> runtimeDirs;
+ pcli->GetRPath(runtimeDirs, false);
+ for(std::vector<std::string>::const_iterator i = runtimeDirs.begin();
+ i != runtimeDirs.end(); ++i)
+ {
+ if(!search_paths.empty())
+ {
+ search_paths += " ";
+ }
+ search_paths += this->XCodeEscapePath((*i).c_str());
+ }
+ if(!search_paths.empty())
+ {
+ buildSettings->AddAttribute("LD_RUNPATH_SEARCH_PATHS",
+ this->CreateString(search_paths.c_str()));
+ }
+ }
+
buildSettings->AddAttribute("OTHER_LDFLAGS",
this->CreateString(extraLinkOptions.c_str()));
buildSettings->AddAttribute("OTHER_REZFLAGS",
@@ -2235,8 +2337,39 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
{
if(i->first.find("XCODE_ATTRIBUTE_") == 0)
{
- buildSettings->AddAttribute(i->first.substr(16).c_str(),
- this->CreateString(i->second.GetValue()));
+ cmStdString attribute = i->first.substr(16);
+ // Handle [variant=<config>] condition explicitly here.
+ cmStdString::size_type beginVariant =
+ attribute.find("[variant=");
+ if (beginVariant != cmStdString::npos)
+ {
+ cmStdString::size_type endVariant =
+ attribute.find("]", beginVariant+9);
+ if (endVariant != cmStdString::npos)
+ {
+ // Compare the variant to the configuration.
+ cmStdString variant =
+ attribute.substr(beginVariant+9, endVariant-beginVariant-9);
+ if (variant == configName)
+ {
+ // The variant matches the configuration so use this
+ // attribute but drop the [variant=<config>] condition.
+ attribute.erase(beginVariant, endVariant-beginVariant+1);
+ }
+ else
+ {
+ // The variant does not match the configuration so
+ // do not use this attribute.
+ attribute.clear();
+ }
+ }
+ }
+
+ if (!attribute.empty())
+ {
+ buildSettings->AddAttribute(attribute.c_str(),
+ this->CreateString(i->second.GetValue()));
+ }
}
}
}
@@ -2641,13 +2774,6 @@ void cmGlobalXCodeGenerator
}
}
- // Skip link information for static libraries.
- if(cmtarget->GetType() == cmTarget::OBJECT_LIBRARY ||
- cmtarget->GetType() == cmTarget::STATIC_LIBRARY)
- {
- return;
- }
-
// Loop over configuration types and set per-configuration info.
for(std::vector<std::string>::iterator i =
this->CurrentConfigurationTypes.begin();
@@ -2660,6 +2786,31 @@ void cmGlobalXCodeGenerator
configName = 0;
}
+ if(this->XcodeVersion >= 50)
+ {
+ // Add object library contents as link flags.
+ std::string linkObjs;
+ const char* sep = "";
+ std::vector<std::string> objs;
+ this->GetGeneratorTarget(cmtarget)->UseObjectLibraries(objs);
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ linkObjs += sep;
+ sep = " ";
+ linkObjs += this->XCodeEscapePath(oi->c_str());
+ }
+ this->AppendBuildSettingAttribute(target, "OTHER_LDFLAGS",
+ linkObjs.c_str(), configName);
+ }
+
+ // Skip link information for object libraries.
+ if(cmtarget->GetType() == cmTarget::OBJECT_LIBRARY ||
+ cmtarget->GetType() == cmTarget::STATIC_LIBRARY)
+ {
+ continue;
+ }
+
// Compute the link library and directory information.
cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName);
if(!pcli)
@@ -3214,8 +3365,11 @@ void cmGlobalXCodeGenerator
cmXCodeObject* t = *i;
this->AddDependAndLinkInformation(t);
}
- // now create xcode depend hack makefile
- this->CreateXCodeDependHackTarget(targets);
+ if(this->XcodeVersion < 50)
+ {
+ // now create xcode depend hack makefile
+ this->CreateXCodeDependHackTarget(targets);
+ }
// now add all targets to the root object
cmXCodeObject* allTargets = this->CreateObject(cmXCodeObject::OBJECT_LIST);
for(std::vector<cmXCodeObject*>::iterator i = targets.begin();
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 131a6e6d5..c05394346 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -55,6 +55,7 @@ public:
*/
virtual std::string GenerateBuildCommand(const char* makeProgram,
const char *projectName,
+ const char *projectDir,
const char* additionalOptions,
const char *targetName,
const char* config,
@@ -84,6 +85,7 @@ public:
virtual bool IsMultiConfig();
virtual bool SetGeneratorToolset(std::string const& ts);
+ void AppendFlag(std::string& flags, std::string const& flag);
private:
cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget,
cmSourceGroup* sg);
@@ -197,7 +199,6 @@ private:
void AppendDefines(BuildObjectListOrString& defs,
std::vector<std::string> const& defines,
bool dflag = false);
- void AppendFlag(std::string& flags, std::string const& flag);
protected:
virtual const char* GetInstallTargetName() const { return "install"; }
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index 76a60cfcd..34a9c7c78 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -165,6 +165,11 @@ void cmIDEOptions::AddDefines(const char* defines)
cmSystemTools::ExpandListArgument(defines, this->Defines);
}
}
+//----------------------------------------------------------------------------
+void cmIDEOptions::AddDefines(const std::vector<std::string> &defines)
+{
+ this->Defines.insert(this->Defines.end(), defines.begin(), defines.end());
+}
//----------------------------------------------------------------------------
void cmIDEOptions::AddFlag(const char* flag, const char* value)
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index e556bdeca..e78af3ee4 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -27,6 +27,7 @@ public:
// Store definitions and flags.
void AddDefine(const std::string& define);
void AddDefines(const char* defines);
+ void AddDefines(const std::vector<std::string> &defines);
void AddFlag(const char* flag, const char* value);
void RemoveFlag(const char* flag);
const char* GetFlag(const char* flag);
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx
index 56d717031..57cec5bbb 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -406,38 +406,6 @@ namespace
}
//=========================================================================
- enum Op { OpLess, OpEqual, OpGreater };
- bool HandleVersionCompare(Op op, const char* lhs_str, const char* rhs_str)
- {
- // Parse out up to 8 components.
- unsigned int lhs[8] = {0,0,0,0,0,0,0,0};
- unsigned int rhs[8] = {0,0,0,0,0,0,0,0};
- sscanf(lhs_str, "%u.%u.%u.%u.%u.%u.%u.%u",
- &lhs[0], &lhs[1], &lhs[2], &lhs[3],
- &lhs[4], &lhs[5], &lhs[6], &lhs[7]);
- sscanf(rhs_str, "%u.%u.%u.%u.%u.%u.%u.%u",
- &rhs[0], &rhs[1], &rhs[2], &rhs[3],
- &rhs[4], &rhs[5], &rhs[6], &rhs[7]);
-
- // Do component-wise comparison.
- for(unsigned int i=0; i < 8; ++i)
- {
- if(lhs[i] < rhs[i])
- {
- // lhs < rhs, so true if operation is LESS
- return op == OpLess;
- }
- else if(lhs[i] > rhs[i])
- {
- // lhs > rhs, so true if operation is GREATER
- return op == OpGreater;
- }
- }
- // lhs == rhs, so true if operation is EQUAL
- return op == OpEqual;
- }
-
- //=========================================================================
// level 0 processes parenthetical expressions
bool HandleLevel0(std::list<std::string> &newArgs,
cmMakefile *makefile,
@@ -723,16 +691,16 @@ namespace
{
def = cmIfCommand::GetVariableOrString(arg->c_str(), makefile);
def2 = cmIfCommand::GetVariableOrString((argP2)->c_str(), makefile);
- Op op = OpEqual;
+ cmSystemTools::CompareOp op = cmSystemTools::OP_EQUAL;
if(*argP1 == "VERSION_LESS")
{
- op = OpLess;
+ op = cmSystemTools::OP_LESS;
}
else if(*argP1 == "VERSION_GREATER")
{
- op = OpGreater;
+ op = cmSystemTools::OP_GREATER;
}
- bool result = HandleVersionCompare(op, def, def2);
+ bool result = cmSystemTools::VersionCompare(op, def, def2);
HandleBinaryOp(result,
reducible, arg, newArgs, argP1, argP2);
}
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index 0d5f67b78..bb891d6fc 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -61,7 +61,7 @@ bool cmIncludeCommand
noPolicyScope = true;
}
else if(i > 1) // compat.: in previous cmake versions the second
- // parameter was ignore if it wasn't "OPTIONAL"
+ // parameter was ignored if it wasn't "OPTIONAL"
{
std::string errorText = "called with invalid argument: ";
errorText += args[i];
diff --git a/Source/cmIncludeCommand.h b/Source/cmIncludeCommand.h
index c46c02d71..d97b7c3f5 100644
--- a/Source/cmIncludeCommand.h
+++ b/Source/cmIncludeCommand.h
@@ -55,7 +55,7 @@ public:
*/
virtual const char* GetTerseDocumentation() const
{
- return "Read CMake listfile code from the given file.";
+ return "Load and run CMake code from a file or module.";
}
/**
@@ -66,9 +66,10 @@ public:
return
" include(<file|module> [OPTIONAL] [RESULT_VARIABLE <VAR>]\n"
" [NO_POLICY_SCOPE])\n"
- "Reads CMake listfile code from the given file. Commands in the file "
- "are processed immediately as if they were written in place of the "
- "include command. If OPTIONAL is present, then no error "
+ "Load and run CMake code from the file given. "
+ "Variable reads and writes access the scope of the caller "
+ "(dynamic scoping). "
+ "If OPTIONAL is present, then no error "
"is raised if the file does not exist. If RESULT_VARIABLE is given "
"the variable will be set to the full filename which "
"has been included or NOTFOUND if it failed.\n"
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index dcd418b45..3c76bd638 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -219,6 +219,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmCAStringVector runtimeArgVector (&argHelper,"RUNTIME",&group);
cmCAStringVector frameworkArgVector (&argHelper,"FRAMEWORK",&group);
cmCAStringVector bundleArgVector (&argHelper,"BUNDLE",&group);
+ cmCAStringVector includesArgVector (&argHelper,"INCLUDES",&group);
cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER",&group);
cmCAStringVector publicHeaderArgVector (&argHelper,"PUBLIC_HEADER",&group);
cmCAStringVector resourceArgVector (&argHelper,"RESOURCE",&group);
@@ -247,6 +248,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName);
cmInstallCommandArguments publicHeaderArgs(this->DefaultComponentName);
cmInstallCommandArguments resourceArgs(this->DefaultComponentName);
+ cmInstallCommandIncludesArgument includesArgs;
// now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME, ARCHIVE etc.
@@ -258,6 +260,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(), &unknownArgs);
resourceArgs.Parse (&resourceArgVector.GetVector(), &unknownArgs);
+ includesArgs.Parse (&includesArgVector.GetVector(), &unknownArgs);
if(!unknownArgs.empty())
{
@@ -359,6 +362,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
targetIt!=targetList.GetVector().end();
++targetIt)
{
+
+ if (this->Makefile->IsAlias(targetIt->c_str()))
+ {
+ cmOStringStream e;
+ e << "TARGETS given target \"" << (*targetIt)
+ << "\" which is an alias.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
// Lookup this target in the current directory.
if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str()))
{
@@ -747,6 +759,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
te->RuntimeGenerator = runtimeGenerator;
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
->GetExportSets()[exports.GetString()]->AddTargetExport(te);
+
+ std::vector<std::string> dirs = includesArgs.GetIncludeDirs();
+ if(!dirs.empty())
+ {
+ std::string dirString;
+ const char *sep = "";
+ for (std::vector<std::string>::const_iterator it = dirs.begin();
+ it != dirs.end(); ++it)
+ {
+ te->InterfaceIncludeDirectories += sep;
+ te->InterfaceIncludeDirectories += *it;
+ sep = ";";
+ }
+ }
}
}
@@ -1196,6 +1222,8 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
cmInstallCommandArguments ica(this->DefaultComponentName);
cmCAString exp(&ica.Parser, "EXPORT");
cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
+ cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES",
+ &ica.ArgumentGroup);
cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
exp.Follows(0);
@@ -1268,15 +1296,40 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
}
}
+ cmExportSet *exportSet = this->Makefile->GetLocalGenerator()
+ ->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
+ if (exportOld.IsEnabled())
+ {
+ for(std::vector<cmTargetExport*>::const_iterator
+ tei = exportSet->GetTargetExports()->begin();
+ tei != exportSet->GetTargetExports()->end(); ++tei)
+ {
+ cmTargetExport const* te = *tei;
+ const bool newCMP0022Behavior =
+ te->Target->GetPolicyStatusCMP0022() != cmPolicies::WARN
+ && te->Target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+
+ if(!newCMP0022Behavior)
+ {
+ cmOStringStream e;
+ e << "INSTALL(EXPORT) given keyword \""
+ << "EXPORT_LINK_INTERFACE_LIBRARIES" << "\", but target \""
+ << te->Target->GetName()
+ << "\" does not have policy CMP0022 set to NEW.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
+ }
+ }
+
// Create the export install generator.
cmInstallExportGenerator* exportGenerator =
new cmInstallExportGenerator(
- this->Makefile->GetLocalGenerator()
- ->GetGlobalGenerator()->GetExportSets()[exp.GetString()],
+ exportSet,
ica.GetDestination().c_str(),
ica.GetPermissions().c_str(), ica.GetConfigurations(),
ica.GetComponent().c_str(), fname.c_str(),
- name_space.GetCString(), this->Makefile);
+ name_space.GetCString(), exportOld.IsEnabled(), this->Makefile);
this->Makefile->AddInstallGenerator(exportGenerator);
return true;
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index 7c060090d..65095011f 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -102,6 +102,7 @@ public:
" [[ARCHIVE|LIBRARY|RUNTIME|FRAMEWORK|BUNDLE|\n"
" PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]\n"
" [DESTINATION <dir>]\n"
+ " [INCLUDES DESTINATION [<dir> ...]]\n"
" [PERMISSIONS permissions...]\n"
" [CONFIGURATIONS [Debug|Release|...]]\n"
" [COMPONENT <component>]\n"
@@ -130,6 +131,10 @@ public:
"all target types. If only one is given then only targets of that "
"type will be installed (which can be used to install just a DLL or "
"just an import library)."
+ "The INCLUDES DESTINATION specifies a list of directories which will "
+ "be added to the INTERFACE_INCLUDE_DIRECTORIES of the <targets> when "
+ "exported by install(EXPORT). If a relative path is specified, it is "
+ "treated as relative to the $<INSTALL_PREFIX>."
"\n"
"The PRIVATE_HEADER, PUBLIC_HEADER, and RESOURCE arguments cause "
"subsequent properties to be applied to installing a FRAMEWORK "
@@ -291,6 +296,7 @@ public:
" [NAMESPACE <namespace>] [FILE <name>.cmake]\n"
" [PERMISSIONS permissions...]\n"
" [CONFIGURATIONS [Debug|Release|...]]\n"
+ " [EXPORT_LINK_INTERFACE_LIBRARIES]\n"
" [COMPONENT <component>])\n"
"The EXPORT form generates and installs a CMake file containing code "
"to import targets from the installation tree into another project. "
@@ -306,6 +312,10 @@ public:
"installed when one of the named configurations is installed. "
"Additionally, the generated import file will reference only the "
"matching target configurations. "
+ "The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if present, causes the "
+ "contents of the properties matching "
+ "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? to be exported, when "
+ "policy CMP0022 is NEW. "
"If a COMPONENT option is specified that does not match that given "
"to the targets associated with <export-name> the behavior is "
"undefined. "
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index 8e48f08e6..91ea861a4 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -203,3 +203,37 @@ bool cmInstallCommandArguments::CheckPermissions(
// This is not a valid permission.
return false;
}
+
+cmInstallCommandIncludesArgument::cmInstallCommandIncludesArgument()
+{
+
+}
+
+const std::vector<std::string>&
+cmInstallCommandIncludesArgument::GetIncludeDirs() const
+{
+ return this->IncludeDirs;
+}
+
+void cmInstallCommandIncludesArgument::Parse(
+ const std::vector<std::string>* args,
+ std::vector<std::string>*)
+{
+ if(args->empty())
+ {
+ return;
+ }
+ std::vector<std::string>::const_iterator it = args->begin();
+ ++it;
+ for ( ; it != args->end(); ++it)
+ {
+ std::string dir = *it;
+ if (!cmSystemTools::FileIsFullPath(it->c_str())
+ && cmGeneratorExpression::Find(*it) == std::string::npos)
+ {
+ dir = "$<INSTALL_PREFIX>/" + dir;
+ }
+ cmSystemTools::ConvertToUnixSlashes(dir);
+ this->IncludeDirs.push_back(dir);
+ }
+}
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index 01f7d5679..90347e668 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -65,4 +65,17 @@ class cmInstallCommandArguments
bool CheckPermissions();
};
+class cmInstallCommandIncludesArgument
+{
+ public:
+ cmInstallCommandIncludesArgument();
+ void Parse(const std::vector<std::string>* args,
+ std::vector<std::string>* unconsumedArgs);
+
+ const std::vector<std::string>& GetIncludeDirs() const;
+
+ private:
+ std::vector<std::string> IncludeDirs;
+};
+
#endif
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index 0a645a8fa..3e9e6ac02 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -33,12 +33,14 @@ cmInstallExportGenerator::cmInstallExportGenerator(
std::vector<std::string> const& configurations,
const char* component,
const char* filename, const char* name_space,
+ bool exportOld,
cmMakefile* mf)
:cmInstallGenerator(destination, configurations, component)
,ExportSet(exportSet)
,FilePermissions(file_permissions)
,FileName(filename)
,Namespace(name_space)
+ ,ExportOld(exportOld)
,Makefile(mf)
{
this->EFGen = new cmExportInstallFileGenerator(this);
@@ -137,6 +139,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
// Generate the import file for this export set.
this->EFGen->SetExportFile(this->MainImportFile.c_str());
this->EFGen->SetNamespace(this->Namespace.c_str());
+ this->EFGen->SetExportOld(this->ExportOld);
if(this->ConfigurationTypes->empty())
{
if(this->ConfigurationName && *this->ConfigurationName)
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index 7aff7314c..37b55932f 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -31,7 +31,7 @@ public:
const std::vector<std::string>& configurations,
const char* component,
const char* filename, const char* name_space,
- cmMakefile* mf);
+ bool exportOld, cmMakefile* mf);
~cmInstallExportGenerator();
cmExportSet* GetExportSet() {return this->ExportSet;}
@@ -52,6 +52,7 @@ protected:
std::string FilePermissions;
std::string FileName;
std::string Namespace;
+ bool ExportOld;
cmMakefile* Makefile;
std::string TempDir;
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 5f9b6585e..c9624c8e0 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -198,14 +198,12 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
// Install the whole framework directory.
type = cmInstallType_DIRECTORY;
literal_args += " USE_SOURCE_PERMISSIONS";
- std::string from1 = fromDirConfig + targetName + ".framework";
+
+ std::string from1 = fromDirConfig + targetName;
+ from1 = cmSystemTools::GetFilenamePath(from1);
// Tweaks apply to the binary inside the bundle.
- std::string to1 = toDir + targetName;
- to1 += ".framework/Versions/";
- to1 += this->Target->GetFrameworkVersion();
- to1 += "/";
- to1 += targetName;
+ std::string to1 = toDir + targetNameReal;
filesFrom.push_back(from1);
filesTo.push_back(to1);
@@ -528,7 +526,7 @@ cmInstallTargetGenerator
// components of the install_name field then we need to create a
// mapping to be applied after installation.
std::string for_build = tgt->GetInstallNameDirForBuildTree(config);
- std::string for_install = tgt->GetInstallNameDirForInstallTree(config);
+ std::string for_install = tgt->GetInstallNameDirForInstallTree();
if(for_build != for_install)
{
// The directory portions differ. Append the filename to
@@ -555,7 +553,7 @@ cmInstallTargetGenerator
std::string for_build =
this->Target->GetInstallNameDirForBuildTree(config);
std::string for_install =
- this->Target->GetInstallNameDirForInstallTree(config);
+ this->Target->GetInstallNameDirForInstallTree();
if(this->Target->IsFrameworkOnApple() && for_install.empty())
{
@@ -608,6 +606,12 @@ cmInstallTargetGenerator
return;
}
+ // Skip if on Apple
+ if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
+ {
+ return;
+ }
+
// Get the link information for this target.
// It can provide the RPATH.
cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
@@ -647,30 +651,62 @@ cmInstallTargetGenerator
return;
}
- // Construct the original rpath string to be replaced.
- std::string oldRpath = cli->GetRPathString(false);
-
- // Get the install RPATH from the link information.
- std::string newRpath = cli->GetChrpathString();
-
- // Skip the rule if the paths are identical
- if(oldRpath == newRpath)
+ if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
{
- return;
- }
+ // If using install_name_tool, set up the rules to modify the rpaths.
+ std::string installNameTool =
+ this->Target->GetMakefile()->
+ GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL");
+
+ std::vector<std::string> oldRuntimeDirs, newRuntimeDirs;
+ cli->GetRPath(oldRuntimeDirs, false);
+ cli->GetRPath(newRuntimeDirs, true);
+
+ // Note: These are separate commands to avoid install_name_tool
+ // corruption on 10.6.
+ for(std::vector<std::string>::const_iterator i = oldRuntimeDirs.begin();
+ i != oldRuntimeDirs.end(); ++i)
+ {
+ os << indent << "execute_process(COMMAND " << installNameTool << "\n";
+ os << indent << " -delete_rpath \"" << *i << "\"\n";
+ os << indent << " \"" << toDestDirPath << "\")\n";
+ }
- // Write a rule to run chrpath to set the install-tree RPATH
- if(newRpath.empty())
- {
- os << indent << "FILE(RPATH_REMOVE\n"
- << indent << " FILE \"" << toDestDirPath << "\")\n";
+ for(std::vector<std::string>::const_iterator i = newRuntimeDirs.begin();
+ i != newRuntimeDirs.end(); ++i)
+ {
+ os << indent << "execute_process(COMMAND " << installNameTool << "\n";
+ os << indent << " -add_rpath \"" << *i << "\"\n";
+ os << indent << " \"" << toDestDirPath << "\")\n";
+ }
}
else
{
- os << indent << "FILE(RPATH_CHANGE\n"
- << indent << " FILE \"" << toDestDirPath << "\"\n"
- << indent << " OLD_RPATH \"" << oldRpath << "\"\n"
- << indent << " NEW_RPATH \"" << newRpath << "\")\n";
+ // Construct the original rpath string to be replaced.
+ std::string oldRpath = cli->GetRPathString(false);
+
+ // Get the install RPATH from the link information.
+ std::string newRpath = cli->GetChrpathString();
+
+ // Skip the rule if the paths are identical
+ if(oldRpath == newRpath)
+ {
+ return;
+ }
+
+ // Write a rule to run chrpath to set the install-tree RPATH
+ if(newRpath.empty())
+ {
+ os << indent << "FILE(RPATH_REMOVE\n"
+ << indent << " FILE \"" << toDestDirPath << "\")\n";
+ }
+ else
+ {
+ os << indent << "FILE(RPATH_CHANGE\n"
+ << indent << " FILE \"" << toDestDirPath << "\"\n"
+ << indent << " OLD_RPATH \"" << oldRpath << "\"\n"
+ << indent << " NEW_RPATH \"" << newRpath << "\")\n";
+ }
}
}
@@ -681,9 +717,9 @@ cmInstallTargetGenerator::AddStripRule(std::ostream& os,
const std::string& toDestDirPath)
{
- // don't strip static libraries, because it removes the only symbol table
- // they have so you can't link to them anymore
- if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
+ // don't strip static and import libraries, because it removes the only
+ // symbol table they have so you can't link to them anymore
+ if(this->Target->GetType()==cmTarget::STATIC_LIBRARY || this->ImportLibrary)
{
return;
}
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 36d84f3be..898f379ad 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -22,45 +22,58 @@
# pragma warn -8060 /* possibly incorrect assignment */
#endif
-bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
- cmListFileFunction& function,
- const char* filename);
+//----------------------------------------------------------------------------
+struct cmListFileParser
+{
+ cmListFileParser(cmListFile* lf, cmMakefile* mf, const char* filename);
+ ~cmListFileParser();
+ bool ParseFile();
+ bool ParseFunction(const char* name, long line);
+ void AddArgument(cmListFileLexer_Token* token,
+ cmListFileArgument::Delimiter delim);
+ cmListFile* ListFile;
+ cmMakefile* Makefile;
+ const char* FileName;
+ cmListFileLexer* Lexer;
+ cmListFileFunction Function;
+ enum { SeparationOkay, SeparationWarning } Separation;
+};
-bool cmListFile::ParseFile(const char* filename,
- bool topLevel,
- cmMakefile *mf)
+//----------------------------------------------------------------------------
+cmListFileParser::cmListFileParser(cmListFile* lf, cmMakefile* mf,
+ const char* filename):
+ ListFile(lf), Makefile(mf), FileName(filename),
+ Lexer(cmListFileLexer_New())
{
- if(!cmSystemTools::FileExists(filename))
- {
- return false;
- }
+}
- // Create the scanner.
- cmListFileLexer* lexer = cmListFileLexer_New();
- if(!lexer)
- {
- cmSystemTools::Error("cmListFileCache: error allocating lexer ");
- return false;
- }
+//----------------------------------------------------------------------------
+cmListFileParser::~cmListFileParser()
+{
+ cmListFileLexer_Delete(this->Lexer);
+}
+//----------------------------------------------------------------------------
+bool cmListFileParser::ParseFile()
+{
// Open the file.
- if(!cmListFileLexer_SetFileName(lexer, filename))
+ if(!cmListFileLexer_SetFileName(this->Lexer, this->FileName))
{
- cmListFileLexer_Delete(lexer);
cmSystemTools::Error("cmListFileCache: error can not open file ",
- filename);
+ this->FileName);
return false;
}
// Use a simple recursive-descent parser to process the token
// stream.
- this->ModifiedTime = cmSystemTools::ModifiedTime(filename);
- bool parseError = false;
bool haveNewline = true;
- cmListFileLexer_Token* token;
- while(!parseError && (token = cmListFileLexer_Scan(lexer)))
+ while(cmListFileLexer_Token* token =
+ cmListFileLexer_Scan(this->Lexer))
{
- if(token->type == cmListFileLexer_Token_Newline)
+ if(token->type == cmListFileLexer_Token_Space)
+ {
+ }
+ else if(token->type == cmListFileLexer_Token_Newline)
{
haveNewline = true;
}
@@ -69,51 +82,66 @@ bool cmListFile::ParseFile(const char* filename,
if(haveNewline)
{
haveNewline = false;
- cmListFileFunction inFunction;
- inFunction.Name = token->text;
- inFunction.FilePath = filename;
- inFunction.Line = token->line;
- if(cmListFileCacheParseFunction(lexer, inFunction, filename))
+ if(this->ParseFunction(token->text, token->line))
{
- this->Functions.push_back(inFunction);
+ this->ListFile->Functions.push_back(this->Function);
}
else
{
- parseError = true;
+ return false;
}
}
else
{
cmOStringStream error;
error << "Error in cmake code at\n"
- << filename << ":" << token->line << ":\n"
+ << this->FileName << ":" << token->line << ":\n"
<< "Parse error. Expected a newline, got "
- << cmListFileLexer_GetTypeAsString(lexer, token->type)
+ << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
cmSystemTools::Error(error.str().c_str());
- parseError = true;
+ return false;
}
}
else
{
cmOStringStream error;
error << "Error in cmake code at\n"
- << filename << ":" << token->line << ":\n"
+ << this->FileName << ":" << token->line << ":\n"
<< "Parse error. Expected a command name, got "
- << cmListFileLexer_GetTypeAsString(lexer, token->type)
+ << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \""
<< token->text << "\".";
cmSystemTools::Error(error.str().c_str());
- parseError = true;
+ return false;
}
}
- if (parseError)
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmListFile::ParseFile(const char* filename,
+ bool topLevel,
+ cmMakefile *mf)
+{
+ if(!cmSystemTools::FileExists(filename))
+ {
+ return false;
+ }
+
+ bool parseError = false;
+ this->ModifiedTime = cmSystemTools::ModifiedTime(filename);
+
+ {
+ cmListFileParser parser(this, mf, filename);
+ parseError = !parser.ParseFile();
+ }
+
+ if(parseError)
{
this->ModifiedTime = 0;
}
- cmListFileLexer_Delete(lexer);
-
// do we need a cmake_policy(VERSION call?
if(topLevel)
{
@@ -196,7 +224,8 @@ bool cmListFile::ParseFile(const char* filename,
{
cmListFileFunction project;
project.Name = "PROJECT";
- cmListFileArgument prj("Project", false, filename, 0);
+ cmListFileArgument prj("Project", cmListFileArgument::Unquoted,
+ filename, 0);
project.Arguments.push_back(prj);
this->Functions.insert(this->Functions.begin(),project);
}
@@ -208,17 +237,24 @@ bool cmListFile::ParseFile(const char* filename,
return true;
}
-bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
- cmListFileFunction& function,
- const char* filename)
+//----------------------------------------------------------------------------
+bool cmListFileParser::ParseFunction(const char* name, long line)
{
+ // Inintialize a new function call.
+ this->Function = cmListFileFunction();
+ this->Function.FilePath = this->FileName;
+ this->Function.Name = name;
+ this->Function.Line = line;
+
// Command name has already been parsed. Read the left paren.
cmListFileLexer_Token* token;
- if(!(token = cmListFileLexer_Scan(lexer)))
+ while((token = cmListFileLexer_Scan(this->Lexer)) &&
+ token->type == cmListFileLexer_Token_Space) {}
+ if(!token)
{
cmOStringStream error;
- error << "Error in cmake code at\n"
- << filename << ":" << cmListFileLexer_GetCurrentLine(lexer) << ":\n"
+ error << "Error in cmake code at\n" << this->FileName << ":"
+ << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
<< "Parse error. Function missing opening \"(\".";
cmSystemTools::Error(error.str().c_str());
return false;
@@ -226,26 +262,33 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
if(token->type != cmListFileLexer_Token_ParenLeft)
{
cmOStringStream error;
- error << "Error in cmake code at\n"
- << filename << ":" << cmListFileLexer_GetCurrentLine(lexer) << ":\n"
+ error << "Error in cmake code at\n" << this->FileName << ":"
+ << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
<< "Parse error. Expected \"(\", got "
- << cmListFileLexer_GetTypeAsString(lexer, token->type)
+ << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
cmSystemTools::Error(error.str().c_str());
return false;
}
// Arguments.
- unsigned long lastLine = cmListFileLexer_GetCurrentLine(lexer);
+ unsigned long lastLine;
unsigned long parenDepth = 0;
- while((token = cmListFileLexer_Scan(lexer)))
+ this->Separation = SeparationOkay;
+ while((lastLine = cmListFileLexer_GetCurrentLine(this->Lexer),
+ token = cmListFileLexer_Scan(this->Lexer)))
{
+ if(token->type == cmListFileLexer_Token_Space ||
+ token->type == cmListFileLexer_Token_Newline)
+ {
+ this->Separation = SeparationOkay;
+ continue;
+ }
if(token->type == cmListFileLexer_Token_ParenLeft)
{
parenDepth++;
- cmListFileArgument a("(",
- false, filename, token->line);
- function.Arguments.push_back(a);
+ this->Separation = SeparationOkay;
+ this->AddArgument(token, cmListFileArgument::Unquoted);
}
else if(token->type == cmListFileLexer_Token_ParenRight)
{
@@ -254,43 +297,39 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
return true;
}
parenDepth--;
- cmListFileArgument a(")",
- false, filename, token->line);
- function.Arguments.push_back(a);
+ this->Separation = SeparationOkay;
+ this->AddArgument(token, cmListFileArgument::Unquoted);
+ this->Separation = SeparationWarning;
}
else if(token->type == cmListFileLexer_Token_Identifier ||
token->type == cmListFileLexer_Token_ArgumentUnquoted)
{
- cmListFileArgument a(token->text,
- false, filename, token->line);
- function.Arguments.push_back(a);
+ this->AddArgument(token, cmListFileArgument::Unquoted);
+ this->Separation = SeparationWarning;
}
else if(token->type == cmListFileLexer_Token_ArgumentQuoted)
{
- cmListFileArgument a(token->text,
- true, filename, token->line);
- function.Arguments.push_back(a);
+ this->AddArgument(token, cmListFileArgument::Quoted);
+ this->Separation = SeparationWarning;
}
- else if(token->type != cmListFileLexer_Token_Newline)
+ else
{
// Error.
cmOStringStream error;
- error << "Error in cmake code at\n"
- << filename << ":" << cmListFileLexer_GetCurrentLine(lexer)
- << ":\n"
+ error << "Error in cmake code at\n" << this->FileName << ":"
+ << cmListFileLexer_GetCurrentLine(this->Lexer) << ":\n"
<< "Parse error. Function missing ending \")\". "
<< "Instead found "
- << cmListFileLexer_GetTypeAsString(lexer, token->type)
+ << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
<< " with text \"" << token->text << "\".";
cmSystemTools::Error(error.str().c_str());
return false;
}
- lastLine = cmListFileLexer_GetCurrentLine(lexer);
}
cmOStringStream error;
error << "Error in cmake code at\n"
- << filename << ":" << lastLine << ":\n"
+ << this->FileName << ":" << lastLine << ":\n"
<< "Parse error. Function missing ending \")\". "
<< "End of file reached.";
cmSystemTools::Error(error.str().c_str());
@@ -299,6 +338,45 @@ bool cmListFileCacheParseFunction(cmListFileLexer* lexer,
}
//----------------------------------------------------------------------------
+void cmListFileParser::AddArgument(cmListFileLexer_Token* token,
+ cmListFileArgument::Delimiter delim)
+{
+ cmListFileArgument a(token->text, delim, this->FileName, token->line);
+ this->Function.Arguments.push_back(a);
+ if(delim == cmListFileArgument::Unquoted)
+ {
+ // Warn about a future behavior change.
+ const char* c = a.Value.c_str();
+ if(*c++ == '[')
+ {
+ while(*c == '=')
+ { ++c; }
+ if(*c == '[')
+ {
+ cmOStringStream m;
+ m << "Syntax Warning in cmake code at\n"
+ << " " << this->FileName << ":" << token->line << ":"
+ << token->column << "\n"
+ << "A future version of CMake may treat unquoted argument:\n"
+ << " " << a.Value << "\n"
+ << "as an opening long bracket. Double-quote the argument.";
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str().c_str());
+ }
+ }
+ }
+ if(this->Separation == SeparationOkay)
+ {
+ return;
+ }
+ cmOStringStream m;
+ m << "Syntax Warning in cmake code at\n"
+ << " " << this->FileName << ":" << token->line << ":"
+ << token->column << "\n"
+ << "Argument not separated from preceding token by whitespace.";
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, m.str().c_str());
+}
+
+//----------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
{
os << lfc.FilePath;
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index fec3d07d8..7bb3b346c 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -25,22 +25,27 @@ class cmMakefile;
struct cmListFileArgument
{
- cmListFileArgument(): Value(), Quoted(false), FilePath(0), Line(0) {}
+ enum Delimiter
+ {
+ Unquoted,
+ Quoted
+ };
+ cmListFileArgument(): Value(), Delim(Unquoted), FilePath(0), Line(0) {}
cmListFileArgument(const cmListFileArgument& r):
- Value(r.Value), Quoted(r.Quoted), FilePath(r.FilePath), Line(r.Line) {}
- cmListFileArgument(const std::string& v, bool q, const char* file,
- long line): Value(v), Quoted(q),
+ Value(r.Value), Delim(r.Delim), FilePath(r.FilePath), Line(r.Line) {}
+ cmListFileArgument(const std::string& v, Delimiter d, const char* file,
+ long line): Value(v), Delim(d),
FilePath(file), Line(line) {}
bool operator == (const cmListFileArgument& r) const
{
- return (this->Value == r.Value) && (this->Quoted == r.Quoted);
+ return (this->Value == r.Value) && (this->Delim == r.Delim);
}
bool operator != (const cmListFileArgument& r) const
{
return !(*this == r);
}
std::string Value;
- bool Quoted;
+ Delimiter Delim;
const char* FilePath;
long Line;
};
diff --git a/Source/cmListFileLexer.c b/Source/cmListFileLexer.c
index b6424d60e..2841fe511 100644
--- a/Source/cmListFileLexer.c
+++ b/Source/cmListFileLexer.c
@@ -9,7 +9,7 @@
#define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 31
+#define YY_FLEX_SUBMINOR_VERSION 35
#if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA
#endif
@@ -31,7 +31,15 @@
/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
#include <inttypes.h>
typedef int8_t flex_int8_t;
typedef uint8_t flex_uint8_t;
@@ -46,7 +54,6 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -77,6 +84,8 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#endif /* ! C99 */
+
#endif /* ! FLEXINT_H */
#ifdef __cplusplus
@@ -86,11 +95,12 @@ typedef unsigned int flex_uint32_t;
#else /* ! __cplusplus */
-#if __STDC__
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
#define YY_USE_CONST
-#endif /* __STDC__ */
+#endif /* defined (__STDC__) */
#endif /* ! __cplusplus */
#ifdef YY_USE_CONST
@@ -126,8 +136,6 @@ typedef void* yyscan_t;
#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
#define yy_flex_debug yyg->yy_flex_debug_r
-int cmListFileLexer_yylex_init (yyscan_t* scanner);
-
/* Enter a start condition. This macro really ought to take a parameter,
* but we do it the disgusting crufty way forced on us by the ()-less
* definition of BEGIN.
@@ -151,9 +159,21 @@ int cmListFileLexer_yylex_init (yyscan_t* scanner);
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
#endif
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
#ifndef YY_TYPEDEF_YY_BUFFER_STATE
#define YY_TYPEDEF_YY_BUFFER_STATE
typedef struct yy_buffer_state *YY_BUFFER_STATE;
@@ -192,14 +212,9 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
} \
while ( 0 )
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-
#ifndef YY_TYPEDEF_YY_SIZE_T
#define YY_TYPEDEF_YY_SIZE_T
-typedef unsigned int yy_size_t;
+typedef size_t yy_size_t;
#endif
#ifndef YY_STRUCT_YY_BUFFER_STATE
@@ -354,8 +369,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
*yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 14
-#define YY_END_OF_BUFFER 15
+#define YY_NUM_RULES 16
+#define YY_END_OF_BUFFER 17
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -363,12 +378,13 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[39] =
+static yyconst flex_int16_t yy_accept[45] =
{ 0,
- 0, 0, 0, 0, 15, 6, 12, 1, 7, 2,
- 6, 3, 4, 6, 13, 8, 9, 10, 11, 6,
- 0, 6, 0, 2, 0, 5, 6, 8, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 17, 6, 14, 1, 8, 2,
+ 6, 3, 4, 6, 15, 9, 11, 12, 13, 6,
+ 0, 6, 0, 14, 2, 0, 5, 6, 9, 0,
+ 10, 0, 7, 0, 0, 0, 7, 0, 7, 0,
+ 0, 0, 0, 0
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -405,64 +421,70 @@ static yyconst flex_int32_t yy_ec[256] =
static yyconst flex_int32_t yy_meta[13] =
{ 0,
- 1, 1, 2, 1, 3, 1, 1, 1, 4, 4,
- 4, 1
+ 1, 2, 3, 2, 4, 1, 1, 1, 5, 5,
+ 5, 1
} ;
-static yyconst flex_int16_t yy_base[48] =
+static yyconst flex_int16_t yy_base[56] =
{ 0,
- 0, 0, 10, 20, 34, 32, 89, 89, 89, 0,
- 23, 89, 89, 35, 0, 18, 89, 89, 44, 0,
- 49, 21, 0, 0, 19, 0, 0, 15, 59, 0,
- 18, 0, 15, 12, 11, 10, 9, 89, 64, 68,
- 72, 76, 80, 13, 84, 12, 10
+ 0, 0, 10, 20, 38, 32, 0, 109, 109, 0,
+ 28, 109, 109, 35, 0, 23, 109, 109, 44, 0,
+ 49, 26, 0, 0, 0, 22, 0, 0, 18, 24,
+ 109, 0, 61, 20, 0, 18, 0, 17, 16, 0,
+ 12, 11, 10, 109, 73, 16, 78, 83, 88, 93,
+ 12, 98, 11, 103, 9
} ;
-static yyconst flex_int16_t yy_def[48] =
+static yyconst flex_int16_t yy_def[56] =
{ 0,
- 38, 1, 39, 39, 38, 38, 38, 38, 38, 40,
- 6, 38, 38, 6, 41, 42, 38, 38, 42, 6,
- 38, 6, 43, 40, 44, 14, 6, 42, 42, 21,
- 21, 45, 46, 44, 47, 46, 47, 0, 38, 38,
- 38, 38, 38, 38, 38, 38, 38
+ 44, 1, 45, 45, 44, 44, 46, 44, 44, 47,
+ 6, 44, 44, 6, 48, 49, 44, 44, 49, 6,
+ 44, 6, 50, 46, 47, 51, 14, 6, 49, 49,
+ 44, 21, 44, 21, 52, 53, 33, 51, 33, 54,
+ 55, 53, 55, 0, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44
} ;
-static yyconst flex_int16_t yy_nxt[102] =
+static yyconst flex_int16_t yy_nxt[122] =
{ 0,
6, 7, 8, 7, 9, 10, 11, 12, 13, 6,
- 14, 15, 17, 37, 18, 36, 34, 30, 20, 30,
- 27, 19, 17, 20, 18, 35, 29, 27, 33, 29,
- 25, 19, 20, 38, 38, 38, 21, 38, 22, 38,
- 38, 20, 20, 23, 26, 26, 28, 38, 28, 30,
- 30, 38, 38, 20, 38, 31, 38, 38, 30, 30,
- 32, 28, 38, 28, 16, 16, 16, 16, 24, 38,
- 24, 24, 27, 38, 27, 27, 28, 38, 38, 28,
- 20, 38, 20, 20, 30, 38, 30, 30, 5, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-
- 38
+ 14, 15, 17, 43, 18, 42, 38, 24, 32, 33,
+ 32, 19, 17, 36, 18, 37, 33, 41, 29, 30,
+ 37, 19, 20, 36, 30, 26, 21, 44, 22, 44,
+ 44, 20, 20, 23, 27, 27, 31, 44, 29, 32,
+ 32, 44, 44, 33, 44, 34, 44, 44, 32, 32,
+ 35, 33, 44, 44, 44, 21, 44, 39, 44, 44,
+ 33, 33, 40, 16, 16, 16, 16, 16, 25, 25,
+ 44, 25, 25, 28, 28, 44, 28, 28, 29, 29,
+ 44, 44, 29, 20, 20, 44, 20, 20, 32, 32,
+
+ 44, 32, 32, 33, 33, 44, 33, 33, 5, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44
} ;
-static yyconst flex_int16_t yy_chk[102] =
+static yyconst flex_int16_t yy_chk[122] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 3, 47, 3, 46, 44, 37, 36, 35,
- 34, 3, 4, 33, 4, 31, 28, 25, 22, 16,
- 11, 4, 6, 5, 0, 0, 6, 0, 6, 0,
+ 1, 1, 3, 55, 3, 53, 51, 46, 43, 42,
+ 41, 3, 4, 39, 4, 38, 36, 34, 30, 29,
+ 26, 4, 6, 22, 16, 11, 6, 5, 6, 0,
0, 6, 6, 6, 14, 14, 19, 0, 19, 21,
21, 0, 0, 21, 0, 21, 0, 0, 21, 21,
- 21, 29, 0, 29, 39, 39, 39, 39, 40, 0,
- 40, 40, 41, 0, 41, 41, 42, 0, 0, 42,
- 43, 0, 43, 43, 45, 0, 45, 45, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
-
- 38
+ 21, 33, 0, 0, 0, 33, 0, 33, 0, 0,
+ 33, 33, 33, 45, 45, 45, 45, 45, 47, 47,
+ 0, 47, 47, 48, 48, 0, 48, 48, 49, 49,
+ 0, 0, 49, 50, 50, 0, 50, 50, 52, 52,
+
+ 0, 52, 52, 54, 54, 0, 54, 54, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44
} ;
/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[15] =
+static yyconst flex_int32_t yy_rule_can_match_eol[17] =
{ 0,
-1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, };
+1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, };
/* The intent behind this definition is that it'll catch
* any uses of REJECT which flex missed.
@@ -494,9 +516,11 @@ Run flex like this:
Modify cmListFileLexer.c:
- remove TABs
+ - remove use of the 'register' storage class specifier
- remove the yyunput function
- add a statement "(void)yyscanner;" to the top of these methods:
yy_fatal_error, cmListFileLexer_yyalloc, cmListFileLexer_yyrealloc, cmListFileLexer_yyfree
+ - remove statement "yyscanner = NULL;" from cmListFileLexer_yylex_destroy
- remove all YY_BREAK lines occurring right after return statements
- remove the isatty forward declaration
@@ -540,7 +564,7 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer);
/*--------------------------------------------------------------------------*/
-#line 568 "cmListFileLexer.c"
+#line 570 "cmListFileLexer.c"
#define INITIAL 0
#define STRING 1
@@ -591,6 +615,12 @@ struct yyguts_t
}; /* end struct yyguts_t */
+static int yy_init_globals (yyscan_t yyscanner );
+
+int cmListFileLexer_yylex_init (yyscan_t* scanner);
+
+int cmListFileLexer_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
/* Accessor methods to globals.
These are made visible to non-reentrant scanners for convenience. */
@@ -620,6 +650,10 @@ int cmListFileLexer_yyget_lineno (yyscan_t yyscanner );
void cmListFileLexer_yyset_lineno (int line_number ,yyscan_t yyscanner );
+int cmListFileLexer_yyget_column (yyscan_t yyscanner );
+
+void cmListFileLexer_yyset_column (int column_no ,yyscan_t yyscanner );
+
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
@@ -652,7 +686,12 @@ static int input (yyscan_t yyscanner );
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
#endif
/* Copy whatever the last rule matched to the standard output. */
@@ -660,7 +699,7 @@ static int input (yyscan_t yyscanner );
/* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite().
*/
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
#endif
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
@@ -749,19 +788,19 @@ extern int cmListFileLexer_yylex (yyscan_t yyscanner);
*/
YY_DECL
{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
+ yy_state_type yy_current_state;
+ char *yy_cp, *yy_bp;
+ int yy_act;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
-#line 100 "cmListFileLexer.in.l"
+#line 82 "cmListFileLexer.in.l"
-#line 787 "cmListFileLexer.c"
+#line 804 "cmListFileLexer.c"
- if ( yyg->yy_init )
+ if ( !yyg->yy_init )
{
- yyg->yy_init = 0;
+ yyg->yy_init = 1;
#ifdef YY_USER_INIT
YY_USER_INIT;
@@ -801,7 +840,7 @@ YY_DECL
yy_match:
do
{
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -810,13 +849,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 39 )
+ if ( yy_current_state >= 45 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 89 );
+ while ( yy_base[yy_current_state] != 109 );
yy_find_action:
yy_act = yy_accept[yy_current_state];
@@ -855,7 +894,7 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
/* rule 1 can match eol */
YY_RULE_SETUP
-#line 102 "cmListFileLexer.in.l"
+#line 84 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_Newline;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -865,14 +904,14 @@ YY_RULE_SETUP
}
case 2:
YY_RULE_SETUP
-#line 110 "cmListFileLexer.in.l"
+#line 92 "cmListFileLexer.in.l"
{
lexer->column += yyleng;
}
YY_BREAK
case 3:
YY_RULE_SETUP
-#line 114 "cmListFileLexer.in.l"
+#line 96 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ParenLeft;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -881,7 +920,7 @@ YY_RULE_SETUP
}
case 4:
YY_RULE_SETUP
-#line 121 "cmListFileLexer.in.l"
+#line 103 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ParenRight;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -890,7 +929,7 @@ YY_RULE_SETUP
}
case 5:
YY_RULE_SETUP
-#line 128 "cmListFileLexer.in.l"
+#line 110 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_Identifier;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -899,7 +938,7 @@ YY_RULE_SETUP
}
case 6:
YY_RULE_SETUP
-#line 135 "cmListFileLexer.in.l"
+#line 117 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -908,7 +947,16 @@ YY_RULE_SETUP
}
case 7:
YY_RULE_SETUP
-#line 142 "cmListFileLexer.in.l"
+#line 124 "cmListFileLexer.in.l"
+{
+ lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+case 8:
+YY_RULE_SETUP
+#line 131 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_ArgumentQuoted;
cmListFileLexerSetToken(lexer, "", 0);
@@ -916,58 +964,69 @@ YY_RULE_SETUP
BEGIN(STRING);
}
YY_BREAK
-case 8:
-/* rule 8 can match eol */
+case 9:
YY_RULE_SETUP
-#line 149 "cmListFileLexer.in.l"
+#line 138 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
YY_BREAK
-case 9:
-/* rule 9 can match eol */
+case 10:
+/* rule 10 can match eol */
YY_RULE_SETUP
-#line 154 "cmListFileLexer.in.l"
+#line 143 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
++lexer->line;
lexer->column = 1;
}
YY_BREAK
-case 10:
+case 11:
+/* rule 11 can match eol */
+YY_RULE_SETUP
+#line 149 "cmListFileLexer.in.l"
+{
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ ++lexer->line;
+ lexer->column = 1;
+}
+ YY_BREAK
+case 12:
YY_RULE_SETUP
-#line 160 "cmListFileLexer.in.l"
+#line 155 "cmListFileLexer.in.l"
{
lexer->column += yyleng;
BEGIN(INITIAL);
return 1;
}
-case 11:
+case 13:
YY_RULE_SETUP
-#line 166 "cmListFileLexer.in.l"
+#line 161 "cmListFileLexer.in.l"
{
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
YY_BREAK
case YY_STATE_EOF(STRING):
-#line 171 "cmListFileLexer.in.l"
+#line 166 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_BadString;
BEGIN(INITIAL);
return 1;
}
-case 12:
+case 14:
YY_RULE_SETUP
-#line 177 "cmListFileLexer.in.l"
+#line 172 "cmListFileLexer.in.l"
{
+ lexer->token.type = cmListFileLexer_Token_Space;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
lexer->column += yyleng;
+ return 1;
}
- YY_BREAK
-case 13:
+case 15:
YY_RULE_SETUP
-#line 181 "cmListFileLexer.in.l"
+#line 179 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_BadCharacter;
cmListFileLexerSetToken(lexer, yytext, yyleng);
@@ -975,18 +1034,18 @@ YY_RULE_SETUP
return 1;
}
case YY_STATE_EOF(INITIAL):
-#line 188 "cmListFileLexer.in.l"
+#line 186 "cmListFileLexer.in.l"
{
lexer->token.type = cmListFileLexer_Token_None;
cmListFileLexerSetToken(lexer, 0, 0);
return 0;
}
-case 14:
+case 16:
YY_RULE_SETUP
-#line 194 "cmListFileLexer.in.l"
+#line 192 "cmListFileLexer.in.l"
ECHO;
YY_BREAK
-#line 1025 "cmListFileLexer.c"
+#line 1064 "cmListFileLexer.c"
case YY_END_OF_BUFFER:
{
@@ -1127,9 +1186,9 @@ ECHO;
static int yy_get_next_buffer (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = yyg->yytext_ptr;
- register int number_to_move, i;
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ char *source = yyg->yytext_ptr;
+ int number_to_move, i;
int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@@ -1171,7 +1230,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
{
- size_t num_to_read =
+ int num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 )
@@ -1216,7 +1275,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Read in more data. */
YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
- yyg->yy_n_chars, num_to_read );
+ yyg->yy_n_chars, (size_t) num_to_read );
YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
}
@@ -1240,6 +1299,14 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else
ret_val = EOB_ACT_CONTINUE_SCAN;
+ if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cmListFileLexer_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
yyg->yy_n_chars += number_to_move;
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
@@ -1253,15 +1320,15 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
{
- register yy_state_type yy_current_state;
- register char *yy_cp;
+ yy_state_type yy_current_state;
+ char *yy_cp;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
yy_current_state = yyg->yy_start;
for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
{
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1270,7 +1337,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 39 )
+ if ( yy_current_state >= 45 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1286,11 +1353,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
*/
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
{
- register int yy_is_jam;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
- register char *yy_cp = yyg->yy_c_buf_p;
+ int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+ char *yy_cp = yyg->yy_c_buf_p;
- register YY_CHAR yy_c = 1;
+ YY_CHAR yy_c = 1;
if ( yy_accept[yy_current_state] )
{
yyg->yy_last_accepting_state = yy_current_state;
@@ -1299,11 +1366,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 39 )
+ if ( yy_current_state >= 45 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 38);
+ yy_is_jam = (yy_current_state == 44);
return yy_is_jam ? 0 : yy_current_state;
}
@@ -1633,6 +1700,8 @@ static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
yyg->yy_buffer_stack = (struct yy_buffer_state**)cmListFileLexer_yyalloc
(num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" );
memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
@@ -1651,6 +1720,8 @@ static void cmListFileLexer_yyensure_buffer_stack (yyscan_t yyscanner)
(yyg->yy_buffer_stack,
num_to_alloc * sizeof(struct yy_buffer_state*)
, yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yyensure_buffer_stack()" );
/* zero only the new slots.*/
memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
@@ -1695,26 +1766,26 @@ YY_BUFFER_STATE cmListFileLexer_yy_scan_buffer (char * base, yy_size_t size ,
/** Setup the input buffer state to scan a string. The next call to cmListFileLexer_yylex() will
* scan from a @e copy of @a str.
- * @param str a NUL-terminated string to scan
+ * @param yystr a NUL-terminated string to scan
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
* @note If you want to scan bytes that may contain NUL values, then use
* cmListFileLexer_yy_scan_bytes() instead.
*/
-YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yy_str , yyscan_t yyscanner)
+YY_BUFFER_STATE cmListFileLexer_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
{
- return cmListFileLexer_yy_scan_bytes(yy_str,strlen(yy_str) ,yyscanner);
+ return cmListFileLexer_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
}
/** Setup the input buffer state to scan the given bytes. The next call to cmListFileLexer_yylex() will
* scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
* @param yyscanner The scanner object.
* @return the newly allocated buffer state object.
*/
-YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * bytes, int len , yyscan_t yyscanner)
+YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{
YY_BUFFER_STATE b;
char *buf;
@@ -1722,15 +1793,15 @@ YY_BUFFER_STATE cmListFileLexer_yy_scan_bytes (yyconst char * bytes, int len ,
int i;
/* Get memory for full buffer, including space for trailing EOB's. */
- n = len + 2;
+ n = _yybytes_len + 2;
buf = (char *) cmListFileLexer_yyalloc(n ,yyscanner );
if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in cmListFileLexer_yy_scan_bytes()" );
- for ( i = 0; i < len; ++i )
- buf[i] = bytes[i];
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
- buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
b = cmListFileLexer_yy_scan_buffer(buf,n ,yyscanner);
if ( ! b )
@@ -1918,21 +1989,87 @@ void cmListFileLexer_yyset_debug (int bdebug , yyscan_t yyscanner)
/* Accessor methods for yylval and yylloc */
+/* User-visible API */
+
+/* cmListFileLexer_yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int cmListFileLexer_yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* cmListFileLexer_yylex_init_extra has the same functionality as cmListFileLexer_yylex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to cmListFileLexer_yyalloc in
+ * the yyextra field.
+ */
+
+int cmListFileLexer_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+ struct yyguts_t dummy_yyguts;
+
+ cmListFileLexer_yyset_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ cmListFileLexer_yyset_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
static int yy_init_globals (yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
/* Initialization is the same as for the non-reentrant scanner.
- This function is called once per scanner lifetime. */
+ * This function is called from cmListFileLexer_yylex_destroy(), so don't allocate here.
+ */
yyg->yy_buffer_stack = 0;
yyg->yy_buffer_stack_top = 0;
yyg->yy_buffer_stack_max = 0;
yyg->yy_c_buf_p = (char *) 0;
- yyg->yy_init = 1;
+ yyg->yy_init = 0;
yyg->yy_start = 0;
+
yyg->yy_start_stack_ptr = 0;
yyg->yy_start_stack_depth = 0;
- yyg->yy_start_stack = (int *) 0;
+ yyg->yy_start_stack = NULL;
/* Defined in main.c */
#ifdef YY_STDINIT
@@ -1949,33 +2086,6 @@ static int yy_init_globals (yyscan_t yyscanner)
return 0;
}
-/* User-visible API */
-
-/* cmListFileLexer_yylex_init is special because it creates the scanner itself, so it is
- * the ONLY reentrant function that doesn't take the scanner as the last argument.
- * That's why we explicitly handle the declaration, instead of using our macros.
- */
-
-int cmListFileLexer_yylex_init(yyscan_t* ptr_yy_globals)
-
-{
- if (ptr_yy_globals == NULL){
- errno = EINVAL;
- return 1;
- }
-
- *ptr_yy_globals = (yyscan_t) cmListFileLexer_yyalloc ( sizeof( struct yyguts_t ), NULL );
-
- if (*ptr_yy_globals == NULL){
- errno = ENOMEM;
- return 1;
- }
-
- memset(*ptr_yy_globals,0,sizeof(struct yyguts_t));
-
- return yy_init_globals ( *ptr_yy_globals );
-}
-
/* cmListFileLexer_yylex_destroy is for both reentrant and non-reentrant scanners. */
int cmListFileLexer_yylex_destroy (yyscan_t yyscanner)
{
@@ -1996,6 +2106,10 @@ int cmListFileLexer_yylex_destroy (yyscan_t yyscanner)
cmListFileLexer_yyfree(yyg->yy_start_stack ,yyscanner );
yyg->yy_start_stack = NULL;
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * cmListFileLexer_yylex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
/* Destroy the main struct (reentrant only). */
cmListFileLexer_yyfree ( yyscanner , yyscanner );
return 0;
@@ -2008,8 +2122,7 @@ int cmListFileLexer_yylex_destroy (yyscan_t yyscanner)
#ifndef yytext_ptr
static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
{
- register int i;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ int i;
for ( i = 0; i < n; ++i )
s1[i] = s2[i];
}
@@ -2018,8 +2131,7 @@ static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yysca
#ifdef YY_NEED_STRLEN
static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
{
- register int n;
- struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ int n;
for ( n = 0; s[n]; ++n )
;
@@ -2054,19 +2166,7 @@ void cmListFileLexer_yyfree (void * ptr , yyscan_t yyscanner)
#define YYTABLES_NAME "yytables"
-#undef YY_NEW_FILE
-#undef YY_FLUSH_BUFFER
-#undef yy_set_bol
-#undef yy_new_buffer
-#undef yy_set_interactive
-#undef yytext_ptr
-#undef YY_DO_BEFORE_ACTION
-
-#ifdef YY_DECL_IS_OURS
-#undef YY_DECL_IS_OURS
-#undef YY_DECL
-#endif
-#line 194 "cmListFileLexer.in.l"
+#line 192 "cmListFileLexer.in.l"
@@ -2122,7 +2222,7 @@ static void cmListFileLexerAppend(cmListFileLexer* lexer, const char* text,
}
/* We need to extend the buffer. */
- temp = (char*)malloc(newSize);
+ temp = malloc(newSize);
if(lexer->token.text)
{
memcpy(temp, lexer->token.text, lexer->token.length);
@@ -2303,6 +2403,7 @@ const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
switch(type)
{
case cmListFileLexer_Token_None: return "nothing";
+ case cmListFileLexer_Token_Space: return "space";
case cmListFileLexer_Token_Newline: return "newline";
case cmListFileLexer_Token_Identifier: return "identifier";
case cmListFileLexer_Token_ParenLeft: return "left paren";
diff --git a/Source/cmListFileLexer.h b/Source/cmListFileLexer.h
index 5f4db33c4..cc78b5c2f 100644
--- a/Source/cmListFileLexer.h
+++ b/Source/cmListFileLexer.h
@@ -15,6 +15,7 @@
typedef enum cmListFileLexer_Type_e
{
cmListFileLexer_Token_None,
+ cmListFileLexer_Token_Space,
cmListFileLexer_Token_Newline,
cmListFileLexer_Token_Identifier,
cmListFileLexer_Token_ParenLeft,
diff --git a/Source/cmListFileLexer.in.l b/Source/cmListFileLexer.in.l
index 41e817b1a..12b53eef6 100644
--- a/Source/cmListFileLexer.in.l
+++ b/Source/cmListFileLexer.in.l
@@ -20,9 +20,11 @@ Run flex like this:
Modify cmListFileLexer.c:
- remove TABs
+ - remove use of the 'register' storage class specifier
- remove the yyunput function
- add a statement "(void)yyscanner;" to the top of these methods:
yy_fatal_error, cmListFileLexer_yyalloc, cmListFileLexer_yyrealloc, cmListFileLexer_yyfree
+ - remove statement "yyscanner = NULL;" from cmListFileLexer_yylex_destroy
- remove all YY_BREAK lines occurring right after return statements
- remove the isatty forward declaration
@@ -74,6 +76,8 @@ static void cmListFileLexerDestroy(cmListFileLexer* lexer);
%x STRING
MAKEVAR \$\([A-Za-z0-9_]*\)
+UNQUOTED ([^ \t\r\n\(\)#\\\"]|\\.)
+LEGACY {MAKEVAR}|{UNQUOTED}|\"({MAKEVAR}|{UNQUOTED}|[ \t])*\"
%%
@@ -110,7 +114,14 @@ MAKEVAR \$\([A-Za-z0-9_]*\)
return 1;
}
-({MAKEVAR}|[^ \t\r\n\(\)#\\\"]|\\.)({MAKEVAR}|[^ \t\r\n\(\)#\\\"]|\\.|\"({MAKEVAR}|[^\r\n\(\)#\\\"]|\\.)*\")* {
+({UNQUOTED})({UNQUOTED})* {
+ lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
+ lexer->column += yyleng;
+ return 1;
+}
+
+({MAKEVAR}|{UNQUOTED})({LEGACY})* {
lexer->token.type = cmListFileLexer_Token_ArgumentUnquoted;
cmListFileLexerSetToken(lexer, yytext, yyleng);
lexer->column += yyleng;
@@ -124,11 +135,17 @@ MAKEVAR \$\([A-Za-z0-9_]*\)
BEGIN(STRING);
}
-<STRING>([^\\\n\"]|\\(.|\n))+ {
+<STRING>([^\\\n\"]|\\.)+ {
cmListFileLexerAppend(lexer, yytext, yyleng);
lexer->column += yyleng;
}
+<STRING>\\\n {
+ cmListFileLexerAppend(lexer, yytext, yyleng);
+ ++lexer->line;
+ lexer->column = 1;
+}
+
<STRING>\n {
cmListFileLexerAppend(lexer, yytext, yyleng);
++lexer->line;
@@ -152,8 +169,11 @@ MAKEVAR \$\([A-Za-z0-9_]*\)
return 1;
}
-[ \t\r] {
+[ \t\r]+ {
+ lexer->token.type = cmListFileLexer_Token_Space;
+ cmListFileLexerSetToken(lexer, yytext, yyleng);
lexer->column += yyleng;
+ return 1;
}
. {
@@ -404,6 +424,7 @@ const char* cmListFileLexer_GetTypeAsString(cmListFileLexer* lexer,
switch(type)
{
case cmListFileLexer_Token_None: return "nothing";
+ case cmListFileLexer_Token_Space: return "space";
case cmListFileLexer_Token_Newline: return "newline";
case cmListFileLexer_Token_Identifier: return "identifier";
case cmListFileLexer_Token_ParenLeft: return "left paren";
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index ee5b9d812..9c0410965 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -55,7 +55,6 @@ cmLocalGenerator::cmLocalGenerator()
this->UseRelativePaths = false;
this->Configured = false;
this->EmitUniversalBinaryFlags = true;
- this->IsMakefileGenerator = false;
this->RelativePathsConfigured = false;
this->PathConversionsSetup = false;
this->BackwardsCompatibility = 0;
@@ -260,12 +259,7 @@ void cmLocalGenerator::TraceDependencies()
cmTargets& targets = this->Makefile->GetTargets();
for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
{
- const char* projectFilename = 0;
- if (this->IsMakefileGenerator == false) // only use of this variable
- {
- projectFilename = t->second.GetName();
- }
- t->second.TraceDependencies(projectFilename);
+ t->second.TraceDependencies();
}
}
@@ -294,7 +288,7 @@ void cmLocalGenerator::GenerateTestFiles()
<< "# Build directory: "
<< this->Makefile->GetStartOutputDirectory() << std::endl
<< "# " << std::endl
- << "# This file includes the relevent testing commands "
+ << "# This file includes the relevant testing commands "
<< "required for " << std::endl
<< "# testing this directory and lists subdirectories to "
<< "be tested as well." << std::endl;
@@ -577,7 +571,7 @@ void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname,
{
std::vector<std::string> includes;
this->GetIncludeDirectories(includes, &target, lang);
- flags += this->GetIncludeFlags(includes, lang);
+ flags += this->GetIncludeFlags(includes, &target, lang);
}
flags += this->Makefile->GetDefineFlags();
@@ -761,7 +755,7 @@ void cmLocalGenerator
if(!llang)
{
cmSystemTools::Error
- ("CMake can not determine linker language for target:",
+ ("CMake can not determine linker language for target: ",
target.Target->GetName());
return;
}
@@ -1084,8 +1078,6 @@ void
cmLocalGenerator::ExpandRuleVariables(std::string& s,
const RuleVariables& replaceValues)
{
- std::vector<std::string> enabledLanguages;
- this->GlobalGenerator->GetEnabledLanguages(enabledLanguages);
this->InsertRuleLauncher(s, replaceValues.CMTarget,
replaceValues.RuleLauncher);
std::string::size_type start = s.find('<');
@@ -1212,6 +1204,7 @@ cmLocalGenerator::ConvertToIncludeReference(std::string const& path)
//----------------------------------------------------------------------------
std::string cmLocalGenerator::GetIncludeFlags(
const std::vector<std::string> &includes,
+ cmGeneratorTarget* target,
const char* lang, bool forResponseFile,
const char *config)
{
@@ -1282,11 +1275,10 @@ std::string cmLocalGenerator::GetIncludeFlags(
continue;
}
- std::string include = *i;
if(!flagUsed || repeatFlag)
{
- if(sysIncludeFlag &&
- this->Makefile->IsSystemIncludeDirectory(i->c_str(), config))
+ if(sysIncludeFlag && target &&
+ target->IsSystemIncludeDirectory(i->c_str(), config))
{
includeFlags << sysIncludeFlag;
}
@@ -1327,6 +1319,65 @@ std::string cmLocalGenerator::GetIncludeFlags(
}
//----------------------------------------------------------------------------
+void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines,
+ cmTarget* target,
+ const char* config)
+{
+ std::vector<std::string> targetDefines;
+ target->GetCompileDefinitions(targetDefines,
+ config);
+ this->AppendDefines(defines, targetDefines);
+}
+
+//----------------------------------------------------------------------------
+void cmLocalGenerator::AddCompileOptions(
+ std::string& flags, cmTarget* target,
+ const char* lang, const char* config
+ )
+{
+ std::string langFlagRegexVar = std::string("CMAKE_")+lang+"_FLAG_REGEX";
+ if(const char* langFlagRegexStr =
+ this->Makefile->GetDefinition(langFlagRegexVar.c_str()))
+ {
+ // Filter flags acceptable to this language.
+ cmsys::RegularExpression r(langFlagRegexStr);
+ std::vector<std::string> opts;
+ if(const char* targetFlags = target->GetProperty("COMPILE_FLAGS"))
+ {
+ cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
+ }
+ target->GetCompileOptions(opts, config);
+ for(std::vector<std::string>::const_iterator i = opts.begin();
+ i != opts.end(); ++i)
+ {
+ if(r.find(i->c_str()))
+ {
+ // (Re-)Escape this flag. COMPILE_FLAGS were already parsed
+ // as a command line above, and COMPILE_OPTIONS are escaped.
+ this->AppendFlagEscape(flags, i->c_str());
+ }
+ }
+ }
+ else
+ {
+ // Use all flags.
+ if(const char* targetFlags = target->GetProperty("COMPILE_FLAGS"))
+ {
+ // COMPILE_FLAGS are not escaped for historical reasons.
+ this->AppendFlags(flags, targetFlags);
+ }
+ std::vector<std::string> opts;
+ target->GetCompileOptions(opts, config);
+ for(std::vector<std::string>::const_iterator i = opts.begin();
+ i != opts.end(); ++i)
+ {
+ // COMPILE_OPTIONS are escaped.
+ this->AppendFlagEscape(flags, i->c_str());
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
cmGeneratorTarget* target,
const char* lang,
@@ -1476,6 +1527,25 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
}
}
+void cmLocalGenerator::GetStaticLibraryFlags(std::string& flags,
+ std::string const& config,
+ cmTarget* target)
+{
+ this->AppendFlags(flags,
+ this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS"));
+ if(!config.empty())
+ {
+ std::string name = "CMAKE_STATIC_LINKER_FLAGS_" + config;
+ this->AppendFlags(flags, this->Makefile->GetSafeDefinition(name.c_str()));
+ }
+ this->AppendFlags(flags, target->GetProperty("STATIC_LIBRARY_FLAGS"));
+ if(!config.empty())
+ {
+ std::string name = "STATIC_LIBRARY_FLAGS_" + config;
+ this->AppendFlags(flags, target->GetProperty(name.c_str()));
+ }
+}
+
void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
std::string& flags,
std::string& linkFlags,
@@ -1492,26 +1562,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
switch(target->GetType())
{
case cmTarget::STATIC_LIBRARY:
- {
- const char* targetLinkFlags =
- target->GetProperty("STATIC_LIBRARY_FLAGS");
- if(targetLinkFlags)
- {
- linkFlags += targetLinkFlags;
- linkFlags += " ";
- }
- if(!buildType.empty())
- {
- std::string build = "STATIC_LIBRARY_FLAGS_";
- build += buildType;
- targetLinkFlags = target->GetProperty(build.c_str());
- if(targetLinkFlags)
- {
- linkFlags += targetLinkFlags;
- linkFlags += " ";
- }
- }
- }
+ this->GetStaticLibraryFlags(linkFlags, buildType, target->Target);
break;
case cmTarget::MODULE_LIBRARY:
libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
@@ -1582,7 +1633,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
if(!linkLanguage)
{
cmSystemTools::Error
- ("CMake can not determine linker language for target:",
+ ("CMake can not determine linker language for target: ",
target->Target->GetName());
return;
}
@@ -1994,6 +2045,81 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
}
}
+static void AddVisibilityCompileOption(std::string &flags, cmTarget* target,
+ cmLocalGenerator *lg, const char *lang)
+{
+ std::string l(lang);
+ std::string compileOption = "CMAKE_" + l + "_COMPILE_OPTIONS_VISIBILITY";
+ const char *opt = lg->GetMakefile()->GetDefinition(compileOption.c_str());
+ if (!opt)
+ {
+ return;
+ }
+ std::string flagDefine = l + "_VISIBILITY_PRESET";
+
+ const char *prop = target->GetProperty(flagDefine.c_str());
+ if (!prop)
+ {
+ return;
+ }
+ if (strcmp(prop, "hidden") != 0
+ && strcmp(prop, "default") != 0
+ && strcmp(prop, "protected") != 0
+ && strcmp(prop, "internal") != 0 )
+ {
+ cmOStringStream e;
+ e << "Target " << target->GetName() << " uses unsupported value \""
+ << prop << "\" for " << flagDefine << ".";
+ cmSystemTools::Error(e.str().c_str());
+ return;
+ }
+ std::string option = std::string(opt) + prop;
+ lg->AppendFlags(flags, option.c_str());
+}
+
+static void AddInlineVisibilityCompileOption(std::string &flags,
+ cmTarget* target,
+ cmLocalGenerator *lg)
+{
+ std::string compileOption
+ = "CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN";
+ const char *opt = lg->GetMakefile()->GetDefinition(compileOption.c_str());
+ if (!opt)
+ {
+ return;
+ }
+
+ bool prop = target->GetPropertyAsBool("VISIBILITY_INLINES_HIDDEN");
+ if (!prop)
+ {
+ return;
+ }
+ lg->AppendFlags(flags, opt);
+}
+
+//----------------------------------------------------------------------------
+void cmLocalGenerator
+::AddVisibilityPresetFlags(std::string &flags, cmTarget* target,
+ const char *lang)
+{
+ int targetType = target->GetType();
+ bool suitableTarget = ((targetType == cmTarget::SHARED_LIBRARY)
+ || (targetType == cmTarget::MODULE_LIBRARY)
+ || (target->IsExecutableWithExports()));
+
+ if (!suitableTarget)
+ {
+ return;
+ }
+
+ if (!lang)
+ {
+ return;
+ }
+ AddVisibilityCompileOption(flags, target, this, lang);
+ AddInlineVisibilityCompileOption(flags, target, this);
+}
+
//----------------------------------------------------------------------------
void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target,
std::string const& lang,
@@ -2011,13 +2137,13 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target,
else
{
if (target->GetType() == cmTarget::OBJECT_LIBRARY)
- {
+ {
if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE"))
{
this->AddPositionIndependentFlags(flags, lang, targetType);
}
return;
- }
+ }
if (target->GetLinkInterfaceDependentBoolProperty(
"POSITION_INDEPENDENT_CODE",
@@ -2105,7 +2231,7 @@ void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags,
for(std::vector<std::string>::const_iterator oi = options.begin();
oi != options.end(); ++oi)
{
- this->AppendFlags(flags, this->EscapeForShell(oi->c_str()).c_str());
+ this->AppendFlagEscape(flags, oi->c_str());
}
}
}
@@ -2143,6 +2269,13 @@ void cmLocalGenerator::AppendFlags(std::string& flags,
}
//----------------------------------------------------------------------------
+void cmLocalGenerator::AppendFlagEscape(std::string& flags,
+ const char* rawFlag)
+{
+ this->AppendFlags(flags, this->EscapeForShell(rawFlag).c_str());
+}
+
+//----------------------------------------------------------------------------
void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
const char* defines_list)
{
@@ -2155,7 +2288,13 @@ void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
// Expand the list of definitions.
std::vector<std::string> defines_vec;
cmSystemTools::ExpandListArgument(defines_list, defines_vec);
+ this->AppendDefines(defines, defines_vec);
+}
+//----------------------------------------------------------------------------
+void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
+ const std::vector<std::string> &defines_vec)
+{
for(std::vector<std::string>::const_iterator di = defines_vec.begin();
di != defines_vec.end(); ++di)
{
@@ -2248,7 +2387,7 @@ void cmLocalGenerator::AppendFeatureOptions(
for(std::vector<std::string>::const_iterator oi = options.begin();
oi != options.end(); ++oi)
{
- this->AppendFlags(flags, this->EscapeForShell(oi->c_str()).c_str());
+ this->AppendFlagEscape(flags, oi->c_str());
}
}
}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index a1c34f076..10f0b1a6c 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -143,12 +143,16 @@ public:
const char* config);
void AddCMP0018Flags(std::string &flags, cmTarget* target,
std::string const& lang, const char *config);
+ void AddVisibilityPresetFlags(std::string &flags, cmTarget* target,
+ const char *lang);
void AddConfigVariableFlags(std::string& flags, const char* var,
const char* config);
///! Append flags to a string.
virtual void AppendFlags(std::string& flags, const char* newFlags);
+ virtual void AppendFlagEscape(std::string& flags, const char* rawFlag);
///! Get the include flags for the current makefile and language
std::string GetIncludeFlags(const std::vector<std::string> &includes,
+ cmGeneratorTarget* target,
const char* lang, bool forResponseFile = false,
const char *config = 0);
@@ -163,6 +167,9 @@ public:
{
this->AppendDefines(defines, defines_list.c_str());
}
+ void AppendDefines(std::set<std::string>& defines,
+ const std::vector<std::string> &defines_vec);
+
/**
* Join a set of defines into a definesString with a space separator.
*/
@@ -215,6 +222,10 @@ public:
cmGeneratorTarget* target,
const char* lang = "C", const char *config = 0,
bool stripImplicitInclDirs = true);
+ void AddCompileOptions(std::string& flags, cmTarget* target,
+ const char* lang, const char* config);
+ void AddCompileDefinitions(std::set<std::string>& defines, cmTarget* target,
+ const char* config);
/** Compute the language used to compile the given source file. */
const char* GetSourceFileLanguage(const cmSourceFile& source);
@@ -337,6 +348,11 @@ public:
std::string const& dir_max,
bool* hasSourceExtension = 0);
+ /** Fill out the static linker flags for the given target. */
+ void GetStaticLibraryFlags(std::string& flags,
+ std::string const& config,
+ cmTarget* target);
+
/** Fill out these strings for the given target. Libraries to link,
* flags, and linkflags. */
void GetTargetFlags(std::string& linkLibs,
@@ -430,8 +446,6 @@ protected:
bool IgnoreLibPrefix;
bool Configured;
bool EmitUniversalBinaryFlags;
- // A type flag is not nice. It's used only in TraceDependencies().
- bool IsMakefileGenerator;
// Hack for ExpandRuleVariable until object-oriented version is
// committed.
std::string TargetImplib;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index d902f4ef7..a522e37e2 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -27,7 +27,6 @@ cmLocalNinjaGenerator::cmLocalNinjaGenerator()
, ConfigName("")
, HomeRelativeOutputPath("")
{
- this->IsMakefileGenerator = true;
#ifdef _WIN32
this->WindowsShell = true;
#endif
@@ -302,7 +301,12 @@ void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc,
wd = this->GetMakefile()->GetStartOutputDirectory();
cmOStringStream cdCmd;
- cdCmd << "cd " << this->ConvertToOutputFormat(wd, SHELL);
+#ifdef _WIN32
+ std::string cdStr = "cd /D ";
+#else
+ std::string cdStr = "cd ";
+#endif
+ cdCmd << cdStr << this->ConvertToOutputFormat(wd, SHELL);
cmdLines.push_back(cdCmd.str());
}
for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) {
@@ -335,14 +339,15 @@ cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
this->AppendCustomCommandLines(cc, cmdLines);
if (cmdLines.empty()) {
- cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
- "Phony custom command for " +
- ninjaOutputs[0],
- ninjaOutputs,
- ninjaDeps,
- cmNinjaDeps(),
- orderOnlyDeps,
- cmNinjaVars());
+ this->GetGlobalNinjaGenerator()->WritePhonyBuild(
+ this->GetBuildFileStream(),
+ "Phony custom command for " +
+ ninjaOutputs[0],
+ ninjaOutputs,
+ ninjaDeps,
+ cmNinjaDeps(),
+ orderOnlyDeps,
+ cmNinjaVars());
} else {
this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
this->BuildCommandLine(cmdLines),
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 0f680f6a1..56da1f936 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -92,7 +92,6 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3()
this->SkipPreprocessedSourceRules = false;
this->SkipAssemblySourceRules = false;
this->MakeCommandEscapeTargetTwice = false;
- this->IsMakefileGenerator = true;
this->BorlandMakeCurlyHack = false;
}
@@ -1304,7 +1303,7 @@ cmLocalUnixMakefileGenerator3
std::string unmodified = s;
unmodified += s2;
// if there is no restriction on the length of make variables
- // and there are no "." charactors in the string, then return the
+ // and there are no "." characters in the string, then return the
// unmodified combination.
if((!this->MakefileVariableSize && unmodified.find('.') == s.npos)
&& (!this->MakefileVariableSize && unmodified.find('+') == s.npos)
@@ -1345,7 +1344,7 @@ cmLocalUnixMakefileGenerator3
return ret;
}
- // if the string is greater the 32 chars it is an invalid vairable name
+ // if the string is greater than 32 chars it is an invalid variable name
// for borland make
if(static_cast<int>(ret.size()) > this->MakefileVariableSize)
{
@@ -1353,8 +1352,8 @@ cmLocalUnixMakefileGenerator3
int size = keep + 3;
std::string str1 = s;
std::string str2 = s2;
- // we must shorten the combined string by 4 charactors
- // keep no more than 24 charactors from the second string
+ // we must shorten the combined string by 4 characters
+ // keep no more than 24 characters from the second string
if(static_cast<int>(str2.size()) > keep)
{
str2 = str2.substr(0, keep);
@@ -1962,8 +1961,8 @@ void cmLocalUnixMakefileGenerator3
// Build a list of preprocessor definitions for the target.
std::set<std::string> defines;
- this->AppendDefines(defines, target.GetCompileDefinitions(
- this->ConfigurationName.c_str()));
+ this->AddCompileDefinitions(defines, &target,
+ this->ConfigurationName.c_str());
if(!defines.empty())
{
cmakefileStream
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index dc94476c8..e5b4057d2 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -573,22 +573,20 @@ cmLocalVisualStudio6Generator
// Add the rule with the given dependencies and commands.
const char* no_main_dependency = 0;
- this->Makefile->AddCustomCommandToOutput(output,
- depends,
- no_main_dependency,
- origCommand.GetCommandLines(),
- comment.c_str(),
- origCommand.GetWorkingDirectory());
+ if(cmSourceFile* outsf =
+ this->Makefile->AddCustomCommandToOutput(
+ output, depends, no_main_dependency,
+ origCommand.GetCommandLines(), comment.c_str(),
+ origCommand.GetWorkingDirectory()))
+ {
+ target.AddSourceFile(outsf);
+ }
// Replace the dependencies with the output of this rule so that the
// next rule added will run after this one.
depends.clear();
depends.push_back(output);
- // Add a source file representing this output to the project.
- cmSourceFile* outsf = this->Makefile->GetSourceFileWithOutput(output);
- target.AddSourceFile(outsf);
-
// Free the fake output name.
delete [] output;
}
@@ -1171,18 +1169,42 @@ void cmLocalVisualStudio6Generator
std::string extraLinkOptionsRelWithDebInfo;
if(target.GetType() == cmTarget::EXECUTABLE)
{
- extraLinkOptions =
- this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
+ extraLinkOptions = this->Makefile->
+ GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
+ extraLinkOptionsDebug = this->Makefile->
+ GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_DEBUG");
+ extraLinkOptionsRelease = this->Makefile->
+ GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_RELEASE");
+ extraLinkOptionsMinSizeRel = this->Makefile->
+ GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_MINSIZEREL");
+ extraLinkOptionsRelWithDebInfo = this->Makefile->
+ GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO");
}
if(target.GetType() == cmTarget::SHARED_LIBRARY)
{
- extraLinkOptions =
- this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
+ extraLinkOptions = this->Makefile->
+ GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
+ extraLinkOptionsDebug = this->Makefile->
+ GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_DEBUG");
+ extraLinkOptionsRelease = this->Makefile->
+ GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_RELEASE");
+ extraLinkOptionsMinSizeRel = this->Makefile->
+ GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL");
+ extraLinkOptionsRelWithDebInfo = this->Makefile->
+ GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO");
}
if(target.GetType() == cmTarget::MODULE_LIBRARY)
{
- extraLinkOptions =
- this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
+ extraLinkOptions = this->Makefile->
+ GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
+ extraLinkOptionsDebug = this->Makefile->
+ GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_DEBUG");
+ extraLinkOptionsRelease = this->Makefile->
+ GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_RELEASE");
+ extraLinkOptionsMinSizeRel = this->Makefile->
+ GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL");
+ extraLinkOptionsRelWithDebInfo = this->Makefile->
+ GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO");
}
// Get extra linker options for this target.
@@ -1228,7 +1250,7 @@ void cmLocalVisualStudio6Generator
if(!linkLanguage)
{
cmSystemTools::Error
- ("CMake can not determine linker language for target:",
+ ("CMake can not determine linker language for target: ",
target.GetName());
return;
}
@@ -1435,38 +1457,39 @@ void cmLocalVisualStudio6Generator
std::string staticLibOptionsRelWithDebInfo;
if(target.GetType() == cmTarget::STATIC_LIBRARY )
{
- if(const char* libflags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
- {
- staticLibOptions = libflags;
- staticLibOptionsDebug = libflags;
- staticLibOptionsRelease = libflags;
- staticLibOptionsMinSizeRel = libflags;
- staticLibOptionsRelWithDebInfo = libflags;
- }
- if(const char* libflagsDebug =
- target.GetProperty("STATIC_LIBRARY_FLAGS_DEBUG"))
- {
- staticLibOptionsDebug += " ";
- staticLibOptionsDebug = libflagsDebug;
- }
- if(const char* libflagsRelease =
- target.GetProperty("STATIC_LIBRARY_FLAGS_RELEASE"))
- {
- staticLibOptionsRelease += " ";
- staticLibOptionsRelease = libflagsRelease;
- }
- if(const char* libflagsMinSizeRel =
- target.GetProperty("STATIC_LIBRARY_FLAGS_MINSIZEREL"))
- {
- staticLibOptionsMinSizeRel += " ";
- staticLibOptionsMinSizeRel = libflagsMinSizeRel;
- }
- if(const char* libflagsRelWithDebInfo =
- target.GetProperty("STATIC_LIBRARY_FLAGS_RELWITHDEBINFO"))
- {
- staticLibOptionsRelWithDebInfo += " ";
- staticLibOptionsRelWithDebInfo = libflagsRelWithDebInfo;
- }
+ const char *libflagsGlobal =
+ this->Makefile->GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS");
+ this->AppendFlags(staticLibOptions, libflagsGlobal);
+ this->AppendFlags(staticLibOptionsDebug, libflagsGlobal);
+ this->AppendFlags(staticLibOptionsRelease, libflagsGlobal);
+ this->AppendFlags(staticLibOptionsMinSizeRel, libflagsGlobal);
+ this->AppendFlags(staticLibOptionsRelWithDebInfo, libflagsGlobal);
+
+ this->AppendFlags(staticLibOptionsDebug, this->Makefile->
+ GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_DEBUG"));
+ this->AppendFlags(staticLibOptionsRelease, this->Makefile->
+ GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_RELEASE"));
+ this->AppendFlags(staticLibOptionsMinSizeRel, this->Makefile->
+ GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL"));
+ this->AppendFlags(staticLibOptionsRelWithDebInfo, this->Makefile->
+ GetSafeDefinition("CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO"));
+
+ const char *libflags = target.GetProperty("STATIC_LIBRARY_FLAGS");
+ this->AppendFlags(staticLibOptions, libflags);
+ this->AppendFlags(staticLibOptionsDebug, libflags);
+ this->AppendFlags(staticLibOptionsRelease, libflags);
+ this->AppendFlags(staticLibOptionsMinSizeRel, libflags);
+ this->AppendFlags(staticLibOptionsRelWithDebInfo, libflags);
+
+ this->AppendFlags(staticLibOptionsDebug,
+ target.GetProperty("STATIC_LIBRARY_FLAGS_DEBUG"));
+ this->AppendFlags(staticLibOptionsRelease,
+ target.GetProperty("STATIC_LIBRARY_FLAGS_RELEASE"));
+ this->AppendFlags(staticLibOptionsMinSizeRel,
+ target.GetProperty("STATIC_LIBRARY_FLAGS_MINSIZEREL"));
+ this->AppendFlags(staticLibOptionsRelWithDebInfo,
+ target.GetProperty("STATIC_LIBRARY_FLAGS_RELWITHDEBINFO"));
+
std::string objects;
this->OutputObjects(target, "LIB", objects);
if(!objects.empty())
@@ -1639,9 +1662,9 @@ void cmLocalVisualStudio6Generator
// store flags for each configuration
std::string flags = " ";
std::string flagsRelease = " ";
- std::string flagsMinSize = " ";
+ std::string flagsMinSizeRel = " ";
std::string flagsDebug = " ";
- std::string flagsDebugRel = " ";
+ std::string flagsRelWithDebInfo = " ";
if(target.GetType() >= cmTarget::EXECUTABLE &&
target.GetType() <= cmTarget::OBJECT_LIBRARY)
{
@@ -1649,7 +1672,7 @@ void cmLocalVisualStudio6Generator
if(!linkLanguage)
{
cmSystemTools::Error
- ("CMake can not determine linker language for target:",
+ ("CMake can not determine linker language for target: ",
target.GetName());
return;
}
@@ -1664,16 +1687,24 @@ void cmLocalVisualStudio6Generator
flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" ";
flagVar = baseFlagVar + "_MINSIZEREL";
- flagsMinSize = this->Makefile->GetSafeDefinition(flagVar.c_str());
- flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
+ flagsMinSizeRel = this->Makefile->GetSafeDefinition(flagVar.c_str());
+ flagsMinSizeRel += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
flagVar = baseFlagVar + "_DEBUG";
flagsDebug = this->Makefile->GetSafeDefinition(flagVar.c_str());
flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" ";
flagVar = baseFlagVar + "_RELWITHDEBINFO";
- flagsDebugRel = this->Makefile->GetSafeDefinition(flagVar.c_str());
- flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
+ flagsRelWithDebInfo = this->Makefile->GetSafeDefinition(flagVar.c_str());
+ flagsRelWithDebInfo += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
+
+ this->AddCompileOptions(flags, &target, linkLanguage, 0);
+ this->AddCompileOptions(flagsDebug, &target, linkLanguage, "Debug");
+ this->AddCompileOptions(flagsRelease, &target, linkLanguage, "Release");
+ this->AddCompileOptions(flagsMinSizeRel, &target, linkLanguage,
+ "MinSizeRel");
+ this->AddCompileOptions(flagsRelWithDebInfo, &target, linkLanguage,
+ "RelWithDebInfo");
}
// if _UNICODE and _SBCS are not found, then add -D_MBCS
@@ -1686,13 +1717,6 @@ void cmLocalVisualStudio6Generator
flags += " /D \"_MBCS\"";
}
- // Add per-target flags.
- if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS"))
- {
- flags += " ";
- flags += targetFlags;
- }
-
// Add per-target and per-configuration preprocessor definitions.
std::set<std::string> definesSet;
std::set<std::string> debugDefinesSet;
@@ -1700,21 +1724,11 @@ void cmLocalVisualStudio6Generator
std::set<std::string> minsizeDefinesSet;
std::set<std::string> debugrelDefinesSet;
- this->AppendDefines(
- definesSet,
- target.GetCompileDefinitions(0));
- this->AppendDefines(
- debugDefinesSet,
- target.GetCompileDefinitions("DEBUG"));
- this->AppendDefines(
- releaseDefinesSet,
- target.GetCompileDefinitions("RELEASE"));
- this->AppendDefines(
- minsizeDefinesSet,
- target.GetCompileDefinitions("MINSIZEREL"));
- this->AppendDefines(
- debugrelDefinesSet,
- target.GetCompileDefinitions("RELWITHDEBINFO"));
+ this->AddCompileDefinitions(definesSet, &target, 0);
+ this->AddCompileDefinitions(debugDefinesSet, &target, "DEBUG");
+ this->AddCompileDefinitions(releaseDefinesSet, &target, "RELEASE");
+ this->AddCompileDefinitions(minsizeDefinesSet, &target, "MINSIZEREL");
+ this->AddCompileDefinitions(debugrelDefinesSet, &target, "RELWITHDEBINFO");
std::string defines = " ";
std::string debugDefines = " ";
@@ -1731,19 +1745,19 @@ void cmLocalVisualStudio6Generator
flags += defines;
flagsDebug += debugDefines;
flagsRelease += releaseDefines;
- flagsMinSize += minsizeDefines;
- flagsDebugRel += debugrelDefines;
+ flagsMinSizeRel += minsizeDefines;
+ flagsRelWithDebInfo += debugrelDefines;
// The template files have CXX FLAGS in them, that need to be replaced.
// There are not separate CXX and C template files, so we use the same
// variable names. The previous code sets up flags* variables to contain
// the correct C or CXX flags
cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL",
- flagsMinSize.c_str());
+ flagsMinSizeRel.c_str());
cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG",
flagsDebug.c_str());
cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
- flagsDebugRel.c_str());
+ flagsRelWithDebInfo.c_str());
cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE",
flagsRelease.c_str());
cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 7d0bc67ed..8ffd96eb1 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -146,11 +146,10 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets()
force += "/";
force += tgt.GetName();
force += "_force";
- this->Makefile->AddCustomCommandToOutput(force.c_str(), no_depends,
- no_main_dependency,
- force_commands, " ", 0, true);
if(cmSourceFile* file =
- this->Makefile->GetSourceFileWithOutput(force.c_str()))
+ this->Makefile->AddCustomCommandToOutput(
+ force.c_str(), no_depends, no_main_dependency,
+ force_commands, " ", 0, true))
{
tgt.AddSourceFile(file);
}
@@ -202,7 +201,7 @@ void cmLocalVisualStudio7Generator::WriteStampFiles()
stampName += "/";
stampName += "generate.stamp";
std::ofstream stamp(stampName.c_str());
- stamp << "# CMake generation timestamp file this directory.\n";
+ stamp << "# CMake generation timestamp file for this directory.\n";
// Create a helper file so CMake can determine when it is run
// through the rule created by CreateVCProjBuildRule whether it
@@ -443,12 +442,12 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] =
{"InlineFunctionExpansion", "Ob0", "no inlines", "0", 0},
{"InlineFunctionExpansion", "Ob1", "when inline keyword", "1", 0},
{"InlineFunctionExpansion", "Ob2", "any time you can inline", "2", 0},
- {"RuntimeLibrary", "MTd", "Multithreded debug", "1", 0},
- {"RuntimeLibrary", "MT", "Multithreded", "0", 0},
- {"RuntimeLibrary", "MDd", "Multithreded dll debug", "3", 0},
- {"RuntimeLibrary", "MD", "Multithreded dll", "2", 0},
- {"RuntimeLibrary", "MLd", "Sinble Thread debug", "5", 0},
- {"RuntimeLibrary", "ML", "Sinble Thread", "4", 0},
+ {"RuntimeLibrary", "MTd", "Multithreaded debug", "1", 0},
+ {"RuntimeLibrary", "MT", "Multithreaded", "0", 0},
+ {"RuntimeLibrary", "MDd", "Multithreaded dll debug", "3", 0},
+ {"RuntimeLibrary", "MD", "Multithreaded dll", "2", 0},
+ {"RuntimeLibrary", "MLd", "Single Thread debug", "5", 0},
+ {"RuntimeLibrary", "ML", "Single Thread", "4", 0},
{"StructMemberAlignment", "Zp16", "struct align 16 byte ", "5", 0},
{"StructMemberAlignment", "Zp1", "struct align 1 byte ", "1", 0},
{"StructMemberAlignment", "Zp2", "struct align 2 byte ", "2", 0},
@@ -476,6 +475,11 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] =
{"ForcedIncludeFiles", "FI", "Forced include files", "",
cmVS7FlagTable::UserValueRequired | cmVS7FlagTable::SemicolonAppendable},
+ {"AssemblerListingLocation", "Fa", "ASM List Location", "",
+ cmVS7FlagTable::UserValue},
+ {"ProgramDataBaseFileName", "Fd", "Program Database File Name", "",
+ cmVS7FlagTable::UserValue},
+
// boolean flags
{"BufferSecurityCheck", "GS", "Buffer security check", "TRUE", 0},
{"BufferSecurityCheck", "GS-", "Turn off Buffer security check", "FALSE", 0},
@@ -683,7 +687,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
if(!linkLanguage)
{
cmSystemTools::Error
- ("CMake can not determine linker language for target:",
+ ("CMake can not determine linker language for target: ",
target.GetName());
return;
}
@@ -708,6 +712,9 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
{
flags += " /TP ";
}
+
+ // Add the target-specific flags.
+ this->AddCompileOptions(flags, &target, linkLanguage, configName);
}
if(this->FortranProject)
@@ -720,13 +727,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
}
}
- // Add the target-specific flags.
- if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS"))
- {
- flags += " ";
- flags += targetFlags;
- }
-
// Get preprocessor definitions for this directory.
std::string defineFlags = this->Makefile->GetDefineFlags();
Options::Tool t = Options::Compiler;
@@ -740,12 +740,16 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
table,
this->ExtraFlagTable);
targetOptions.FixExceptionHandlingDefault();
+ std::string asmLocation = std::string(configName) + "/";
+ targetOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
targetOptions.Parse(flags.c_str());
targetOptions.Parse(defineFlags.c_str());
targetOptions.ParseFinish();
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
- targetOptions.AddDefines(target.GetCompileDefinitions(configName).c_str());
+ std::vector<std::string> targetDefines;
+ target.GetCompileDefinitions(targetDefines, configName);
+ targetOptions.AddDefines(targetDefines);
targetOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -836,18 +840,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
fout << "\"\n";
targetOptions.OutputFlagMap(fout, "\t\t\t\t");
targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX");
- fout << "\t\t\t\tAssemblerListingLocation=\"" << configName << "\"\n";
fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
- if(targetBuilds)
- {
- // We need to specify a program database file name even for
- // non-debug configurations because VS still creates .idb files.
- fout << "\t\t\t\tProgramDataBaseFileName=\""
- << this->ConvertToXMLOutputPathSingle(
- target.GetPDBDirectory(configName).c_str())
- << "/"
- << target.GetPDBName(configName) << "\"\n";
- }
fout << "/>\n"; // end of <Tool Name=VCCLCompilerTool
tool = "VCCustomBuildTool";
if(this->FortranProject)
@@ -928,7 +921,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
}
this->OutputTargetRules(fout, configName, target, libName);
- this->OutputBuildTool(fout, configName, target, targetOptions.IsDebug());
+ this->OutputBuildTool(fout, configName, target, targetOptions);
fout << "\t\t</Configuration>\n";
}
@@ -949,9 +942,7 @@ cmLocalVisualStudio7Generator
}
void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
- const char* configName,
- cmTarget &target,
- bool isDebug)
+ const char* configName, cmTarget &target, const Options& targetOptions)
{
cmGlobalVisualStudio7Generator* gg =
static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
@@ -1047,17 +1038,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
}
}
std::string libflags;
- if(const char* flags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
- {
- libflags += flags;
- }
- std::string libFlagsConfig = "STATIC_LIBRARY_FLAGS_";
- libFlagsConfig += configTypeUpper;
- if(const char* flagsConfig = target.GetProperty(libFlagsConfig.c_str()))
- {
- libflags += " ";
- libflags += flagsConfig;
- }
+ this->GetStaticLibraryFlags(libflags, configTypeUpper, &target);
if(!libflags.empty())
{
fout << "\t\t\t\tAdditionalOptions=\"" << libflags << "\"\n";
@@ -1129,7 +1110,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
temp += targetNamePDB;
fout << "\t\t\t\tProgramDatabaseFile=\"" <<
this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
- if(isDebug)
+ if(targetOptions.IsDebug())
{
fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
}
@@ -1227,7 +1208,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
fout << "\t\t\t\tProgramDatabaseFile=\""
<< path << "/" << targetNamePDB
<< "\"\n";
- if(isDebug)
+ if(targetOptions.IsDebug())
{
fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
}
@@ -1241,9 +1222,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
{
fout << "\t\t\t\tSubSystem=\"8\"\n";
}
- fout << "\t\t\t\tEntryPointSymbol=\""
- << (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup")
- << "\"\n";
+
+ if(!linkOptions.GetFlag("EntryPointSymbol"))
+ {
+ const char* entryPointSymbol = targetOptions.UsingUnicode() ?
+ (isWin32Executable ? "wWinMainCRTStartup" : "mainWCRTStartup") :
+ (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup");
+ fout << "\t\t\t\tEntryPointSymbol=\"" << entryPointSymbol << "\"\n";
+ }
}
else if ( this->FortranProject )
{
@@ -1970,23 +1956,27 @@ cmLocalVisualStudio7Generator
// Compute the version of the Intel plugin to the VS IDE.
// If the key does not exist then use a default guess.
- std::string intelVersion = "9.10";
+ std::string intelVersion;
std::string vskey = gg->GetRegistryBase();
vskey += "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion";
cmSystemTools::ReadRegistryValue(vskey.c_str(), intelVersion,
cmSystemTools::KeyWOW64_32);
- if (intelVersion.find("13") == 0 ||
- intelVersion.find("12") == 0 ||
- intelVersion.find("11") == 0)
+ unsigned int intelVersionNumber = ~0u;
+ sscanf(intelVersion.c_str(), "%u", &intelVersionNumber);
+ if(intelVersionNumber >= 11)
{
- // Version 11.x, 12.x, and 13.x actually use 11.0 in project files!
- intelVersion = "11.0" ;
+ // Default to latest known project file version.
+ intelVersion = "11.0";
}
- else if(intelVersion.find("10") == 0)
+ else if(intelVersionNumber == 10)
{
// Version 10.x actually uses 9.10 in project files!
intelVersion = "9.10";
}
+ else
+ {
+ // Version <= 9: use ProductVersion from registry.
+ }
fout << "<?xml version=\"1.0\" encoding = \"Windows-1252\"?>\n"
<< "<VisualStudioProject\n"
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index d9e2ef0dd..92e4d3c12 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -90,7 +90,7 @@ private:
void OutputTargetRules(std::ostream& fout, const char* configName,
cmTarget &target, const char *libName);
void OutputBuildTool(std::ostream& fout, const char* configName,
- cmTarget& t, bool debug);
+ cmTarget& t, const Options& targetOptions);
void OutputLibraryDirectories(std::ostream& fout,
std::vector<std::string> const& dirs);
void WriteProjectSCC(std::ostream& fout, cmTarget& target);
diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx
index 551ebd30a..7c5f69df5 100644
--- a/Source/cmLocalXCodeGenerator.cxx
+++ b/Source/cmLocalXCodeGenerator.cxx
@@ -33,3 +33,12 @@ cmLocalXCodeGenerator::GetTargetDirectory(cmTarget const&) const
// No per-target directory for this generator (yet).
return "";
}
+
+//----------------------------------------------------------------------------
+void cmLocalXCodeGenerator::AppendFlagEscape(std::string& flags,
+ const char* rawFlag)
+{
+ cmGlobalXCodeGenerator* gg =
+ static_cast<cmGlobalXCodeGenerator*>(this->GlobalGenerator);
+ gg->AppendFlag(flags, rawFlag);
+}
diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h
index eab228f6b..d97a41cea 100644
--- a/Source/cmLocalXCodeGenerator.h
+++ b/Source/cmLocalXCodeGenerator.h
@@ -28,6 +28,7 @@ public:
virtual ~cmLocalXCodeGenerator();
virtual std::string GetTargetDirectory(cmTarget const& target) const;
+ virtual void AppendFlagEscape(std::string& flags, const char* rawFlag);
private:
};
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index bd7ec004b..8ba612cc9 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -227,7 +227,7 @@ bool cmMacroHelperCommand::InvokeInitialPass
}
arg.Value = tmps;
- arg.Quoted = k->Quoted;
+ arg.Delim = k->Delim;
arg.FilePath = k->FilePath;
arg.Line = k->Line;
newLFF.Arguments.push_back(arg);
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 47a6d2e66..34541e996 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -21,6 +21,7 @@
#include "cmCacheManager.h"
#include "cmFunctionBlocker.h"
#include "cmListFileCache.h"
+#include "cmDocumentGeneratorExpressions.h"
#include "cmCommandArgumentParserHelper.h"
#include "cmDocumentCompileDefinitions.h"
#include "cmGeneratorExpression.h"
@@ -40,6 +41,7 @@
#include <stack>
#include <ctype.h> // for isspace
+#include <assert.h>
class cmMakefile::Internals
{
@@ -148,6 +150,7 @@ cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
this->Initialize();
this->CheckSystemVars = mf.CheckSystemVars;
this->ListFileStack = mf.ListFileStack;
+ this->OutputToSource = mf.OutputToSource;
}
//----------------------------------------------------------------------------
@@ -813,6 +816,19 @@ bool cmMakefile::NeedBackwardsCompatibility(unsigned int major,
}
}
+
+namespace
+{
+ struct file_not_persistent
+ {
+ bool operator()(const std::string& path) const
+ {
+ return !(path.find("CMakeTmp") == path.npos &&
+ cmSystemTools::FileExists(path.c_str()));
+ }
+ };
+}
+
void cmMakefile::FinalPass()
{
// do all the variable expansions here
@@ -826,6 +842,29 @@ void cmMakefile::FinalPass()
(*i)->FinalPass();
}
+ //go through all configured files and see which ones still exist.
+ //we don't want cmake to re-run if a configured file is created and deleted
+ //during processing as that would make it a transient file that can't
+ //influence the build process
+
+ //remove_if will move all items that don't have a valid file name to the
+ //back of the vector
+ std::vector<std::string>::iterator new_output_files_end = std::remove_if(
+ this->OutputFiles.begin(),
+ this->OutputFiles.end(),
+ file_not_persistent() );
+ //we just have to erase all items at the back
+ this->OutputFiles.erase(new_output_files_end, this->OutputFiles.end() );
+
+ //if a configured file is used as input for another configured file,
+ //and then deleted it will show up in the input list files so we
+ //need to scan those too
+ std::vector<std::string>::iterator new_list_files_end = std::remove_if(
+ this->ListFiles.begin(),
+ this->ListFiles.end(),
+ file_not_persistent() );
+
+ this->ListFiles.erase(new_list_files_end, this->ListFiles.end() );
}
// Generate the output file
@@ -1008,11 +1047,45 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
cc->SetEscapeOldStyle(escapeOldStyle);
cc->SetEscapeAllowMakeVars(true);
file->SetCustomCommand(cc);
+ this->UpdateOutputToSourceMap(outputs, file);
}
return file;
}
//----------------------------------------------------------------------------
+void
+cmMakefile::UpdateOutputToSourceMap(std::vector<std::string> const& outputs,
+ cmSourceFile* source)
+{
+ for(std::vector<std::string>::const_iterator o = outputs.begin();
+ o != outputs.end(); ++o)
+ {
+ this->UpdateOutputToSourceMap(*o, source);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmMakefile::UpdateOutputToSourceMap(std::string const& output,
+ cmSourceFile* source)
+{
+ OutputToSourceMap::iterator i = this->OutputToSource.find(output);
+ if(i != this->OutputToSource.end())
+ {
+ // Multiple custom commands produce the same output but may
+ // be attached to a different source file (MAIN_DEPENDENCY).
+ // LinearGetSourceFileWithOutput would return the first one,
+ // so keep the mapping for the first one.
+ //
+ // TODO: Warn the user about this case. However, the VS 8 generator
+ // triggers it for separate generate.stamp rules in ZERO_CHECK and
+ // individual targets.
+ return;
+ }
+ this->OutputToSource[output] = source;
+}
+
+//----------------------------------------------------------------------------
cmSourceFile*
cmMakefile::AddCustomCommandToOutput(const char* output,
const std::vector<std::string>& depends,
@@ -1270,6 +1343,11 @@ void cmMakefile::RemoveDefineFlag(const char* flag,
}
}
+void cmMakefile::AddCompileOption(const char* option)
+{
+ this->AppendProperty("COMPILE_OPTIONS", option);
+}
+
bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
{
// Create a regular expression to match valid definitions.
@@ -1431,12 +1509,20 @@ void cmMakefile::AddLinkDirectoryForTarget(const char *target,
cmTargets::iterator i = this->Targets.find(target);
if ( i != this->Targets.end())
{
+ if(this->IsAlias(target))
+ {
+ cmOStringStream e;
+ e << "ALIAS target \"" << target << "\" "
+ << "may not be linked into another target.";
+ this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
i->second.AddLinkDirectory( d );
}
else
{
cmSystemTools::Error
- ("Attempt to add link directories to non-existant target: ",
+ ("Attempt to add link directories to non-existent target: ",
target, " for directory ", d);
}
}
@@ -1493,6 +1579,18 @@ void cmMakefile::InitializeFromParent()
parentIncludes.begin(),
parentIncludes.end());
+ const std::vector<cmValueWithOrigin> parentOptions =
+ parent->GetCompileOptionsEntries();
+ this->CompileOptionsEntries.insert(this->CompileOptionsEntries.end(),
+ parentOptions.begin(),
+ parentOptions.end());
+
+ const std::vector<cmValueWithOrigin> parentDefines =
+ parent->GetCompileDefinitionsEntries();
+ this->CompileDefinitionsEntries.insert(this->CompileDefinitionsEntries.end(),
+ parentDefines.begin(),
+ parentDefines.end());
+
this->SystemIncludeDirectories = parent->SystemIncludeDirectories;
// define flags
@@ -1663,27 +1761,13 @@ cmMakefile::AddSystemIncludeDirectories(const std::set<cmStdString> &incs)
{
this->SystemIncludeDirectories.insert(*li);
}
-}
-//----------------------------------------------------------------------------
-bool cmMakefile::IsSystemIncludeDirectory(const char* dir, const char *config)
-{
- for (std::set<cmStdString>::const_iterator
- it = this->SystemIncludeDirectories.begin();
- it != this->SystemIncludeDirectories.end(); ++it)
+ for (cmTargets::iterator l = this->Targets.begin();
+ l != this->Targets.end(); ++l)
{
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
-
- std::vector<std::string> incs;
- cmSystemTools::ExpandListArgument(ge.Parse(*it)
- ->Evaluate(this, config, false), incs);
- if (std::find(incs.begin(), incs.end(), dir) != incs.end())
- {
- return true;
- }
+ cmTarget &t = l->second;
+ t.AddSystemIncludeDirectories(incs);
}
- return false;
}
void cmMakefile::AddDefinition(const char* name, const char* value)
@@ -1919,6 +2003,12 @@ void cmMakefile::AddGlobalLinkInformation(const char* name, cmTarget& target)
}
+void cmMakefile::AddAlias(const char* lname, cmTarget *tgt)
+{
+ this->AliasTargets[lname] = tgt;
+ this->LocalGenerator->GetGlobalGenerator()->AddAlias(lname, tgt);
+}
+
cmTarget* cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
const std::vector<std::string> &srcs,
bool excludeFromAll)
@@ -1975,7 +2065,7 @@ cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name)
return &it->second;
}
-cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
+cmSourceFile *cmMakefile::LinearGetSourceFileWithOutput(const char *cname)
{
std::string name = cname;
std::string out;
@@ -2011,6 +2101,25 @@ cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
return 0;
}
+cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
+{
+ std::string name = cname;
+
+ // If the queried path is not absolute we use the backward compatible
+ // linear-time search for an output with a matching suffix.
+ if(!cmSystemTools::FileIsFullPath(cname))
+ {
+ return LinearGetSourceFileWithOutput(cname);
+ }
+ // Otherwise we use an efficient lookup map.
+ OutputToSourceMap::iterator o = this->OutputToSource.find(name);
+ if (o != this->OutputToSource.end())
+ {
+ return (*o).second;
+ }
+ return 0;
+}
+
#if defined(CMAKE_BUILD_WITH_CMAKE)
cmSourceGroup* cmMakefile::GetSourceGroup(const std::vector<std::string>&name)
{
@@ -2086,7 +2195,7 @@ void cmMakefile::AddSourceGroup(const std::vector<std::string>& name,
}
else if(i==-1)
{
- // group does not exists nor belong to any existing group
+ // group does not exist nor belong to any existing group
// add its first component
this->SourceGroups.push_back(cmSourceGroup(name[0].c_str(), regex));
sg = this->GetSourceGroup(currentName);
@@ -2780,7 +2889,7 @@ bool cmMakefile::ExpandArguments(
// If the argument is quoted, it should be one argument.
// Otherwise, it may be a list of arguments.
- if(i->Quoted)
+ if(i->Delim == cmListFileArgument::Quoted)
{
outArgs.push_back(value);
}
@@ -3357,8 +3466,14 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
}
std::string soutfile = outfile;
std::string sinfile = infile;
- this->AddCMakeDependFile(infile);
+ this->AddCMakeDependFile(sinfile);
cmSystemTools::ConvertToUnixSlashes(soutfile);
+
+ // Re-generate if non-temporary outputs are missing.
+ //when we finalize the configuration we will remove all
+ //output files that now don't exist.
+ this->AddCMakeOutputFile(soutfile);
+
mode_t perm = 0;
cmSystemTools::GetPermissions(sinfile.c_str(), perm);
std::string::size_type pos = soutfile.rfind('/');
@@ -3468,6 +3583,31 @@ void cmMakefile::SetProperty(const char* prop, const char* value)
cmValueWithOrigin(value, lfbt));
return;
}
+ if (propname == "COMPILE_OPTIONS")
+ {
+ this->CompileOptionsEntries.clear();
+ if (!value)
+ {
+ return;
+ }
+ cmListFileBacktrace lfbt;
+ this->GetBacktrace(lfbt);
+ this->CompileOptionsEntries.push_back(cmValueWithOrigin(value, lfbt));
+ return;
+ }
+ if (propname == "COMPILE_DEFINITIONS")
+ {
+ this->CompileDefinitionsEntries.clear();
+ if (!value)
+ {
+ return;
+ }
+ cmListFileBacktrace lfbt;
+ this->GetBacktrace(lfbt);
+ cmValueWithOrigin entry(value, lfbt);
+ this->CompileDefinitionsEntries.push_back(entry);
+ return;
+ }
if ( propname == "INCLUDE_REGULAR_EXPRESSION" )
{
@@ -3507,6 +3647,22 @@ void cmMakefile::AppendProperty(const char* prop, const char* value,
cmValueWithOrigin(value, lfbt));
return;
}
+ if (propname == "COMPILE_OPTIONS")
+ {
+ cmListFileBacktrace lfbt;
+ this->GetBacktrace(lfbt);
+ this->CompileOptionsEntries.push_back(
+ cmValueWithOrigin(value, lfbt));
+ return;
+ }
+ if (propname == "COMPILE_DEFINITIONS")
+ {
+ cmListFileBacktrace lfbt;
+ this->GetBacktrace(lfbt);
+ this->CompileDefinitionsEntries.push_back(
+ cmValueWithOrigin(value, lfbt));
+ return;
+ }
if ( propname == "LINK_DIRECTORIES" )
{
std::vector<std::string> varArgsExpanded;
@@ -3632,6 +3788,34 @@ const char *cmMakefile::GetProperty(const char* prop,
}
return output.c_str();
}
+ else if (!strcmp("COMPILE_OPTIONS",prop))
+ {
+ std::string sep;
+ for (std::vector<cmValueWithOrigin>::const_iterator
+ it = this->CompileOptionsEntries.begin(),
+ end = this->CompileOptionsEntries.end();
+ it != end; ++it)
+ {
+ output += sep;
+ output += it->Value;
+ sep = ";";
+ }
+ return output.c_str();
+ }
+ else if (!strcmp("COMPILE_DEFINITIONS",prop))
+ {
+ std::string sep;
+ for (std::vector<cmValueWithOrigin>::const_iterator
+ it = this->CompileDefinitionsEntries.begin(),
+ end = this->CompileDefinitionsEntries.end();
+ it != end; ++it)
+ {
+ output += sep;
+ output += it->Value;
+ sep = ";";
+ }
+ return output.c_str();
+ }
bool chain = false;
const char *retVal =
@@ -3680,8 +3864,17 @@ const char* cmMakefile::GetFeature(const char* feature, const char* config)
return 0;
}
-cmTarget* cmMakefile::FindTarget(const char* name)
+cmTarget* cmMakefile::FindTarget(const char* name, bool excludeAliases)
{
+ if (!excludeAliases)
+ {
+ std::map<std::string, cmTarget*>::iterator i
+ = this->AliasTargets.find(name);
+ if (i != this->AliasTargets.end())
+ {
+ return i->second;
+ }
+ }
cmTargets& tgts = this->GetTargets();
cmTargets::iterator i = tgts.find ( name );
@@ -3986,23 +4179,36 @@ void cmMakefile::DefineProperties(cmake *cm)
("INCLUDE_DIRECTORIES", cmProperty::DIRECTORY,
"List of preprocessor include file search directories.",
"This property specifies the list of directories given "
- "so far to the include_directories command. "
- "This property exists on directories and targets. "
+ "so far to the include_directories command. "
+ "This property exists on directories and targets. "
"In addition to accepting values from the include_directories "
"command, values may be set directly on any directory or any "
- "target using the set_property command. "
+ "target using the set_property command. "
"A target gets its initial value for this property from the value "
- "of the directory property. "
+ "of the directory property. "
"A directory gets its initial value from its parent directory if "
- "it has one. "
+ "it has one. "
"Both directory and target property values are adjusted by calls "
"to the include_directories command."
"\n"
"The target property values are used by the generators to set "
- "the include paths for the compiler. "
+ "the include paths for the compiler. "
"See also the include_directories command.");
cm->DefineProperty
+ ("COMPILE_OPTIONS", cmProperty::DIRECTORY,
+ "List of options to pass to the compiler.",
+ "This property specifies the list of directories given "
+ "so far for this property. "
+ "This property exists on directories and targets."
+ "\n"
+ "The target property values are used by the generators to set "
+ "the options for the compiler.\n"
+ "Contents of COMPILE_OPTIONS may use \"generator expressions\" with "
+ "the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+
+ cm->DefineProperty
("LINK_DIRECTORIES", cmProperty::DIRECTORY,
"List of linker search directories.",
"This read-only property specifies the list of directories given "
@@ -4043,7 +4249,7 @@ void cmMakefile::DefineProperties(cmake *cm)
"\n"
"This property only works for Visual Studio 7 and above; it is ignored "
"on other generators. The property only applies when set on a directory "
- "whose CMakeLists.txt conatins a project() command.");
+ "whose CMakeLists.txt contains a project() command.");
cm->DefineProperty
("VS_GLOBAL_SECTION_POST_<section>", cmProperty::DIRECTORY,
"Specify a postSolution global section in Visual Studio.",
@@ -4059,7 +4265,7 @@ void cmMakefile::DefineProperties(cmake *cm)
"\n"
"This property only works for Visual Studio 7 and above; it is ignored "
"on other generators. The property only applies when set on a directory "
- "whose CMakeLists.txt conatins a project() command."
+ "whose CMakeLists.txt contains a project() command."
"\n"
"Note that CMake generates postSolution sections ExtensibilityGlobals "
"and ExtensibilityAddIns by default. If you set the corresponding "
@@ -4093,7 +4299,7 @@ cmMakefile::AddImportedTarget(const char* name, cmTarget::TargetType type,
}
//----------------------------------------------------------------------------
-cmTarget* cmMakefile::FindTargetToUse(const char* name)
+cmTarget* cmMakefile::FindTargetToUse(const char* name, bool excludeAliases)
{
// Look for an imported target. These take priority because they
// are more local in scope and do not have to be globally unique.
@@ -4105,15 +4311,25 @@ cmTarget* cmMakefile::FindTargetToUse(const char* name)
}
// Look for a target built in this directory.
- if(cmTarget* t = this->FindTarget(name))
+ if(cmTarget* t = this->FindTarget(name, excludeAliases))
{
return t;
}
// Look for a target built in this project.
- return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name);
+ return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name,
+ excludeAliases);
}
+//----------------------------------------------------------------------------
+bool cmMakefile::IsAlias(const char *name)
+{
+ if (this->AliasTargets.find(name) != this->AliasTargets.end())
+ return true;
+ return this->GetLocalGenerator()->GetGlobalGenerator()->IsAlias(name);
+}
+
+//----------------------------------------------------------------------------
cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name)
{
cmTarget *t = this->FindTargetToUse(name);
@@ -4124,6 +4340,14 @@ cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name)
bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg,
bool isCustom)
{
+ if(this->IsAlias(name.c_str()))
+ {
+ cmOStringStream e;
+ e << "cannot create target \"" << name
+ << "\" because an alias with the same name already exists.";
+ msg = e.str();
+ return false;
+ }
if(cmTarget* existing = this->FindTargetToUse(name.c_str()))
{
// The name given conflicts with an existing target. Produce an
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 74a731d5b..8bce9fd65 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -29,6 +29,9 @@
#include <cmsys/auto_ptr.hxx>
#include <cmsys/RegularExpression.hxx>
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+# include <cmsys/hash_map.hxx>
+#endif
class cmFunctionBlocker;
class cmCommand;
@@ -206,6 +209,7 @@ public:
*/
void AddDefineFlag(const char* definition);
void RemoveDefineFlag(const char* definition);
+ void AddCompileOption(const char* option);
/** Create a new imported target with the name and type given. */
cmTarget* AddImportedTarget(const char* name, cmTarget::TargetType type,
@@ -336,6 +340,7 @@ public:
cmTarget* AddLibrary(const char *libname, cmTarget::TargetType type,
const std::vector<std::string> &srcs,
bool excludeFromAll = false);
+ void AddAlias(const char *libname, cmTarget *tgt);
#if defined(CMAKE_BUILD_WITH_CMAKE)
/**
@@ -535,11 +540,12 @@ public:
this->GeneratorTargets = targets;
}
- cmTarget* FindTarget(const char* name);
+ cmTarget* FindTarget(const char* name, bool excludeAliases = false);
/** Find a target to use in place of the given name. The target
returned may be imported or built within the project. */
- cmTarget* FindTargetToUse(const char* name);
+ cmTarget* FindTargetToUse(const char* name, bool excludeAliases = false);
+ bool IsAlias(const char *name);
cmGeneratorTarget* FindGeneratorTargetToUse(const char* name);
/**
@@ -647,7 +653,7 @@ public:
const std::vector<std::string>& GetListFiles() const
{ return this->ListFiles; }
///! When the file changes cmake will be re-run from the build system.
- void AddCMakeDependFile(const char* file)
+ void AddCMakeDependFile(const std::string& file)
{ this->ListFiles.push_back(file);}
/**
@@ -665,7 +671,7 @@ public:
*/
const std::vector<std::string>& GetOutputFiles() const
{ return this->OutputFiles; }
- void AddCMakeOutputFile(const char* file)
+ void AddCMakeOutputFile(const std::string& file)
{ this->OutputFiles.push_back(file);}
/**
@@ -866,10 +872,21 @@ public:
{
return this->IncludeDirectoriesEntries;
}
+ std::vector<cmValueWithOrigin> GetCompileOptionsEntries() const
+ {
+ return this->CompileOptionsEntries;
+ }
+ std::vector<cmValueWithOrigin> GetCompileDefinitionsEntries() const
+ {
+ return this->CompileDefinitionsEntries;
+ }
bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; }
void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; }
+ std::set<cmStdString> const & GetSystemIncludeDirectories() const
+ { return this->SystemIncludeDirectories; }
+
protected:
// add link libraries and directories to the target
void AddGlobalLinkInformation(const char* name, cmTarget& target);
@@ -890,6 +907,7 @@ protected:
// libraries, classes, and executables
cmTargets Targets;
+ std::map<std::string, cmTarget*> AliasTargets;
cmGeneratorTargetsType GeneratorTargets;
std::vector<cmSourceFile*> SourceFiles;
@@ -919,6 +937,8 @@ protected:
std::string DefineFlags;
std::vector<cmValueWithOrigin> IncludeDirectoriesEntries;
+ std::vector<cmValueWithOrigin> CompileOptionsEntries;
+ std::vector<cmValueWithOrigin> CompileDefinitionsEntries;
// Track the value of the computed DEFINITIONS property.
void AddDefineFlag(const char*, std::string&);
@@ -1022,6 +1042,26 @@ private:
bool GeneratingBuildSystem;
+ /**
+ * Old version of GetSourceFileWithOutput(const char*) kept for
+ * backward-compatibility. It implements a linear search and support
+ * relative file paths. It is used as a fall back by
+ * GetSourceFileWithOutput(const char*).
+ */
+ cmSourceFile *LinearGetSourceFileWithOutput(const char *cname);
+
+ // A map for fast output to input look up.
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ typedef cmsys::hash_map<std::string, cmSourceFile*> OutputToSourceMap;
+#else
+ typedef std::map<std::string, cmSourceFile*> OutputToSourceMap;
+#endif
+ OutputToSourceMap OutputToSource;
+
+ void UpdateOutputToSourceMap(std::vector<std::string> const& outputs,
+ cmSourceFile* source);
+ void UpdateOutputToSourceMap(std::string const& output,
+ cmSourceFile* source);
};
//----------------------------------------------------------------------------
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index b7a454b17..3a71bd6eb 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -30,11 +30,8 @@ cmMakefileExecutableTargetGenerator
this->TargetNamePDB, this->ConfigName);
this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
- this->TargetNameOut,
this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
- this->MacContentDirectory =
- this->OSXBundleGenerator->GetMacContentDirectory();
}
//----------------------------------------------------------------------------
@@ -103,11 +100,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Construct the full path version of the names.
std::string outpath = this->Target->GetDirectory(this->ConfigName);
- outpath += "/";
if(this->Target->IsAppBundleOnApple())
{
this->OSXBundleGenerator->CreateAppBundle(targetName, outpath);
}
+ outpath += "/";
std::string outpathImp;
if(relink)
{
@@ -341,13 +338,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
vars.CMTarget = this->Target;
vars.Language = linkLanguage;
vars.Objects = buildObjs.c_str();
- std::string objdir = cmake::GetCMakeFilesDirectoryPostSlash();
- objdir += this->Target->GetName();
- objdir += ".dir";
- objdir = this->Convert(objdir.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
- vars.ObjectDir = objdir.c_str();
+ std::string objectDir = this->Target->GetSupportDirectory();
+ objectDir = this->Convert(objectDir.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::SHELL);
+ vars.ObjectDir = objectDir.c_str();
vars.Target = targetOutPathReal.c_str();
vars.TargetPDB = targetOutPathPDB.c_str();
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 5b4e4d774..ffe68e5b2 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -24,19 +24,14 @@ cmMakefileLibraryTargetGenerator
::cmMakefileLibraryTargetGenerator(cmTarget* target):
cmMakefileTargetGenerator(target)
{
- cmOSXBundleGenerator::PrepareTargetProperties(this->Target);
-
this->CustomCommandDriver = OnDepends;
this->Target->GetLibraryNames(
this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
- this->TargetNameOut,
this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
- this->MacContentDirectory =
- this->OSXBundleGenerator->GetMacContentDirectory();
}
//----------------------------------------------------------------------------
@@ -149,12 +144,8 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
}
std::string extraFlags;
- this->LocalGenerator->AppendFlags
- (extraFlags,this->Target->GetProperty("STATIC_LIBRARY_FLAGS"));
- std::string staticLibraryFlagsConfig = "STATIC_LIBRARY_FLAGS_";
- staticLibraryFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
- this->LocalGenerator->AppendFlags
- (extraFlags, this->Target->GetProperty(staticLibraryFlagsConfig.c_str()));
+ this->LocalGenerator->GetStaticLibraryFlags(extraFlags,
+ cmSystemTools::UpperCase(this->ConfigName), this->Target);
this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), false);
}
@@ -292,14 +283,15 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string outpathImp;
if(this->Target->IsFrameworkOnApple())
{
- outpath = this->MacContentDirectory;
- this->OSXBundleGenerator->CreateFramework(targetName);
+ outpath = this->Target->GetDirectory(this->ConfigName);
+ this->OSXBundleGenerator->CreateFramework(targetName, outpath);
+ outpath += "/";
}
else if(this->Target->IsCFBundleOnApple())
{
outpath = this->Target->GetDirectory(this->ConfigName);
- outpath += "/";
this->OSXBundleGenerator->CreateCFBundle(targetName, outpath);
+ outpath += "/";
}
else if(relink)
{
@@ -585,13 +577,11 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
vars.CMTarget = this->Target;
vars.Language = linkLanguage;
vars.Objects = buildObjs.c_str();
- std::string objdir = cmake::GetCMakeFilesDirectoryPostSlash();
- objdir += this->Target->GetName();
- objdir += ".dir";
- objdir = this->Convert(objdir.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
- vars.ObjectDir = objdir.c_str();
+ std::string objectDir = this->Target->GetSupportDirectory();
+ objectDir = this->Convert(objectDir.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::SHELL);
+ vars.ObjectDir = objectDir.c_str();
vars.Target = targetOutPathReal.c_str();
vars.LinkLibraries = linkLibs.c_str();
vars.ObjectsQuoted = buildObjs.c_str();
@@ -727,7 +717,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
commands1.clear();
// Add a rule to create necessary symlinks for the library.
- if(targetOutPath != targetOutPathReal)
+ // Frameworks are handled by cmOSXBundleGenerator.
+ if(targetOutPath != targetOutPathReal && !this->Target->IsFrameworkOnApple())
{
std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
symlink += targetOutPathReal;
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 4220ae148..5e6c54822 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -271,6 +271,9 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l)
this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
lang, this->ConfigName);
+ this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target,
+ lang);
+
// Add include directory flags.
this->AddIncludeFlags(flags, lang);
@@ -282,6 +285,10 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l)
this->LocalGenerator->
AppendFlags(flags,this->GetFrameworkFlags().c_str());
+ // Add target-specific flags.
+ this->LocalGenerator->AddCompileOptions(flags, this->Target,
+ lang, this->ConfigName);
+
ByLanguageMap::value_type entry(l, flags);
i = this->FlagsByLanguage.insert(entry).first;
}
@@ -302,9 +309,8 @@ std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
}
// Add preprocessor definitions for this target and configuration.
- this->LocalGenerator->AppendDefines
- (defines, this->Target->GetCompileDefinitions(
- this->LocalGenerator->ConfigurationName.c_str()));
+ this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
+ this->LocalGenerator->ConfigurationName.c_str());
std::string definesString;
this->LocalGenerator->JoinDefines(defines, definesString, lang);
@@ -339,15 +345,6 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
*this->FlagFileStream << *l << "_DEFINES = " << this->GetDefines(*l) <<
"\n\n";
}
-
- // Add target-specific flags.
- if(this->Target->GetProperty("COMPILE_FLAGS"))
- {
- std::string flags;
- this->LocalGenerator->AppendFlags
- (flags, this->Target->GetProperty("COMPILE_FLAGS"));
- *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n";
- }
}
@@ -357,7 +354,7 @@ cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()
(cmSourceFile& source, const char* pkgloc)
{
// Skip OS X content when not building a Framework or Bundle.
- if(this->Generator->MacContentDirectory.empty())
+ if(!this->Generator->GetTarget()->IsBundleOnApple())
{
return;
}
@@ -532,37 +529,8 @@ cmMakefileTargetGenerator
langFlags += "_FLAGS)";
this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
- // Add target-specific flags.
- if(this->Target->GetProperty("COMPILE_FLAGS"))
- {
- std::string langIncludeExpr = "CMAKE_";
- langIncludeExpr += lang;
- langIncludeExpr += "_FLAG_REGEX";
- const char* regex = this->Makefile->
- GetDefinition(langIncludeExpr.c_str());
- if(regex)
- {
- cmsys::RegularExpression r(regex);
- std::vector<std::string> args;
- cmSystemTools::ParseWindowsCommandLine(
- this->Target->GetProperty("COMPILE_FLAGS"),
- args);
- for(std::vector<std::string>::iterator i = args.begin();
- i != args.end(); ++i)
- {
- if(r.find(i->c_str()))
- {
- this->LocalGenerator->AppendFlags
- (flags, i->c_str());
- }
- }
- }
- else
- {
- this->LocalGenerator->AppendFlags
- (flags, this->Target->GetProperty("COMPILE_FLAGS"));
- }
- }
+ std::string configUpper =
+ cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
// Add Fortran format flags.
if(strcmp(lang, "Fortran") == 0)
@@ -594,8 +562,6 @@ cmMakefileTargetGenerator
<< compile_defs << "\n"
<< "\n";
}
- std::string configUpper =
- cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
std::string defPropName = "COMPILE_DEFINITIONS_";
defPropName += configUpper;
if(const char* config_compile_defs =
@@ -672,7 +638,7 @@ cmMakefileTargetGenerator
cmLocalGenerator::NONE,
cmLocalGenerator::SHELL).c_str();
vars.Object = shellObj.c_str();
- std::string objectDir = cmSystemTools::GetFilenamePath(obj);
+ std::string objectDir = this->Target->GetSupportDirectory();
objectDir = this->Convert(objectDir.c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::SHELL);
@@ -1869,7 +1835,8 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
lang, config);
std::string includeFlags =
- this->LocalGenerator->GetIncludeFlags(includes, lang, useResponseFile);
+ this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget,
+ lang, useResponseFile);
if(includeFlags.empty())
{
return;
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index 2798e5462..f7a1e2e56 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -233,7 +233,6 @@ protected:
std::string TargetNamePDB;
// Mac OS X content info.
- std::string MacContentDirectory;
std::set<cmStdString> MacContentFolders;
cmOSXBundleGenerator* OSXBundleGenerator;
MacOSXContentGeneratorType* MacOSXContentGenerator;
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx
index 4456aa794..1fa4e95b6 100644
--- a/Source/cmMakefileUtilityTargetGenerator.cxx
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -25,11 +25,8 @@ cmMakefileUtilityTargetGenerator
{
this->CustomCommandDriver = OnUtility;
this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
- this->TargetNameOut,
this->ConfigName);
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
- this->MacContentDirectory =
- this->OSXBundleGenerator->GetMacContentDirectory();
}
//----------------------------------------------------------------------------
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 7e48cd716..57adeba23 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -36,8 +36,6 @@ cmNinjaNormalTargetGenerator(cmTarget* target)
, TargetNamePDB()
, TargetLinkLanguage(0)
{
- cmOSXBundleGenerator::PrepareTargetProperties(target);
-
this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName());
if (target->GetType() == cmTarget::EXECUTABLE)
target->GetExecutableNames(this->TargetNameOut,
@@ -61,7 +59,6 @@ cmNinjaNormalTargetGenerator(cmTarget* target)
}
this->OSXBundleGenerator = new cmOSXBundleGenerator(target,
- this->TargetNameOut,
this->GetConfigName());
this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}
@@ -74,7 +71,8 @@ cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator()
void cmNinjaNormalTargetGenerator::Generate()
{
if (!this->TargetLinkLanguage) {
- cmSystemTools::Error("CMake can not determine linker language for target:",
+ cmSystemTools::Error("CMake can not determine linker language for "
+ "target: ",
this->GetTarget()->GetName());
return;
}
@@ -267,7 +265,8 @@ cmNinjaNormalTargetGenerator
rspcontent);
}
- if (this->TargetNameOut != this->TargetNameReal) {
+ if (this->TargetNameOut != this->TargetNameReal &&
+ !this->GetTarget()->IsFrameworkOnApple()) {
std::string cmakeCommand =
this->GetLocalGenerator()->ConvertToOutputFormat(
this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND"),
@@ -383,24 +382,32 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
if (this->GetTarget()->IsAppBundleOnApple())
{
// Create the app bundle
- std::string outpath;
+ std::string outpath =
+ this->GetTarget()->GetDirectory(this->GetConfigName());
this->OSXBundleGenerator->CreateAppBundle(this->TargetNameOut, outpath);
// Calculate the output path
- targetOutput = outpath + this->TargetNameOut;
+ targetOutput = outpath;
+ targetOutput += "/";
+ targetOutput += this->TargetNameOut;
targetOutput = this->ConvertToNinjaPath(targetOutput.c_str());
- targetOutputReal = outpath + this->TargetNameReal;
+ targetOutputReal = outpath;
+ targetOutputReal += "/";
+ targetOutputReal += this->TargetNameReal;
targetOutputReal = this->ConvertToNinjaPath(targetOutputReal.c_str());
}
else if (this->GetTarget()->IsFrameworkOnApple())
{
// Create the library framework.
- this->OSXBundleGenerator->CreateFramework(this->TargetNameOut);
+ std::string outpath =
+ this->GetTarget()->GetDirectory(this->GetConfigName());
+ this->OSXBundleGenerator->CreateFramework(this->TargetNameOut, outpath);
}
else if(this->GetTarget()->IsCFBundleOnApple())
{
// Create the core foundation bundle.
- std::string outpath;
+ std::string outpath =
+ this->GetTarget()->GetDirectory(this->GetConfigName());
this->OSXBundleGenerator->CreateCFBundle(this->TargetNameOut, outpath);
}
@@ -505,7 +512,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
const std::string objPath = GetTarget()->GetSupportDirectory();
vars["OBJECT_DIR"] = ConvertToNinjaPath(objPath.c_str());
EnsureDirectoryExists(objPath);
- // ar.exe can't handle backslashes in rsp files (implictly used by gcc)
+ // ar.exe can't handle backslashes in rsp files (implicitly used by gcc)
std::string& linkLibraries = vars["LINK_LIBRARIES"];
std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/');
}
@@ -572,32 +579,38 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
#endif
}
+ //Get the global generator as we are going to be call WriteBuild numerous
+ //times in the following section
+ cmGlobalNinjaGenerator* globalGenerator = this->GetGlobalGenerator();
+
+
const std::string rspfile = std::string
(cmake::GetCMakeFilesDirectoryPostSlash()) +
this->GetTarget()->GetName() + ".rsp";
// Write the build statement for this target.
- cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
- comment.str(),
- this->LanguageLinkerRule(),
- outputs,
- explicitDeps,
- implicitDeps,
- emptyDeps,
- vars,
- rspfile,
- commandLineLengthLimit);
-
- if (targetOutput != targetOutputReal) {
+ globalGenerator->WriteBuild(this->GetBuildFileStream(),
+ comment.str(),
+ this->LanguageLinkerRule(),
+ outputs,
+ explicitDeps,
+ implicitDeps,
+ emptyDeps,
+ vars,
+ rspfile,
+ commandLineLengthLimit);
+
+ if (targetOutput != targetOutputReal &&
+ !this->GetTarget()->IsFrameworkOnApple()) {
if (targetType == cmTarget::EXECUTABLE) {
- cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
+ globalGenerator->WriteBuild(this->GetBuildFileStream(),
"Create executable symlink " + targetOutput,
- "CMAKE_SYMLINK_EXECUTABLE",
- cmNinjaDeps(1, targetOutput),
- cmNinjaDeps(1, targetOutputReal),
- emptyDeps,
- emptyDeps,
- symlinkVars);
+ "CMAKE_SYMLINK_EXECUTABLE",
+ cmNinjaDeps(1, targetOutput),
+ cmNinjaDeps(1, targetOutputReal),
+ emptyDeps,
+ emptyDeps,
+ symlinkVars);
} else {
cmNinjaDeps symlinks;
const std::string soName = this->GetTargetFilePath(this->TargetNameSO);
@@ -609,30 +622,30 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
symlinks.push_back(soName);
}
symlinks.push_back(targetOutput);
- cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
- "Create library symlink " + targetOutput,
- "CMAKE_SYMLINK_LIBRARY",
- symlinks,
- cmNinjaDeps(1, targetOutputReal),
- emptyDeps,
- emptyDeps,
- symlinkVars);
+ globalGenerator->WriteBuild(this->GetBuildFileStream(),
+ "Create library symlink " + targetOutput,
+ "CMAKE_SYMLINK_LIBRARY",
+ symlinks,
+ cmNinjaDeps(1, targetOutputReal),
+ emptyDeps,
+ emptyDeps,
+ symlinkVars);
}
}
if (!this->TargetNameImport.empty()) {
// Since using multiple outputs would mess up the $out variable, use an
// alias for the import library.
- cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
- "Alias for import library.",
- cmNinjaDeps(1, targetOutputImplib),
- cmNinjaDeps(1, targetOutputReal));
+ globalGenerator->WritePhonyBuild(this->GetBuildFileStream(),
+ "Alias for import library.",
+ cmNinjaDeps(1, targetOutputImplib),
+ cmNinjaDeps(1, targetOutputReal));
}
// Add aliases for the file name and the target name.
- this->GetGlobalGenerator()->AddTargetAlias(this->TargetNameOut,
+ globalGenerator->AddTargetAlias(this->TargetNameOut,
this->GetTarget());
- this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
+ globalGenerator->AddTargetAlias(this->GetTargetName(),
this->GetTarget());
}
@@ -643,11 +656,11 @@ void cmNinjaNormalTargetGenerator::WriteObjectLibStatement()
cmNinjaDeps outputs;
this->GetLocalGenerator()->AppendTargetOutputs(this->GetTarget(), outputs);
cmNinjaDeps depends = this->GetObjects();
- cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
- "Object library "
- + this->GetTargetName(),
- outputs,
- depends);
+ this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
+ "Object library "
+ + this->GetTargetName(),
+ outputs,
+ depends);
// Add aliases for the target name.
this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 3fb823cb0..9c8b4810b 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -150,15 +150,19 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
language.c_str(),
this->GetConfigName());
+ this->LocalGenerator->AddVisibilityPresetFlags(flags, this->Target,
+ language.c_str());
+
// Add include directory flags.
+ const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
{
std::vector<std::string> includes;
- const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
this->LocalGenerator->GetIncludeDirectories(includes,
this->GeneratorTarget,
language.c_str(), config);
std::string includeFlags =
- this->LocalGenerator->GetIncludeFlags(includes, language.c_str(),
+ this->LocalGenerator->GetIncludeFlags(includes, this->GeneratorTarget,
+ language.c_str(),
language == "RC" ? true : false); // full include paths for RC
// needed by cmcldeps
if(cmGlobalNinjaGenerator::IsMinGW())
@@ -171,36 +175,8 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
this->LocalGenerator->AppendFlags(flags, this->Makefile->GetDefineFlags());
// Add target-specific flags.
- if(this->Target->GetProperty("COMPILE_FLAGS"))
- {
- std::string langIncludeExpr = "CMAKE_";
- langIncludeExpr += language;
- langIncludeExpr += "_FLAG_REGEX";
- const char* regex = this->Makefile->
- GetDefinition(langIncludeExpr.c_str());
- if(regex)
- {
- cmsys::RegularExpression r(regex);
- std::vector<std::string> args;
- cmSystemTools::ParseWindowsCommandLine(
- this->Target->GetProperty("COMPILE_FLAGS"),
- args);
- for(std::vector<std::string>::iterator i = args.begin();
- i != args.end(); ++i)
- {
- if(r.find(i->c_str()))
- {
- this->LocalGenerator->AppendFlags
- (flags, i->c_str());
- }
- }
- }
- else
- {
- this->LocalGenerator->AppendFlags
- (flags, this->Target->GetProperty("COMPILE_FLAGS"));
- }
- }
+ this->LocalGenerator->AddCompileOptions(flags, this->Target,
+ language.c_str(), config);
// Add source file specific flags.
this->LocalGenerator->AppendFlags(flags,
@@ -226,9 +202,8 @@ ComputeDefines(cmSourceFile *source, const std::string& language)
}
// Add preprocessor definitions for this target and configuration.
- this->LocalGenerator->AppendDefines
- (defines,
- this->Target->GetCompileDefinitions(this->GetConfigName()));
+ this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
+ this->GetConfigName());
this->LocalGenerator->AppendDefines
(defines,
source->GetProperty("COMPILE_DEFINITIONS"));
@@ -568,12 +543,10 @@ cmNinjaTargetGenerator
vars["DEP_FILE"] = objectFileName + ".d";;
EnsureParentDirectoryExists(objectFileName);
- std::string objectDir = cmSystemTools::GetFilenamePath(objectFileName);
- objectDir = this->GetLocalGenerator()->Convert(objectDir.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL);
- vars["OBJECT_DIR"] = objectDir;
-
+ std::string objectDir = this->Target->GetSupportDirectory();
+ vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ ConvertToNinjaPath(objectDir.c_str()).c_str(),
+ cmLocalGenerator::SHELL);
this->SetMsvcTargetPdbVariable(vars);
@@ -623,24 +596,24 @@ cmNinjaTargetGenerator
sourceFileName);
}
- cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
- comment,
- rule,
- outputs,
- explicitDeps,
- implicitDeps,
- orderOnlyDeps,
- vars);
+ this->GetGlobalGenerator()->WriteBuild(this->GetBuildFileStream(),
+ comment,
+ rule,
+ outputs,
+ explicitDeps,
+ implicitDeps,
+ orderOnlyDeps,
+ vars);
if(const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
std::vector<std::string> outputList;
cmSystemTools::ExpandListArgument(objectOutputs, outputList);
std::transform(outputList.begin(), outputList.end(), outputList.begin(),
MapToNinjaPath());
- cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
- "Additional output files.",
- outputList,
- outputs);
+ this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
+ "Additional output files.",
+ outputList,
+ outputs);
}
}
@@ -701,7 +674,7 @@ cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
cmSourceFile& source, const char* pkgloc)
{
// Skip OS X content when not building a Framework or Bundle.
- if(this->Generator->OSXBundleGenerator->GetMacContentDirectory().empty())
+ if(!this->Generator->GetTarget()->IsBundleOnApple())
{
return;
}
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 9c2fd13dd..755ce6edc 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -61,11 +61,11 @@ void cmNinjaUtilityTargetGenerator::Generate()
this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(), deps);
if (commands.empty()) {
- cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
- "Utility command for "
- + this->GetTargetName(),
- outputs,
- deps);
+ this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
+ "Utility command for "
+ + this->GetTargetName(),
+ outputs,
+ deps);
} else {
std::string command =
this->GetLocalGenerator()->BuildCommandLine(commands);
@@ -105,10 +105,11 @@ void cmNinjaUtilityTargetGenerator::Generate()
cmNinjaDeps(1, utilCommandName),
deps);
- cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
- "",
- outputs,
- cmNinjaDeps(1, utilCommandName));
+ this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
+ "",
+ outputs,
+ cmNinjaDeps(1, utilCommandName)
+ );
}
this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx
index 42fad0742..a475c7cfa 100644
--- a/Source/cmOSXBundleGenerator.cxx
+++ b/Source/cmOSXBundleGenerator.cxx
@@ -16,38 +16,19 @@
#include <cassert>
-void cmOSXBundleGenerator::PrepareTargetProperties(cmTarget* target)
-{
- if(target->IsCFBundleOnApple())
- {
- target->SetProperty("PREFIX", "");
- target->SetProperty("SUFFIX", "");
- }
-}
-
//----------------------------------------------------------------------------
cmOSXBundleGenerator::
cmOSXBundleGenerator(cmTarget* target,
- std::string targetNameOut,
const char* configName)
: Target(target)
, Makefile(target->GetMakefile())
, LocalGenerator(Makefile->GetLocalGenerator())
- , TargetNameOut(targetNameOut)
, ConfigName(configName)
- , MacContentDirectory()
- , FrameworkVersion()
, MacContentFolders(0)
{
if (this->MustSkip())
return;
- this->MacContentDirectory =
- this->Target->GetMacContentDirectory(this->ConfigName,
- /*implib*/ false,
- /*includeMacOS*/ false);
- if(this->Target->IsFrameworkOnApple())
- this->FrameworkVersion = this->Target->GetFrameworkVersion();
}
//----------------------------------------------------------------------------
@@ -57,41 +38,60 @@ bool cmOSXBundleGenerator::MustSkip()
}
//----------------------------------------------------------------------------
-void cmOSXBundleGenerator::CreateAppBundle(std::string& targetName,
+void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
std::string& outpath)
{
if (this->MustSkip())
return;
// Compute bundle directory names.
- outpath = this->MacContentDirectory;
- outpath += "MacOS";
- cmSystemTools::MakeDirectory(outpath.c_str());
- outpath += "/";
- this->Makefile->AddCMakeOutputFile(outpath.c_str());
+ std::string out = outpath;
+ out += "/";
+ out += this->Target->GetAppBundleDirectory(this->ConfigName, false);
+ cmSystemTools::MakeDirectory(out.c_str());
+ this->Makefile->AddCMakeOutputFile(out);
+
+ std::string newoutpath = out;
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
- std::string plist = this->MacContentDirectory + "Info.plist";
+ std::string plist = outpath;
+ plist += "/";
+ plist += this->Target->GetAppBundleDirectory(this->ConfigName, true);
+ plist += "/Info.plist";
this->LocalGenerator->GenerateAppleInfoPList(this->Target,
targetName.c_str(),
plist.c_str());
- this->Makefile->AddCMakeOutputFile(plist.c_str());
+ this->Makefile->AddCMakeOutputFile(plist);
+ outpath = newoutpath;
}
//----------------------------------------------------------------------------
-void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
+void cmOSXBundleGenerator::CreateFramework(
+ const std::string& targetName, const std::string& outpath)
{
if (this->MustSkip())
return;
assert(this->MacContentFolders);
+ // Compute the location of the top-level foo.framework directory.
+ std::string contentdir = outpath + "/" +
+ this->Target->GetFrameworkDirectory(this->ConfigName, true);
+ contentdir += "/";
+
+ std::string newoutpath = outpath + "/" +
+ this->Target->GetFrameworkDirectory(this->ConfigName, false);
+
+ std::string frameworkVersion = this->Target->GetFrameworkVersion();
+
// Configure the Info.plist file into the Resources directory.
this->MacContentFolders->insert("Resources");
- std::string plist = this->MacContentDirectory + "Resources/Info.plist";
+ std::string plist = newoutpath;
+ plist += "/Resources/Info.plist";
+ std::string name = cmSystemTools::GetFilenameName(targetName);
this->LocalGenerator->GenerateFrameworkInfoPList(this->Target,
- targetName.c_str(),
+ name.c_str(),
plist.c_str());
// TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
@@ -99,50 +99,42 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
std::string oldName;
std::string newName;
- // Compute the location of the top-level foo.framework directory.
- std::string top = this->Target->GetDirectory(this->ConfigName);
- top += "/";
- top += this->TargetNameOut;
- top += ".framework/";
// Make foo.framework/Versions
- std::string versions = top;
+ std::string versions = contentdir;
versions += "Versions";
cmSystemTools::MakeDirectory(versions.c_str());
// Make foo.framework/Versions/version
- std::string version = versions;
- version += "/";
- version += this->FrameworkVersion;
- cmSystemTools::MakeDirectory(version.c_str());
+ cmSystemTools::MakeDirectory(newoutpath.c_str());
// Current -> version
- oldName = this->FrameworkVersion;
+ oldName = frameworkVersion;
newName = versions;
newName += "/Current";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
- this->Makefile->AddCMakeOutputFile(newName.c_str());
+ this->Makefile->AddCMakeOutputFile(newName);
// foo -> Versions/Current/foo
oldName = "Versions/Current/";
- oldName += this->TargetNameOut;
- newName = top;
- newName += this->TargetNameOut;
+ oldName += name;
+ newName = contentdir;
+ newName += name;
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
- this->Makefile->AddCMakeOutputFile(newName.c_str());
+ this->Makefile->AddCMakeOutputFile(newName);
// Resources -> Versions/Current/Resources
if(this->MacContentFolders->find("Resources") !=
this->MacContentFolders->end())
{
oldName = "Versions/Current/Resources";
- newName = top;
+ newName = contentdir;
newName += "Resources";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
- this->Makefile->AddCMakeOutputFile(newName.c_str());
+ this->Makefile->AddCMakeOutputFile(newName);
}
// Headers -> Versions/Current/Headers
@@ -150,11 +142,11 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
this->MacContentFolders->end())
{
oldName = "Versions/Current/Headers";
- newName = top;
+ newName = contentdir;
newName += "Headers";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
- this->Makefile->AddCMakeOutputFile(newName.c_str());
+ this->Makefile->AddCMakeOutputFile(newName);
}
// PrivateHeaders -> Versions/Current/PrivateHeaders
@@ -162,36 +154,37 @@ void cmOSXBundleGenerator::CreateFramework(std::string const& targetName)
this->MacContentFolders->end())
{
oldName = "Versions/Current/PrivateHeaders";
- newName = top;
+ newName = contentdir;
newName += "PrivateHeaders";
cmSystemTools::RemoveFile(newName.c_str());
cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
- this->Makefile->AddCMakeOutputFile(newName.c_str());
+ this->Makefile->AddCMakeOutputFile(newName);
}
}
//----------------------------------------------------------------------------
-void cmOSXBundleGenerator::CreateCFBundle(std::string& targetName,
- std::string& outpath)
+void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
+ const std::string& root)
{
if (this->MustSkip())
return;
// Compute bundle directory names.
- outpath = this->MacContentDirectory;
- outpath += "MacOS";
- cmSystemTools::MakeDirectory(outpath.c_str());
- outpath += "/";
- this->Makefile->AddCMakeOutputFile(outpath.c_str());
+ std::string out = root;
+ out += "/";
+ out += this->Target->GetCFBundleDirectory(this->ConfigName, false);
+ cmSystemTools::MakeDirectory(out.c_str());
+ this->Makefile->AddCMakeOutputFile(out);
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
- std::string plist = this->MacContentDirectory;
- plist += "Info.plist";
+ std::string plist =
+ this->Target->GetCFBundleDirectory(this->ConfigName, true);
+ plist += "/Info.plist";
this->LocalGenerator->GenerateAppleInfoPList(this->Target,
targetName.c_str(),
plist.c_str());
- this->Makefile->AddCMakeOutputFile(plist.c_str());
+ this->Makefile->AddCMakeOutputFile(plist);
}
//----------------------------------------------------------------------------
@@ -220,7 +213,11 @@ std::string
cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc)
{
// Construct the full path to the content subdirectory.
- std::string macdir = this->MacContentDirectory;
+
+ std::string macdir =
+ this->Target->GetMacContentDirectory(this->ConfigName,
+ /*implib*/ false);
+ macdir += "/";
macdir += pkgloc;
cmSystemTools::MakeDirectory(macdir.c_str());
diff --git a/Source/cmOSXBundleGenerator.h b/Source/cmOSXBundleGenerator.h
index 01e3cbeb4..ec82b9a15 100644
--- a/Source/cmOSXBundleGenerator.h
+++ b/Source/cmOSXBundleGenerator.h
@@ -25,15 +25,20 @@ class cmLocalGenerator;
class cmOSXBundleGenerator
{
public:
- static void PrepareTargetProperties(cmTarget* target);
-
cmOSXBundleGenerator(cmTarget* target,
- std::string targetNameOut,
const char* configName);
- void CreateAppBundle(std::string& targetName, std::string& outpath);
- void CreateFramework(std::string const& targetName);
- void CreateCFBundle(std::string& targetName, std::string& outpath);
+ // create an app bundle at a given root, and return
+ // the directory within the bundle that contains the executable
+ void CreateAppBundle(const std::string& targetName, std::string& root);
+
+ // create a framework at a given root
+ void CreateFramework(const std::string& targetName,
+ const std::string& root);
+
+ // create a cf bundle at a given root
+ void CreateCFBundle(const std::string& targetName,
+ const std::string& root);
struct MacOSXContentGeneratorType
{
@@ -46,10 +51,6 @@ public:
MacOSXContentGeneratorType* generator);
std::string InitMacOSXContentDirectory(const char* pkgloc);
- std::string GetMacContentDirectory() const
- { return this->MacContentDirectory; }
- std::string GetFrameworkVersion() const
- { return this->FrameworkVersion; }
void SetMacContentFolders(std::set<cmStdString>* macContentFolders)
{ this->MacContentFolders = macContentFolders; }
@@ -60,10 +61,7 @@ private:
cmTarget* Target;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
- std::string TargetNameOut;
const char* ConfigName;
- std::string MacContentDirectory;
- std::string FrameworkVersion;
std::set<cmStdString>* MacContentFolders;
};
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 6e41768b0..022082519 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -36,8 +36,26 @@ public:
OD(od), GlobalGenerator(od->GlobalGenerator)
{
this->FullPath = file;
- this->Directory = cmSystemTools::GetFilenamePath(file);
- this->FileName = cmSystemTools::GetFilenameName(file);
+
+ if(file.rfind(".framework") != std::string::npos)
+ {
+ cmsys::RegularExpression splitFramework;
+ splitFramework.compile("^(.*)/(.*).framework/(.*)$");
+ if(splitFramework.find(file) &&
+ (std::string::npos !=
+ splitFramework.match(3).find(splitFramework.match(2))))
+ {
+ this->Directory = splitFramework.match(1);
+ this->FileName =
+ std::string(file.begin() + this->Directory.size() + 1, file.end());
+ }
+ }
+
+ if(this->FileName.empty())
+ {
+ this->Directory = cmSystemTools::GetFilenamePath(file);
+ this->FileName = cmSystemTools::GetFilenameName(file);
+ }
}
virtual ~cmOrderDirectoriesConstraint() {}
@@ -305,6 +323,19 @@ void cmOrderDirectories::AddRuntimeLibrary(std::string const& fullPath,
if(!this->ImplicitDirectories.empty())
{
std::string dir = cmSystemTools::GetFilenamePath(fullPath);
+
+ if(fullPath.rfind(".framework") != std::string::npos)
+ {
+ cmsys::RegularExpression splitFramework;
+ splitFramework.compile("^(.*)/(.*).framework/(.*)$");
+ if(splitFramework.find(fullPath) &&
+ (std::string::npos !=
+ splitFramework.match(3).find(splitFramework.match(2))))
+ {
+ dir = splitFramework.match(1);
+ }
+ }
+
if(this->ImplicitDirectories.find(dir) !=
this->ImplicitDirectories.end())
{
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 831e92e92..a823f0595 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -440,7 +440,8 @@ cmPolicies::cmPolicies()
this->DefinePolicy(
CMP0016, "CMP0016",
- "target_link_libraries() reports error if only argument is not a target.",
+ "target_link_libraries() reports error if its only argument "
+ "is not a target.",
"In CMake 2.8.2 and lower the target_link_libraries() command silently "
"ignored if it was called with only one argument, and this argument "
"wasn't a valid target. "
@@ -452,7 +453,7 @@ cmPolicies::cmPolicies()
"Prefer files from the CMake module directory when including from there.",
"Starting with CMake 2.8.4, if a cmake-module shipped with CMake (i.e. "
"located in the CMake module directory) calls include() or "
- "find_package(), the files located in the the CMake module directory are "
+ "find_package(), the files located in the CMake module directory are "
"preferred over the files in CMAKE_MODULE_PATH. "
"This makes sure that the modules belonging to "
"CMake always get those files included which they expect, and against "
@@ -529,6 +530,77 @@ cmPolicies::cmPolicies()
"The NEW behavior for this policy is to link executables to "
"qtmain.lib automatically when they link to QtCore IMPORTED target.",
2,8,11,0, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0021, "CMP0021",
+ "Fatal error on relative paths in INCLUDE_DIRECTORIES target property.",
+ "CMake 2.8.10.2 and lower allowed the INCLUDE_DIRECTORIES target "
+ "property to contain relative paths. The base path for such relative "
+ "entries is not well defined. CMake 2.8.12 issues a FATAL_ERROR if the "
+ "INCLUDE_DIRECTORIES property contains a relative path."
+ "\n"
+ "The OLD behavior for this policy is not to warn about relative paths in "
+ "the INCLUDE_DIRECTORIES target property. "
+ "The NEW behavior for this policy is to issue a FATAL_ERROR if "
+ "INCLUDE_DIRECTORIES contains a relative path.",
+ 2,8,12,0, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0022, "CMP0022",
+ "INTERFACE_LINK_LIBRARIES defines the link interface.",
+ "CMake 2.8.11 constructed the 'link interface' of a target from "
+ "properties matching (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?. "
+ "The modern way to specify config-sensitive content is to use generator "
+ "expressions and the IMPORTED_ prefix makes uniform processing of the "
+ "link interface with generator expressions impossible. The "
+ "INTERFACE_LINK_LIBRARIES target property was introduced as a "
+ "replacement in CMake 2.8.12. This new property is named consistently "
+ "with the INTERFACE_COMPILE_DEFINITIONS, INTERFACE_INCLUDE_DIRECTORIES "
+ "and INTERFACE_COMPILE_OPTIONS properties. For in-build targets, CMake "
+ "will use the INTERFACE_LINK_LIBRARIES property as the source of the "
+ "link interface only if policy CMP0022 is NEW. "
+ "When exporting a target which has this policy set to NEW, only the "
+ "INTERFACE_LINK_LIBRARIES property will be processed and generated for "
+ "the IMPORTED target by default. A new option to the install(EXPORT) "
+ "and export commands allows export of the old-style properties for "
+ "compatibility with downstream users of CMake versions older than "
+ "2.8.12. "
+ "The target_link_libraries command will no longer populate the "
+ "properties matching LINK_INTERFACE_LIBRARIES(_<CONFIG>)? if this policy "
+ "is NEW."
+ "\n"
+ "The OLD behavior for this policy is to ignore the "
+ "INTERFACE_LINK_LIBRARIES property for in-build targets. "
+ "The NEW behavior for this policy is to use the INTERFACE_LINK_LIBRARIES "
+ "property for in-build targets, and ignore the old properties matching "
+ "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)?.",
+ 2,8,12,0, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0023, "CMP0023",
+ "Plain and keyword target_link_libraries signatures cannot be mixed.",
+ "CMake 2.8.12 introduced the target_link_libraries signature using "
+ "the PUBLIC, PRIVATE, and INTERFACE keywords to generalize the "
+ "LINK_PUBLIC and LINK_PRIVATE keywords introduced in CMake 2.8.7. "
+ "Use of signatures with any of these keywords sets the link interface "
+ "of a target explicitly, even if empty. "
+ "This produces confusing behavior when used in combination with the "
+ "historical behavior of the plain target_link_libraries signature. "
+ "For example, consider the code:\n"
+ " target_link_libraries(mylib A)\n"
+ " target_link_libraries(mylib PRIVATE B)\n"
+ "After the first line the link interface has not been set explicitly "
+ "so CMake would use the link implementation, A, as the link interface. "
+ "However, the second line sets the link interface to empty. "
+ "In order to avoid this subtle behavior CMake now prefers to disallow "
+ "mixing the plain and keyword signatures of target_link_libraries for "
+ "a single target."
+ "\n"
+ "The OLD behavior for this policy is to allow keyword and plain "
+ "target_link_libraries signatures to be mixed. "
+ "The NEW behavior for this policy is to not to allow mixing of the "
+ "keyword and plain signatures.",
+ 2,8,12,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()
@@ -770,7 +842,7 @@ std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id)
{
cmSystemTools::Error(
"Request for error text for undefined policy!");
- return "Request for warning text for undefined policy!";
+ return "Request for error text for undefined policy!";
}
cmOStringStream error;
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index c11af0714..5b843a9ad 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -70,6 +70,10 @@ public:
/// instead.
CMP0019, ///< No variable re-expansion in include and link info
CMP0020, ///< Automatically link Qt executables to qtmain target
+ CMP0021, ///< Fatal error on relative paths in INCLUDE_DIRECTORIES
+ /// target property
+ CMP0022, ///< INTERFACE_LINK_LIBRARIES defines the link interface
+ CMP0023, ///< Disallow mixing keyword and plain tll signatures
/** \brief Always the last entry.
*
diff --git a/Source/cmProjectCommand.h b/Source/cmProjectCommand.h
index a53cb3fb8..9547c4c8f 100644
--- a/Source/cmProjectCommand.h
+++ b/Source/cmProjectCommand.h
@@ -71,7 +71,13 @@ public:
"language \"NONE\" all checks for any language can be disabled. "
"If a variable exists called CMAKE_PROJECT_<projectName>_INCLUDE, "
"the file pointed to by that variable will be included as the last step "
- "of the project command.";
+ "of the project command."
+ "\n"
+ "The top-level CMakeLists.txt file for a project must contain a "
+ "literal, direct call to the project() command; loading one through "
+ "the include() command is not sufficient. "
+ "If no such call exists CMake will implicitly add one to the top that "
+ "enables the default languages (C and CXX).";
}
cmTypeMacro(cmProjectCommand, cmCommand);
diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx
index a1fa31f2a..93e39abeb 100644
--- a/Source/cmQtAutomoc.cxx
+++ b/Source/cmQtAutomoc.cxx
@@ -152,10 +152,46 @@ bool cmQtAutomoc::InitializeMocSourceFile(cmTarget* target)
return true;
}
-void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
+static void GetCompileDefinitionsAndDirectories(cmTarget *target,
+ const char * config,
+ std::string &incs,
+ std::string &defs)
{
cmMakefile* makefile = target->GetMakefile();
cmLocalGenerator* localGen = makefile->GetLocalGenerator();
+ std::vector<std::string> includeDirs;
+ cmGeneratorTarget gtgt(target);
+ // Get the include dirs for this target, without stripping the implicit
+ // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667
+ localGen->GetIncludeDirectories(includeDirs, &gtgt, "CXX", config, false);
+ const char* sep = "";
+ incs = "";
+ for(std::vector<std::string>::const_iterator incDirIt = includeDirs.begin();
+ incDirIt != includeDirs.end();
+ ++incDirIt)
+ {
+ incs += sep;
+ sep = ";";
+ incs += *incDirIt;
+ }
+
+ std::set<std::string> defines;
+ localGen->AddCompileDefinitions(defines, target, config);
+
+ sep = "";
+ for(std::set<std::string>::const_iterator defIt = defines.begin();
+ defIt != defines.end();
+ ++defIt)
+ {
+ defs += sep;
+ sep = ";";
+ defs += *defIt;
+ }
+}
+
+void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
+{
+ cmMakefile* makefile = target->GetMakefile();
const char* targetName = target->GetName();
bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE");
@@ -175,6 +211,7 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
currentLine.push_back("-E");
currentLine.push_back("cmake_automoc");
currentLine.push_back(targetDir);
+ currentLine.push_back("$<CONFIGURATION>");
cmCustomCommandLines commandLines;
commandLines.push_back(currentLine);
@@ -188,6 +225,7 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
#if defined(_WIN32) && !defined(__CYGWIN__)
bool usePRE_BUILD = false;
+ cmLocalGenerator* localGen = makefile->GetLocalGenerator();
cmGlobalGenerator* gg = localGen->GetGlobalGenerator();
if(strstr(gg->GetName(), "Visual Studio"))
{
@@ -219,8 +257,18 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
automocTargetName.c_str(), true,
workingDirectory.c_str(), depends,
commandLines, false, automocComment.c_str());
- // inherit FOLDER property from target (#13688)
- copyTargetProperty(automocTarget, target, "FOLDER");
+ // Set target folder
+ const char* automocFolder = makefile->GetCMakeInstance()->GetProperty(
+ "AUTOMOC_TARGETS_FOLDER");
+ if (automocFolder && *automocFolder)
+ {
+ automocTarget->SetProperty("FOLDER", automocFolder);
+ }
+ else
+ {
+ // inherit FOLDER property from target (#13688)
+ copyTargetProperty(automocTarget, target, "FOLDER");
+ }
target->AddUtility(automocTargetName.c_str());
}
@@ -263,36 +311,7 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
}
}
-
- std::vector<std::string> includeDirs;
- cmGeneratorTarget gtgt(target);
- // Get the include dirs for this target, without stripping the implicit
- // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667
- localGen->GetIncludeDirectories(includeDirs, &gtgt, "CXX", 0, false);
- std::string _moc_incs = "";
- const char* sep = "";
- for(std::vector<std::string>::const_iterator incDirIt = includeDirs.begin();
- incDirIt != includeDirs.end();
- ++incDirIt)
- {
- _moc_incs += sep;
- sep = ";";
- _moc_incs += *incDirIt;
- }
-
- const char* tmp = target->GetProperty("COMPILE_DEFINITIONS");
- std::string _moc_compile_defs;
- if (tmp)
- {
- _moc_compile_defs = target->GetCompileDefinitions(0);
- }
- tmp = makefile->GetProperty("COMPILE_DEFINITIONS");
- if (tmp)
- {
- _moc_compile_defs += ";";
- _moc_compile_defs += tmp;
- }
- tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS");
+ const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS");
std::string _moc_options = (tmp!=0 ? tmp : "");
// forget the variables added here afterwards again:
@@ -301,10 +320,6 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
makefile->AddDefinition("_moc_target_name",
cmLocalGenerator::EscapeForCMake(automocTargetName.c_str()).c_str());
- makefile->AddDefinition("_moc_incs",
- cmLocalGenerator::EscapeForCMake(_moc_incs.c_str()).c_str());
- makefile->AddDefinition("_moc_compile_defs",
- cmLocalGenerator::EscapeForCMake(_moc_compile_defs.c_str()).c_str());
makefile->AddDefinition("_moc_options",
cmLocalGenerator::EscapeForCMake(_moc_options.c_str()).c_str());
makefile->AddDefinition("_moc_files",
@@ -313,6 +328,89 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
cmLocalGenerator::EscapeForCMake(_moc_headers.c_str()).c_str());
makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE");
+ std::string _moc_incs;
+ std::string _moc_compile_defs;
+ std::vector<std::string> configs;
+ const char *config = makefile->GetConfigurations(configs);
+ GetCompileDefinitionsAndDirectories(target, config,
+ _moc_incs, _moc_compile_defs);
+
+ makefile->AddDefinition("_moc_incs",
+ cmLocalGenerator::EscapeForCMake(_moc_incs.c_str()).c_str());
+ makefile->AddDefinition("_moc_compile_defs",
+ cmLocalGenerator::EscapeForCMake(_moc_compile_defs.c_str()).c_str());
+
+ std::map<std::string, std::string> configIncludes;
+ std::map<std::string, std::string> configDefines;
+
+ for (std::vector<std::string>::const_iterator li = configs.begin();
+ li != configs.end(); ++li)
+ {
+ std::string config_moc_incs;
+ std::string config_moc_compile_defs;
+ GetCompileDefinitionsAndDirectories(target, li->c_str(),
+ config_moc_incs,
+ config_moc_compile_defs);
+ if (config_moc_incs != _moc_incs)
+ {
+ configIncludes["_moc_incs_" + *li] =
+ cmLocalGenerator::EscapeForCMake(config_moc_incs.c_str());
+ if(_moc_incs.empty())
+ {
+ _moc_incs = config_moc_incs;
+ }
+ }
+ if (config_moc_compile_defs != _moc_compile_defs)
+ {
+ configDefines["_moc_compile_defs_" + *li] =
+ cmLocalGenerator::EscapeForCMake(config_moc_compile_defs.c_str());
+ if(_moc_compile_defs.empty())
+ {
+ _moc_compile_defs = config_moc_compile_defs;
+ }
+ }
+ }
+
+ const char *qtVersion = makefile->GetDefinition("Qt5Core_VERSION_MAJOR");
+ if (!qtVersion)
+ {
+ qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR");
+ }
+ if (const char *targetQtVersion =
+ target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", 0))
+ {
+ qtVersion = targetQtVersion;
+ }
+ if (qtVersion)
+ {
+ makefile->AddDefinition("_target_qt_version", qtVersion);
+ }
+
+ {
+ const char *qtMoc = makefile->GetSafeDefinition("QT_MOC_EXECUTABLE");
+ makefile->AddDefinition("_qt_moc_executable", qtMoc);
+ }
+
+ if (strcmp(qtVersion, "5") == 0)
+ {
+ cmTarget *qt5Moc = makefile->FindTargetToUse("Qt5::moc");
+ if (!qt5Moc)
+ {
+ cmSystemTools::Error("Qt5::moc target not found ",
+ automocTargetName.c_str());
+ return;
+ }
+ makefile->AddDefinition("_qt_moc_executable", qt5Moc->GetLocation(0));
+ }
+ else
+ {
+ if (strcmp(qtVersion, "4") != 0)
+ {
+ cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and "
+ "Qt 5 ", automocTargetName.c_str());
+ }
+ }
+
const char* cmakeRoot = makefile->GetSafeDefinition("CMAKE_ROOT");
std::string inputFile = cmakeRoot;
inputFile += "/Modules/AutomocInfo.cmake.in";
@@ -320,17 +418,50 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
outputFile += "/AutomocInfo.cmake";
makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(),
false, true, false);
+
+ if (!configDefines.empty() || !configIncludes.empty())
+ {
+ std::ofstream infoFile(outputFile.c_str(), std::ios::app);
+ if ( !infoFile )
+ {
+ std::string error = "Internal CMake error when trying to open file: ";
+ error += outputFile.c_str();
+ error += " for writing.";
+ cmSystemTools::Error(error.c_str());
+ return;
+ }
+ if (!configDefines.empty())
+ {
+ for (std::map<std::string, std::string>::iterator
+ it = configDefines.begin(), end = configDefines.end();
+ it != end; ++it)
+ {
+ infoFile << "SET(AM_MOC_COMPILE_DEFINITIONS_" << it->first <<
+ " " << it->second << ")\n";
+ }
+ }
+ if (!configIncludes.empty())
+ {
+ for (std::map<std::string, std::string>::iterator
+ it = configIncludes.begin(), end = configIncludes.end();
+ it != end; ++it)
+ {
+ infoFile << "SET(AM_MOC_INCLUDES_" << it->first <<
+ " " << it->second << ")\n";
+ }
+ }
+ }
}
-bool cmQtAutomoc::Run(const char* targetDirectory)
+bool cmQtAutomoc::Run(const char* targetDirectory, const char *config)
{
bool success = true;
cmake cm;
cmGlobalGenerator* gg = this->CreateGlobalGenerator(&cm, targetDirectory);
cmMakefile* makefile = gg->GetCurrentLocalGenerator()->GetMakefile();
- this->ReadAutomocInfoFile(makefile, targetDirectory);
+ this->ReadAutomocInfoFile(makefile, targetDirectory, config);
this->ReadOldMocDefinitionsFile(makefile, targetDirectory);
this->Init();
@@ -367,7 +498,8 @@ cmGlobalGenerator* cmQtAutomoc::CreateGlobalGenerator(cmake* cm,
bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile,
- const char* targetDirectory)
+ const char* targetDirectory,
+ const char *config)
{
std::string filename(cmSystemTools::CollapseFullPath(targetDirectory));
cmSystemTools::ConvertToUnixSlashes(filename);
@@ -375,7 +507,7 @@ bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile,
if (!makefile->ReadListFile(0, filename.c_str()))
{
- cmSystemTools::Error("Error processing file:", filename.c_str());
+ cmSystemTools::Error("Error processing file: ", filename.c_str());
return false;
}
@@ -392,9 +524,26 @@ bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile,
this->Srcdir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_SOURCE_DIR");
this->Builddir = makefile->GetSafeDefinition("AM_CMAKE_CURRENT_BINARY_DIR");
this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE");
- this->MocCompileDefinitionsStr = makefile->GetSafeDefinition(
- "AM_MOC_COMPILE_DEFINITIONS");
- this->MocIncludesStr = makefile->GetSafeDefinition("AM_MOC_INCLUDES");
+ std::string compileDefsPropOrig = "AM_MOC_COMPILE_DEFINITIONS";
+ std::string compileDefsProp = compileDefsPropOrig;
+ if(config)
+ {
+ compileDefsProp += "_";
+ compileDefsProp += config;
+ }
+ const char *compileDefs = makefile->GetDefinition(compileDefsProp.c_str());
+ this->MocCompileDefinitionsStr = compileDefs ? compileDefs
+ : makefile->GetSafeDefinition(compileDefsPropOrig.c_str());
+ std::string includesPropOrig = "AM_MOC_INCLUDES";
+ std::string includesProp = includesPropOrig;
+ if(config)
+ {
+ includesProp += "_";
+ includesProp += config;
+ }
+ const char *includes = makefile->GetDefinition(includesProp.c_str());
+ this->MocIncludesStr = includes ? includes
+ : makefile->GetSafeDefinition(includesPropOrig.c_str());
this->MocOptionsStr = makefile->GetSafeDefinition("AM_MOC_OPTIONS");
this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR");
this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR");
@@ -696,7 +845,7 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
std::string ownMocHeaderFile;
std::string::size_type matchOffset = 0;
- // first a simply string check for "moc" is *much* faster than the regexp,
+ // first a simple string check for "moc" is *much* faster than the regexp,
// and if the string search already fails, we don't have to try the
// expensive regexp
if ((strstr(contentsString.c_str(), "moc") != NULL)
@@ -870,7 +1019,7 @@ void cmQtAutomoc::StrictParseCppFile(const std::string& absFilename,
bool dotMocIncluded = false;
std::string::size_type matchOffset = 0;
- // first a simply string check for "moc" is *much* faster than the regexp,
+ // first a simple string check for "moc" is *much* faster than the regexp,
// and if the string search already fails, we don't have to try the
// expensive regexp
if ((strstr(contentsString.c_str(), "moc") != NULL)
diff --git a/Source/cmQtAutomoc.h b/Source/cmQtAutomoc.h
index 01b68fc54..ebeeb0eee 100644
--- a/Source/cmQtAutomoc.h
+++ b/Source/cmQtAutomoc.h
@@ -21,7 +21,7 @@ class cmQtAutomoc
{
public:
cmQtAutomoc();
- bool Run(const char* targetDirectory);
+ bool Run(const char* targetDirectory, const char *config);
bool InitializeMocSourceFile(cmTarget* target);
void SetupAutomocTarget(cmTarget* target);
@@ -31,7 +31,8 @@ private:
const char* targetDirectory);
bool ReadAutomocInfoFile(cmMakefile* makefile,
- const char* targetDirectory);
+ const char* targetDirectory,
+ const char *config);
bool ReadOldMocDefinitionsFile(cmMakefile* makefile,
const char* targetDirectory);
void WriteOldMocDefinitionsFile(const char* targetDirectory);
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index cc10840fd..42078605a 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -84,12 +84,14 @@ bool cmSetPropertyCommand
{
doing = DoingNone;
this->AppendMode = true;
+ this->Remove = false;
this->AppendAsString = false;
}
else if(*arg == "APPEND_STRING")
{
doing = DoingNone;
this->AppendMode = true;
+ this->Remove = false;
this->AppendAsString = true;
}
else if(doing == DoingNames)
@@ -160,7 +162,7 @@ bool cmSetPropertyCommand::HandleGlobalMode()
}
if(this->AppendMode)
{
- cm->AppendProperty(name, value, this->AppendAsString);
+ cm->AppendProperty(name, value ? value : "", this->AppendAsString);
}
else
{
@@ -226,7 +228,7 @@ bool cmSetPropertyCommand::HandleDirectoryMode()
}
if(this->AppendMode)
{
- mf->AppendProperty(name, value, this->AppendAsString);
+ mf->AppendProperty(name, value ? value : "", this->AppendAsString);
}
else
{
@@ -242,6 +244,11 @@ bool cmSetPropertyCommand::HandleTargetMode()
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
ni != this->Names.end(); ++ni)
{
+ if (this->Makefile->IsAlias(ni->c_str()))
+ {
+ this->SetError("can not be used on an ALIAS target.");
+ return false;
+ }
if(cmTarget* target = this->Makefile->FindTargetToUse(ni->c_str()))
{
// Handle the current target.
diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx
index a2b50a8ef..78ef393cc 100644
--- a/Source/cmSetTargetPropertiesCommand.cxx
+++ b/Source/cmSetTargetPropertiesCommand.cxx
@@ -72,6 +72,11 @@ bool cmSetTargetPropertiesCommand
int i;
for(i = 0; i < numFiles; ++i)
{
+ if (this->Makefile->IsAlias(args[i].c_str()))
+ {
+ this->SetError("can not be used on an ALIAS target.");
+ return false;
+ }
bool ret = cmSetTargetPropertiesCommand::SetOneTarget
(args[i].c_str(),propertyPairs,this->Makefile);
if (!ret)
diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h
index 9dd7848d3..cf9c19350 100644
--- a/Source/cmSetTargetPropertiesCommand.h
+++ b/Source/cmSetTargetPropertiesCommand.h
@@ -104,7 +104,7 @@ public:
"are common values for this property."
"\n"
"For shared libraries VERSION and SOVERSION can be used to specify "
- "the build version and api version respectively. When building or "
+ "the build version and API version respectively. When building or "
"installing appropriate symlinks are created if the platform "
"supports symlinks and the linker supports so-names. "
"If only one of both is specified the missing is assumed to have "
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index 1d4b0c8b4..8bb7d96f5 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -483,7 +483,7 @@ void cmSourceFile::DefineProperties(cmake *cm)
"the source file is. If it is not set the language is determined "
"based on the file extension. Typical values are CXX C etc. Setting "
"this property for a file means this file will be compiled. "
- "Do not set this for header or files that should not be compiled.");
+ "Do not set this for headers or files that should not be compiled.");
cm->DefineProperty
("LOCATION", cmProperty::SOURCE_FILE,
@@ -551,7 +551,7 @@ void cmSourceFile::DefineProperties(cmake *cm)
"Some packages can wrap source files into alternate languages "
"to provide additional functionality. For example, C++ code "
"can be wrapped into Java or Python etc using SWIG etc. "
- "If WRAP_EXCLUDE is set to true (1 etc) that indicates then "
+ "If WRAP_EXCLUDE is set to true (1 etc) that indicates that "
"this source file should not be wrapped.");
}
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index e49edd878..68ba13f62 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -93,6 +93,10 @@ bool cmStringCommand
{
return this->HandleTimestampCommand(args);
}
+ else if(subCommand == "MAKE_C_IDENTIFIER")
+ {
+ return this->HandleMakeCIdentifierCommand(args);
+ }
std::string e = "does not recognize sub-command "+subCommand;
this->SetError(e.c_str());
@@ -530,8 +534,12 @@ void cmStringCommand::ClearMatches(cmMakefile* mf)
{
char name[128];
sprintf(name, "CMAKE_MATCH_%d", i);
- mf->AddDefinition(name, "");
- mf->MarkVariableAsUsed(name);
+ const char* s = mf->GetDefinition(name);
+ if(s && *s != 0)
+ {
+ mf->AddDefinition(name, "");
+ mf->MarkVariableAsUsed(name);
+ }
}
}
@@ -540,10 +548,14 @@ void cmStringCommand::StoreMatches(cmMakefile* mf,cmsys::RegularExpression& re)
{
for (unsigned int i=0; i<10; i++)
{
- char name[128];
- sprintf(name, "CMAKE_MATCH_%d", i);
- mf->AddDefinition(name, re.match(i).c_str());
- mf->MarkVariableAsUsed(name);
+ std::string m = re.match(i);
+ if(m.size() > 0)
+ {
+ char name[128];
+ sprintf(name, "CMAKE_MATCH_%d", i);
+ mf->AddDefinition(name, re.match(i).c_str());
+ mf->MarkVariableAsUsed(name);
+ }
}
}
@@ -755,6 +767,24 @@ bool cmStringCommand
}
//----------------------------------------------------------------------------
+bool cmStringCommand
+::HandleMakeCIdentifierCommand(std::vector<std::string> const& args)
+{
+ if(args.size() != 3)
+ {
+ this->SetError("sub-command MAKE_C_IDENTIFIER requires two arguments.");
+ return false;
+ }
+
+ const std::string& input = args[1];
+ const std::string& variableName = args[2];
+
+ this->Makefile->AddDefinition(variableName.c_str(),
+ cmSystemTools::MakeCidentifier(input.c_str()).c_str());
+ return true;
+}
+
+//----------------------------------------------------------------------------
bool cmStringCommand::HandleStripCommand(
std::vector<std::string> const& args)
{
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index 802e0b850..f584cfdbf 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -94,6 +94,7 @@ public:
" [RANDOM_SEED <seed>] <output variable>)\n"
" string(FIND <string> <substring> <output variable> [REVERSE])\n"
" string(TIMESTAMP <output variable> [<format string>] [UTC])\n"
+ " string(MAKE_C_IDENTIFIER <input string> <output variable>)\n"
"REGEX MATCH will match the regular expression once and store the "
"match in the output variable.\n"
"REGEX MATCHALL will match the regular expression as many times as "
@@ -176,7 +177,9 @@ public:
"and copied to the output as-is.\n"
"If no explicit <format string> is given it will default to:\n"
" %Y-%m-%dT%H:%M:%S for local time.\n"
- " %Y-%m-%dT%H:%M:%SZ for UTC.";
+ " %Y-%m-%dT%H:%M:%SZ for UTC.\n"
+ "MAKE_C_IDENTIFIER will write a string which can be used as an "
+ "identifier in C.";
}
cmTypeMacro(cmStringCommand, cmCommand);
@@ -200,6 +203,7 @@ protected:
bool HandleRandomCommand(std::vector<std::string> const& args);
bool HandleFindCommand(std::vector<std::string> const& args);
bool HandleTimestampCommand(std::vector<std::string> const& args);
+ bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args);
class RegexReplacement
{
diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx
index 0cfe7722d..e497b4642 100644
--- a/Source/cmSubdirCommand.cxx
+++ b/Source/cmSubdirCommand.cxx
@@ -64,7 +64,7 @@ bool cmSubdirCommand
else
{
std::string error = "Incorrect SUBDIRS command. Directory: ";
- error += *i + " does not exists.";
+ error += *i + " does not exist.";
this->SetError(error.c_str());
res = false;
}
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 67f302391..9ec49382a 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -638,6 +638,12 @@ bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command,
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
}
+ if (outputflag == OUTPUT_PASSTHROUGH)
+ {
+ cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
+ cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
+ }
+
cmsysProcess_SetTimeout(cp, timeout);
cmsysProcess_Execute(cp);
@@ -645,7 +651,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command,
char* data;
int length;
int pipe;
- if ( output || outputflag != OUTPUT_NONE )
+ if(outputflag != OUTPUT_PASSTHROUGH && (output || outputflag != OUTPUT_NONE))
{
while((pipe = cmsysProcess_WaitForData(cp, &data, &length, 0)) > 0)
{
@@ -1594,6 +1600,40 @@ std::string cmSystemTools::RelativePath(const char* local, const char* remote)
return cmsys::SystemTools::RelativePath(local, remote);
}
+std::string cmSystemTools::CollapseCombinedPath(std::string const& dir,
+ std::string const& file)
+{
+ if(dir.empty() || dir == ".")
+ {
+ return file;
+ }
+
+ std::vector<std::string> dirComponents;
+ std::vector<std::string> fileComponents;
+ cmSystemTools::SplitPath(dir.c_str(), dirComponents);
+ cmSystemTools::SplitPath(file.c_str(), fileComponents);
+
+ if(fileComponents.empty())
+ {
+ return dir;
+ }
+ if(fileComponents[0] != "")
+ {
+ // File is not a relative path.
+ return file;
+ }
+
+ std::vector<std::string>::iterator i = fileComponents.begin()+1;
+ while(i != fileComponents.end() && *i == ".." && dirComponents.size() > 1)
+ {
+ ++i; // Remove ".." file component.
+ dirComponents.pop_back(); // Remove last dir component.
+ }
+
+ dirComponents.insert(dirComponents.end(), i, fileComponents.end());
+ return cmSystemTools::JoinPath(dirComponents);
+}
+
#ifdef CMAKE_BUILD_WITH_CMAKE
//----------------------------------------------------------------------
bool cmSystemTools::UnsetEnv(const char* value)
@@ -1662,6 +1702,7 @@ cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment()
void cmSystemTools::EnableVSConsoleOutput()
{
+#ifdef _WIN32
// Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not
// display output to the console unless this environment variable is
// set. We need it to capture the output of these build tools.
@@ -1669,8 +1710,15 @@ void cmSystemTools::EnableVSConsoleOutput()
// either of these executables where NAME is created with
// CreateNamedPipe. This would bypass the internal buffering of the
// output and allow it to be captured on the fly.
-#ifdef _WIN32
cmSystemTools::PutEnv("vsconsoleoutput=1");
+
+# ifdef CMAKE_BUILD_WITH_CMAKE
+ // VS sets an environment variable to tell MS tools like "cl" to report
+ // output through a backdoor pipe instead of stdout/stderr. Unset the
+ // environment variable to close this backdoor for any path of process
+ // invocations that passes through CMake so we can capture the output.
+ cmSystemTools::UnsetEnv("VS_UNICODE_OUTPUT");
+# endif
#endif
}
@@ -1951,7 +1999,7 @@ bool extract_tar(const char* outFileName, bool verbose,
{
cmSystemTools::Error("Problem with archive_write_header(): ",
archive_error_string(ext));
- cmSystemTools::Error("Current file:",
+ cmSystemTools::Error("Current file: ",
archive_entry_pathname(entry));
break;
}
@@ -2413,6 +2461,38 @@ bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
}
//----------------------------------------------------------------------------
+bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath,
+ std::string& soname)
+{
+ std::vector<cmStdString> cmds;
+ cmds.push_back("otool");
+ cmds.push_back("-D");
+ cmds.push_back(fullPath.c_str());
+
+ std::string output;
+ if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE))
+ {
+ cmds.insert(cmds.begin(), "-r");
+ cmds.insert(cmds.begin(), "xcrun");
+ if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE))
+ {
+ return false;
+ }
+ }
+
+ std::vector<std::string> strs = cmSystemTools::tokenize(output, "\n");
+ // otool returns extra lines reporting multiple install names
+ // in case the binary is multi-arch and none of the architectures
+ // is native (e.g. i386;ppc on x86_64)
+ if(strs.size() >= 2)
+ {
+ soname = strs[1];
+ return true;
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------------
#if defined(CMAKE_USE_ELF_PARSER)
std::string::size_type cmSystemToolsFindRPath(std::string const& have,
std::string const& want)
@@ -2659,13 +2739,18 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
const char* lhss, const char* rhss)
{
- unsigned int lhs[4] = {0,0,0,0};
- unsigned int rhs[4] = {0,0,0,0};
- sscanf(lhss, "%u.%u.%u.%u", &lhs[0], &lhs[1], &lhs[2], &lhs[3]);
- sscanf(rhss, "%u.%u.%u.%u", &rhs[0], &rhs[1], &rhs[2], &rhs[3]);
+ // Parse out up to 8 components.
+ unsigned int lhs[8] = {0,0,0,0,0,0,0,0};
+ unsigned int rhs[8] = {0,0,0,0,0,0,0,0};
+ sscanf(lhss, "%u.%u.%u.%u.%u.%u.%u.%u",
+ &lhs[0], &lhs[1], &lhs[2], &lhs[3],
+ &lhs[4], &lhs[5], &lhs[6], &lhs[7]);
+ sscanf(rhss, "%u.%u.%u.%u.%u.%u.%u.%u",
+ &rhs[0], &rhs[1], &rhs[2], &rhs[3],
+ &rhs[4], &rhs[5], &rhs[6], &rhs[7]);
// Do component-wise comparison.
- for(unsigned int i=0; i < 4; ++i)
+ for(unsigned int i=0; i < 8; ++i)
{
if(lhs[i] < rhs[i])
{
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 0b2def216..9d7dae9ef 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -56,7 +56,7 @@ public:
typedef void (*ErrorCallback)(const char*, const char*, bool&, void*);
/**
- * Set the function used by GUI's to display error messages
+ * Set the function used by GUIs to display error messages
* Function gets passed: message as a const char*,
* title as a const char*, and a reference to bool that when
* set to false, will disable furthur messages (cancel).
@@ -211,7 +211,7 @@ public:
* user-viewable output from the program being run will be generated.
* OUTPUT_MERGE is the legacy behaviour where stdout and stderr are merged
* into stdout. OUTPUT_NORMAL passes through the output to stdout/stderr as
- * it was received.
+ * it was received. OUTPUT_PASSTHROUGH passes through the original handles.
*
* If timeout is specified, the command will be terminated after
* timeout expires. Timeout is specified in seconds.
@@ -230,7 +230,8 @@ public:
{
OUTPUT_NONE = 0,
OUTPUT_MERGE,
- OUTPUT_NORMAL
+ OUTPUT_NORMAL,
+ OUTPUT_PASSTHROUGH
};
static bool RunSingleCommand(const char* command, std::string* output = 0,
int* retVal = 0, const char* dir = 0,
@@ -274,7 +275,7 @@ public:
static bool GetRunCommandOutput() { return s_DisableRunCommandOutput; }
/**
- * Come constants for different file formats.
+ * Some constants for different file formats.
*/
enum FileFormat {
NO_FILE_FORMAT = 0,
@@ -365,6 +366,12 @@ public:
*/
static std::string RelativePath(const char* local, const char* remote);
+ /** Joins two paths while collapsing x/../ parts
+ * For example CollapseCombinedPath("a/b/c", "../../d") results in "a/d"
+ */
+ static std::string CollapseCombinedPath(std::string const& dir,
+ std::string const& file);
+
#ifdef CMAKE_BUILD_WITH_CMAKE
/** Remove an environment variable */
static bool UnsetEnv(const char* value);
@@ -439,6 +446,10 @@ public:
static bool GuessLibrarySOName(std::string const& fullPath,
std::string& soname);
+ /** Try to guess the install name of a shared library. */
+ static bool GuessLibraryInstallName(std::string const& fullPath,
+ std::string& soname);
+
/** Try to set the RPATH in an ELF binary. */
static bool ChangeRPath(std::string const& file,
std::string const& oldRPath,
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index d14bfcaf6..4ba6c1981 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -83,10 +83,12 @@ class cmTargetInternals
public:
cmTargetInternals()
{
+ this->PolicyWarnedCMP0022 = false;
this->SourceFileFlagsConstructed = false;
}
cmTargetInternals(cmTargetInternals const& r)
{
+ this->PolicyWarnedCMP0022 = false;
this->SourceFileFlagsConstructed = false;
// Only some of these entries are part of the object state.
// Others not copied here are result caches.
@@ -109,6 +111,7 @@ public:
typedef std::map<TargetConfigPair, OptionalLinkInterface>
LinkInterfaceMapType;
LinkInterfaceMapType LinkInterfaceMap;
+ bool PolicyWarnedCMP0022;
typedef std::map<cmStdString, cmTarget::OutputInfo> OutputInfoMapType;
OutputInfoMapType OutputInfoMap;
@@ -130,31 +133,37 @@ public:
typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
SourceEntriesType SourceEntries;
- struct IncludeDirectoriesEntry {
- IncludeDirectoriesEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
+ struct TargetPropertyEntry {
+ TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
const std::string &targetName = std::string())
: ge(cge), TargetName(targetName)
{}
const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
- std::vector<std::string> CachedIncludes;
+ std::vector<std::string> CachedEntries;
const std::string TargetName;
};
- std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
- std::vector<cmValueWithOrigin> LinkInterfaceIncludeDirectoriesEntries;
+ std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
+ std::vector<TargetPropertyEntry*> CompileOptionsEntries;
+ std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
+ std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
- std::map<std::string, std::vector<IncludeDirectoriesEntry*> >
+ std::map<std::string, std::vector<TargetPropertyEntry*> >
CachedLinkInterfaceIncludeDirectoriesEntries;
- std::map<std::string, std::string> CachedLinkInterfaceCompileDefinitions;
+ std::map<std::string, std::vector<TargetPropertyEntry*> >
+ CachedLinkInterfaceCompileOptionsEntries;
+ std::map<std::string, std::vector<TargetPropertyEntry*> >
+ CachedLinkInterfaceCompileDefinitionsEntries;
std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
+ std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
};
//----------------------------------------------------------------------------
void deleteAndClear(
- std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries)
+ std::vector<cmTargetInternals::TargetPropertyEntry*> &entries)
{
- for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+ for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
it = entries.begin(),
end = entries.end();
it != end; ++it)
@@ -167,10 +176,10 @@ void deleteAndClear(
//----------------------------------------------------------------------------
void deleteAndClear(
std::map<std::string,
- std::vector<cmTargetInternals::IncludeDirectoriesEntry*> > &entries)
+ std::vector<cmTargetInternals::TargetPropertyEntry*> > &entries)
{
for (std::map<std::string,
- std::vector<cmTargetInternals::IncludeDirectoriesEntry*> >::iterator
+ std::vector<cmTargetInternals::TargetPropertyEntry*> >::iterator
it = entries.begin(), end = entries.end(); it != end; ++it)
{
deleteAndClear(it->second);
@@ -180,17 +189,22 @@ void deleteAndClear(
//----------------------------------------------------------------------------
cmTargetInternals::~cmTargetInternals()
{
- deleteAndClear(CachedLinkInterfaceIncludeDirectoriesEntries);
+ deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
+ deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
+ deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
}
//----------------------------------------------------------------------------
cmTarget::cmTarget()
{
+#define INITIALIZE_TARGET_POLICY_MEMBER(POLICY) \
+ this->PolicyStatus ## POLICY = cmPolicies::WARN;
+
+ CM_FOR_EACH_TARGET_POLICY(INITIALIZE_TARGET_POLICY_MEMBER)
+
+#undef INITIALIZE_TARGET_POLICY_MEMBER
+
this->Makefile = 0;
- this->PolicyStatusCMP0003 = cmPolicies::WARN;
- this->PolicyStatusCMP0004 = cmPolicies::WARN;
- this->PolicyStatusCMP0008 = cmPolicies::WARN;
- this->PolicyStatusCMP0020 = cmPolicies::WARN;
this->LinkLibrariesAnalyzed = false;
this->HaveInstallRule = false;
this->DLLPlatform = false;
@@ -198,6 +212,8 @@ cmTarget::cmTarget()
this->IsImportedTarget = false;
this->BuildInterfaceIncludesAppended = false;
this->DebugIncludesDone = false;
+ this->DebugCompileOptionsDone = false;
+ this->DebugCompileDefinitionsDone = false;
}
//----------------------------------------------------------------------------
@@ -229,7 +245,9 @@ void cmTarget::DefineProperties(cmake *cm)
"AUTOMOC_MOC_OPTIONS property.\n"
"By setting the CMAKE_AUTOMOC_RELAXED_MODE variable to TRUE the rules "
"for searching the files which will be processed by moc can be relaxed. "
- "See the documentation for this variable for more details.");
+ "See the documentation for this variable for more details.\n"
+ "The global property AUTOMOC_TARGETS_FOLDER can be used to group the "
+ "automoc targets together in an IDE, e.g. in MSVS.");
cm->DefineProperty
("AUTOMOC_MOC_OPTIONS", cmProperty::TARGET,
@@ -285,6 +303,30 @@ void cmTarget::DefineProperties(cmake *cm)
"This is the configuration-specific version of COMPILE_DEFINITIONS.");
cm->DefineProperty
+ ("COMPILE_OPTIONS", cmProperty::TARGET,
+ "List of options to pass to the compiler.",
+ "This property specifies the list of options specified "
+ "so far for this property. "
+ "This property exists on directories and targets."
+ "\n"
+ "The target property values are used by the generators to set "
+ "the options for the compiler.\n"
+ "Contents of COMPILE_OPTIONS may use \"generator expressions\" with "
+ "the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+
+ cm->DefineProperty
+ ("INTERFACE_COMPILE_OPTIONS", cmProperty::TARGET,
+ "List of interface options to pass to the compiler.",
+ "Targets may populate this property to publish the compile options "
+ "required to compile against the headers for the target. Consuming "
+ "targets can add entries to their own COMPILE_OPTIONS property such "
+ "as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_OPTIONS> to use the "
+ "compile options specified in the interface of 'foo'."
+ "\n"
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+
+ cm->DefineProperty
("DEFINE_SYMBOL", cmProperty::TARGET,
"Define a symbol when compiling this target's sources.",
"DEFINE_SYMBOL sets the name of the preprocessor symbol defined when "
@@ -292,7 +334,7 @@ void cmTarget::DefineProperties(cmake *cm)
"If not set here then it is set to target_EXPORTS by default "
"(with some substitutions if the target is not a valid C "
"identifier). This is useful for headers to know whether they are "
- "being included from inside their library our outside to properly "
+ "being included from inside their library or outside to properly "
"setup dllexport/dllimport decorations. ");
cm->DefineProperty
@@ -438,7 +480,7 @@ void cmTarget::DefineProperties(cmake *cm)
"imported library. "
"The list "
"should be disjoint from the list of interface libraries in the "
- "IMPORTED_LINK_INTERFACE_LIBRARIES property. On platforms requiring "
+ "INTERFACE_LINK_LIBRARIES property. On platforms requiring "
"dependent shared libraries to be found at link time CMake uses this "
"list to add appropriate files or paths to the link command line. "
"Ignored for non-imported targets.");
@@ -459,7 +501,10 @@ void cmTarget::DefineProperties(cmake *cm)
"The libraries will be included on the link line for the target. "
"Unlike the LINK_INTERFACE_LIBRARIES property, this property applies "
"to all imported target types, including STATIC libraries. "
- "This property is ignored for non-imported targets.");
+ "This property is ignored for non-imported targets.\n"
+ "This property is ignored if the target also has a non-empty "
+ "INTERFACE_LINK_LIBRARIES property.\n"
+ "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
cm->DefineProperty
("IMPORTED_LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET,
@@ -467,7 +512,10 @@ void cmTarget::DefineProperties(cmake *cm)
"Configuration names correspond to those provided by the project "
"from which the target is imported. "
"If set, this property completely overrides the generic property "
- "for the named configuration.");
+ "for the named configuration.\n"
+ "This property is ignored if the target also has a non-empty "
+ "INTERFACE_LINK_LIBRARIES property.\n"
+ "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
cm->DefineProperty
("IMPORTED_LINK_INTERFACE_LANGUAGES", cmProperty::TARGET,
@@ -700,7 +748,11 @@ void cmTarget::DefineProperties(cmake *cm)
"file providing the program entry point (main). "
"If not set, the language with the highest linker preference "
"value is the default. "
- "See documentation of CMAKE_<LANG>_LINKER_PREFERENCE variables.");
+ "See documentation of CMAKE_<LANG>_LINKER_PREFERENCE variables."
+ "\n"
+ "If this property is not set by the user, it will be calculated at "
+ "generate-time by CMake."
+ );
cm->DefineProperty
("LOCATION", cmProperty::TARGET,
@@ -783,7 +835,10 @@ void cmTarget::DefineProperties(cmake *cm)
"This property is initialized by the value of the variable "
"CMAKE_LINK_INTERFACE_LIBRARIES if it is set when a target is "
"created. "
- "This property is ignored for STATIC libraries.");
+ "This property is ignored for STATIC libraries.\n"
+ "This property is overridden by the INTERFACE_LINK_LIBRARIES property if "
+ "policy CMP0022 is NEW.\n"
+ "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
cm->DefineProperty
("LINK_INTERFACE_LIBRARIES_<CONFIG>", cmProperty::TARGET,
@@ -791,7 +846,23 @@ void cmTarget::DefineProperties(cmake *cm)
"This is the configuration-specific version of "
"LINK_INTERFACE_LIBRARIES. "
"If set, this property completely overrides the generic property "
- "for the named configuration.");
+ "for the named configuration.\n"
+ "This property is overridden by the INTERFACE_LINK_LIBRARIES property if "
+ "policy CMP0022 is NEW.\n"
+ "This property is deprecated. Use INTERFACE_LINK_LIBRARIES instead.");
+
+ cm->DefineProperty
+ ("INTERFACE_LINK_LIBRARIES", cmProperty::TARGET,
+ "List public interface libraries for a library.",
+ "This property contains the list of transitive link dependencies. "
+ "When the target is linked into another target the libraries "
+ "listed (and recursively their link interface libraries) will be "
+ "provided to the other target also. "
+ "This property is overridden by the LINK_INTERFACE_LIBRARIES or "
+ "LINK_INTERFACE_LIBRARIES_<CONFIG> property if "
+ "policy CMP0022 is OLD or unset.\n"
+ "\n"
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
cm->DefineProperty
("INTERFACE_INCLUDE_DIRECTORIES", cmProperty::TARGET,
@@ -805,6 +876,16 @@ void cmTarget::DefineProperties(cmake *cm)
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
cm->DefineProperty
+ ("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", cmProperty::TARGET,
+ "List of public system include directories for a library.",
+ "Targets may populate this property to publish the include directories "
+ "which contain system headers, and therefore should not result in "
+ "compiler warnings. Consuming targets will then mark the same include "
+ "directories as system headers."
+ "\n"
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+
+ cm->DefineProperty
("INTERFACE_COMPILE_DEFINITIONS", cmProperty::TARGET,
"List of public compile definitions for a library.",
"Targets may populate this property to publish the compile definitions "
@@ -867,6 +948,18 @@ void cmTarget::DefineProperties(cmake *cm)
"OSX_ARCHITECTURES.");
cm->DefineProperty
+ ("NAME", cmProperty::TARGET,
+ "Logical name for the target.",
+ "Read-only logical name for the target as used by CMake.");
+
+ cm->DefineProperty
+ ("EXPORT_NAME", cmProperty::TARGET,
+ "Exported name for target files.",
+ "This sets the name for the IMPORTED target generated when it this "
+ "target is is exported. "
+ "If not set, the logical target name is used by default.");
+
+ cm->DefineProperty
("OUTPUT_NAME", cmProperty::TARGET,
"Output name for target files.",
"This sets the base name for output files created for an executable or "
@@ -879,6 +972,12 @@ void cmTarget::DefineProperties(cmake *cm)
"This is the configuration-specific version of OUTPUT_NAME.");
cm->DefineProperty
+ ("ALIASED_TARGET", cmProperty::TARGET,
+ "Name of target aliased by this target.",
+ "If this is an ALIAS target, this property contains the name of the "
+ "target aliased.");
+
+ cm->DefineProperty
("<CONFIG>_OUTPUT_NAME", cmProperty::TARGET,
"Old per-configuration target file base name.",
"This is a configuration-specific version of OUTPUT_NAME. "
@@ -886,9 +985,9 @@ void cmTarget::DefineProperties(cmake *cm)
cm->DefineProperty
("PDB_NAME", cmProperty::TARGET,
- "Output name for MS debug symbols .pdb file.",
+ "Output name for MS debug symbols .pdb file from linker.",
"Set the base name for debug symbols file created for an "
- "executable or library target. "
+ "executable or shared library target. "
"If not set, the logical target name is used by default. "
"\n"
"This property is not implemented by the Visual Studio 6 generator.");
@@ -916,6 +1015,26 @@ void cmTarget::DefineProperties(cmake *cm)
"(such as \"lib\") on a library name.");
cm->DefineProperty
+ ("<LANG>_VISIBILITY_PRESET", cmProperty::TARGET,
+ "Value for symbol visibility compile flags",
+ "The <LANG>_VISIBILITY_PRESET property determines the value passed in "
+ "a visibility related compile option, such as -fvisibility= for <LANG>. "
+ "This property only has an affect for libraries and executables with "
+ "exports. This property is initialized by the value of the variable "
+ "CMAKE_<LANG>_VISIBILITY_PRESET if it is set when a target is created.");
+
+ cm->DefineProperty
+ ("VISIBILITY_INLINES_HIDDEN", cmProperty::TARGET,
+ "Whether to add a compile flag to hide symbols of inline functions",
+ "The VISIBILITY_INLINES_HIDDEN property determines whether a flag for "
+ "hiding symbols for inline functions. the value passed used in "
+ "a visibility related compile option, such as -fvisibility=. This "
+ "property only has an affect for libraries and executables with "
+ "exports. This property is initialized by the value of the variable "
+ "CMAKE_VISIBILITY_INLINES_HIDDEN if it is set when a target is "
+ "created.");
+
+ cm->DefineProperty
("POSITION_INDEPENDENT_CODE", cmProperty::TARGET,
"Whether to create a position-independent target",
"The POSITION_INDEPENDENT_CODE property determines whether position "
@@ -1054,7 +1173,7 @@ void cmTarget::DefineProperties(cmake *cm)
("SOVERSION", cmProperty::TARGET,
"What version number is this target.",
"For shared libraries VERSION and SOVERSION can be used to specify "
- "the build version and api version respectively. When building or "
+ "the build version and API version respectively. When building or "
"installing appropriate symlinks are created if the platform "
"supports symlinks and the linker supports so-names. "
"If only one of both is specified the missing is assumed to have "
@@ -1092,7 +1211,7 @@ void cmTarget::DefineProperties(cmake *cm)
("VERSION", cmProperty::TARGET,
"What version number is this target.",
"For shared libraries VERSION and SOVERSION can be used to specify "
- "the build version and api version respectively. When building or "
+ "the build version and API version respectively. When building or "
"installing appropriate symlinks are created if the platform "
"supports symlinks and the linker supports so-names. "
"If only one of both is specified the missing is assumed to have "
@@ -1156,7 +1275,7 @@ void cmTarget::DefineProperties(cmake *cm)
cm->DefineProperty
("MACOSX_FRAMEWORK_INFO_PLIST", cmProperty::TARGET,
"Specify a custom Info.plist template for a Mac OS X Framework.",
- "An library target with FRAMEWORK enabled will be built as a "
+ "A library target with FRAMEWORK enabled will be built as a "
"framework on Mac OS X. "
"By default its Info.plist file is created by configuring a template "
"called MacOSXFrameworkInfo.plist.in located in the CMAKE_MODULE_PATH. "
@@ -1174,6 +1293,15 @@ void cmTarget::DefineProperties(cmake *cm)
"hard-code all the settings instead of using the target properties.");
cm->DefineProperty
+ ("MACOSX_RPATH", cmProperty::TARGET,
+ "Whether to use rpaths on Mac OS X.",
+ "When this property is set to true, the directory portion of the"
+ "\"install_name\" field of shared libraries will default to \"@rpath\"."
+ "Runtime paths will also be embedded in binaries using this target."
+ "This property is initialized by the value of the variable "
+ "CMAKE_MACOSX_RPATH if it is set when a target is created.");
+
+ cm->DefineProperty
("ENABLE_EXPORTS", cmProperty::TARGET,
"Specify whether an executable exports symbols for loadable modules.",
"Normally an executable does not export any symbols because it is "
@@ -1247,7 +1375,7 @@ void cmTarget::DefineProperties(cmake *cm)
cm->DefineProperty
("GENERATOR_FILE_NAME", cmProperty::TARGET,
"Generator's file for this target.",
- "An internal property used by some generators to record the name of "
+ "An internal property used by some generators to record the name of the "
"project or dsp file associated with this target. Note that at configure "
"time, this property is only set for targets created by "
"include_external_msproject().");
@@ -1316,6 +1444,16 @@ void cmTarget::DefineProperties(cmake *cm)
"this value with \"ManagedCProj\", for example, in a Visual "
"Studio managed C++ unit test project.");
cm->DefineProperty
+ ("VS_GLOBAL_ROOTNAMESPACE", cmProperty::TARGET,
+ "Visual Studio project root namespace.",
+ "Sets the \"RootNamespace\" attribute for a generated Visual Studio "
+ "project. The attribute will be generated only if this is set.");
+ cm->DefineProperty
+ ("VS_DOTNET_TARGET_FRAMEWORK_VERSION", cmProperty::TARGET,
+ "Specify the .NET target framework version.",
+ "Used to specify the .NET target framework version for C++/CLI. "
+ "For example, \"v4.5\".");
+ cm->DefineProperty
("VS_DOTNET_REFERENCES", cmProperty::TARGET,
"Visual Studio managed project .NET references",
"Adds one or more semicolon-delimited .NET references to a "
@@ -1397,9 +1535,9 @@ void cmTarget::DefineProperties(cmake *cm)
cm->DefineProperty
("PDB_OUTPUT_DIRECTORY", cmProperty::TARGET,
- "Output directory for MS debug symbols .pdb files.",
+ "Output directory for MS debug symbols .pdb file from linker.",
"This property specifies the directory into which the MS debug symbols "
- "will be placed. "
+ "will be placed by the linker. "
"This property is initialized by the value of the variable "
"CMAKE_PDB_OUTPUT_DIRECTORY if it is set when a target is created."
"\n"
@@ -1482,7 +1620,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->IsApple = this->Makefile->IsOn("APPLE");
// Setup default property values.
- this->SetPropertyDefault("INSTALL_NAME_DIR", "");
+ this->SetPropertyDefault("INSTALL_NAME_DIR", 0);
this->SetPropertyDefault("INSTALL_RPATH", "");
this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF");
this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF");
@@ -1501,6 +1639,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0);
this->SetPropertyDefault("WIN32_EXECUTABLE", 0);
this->SetPropertyDefault("MACOSX_BUNDLE", 0);
+ this->SetPropertyDefault("MACOSX_RPATH", 0);
+
// Collect the set of configuration types.
std::vector<std::string> configNames;
@@ -1552,6 +1692,29 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->InsertInclude(*it);
}
+ const std::set<cmStdString> parentSystemIncludes =
+ this->Makefile->GetSystemIncludeDirectories();
+
+ for (std::set<cmStdString>::const_iterator it
+ = parentSystemIncludes.begin();
+ it != parentSystemIncludes.end(); ++it)
+ {
+ this->SystemIncludeDirectories.insert(*it);
+ }
+
+ const std::vector<cmValueWithOrigin> parentOptions =
+ this->Makefile->GetCompileOptionsEntries();
+
+ for (std::vector<cmValueWithOrigin>::const_iterator it
+ = parentOptions.begin(); it != parentOptions.end(); ++it)
+ {
+ this->InsertCompileOption(*it);
+ }
+
+ this->SetPropertyDefault("C_VISIBILITY_PRESET", 0);
+ this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0);
+ this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", 0);
+
if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY
|| this->TargetTypeValue == cmTarget::MODULE_LIBRARY)
{
@@ -1560,14 +1723,13 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0);
// Record current policies for later use.
- this->PolicyStatusCMP0003 =
- this->Makefile->GetPolicyStatus(cmPolicies::CMP0003);
- this->PolicyStatusCMP0004 =
- this->Makefile->GetPolicyStatus(cmPolicies::CMP0004);
- this->PolicyStatusCMP0008 =
- this->Makefile->GetPolicyStatus(cmPolicies::CMP0008);
- this->PolicyStatusCMP0020 =
- this->Makefile->GetPolicyStatus(cmPolicies::CMP0020);
+#define CAPTURE_TARGET_POLICY(POLICY) \
+ this->PolicyStatus ## POLICY = \
+ this->Makefile->GetPolicyStatus(cmPolicies::POLICY);
+
+ CM_FOR_EACH_TARGET_POLICY(CAPTURE_TARGET_POLICY)
+
+#undef CAPTURE_TARGET_POLICY
}
//----------------------------------------------------------------------------
@@ -1669,11 +1831,17 @@ bool cmTarget::IsCFBundleOnApple()
}
//----------------------------------------------------------------------------
+bool cmTarget::IsBundleOnApple()
+{
+ return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() ||
+ this->IsCFBundleOnApple();
+}
+
+//----------------------------------------------------------------------------
class cmTargetTraceDependencies
{
public:
- cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal,
- const char* vsProjectFile);
+ cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal);
void Trace();
private:
cmTarget* Target;
@@ -1697,8 +1865,7 @@ private:
//----------------------------------------------------------------------------
cmTargetTraceDependencies
-::cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal,
- const char* vsProjectFile):
+::cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal):
Target(target), Internal(internal)
{
// Convenience.
@@ -1715,13 +1882,6 @@ cmTargetTraceDependencies
this->QueueSource(*si);
}
- // Queue the VS project file to check dependencies on the rule to
- // generate it.
- if(vsProjectFile)
- {
- this->FollowName(vsProjectFile);
- }
-
// Queue pre-build, pre-link, and post-build rule dependencies.
this->CheckCustomCommands(this->Target->GetPreBuildCommands());
this->CheckCustomCommands(this->Target->GetPreLinkCommands());
@@ -1940,7 +2100,7 @@ cmTargetTraceDependencies
}
//----------------------------------------------------------------------------
-void cmTarget::TraceDependencies(const char* vsProjectFile)
+void cmTarget::TraceDependencies()
{
// CMake-generated targets have no dependencies to trace. Normally tracing
// would find nothing anyway, but when building CMake itself the "install"
@@ -1952,7 +2112,7 @@ void cmTarget::TraceDependencies(const char* vsProjectFile)
}
// Use a helper object to trace the dependencies.
- cmTargetTraceDependencies tracer(this, this->Internal.Get(), vsProjectFile);
+ cmTargetTraceDependencies tracer(this, this->Internal.Get());
tracer.Trace();
}
@@ -2174,8 +2334,10 @@ void cmTarget::MergeLinkLibraries( cmMakefile& mf,
i += this->PrevLinkedLibraries.size();
for( ; i != libs.end(); ++i )
{
- // We call this so that the dependencies get written to the cache
+ // This is equivalent to the target_link_libraries plain signature.
this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second );
+ this->AppendProperty("INTERFACE_LINK_LIBRARIES",
+ this->GetDebugGeneratorExpressions(i->first.c_str(), i->second).c_str());
}
this->PrevLinkedLibraries = libs;
}
@@ -2331,6 +2493,63 @@ static std::string targetNameGenex(const char *lib)
}
//----------------------------------------------------------------------------
+bool cmTarget::PushTLLCommandTrace(TLLSignature signature)
+{
+ bool ret = true;
+ if (!this->TLLCommands.empty())
+ {
+ if (this->TLLCommands.back().first != signature)
+ {
+ ret = false;
+ }
+ }
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ this->TLLCommands.push_back(std::make_pair(signature, lfbt));
+ return ret;
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::GetTllSignatureTraces(cmOStringStream &s,
+ TLLSignature sig) const
+{
+ std::vector<cmListFileBacktrace> sigs;
+ typedef std::vector<std::pair<TLLSignature, cmListFileBacktrace> > Container;
+ for(Container::const_iterator it = this->TLLCommands.begin();
+ it != this->TLLCommands.end(); ++it)
+ {
+ if (it->first == sig)
+ {
+ sigs.push_back(it->second);
+ }
+ }
+ if (!sigs.empty())
+ {
+ const char *sigString
+ = (sig == cmTarget::KeywordTLLSignature ? "keyword"
+ : "plain");
+ s << "The uses of the " << sigString << " signature are here:\n";
+ std::set<cmStdString> emitted;
+ for(std::vector<cmListFileBacktrace>::const_iterator it = sigs.begin();
+ it != sigs.end(); ++it)
+ {
+ cmListFileBacktrace::const_iterator i = it->begin();
+ if(i != it->end())
+ {
+ cmListFileContext const& lfc = *i;
+ cmOStringStream line;
+ line << " * " << (lfc.Line? "": " in ") << lfc << std::endl;
+ if (emitted.insert(line.str()).second)
+ {
+ s << line.str();
+ }
+ ++i;
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
void cmTarget::AddLinkLibrary(cmMakefile& mf,
const char *target, const char* lib,
LinkLibraryType llt)
@@ -2407,6 +2626,61 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
//----------------------------------------------------------------------------
void
+cmTarget::AddSystemIncludeDirectories(const std::set<cmStdString> &incs)
+{
+ for(std::set<cmStdString>::const_iterator li = incs.begin();
+ li != incs.end(); ++li)
+ {
+ this->SystemIncludeDirectories.insert(*li);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmTarget::AddSystemIncludeDirectories(const std::vector<std::string> &incs)
+{
+ for(std::vector<std::string>::const_iterator li = incs.begin();
+ li != incs.end(); ++li)
+ {
+ this->SystemIncludeDirectories.insert(*li);
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::FinalizeSystemIncludeDirectories()
+{
+ for (std::vector<cmValueWithOrigin>::const_iterator
+ it = this->Internal->LinkInterfacePropertyEntries.begin(),
+ end = this->Internal->LinkInterfacePropertyEntries.end();
+ it != end; ++it)
+ {
+ {
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(it->Value);
+ std::string targetName = cge->Evaluate(this->Makefile, 0,
+ false, this, 0, 0);
+ if (!this->Makefile->FindTargetToUse(targetName.c_str()))
+ {
+ continue;
+ }
+ }
+ std::string includeGenex = "$<TARGET_PROPERTY:" +
+ it->Value + ",INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>";
+ if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
+ {
+ // Because it->Value is a generator expression, ensure that it
+ // evaluates to the non-empty string before being used in the
+ // TARGET_PROPERTY expression.
+ includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
+ }
+ this->SystemIncludeDirectories.insert(includeGenex);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
{
// There are two key parts of the dependency analysis: (1)
@@ -2491,8 +2765,6 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
}
}
- typedef std::vector< std::string > LinkLine;
-
// The dependency map.
DependencyMap dep_map;
@@ -2707,7 +2979,13 @@ void cmTarget::SetProperty(const char* prop, const char* value)
{
return;
}
-
+ if (strcmp(prop, "NAME") == 0)
+ {
+ cmOStringStream e;
+ e << "NAME property is read-only\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
{
cmListFileBacktrace lfbt;
@@ -2716,19 +2994,49 @@ void cmTarget::SetProperty(const char* prop, const char* value)
deleteAndClear(this->Internal->IncludeDirectoriesEntries);
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
this->Internal->IncludeDirectoriesEntries.push_back(
- new cmTargetInternals::IncludeDirectoriesEntry(cge));
+ new cmTargetInternals::TargetPropertyEntry(cge));
+ return;
+ }
+ if(strcmp(prop,"COMPILE_OPTIONS") == 0)
+ {
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmGeneratorExpression ge(lfbt);
+ deleteAndClear(this->Internal->CompileOptionsEntries);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+ this->Internal->CompileOptionsEntries.push_back(
+ new cmTargetInternals::TargetPropertyEntry(cge));
+ return;
+ }
+ if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
+ {
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmGeneratorExpression ge(lfbt);
+ deleteAndClear(this->Internal->CompileDefinitionsEntries);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+ this->Internal->CompileDefinitionsEntries.push_back(
+ new cmTargetInternals::TargetPropertyEntry(cge));
+ return;
+ }
+ if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
+ {
+ cmOStringStream e;
+ e << "EXPORT_NAME property can't be set on imported targets (\""
+ << this->Name << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
return;
}
if (strcmp(prop, "LINK_LIBRARIES") == 0)
{
- this->Internal->LinkInterfaceIncludeDirectoriesEntries.clear();
+ this->Internal->LinkInterfacePropertyEntries.clear();
if (cmGeneratorExpression::IsValidTargetName(value)
|| cmGeneratorExpression::Find(value) != std::string::npos)
{
cmListFileBacktrace lfbt;
this->Makefile->GetBacktrace(lfbt);
cmValueWithOrigin entry(value, lfbt);
- this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry);
+ this->Internal->LinkInterfacePropertyEntries.push_back(entry);
}
// Fall through
}
@@ -2744,13 +3052,46 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
{
return;
}
+ if (strcmp(prop, "NAME") == 0)
+ {
+ cmOStringStream e;
+ e << "NAME property is read-only\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
{
cmListFileBacktrace lfbt;
this->Makefile->GetBacktrace(lfbt);
cmGeneratorExpression ge(lfbt);
this->Internal->IncludeDirectoriesEntries.push_back(
- new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value)));
+ new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
+ return;
+ }
+ if(strcmp(prop,"COMPILE_OPTIONS") == 0)
+ {
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmGeneratorExpression ge(lfbt);
+ this->Internal->CompileOptionsEntries.push_back(
+ new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
+ return;
+ }
+ if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
+ {
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmGeneratorExpression ge(lfbt);
+ this->Internal->CompileDefinitionsEntries.push_back(
+ new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
+ return;
+ }
+ if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
+ {
+ cmOStringStream e;
+ e << "EXPORT_NAME property can't be set on imported targets (\""
+ << this->Name << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
return;
}
if (strcmp(prop, "LINK_LIBRARIES") == 0)
@@ -2761,7 +3102,7 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
cmListFileBacktrace lfbt;
this->Makefile->GetBacktrace(lfbt);
cmValueWithOrigin entry(value, lfbt);
- this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry);
+ this->Internal->LinkInterfacePropertyEntries.push_back(entry);
}
// Fall through
}
@@ -2770,6 +3111,26 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
}
//----------------------------------------------------------------------------
+const char* cmTarget::GetExportName()
+{
+ const char *exportName = this->GetProperty("EXPORT_NAME");
+
+ if (exportName && *exportName)
+ {
+ if (!cmGeneratorExpression::IsValidTargetName(exportName))
+ {
+ cmOStringStream e;
+ e << "EXPORT_NAME property \"" << exportName << "\" for \""
+ << this->GetName() << "\": is not valid.";
+ cmSystemTools::Error(e.str().c_str());
+ return "";
+ }
+ return exportName;
+ }
+ return this->GetName();
+}
+
+//----------------------------------------------------------------------------
void cmTarget::AppendBuildInterfaceIncludes()
{
if(this->GetType() != cmTarget::SHARED_LIBRARY &&
@@ -2806,17 +3167,45 @@ void cmTarget::InsertInclude(const cmValueWithOrigin &entry,
{
cmGeneratorExpression ge(entry.Backtrace);
- std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::iterator position
+ std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
= before ? this->Internal->IncludeDirectoriesEntries.begin()
: this->Internal->IncludeDirectoriesEntries.end();
this->Internal->IncludeDirectoriesEntries.insert(position,
- new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value)));
+ new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::InsertCompileOption(const cmValueWithOrigin &entry,
+ bool before)
+{
+ cmGeneratorExpression ge(entry.Backtrace);
+
+ std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
+ = before ? this->Internal->CompileOptionsEntries.begin()
+ : this->Internal->CompileOptionsEntries.end();
+
+ this->Internal->CompileOptionsEntries.insert(position,
+ new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::InsertCompileDefinition(const cmValueWithOrigin &entry,
+ bool before)
+{
+ cmGeneratorExpression ge(entry.Backtrace);
+
+ std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
+ = before ? this->Internal->CompileDefinitionsEntries.begin()
+ : this->Internal->CompileDefinitionsEntries.end();
+
+ this->Internal->CompileDefinitionsEntries.insert(position,
+ new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
}
//----------------------------------------------------------------------------
static void processIncludeDirectories(cmTarget *tgt,
- const std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries,
+ const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
std::vector<std::string> &includes,
std::set<std::string> &uniqueIncludes,
cmGeneratorExpressionDAGChecker *dagChecker,
@@ -2824,12 +3213,12 @@ static void processIncludeDirectories(cmTarget *tgt,
{
cmMakefile *mf = tgt->GetMakefile();
- for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+ for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
it = entries.begin(), end = entries.end(); it != end; ++it)
{
bool testIsOff = true;
bool cacheIncludes = false;
- std::vector<std::string> entryIncludes = (*it)->CachedIncludes;
+ std::vector<std::string> entryIncludes = (*it)->CachedEntries;
if(!entryIncludes.empty())
{
testIsOff = false;
@@ -2876,15 +3265,45 @@ static void processIncludeDirectories(cmTarget *tgt,
if (!cmSystemTools::FileIsFullPath(li->c_str()))
{
+ cmOStringStream e;
+ bool noMessage = false;
+ cmake::MessageType messageType = cmake::FATAL_ERROR;
if (!(*it)->TargetName.empty())
{
- cmOStringStream e;
e << "Target \"" << (*it)->TargetName << "\" contains relative "
"path in its INTERFACE_INCLUDE_DIRECTORIES:\n"
- " \"" << *li << "\" ";
- tgt->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
- e.str().c_str());
- return;
+ " \"" << *li << "\"";
+ }
+ else
+ {
+ switch(tgt->GetPolicyStatusCMP0021())
+ {
+ case cmPolicies::WARN:
+ {
+ cmOStringStream w;
+ e << (mf->GetPolicies()
+ ->GetPolicyWarning(cmPolicies::CMP0021)) << "\n";
+ messageType = cmake::AUTHOR_WARNING;
+ }
+ break;
+ case cmPolicies::OLD:
+ noMessage = true;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Issue the fatal message.
+ break;
+ }
+ e << "Found relative path while evaluating include directories of "
+ "\"" << tgt->GetName() << "\":\n \"" << *li << "\"\n";
+ }
+ if (!noMessage)
+ {
+ tgt->GetMakefile()->IssueMessage(messageType, e.str().c_str());
+ if (messageType == cmake::FATAL_ERROR)
+ {
+ return;
+ }
}
}
@@ -2905,7 +3324,7 @@ static void processIncludeDirectories(cmTarget *tgt,
}
if (cacheIncludes)
{
- (*it)->CachedIncludes = entryIncludes;
+ (*it)->CachedEntries = entryIncludes;
}
if (!usedIncludes.empty())
{
@@ -2925,8 +3344,8 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
cmListFileBacktrace lfbt;
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "INCLUDE_DIRECTORIES", 0, 0);
+ this->GetName(),
+ "INCLUDE_DIRECTORIES", 0, 0);
this->AppendBuildInterfaceIncludes();
@@ -2961,8 +3380,8 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
if (!this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString])
{
for (std::vector<cmValueWithOrigin>::const_iterator
- it = this->Internal->LinkInterfaceIncludeDirectoriesEntries.begin(),
- end = this->Internal->LinkInterfaceIncludeDirectoriesEntries.end();
+ it = this->Internal->LinkInterfacePropertyEntries.begin(),
+ end = this->Internal->LinkInterfacePropertyEntries.end();
it != end; ++it)
{
{
@@ -2991,9 +3410,37 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
this->Internal
->CachedLinkInterfaceIncludeDirectoriesEntries[configString].push_back(
- new cmTargetInternals::IncludeDirectoriesEntry(cge,
+ new cmTargetInternals::TargetPropertyEntry(cge,
it->Value));
}
+
+ if(this->Makefile->IsOn("APPLE"))
+ {
+ LinkImplementation const* impl = this->GetLinkImplementation(config,
+ this);
+ for(std::vector<std::string>::const_iterator
+ it = impl->Libraries.begin();
+ it != impl->Libraries.end(); ++it)
+ {
+ std::string libDir = cmSystemTools::CollapseFullPath(it->c_str());
+
+ static cmsys::RegularExpression
+ frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
+ if(!frameworkCheck.find(libDir))
+ {
+ continue;
+ }
+
+ libDir = frameworkCheck.match(1);
+
+ cmGeneratorExpression ge(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(libDir.c_str());
+ this->Internal
+ ->CachedLinkInterfaceIncludeDirectoriesEntries[configString]
+ .push_back(new cmTargetInternals::TargetPropertyEntry(cge));
+ }
+ }
}
processIncludeDirectories(this,
@@ -3019,90 +3466,294 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
}
//----------------------------------------------------------------------------
-std::string cmTarget::GetCompileDefinitions(const char *config)
+static void processCompileOptionsInternal(cmTarget *tgt,
+ const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
+ std::vector<std::string> &options,
+ std::set<std::string> &uniqueOptions,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ const char *config, bool debugOptions, const char *logName)
{
- const char *configProp = 0;
- if (config)
+ cmMakefile *mf = tgt->GetMakefile();
+
+ for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
+ it = entries.begin(), end = entries.end(); it != end; ++it)
{
- std::string configPropName;
- configPropName = "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
- configProp = this->GetProperty(configPropName.c_str());
+ bool cacheOptions = false;
+ std::vector<std::string> entryOptions = (*it)->CachedEntries;
+ if(entryOptions.empty())
+ {
+ cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
+ config,
+ false,
+ tgt,
+ dagChecker),
+ entryOptions);
+ if (mf->IsGeneratingBuildSystem()
+ && !(*it)->ge->GetHadContextSensitiveCondition())
+ {
+ cacheOptions = true;
+ }
+ }
+ std::string usedOptions;
+ for(std::vector<std::string>::iterator
+ li = entryOptions.begin(); li != entryOptions.end(); ++li)
+ {
+ std::string opt = *li;
+
+ if(uniqueOptions.insert(opt).second)
+ {
+ options.push_back(opt);
+ if (debugOptions)
+ {
+ usedOptions += " * " + opt + "\n";
+ }
+ }
+ }
+ if (cacheOptions)
+ {
+ (*it)->CachedEntries = entryOptions;
+ }
+ if (!usedOptions.empty())
+ {
+ mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
+ std::string("Used compile ") + logName
+ + std::string(" for target ")
+ + tgt->GetName() + ":\n"
+ + usedOptions, (*it)->ge->GetBacktrace());
+ }
}
+}
+
+//----------------------------------------------------------------------------
+static void processCompileOptions(cmTarget *tgt,
+ const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
+ std::vector<std::string> &options,
+ std::set<std::string> &uniqueOptions,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ const char *config, bool debugOptions)
+{
+ processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+ dagChecker, config, debugOptions, "options");
+}
- const char *noconfigProp = this->GetProperty("COMPILE_DEFINITIONS");
+//----------------------------------------------------------------------------
+void cmTarget::GetCompileOptions(std::vector<std::string> &result,
+ const char *config)
+{
+ std::set<std::string> uniqueOptions;
cmListFileBacktrace lfbt;
+
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "COMPILE_DEFINITIONS", 0, 0);
+ this->GetName(),
+ "COMPILE_OPTIONS", 0, 0);
- std::string defsString = (noconfigProp ? noconfigProp : "");
- if (configProp && noconfigProp)
+ std::vector<std::string> debugProperties;
+ const char *debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp)
{
- defsString += ";";
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
}
- defsString += (configProp ? configProp : "");
- cmGeneratorExpression ge(lfbt);
- std::string result = ge.Parse(defsString.c_str())->Evaluate(this->Makefile,
- config,
- false,
- this,
- &dagChecker);
-
- std::vector<std::string> libs;
- this->GetDirectLinkLibraries(config, libs, this);
+ bool debugOptions = !this->DebugCompileOptionsDone
+ && std::find(debugProperties.begin(),
+ debugProperties.end(),
+ "COMPILE_OPTIONS")
+ != debugProperties.end();
- if (libs.empty())
+ if (this->Makefile->IsGeneratingBuildSystem())
{
- return result;
+ this->DebugCompileOptionsDone = true;
}
- std::string sep;
- std::string depString;
- for (std::vector<std::string>::const_iterator it = libs.begin();
- it != libs.end(); ++it)
+ processCompileOptions(this,
+ this->Internal->CompileOptionsEntries,
+ result,
+ uniqueOptions,
+ &dagChecker,
+ config,
+ debugOptions);
+
+ std::string configString = config ? config : "";
+ if (!this->Internal->CacheLinkInterfaceCompileOptionsDone[configString])
{
- if ((cmGeneratorExpression::IsValidTargetName(it->c_str())
- || cmGeneratorExpression::Find(it->c_str()) != std::string::npos)
- && this->Makefile->FindTargetToUse(it->c_str()))
+ for (std::vector<cmValueWithOrigin>::const_iterator
+ it = this->Internal->LinkInterfacePropertyEntries.begin(),
+ end = this->Internal->LinkInterfacePropertyEntries.end();
+ it != end; ++it)
{
- depString += sep + "$<TARGET_PROPERTY:"
- + *it + ",INTERFACE_COMPILE_DEFINITIONS>";
- sep = ";";
+ {
+ cmGeneratorExpression ge(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(it->Value);
+ std::string targetResult = cge->Evaluate(this->Makefile, config,
+ false, this, 0, 0);
+ if (!this->Makefile->FindTargetToUse(targetResult.c_str()))
+ {
+ continue;
+ }
+ }
+ std::string optionGenex = "$<TARGET_PROPERTY:" +
+ it->Value + ",INTERFACE_COMPILE_OPTIONS>";
+ if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
+ {
+ // Because it->Value is a generator expression, ensure that it
+ // evaluates to the non-empty string before being used in the
+ // TARGET_PROPERTY expression.
+ optionGenex = "$<$<BOOL:" + it->Value + ">:" + optionGenex + ">";
+ }
+ cmGeneratorExpression ge(it->Backtrace);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
+ optionGenex);
+
+ this->Internal
+ ->CachedLinkInterfaceCompileOptionsEntries[configString].push_back(
+ new cmTargetInternals::TargetPropertyEntry(cge,
+ it->Value));
}
}
- std::string configString = config ? config : "";
- if (!this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString])
+ processCompileOptions(this,
+ this->Internal->CachedLinkInterfaceCompileOptionsEntries[configString],
+ result,
+ uniqueOptions,
+ &dagChecker,
+ config,
+ debugOptions);
+
+ if (!this->Makefile->IsGeneratingBuildSystem())
+ {
+ deleteAndClear(this->Internal->CachedLinkInterfaceCompileOptionsEntries);
+ }
+ else
+ {
+ this->Internal->CacheLinkInterfaceCompileOptionsDone[configString] = true;
+ }
+}
+
+//----------------------------------------------------------------------------
+static void processCompileDefinitions(cmTarget *tgt,
+ const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
+ std::vector<std::string> &options,
+ std::set<std::string> &uniqueOptions,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ const char *config, bool debugOptions)
+{
+ processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+ dagChecker, config, debugOptions,
+ "definitions");
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
+ const char *config)
+{
+ std::set<std::string> uniqueOptions;
+ cmListFileBacktrace lfbt;
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "COMPILE_DEFINITIONS", 0, 0);
+
+ std::vector<std::string> debugProperties;
+ const char *debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp)
{
- cmGeneratorExpression ge2(lfbt);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge2 =
- ge2.Parse(depString);
- this->Internal->CachedLinkInterfaceCompileDefinitions[configString] =
- cge2->Evaluate(this->Makefile,
- config,
- false,
- this,
- &dagChecker);
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
}
- if (!this->Internal->CachedLinkInterfaceCompileDefinitions[configString]
- .empty())
+
+ bool debugDefines = !this->DebugCompileDefinitionsDone
+ && std::find(debugProperties.begin(),
+ debugProperties.end(),
+ "COMPILE_DEFINITIONS")
+ != debugProperties.end();
+
+ if (this->Makefile->IsGeneratingBuildSystem())
+ {
+ this->DebugCompileDefinitionsDone = true;
+ }
+
+ processCompileDefinitions(this,
+ this->Internal->CompileDefinitionsEntries,
+ list,
+ uniqueOptions,
+ &dagChecker,
+ config,
+ debugDefines);
+
+ std::string configString = config ? config : "";
+ if (!this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString])
{
- result += (result.empty() ? "" : ";")
- + this->Internal->CachedLinkInterfaceCompileDefinitions[configString];
+ for (std::vector<cmValueWithOrigin>::const_iterator
+ it = this->Internal->LinkInterfacePropertyEntries.begin(),
+ end = this->Internal->LinkInterfacePropertyEntries.end();
+ it != end; ++it)
+ {
+ {
+ cmGeneratorExpression ge(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(it->Value);
+ std::string targetResult = cge->Evaluate(this->Makefile, config,
+ false, this, 0, 0);
+ if (!this->Makefile->FindTargetToUse(targetResult.c_str()))
+ {
+ continue;
+ }
+ }
+ std::string defsGenex = "$<TARGET_PROPERTY:" +
+ it->Value + ",INTERFACE_COMPILE_DEFINITIONS>";
+ if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
+ {
+ // Because it->Value is a generator expression, ensure that it
+ // evaluates to the non-empty string before being used in the
+ // TARGET_PROPERTY expression.
+ defsGenex = "$<$<BOOL:" + it->Value + ">:" + defsGenex + ">";
+ }
+ cmGeneratorExpression ge(it->Backtrace);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
+ defsGenex);
+
+ this->Internal
+ ->CachedLinkInterfaceCompileDefinitionsEntries[configString].push_back(
+ new cmTargetInternals::TargetPropertyEntry(cge,
+ it->Value));
+ }
+ if (config)
+ {
+ std::string configPropName = "COMPILE_DEFINITIONS_"
+ + cmSystemTools::UpperCase(config);
+ const char *configProp = this->GetProperty(configPropName.c_str());
+ std::string defsString = (configProp ? configProp : "");
+
+ cmGeneratorExpression ge(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(defsString);
+ this->Internal
+ ->CachedLinkInterfaceCompileDefinitionsEntries[configString].push_back(
+ new cmTargetInternals::TargetPropertyEntry(cge));
+ }
+
}
+ processCompileDefinitions(this,
+ this->Internal->CachedLinkInterfaceCompileDefinitionsEntries[configString],
+ list,
+ uniqueOptions,
+ &dagChecker,
+ config,
+ debugDefines);
+
if (!this->Makefile->IsGeneratingBuildSystem())
{
- this->Internal->CachedLinkInterfaceCompileDefinitions[configString] = "";
+ deleteAndClear(this->Internal
+ ->CachedLinkInterfaceCompileDefinitionsEntries);
}
else
{
this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString]
= true;
}
-
- return result;
}
//----------------------------------------------------------------------------
@@ -3163,6 +3814,29 @@ static void cmTargetCheckLINK_INTERFACE_LIBRARIES(
}
//----------------------------------------------------------------------------
+static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value,
+ cmMakefile* context)
+{
+ // Look for link-type keywords in the value.
+ static cmsys::RegularExpression
+ keys("(^|;)(debug|optimized|general)(;|$)");
+ if(!keys.find(value))
+ {
+ return;
+ }
+
+ // Report an error.
+ cmOStringStream e;
+
+ e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type "
+ "keyword \"" << keys.match(2) << "\". The INTERFACE_LINK_LIBRARIES "
+ "property may contain configuration-sensitive generator-expressions "
+ "which may be used to specify per-configuration rules.";
+
+ context->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
void cmTarget::CheckProperty(const char* prop, cmMakefile* context)
{
// Certain properties need checking.
@@ -3180,6 +3854,13 @@ void cmTarget::CheckProperty(const char* prop, cmMakefile* context)
cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true);
}
}
+ if(strncmp(prop, "INTERFACE_LINK_LIBRARIES", 24) == 0)
+ {
+ if(const char* value = this->GetProperty(prop))
+ {
+ cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context);
+ }
+ }
}
//----------------------------------------------------------------------------
@@ -3304,17 +3985,23 @@ const char* cmTarget::NormalGetLocation(const char* config)
// Now handle the deprecated build-time configuration location.
this->Location = this->GetDirectory();
- if(!this->Location.empty())
- {
- this->Location += "/";
- }
const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
if(cfgid && strcmp(cfgid, ".") != 0)
{
- this->Location += cfgid;
this->Location += "/";
+ this->Location += cfgid;
}
- this->Location = this->BuildMacContentDirectory(this->Location, config);
+
+ if(this->IsAppBundleOnApple())
+ {
+ std::string macdir = this->BuildMacContentDirectory("", config, false);
+ if(!macdir.empty())
+ {
+ this->Location += "/";
+ this->Location += macdir;
+ }
+ }
+ this->Location += "/";
this->Location += this->GetFullName(config, false);
return this->Location.c_str();
}
@@ -3390,6 +4077,11 @@ const char *cmTarget::GetProperty(const char* prop,
return 0;
}
+ if (strcmp(prop, "NAME") == 0)
+ {
+ return this->GetName();
+ }
+
// Watch for special "computed" properties that are dependent on
// other properties or variables. Always recompute them.
if(this->GetType() == cmTarget::EXECUTABLE ||
@@ -3437,9 +4129,9 @@ const char *cmTarget::GetProperty(const char* prop,
static std::string output;
output = "";
std::string sep;
- typedef cmTargetInternals::IncludeDirectoriesEntry
- IncludeDirectoriesEntry;
- for (std::vector<IncludeDirectoriesEntry*>::const_iterator
+ typedef cmTargetInternals::TargetPropertyEntry
+ TargetPropertyEntry;
+ for (std::vector<TargetPropertyEntry*>::const_iterator
it = this->Internal->IncludeDirectoriesEntries.begin(),
end = this->Internal->IncludeDirectoriesEntries.end();
it != end; ++it)
@@ -3450,6 +4142,42 @@ const char *cmTarget::GetProperty(const char* prop,
}
return output.c_str();
}
+ if(strcmp(prop,"COMPILE_OPTIONS") == 0)
+ {
+ static std::string output;
+ output = "";
+ std::string sep;
+ typedef cmTargetInternals::TargetPropertyEntry
+ TargetPropertyEntry;
+ for (std::vector<TargetPropertyEntry*>::const_iterator
+ it = this->Internal->CompileOptionsEntries.begin(),
+ end = this->Internal->CompileOptionsEntries.end();
+ it != end; ++it)
+ {
+ output += sep;
+ output += (*it)->ge->GetInput();
+ sep = ";";
+ }
+ return output.c_str();
+ }
+ if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
+ {
+ static std::string output;
+ output = "";
+ std::string sep;
+ typedef cmTargetInternals::TargetPropertyEntry
+ TargetPropertyEntry;
+ for (std::vector<TargetPropertyEntry*>::const_iterator
+ it = this->Internal->CompileDefinitionsEntries.begin(),
+ end = this->Internal->CompileDefinitionsEntries.end();
+ it != end; ++it)
+ {
+ output += sep;
+ output += (*it)->ge->GetInput();
+ sep = ";";
+ }
+ return output.c_str();
+ }
if (strcmp(prop,"IMPORTED") == 0)
{
@@ -3798,6 +4526,10 @@ std::string cmTarget::GetSOName(const char* config)
else
{
// Use the soname given if any.
+ if(info->SOName.find("@rpath/") == 0)
+ {
+ return info->SOName.substr(6);
+ }
return info->SOName;
}
}
@@ -3820,6 +4552,79 @@ std::string cmTarget::GetSOName(const char* config)
}
//----------------------------------------------------------------------------
+bool cmTarget::HasMacOSXRpath(const char* config)
+{
+ bool install_name_is_rpath = false;
+ bool macosx_rpath = this->GetPropertyAsBool("MACOSX_RPATH");
+
+ if(!this->IsImportedTarget)
+ {
+ const char* install_name = this->GetProperty("INSTALL_NAME_DIR");
+ bool use_install_name =
+ this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
+ if(install_name && use_install_name &&
+ std::string(install_name) == "@rpath")
+ {
+ install_name_is_rpath = true;
+ }
+ else if(install_name && use_install_name)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Lookup the imported soname.
+ if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
+ {
+ if(!info->NoSOName && !info->SOName.empty())
+ {
+ if(info->SOName.find("@rpath/") == 0)
+ {
+ install_name_is_rpath = true;
+ }
+ }
+ else
+ {
+ std::string install_name;
+ cmSystemTools::GuessLibraryInstallName(info->Location, install_name);
+ if(install_name.find("@rpath") != std::string::npos)
+ {
+ install_name_is_rpath = true;
+ }
+ }
+ }
+ }
+
+ if(!install_name_is_rpath && !macosx_rpath)
+ {
+ return false;
+ }
+
+ if(!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG"))
+ {
+ cmOStringStream w;
+ w << "Attempting to use";
+ if(macosx_rpath)
+ {
+ w << " MACOSX_RPATH";
+ }
+ else
+ {
+ w << " @rpath";
+ }
+ w << " without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being set.";
+ w << " This could be because you are using a Mac OS X version";
+ w << " less than 10.5 or because CMake's platform configuration is";
+ w << " corrupt.";
+ cmake* cm = this->Makefile->GetCMakeInstance();
+ cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace());
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config)
{
if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY)
@@ -3916,7 +4721,13 @@ std::string cmTarget::GetFullPath(const char* config, bool implib,
std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
bool realname)
{
- std::string fpath = this->GetMacContentDirectory(config, implib);
+ std::string fpath = this->GetDirectory(config, implib);
+ fpath += "/";
+ if(this->IsAppBundleOnApple())
+ {
+ fpath = this->BuildMacContentDirectory(fpath, config, false);
+ fpath += "/";
+ }
// Add the full name of the target.
if(implib)
@@ -4048,10 +4859,28 @@ void cmTarget::GetFullNameInternal(const char* config,
targetSuffix = this->Makefile->GetSafeDefinition(suffixVar);
}
- // frameworks do not have a prefix or a suffix
+ // frameworks have directory prefix but no suffix
+ std::string fw_prefix;
if(this->IsFrameworkOnApple())
{
- targetPrefix = 0;
+ fw_prefix = this->GetOutputName(config, false);
+ fw_prefix += ".framework/";
+ targetPrefix = fw_prefix.c_str();
+ targetSuffix = 0;
+ }
+
+ if(this->IsCFBundleOnApple())
+ {
+ fw_prefix = this->GetOutputName(config, false);
+ fw_prefix += ".";
+ const char *ext = this->GetProperty("BUNDLE_EXTENSION");
+ if (!ext)
+ {
+ ext = "bundle";
+ }
+ fw_prefix += ext;
+ fw_prefix += "/Contents/MacOS/";
+ targetPrefix = fw_prefix.c_str();
targetSuffix = 0;
}
@@ -4131,13 +4960,24 @@ void cmTarget::GetLibraryNames(std::string& name,
// The library name.
name = prefix+base+suffix;
- // The library's soname.
- this->ComputeVersionedName(soName, prefix, base, suffix,
- name, soversion);
-
- // The library's real name on disk.
- this->ComputeVersionedName(realName, prefix, base, suffix,
- name, version);
+ if(this->IsFrameworkOnApple())
+ {
+ realName = prefix;
+ realName += "Versions/";
+ realName += this->GetFrameworkVersion();
+ realName += "/";
+ realName += base;
+ soName = realName;
+ }
+ else
+ {
+ // The library's soname.
+ this->ComputeVersionedName(soName, prefix, base, suffix,
+ name, soversion);
+ // The library's real name on disk.
+ this->ComputeVersionedName(realName, prefix, base, suffix,
+ name, version);
+ }
// The import library name.
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
@@ -4425,14 +5265,13 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config)
}
//----------------------------------------------------------------------------
-std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
- bool for_xcode)
+std::string cmTarget::GetInstallNameDirForBuildTree(const char* config)
{
// If building directly for installation then the build tree install_name
// is the same as the install tree.
if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
{
- return GetInstallNameDirForInstallTree(config, for_xcode);
+ return GetInstallNameDirForInstallTree();
}
// Use the build tree directory for the target.
@@ -4440,12 +5279,16 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
!this->GetPropertyAsBool("SKIP_BUILD_RPATH"))
{
- std::string dir = this->GetDirectory(config);
- dir += "/";
- if(this->IsFrameworkOnApple() && !for_xcode)
+ std::string dir;
+ if(this->GetPropertyAsBool("MACOSX_RPATH"))
+ {
+ dir = "@rpath";
+ }
+ else
{
- dir += this->GetFrameworkDirectory(config);
+ dir = this->GetDirectory(config);
}
+ dir += "/";
return dir;
}
else
@@ -4455,29 +5298,26 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
}
//----------------------------------------------------------------------------
-std::string cmTarget::GetInstallNameDirForInstallTree(const char* config,
- bool for_xcode)
+std::string cmTarget::GetInstallNameDirForInstallTree()
{
if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
{
std::string dir;
+ const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
if(!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH"))
{
- const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
if(install_name_dir && *install_name_dir)
{
dir = install_name_dir;
dir += "/";
}
}
-
- if(this->IsFrameworkOnApple() && !for_xcode)
+ if(!install_name_dir && this->GetPropertyAsBool("MACOSX_RPATH"))
{
- dir += this->GetFrameworkDirectory(config);
+ dir = "@rpath/";
}
-
return dir;
}
else
@@ -5059,7 +5899,6 @@ void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
//----------------------------------------------------------------------------
bool cmTarget::IsChrpathUsed(const char* config)
{
-#if defined(CMAKE_USE_ELF_PARSER)
// Only certain target types have an rpath.
if(!(this->GetType() == cmTarget::SHARED_LIBRARY ||
this->GetType() == cmTarget::MODULE_LIBRARY ||
@@ -5093,6 +5932,12 @@ bool cmTarget::IsChrpathUsed(const char* config)
return false;
}
+ if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
+ {
+ return true;
+ }
+
+#if defined(CMAKE_USE_ELF_PARSER)
// Enable if the rpath flag uses a separator and the target uses ELF
// binaries.
if(const char* ll = this->GetLinkerLanguage(config, this))
@@ -5289,7 +6134,6 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
ImportInfo& info,
cmTarget *headTarget)
{
- (void)headTarget;
// This method finds information about an imported target from its
// properties. The "IMPORTED_" namespace is reserved for properties
// defined by the project exporting the target.
@@ -5379,11 +6223,16 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
// Get the link interface.
{
- std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
- linkProp += suffix;
-
+ std::string linkProp = "INTERFACE_LINK_LIBRARIES";
const char *propertyLibs = this->GetProperty(linkProp.c_str());
+ if (!propertyLibs)
+ {
+ linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
+ linkProp += suffix;
+ propertyLibs = this->GetProperty(linkProp.c_str());
+ }
+
if(!propertyLibs)
{
linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
@@ -5425,7 +6274,7 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
}
// Get the link languages.
- if(this->GetType() == cmTarget::STATIC_LIBRARY)
+ if(this->LinkLanguagePropagatesToDependents())
{
std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES";
linkProp += suffix;
@@ -5501,6 +6350,48 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config,
}
//----------------------------------------------------------------------------
+void cmTarget::GetTransitivePropertyLinkLibraries(
+ const char* config,
+ cmTarget *headTarget,
+ std::vector<std::string> &libs)
+{
+ cmTarget::LinkInterface const* iface = this->GetLinkInterface(config,
+ headTarget);
+ if (!iface)
+ {
+ return;
+ }
+ if(this->GetType() != STATIC_LIBRARY
+ || this->GetPolicyStatusCMP0022() == cmPolicies::WARN
+ || this->GetPolicyStatusCMP0022() == cmPolicies::OLD)
+ {
+ libs = iface->Libraries;
+ return;
+ }
+
+ const char* linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
+ const char* interfaceLibs = this->GetProperty(linkIfaceProp);
+
+ if (!interfaceLibs)
+ {
+ return;
+ }
+
+ // The interface libraries have been explicitly set.
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
+ linkIfaceProp, 0, 0);
+ dagChecker.SetTransitivePropertiesOnly();
+ cmSystemTools::ExpandListArgument(ge.Parse(interfaceLibs)->Evaluate(
+ this->Makefile,
+ config,
+ false,
+ headTarget,
+ this, &dagChecker), libs);
+}
+
+//----------------------------------------------------------------------------
bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
cmTarget *headTarget)
{
@@ -5519,9 +6410,19 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
// libraries and executables that export symbols.
const char* explicitLibraries = 0;
std::string linkIfaceProp;
- if(this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->IsExecutableWithExports())
+ if(this->PolicyStatusCMP0022 != cmPolicies::OLD &&
+ this->PolicyStatusCMP0022 != cmPolicies::WARN)
+ {
+ // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES.
+ linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
+ explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
+ }
+ else if(this->GetType() == cmTarget::SHARED_LIBRARY ||
+ this->IsExecutableWithExports())
{
+ // CMP0022 OLD behavior is to use LINK_INTERFACE_LIBRARIES if set on a
+ // shared lib or executable.
+
// Lookup the per-configuration property.
linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
linkIfaceProp += suffix;
@@ -5535,6 +6436,33 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
}
}
+ if(explicitLibraries && this->PolicyStatusCMP0022 == cmPolicies::WARN &&
+ !this->Internal->PolicyWarnedCMP0022)
+ {
+ // Compare the explicitly set old link interface properties to the
+ // preferred new link interface property one and warn if different.
+ const char* newExplicitLibraries =
+ this->GetProperty("INTERFACE_LINK_LIBRARIES");
+ if (newExplicitLibraries
+ && strcmp(newExplicitLibraries, explicitLibraries) != 0)
+ {
+ cmOStringStream w;
+ w <<
+ (this->Makefile->GetPolicies()
+ ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n"
+ "Target \"" << this->GetName() << "\" has an "
+ "INTERFACE_LINK_LIBRARIES property which differs from its " <<
+ linkIfaceProp << " properties."
+ "\n"
+ "INTERFACE_LINK_LIBRARIES:\n"
+ " " << newExplicitLibraries << "\n" <<
+ linkIfaceProp << ":\n"
+ " " << (explicitLibraries ? explicitLibraries : "(empty)") << "\n";
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->Internal->PolicyWarnedCMP0022 = true;
+ }
+ }
+
// There is no implicit link interface for executables or modules
// so if none was explicitly set then there is no link interface.
// Note that CMake versions 2.2 and below allowed linking to modules.
@@ -5560,7 +6488,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
headTarget,
this, &dagChecker), iface.Libraries);
- if(this->GetType() == cmTarget::SHARED_LIBRARY)
+ if(this->GetType() == cmTarget::SHARED_LIBRARY
+ || this->GetType() == cmTarget::STATIC_LIBRARY)
{
// Shared libraries may have runtime implementation dependencies
// on other shared libraries that are not in the interface.
@@ -5594,9 +6523,19 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
}
}
}
+ if(this->LinkLanguagePropagatesToDependents())
+ {
+ // Targets using this archive need its language runtime libraries.
+ iface.Languages = impl->Languages;
+ }
}
}
- else
+ else if (this->PolicyStatusCMP0022 == cmPolicies::WARN
+ || this->PolicyStatusCMP0022 == cmPolicies::OLD)
+ // If CMP0022 is NEW then the plain tll signature sets the
+ // INTERFACE_LINK_LIBRARIES, so if we get here then the project
+ // cleared the property explicitly and we should not fall back
+ // to the link implementation.
{
// The link implementation is the default link interface.
LinkImplementation const* impl = this->GetLinkImplementation(config,
@@ -5604,11 +6543,75 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
iface.ImplementationIsInterface = true;
iface.Libraries = impl->Libraries;
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
- if(this->GetType() == cmTarget::STATIC_LIBRARY)
+ if(this->LinkLanguagePropagatesToDependents())
{
// Targets using this archive need its language runtime libraries.
iface.Languages = impl->Languages;
}
+
+ if(this->PolicyStatusCMP0022 == cmPolicies::WARN &&
+ !this->Internal->PolicyWarnedCMP0022)
+ {
+ // Compare the link implementation fallback link interface to the
+ // preferred new link interface property and warn if different.
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
+ "INTERFACE_LINK_LIBRARIES", 0, 0);
+ std::vector<std::string> ifaceLibs;
+ const char* newExplicitLibraries =
+ this->GetProperty("INTERFACE_LINK_LIBRARIES");
+ cmSystemTools::ExpandListArgument(
+ ge.Parse(newExplicitLibraries)->Evaluate(this->Makefile,
+ config,
+ false,
+ headTarget,
+ this, &dagChecker),
+ ifaceLibs);
+ if (ifaceLibs != impl->Libraries)
+ {
+ std::string oldLibraries;
+ std::string newLibraries;
+ const char *sep = "";
+ for(std::vector<std::string>::const_iterator it
+ = impl->Libraries.begin(); it != impl->Libraries.end(); ++it)
+ {
+ oldLibraries += sep;
+ oldLibraries += *it;
+ sep = ";";
+ }
+ sep = "";
+ for(std::vector<std::string>::const_iterator it
+ = ifaceLibs.begin(); it != ifaceLibs.end(); ++it)
+ {
+ newLibraries += sep;
+ newLibraries += *it;
+ sep = ";";
+ }
+ if(oldLibraries.empty())
+ { oldLibraries = "(empty)"; }
+ if(newLibraries.empty())
+ { newLibraries = "(empty)"; }
+
+ cmOStringStream w;
+ w <<
+ (this->Makefile->GetPolicies()
+ ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n"
+ "Target \"" << this->GetName() << "\" has an "
+ "INTERFACE_LINK_LIBRARIES property. "
+ "This should be preferred as the source of the link interface "
+ "for this library but because CMP0022 is not set CMake is "
+ "ignoring the property and using the link implementation "
+ "as the link interface instead."
+ "\n"
+ "INTERFACE_LINK_LIBRARIES:\n"
+ " " << newLibraries << "\n"
+ "Link implementation:\n"
+ " " << oldLibraries << "\n";
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ this->Internal->PolicyWarnedCMP0022 = true;
+ }
+ }
}
if(this->GetType() == cmTarget::STATIC_LIBRARY)
@@ -5936,59 +6939,86 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head)
}
//----------------------------------------------------------------------------
-std::string cmTarget::GetFrameworkDirectory(const char* config)
+std::string cmTarget::GetFrameworkDirectory(const char* config,
+ bool rootDir)
{
std::string fpath;
- fpath += this->GetFullName(config, false);
- fpath += ".framework/Versions/";
- fpath += this->GetFrameworkVersion();
- fpath += "/";
+ fpath += this->GetOutputName(config, false);
+ fpath += ".framework";
+ if(!rootDir)
+ {
+ fpath += "/Versions/";
+ fpath += this->GetFrameworkVersion();
+ }
+ return fpath;
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::GetCFBundleDirectory(const char* config,
+ bool contentOnly)
+{
+ std::string fpath;
+ fpath += this->GetOutputName(config, false);
+ fpath += ".";
+ const char *ext = this->GetProperty("BUNDLE_EXTENSION");
+ if (!ext)
+ {
+ ext = "bundle";
+ }
+ fpath += ext;
+ fpath += "/Contents";
+ if(!contentOnly)
+ fpath += "/MacOS";
+ return fpath;
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::GetAppBundleDirectory(const char* config,
+ bool contentOnly)
+{
+ std::string fpath = this->GetFullName(config, false);
+ fpath += ".app/Contents";
+ if(!contentOnly)
+ fpath += "/MacOS";
return fpath;
}
//----------------------------------------------------------------------------
std::string cmTarget::BuildMacContentDirectory(const std::string& base,
const char* config,
- bool includeMacOS)
+ bool contentOnly)
{
std::string fpath = base;
if(this->IsAppBundleOnApple())
{
- fpath += this->GetFullName(config, false);
- fpath += ".app/Contents/";
- if(includeMacOS)
- fpath += "MacOS/";
+ fpath += this->GetAppBundleDirectory(config, contentOnly);
}
if(this->IsFrameworkOnApple())
{
- fpath += this->GetFrameworkDirectory(config);
+ fpath += this->GetFrameworkDirectory(config, contentOnly);
}
if(this->IsCFBundleOnApple())
{
- fpath += this->GetFullName(config, false);
- fpath += ".";
- const char *ext = this->GetProperty("BUNDLE_EXTENSION");
- if (!ext)
- {
- ext = "bundle";
- }
- fpath += ext;
- fpath += "/Contents/";
- if(includeMacOS)
- fpath += "MacOS/";
+ fpath += this->GetCFBundleDirectory(config, contentOnly);
}
return fpath;
}
//----------------------------------------------------------------------------
std::string cmTarget::GetMacContentDirectory(const char* config,
- bool implib,
- bool includeMacOS)
+ bool implib)
{
// Start with the output directory for the target.
std::string fpath = this->GetDirectory(config, implib);
fpath += "/";
- fpath = this->BuildMacContentDirectory(fpath, config, includeMacOS);
+ bool contentOnly = true;
+ if(this->IsFrameworkOnApple())
+ {
+ // additional files with a framework go into the version specific
+ // directory
+ contentOnly = false;
+ }
+ fpath = this->BuildMacContentDirectory(fpath, config, contentOnly);
return fpath;
}
@@ -6035,6 +7065,8 @@ cmTargetInternalPointer
cmTargetInternalPointer::~cmTargetInternalPointer()
{
deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
+ deleteAndClear(this->Pointer->CompileOptionsEntries);
+ deleteAndClear(this->Pointer->CompileDefinitionsEntries);
delete this->Pointer;
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 9d467961b..27b74ca4b 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -19,6 +19,14 @@
#include <cmsys/auto_ptr.hxx>
+#define CM_FOR_EACH_TARGET_POLICY(F) \
+ F(CMP0003) \
+ F(CMP0004) \
+ F(CMP0008) \
+ F(CMP0020) \
+ F(CMP0021) \
+ F(CMP0022)
+
class cmake;
class cmMakefile;
class cmSourceFile;
@@ -85,26 +93,19 @@ public:
///! Set/Get the name of the target
const char* GetName() const {return this->Name.c_str();}
+ const char* GetExportName();
///! Set the cmMakefile that owns this target
void SetMakefile(cmMakefile *mf);
cmMakefile *GetMakefile() const { return this->Makefile;};
- /** Get the status of policy CMP0003 when the target was created. */
- cmPolicies::PolicyStatus GetPolicyStatusCMP0003() const
- { return this->PolicyStatusCMP0003; }
-
- /** Get the status of policy CMP0004 when the target was created. */
- cmPolicies::PolicyStatus GetPolicyStatusCMP0004() const
- { return this->PolicyStatusCMP0004; }
+#define DECLARE_TARGET_POLICY(POLICY) \
+ cmPolicies::PolicyStatus GetPolicyStatus ## POLICY () const \
+ { return this->PolicyStatus ## POLICY; }
- /** Get the status of policy CMP0008 when the target was created. */
- cmPolicies::PolicyStatus GetPolicyStatusCMP0008() const
- { return this->PolicyStatusCMP0008; }
+ CM_FOR_EACH_TARGET_POLICY(DECLARE_TARGET_POLICY)
- /** Get the status of policy CMP0020 when the target was created. */
- cmPolicies::PolicyStatus GetPolicyStatusCMP0020() const
- { return this->PolicyStatusCMP0020; }
+#undef DECLARE_TARGET_POLICY
/**
* Get the list of the custom commands for this target
@@ -189,6 +190,12 @@ public:
void AddLinkLibrary(cmMakefile& mf,
const char *target, const char* lib,
LinkLibraryType llt);
+ enum TLLSignature {
+ KeywordTLLSignature,
+ PlainTLLSignature
+ };
+ bool PushTLLCommandTrace(TLLSignature signature);
+ void GetTllSignatureTraces(cmOStringStream &s, TLLSignature sig) const;
void MergeLinkLibraries( cmMakefile& mf, const char* selfname,
const LinkLibraryVectorType& libs );
@@ -271,6 +278,9 @@ public:
if the target cannot be linked. */
LinkInterface const* GetLinkInterface(const char* config,
cmTarget *headTarget);
+ void GetTransitivePropertyLinkLibraries(const char* config,
+ cmTarget *headTarget,
+ std::vector<std::string> &libs);
/** The link implementation specifies the direct library
dependencies needed by the object files of the target. */
@@ -336,7 +346,7 @@ public:
* Trace through the source files in this target and add al source files
* that they depend on, used by all generators
*/
- void TraceDependencies(const char* vsProjectFile);
+ void TraceDependencies();
/**
* Make sure the full path to all source files is known.
@@ -362,6 +372,9 @@ public:
/** Get the soname of the target. Allowed only for a shared library. */
std::string GetSOName(const char* config);
+ /** Whether this library has @rpath and platform supports it. */
+ bool HasMacOSXRpath(const char* config);
+
/** Test for special case of a third-party shared library that has
no soname at all. */
bool IsImportedSharedLibWithoutSOName(const char* config);
@@ -407,10 +420,14 @@ public:
/** Return true if builtin chrpath will work for this target */
bool IsChrpathUsed(const char* config);
- std::string GetInstallNameDirForBuildTree(const char* config,
- bool for_xcode = false);
- std::string GetInstallNameDirForInstallTree(const char* config,
- bool for_xcode = false);
+ /** Return the install name directory for the target in the
+ * build tree. For example: "@rpath/", "@loader_path/",
+ * or "/full/path/to/library". */
+ std::string GetInstallNameDirForBuildTree(const char* config);
+
+ /** Return the install name directory for the target in the
+ * install tree. For example: "@rpath/" or "@loader_path/". */
+ std::string GetInstallNameDirForInstallTree();
cmComputeLinkInformation* GetLinkInformation(const char* config,
cmTarget *head = 0);
@@ -430,7 +447,8 @@ public:
If no macro should be defined null is returned. */
const char* GetExportMacro();
- std::string GetCompileDefinitions(const char *config);
+ void GetCompileDefinitions(std::vector<std::string> &result,
+ const char *config);
// Compute the set of languages compiled by the target. This is
// computed every time it is called because the languages can change
@@ -462,6 +480,10 @@ public:
/** Return whether this target is an executable Bundle on Apple. */
bool IsAppBundleOnApple();
+ /** Return whether this target is an executable Bundle, a framework
+ or CFBundle on Apple. */
+ bool IsBundleOnApple();
+
/** Return the framework version string. Undefined if
IsFrameworkOnApple returns false. */
std::string GetFrameworkVersion();
@@ -476,28 +498,35 @@ public:
directory. */
bool UsesDefaultOutputDir(const char* config, bool implib);
- /** Append to @a base the mac content directory and return it. */
- std::string BuildMacContentDirectory(const std::string& base,
- const char* config = 0,
- bool includeMacOS = true);
-
/** @return the mac content directory for this target. */
- std::string GetMacContentDirectory(const char* config = 0,
- bool implib = false,
- bool includeMacOS = true);
+ std::string GetMacContentDirectory(const char* config,
+ bool implib);
/** @return whether this target have a well defined output file name. */
bool HaveWellDefinedOutputFiles();
/** @return the Mac framework directory without the base. */
- std::string GetFrameworkDirectory(const char* config = 0);
+ std::string GetFrameworkDirectory(const char* config, bool rootDir);
+
+ /** @return the Mac CFBundle directory without the base */
+ std::string GetCFBundleDirectory(const char* config, bool contentOnly);
+
+ /** @return the Mac App directory without the base */
+ std::string GetAppBundleDirectory(const char* config, bool contentOnly);
std::vector<std::string> GetIncludeDirectories(const char *config);
void InsertInclude(const cmValueWithOrigin &entry,
bool before = false);
+ void InsertCompileOption(const cmValueWithOrigin &entry,
+ bool before = false);
+ void InsertCompileDefinition(const cmValueWithOrigin &entry,
+ bool before = false);
void AppendBuildInterfaceIncludes();
+ void GetCompileOptions(std::vector<std::string> &result,
+ const char *config);
+
bool IsNullImpliedByLinkLibraries(const std::string &p);
bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config);
@@ -512,7 +541,24 @@ public:
std::string GetDebugGeneratorExpressions(const std::string &value,
cmTarget::LinkLibraryType llt);
+
+ void AddSystemIncludeDirectories(const std::set<cmStdString> &incs);
+ void AddSystemIncludeDirectories(const std::vector<std::string> &incs);
+ std::set<cmStdString> const & GetSystemIncludeDirectories() const
+ { return this->SystemIncludeDirectories; }
+
+ void FinalizeSystemIncludeDirectories();
+
+ bool LinkLanguagePropagatesToDependents() const
+ { return this->TargetTypeValue == STATIC_LIBRARY; }
+
private:
+ // The set of include directories that are marked as system include
+ // directories.
+ std::set<cmStdString> SystemIncludeDirectories;
+
+ std::vector<std::pair<TLLSignature, cmListFileBacktrace> > TLLCommands;
+
/**
* A list of direct dependencies. Use in conjunction with DependencyMap.
*/
@@ -596,6 +642,11 @@ private:
the same as GetFullName. */
std::string NormalGetRealName(const char* config);
+ /** Append to @a base the mac content directory and return it. */
+ std::string BuildMacContentDirectory(const std::string& base,
+ const char* config,
+ bool contentOnly);
+
private:
std::string Name;
std::vector<cmCustomCommand> PreBuildCommands;
@@ -622,6 +673,8 @@ private:
bool IsApple;
bool IsImportedTarget;
bool DebugIncludesDone;
+ bool DebugCompileOptionsDone;
+ bool DebugCompileDefinitionsDone;
mutable std::set<std::string> LinkImplicitNullProperties;
bool BuildInterfaceIncludesAppended;
@@ -660,10 +713,12 @@ private:
cmMakefile* Makefile;
// Policy status recorded when target was created.
- cmPolicies::PolicyStatus PolicyStatusCMP0003;
- cmPolicies::PolicyStatus PolicyStatusCMP0004;
- cmPolicies::PolicyStatus PolicyStatusCMP0008;
- cmPolicies::PolicyStatus PolicyStatusCMP0020;
+#define TARGET_POLICY_MEMBER(POLICY) \
+ cmPolicies::PolicyStatus PolicyStatus ## POLICY;
+
+ CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_MEMBER)
+
+#undef TARGET_POLICY_MEMBER
// Internal representation details.
friend class cmTargetInternals;
diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
index ba0ad5986..46c9666ef 100644
--- a/Source/cmTargetCompileDefinitionsCommand.cxx
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -60,7 +60,7 @@ std::string cmTargetCompileDefinitionsCommand
//----------------------------------------------------------------------------
void cmTargetCompileDefinitionsCommand
::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
- bool)
+ bool, bool)
{
tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
}
diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h
index ec9b071db..585485d2a 100644
--- a/Source/cmTargetCompileDefinitionsCommand.h
+++ b/Source/cmTargetCompileDefinitionsCommand.h
@@ -81,7 +81,7 @@ private:
virtual void HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content,
- bool prepend);
+ bool prepend, bool system);
virtual std::string Join(const std::vector<std::string> &content);
};
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
new file mode 100644
index 000000000..254acc73d
--- /dev/null
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -0,0 +1,62 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2013 Stephen Kelly <steveire@gmail.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmTargetCompileOptionsCommand.h"
+
+bool cmTargetCompileOptionsCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+ return this->HandleArguments(args, "COMPILE_OPTIONS", PROCESS_BEFORE);
+}
+
+void cmTargetCompileOptionsCommand
+::HandleImportedTarget(const std::string &tgt)
+{
+ cmOStringStream e;
+ e << "Cannot specify compile options for imported target \""
+ << tgt << "\".";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+void cmTargetCompileOptionsCommand
+::HandleMissingTarget(const std::string &name)
+{
+ cmOStringStream e;
+ e << "Cannot specify compile options for target \"" << name << "\" "
+ "which is not built by this project.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
+std::string cmTargetCompileOptionsCommand
+::Join(const std::vector<std::string> &content)
+{
+ std::string defs;
+ std::string sep;
+ for(std::vector<std::string>::const_iterator it = content.begin();
+ it != content.end(); ++it)
+ {
+ defs += sep + *it;
+ sep = ";";
+ }
+ return defs;
+}
+
+//----------------------------------------------------------------------------
+void cmTargetCompileOptionsCommand
+::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
+ bool, bool)
+{
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmValueWithOrigin entry(this->Join(content), lfbt);
+ tgt->InsertCompileOption(entry);
+}
diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h
new file mode 100644
index 000000000..b9afd7169
--- /dev/null
+++ b/Source/cmTargetCompileOptionsCommand.h
@@ -0,0 +1,90 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2013 Stephen Kelly <steveire@gmail.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+
+#ifndef cmTargetCompileOptionsCommand_h
+#define cmTargetCompileOptionsCommand_h
+
+#include "cmTargetPropCommandBase.h"
+
+class cmTargetCompileOptionsCommand : public cmTargetPropCommandBase
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ virtual cmCommand* Clone()
+ {
+ return new cmTargetCompileOptionsCommand;
+ }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ virtual bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus &status);
+
+ /**
+ * The name of the command as specified in CMakeList.txt.
+ */
+ virtual const char* GetName() const { return "target_compile_options";}
+
+ /**
+ * Succinct documentation.
+ */
+ virtual const char* GetTerseDocumentation() const
+ {
+ return
+ "Add compile options to a target.";
+ }
+
+ /**
+ * More documentation.
+ */
+ virtual const char* GetFullDocumentation() const
+ {
+ return
+ " target_compile_options(<target> [BEFORE] "
+ "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
+ " [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
+ "Specify compile options to use when compiling a given target. "
+ "The named <target> must have been created by a command such as "
+ "add_executable or add_library and must not be an IMPORTED target. "
+ "If BEFORE is specified, the content will be prepended to the property "
+ "instead of being appended.\n"
+ "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
+ "the scope of the following arguments. PRIVATE and PUBLIC items will "
+ "populate the COMPILE_OPTIONS property of <target>. PUBLIC and "
+ "INTERFACE items will populate the INTERFACE_COMPILE_OPTIONS "
+ "property of <target>. "
+ "The following arguments specify compile opitions. "
+ "Repeated calls for the same <target> append items in the order called."
+ "\n"
+ "Arguments to target_compile_options may use \"generator "
+ "expressions\" with the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ ;
+ }
+
+ cmTypeMacro(cmTargetCompileOptionsCommand, cmTargetPropCommandBase);
+
+private:
+ virtual void HandleImportedTarget(const std::string &tgt);
+ virtual void HandleMissingTarget(const std::string &name);
+
+ virtual void HandleDirectContent(cmTarget *tgt,
+ const std::vector<std::string> &content,
+ bool prepend, bool system);
+ virtual std::string Join(const std::vector<std::string> &content);
+};
+
+#endif
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
index c9d87fb7e..76658887d 100644
--- a/Source/cmTargetExport.h
+++ b/Source/cmTargetExport.h
@@ -12,6 +12,8 @@
#ifndef cmTargetExport_h
#define cmTargetExport_h
+#include "cmStandardIncludes.h"
+
class cmTarget;
class cmInstallTargetGenerator;
class cmInstallFilesGenerator;
@@ -33,6 +35,7 @@ public:
cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
+ std::string InterfaceIncludeDirectories;
///@}
};
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
index 12d0a515f..e7b906c9e 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.cxx
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -15,7 +15,8 @@
bool cmTargetIncludeDirectoriesCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
- return this->HandleArguments(args, "INCLUDE_DIRECTORIES", PROCESS_BEFORE);
+ return this->HandleArguments(args, "INCLUDE_DIRECTORIES",
+ ArgumentFlags(PROCESS_BEFORE | PROCESS_SYSTEM));
}
//----------------------------------------------------------------------------
@@ -65,10 +66,39 @@ std::string cmTargetIncludeDirectoriesCommand
//----------------------------------------------------------------------------
void cmTargetIncludeDirectoriesCommand
::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
- bool prepend)
+ bool prepend, bool system)
{
cmListFileBacktrace lfbt;
this->Makefile->GetBacktrace(lfbt);
cmValueWithOrigin entry(this->Join(content), lfbt);
tgt->InsertInclude(entry, prepend);
+ if (system)
+ {
+ tgt->AddSystemIncludeDirectories(content);
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmTargetIncludeDirectoriesCommand
+::HandleInterfaceContent(cmTarget *tgt,
+ const std::vector<std::string> &content,
+ bool prepend, bool system)
+{
+ cmTargetPropCommandBase::HandleInterfaceContent(tgt, content,
+ prepend, system);
+
+ if (system)
+ {
+ std::string joined;
+ std::string sep;
+ for(std::vector<std::string>::const_iterator it = content.begin();
+ it != content.end(); ++it)
+ {
+ joined += sep;
+ sep = ";";
+ joined += *it;
+ }
+ tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES",
+ joined.c_str());
+ }
}
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
index e4bc9cf67..fcc37f06a 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.h
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -54,7 +54,7 @@ public:
virtual const char* GetFullDocumentation() const
{
return
- " target_include_directories(<target> [BEFORE] "
+ " target_include_directories(<target> [SYSTEM] [BEFORE] "
"<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
" [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
"Specify include directories or targets to use when compiling a given "
@@ -71,6 +71,14 @@ public:
"The following arguments specify include directories. Specified "
"include directories may be absolute paths or relative paths. "
"Repeated calls for the same <target> append items in the order called."
+ "If SYSTEM is specified, the compiler will be told the "
+ "directories are meant as system include directories on some "
+ "platforms (signalling this setting might achieve effects such as "
+ "the compiler skipping warnings, or these fixed-install system files "
+ "not being considered in dependency calculations - see compiler "
+ "docs). If SYSTEM is used together with PUBLIC or INTERFACE, the "
+ "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES target property will be "
+ "populated with the specified directories."
"\n"
"Arguments to target_include_directories may use \"generator "
"expressions\" with the syntax \"$<...>\". "
@@ -86,7 +94,11 @@ private:
virtual void HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content,
- bool prepend);
+ bool prepend, bool system);
+ virtual void HandleInterfaceContent(cmTarget *tgt,
+ const std::vector<std::string> &content,
+ bool prepend, bool system);
+
virtual std::string Join(const std::vector<std::string> &content);
};
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index b7b7691c8..c2f46a1b1 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -31,6 +31,11 @@ bool cmTargetLinkLibrariesCommand
return false;
}
+ if (this->Makefile->IsAlias(args[0].c_str()))
+ {
+ this->SetError("can not be used on an ALIAS target.");
+ return false;
+ }
// Lookup the target for which libraries are specified.
this->Target =
this->Makefile->GetCMakeInstance()
@@ -116,7 +121,7 @@ bool cmTargetLinkLibrariesCommand
{
if(args[i] == "LINK_INTERFACE_LIBRARIES")
{
- this->CurrentProcessingState = ProcessingLinkInterface;
+ this->CurrentProcessingState = ProcessingPlainLinkInterface;
if(i != 1)
{
this->Makefile->IssueMessage(
@@ -127,9 +132,26 @@ bool cmTargetLinkLibrariesCommand
return true;
}
}
+ else if(args[i] == "INTERFACE")
+ {
+ if(i != 1
+ && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
+ && this->CurrentProcessingState != ProcessingKeywordPublicInterface
+ && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
+ {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "The INTERFACE option must appear as the second "
+ "argument, just after the target name."
+ );
+ return true;
+ }
+ this->CurrentProcessingState = ProcessingKeywordLinkInterface;
+ }
else if(args[i] == "LINK_PUBLIC")
{
- if(i != 1 && this->CurrentProcessingState != ProcessingPrivateInterface)
+ if(i != 1
+ && this->CurrentProcessingState != ProcessingPlainPrivateInterface)
{
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
@@ -138,11 +160,28 @@ bool cmTargetLinkLibrariesCommand
);
return true;
}
- this->CurrentProcessingState = ProcessingPublicInterface;
+ this->CurrentProcessingState = ProcessingPlainPublicInterface;
+ }
+ else if(args[i] == "PUBLIC")
+ {
+ if(i != 1
+ && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
+ && this->CurrentProcessingState != ProcessingKeywordPublicInterface
+ && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
+ {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "The PUBLIC or PRIVATE option must appear as the second "
+ "argument, just after the target name."
+ );
+ return true;
+ }
+ this->CurrentProcessingState = ProcessingKeywordPublicInterface;
}
else if(args[i] == "LINK_PRIVATE")
{
- if(i != 1 && this->CurrentProcessingState != ProcessingPublicInterface)
+ if(i != 1
+ && this->CurrentProcessingState != ProcessingPlainPublicInterface)
{
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
@@ -151,7 +190,23 @@ bool cmTargetLinkLibrariesCommand
);
return true;
}
- this->CurrentProcessingState = ProcessingPrivateInterface;
+ this->CurrentProcessingState = ProcessingPlainPrivateInterface;
+ }
+ else if(args[i] == "PRIVATE")
+ {
+ if(i != 1
+ && this->CurrentProcessingState != ProcessingKeywordPrivateInterface
+ && this->CurrentProcessingState != ProcessingKeywordPublicInterface
+ && this->CurrentProcessingState != ProcessingKeywordLinkInterface)
+ {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "The PUBLIC or PRIVATE option must appear as the second "
+ "argument, just after the target name."
+ );
+ return true;
+ }
+ this->CurrentProcessingState = ProcessingKeywordPrivateInterface;
}
else if(args[i] == "debug")
{
@@ -184,7 +239,10 @@ bool cmTargetLinkLibrariesCommand
{
// The link type was specified by the previous argument.
haveLLT = false;
- this->HandleLibrary(args[i].c_str(), llt);
+ if (!this->HandleLibrary(args[i].c_str(), llt))
+ {
+ return false;
+ }
}
else
{
@@ -210,7 +268,10 @@ bool cmTargetLinkLibrariesCommand
llt = cmTarget::OPTIMIZED;
}
}
- this->HandleLibrary(args[i].c_str(), llt);
+ if (!this->HandleLibrary(args[i].c_str(), llt))
+ {
+ return false;
+ }
}
}
@@ -224,12 +285,17 @@ bool cmTargetLinkLibrariesCommand
cmSystemTools::SetFatalErrorOccured();
}
+ const cmPolicies::PolicyStatus policy22Status
+ = this->Target->GetPolicyStatusCMP0022();
+
// If any of the LINK_ options were given, make sure the
// LINK_INTERFACE_LIBRARIES target property exists.
// Use of any of the new keywords implies awareness of
// this property. And if no libraries are named, it should
// result in an empty link interface.
- if(this->CurrentProcessingState != ProcessingLinkLibraries &&
+ if((policy22Status == cmPolicies::OLD ||
+ policy22Status == cmPolicies::WARN) &&
+ this->CurrentProcessingState != ProcessingLinkLibraries &&
!this->Target->GetProperty("LINK_INTERFACE_LIBRARIES"))
{
this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
@@ -252,22 +318,106 @@ cmTargetLinkLibrariesCommand
}
//----------------------------------------------------------------------------
-void
+bool
cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
cmTarget::LinkLibraryType llt)
{
+ cmTarget::TLLSignature sig =
+ (this->CurrentProcessingState == ProcessingPlainPrivateInterface
+ || this->CurrentProcessingState == ProcessingPlainPublicInterface
+ || this->CurrentProcessingState == ProcessingKeywordPrivateInterface
+ || this->CurrentProcessingState == ProcessingKeywordPublicInterface
+ || this->CurrentProcessingState == ProcessingKeywordLinkInterface)
+ ? cmTarget::KeywordTLLSignature : cmTarget::PlainTLLSignature;
+ if (!this->Target->PushTLLCommandTrace(sig))
+ {
+ const char *modal = 0;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0023))
+ {
+ case cmPolicies::WARN:
+ modal = "should";
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ modal = "must";
+ messageType = cmake::FATAL_ERROR;
+ }
+
+ if(modal)
+ {
+ cmOStringStream e;
+ // If the sig is a keyword form and there is a conflict, the existing
+ // form must be the plain form.
+ const char *existingSig
+ = (sig == cmTarget::KeywordTLLSignature ? "plain"
+ : "keyword");
+ e << this->Makefile->GetPolicies()
+ ->GetPolicyWarning(cmPolicies::CMP0023) << "\n"
+ "The " << existingSig << " signature for target_link_libraries "
+ "has already been used with the target \""
+ << this->Target->GetName() << "\". All uses of "
+ "target_link_libraries with a target " << modal << " be either "
+ "all-keyword or all-plain.\n";
+ this->Target->GetTllSignatureTraces(e,
+ sig == cmTarget::KeywordTLLSignature
+ ? cmTarget::PlainTLLSignature
+ : cmTarget::KeywordTLLSignature);
+ this->Makefile->IssueMessage(messageType, e.str().c_str());
+ if(messageType == cmake::FATAL_ERROR)
+ {
+ return false;
+ }
+ }
+ }
+
// Handle normal case first.
- if(this->CurrentProcessingState != ProcessingLinkInterface)
+ if(this->CurrentProcessingState != ProcessingKeywordLinkInterface
+ && this->CurrentProcessingState != ProcessingPlainLinkInterface)
{
this->Makefile
->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
- if (this->CurrentProcessingState != ProcessingPublicInterface)
+ if(this->CurrentProcessingState == ProcessingLinkLibraries)
+ {
+ this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
+ this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
+ return true;
+ }
+ else if(this->CurrentProcessingState != ProcessingKeywordPublicInterface
+ && this->CurrentProcessingState != ProcessingPlainPublicInterface)
{
- // Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface.
- return;
+ if (this->Target->GetType() == cmTarget::STATIC_LIBRARY)
+ {
+ std::string configLib = this->Target
+ ->GetDebugGeneratorExpressions(lib, llt);
+ if (cmGeneratorExpression::IsValidTargetName(lib)
+ || cmGeneratorExpression::Find(lib) != std::string::npos)
+ {
+ configLib = "$<LINK_ONLY:" + configLib + ">";
+ }
+ this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
+ configLib.c_str());
+ }
+ // Not a 'public' or 'interface' library. Do not add to interface
+ // property.
+ return true;
}
}
+ this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
+ this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
+
+ const cmPolicies::PolicyStatus policy22Status
+ = this->Target->GetPolicyStatusCMP0022();
+
+ if (policy22Status != cmPolicies::OLD
+ && policy22Status != cmPolicies::WARN)
+ {
+ return true;
+ }
+
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> const& debugConfigs =
this->Makefile->GetCMakeInstance()->GetDebugConfigs();
@@ -303,4 +453,5 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
}
}
}
+ return true;
}
diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h
index c683016dd..2cf6b03ef 100644
--- a/Source/cmTargetLinkLibrariesCommand.h
+++ b/Source/cmTargetLinkLibrariesCommand.h
@@ -88,14 +88,19 @@ public:
"See the IMPORTED mode of the add_library command for more "
"information. "
"\n"
- "Library dependencies are transitive by default. "
+ "Library dependencies are transitive by default with this signature. "
"When this target is linked into another target then the libraries "
"linked to this target will appear on the link line for the other "
"target too. "
- "See the LINK_INTERFACE_LIBRARIES target property to override the "
- "set of transitive link dependencies for a target. "
+ "This transitive \"link interface\" is stored in the "
+ "INTERFACE_LINK_LIBRARIES target property when policy CMP0022 is set "
+ "to NEW and may be overridden by setting the property directly. "
+ "("
+ "When CMP0022 is not set to NEW, transitive linking is builtin "
+ "but may be overridden by the LINK_INTERFACE_LIBRARIES property. "
"Calls to other signatures of this command may set the property "
"making any libraries linked exclusively by this signature private."
+ ")"
"\n"
"CMake will also propagate \"usage requirements\" from linked library "
"targets. "
@@ -109,17 +114,38 @@ public:
" INTERFACE_POSITION_INDEPENDENT_CODE: Sets POSITION_INDEPENDENT_CODE\n"
" or checked for consistency with existing value\n"
"\n"
+ "If an <item> is a library in a Mac OX framework, the Headers "
+ "directory of the framework will also be processed as a \"usage "
+ "requirement\". This has the same effect as passing the framework "
+ "directory as an include directory."
+ " target_link_libraries(<target>\n"
+ " <PRIVATE|PUBLIC|INTERFACE> <lib> ...\n"
+ " [<PRIVATE|PUBLIC|INTERFACE> <lib> ... ] ...])\n"
+ "The PUBLIC, PRIVATE and INTERFACE keywords can be used to specify "
+ "both the link dependencies and the link interface in one command. "
+ "Libraries and targets following PUBLIC are linked to, and are "
+ "made part of the link interface. Libraries and targets "
+ "following PRIVATE are linked to, but are not made part of the "
+ "link interface. Libraries following INTERFACE are appended "
+ "to the link interface and are not used for linking <target>."
+ "\n"
" target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n"
" [[debug|optimized|general] <lib>] ...)\n"
"The LINK_INTERFACE_LIBRARIES mode appends the libraries "
- "to the LINK_INTERFACE_LIBRARIES and its per-configuration equivalent "
- "target properties instead of using them for linking. "
- "Libraries specified as \"debug\" are appended to the "
+ "to the INTERFACE_LINK_LIBRARIES target property instead of using them "
+ "for linking. If policy CMP0022 is not NEW, then this mode also "
+ "appends libraries to the LINK_INTERFACE_LIBRARIES and its "
+ "per-configuration equivalent. This signature "
+ "is for compatibility only. Prefer the INTERFACE mode instead. "
+ "Libraries specified as \"debug\" are wrapped in a generator "
+ "expression to correspond to debug builds. If policy CMP0022 is not "
+ "NEW, the libraries are also appended to the "
"LINK_INTERFACE_LIBRARIES_DEBUG property (or to the properties "
"corresponding to configurations listed in the DEBUG_CONFIGURATIONS "
"global property if it is set). "
"Libraries specified as \"optimized\" are appended to the "
- "LINK_INTERFACE_LIBRARIES property. "
+ "INTERFACE_LINK_LIBRARIES property. If policy CMP0022 is not NEW, "
+ "they are also appended to the LINK_INTERFACE_LIBRARIES property. "
"Libraries specified as \"general\" (or without any keyword) are "
"treated as if specified for both \"debug\" and \"optimized\"."
"\n"
@@ -129,11 +155,15 @@ public:
" [<LINK_PRIVATE|LINK_PUBLIC>\n"
" [[debug|optimized|general] <lib>] ...])\n"
"The LINK_PUBLIC and LINK_PRIVATE modes can be used to specify both "
- "the link dependencies and the link interface in one command. "
+ "the link dependencies and the link interface in one command. This "
+ "signature is for compatibility only. Prefer the PUBLIC or PRIVATE "
+ "keywords instead. "
"Libraries and targets following LINK_PUBLIC are linked to, and are "
- "made part of the LINK_INTERFACE_LIBRARIES. Libraries and targets "
- "following LINK_PRIVATE are linked to, but are not made part of the "
- "LINK_INTERFACE_LIBRARIES. "
+ "made part of the INTERFACE_LINK_LIBRARIES. If policy CMP0022 is not "
+ "NEW, they are also made part of the LINK_INTERFACE_LIBRARIES. "
+ "Libraries and targets following LINK_PRIVATE are linked to, but are "
+ "not made part of the INTERFACE_LINK_LIBRARIES (or "
+ "LINK_INTERFACE_LIBRARIES)."
"\n"
"The library dependency graph is normally acyclic (a DAG), but in the "
"case of mutually-dependent STATIC libraries CMake allows the graph "
@@ -173,14 +203,17 @@ private:
cmTarget* Target;
enum ProcessingState {
ProcessingLinkLibraries,
- ProcessingLinkInterface,
- ProcessingPublicInterface,
- ProcessingPrivateInterface
+ ProcessingPlainLinkInterface,
+ ProcessingKeywordLinkInterface,
+ ProcessingPlainPublicInterface,
+ ProcessingKeywordPublicInterface,
+ ProcessingPlainPrivateInterface,
+ ProcessingKeywordPrivateInterface
};
ProcessingState CurrentProcessingState;
- void HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt);
+ bool HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt);
};
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 771097ca2..1862cb696 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -19,13 +19,18 @@ bool cmTargetPropCommandBase
::HandleArguments(std::vector<std::string> const& args, const char *prop,
ArgumentFlags flags)
{
- if(args.size() < 3)
+ if(args.size() < 2)
{
this->SetError("called with incorrect number of arguments");
return false;
}
// Lookup the target for which libraries are specified.
+ if (this->Makefile->IsAlias(args[0].c_str()))
+ {
+ this->SetError("can not be used on an ALIAS target.");
+ return false;
+ }
this->Target =
this->Makefile->GetCMakeInstance()
->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
@@ -48,12 +53,24 @@ bool cmTargetPropCommandBase
return false;
}
+ bool system = false;
unsigned int argIndex = 1;
+ if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM")
+ {
+ if (args.size() < 3)
+ {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+ system = true;
+ ++argIndex;
+ }
+
bool prepend = false;
if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE")
{
- if (args.size() < 4)
+ if (args.size() < 3)
{
this->SetError("called with incorrect number of arguments");
return false;
@@ -66,7 +83,7 @@ bool cmTargetPropCommandBase
while (argIndex < args.size())
{
- if (!this->ProcessContentArgs(args, argIndex, prepend))
+ if (!this->ProcessContentArgs(args, argIndex, prepend, system))
{
return false;
}
@@ -77,7 +94,7 @@ bool cmTargetPropCommandBase
//----------------------------------------------------------------------------
bool cmTargetPropCommandBase
::ProcessContentArgs(std::vector<std::string> const& args,
- unsigned int &argIndex, bool prepend)
+ unsigned int &argIndex, bool prepend, bool system)
{
const std::string scope = args[argIndex];
@@ -105,12 +122,12 @@ bool cmTargetPropCommandBase
|| args[i] == "PRIVATE"
|| args[i] == "INTERFACE" )
{
- this->PopulateTargetProperies(scope, content, prepend);
+ this->PopulateTargetProperies(scope, content, prepend, system);
return true;
}
content.push_back(args[i]);
}
- this->PopulateTargetProperies(scope, content, prepend);
+ this->PopulateTargetProperies(scope, content, prepend, system);
return true;
}
@@ -118,27 +135,35 @@ bool cmTargetPropCommandBase
void cmTargetPropCommandBase
::PopulateTargetProperies(const std::string &scope,
const std::vector<std::string> &content,
- bool prepend)
+ bool prepend, bool system)
{
if (scope == "PRIVATE" || scope == "PUBLIC")
{
- this->HandleDirectContent(this->Target, content, prepend);
+ this->HandleDirectContent(this->Target, content, prepend, system);
}
if (scope == "INTERFACE" || scope == "PUBLIC")
{
- if (prepend)
- {
- const std::string propName = std::string("INTERFACE_") + this->Property;
- const char *propValue = this->Target->GetProperty(propName.c_str());
- const std::string totalContent = this->Join(content) + (propValue
- ? std::string(";") + propValue
- : std::string());
- this->Target->SetProperty(propName.c_str(), totalContent.c_str());
- }
- else
- {
- this->Target->AppendProperty(("INTERFACE_" + this->Property).c_str(),
- this->Join(content).c_str());
- }
+ this->HandleInterfaceContent(this->Target, content, prepend, system);
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmTargetPropCommandBase::HandleInterfaceContent(cmTarget *tgt,
+ const std::vector<std::string> &content,
+ bool prepend, bool)
+{
+ if (prepend)
+ {
+ const std::string propName = std::string("INTERFACE_") + this->Property;
+ const char *propValue = tgt->GetProperty(propName.c_str());
+ const std::string totalContent = this->Join(content) + (propValue
+ ? std::string(";") + propValue
+ : std::string());
+ tgt->SetProperty(propName.c_str(), totalContent.c_str());
+ }
+ else
+ {
+ tgt->AppendProperty(("INTERFACE_" + this->Property).c_str(),
+ this->Join(content).c_str());
}
}
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index 8047a48aa..690582fdd 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -25,7 +25,8 @@ public:
enum ArgumentFlags {
NO_FLAGS = 0,
- PROCESS_BEFORE = 1
+ PROCESS_BEFORE = 1,
+ PROCESS_SYSTEM = 2
};
bool HandleArguments(std::vector<std::string> const& args,
@@ -36,20 +37,24 @@ protected:
std::string Property;
cmTarget *Target;
+ virtual void HandleInterfaceContent(cmTarget *tgt,
+ const std::vector<std::string> &content,
+ bool prepend, bool system);
private:
virtual void HandleImportedTarget(const std::string &tgt) = 0;
virtual void HandleMissingTarget(const std::string &name) = 0;
virtual void HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content,
- bool prepend) = 0;
+ bool prepend, bool system) = 0;
+
virtual std::string Join(const std::vector<std::string> &content) = 0;
bool ProcessContentArgs(std::vector<std::string> const& args,
- unsigned int &argIndex, bool prepend);
+ unsigned int &argIndex, bool prepend, bool system);
void PopulateTargetProperies(const std::string &scope,
const std::vector<std::string> &content,
- bool prepend);
+ bool prepend, bool system);
};
#endif
diff --git a/Source/cmTest.cxx b/Source/cmTest.cxx
index 912ec7634..0904431d1 100644
--- a/Source/cmTest.cxx
+++ b/Source/cmTest.cxx
@@ -135,7 +135,7 @@ void cmTest::DefineProperties(cmake *cm)
"If the output matches this regular expression the test will fail.",
"If set, if the output matches one of "
"specified regular expressions, the test will fail."
- "For example: PASS_REGULAR_EXPRESSION \"[^a-z]Error;ERROR;Failed\"");
+ "For example: FAIL_REGULAR_EXPRESSION \"[^a-z]Error;ERROR;Failed\"");
cm->DefineProperty
("LABELS", cmProperty::TEST,
diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h
index 6caa130ce..a20594cbe 100644
--- a/Source/cmTryCompileCommand.h
+++ b/Source/cmTryCompileCommand.h
@@ -64,19 +64,19 @@ public:
"Specify targetName to build a specific target instead of the 'all' or "
"'ALL_BUILD' target."
"\n"
- " try_compile(RESULT_VAR <bindir> <srcfile>\n"
+ " try_compile(RESULT_VAR <bindir> <srcfile|SOURCES srcfile...>\n"
" [CMAKE_FLAGS flags...]\n"
" [COMPILE_DEFINITIONS flags...]\n"
" [LINK_LIBRARIES libs...]\n"
" [OUTPUT_VARIABLE <var>]\n"
- " [COPY_FILE <fileName>])\n"
- "Try building a source file into an executable. "
- "In this form the user need only supply a source file that defines "
- "a 'main'. "
- "CMake will create a CMakeLists.txt file to build the source "
+ " [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]])\n"
+ "Try building an executable from one or more source files. "
+ "In this form the user need only supply one or more source files "
+ "that include a definition for 'main'. "
+ "CMake will create a CMakeLists.txt file to build the source(s) "
"as an executable. "
"Specify COPY_FILE to get a copy of the linked executable at the "
- "given fileName."
+ "given fileName and optionally COPY_FILE_ERROR to capture any error."
"\n"
"In this version all files in bindir/CMakeFiles/CMakeTmp "
"will be cleaned automatically. For debugging, --debug-trycompile can "
diff --git a/Source/cmVS10LinkFlagTable.h b/Source/cmVS10LinkFlagTable.h
index 64febbb52..5d1562002 100644
--- a/Source/cmVS10LinkFlagTable.h
+++ b/Source/cmVS10LinkFlagTable.h
@@ -201,7 +201,7 @@ static cmVS7FlagTable cmVS10LinkFlagTable[] =
cmVS7FlagTable::UserValueRequired},
{"GenerateMapFile", "MAP", "", "true",
cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
- {"MapFileName", "MAP", "Generate Map File", "",
+ {"MapFileName", "MAP:", "Generate Map File", "",
cmVS7FlagTable::UserValueRequired},
//String List Properties
diff --git a/Source/cmVS11LinkFlagTable.h b/Source/cmVS11LinkFlagTable.h
index ea0d0f0b0..b4587a836 100644
--- a/Source/cmVS11LinkFlagTable.h
+++ b/Source/cmVS11LinkFlagTable.h
@@ -227,7 +227,7 @@ static cmVS7FlagTable cmVS11LinkFlagTable[] =
cmVS7FlagTable::UserValueRequired},
{"GenerateMapFile", "MAP", "", "true",
cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
- {"MapFileName", "MAP", "Generate Map File", "",
+ {"MapFileName", "MAP:", "Generate Map File", "",
cmVS7FlagTable::UserValueRequired},
//String List Properties
diff --git a/Source/cmVS12LinkFlagTable.h b/Source/cmVS12LinkFlagTable.h
index ce32e3815..73d450a9d 100644
--- a/Source/cmVS12LinkFlagTable.h
+++ b/Source/cmVS12LinkFlagTable.h
@@ -227,7 +227,7 @@ static cmVS7FlagTable cmVS12LinkFlagTable[] =
cmVS7FlagTable::UserValueRequired},
{"GenerateMapFile", "MAP", "", "true",
cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
- {"MapFileName", "MAP", "Generate Map File", "",
+ {"MapFileName", "MAP:", "Generate Map File", "",
cmVS7FlagTable::UserValueRequired},
//String List Properties
diff --git a/Source/cmVariableWatch.cxx b/Source/cmVariableWatch.cxx
index f5fdca465..8ad6fce8f 100644
--- a/Source/cmVariableWatch.cxx
+++ b/Source/cmVariableWatch.cxx
@@ -15,6 +15,7 @@ static const char* const cmVariableWatchAccessStrings[] =
{
"READ_ACCESS",
"UNKNOWN_READ_ACCESS",
+ "UNKNOWN_DEFINED_ACCESS",
"ALLOWED_UNKNOWN_READ_ACCESS",
"MODIFIED_ACCESS",
"REMOVED_ACCESS",
@@ -36,37 +37,63 @@ cmVariableWatch::cmVariableWatch()
cmVariableWatch::~cmVariableWatch()
{
+ cmVariableWatch::StringToVectorOfPairs::iterator svp_it;
+
+ for ( svp_it = this->WatchMap.begin();
+ svp_it != this->WatchMap.end(); ++svp_it )
+ {
+ cmVariableWatch::VectorOfPairs::iterator p_it;
+
+ for ( p_it = svp_it->second.begin();
+ p_it != svp_it->second.end(); ++p_it )
+ {
+ delete *p_it;
+ }
+ }
}
-void cmVariableWatch::AddWatch(const std::string& variable,
- WatchMethod method, void* client_data /*=0*/)
+bool cmVariableWatch::AddWatch(const std::string& variable,
+ WatchMethod method, void* client_data /*=0*/,
+ DeleteData delete_data /*=0*/)
{
- cmVariableWatch::Pair p;
- p.Method = method;
- p.ClientData = client_data;
+ cmVariableWatch::Pair* p = new cmVariableWatch::Pair;
+ p->Method = method;
+ p->ClientData = client_data;
+ p->DeleteDataCall = delete_data;
cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable];
cmVariableWatch::VectorOfPairs::size_type cc;
for ( cc = 0; cc < vp->size(); cc ++ )
{
- cmVariableWatch::Pair* pair = &(*vp)[cc];
- if ( pair->Method == method )
+ cmVariableWatch::Pair* pair = (*vp)[cc];
+ if ( pair->Method == method &&
+ client_data && client_data == pair->ClientData)
{
- (*vp)[cc] = p;
- return;
+ // Callback already exists
+ return false;
}
}
vp->push_back(p);
+ return true;
}
void cmVariableWatch::RemoveWatch(const std::string& variable,
- WatchMethod method)
+ WatchMethod method,
+ void* client_data /*=0*/)
{
+ if ( !this->WatchMap.count(variable) )
+ {
+ return;
+ }
cmVariableWatch::VectorOfPairs* vp = &this->WatchMap[variable];
cmVariableWatch::VectorOfPairs::iterator it;
for ( it = vp->begin(); it != vp->end(); ++it )
{
- if ( it->Method == method )
+ if ( (*it)->Method == method &&
+ // If client_data is NULL, we want to disconnect all watches against
+ // the given method; otherwise match ClientData as well.
+ (!client_data || (client_data == (*it)->ClientData)))
{
+ delete *it;
vp->erase(it);
return;
}
@@ -86,7 +113,7 @@ void cmVariableWatch::VariableAccessed(const std::string& variable,
cmVariableWatch::VectorOfPairs::const_iterator it;
for ( it = vp->begin(); it != vp->end(); it ++ )
{
- it->Method(variable, access_type, it->ClientData,
+ (*it)->Method(variable, access_type, (*it)->ClientData,
newValue, mf);
}
}
diff --git a/Source/cmVariableWatch.h b/Source/cmVariableWatch.h
index 7dd4ac5e6..790c75acc 100644
--- a/Source/cmVariableWatch.h
+++ b/Source/cmVariableWatch.h
@@ -26,6 +26,7 @@ class cmVariableWatch
public:
typedef void (*WatchMethod)(const std::string& variable, int access_type,
void* client_data, const char* newValue, const cmMakefile* mf);
+ typedef void (*DeleteData)(void* client_data);
cmVariableWatch();
~cmVariableWatch();
@@ -33,9 +34,10 @@ public:
/**
* Add watch to the variable
*/
- void AddWatch(const std::string& variable, WatchMethod method,
- void* client_data=0);
- void RemoveWatch(const std::string& variable, WatchMethod method);
+ bool AddWatch(const std::string& variable, WatchMethod method,
+ void* client_data=0, DeleteData delete_data=0);
+ void RemoveWatch(const std::string& variable, WatchMethod method,
+ void* client_data=0);
/**
* This method is called when variable is accessed
@@ -67,10 +69,18 @@ protected:
{
WatchMethod Method;
void* ClientData;
- Pair() : Method(0), ClientData(0) {}
+ DeleteData DeleteDataCall;
+ Pair() : Method(0), ClientData(0), DeleteDataCall(0) {}
+ ~Pair()
+ {
+ if (this->DeleteDataCall && this->ClientData)
+ {
+ this->DeleteDataCall(this->ClientData);
+ }
+ }
};
- typedef std::vector< Pair > VectorOfPairs;
+ typedef std::vector< Pair* > VectorOfPairs;
typedef std::map<cmStdString, VectorOfPairs > StringToVectorOfPairs;
StringToVectorOfPairs WatchMap;
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index a432943ae..33e159bce 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -14,63 +14,27 @@
#include "cmVariableWatch.h"
//----------------------------------------------------------------------------
-static void cmVariableWatchCommandVariableAccessed(
- const std::string& variable, int access_type, void* client_data,
- const char* newValue, const cmMakefile* mf)
+struct cmVariableWatchCallbackData
{
- cmVariableWatchCommand* command
- = static_cast<cmVariableWatchCommand*>(client_data);
- command->VariableAccessed(variable, access_type, newValue, mf);
-}
+ bool InCallback;
+ std::string Command;
+};
//----------------------------------------------------------------------------
-cmVariableWatchCommand::cmVariableWatchCommand()
-{
- this->InCallback = false;
-}
-
-//----------------------------------------------------------------------------
-bool cmVariableWatchCommand
-::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+static void cmVariableWatchCommandVariableAccessed(
+ const std::string& variable, int access_type, void* client_data,
+ const char* newValue, const cmMakefile* mf)
{
- if ( args.size() < 1 )
- {
- this->SetError("must be called with at least one argument.");
- return false;
- }
- std::string variable = args[0];
- if ( args.size() > 1 )
- {
- std::string command = args[1];
- this->Handlers[variable].Commands.push_back(args[1]);
- }
- if ( variable == "CMAKE_CURRENT_LIST_FILE" )
- {
- cmOStringStream ostr;
- ostr << "cannot be set on the variable: " << variable.c_str();
- this->SetError(ostr.str().c_str());
- return false;
- }
+ cmVariableWatchCallbackData* data
+ = static_cast<cmVariableWatchCallbackData*>(client_data);
- this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
- variable, cmVariableWatchCommandVariableAccessed, this);
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
- int access_type, const char* newValue, const cmMakefile* mf)
-{
- if ( this->InCallback )
+ if ( data->InCallback )
{
return;
}
- this->InCallback = true;
+ data->InCallback = true;
cmListFileFunction newLFF;
- cmVariableWatchCommandHandler *handler = &this->Handlers[variable];
- cmVariableWatchCommandHandler::VectorOfCommands::iterator it;
cmListFileArgument arg;
bool processed = false;
const char* accessString = cmVariableWatch::GetAccessAsString(access_type);
@@ -80,22 +44,25 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
cmMakefile* makefile = const_cast<cmMakefile*>(mf);
std::string stack = makefile->GetProperty("LISTFILE_STACK");
- for ( it = handler->Commands.begin(); it != handler->Commands.end();
- ++ it )
+ if ( !data->Command.empty() )
{
- std::string command = *it;
newLFF.Arguments.clear();
newLFF.Arguments.push_back(
- cmListFileArgument(variable, true, "unknown", 9999));
+ cmListFileArgument(variable, cmListFileArgument::Quoted,
+ "unknown", 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(accessString, true, "unknown", 9999));
+ cmListFileArgument(accessString, cmListFileArgument::Quoted,
+ "unknown", 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(newValue?newValue:"", true, "unknown", 9999));
+ cmListFileArgument(newValue?newValue:"", cmListFileArgument::Quoted,
+ "unknown", 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(currentListFile, true, "unknown", 9999));
+ cmListFileArgument(currentListFile, cmListFileArgument::Quoted,
+ "unknown", 9999));
newLFF.Arguments.push_back(
- cmListFileArgument(stack, true, "unknown", 9999));
- newLFF.Name = command;
+ cmListFileArgument(stack, cmListFileArgument::Quoted,
+ "unknown", 9999));
+ newLFF.Name = data->Command;
newLFF.FilePath = "Some weird path";
newLFF.Line = 9999;
cmExecutionStatus status;
@@ -106,10 +73,10 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
cmOStringStream error;
error << "Error in cmake code at\n"
<< arg.FilePath << ":" << arg.Line << ":\n"
- << "A command failed during the invocation of callback\""
- << command << "\".";
+ << "A command failed during the invocation of callback \""
+ << data->Command << "\".";
cmSystemTools::Error(error.str().c_str());
- this->InCallback = false;
+ data->InCallback = false;
return;
}
processed = true;
@@ -117,24 +84,76 @@ void cmVariableWatchCommand::VariableAccessed(const std::string& variable,
if ( !processed )
{
cmOStringStream msg;
- msg << "* Variable \"" << variable.c_str() << "\" was accessed using "
- << accessString << " in: " << currentListFile << std::endl;
- msg << " The value of the variable: \"" << newValue << "\"" << std::endl;
- msg << " The list file stack: " << stack.c_str();
- cmSystemTools::Message(msg.str().c_str());
- std::vector<std::string> vars = makefile->GetDefinitions();
- cmOStringStream msg2;
- size_t cc;
- for ( cc = 0; cc < vars.size(); cc ++ )
- {
- if ( vars[cc] == variable )
- {
- continue;
- }
- msg2 << vars[cc] << " = \""
- << makefile->GetDefinition(vars[cc].c_str()) << "\"" << std::endl;
- }
- //cmSystemTools::Message(msg2.str().c_str());
+ msg << "Variable \"" << variable.c_str() << "\" was accessed using "
+ << accessString << " with value \"" << (newValue?newValue:"") << "\".";
+ makefile->IssueMessage(cmake::LOG, msg.str());
+ }
+
+ data->InCallback = false;
+}
+
+//----------------------------------------------------------------------------
+static void deleteVariableWatchCallbackData(void* client_data)
+{
+ cmVariableWatchCallbackData* data
+ = static_cast<cmVariableWatchCallbackData*>(client_data);
+ delete data;
+}
+
+//----------------------------------------------------------------------------
+cmVariableWatchCommand::cmVariableWatchCommand()
+{
+}
+
+//----------------------------------------------------------------------------
+cmVariableWatchCommand::~cmVariableWatchCommand()
+{
+ std::set<std::string>::const_iterator it;
+ for ( it = this->WatchedVariables.begin();
+ it != this->WatchedVariables.end();
+ ++it )
+ {
+ this->Makefile->GetCMakeInstance()->GetVariableWatch()->RemoveWatch(
+ *it, cmVariableWatchCommandVariableAccessed);
+ }
+}
+
+//----------------------------------------------------------------------------
+bool cmVariableWatchCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+ if ( args.size() < 1 )
+ {
+ this->SetError("must be called with at least one argument.");
+ return false;
+ }
+ std::string variable = args[0];
+ std::string command;
+ if ( args.size() > 1 )
+ {
+ command = args[1];
}
- this->InCallback = false;
+ if ( variable == "CMAKE_CURRENT_LIST_FILE" )
+ {
+ cmOStringStream ostr;
+ ostr << "cannot be set on the variable: " << variable.c_str();
+ this->SetError(ostr.str().c_str());
+ return false;
+ }
+
+ cmVariableWatchCallbackData* data = new cmVariableWatchCallbackData;
+
+ data->InCallback = false;
+ data->Command = command;
+
+ this->WatchedVariables.insert(variable);
+ if ( !this->Makefile->GetCMakeInstance()->GetVariableWatch()->AddWatch(
+ variable, cmVariableWatchCommandVariableAccessed,
+ data, deleteVariableWatchCallbackData) )
+ {
+ deleteVariableWatchCallbackData(data);
+ return false;
+ }
+
+ return true;
}
diff --git a/Source/cmVariableWatchCommand.h b/Source/cmVariableWatchCommand.h
index 3abc08894..545535c40 100644
--- a/Source/cmVariableWatchCommand.h
+++ b/Source/cmVariableWatchCommand.h
@@ -14,13 +14,6 @@
#include "cmCommand.h"
-class cmVariableWatchCommandHandler
-{
-public:
- typedef std::vector<std::string> VectorOfCommands;
- VectorOfCommands Commands;
-};
-
/** \class cmVariableWatchCommand
* \brief Watch when the variable changes and invoke command
*
@@ -39,6 +32,9 @@ public:
//! Default constructor
cmVariableWatchCommand();
+ //! Destructor.
+ ~cmVariableWatchCommand();
+
/**
* This is called when the command is first encountered in
* the CMakeLists.txt file.
@@ -83,13 +79,8 @@ public:
cmTypeMacro(cmVariableWatchCommand, cmCommand);
- void VariableAccessed(const std::string& variable, int access_type,
- const char* newValue, const cmMakefile* mf);
-
protected:
- std::map<std::string, cmVariableWatchCommandHandler> Handlers;
-
- bool InCallback;
+ std::set<std::string> WatchedVariables;
};
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 9cfb3703e..6376376a0 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -216,12 +216,16 @@ void cmVisualStudio10TargetGenerator::Generate()
// Write the encoding header into the file
char magic[] = {0xEF,0xBB, 0xBF};
this->BuildFileStream->write(magic, 3);
- this->WriteString("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",0);
- this->WriteString("<Project DefaultTargets=\"Build\" "
- "ToolsVersion=\"4.0\" "
- "xmlns=\"http://schemas.microsoft.com/"
- "developer/msbuild/2003\">\n",
- 0);
+
+ //get the tools version to use
+ const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
+ std::string project_defaults="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+ project_defaults.append("<Project DefaultTargets=\"Build\" ToolsVersion=\"");
+ project_defaults.append(toolsVer +"\" ");
+ project_defaults.append(
+ "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
+ this->WriteString(project_defaults.c_str(),0);
+
this->WriteProjectConfigurations();
this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1);
this->WriteString("<ProjectGUID>", 2);
@@ -274,6 +278,15 @@ void cmVisualStudio10TargetGenerator::Generate()
"</Keyword>\n";
}
+ const char* vsGlobalRootNamespace =
+ this->Target->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
+ if(vsGlobalRootNamespace)
+ {
+ this->WriteString("<RootNamespace>", 2);
+ (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalRootNamespace) <<
+ "</RootNamespace>\n";
+ }
+
this->WriteString("<Platform>", 2);
(*this->BuildFileStream) << this->Platform << "</Platform>\n";
const char* projLabel = this->Target->GetProperty("PROJECT_LABEL");
@@ -283,6 +296,13 @@ void cmVisualStudio10TargetGenerator::Generate()
}
this->WriteString("<ProjectName>", 2);
(*this->BuildFileStream) << projLabel << "</ProjectName>\n";
+ if(const char* targetFrameworkVersion = this->Target->GetProperty(
+ "VS_DOTNET_TARGET_FRAMEWORK_VERSION"))
+ {
+ this->WriteString("<TargetFrameworkVersion>", 2);
+ (*this->BuildFileStream) << targetFrameworkVersion
+ << "</TargetFrameworkVersion>\n";
+ }
this->WriteString("</PropertyGroup>\n", 1);
this->WriteString("<Import Project="
"\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n",
@@ -291,6 +311,11 @@ void cmVisualStudio10TargetGenerator::Generate()
this->WriteString(
"<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n", 1);
this->WriteString("<ImportGroup Label=\"ExtensionSettings\">\n", 1);
+ if (this->GlobalGenerator->IsMasmEnabled())
+ {
+ this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
+ "BuildCustomizations\\masm.props\" />\n", 2);
+ }
this->WriteString("</ImportGroup>\n", 1);
this->WriteString("<ImportGroup Label=\"PropertySheets\">\n", 1);
this->WriteString("<Import Project=\"" VS10_USER_PROPS "\""
@@ -303,12 +328,18 @@ void cmVisualStudio10TargetGenerator::Generate()
this->WriteCustomCommands();
this->WriteAllSources();
this->WriteDotNetReferences();
+ this->WriteEmbeddedResourceGroup();
this->WriteWinRTReferences();
this->WriteProjectReferences();
this->WriteString(
"<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\""
" />\n", 1);
this->WriteString("<ImportGroup Label=\"ExtensionTargets\">\n", 1);
+ if (this->GlobalGenerator->IsMasmEnabled())
+ {
+ this->WriteString("<Import Project=\"$(VCTargetsPath)\\"
+ "BuildCustomizations\\masm.targets\" />\n", 2);
+ }
this->WriteString("</ImportGroup>\n", 1);
this->WriteString("</Project>", 0);
// The groups are stored in a separate file for VS 10
@@ -341,6 +372,47 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
}
}
+void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
+{
+ std::vector<cmSourceFile*> const& resxObjs =
+ this->GeneratorTarget->ResxSources;
+ if(!resxObjs.empty())
+ {
+ this->WriteString("<ItemGroup>\n", 1);
+ for(std::vector<cmSourceFile*>::const_iterator oi = resxObjs.begin();
+ oi != resxObjs.end(); ++oi)
+ {
+ std::string obj = (*oi)->GetFullPath();
+ this->WriteString("<EmbeddedResource Include=\"", 2);
+ this->ConvertToWindowsSlash(obj);
+ (*this->BuildFileStream ) << obj << "\">\n";
+
+ this->WriteString("<DependentUpon>", 3);
+ std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
+ (*this->BuildFileStream ) << hFileName;
+ this->WriteString("</DependentUpon>\n", 3);
+
+ std::vector<std::string> const * configs =
+ this->GlobalGenerator->GetConfigurations();
+ for(std::vector<std::string>::const_iterator i = configs->begin();
+ i != configs->end(); ++i)
+ {
+ this->WritePlatformConfigTag("LogicalName", i->c_str(), 3);
+ if(this->Target->GetProperty("VS_GLOBAL_ROOTNAMESPACE"))
+ {
+ (*this->BuildFileStream ) << "$(RootNamespace).";
+ }
+ (*this->BuildFileStream ) << "%(Filename)";
+ (*this->BuildFileStream ) << ".resources";
+ (*this->BuildFileStream ) << "</LogicalName>\n";
+ }
+
+ this->WriteString("</EmbeddedResource>\n", 2);
+ }
+ this->WriteString("</ItemGroup>\n", 1);
+ }
+}
+
void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
{
std::vector<std::string> references;
@@ -467,6 +539,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
this->WriteString("<WindowsAppContainer>true"
"</WindowsAppContainer>\n", 2);
}
+
this->WriteString("</PropertyGroup>\n", 1);
}
}
@@ -647,18 +720,40 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
fout.write(magic, 3);
cmGeneratedFileStream* save = this->BuildFileStream;
this->BuildFileStream = & fout;
- this->WriteString("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<Project "
- "ToolsVersion=\"4.0\" "
- "xmlns=\"http://schemas.microsoft.com/"
- "developer/msbuild/2003\">\n",
- 0);
+
+ //get the tools version to use
+ const std::string toolsVer(this->GlobalGenerator->GetToolsVersion());
+ std::string project_defaults="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+ project_defaults.append("<Project ToolsVersion=\"");
+ project_defaults.append(toolsVer +"\" ");
+ project_defaults.append(
+ "xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
+ this->WriteString(project_defaults.c_str(),0);
+
for(ToolSourceMap::const_iterator ti = this->Tools.begin();
ti != this->Tools.end(); ++ti)
{
this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
}
+ std::vector<cmSourceFile*> const& resxObjs =
+ this->GeneratorTarget->ResxSources;
+ if(!resxObjs.empty())
+ {
+ this->WriteString("<ItemGroup>\n", 1);
+ for(std::vector<cmSourceFile*>::const_iterator oi = resxObjs.begin();
+ oi != resxObjs.end(); ++oi)
+ {
+ std::string obj = (*oi)->GetFullPath();
+ this->WriteString("<EmbeddedResource Include=\"", 2);
+ this->ConvertToWindowsSlash(obj);
+ (*this->BuildFileStream ) << obj << "\">\n";
+ this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteString("</EmbeddedResource>\n", 2);
+ }
+ this->WriteString("</ItemGroup>\n", 1);
+ }
+
// Add object library contents as external objects.
std::vector<std::string> objs;
this->GeneratorTarget->UseObjectLibraries(objs);
@@ -713,6 +808,23 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
<< "</UniqueIdentifier>\n";
this->WriteString("</Filter>\n", 2);
}
+
+ if(!this->GeneratorTarget->ResxSources.empty())
+ {
+ this->WriteString("<Filter Include=\"Resource Files\">\n", 2);
+ std::string guidName = "SG_Filter_Resource Files";
+ this->GlobalGenerator->CreateGUID(guidName.c_str());
+ this->WriteString("<UniqueIdentifier>", 3);
+ std::string guid =
+ this->GlobalGenerator->GetGUID(guidName.c_str());
+ (*this->BuildFileStream) << "{" << guid << "}"
+ << "</UniqueIdentifier>\n";
+ this->WriteString("<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;", 3);
+ (*this->BuildFileStream) << "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;";
+ (*this->BuildFileStream) << "mfcribbon-ms</Extensions>\n";
+ this->WriteString("</Filter>\n", 2);
+ }
+
this->WriteString("</ItemGroup>\n", 1);
this->WriteString("</Project>\n", 0);
// restore stream pointer
@@ -844,8 +956,20 @@ void cmVisualStudio10TargetGenerator::WriteSource(
}
this->ConvertToWindowsSlash(sourceFile);
this->WriteString("<", 2);
- (*this->BuildFileStream ) << tool <<
- " Include=\"" << sourceFile << "\"" << (end? end : " />\n");
+ (*this->BuildFileStream ) << tool << " Include=\"" << sourceFile << "\"";
+
+ if(sf->GetExtension() == "h" &&
+ this->IsResxHeader(sf->GetFullPath()))
+ {
+ (*this->BuildFileStream ) << ">\n";
+ this->WriteString("<FileType>CppForm</FileType>\n", 3);
+ this->WriteString("</ClInclude>\n", 2);
+ }
+ else
+ {
+ (*this->BuildFileStream ) << (end? end : " />\n");
+ }
+
ToolSource toolSource = {sf, forceRelative};
this->Tools[tool].push_back(toolSource);
}
@@ -876,24 +1000,37 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
si != this->GeneratorTarget->ObjectSources.end(); ++si)
{
const char* lang = (*si)->GetLanguage();
- bool cl = strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0;
- bool rc = strcmp(lang, "RC") == 0;
- const char* tool = cl? "ClCompile" : (rc? "ResourceCompile" : "None");
- this->WriteSource(tool, *si, " ");
- // ouput any flags specific to this source file
- if(cl && this->OutputSourceSpecificFlags(*si))
+ const char* tool = NULL;
+ if (strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0)
{
- // if the source file has specific flags the tag
- // is ended on a new line
- this->WriteString("</ClCompile>\n", 2);
+ tool = "ClCompile";
}
- else if(rc && this->OutputSourceSpecificFlags(*si))
+ else if (strcmp(lang, "ASM_MASM") == 0 &&
+ this->GlobalGenerator->IsMasmEnabled())
{
- this->WriteString("</ResourceCompile>\n", 2);
+ tool = "MASM";
+ }
+ else if (strcmp(lang, "RC") == 0)
+ {
+ tool = "ResourceCompile";
+ }
+
+ if (tool)
+ {
+ this->WriteSource(tool, *si, " ");
+ if (this->OutputSourceSpecificFlags(*si))
+ {
+ this->WriteString("</", 2);
+ (*this->BuildFileStream ) << tool << ">\n";
+ }
+ else
+ {
+ (*this->BuildFileStream ) << " />\n";
+ }
}
else
{
- (*this->BuildFileStream ) << " />\n";
+ this->WriteSource("None", *si);
}
}
@@ -1192,7 +1329,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
if(!linkLanguage)
{
cmSystemTools::Error
- ("CMake can not determine linker language for target:",
+ ("CMake can not determine linker language for target: ",
this->Name.c_str());
return false;
}
@@ -1219,21 +1356,21 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
{
flags += " /TP ";
}
+ this->LocalGenerator->AddCompileOptions(flags, this->Target,
+ linkLanguage, configName.c_str());
}
- // Add the target-specific flags.
- if(const char* targetFlags = this->Target->GetProperty("COMPILE_FLAGS"))
- {
- flags += " ";
- flags += targetFlags;
- }
+
// Get preprocessor definitions for this directory.
std::string defineFlags = this->Target->GetMakefile()->GetDefineFlags();
clOptions.FixExceptionHandlingDefault();
clOptions.AddFlag("PrecompiledHeader", "NotUsing");
+ std::string asmLocation = configName + "/";
+ clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
clOptions.Parse(flags.c_str());
clOptions.Parse(defineFlags.c_str());
- clOptions.AddDefines(this->Target->GetCompileDefinitions(
- configName.c_str()).c_str());
+ std::vector<std::string> targetDefines;
+ this->Target->GetCompileDefinitions(targetDefines, configName.c_str());
+ clOptions.AddDefines(targetDefines);
clOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -1272,18 +1409,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
"\n", "CXX");
- this->WriteString("<AssemblerListingLocation>", 3);
- *this->BuildFileStream << configName
- << "</AssemblerListingLocation>\n";
this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
- if(this->Target->GetType() != cmTarget::OBJECT_LIBRARY)
- {
- this->WriteString("<ProgramDataBaseFileName>", 3);
- *this->BuildFileStream << this->Target->GetPDBDirectory(configName.c_str())
- << "/"
- << this->Target->GetPDBName(configName.c_str())
- << "</ProgramDataBaseFileName>\n";
- }
this->WriteString("</ClCompile>\n", 2);
}
@@ -1294,7 +1420,9 @@ OutputIncludes(std::vector<std::string> const & includes)
for(std::vector<std::string>::const_iterator i = includes.begin();
i != includes.end(); ++i)
{
- *this->BuildFileStream << *i << ";";
+ std::string incDir = *i;
+ this->ConvertToWindowsSlash(incDir);
+ *this->BuildFileStream << cmVS10EscapeXML(incDir) << ";";
}
this->WriteString("%(AdditionalIncludeDirectories)"
"</AdditionalIncludeDirectories>\n", 0);
@@ -1322,20 +1450,17 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config)
{
return;
}
- const char* libflags = this->Target->GetProperty("STATIC_LIBRARY_FLAGS");
- std::string flagsConfigVar = "STATIC_LIBRARY_FLAGS_";
- flagsConfigVar += cmSystemTools::UpperCase(config);
- const char* libflagsConfig =
- this->Target->GetProperty(flagsConfigVar.c_str());
- if(libflags || libflagsConfig)
+ std::string libflags;
+ this->LocalGenerator->GetStaticLibraryFlags(libflags,
+ cmSystemTools::UpperCase(config), this->Target);
+ if(!libflags.empty())
{
this->WriteString("<Lib>\n", 2);
cmVisualStudioGeneratorOptions
libOptions(this->LocalGenerator,
cmVisualStudioGeneratorOptions::Linker,
cmVSGetLibFlagTable(this->LocalGenerator), 0, this);
- libOptions.Parse(libflags?libflags:"");
- libOptions.Parse(libflagsConfig?libflagsConfig:"");
+ libOptions.Parse(libflags.c_str());
libOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
libOptions.OutputFlagMap(*this->BuildFileStream, " ");
this->WriteString("</Lib>\n", 2);
@@ -1377,7 +1502,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
if(!linkLanguage)
{
cmSystemTools::Error
- ("CMake can not determine linker language for target:",
+ ("CMake can not determine linker language for target: ",
this->Name.c_str());
return false;
}
@@ -1428,11 +1553,11 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
}
if ( this->Target->GetPropertyAsBool("WIN32_EXECUTABLE") )
{
- flags += " /SUBSYSTEM:WINDOWS";
+ linkOptions.AddFlag("SubSystem", "Windows");
}
else
{
- flags += " /SUBSYSTEM:CONSOLE";
+ linkOptions.AddFlag("SubSystem", "Console");
}
std::string standardLibsVar = "CMAKE_";
standardLibsVar += linkLanguage;
@@ -1459,7 +1584,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
if(!pcli)
{
cmSystemTools::Error
- ("CMake can not compute cmComputeLinkInformation for target:",
+ ("CMake can not compute cmComputeLinkInformation for target: ",
this->Name.c_str());
return false;
}
@@ -1591,6 +1716,21 @@ void cmVisualStudio10TargetGenerator::
WriteMidlOptions(std::string const& /*config*/,
std::vector<std::string> const & includes)
{
+ // This processes *any* of the .idl files specified in the project's file
+ // list (and passed as the item metadata %(Filename) expressing the rule
+ // input filename) into output files at the per-config *build* dir
+ // ($(IntDir)) each.
+ //
+ // IOW, this MIDL section is intended to provide a fully generic syntax
+ // content suitable for most cases (read: if you get errors, then it's quite
+ // probable that the error is on your side of the .idl setup).
+ //
+ // Also, note that the marked-as-generated _i.c file in the Visual Studio
+ // generator case needs to be referred to as $(IntDir)\foo_i.c at the
+ // project's file list, otherwise the compiler-side processing won't pick it
+ // up (for non-directory form, it ends up looking in project binary dir
+ // only). Perhaps there's something to be done to make this more automatic
+ // on the CMake side?
this->WriteString("<Midl>\n", 2);
this->OutputIncludes(includes);
this->WriteString("<OutputDirectory>$(IntDir)</OutputDirectory>\n", 3);
@@ -1730,3 +1870,12 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
}
this->WriteString("</ItemGroup>\n", 1);
}
+
+bool cmVisualStudio10TargetGenerator::
+ IsResxHeader(const std::string& headerFile)
+{
+ std::set<std::string>::iterator it =
+ this->GeneratorTarget->ExpectedResxHeaders.find(headerFile);
+
+ return it != this->GeneratorTarget->ExpectedResxHeaders.end();
+}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 55a850a1b..9a480a87f 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -59,9 +59,11 @@ private:
void WriteSources(const char* tool, std::vector<cmSourceFile*> const&);
void WriteAllSources();
void WriteDotNetReferences();
+ void WriteEmbeddedResourceGroup();
void WriteWinRTReferences();
void WritePathAndIncrementalLinkOptions();
void WriteItemDefinitionGroups();
+
bool ComputeClOptions();
bool ComputeClOptions(std::string const& configName);
void WriteClOptions(std::string const& config,
@@ -91,7 +93,7 @@ private:
std::vector<cmSourceGroup>& );
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups);
-
+ bool IsResxHeader(const std::string& headerFile);
private:
typedef cmVisualStudioGeneratorOptions Options;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 01950e16d..6aca787f5 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -6,6 +6,7 @@
inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s)
{
std::string ret = s;
+ cmSystemTools::ReplaceString(ret, ";", "%3B");
cmSystemTools::ReplaceString(ret, "&", "&amp;");
cmSystemTools::ReplaceString(ret, "<", "&lt;");
cmSystemTools::ReplaceString(ret, ">", "&gt;");
@@ -99,13 +100,13 @@ void cmVisualStudioGeneratorOptions::SetVerboseMakefile(bool verbose)
}
}
-bool cmVisualStudioGeneratorOptions::IsDebug()
+bool cmVisualStudioGeneratorOptions::IsDebug() const
{
return this->FlagMap.find("DebugInformationFormat") != this->FlagMap.end();
}
//----------------------------------------------------------------------------
-bool cmVisualStudioGeneratorOptions::UsingUnicode()
+bool cmVisualStudioGeneratorOptions::UsingUnicode() const
{
// Look for the a _UNICODE definition.
for(std::vector<std::string>::const_iterator di = this->Defines.begin();
@@ -119,7 +120,7 @@ bool cmVisualStudioGeneratorOptions::UsingUnicode()
return false;
}
//----------------------------------------------------------------------------
-bool cmVisualStudioGeneratorOptions::UsingSBCS()
+bool cmVisualStudioGeneratorOptions::UsingSBCS() const
{
// Look for the a _SBCS definition.
for(std::vector<std::string>::const_iterator di = this->Defines.begin();
@@ -229,7 +230,7 @@ cmVisualStudioGeneratorOptions
}
if(this->Version >= cmLocalVisualStudioGenerator::VS10)
{
- // if there are configuration specifc flags, then
+ // if there are configuration specific flags, then
// use the configuration specific tag for PreprocessorDefinitions
if(this->Configuration.size())
{
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index a1a55daff..90f76672d 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -47,10 +47,10 @@ public:
void SetVerboseMakefile(bool verbose);
// Check for specific options.
- bool UsingUnicode();
- bool UsingSBCS();
+ bool UsingUnicode() const;
+ bool UsingSBCS() const;
- bool IsDebug();
+ bool IsDebug() const;
// Write options to output.
void OutputPreprocessorDefinitions(std::ostream& fout,
const char* prefix,
diff --git a/Source/cmVisualStudioSlnData.cxx b/Source/cmVisualStudioSlnData.cxx
new file mode 100644
index 000000000..82b4ee84f
--- /dev/null
+++ b/Source/cmVisualStudioSlnData.cxx
@@ -0,0 +1,62 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2013 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmVisualStudioSlnData.h"
+
+//----------------------------------------------------------------------------
+const cmSlnProjectEntry*
+cmSlnData::GetProjectByGUID(const std::string& projectGUID) const
+{
+ ProjectStorage::const_iterator it(ProjectsByGUID.find(projectGUID));
+ if (it != ProjectsByGUID.end())
+ return &it->second;
+ else
+ return NULL;
+}
+
+//----------------------------------------------------------------------------
+const cmSlnProjectEntry*
+cmSlnData::GetProjectByName(const std::string& projectName) const
+{
+ ProjectStringIndex::const_iterator it(ProjectNameIndex.find(projectName));
+ if (it != ProjectNameIndex.end())
+ return &it->second->second;
+ else
+ return NULL;
+}
+
+//----------------------------------------------------------------------------
+std::vector<cmSlnProjectEntry> cmSlnData::GetProjects() const
+{
+ ProjectStringIndex::const_iterator it(this->ProjectNameIndex.begin()),
+ itEnd(this->ProjectNameIndex.end());
+ std::vector<cmSlnProjectEntry> result;
+ for (; it != itEnd; ++it)
+ result.push_back(it->second->second);
+ return result;
+}
+
+//----------------------------------------------------------------------------
+cmSlnProjectEntry* cmSlnData::AddProject(
+ const std::string& projectGUID,
+ const std::string& projectName,
+ const std::string& projectRelativePath)
+{
+ ProjectStorage::iterator it(ProjectsByGUID.find(projectGUID));
+ if (it != ProjectsByGUID.end())
+ return NULL;
+ it = ProjectsByGUID.insert(
+ ProjectStorage::value_type(
+ projectGUID,
+ cmSlnProjectEntry(projectGUID, projectName, projectRelativePath))).first;
+ ProjectNameIndex[projectName] = it;
+ return &it->second;
+}
diff --git a/Source/cmVisualStudioSlnData.h b/Source/cmVisualStudioSlnData.h
new file mode 100644
index 000000000..ec128cf11
--- /dev/null
+++ b/Source/cmVisualStudioSlnData.h
@@ -0,0 +1,58 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2013 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmVisualStudioSlnData_h
+#define cmVisualStudioSlnData_h
+
+#include "cmStandardIncludes.h"
+
+class cmSlnProjectEntry
+{
+public:
+ cmSlnProjectEntry() {}
+ cmSlnProjectEntry(const std::string& guid,
+ const std::string& name,
+ const std::string& relativePath)
+ : Guid(guid), Name(name), RelativePath(relativePath)
+ {}
+
+ std::string GetGUID() const { return Guid; }
+ std::string GetName() const { return Name; }
+ std::string GetRelativePath() const { return RelativePath; }
+
+private:
+ std::string Guid, Name, RelativePath;
+};
+
+
+class cmSlnData
+{
+public:
+ const cmSlnProjectEntry*
+ GetProjectByGUID(const std::string& projectGUID) const;
+
+ const cmSlnProjectEntry*
+ GetProjectByName(const std::string& projectName) const;
+
+ std::vector<cmSlnProjectEntry> GetProjects() const;
+
+ cmSlnProjectEntry* AddProject(const std::string& projectGUID,
+ const std::string& projectName,
+ const std::string& projectRelativePath);
+
+private:
+ typedef std::map<std::string, cmSlnProjectEntry> ProjectStorage;
+ ProjectStorage ProjectsByGUID;
+ typedef std::map<std::string, ProjectStorage::iterator> ProjectStringIndex;
+ ProjectStringIndex ProjectNameIndex;
+};
+
+#endif
diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx
new file mode 100644
index 000000000..bae59740a
--- /dev/null
+++ b/Source/cmVisualStudioSlnParser.cxx
@@ -0,0 +1,712 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2013 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmVisualStudioSlnParser.h"
+
+#include "cmSystemTools.h"
+#include "cmVisualStudioSlnData.h"
+
+#include <cassert>
+#include <stack>
+
+//----------------------------------------------------------------------------
+namespace
+{
+ enum LineFormat
+ {
+ LineMultiValueTag,
+ LineSingleValueTag,
+ LineKeyValuePair,
+ LineVerbatim
+ };
+}
+
+//----------------------------------------------------------------------------
+class cmVisualStudioSlnParser::ParsedLine
+{
+public:
+ bool IsComment() const;
+ bool IsKeyValuePair() const;
+
+ const std::string& GetTag() const { return this->Tag; }
+ const std::string& GetArg() const { return this->Arg.first; }
+ std::string GetArgVerbatim() const;
+ size_t GetValueCount() const { return this->Values.size(); }
+ const std::string& GetValue(size_t idxValue) const;
+ std::string GetValueVerbatim(size_t idxValue) const;
+
+ void SetTag(const std::string& tag) { this->Tag = tag; }
+ void SetArg(const std::string& arg) { this->Arg = StringData(arg, false); }
+ void SetQuotedArg(const std::string& arg)
+ { this->Arg = StringData(arg, true); }
+ void AddValue(const std::string& value)
+ { this->Values.push_back(StringData(value, false)); }
+ void AddQuotedValue(const std::string& value)
+ { this->Values.push_back(StringData(value, true)); }
+
+ void CopyVerbatim(const std::string& line) { this->Tag = line; }
+
+private:
+ typedef std::pair<std::string, bool> StringData;
+ std::string Tag;
+ StringData Arg;
+ std::vector<StringData> Values;
+ static const std::string BadString;
+ static const std::string Quote;
+};
+
+//----------------------------------------------------------------------------
+const std::string cmVisualStudioSlnParser::ParsedLine::BadString;
+const std::string cmVisualStudioSlnParser::ParsedLine::Quote("\"");
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::ParsedLine::IsComment() const
+{
+ assert(!this->Tag.empty());
+ return (this->Tag[0]== '#');
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::ParsedLine::IsKeyValuePair() const
+{
+ assert(!this->Tag.empty());
+ return this->Arg.first.empty() && this->Values.size() == 1;
+}
+
+//----------------------------------------------------------------------------
+std::string cmVisualStudioSlnParser::ParsedLine::GetArgVerbatim() const
+{
+ if (this->Arg.second)
+ return Quote + this->Arg.first + Quote;
+ else
+ return this->Arg.first;
+}
+
+//----------------------------------------------------------------------------
+const std::string&
+cmVisualStudioSlnParser::ParsedLine::GetValue(size_t idxValue) const
+{
+ if (idxValue < this->Values.size())
+ return this->Values[idxValue].first;
+ else
+ return BadString;
+}
+
+//----------------------------------------------------------------------------
+std::string
+cmVisualStudioSlnParser::ParsedLine::GetValueVerbatim(size_t idxValue) const
+{
+ if (idxValue < this->Values.size())
+ {
+ const StringData& data = this->Values[idxValue];
+ if (data.second)
+ return Quote + data.first + Quote;
+ else
+ return data.first;
+ }
+ else
+ return BadString;
+}
+
+//----------------------------------------------------------------------------
+class cmVisualStudioSlnParser::State
+{
+public:
+ explicit State(DataGroupSet requestedData);
+
+ size_t GetCurrentLine() const { return this->CurrentLine; }
+ bool ReadLine(std::istream& input, std::string& line);
+
+ LineFormat NextLineFormat() const;
+
+ bool Process(const cmVisualStudioSlnParser::ParsedLine& line,
+ cmSlnData& output,
+ cmVisualStudioSlnParser::ResultData& result);
+
+ bool Finished(cmVisualStudioSlnParser::ResultData& result);
+
+private:
+ enum FileState
+ {
+ FileStateStart,
+ FileStateTopLevel,
+ FileStateProject,
+ FileStateProjectDependencies,
+ FileStateGlobal,
+ FileStateSolutionConfigurations,
+ FileStateProjectConfigurations,
+ FileStateSolutionFilters,
+ FileStateGlobalSection,
+ FileStateIgnore
+ };
+ std::stack<FileState> Stack;
+ std::string EndIgnoreTag;
+ DataGroupSet RequestedData;
+ size_t CurrentLine;
+
+ void IgnoreUntilTag(const std::string& endTag);
+};
+
+//----------------------------------------------------------------------------
+cmVisualStudioSlnParser::State::State(DataGroupSet requestedData) :
+ RequestedData(requestedData),
+ CurrentLine(0)
+{
+ if (this->RequestedData.test(DataGroupProjectDependenciesBit))
+ this->RequestedData.set(DataGroupProjectsBit);
+ this->Stack.push(FileStateStart);
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::State::ReadLine(std::istream& input,
+ std::string& line)
+{
+ ++this->CurrentLine;
+ return !std::getline(input, line).fail();
+}
+
+//----------------------------------------------------------------------------
+LineFormat cmVisualStudioSlnParser::State::NextLineFormat() const
+{
+ switch (this->Stack.top())
+ {
+ case FileStateStart: return LineVerbatim;
+ case FileStateTopLevel: return LineMultiValueTag;
+ case FileStateProject: return LineSingleValueTag;
+ case FileStateProjectDependencies: return LineKeyValuePair;
+ case FileStateGlobal: return LineSingleValueTag;
+ case FileStateSolutionConfigurations: return LineKeyValuePair;
+ case FileStateProjectConfigurations: return LineKeyValuePair;
+ case FileStateSolutionFilters: return LineKeyValuePair;
+ case FileStateGlobalSection: return LineKeyValuePair;
+ case FileStateIgnore: return LineVerbatim;
+ default:
+ assert(false);
+ return LineVerbatim;
+ }
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::State::Process(
+ const cmVisualStudioSlnParser::ParsedLine& line,
+ cmSlnData& output, cmVisualStudioSlnParser::ResultData& result)
+{
+ assert(!line.IsComment());
+ switch (this->Stack.top())
+ {
+ case FileStateStart:
+ if (!cmSystemTools::StringStartsWith(
+ line.GetTag().c_str(), "Microsoft Visual Studio Solution File"))
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ this->Stack.pop();
+ this->Stack.push(FileStateTopLevel);
+ break;
+ case FileStateTopLevel:
+ if (line.GetTag().compare("Project") == 0)
+ {
+ if (line.GetValueCount() != 3)
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ if (this->RequestedData.test(DataGroupProjectsBit))
+ {
+ if (!output.AddProject(line.GetValue(2),
+ line.GetValue(0),
+ line.GetValue(1)))
+ {
+ result.SetError(ResultErrorInputData, this->GetCurrentLine());
+ return false;
+ }
+ this->Stack.push(FileStateProject);
+ }
+ else
+ this->IgnoreUntilTag("EndProject");
+ }
+ else if (line.GetTag().compare("Global") == 0)
+ this->Stack.push(FileStateGlobal);
+ else
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ break;
+ case FileStateProject:
+ if (line.GetTag().compare("EndProject") == 0)
+ this->Stack.pop();
+ else if (line.GetTag().compare("ProjectSection") == 0)
+ {
+ if (line.GetArg().compare("ProjectDependencies") == 0 &&
+ line.GetValue(0).compare("postProject") == 0)
+ {
+ if (this->RequestedData.test(DataGroupProjectDependenciesBit))
+ this->Stack.push(FileStateProjectDependencies);
+ else
+ this->IgnoreUntilTag("EndProjectSection");
+ }
+ else
+ this->IgnoreUntilTag("EndProjectSection");
+ }
+ else
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ break;
+ case FileStateProjectDependencies:
+ if (line.GetTag().compare("EndProjectSection") == 0)
+ this->Stack.pop();
+ else if (line.IsKeyValuePair())
+ // implement dependency storing here, once needed
+ ;
+ else
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ break;
+ case FileStateGlobal:
+ if (line.GetTag().compare("EndGlobal") == 0)
+ this->Stack.pop();
+ else if (line.GetTag().compare("GlobalSection") == 0)
+ {
+ if (line.GetArg().compare("SolutionConfigurationPlatforms") == 0 &&
+ line.GetValue(0).compare("preSolution") == 0)
+ {
+ if (this->RequestedData.test(DataGroupSolutionConfigurationsBit))
+ this->Stack.push(FileStateSolutionConfigurations);
+ else
+ this->IgnoreUntilTag("EndGlobalSection");
+ }
+ else if (line.GetArg().compare("ProjectConfigurationPlatforms") == 0 &&
+ line.GetValue(0).compare("postSolution") == 0)
+ {
+ if (this->RequestedData.test(DataGroupProjectConfigurationsBit))
+ this->Stack.push(FileStateProjectConfigurations);
+ else
+ this->IgnoreUntilTag("EndGlobalSection");
+ }
+ else if (line.GetArg().compare("NestedProjects") == 0 &&
+ line.GetValue(0).compare("preSolution") == 0)
+ {
+ if (this->RequestedData.test(DataGroupSolutionFiltersBit))
+ this->Stack.push(FileStateSolutionFilters);
+ else
+ this->IgnoreUntilTag("EndGlobalSection");
+ }
+ else if (this->RequestedData.test(DataGroupGenericGlobalSectionsBit))
+ this->Stack.push(FileStateGlobalSection);
+ else
+ this->IgnoreUntilTag("EndGlobalSection");
+ }
+ else
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ break;
+ case FileStateSolutionConfigurations:
+ if (line.GetTag().compare("EndGlobalSection") == 0)
+ this->Stack.pop();
+ else if (line.IsKeyValuePair())
+ // implement configuration storing here, once needed
+ ;
+ else
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ break;
+ case FileStateProjectConfigurations:
+ if (line.GetTag().compare("EndGlobalSection") == 0)
+ this->Stack.pop();
+ else if (line.IsKeyValuePair())
+ // implement configuration storing here, once needed
+ ;
+ else
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ break;
+ case FileStateSolutionFilters:
+ if (line.GetTag().compare("EndGlobalSection") == 0)
+ this->Stack.pop();
+ else if (line.IsKeyValuePair())
+ // implement filter storing here, once needed
+ ;
+ else
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ break;
+ case FileStateGlobalSection:
+ if (line.GetTag().compare("EndGlobalSection") == 0)
+ this->Stack.pop();
+ else if (line.IsKeyValuePair())
+ // implement section storing here, once needed
+ ;
+ else
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ break;
+ case FileStateIgnore:
+ if (line.GetTag() == this->EndIgnoreTag)
+ {
+ this->Stack.pop();
+ this->EndIgnoreTag = "";
+ }
+ break;
+ default:
+ result.SetError(ResultErrorBadInternalState, this->GetCurrentLine());
+ return false;
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::State::Finished(
+ cmVisualStudioSlnParser::ResultData& result)
+{
+ if (this->Stack.top() != FileStateTopLevel)
+ {
+ result.SetError(ResultErrorInputStructure, this->GetCurrentLine());
+ return false;
+ }
+ result.Result = ResultOK;
+ return true;
+}
+
+//----------------------------------------------------------------------------
+void cmVisualStudioSlnParser::State::IgnoreUntilTag(const std::string& endTag)
+{
+ this->Stack.push(FileStateIgnore);
+ this->EndIgnoreTag = endTag;
+}
+
+//----------------------------------------------------------------------------
+cmVisualStudioSlnParser::ResultData::ResultData()
+ : Result(ResultOK)
+ , ResultLine(0)
+{}
+
+//----------------------------------------------------------------------------
+void cmVisualStudioSlnParser::ResultData::Clear()
+{
+ *this = ResultData();
+}
+
+//----------------------------------------------------------------------------
+void cmVisualStudioSlnParser::ResultData::SetError(ParseResult error,
+ size_t line)
+{
+ this->Result = error;
+ this->ResultLine = line;
+}
+
+//----------------------------------------------------------------------------
+const cmVisualStudioSlnParser::DataGroupSet
+cmVisualStudioSlnParser::DataGroupProjects(
+ 1 << cmVisualStudioSlnParser::DataGroupProjectsBit);
+
+const cmVisualStudioSlnParser::DataGroupSet
+cmVisualStudioSlnParser::DataGroupProjectDependencies(
+ 1 << cmVisualStudioSlnParser::DataGroupProjectDependenciesBit);
+
+const cmVisualStudioSlnParser::DataGroupSet
+cmVisualStudioSlnParser::DataGroupSolutionConfigurations(
+ 1 << cmVisualStudioSlnParser::DataGroupSolutionConfigurationsBit);
+
+const cmVisualStudioSlnParser::DataGroupSet
+cmVisualStudioSlnParser::DataGroupProjectConfigurations(
+ 1 << cmVisualStudioSlnParser::DataGroupProjectConfigurationsBit);
+
+const cmVisualStudioSlnParser::DataGroupSet
+cmVisualStudioSlnParser::DataGroupSolutionFilters(
+ 1 << cmVisualStudioSlnParser::DataGroupSolutionFiltersBit);
+
+const cmVisualStudioSlnParser::DataGroupSet
+cmVisualStudioSlnParser::DataGroupGenericGlobalSections(
+ 1 << cmVisualStudioSlnParser::DataGroupGenericGlobalSectionsBit);
+
+const cmVisualStudioSlnParser::DataGroupSet
+cmVisualStudioSlnParser::DataGroupAll(~0);
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::Parse(std::istream& input,
+ cmSlnData& output,
+ DataGroupSet dataGroups)
+{
+ this->LastResult.Clear();
+ if (!this->IsDataGroupSetSupported(dataGroups))
+ {
+ this->LastResult.SetError(ResultErrorUnsupportedDataGroup, 0);
+ return false;
+ }
+ State state(dataGroups);
+ return this->ParseImpl(input, output, state);
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::ParseFile(const std::string& file,
+ cmSlnData& output,
+ DataGroupSet dataGroups)
+{
+ this->LastResult.Clear();
+ if (!this->IsDataGroupSetSupported(dataGroups))
+ {
+ this->LastResult.SetError(ResultErrorUnsupportedDataGroup, 0);
+ return false;
+ }
+ std::ifstream f(file.c_str());
+ if (!f)
+ {
+ this->LastResult.SetError(ResultErrorOpeningInput, 0);
+ return false;
+ }
+ State state(dataGroups);
+ return this->ParseImpl(f, output, state);
+}
+
+//----------------------------------------------------------------------------
+cmVisualStudioSlnParser::ParseResult
+cmVisualStudioSlnParser::GetParseResult() const
+{
+ return this->LastResult.Result;
+}
+
+//----------------------------------------------------------------------------
+size_t cmVisualStudioSlnParser::GetParseResultLine() const
+{
+ return this->LastResult.ResultLine;
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::GetParseHadBOM() const
+{
+ return this->LastResult.HadBOM;
+}
+
+//----------------------------------------------------------------------------
+bool
+cmVisualStudioSlnParser::IsDataGroupSetSupported(DataGroupSet dataGroups) const
+{
+ return (dataGroups & DataGroupProjects) == dataGroups;
+ //only supporting DataGroupProjects for now
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::ParseImpl(std::istream& input,
+ cmSlnData& output,
+ State& state)
+{
+ std::string line;
+ // Does the .sln start with a Byte Order Mark?
+ if (!this->ParseBOM(input, line, state))
+ return false;
+ do
+ {
+ line = cmSystemTools::TrimWhitespace(line);
+ if (line.empty())
+ continue;
+ ParsedLine parsedLine;
+ switch (state.NextLineFormat())
+ {
+ case LineMultiValueTag:
+ if (!this->ParseMultiValueTag(line, parsedLine, state))
+ return false;
+ break;
+ case LineSingleValueTag:
+ if (!this->ParseSingleValueTag(line, parsedLine, state))
+ return false;
+ break;
+ case LineKeyValuePair:
+ if (!this->ParseKeyValuePair(line, parsedLine, state))
+ return false;
+ break;
+ case LineVerbatim:
+ parsedLine.CopyVerbatim(line);
+ break;
+ }
+ if (parsedLine.IsComment())
+ continue;
+ if (!state.Process(parsedLine, output, this->LastResult))
+ return false;
+ }
+ while (state.ReadLine(input, line));
+ return state.Finished(this->LastResult);
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::ParseBOM(std::istream& input,
+ std::string& line,
+ State& state)
+{
+ char bom[4];
+ if (!input.get(bom, 4))
+ {
+ this->LastResult.SetError(ResultErrorReadingInput, 1);
+ return false;
+ }
+ this->LastResult.HadBOM =
+ (bom[0] == char(0xEF) && bom[1] == char(0xBB) && bom[2] == char(0xBF));
+ if (!state.ReadLine(input, line))
+ {
+ this->LastResult.SetError(ResultErrorReadingInput, 1);
+ return false;
+ }
+ if (!this->LastResult.HadBOM)
+ line = bom + line; // it wasn't a BOM, prepend it to first line
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::ParseMultiValueTag(const std::string& line,
+ ParsedLine& parsedLine,
+ State& state)
+{
+ size_t idxEqualSign = line.find('=');
+ const std::string& fullTag = line.substr(0, idxEqualSign);
+ if (!this->ParseTag(fullTag, parsedLine, state))
+ return false;
+ if (idxEqualSign != line.npos)
+ {
+ size_t idxFieldStart = idxEqualSign + 1;
+ if (idxFieldStart < line.size())
+ {
+ size_t idxParsing = idxFieldStart;
+ bool inQuotes = false;
+ for (;;)
+ {
+ idxParsing = line.find_first_of(",\"", idxParsing);
+ bool fieldOver = false;
+ if (idxParsing == line.npos)
+ {
+ fieldOver = true;
+ if (inQuotes)
+ {
+ this->LastResult.SetError(ResultErrorInputStructure,
+ state.GetCurrentLine());
+ return false;
+ }
+ }
+ else if (line[idxParsing] == ',' && !inQuotes)
+ fieldOver = true;
+ else if (line[idxParsing] == '"')
+ inQuotes = !inQuotes;
+ if (fieldOver)
+ {
+ if (!this->ParseValue(line.substr(idxFieldStart,
+ idxParsing - idxFieldStart),
+ parsedLine))
+ return false;
+ if (idxParsing == line.npos)
+ break; //end of last field
+ idxFieldStart = idxParsing + 1;
+ }
+ ++idxParsing;
+ }
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::ParseSingleValueTag(const std::string& line,
+ ParsedLine& parsedLine,
+ State& state)
+{
+ size_t idxEqualSign = line.find('=');
+ const std::string& fullTag = line.substr(0, idxEqualSign);
+ if (!this->ParseTag(fullTag, parsedLine, state))
+ return false;
+ if (idxEqualSign != line.npos)
+ {
+ if (!this->ParseValue(line.substr(idxEqualSign + 1), parsedLine))
+ return false;
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::ParseKeyValuePair(const std::string& line,
+ ParsedLine& parsedLine,
+ State& /*state*/)
+{
+ size_t idxEqualSign = line.find('=');
+ if (idxEqualSign == line.npos)
+ {
+ parsedLine.CopyVerbatim(line);
+ return true;
+ }
+ const std::string& key = line.substr(0, idxEqualSign);
+ parsedLine.SetTag(cmSystemTools::TrimWhitespace(key));
+ const std::string& value = line.substr(idxEqualSign + 1);
+ parsedLine.AddValue(cmSystemTools::TrimWhitespace(value));
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::ParseTag(const std::string& fullTag,
+ ParsedLine& parsedLine,
+ State& state)
+{
+ size_t idxLeftParen = fullTag.find('(');
+ if (idxLeftParen == fullTag.npos)
+ {
+ parsedLine.SetTag(cmSystemTools::TrimWhitespace(fullTag));
+ return true;
+ }
+ parsedLine.SetTag(
+ cmSystemTools::TrimWhitespace(fullTag.substr(0, idxLeftParen)));
+ size_t idxRightParen = fullTag.rfind(')');
+ if (idxRightParen == fullTag.npos)
+ {
+ this->LastResult.SetError(ResultErrorInputStructure,
+ state.GetCurrentLine());
+ return false;
+ }
+ const std::string& arg = cmSystemTools::TrimWhitespace(
+ fullTag.substr(idxLeftParen + 1, idxRightParen - idxLeftParen - 1));
+ if (arg[0] == '"')
+ {
+ if (arg[arg.size() - 1] != '"')
+ {
+ this->LastResult.SetError(ResultErrorInputStructure,
+ state.GetCurrentLine());
+ return false;
+ }
+ parsedLine.SetQuotedArg(arg.substr(1, arg.size() - 2));
+ }
+ else
+ parsedLine.SetArg(arg);
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmVisualStudioSlnParser::ParseValue(const std::string& value,
+ ParsedLine& parsedLine)
+{
+ const std::string& trimmed = cmSystemTools::TrimWhitespace(value);
+ if (trimmed.empty())
+ parsedLine.AddValue(trimmed);
+ else if (trimmed[0] == '"' && trimmed[trimmed.size() - 1] == '"')
+ parsedLine.AddQuotedValue(trimmed.substr(1, trimmed.size() - 2));
+ else
+ parsedLine.AddValue(trimmed);
+ return true;
+}
diff --git a/Source/cmVisualStudioSlnParser.h b/Source/cmVisualStudioSlnParser.h
new file mode 100644
index 000000000..bee70cc13
--- /dev/null
+++ b/Source/cmVisualStudioSlnParser.h
@@ -0,0 +1,118 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2013 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmVisualStudioSlnParser_h
+#define cmVisualStudioSlnParser_h
+
+#include "cmStandardIncludes.h"
+
+#include <bitset>
+
+
+class cmSlnData;
+
+
+class cmVisualStudioSlnParser
+{
+public:
+ enum ParseResult
+ {
+ ResultOK = 0,
+
+ ResultInternalError = -1,
+ ResultExternalError = 1,
+
+ ResultErrorOpeningInput = ResultExternalError,
+ ResultErrorReadingInput,
+ ResultErrorInputStructure,
+ ResultErrorInputData,
+
+ ResultErrorBadInternalState = ResultInternalError,
+ ResultErrorUnsupportedDataGroup = ResultInternalError - 1
+ };
+
+ enum DataGroup
+ {
+ DataGroupProjectsBit,
+ DataGroupProjectDependenciesBit,
+ DataGroupSolutionConfigurationsBit,
+ DataGroupProjectConfigurationsBit,
+ DataGroupSolutionFiltersBit,
+ DataGroupGenericGlobalSectionsBit,
+ DataGroupCount
+ };
+
+ typedef std::bitset<DataGroupCount> DataGroupSet;
+
+ static const DataGroupSet DataGroupProjects;
+ static const DataGroupSet DataGroupProjectDependencies;
+ static const DataGroupSet DataGroupSolutionConfigurations;
+ static const DataGroupSet DataGroupProjectConfigurations;
+ static const DataGroupSet DataGroupSolutionFilters;
+ static const DataGroupSet DataGroupGenericGlobalSections;
+ static const DataGroupSet DataGroupAll;
+
+ bool Parse(std::istream& input,
+ cmSlnData& output,
+ DataGroupSet dataGroups = DataGroupAll);
+
+ bool ParseFile(const std::string& file,
+ cmSlnData& output,
+ DataGroupSet dataGroups = DataGroupAll);
+
+ ParseResult GetParseResult() const;
+
+ size_t GetParseResultLine() const;
+
+ bool GetParseHadBOM() const;
+
+protected:
+ class State;
+ friend class State;
+ class ParsedLine;
+
+ struct ResultData
+ {
+ ParseResult Result;
+ size_t ResultLine;
+ bool HadBOM;
+
+ ResultData();
+ void Clear();
+ void SetError(ParseResult error, size_t line);
+ } LastResult;
+
+ bool IsDataGroupSetSupported(DataGroupSet dataGroups) const;
+
+ bool ParseImpl(std::istream& input, cmSlnData& output, State& state);
+
+ bool ParseBOM(std::istream& input, std::string& line, State& state);
+
+ bool ParseMultiValueTag(const std::string& line,
+ ParsedLine& parsedLine,
+ State& state);
+
+ bool ParseSingleValueTag(const std::string& line,
+ ParsedLine& parsedLine,
+ State& state);
+
+ bool ParseKeyValuePair(const std::string& line,
+ ParsedLine& parsedLine,
+ State& state);
+
+ bool ParseTag(const std::string& fullTag,
+ ParsedLine& parsedLine,
+ State& state);
+
+ bool ParseValue(const std::string& value, ParsedLine& parsedLine);
+};
+
+#endif
diff --git a/Source/cmVisualStudioWCEPlatformParser.cxx b/Source/cmVisualStudioWCEPlatformParser.cxx
index b302246ea..219a5eb49 100644
--- a/Source/cmVisualStudioWCEPlatformParser.cxx
+++ b/Source/cmVisualStudioWCEPlatformParser.cxx
@@ -20,8 +20,12 @@ int cmVisualStudioWCEPlatformParser::ParseVersion(const char* version)
const std::string vckey = registryBase + "\\Setup\\VC;ProductDir";
const std::string vskey = registryBase + "\\Setup\\VS;ProductDir";
- if(!cmSystemTools::ReadRegistryValue(vckey.c_str(), this->VcInstallDir) ||
- !cmSystemTools::ReadRegistryValue(vskey.c_str(), this->VsInstallDir))
+ if(!cmSystemTools::ReadRegistryValue(vckey.c_str(),
+ this->VcInstallDir,
+ cmSystemTools::KeyWOW64_32) ||
+ !cmSystemTools::ReadRegistryValue(vskey.c_str(),
+ this->VsInstallDir,
+ cmSystemTools::KeyWOW64_32))
{
return 0;
}
diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx
index 400034582..7d2eeadd6 100644
--- a/Source/cmWhileCommand.cxx
+++ b/Source/cmWhileCommand.cxx
@@ -49,9 +49,9 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf,
unsigned int i;
for(i =0; i < this->Args.size(); ++i)
{
- err += (this->Args[i].Quoted?"\"":"");
+ err += (this->Args[i].Delim?"\"":"");
err += this->Args[i].Value;
- err += (this->Args[i].Quoted?"\"":"");
+ err += (this->Args[i].Delim?"\"":"");
err += " ";
}
err += "(";
diff --git a/Source/cmWin32ProcessExecution.cxx b/Source/cmWin32ProcessExecution.cxx
index 5752ab61c..1bdeffbed 100644
--- a/Source/cmWin32ProcessExecution.cxx
+++ b/Source/cmWin32ProcessExecution.cxx
@@ -506,7 +506,7 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
/* Create new output read handle and the input write handle. Set
* the inheritance properties to FALSE. Otherwise, the child inherits
- * the these handles; resulting in non-closeable handles to the pipes
+ * these handles; resulting in non-closeable handles to the pipes
* being created. */
fSuccess = DuplicateHandle(GetCurrentProcess(), this->hChildStdinWr,
GetCurrentProcess(), &this->hChildStdinWrDup, 0,
diff --git a/Source/cmWin32ProcessExecution.h b/Source/cmWin32ProcessExecution.h
index 98b6bda98..2127ebd2e 100644
--- a/Source/cmWin32ProcessExecution.h
+++ b/Source/cmWin32ProcessExecution.h
@@ -69,7 +69,7 @@ public:
/**
* Start the process in the directory path. Make sure that the
* executable is either in the path or specify the full path. The
- * argument verbose specifies wether or not to display output while
+ * argument verbose specifies whether or not to display output while
* it is being generated.
*/
bool StartProcess(const char*, const char* path, bool verbose);
diff --git a/Source/cm_sha2.c b/Source/cm_sha2.c
index 12c39ed63..24de2b294 100644
--- a/Source/cm_sha2.c
+++ b/Source/cm_sha2.c
@@ -740,7 +740,8 @@ void SHA1_Final(sha_byte digest[], SHA_CTX* context) {
/* Convert FROM host byte order */
REVERSE64(context->s1.bitcount,context->s1.bitcount);
#endif
- *(sha_word64*)&context->s1.buffer[56] = context->s1.bitcount;
+ MEMCPY_BCOPY(&context->s1.buffer[56], &context->s1.bitcount,
+ sizeof(sha_word64));
/* Final transform: */
SHA1_Internal_Transform(context, (sha_word32*)context->s1.buffer);
@@ -1067,7 +1068,8 @@ void SHA256_Internal_Last(SHA_CTX* context) {
*context->s256.buffer = 0x80;
}
/* Set the bit count: */
- *(sha_word64*)&context->s256.buffer[56] = context->s256.bitcount;
+ MEMCPY_BCOPY(&context->s256.buffer[56], &context->s256.bitcount,
+ sizeof(sha_word64));
/* Final transform: */
SHA256_Internal_Transform(context, (sha_word32*)context->s256.buffer);
@@ -1475,8 +1477,10 @@ void SHA512_Internal_Last(SHA_CTX* context) {
*context->s512.buffer = 0x80;
}
/* Store the length of input data (in bits): */
- *(sha_word64*)&context->s512.buffer[112] = context->s512.bitcount[1];
- *(sha_word64*)&context->s512.buffer[120] = context->s512.bitcount[0];
+ MEMCPY_BCOPY(&context->s512.buffer[112], &context->s512.bitcount[1],
+ sizeof(sha_word64));
+ MEMCPY_BCOPY(&context->s512.buffer[120], &context->s512.bitcount[0],
+ sizeof(sha_word64));
/* Final transform: */
SHA512_Internal_Transform(context, (sha_word64*)context->s512.buffer);
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 376758e48..14ddc1b01 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -129,7 +129,7 @@ void cmNeedBackwardsCompatibility(const std::string& variable,
"by CMake in versions prior to 1.6. To fix this you might need to set "
"the cache value of CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less. If "
"you are writing a CMakeLists file, (or have already set "
- "CMAKE_BACKWARDS_COMPATABILITY to 1.4 or less) then you probably need "
+ "CMAKE_BACKWARDS_COMPATIBILITY to 1.4 or less) then you probably need "
"to include a CMake module to test for the feature this variable "
"defines.";
cmSystemTools::Error(message.c_str());
@@ -384,11 +384,22 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
cmCacheManager::CacheEntryType type = cmCacheManager::UNINITIALIZED;
if(cmCacheManager::ParseEntry(entry.c_str(), var, value, type))
{
+ // The value is transformed if it is a filepath for example, so
+ // we can't compare whether the value is already in the cache until
+ // after we call AddCacheEntry.
+ const char *cachedValue =
+ this->CacheManager->GetCacheValue(var.c_str());
+
this->CacheManager->AddCacheEntry(var.c_str(), value.c_str(),
"No help, variable specified on the command line.", type);
if(this->WarnUnusedCli)
{
- this->WatchUnusedCli(var.c_str());
+ if (!cachedValue
+ || strcmp(this->CacheManager->GetCacheValue(var.c_str()),
+ cachedValue) != 0)
+ {
+ this->WatchUnusedCli(var.c_str());
+ }
}
}
else
@@ -539,7 +550,7 @@ void cmake::ReadListFile(const std::vector<std::string>& args,
}
if (!lg->GetMakefile()->ReadListFile(0, path))
{
- cmSystemTools::Error("Error processing file:", path);
+ cmSystemTools::Error("Error processing file: ", path);
}
}
@@ -601,7 +612,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
std::vector<std::string> includeDirs;
cmSystemTools::ExpandListArgument(includes, includeDirs);
- std::string includeFlags = lg->GetIncludeFlags(includeDirs,
+ std::string includeFlags = lg->GetIncludeFlags(includeDirs, 0,
language.c_str(), false);
std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS");
@@ -1158,9 +1169,8 @@ void CMakeCommandUsage(const char* program)
<< " remove_directory dir - remove a directory and its contents\n"
<< " rename oldname newname - rename a file or directory "
"(on one volume)\n"
- << " tar [cxt][vfz][cvfj] file.tar "
- "file/dir1 file/dir2 ... - create a tar "
- "archive\n"
+ << " tar [cxt][vfz][cvfj] file.tar [file/dir1 file/dir2 ...]\n"
+ << " - create or extract a tar or zip archive\n"
<< " time command [args] ... - run command and return elapsed time\n"
<< " touch file - touch a file.\n"
<< " touch_nocreate file - touch a file but do not create it.\n"
@@ -1724,10 +1734,11 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
{
return cmake::ExecuteEchoColor(args);
}
- else if (args[1] == "cmake_automoc")
+ else if (args[1] == "cmake_automoc" && args.size() >= 4)
{
cmQtAutomoc automoc;
- bool automocSuccess = automoc.Run(args[2].c_str());
+ const char *config = args[3].empty() ? 0 : args[3].c_str();
+ bool automocSuccess = automoc.Run(args[2].c_str(), config);
return automocSuccess ? 0 : 1;
}
#endif
@@ -2367,7 +2378,7 @@ int cmake::ActualConfigure()
// EXECUTABLE_OUTPUT_PATH. They are now documented as old-style and
// should no longer be used. Therefore we present them only if the
// project requires compatibility with CMake 2.4. We detect this
- // here by looking for the old CMAKE_BACKWARDS_COMPATABILITY
+ // here by looking for the old CMAKE_BACKWARDS_COMPATIBILITY
// variable created when CMP0001 is not set to NEW.
if(this->GetCacheManager()->GetCacheValue("CMAKE_BACKWARDS_COMPATIBILITY"))
{
@@ -2633,7 +2644,8 @@ const char* cmake::GetCacheDefinition(const char* name) const
void cmake::AddDefaultCommands()
{
std::list<cmCommand*> commands;
- GetBootstrapCommands(commands);
+ GetBootstrapCommands1(commands);
+ GetBootstrapCommands2(commands);
GetPredefinedCommands(commands);
for(std::list<cmCommand*>::iterator i = commands.begin();
i != commands.end(); ++i)
@@ -3595,6 +3607,14 @@ void cmake::DefineProperties(cmake *cm)
"for the FOLDER target property.");
cm->DefineProperty
+ ("AUTOMOC_TARGETS_FOLDER", cmProperty::GLOBAL,
+ "Name of FOLDER for *_automoc targets that are added automatically by "
+ "CMake for targets for which AUTOMOC is enabled.",
+ "If not set, CMake uses the FOLDER property of the parent target as a "
+ "default value for this property. See also the documentation for the "
+ "FOLDER target property and the AUTOMOC target property.");
+
+ cm->DefineProperty
("PREDEFINED_TARGETS_FOLDER", cmProperty::GLOBAL,
"Name of FOLDER for targets that are added automatically by CMake.",
"If not set, CMake uses \"CMakePredefinedTargets\" as a default "
@@ -3647,11 +3667,11 @@ void cmake::RecordPropertyAccess(const char *name,
void cmake::ReportUndefinedPropertyAccesses(const char *filename)
{
+ if(!this->GlobalGenerator)
+ { return; }
FILE *progFile = fopen(filename,"w");
- if (!progFile || !this->GlobalGenerator)
- {
- return;
- }
+ if(!progFile)
+ { return; }
// what are the enabled languages?
std::vector<std::string> enLangs;
@@ -4049,7 +4069,7 @@ static bool cmakeCheckStampFile(const char* stampName)
// TODO: Teach cmGeneratedFileStream to use a random temp file (with
// multiple tries in unlikely case of conflict) and use that here.
std::ofstream stamp(stampTemp);
- stamp << "# CMake generation timestamp file this directory.\n";
+ stamp << "# CMake generation timestamp file for this directory.\n";
}
if(cmSystemTools::RenameFile(stampTemp, stampName))
{
@@ -4121,7 +4141,7 @@ int cmake::WindowsCEEnvironment(const char* version, const std::string& name)
return -1;
}
-// For visual studio 2005 and newer manifest files need to be embeded into
+// For visual studio 2005 and newer manifest files need to be embedded into
// exe and dll's. This code does that in such a way that incremental linking
// still works.
int cmake::VisualStudioLink(std::vector<std::string>& args, int type)
@@ -4177,7 +4197,7 @@ int cmake::VisualStudioLink(std::vector<std::string>& args, int type)
{
if(verbose)
{
- std::cout << "Visual Studio Incremental Link with embeded manifests\n";
+ std::cout << "Visual Studio Incremental Link with embedded manifests\n";
}
return cmake::VisualStudioLinkIncremental(expandedArgs, type, verbose);
}
diff --git a/Source/cmake.h b/Source/cmake.h
index 63065a17c..a50c1ed02 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -35,7 +35,7 @@ class cmGeneratedFileStream;
/** \brief Represents a cmake invocation.
*
* This class represents a cmake invocation. It is the top level class when
- * running cmake. Most cmake based GUIS should primarily create an instance
+ * running cmake. Most cmake based GUIs should primarily create an instance
* of this class and communicate with it.
*
* The basic process for a GUI is as follows:
@@ -255,7 +255,7 @@ class cmake
typedef void (*ProgressCallbackType)
(const char*msg, float progress, void *);
/**
- * Set the function used by GUI's to receive progress updates
+ * Set the function used by GUIs to receive progress updates
* Function gets passed: message as a const char*, a progress
* amount ranging from 0 to 1.0 and client data. The progress
* number provided may be negative in cases where a message is
@@ -532,9 +532,9 @@ private:
"CMakeCache.txt file, globbing expressions using * and ? are supported. "\
"The option may be repeated for as many cache entries as desired.\n" \
"Use with care, you can make your CMakeCache.txt non-working."}, \
- {"-G <generator-name>", "Specify a makefile generator.", \
+ {"-G <generator-name>", "Specify a build system generator.", \
"CMake may support multiple native build systems on certain platforms. " \
- "A makefile generator is responsible for generating a particular build " \
+ "A generator is responsible for generating a particular build " \
"system. Possible generator names are specified in the Generators " \
"section."},\
{"-T <toolset-name>", "Specify toolset name if supported by generator.", \
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 42678419e..68d833964 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -62,7 +62,10 @@ static const char * cmDocumentationDescription[][3] =
" --config <cfg> = For multi-configuration tools, choose <cfg>.\n" \
" --clean-first = Build target 'clean' first, then build.\n" \
" (To clean only, use --target 'clean'.)\n" \
- " --use-stderr = Don't merge stdout/stderr.\n" \
+ " --use-stderr = Don't merge stdout/stderr output and pass the\n" \
+ " original stdout/stderr handles to the native\n" \
+ " tool so it can use the capabilities of the\n" \
+ " calling terminal (e.g. colored output).\n" \
" -- = Pass remaining options to the native tool.\n"
//----------------------------------------------------------------------------
@@ -86,8 +89,8 @@ static const char * cmDocumentationOptions[][3] =
{"-L[A][H]", "List non-advanced cached variables.",
"List cache variables will run CMake and list all the variables from the "
"CMake cache that are not marked as INTERNAL or ADVANCED. This will "
- "effectively display current CMake settings, which can be then changed "
- "with -D option. Changing some of the variable may result in more "
+ "effectively display current CMake settings, which can then be changed "
+ "with -D option. Changing some of the variables may result in more "
"variables being created. If A is specified, then it will display also "
"advanced variables. If H is specified, it will also display help for "
"each variable."},
@@ -108,9 +111,11 @@ static const char * cmDocumentationOptions[][3] =
"to stdout. This can be used to use cmake instead of pkg-config to find "
"installed libraries in plain Makefile-based projects or in "
"autoconf-based projects (via share/aclocal/cmake.m4)."},
- {"--graphviz=[file]", "Generate graphviz of dependencies.",
+ {"--graphviz=[file]", "Generate graphviz of dependencies, see "
+ "CMakeGraphVizOptions.cmake for more.",
"Generate a graphviz input file that will contain all the library and "
- "executable dependencies in the project."},
+ "executable dependencies in the project. See the documentation for "
+ "CMakeGraphVizOptions.cmake for more details. "},
{"--system-information [file]", "Dump information about this system.",
"Dump a wide range of information about the current system. If run "
"from the top of a binary tree for a CMake project it will dump "
@@ -152,7 +157,7 @@ static const char * cmDocumentationOptions[][3] =
"format is determined depending on the filename suffix. Supported are man "
"page, HTML, DocBook and plain text."},
{"--help-commands [file]", "Print help for all commands and exit.",
- "Full documentation specific for all current command is displayed."
+ "Full documentation specific for all current commands is displayed."
"If a file is specified, the documentation is written into and the output "
"format is determined depending on the filename suffix. Supported are man "
"page, HTML, DocBook and plain text."},
@@ -604,7 +609,7 @@ static int do_build(int ac, char** av)
}
else if(strcmp(av[i], "--use-stderr") == 0)
{
- outputflag = cmSystemTools::OUTPUT_NORMAL;
+ outputflag = cmSystemTools::OUTPUT_PASSTHROUGH;
}
else if(strcmp(av[i], "--") == 0)
{
diff --git a/Source/cmakewizard.cxx b/Source/cmakewizard.cxx
index 749f669d0..bac403a89 100644
--- a/Source/cmakewizard.cxx
+++ b/Source/cmakewizard.cxx
@@ -28,7 +28,7 @@ void cmakewizard::AskUser(const char* key,
printf("Current Value: %s\n", iter.GetValue());
printf("New Value (Enter to keep current value): ");
char buffer[4096];
- if(!fgets(buffer, sizeof(buffer)-1, stdin))
+ if(!fgets(buffer, static_cast<int>(sizeof(buffer) - 1), stdin))
{
buffer[0] = 0;
}
@@ -67,16 +67,13 @@ bool cmakewizard::AskAdvanced()
{
printf("Would you like to see advanced options? [No]:");
char buffer[4096];
- if(!fgets(buffer, sizeof(buffer)-1, stdin))
+ if(!fgets(buffer, static_cast<int>(sizeof(buffer) - 1), stdin))
{
buffer[0] = 0;
}
- if(buffer[0])
+ else if(buffer[0] == 'y' || buffer[0] == 'Y')
{
- if(buffer[0] == 'y' || buffer[0] == 'Y')
- {
- return true;
- }
+ return true;
}
return false;
}
diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx
index 04dab59d0..85715574f 100644
--- a/Source/cmcldeps.cxx
+++ b/Source/cmcldeps.cxx
@@ -62,8 +62,8 @@ static std::string trimLeadingSpace(const std::string& cmdline) {
return cmdline.substr(i);
}
-static void doEscape(std::string& str, const std::string& search,
- const std::string& repl) {
+static void replaceAll(std::string& str, const std::string& search,
+ const std::string& repl) {
std::string::size_type pos = 0;
while ((pos = str.find(search, pos)) != std::string::npos) {
str.replace(pos, search.size(), repl);
@@ -71,6 +71,10 @@ static void doEscape(std::string& str, const std::string& search,
}
}
+bool startsWith(const std::string& str, const std::string& what) {
+ return str.compare(0, what.size(), what) == 0;
+}
+
// Strips one argument from the cmdline and returns it. "surrounding quotes"
// are removed from the argument if there were any.
static std::string getArg(std::string& cmdline) {
@@ -117,6 +121,13 @@ static void parseCommandLine(LPTSTR wincmdline,
rest = trimLeadingSpace(cmdline);
}
+// Not all backslashes need to be escaped in a depfile, but it's easier that
+// way. See the re2c grammar in ninja's source code for more info.
+static void escapePath(std::string &path) {
+ replaceAll(path, "\\", "\\\\");
+ replaceAll(path, " ", "\\ ");
+}
+
static void outputDepFile(const std::string& dfile, const std::string& objfile,
std::vector<std::string>& incs) {
@@ -132,16 +143,24 @@ static void outputDepFile(const std::string& dfile, const std::string& objfile,
// FIXME should this be fatal or not? delete obj? delete d?
if (!out)
return;
+ std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
+ replaceAll(cwd, "/", "\\");
+ cwd += "\\";
std::string tmp = objfile;
- doEscape(tmp, " ", "\\ ");
+ escapePath(tmp);
fprintf(out, "%s: \\\n", tmp.c_str());
std::vector<std::string>::iterator it = incs.begin();
for (; it != incs.end(); ++it) {
tmp = *it;
- doEscape(tmp, "\\", "/");
- doEscape(tmp, " ", "\\ ");
+ // The paths need to match the ones used to identify build artifacts in the
+ // build.ninja file. Therefore we need to canonicalize the path to use
+ // backward slashes and relativize the path to the build directory.
+ replaceAll(tmp, "/", "\\");
+ if (startsWith(tmp, cwd))
+ tmp = tmp.substr(cwd.size());
+ escapePath(tmp);
fprintf(out, "%s \\\n", tmp.c_str());
}
@@ -150,10 +169,6 @@ static void outputDepFile(const std::string& dfile, const std::string& objfile,
}
-bool startsWith(const std::string& str, const std::string& what) {
- return str.compare(0, what.size(), what) == 0;
-}
-
bool contains(const std::string& str, const std::string& what) {
return str.find(what) != std::string::npos;
}
@@ -225,7 +240,7 @@ static int process( const std::string& srcfilename,
int main() {
- // Use the Win32 api instead of argc/argv so we can avoid interpreting the
+ // Use the Win32 API instead of argc/argv so we can avoid interpreting the
// rest of command line after the .d and .obj. Custom parsing seemed
// preferable to the ugliness you get into in trying to re-escape quotes for
// subprocesses, so by avoiding argc/argv, the subprocess is called with
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index 3e63183eb..e767a1612 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -60,7 +60,7 @@ static const char * cmDocumentationOptions[][3] =
"Test output is normally suppressed and only summary information is "
"displayed. This option will show even more test output."},
{"--debug", "Displaying more verbose internals of CTest.",
- "This feature will result in large number of output that is mostly "
+ "This feature will result in a large number of output that is mostly "
"useful for debugging dashboard problems."},
{"--output-on-failure", "Output anything outputted by the test program "
"if the test should fail. This option can also be enabled by setting "
@@ -71,7 +71,8 @@ static const char * cmDocumentationOptions[][3] =
{"-j <jobs>, --parallel <jobs>", "Run the tests in parallel using the"
"given number of jobs.",
"This option tells ctest to run the tests in parallel using given "
- "number of jobs."},
+ "number of jobs. This option can also be set by setting "
+ "the environment variable CTEST_PARALLEL_LEVEL."},
{"-Q,--quiet", "Make ctest quiet.",
"This option will suppress all the output. The output log file will "
"still be generated if the --output-log is specified. Options such "
@@ -99,7 +100,7 @@ static const char * cmDocumentationOptions[][3] =
"This option tells ctest to NOT run the tests whose labels match the "
"given regular expression."},
{"-D <dashboard>, --dashboard <dashboard>", "Execute dashboard test",
- "This option tells ctest to perform act as a Dart client and perform "
+ "This option tells ctest to act as a Dart client and perform "
"a dashboard test. All tests are <Mode><Test>, where Mode can be "
"Experimental, Nightly, and Continuous, and Test can be Start, Update, "
"Configure, Build, Test, Coverage, and Submit."},
@@ -171,7 +172,7 @@ static const char * cmDocumentationOptions[][3] =
"to this command line are the source and binary directories. By default "
"this will run CMake on the Source/Bin directories specified unless "
"--build-nocmake is specified. Both --build-makeprogram and "
- "--build-generator MUST be provided to use --built-and-test. If "
+ "--build-generator MUST be provided to use --build-and-test. If "
"--test-command is specified then that will be run after the build is "
"complete. Other options that affect this mode are --build-target "
"--build-nocmake, --build-run-dir, "
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 124b8aca0..0f2783689 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -569,8 +569,17 @@ IF(KWSYS_USE_SystemTools)
"Checking whether CXX compiler has unsetenv" DIRECT)
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
"Checking whether CXX compiler has environ in stdlib.h" DIRECT)
- SET_SOURCE_FILES_PROPERTIES(SystemTools.cxx PROPERTIES
- COMPILE_FLAGS "-DKWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV} -DKWSYS_CXX_HAS_UNSETENV=${KWSYS_CXX_HAS_UNSETENV} -DKWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=${KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H}")
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UTIMES
+ "Checking whether CXX compiler has utimes" DIRECT)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UTIMENSAT
+ "Checking whether CXX compiler has utimensat" DIRECT)
+ SET_PROPERTY(SOURCE SystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS
+ KWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV}
+ KWSYS_CXX_HAS_UNSETENV=${KWSYS_CXX_HAS_UNSETENV}
+ KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=${KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H}
+ KWSYS_CXX_HAS_UTIMES=${KWSYS_CXX_HAS_UTIMES}
+ KWSYS_CXX_HAS_UTIMENSAT=${KWSYS_CXX_HAS_UTIMENSAT}
+ )
ENDIF()
IF(KWSYS_USE_SystemInformation)
@@ -640,6 +649,68 @@ IF(KWSYS_USE_SystemInformation)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1)
ENDIF()
+ IF(UNIX)
+ INCLUDE(CheckIncludeFileCXX)
+ # check for simple stack trace
+ # usually it's in libc but on FreeBSD
+ # it's in libexecinfo
+ FIND_LIBRARY(EXECINFO_LIB "execinfo")
+ IF (NOT EXECINFO_LIB)
+ SET(EXECINFO_LIB "")
+ ENDIF()
+ CHECK_INCLUDE_FILE_CXX("execinfo.h" KWSYS_CXX_HAS_EXECINFOH)
+ IF (KWSYS_CXX_HAS_EXECINFOH)
+ # we have the backtrace header check if it
+ # can be used with this compiler
+ SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${EXECINFO_LIB})
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BACKTRACE
+ "Checking whether backtrace works with this C++ compiler" DIRECT)
+ SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES)
+ IF (KWSYS_CXX_HAS_BACKTRACE)
+ # backtrace is supported by this system and compiler.
+ # now check for the more advanced capabilities.
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE=1)
+ # check for symbol lookup using dladdr
+ CHECK_INCLUDE_FILE_CXX("dlfcn.h" KWSYS_CXX_HAS_DLFCNH)
+ IF (KWSYS_CXX_HAS_DLFCNH)
+ # we have symbol lookup libraries and headers
+ # check if they can be used with this compiler
+ SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${CMAKE_DL_LIBS})
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_DLADDR
+ "Checking whether dladdr works with this C++ compiler" DIRECT)
+ SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES)
+ IF (KWSYS_CXX_HAS_DLADDR)
+ # symbol lookup is supported by this system
+ # and compiler.
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP=1)
+ ENDIF()
+ ENDIF()
+ # c++ demangling support
+ # check for cxxabi headers
+ CHECK_INCLUDE_FILE_CXX("cxxabi.h" KWSYS_CXX_HAS_CXXABIH)
+ IF (KWSYS_CXX_HAS_CXXABIH)
+ # check if cxxabi can be used with this
+ # system and compiler.
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CXXABI
+ "Checking whether cxxabi works with this C++ compiler" DIRECT)
+ IF (KWSYS_CXX_HAS_CXXABI)
+ # c++ demangle using cxxabi is supported with
+ # this system and compiler
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE=1)
+ ENDIF()
+ ENDIF()
+ # basic backtrace works better with release build
+ # don't bother with advanced features for release
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS_DEBUG KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS_RELWITHDEBINFO KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1)
+ ENDIF()
+ ENDIF()
+ ENDIF()
IF(BORLAND)
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM
"Checking whether Borland CXX compiler supports assembler instructions" DIRECT)
@@ -904,12 +975,23 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
ENDIF(UNIX)
ENDIF(KWSYS_USE_DynamicLoader)
- IF(KWSYS_USE_SystemInformation AND WIN32)
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32)
- IF(KWSYS_SYS_HAS_PSAPI)
- TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi)
+ IF(KWSYS_USE_SystemInformation)
+ IF(WIN32)
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32)
+ IF(KWSYS_SYS_HAS_PSAPI)
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi)
+ ENDIF()
+ ELSEIF(UNIX)
+ IF (EXECINFO_LIB AND KWSYS_CXX_HAS_BACKTRACE)
+ # backtrace on FreeBSD is not in libc
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${EXECINFO_LIB})
+ ENDIF()
+ IF (KWSYS_CXX_HAS_DLADDR)
+ # for symbol lookup using dladdr
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS})
+ ENDIF()
ENDIF()
- ENDIF(KWSYS_USE_SystemInformation AND WIN32)
+ ENDIF()
# Apply user-defined target properties to the library.
IF(KWSYS_PROPERTIES_CXX)
diff --git a/Source/kwsys/CommandLineArguments.hxx.in b/Source/kwsys/CommandLineArguments.hxx.in
index 68e9600ef..cbf6ee393 100644
--- a/Source/kwsys/CommandLineArguments.hxx.in
+++ b/Source/kwsys/CommandLineArguments.hxx.in
@@ -44,7 +44,7 @@ struct CommandLineArgumentsCallbackStructure;
*
* For the variable interface you associate variable with each argument. When
* the argument is specified, the variable is set to the specified value casted
- * to the apropriate type. For boolean (NO_ARGUMENT), the value is "1".
+ * to the appropriate type. For boolean (NO_ARGUMENT), the value is "1".
*
* Both interfaces can be used at the same time.
*
@@ -99,7 +99,7 @@ public:
STRING_TYPE, // The variable is string (char*)
STL_STRING_TYPE, // The variable is string (char*)
VECTOR_INT_TYPE, // The variable is integer (int)
- VECTOR_BOOL_TYPE, // The vairable is boolean (bool)
+ VECTOR_BOOL_TYPE, // The variable is boolean (bool)
VECTOR_DOUBLE_TYPE, // The variable is float (double)
VECTOR_STRING_TYPE, // The variable is string (char*)
VECTOR_STL_STRING_TYPE, // The variable is string (char*)
@@ -128,7 +128,7 @@ public:
void ProcessArgument(const char* arg);
/**
- * This method will parse arguments and call apropriate methods.
+ * This method will parse arguments and call appropriate methods.
*/
int Parse();
@@ -144,7 +144,7 @@ public:
/**
* Add handler for argument which is going to set the variable to the
* specified value. If the argument is specified, the option is casted to the
- * apropriate type.
+ * appropriate type.
*/
void AddArgument(const char* argument, ArgumentTypeEnum type,
bool* variable, const char* help);
@@ -160,7 +160,7 @@ public:
/**
* Add handler for argument which is going to set the variable to the
* specified value. If the argument is specified, the option is casted to the
- * apropriate type. This will handle the multi argument values.
+ * appropriate type. This will handle the multi argument values.
*/
void AddArgument(const char* argument, ArgumentTypeEnum type,
kwsys_stl::vector<bool>* variable, const char* help);
diff --git a/Source/kwsys/RegularExpression.cxx b/Source/kwsys/RegularExpression.cxx
index f6eeebae4..c8297873f 100644
--- a/Source/kwsys/RegularExpression.cxx
+++ b/Source/kwsys/RegularExpression.cxx
@@ -312,8 +312,8 @@ static char* regbranch (int*);
static char* regpiece (int*);
static char* regatom (int*);
static char* regnode (char);
-static const char* regnext (register const char*);
-static char* regnext (register char*);
+static const char* regnext (const char*);
+static char* regnext (char*);
static void regc (char);
static void reginsert (char, char*);
static void regtail (char*, const char*);
@@ -344,10 +344,10 @@ static int strcspn ();
// for later pattern matching.
bool RegularExpression::compile (const char* exp) {
- register const char* scan;
- register const char* longest;
- register size_t len;
- int flags;
+ const char* scan;
+ const char* longest;
+ size_t len;
+ int flags;
if (exp == 0) {
//RAISE Error, SYM(RegularExpression), SYM(No_Expr),
@@ -444,11 +444,11 @@ bool RegularExpression::compile (const char* exp) {
* follows makes it hard to avoid.
*/
static char* reg (int paren, int *flagp) {
- register char* ret;
- register char* br;
- register char* ender;
- register int parno =0;
- int flags;
+ char* ret;
+ char* br;
+ char* ender;
+ int parno =0;
+ int flags;
*flagp = HASWIDTH; // Tentatively.
@@ -525,10 +525,10 @@ static char* reg (int paren, int *flagp) {
* Implements the concatenation operator.
*/
static char* regbranch (int *flagp) {
- register char* ret;
- register char* chain;
- register char* latest;
- int flags;
+ char* ret;
+ char* chain;
+ char* latest;
+ int flags;
*flagp = WORST; // Tentatively.
@@ -562,10 +562,10 @@ static char* regbranch (int *flagp) {
* endmarker role is not redundant.
*/
static char* regpiece (int *flagp) {
- register char* ret;
- register char op;
- register char* next;
- int flags;
+ char* ret;
+ char op;
+ char* next;
+ int flags;
ret = regatom(&flags);
if (ret == 0)
@@ -631,8 +631,8 @@ static char* regpiece (int *flagp) {
* separate node; the code is simpler that way and it's not worth fixing.
*/
static char* regatom (int *flagp) {
- register char* ret;
- int flags;
+ char* ret;
+ int flags;
*flagp = WORST; // Tentatively.
@@ -648,8 +648,8 @@ static char* regatom (int *flagp) {
*flagp |= HASWIDTH | SIMPLE;
break;
case '[':{
- register int rxpclass;
- register int rxpclassend;
+ int rxpclass;
+ int rxpclassend;
if (*regparse == '^') { // Complement of range.
ret = regnode(ANYBUT);
@@ -720,8 +720,8 @@ static char* regatom (int *flagp) {
*flagp |= HASWIDTH | SIMPLE;
break;
default:{
- register int len;
- register char ender;
+ int len;
+ char ender;
regparse--;
len = int(strcspn(regparse, META));
@@ -754,8 +754,8 @@ static char* regatom (int *flagp) {
Location.
*/
static char* regnode (char op) {
- register char* ret;
- register char* ptr;
+ char* ret;
+ char* ptr;
ret = regcode;
if (ret == &regdummy) {
@@ -790,9 +790,9 @@ static void regc (char b) {
* Means relocating the operand.
*/
static void reginsert (char op, char* opnd) {
- register char* src;
- register char* dst;
- register char* place;
+ char* src;
+ char* dst;
+ char* place;
if (regcode == &regdummy) {
regsize += 3;
@@ -816,9 +816,9 @@ static void reginsert (char op, char* opnd) {
- regtail - set the next-pointer at the end of a node chain
*/
static void regtail (char* p, const char* val) {
- register char* scan;
- register char* temp;
- register int offset;
+ char* scan;
+ char* temp;
+ int offset;
if (p == &regdummy)
return;
@@ -893,7 +893,7 @@ bool RegularExpression::find (kwsys_stl::string const& s)
// Returns true if found, and sets start and end indexes accordingly.
bool RegularExpression::find (const char* string) {
- register const char* s;
+ const char* s;
this->searchstring = string;
@@ -956,9 +956,9 @@ bool RegularExpression::find (const char* string) {
*/
static int regtry (const char* string, const char* *start,
const char* *end, const char* prog) {
- register int i;
- register const char* *sp1;
- register const char* *ep;
+ int i;
+ const char* *sp1;
+ const char* *ep;
reginput = string;
regstartp = start;
@@ -992,8 +992,8 @@ static int regtry (const char* string, const char* *start,
* 0 failure, 1 success
*/
static int regmatch (const char* prog) {
- register const char* scan; // Current node.
- const char* next; // Next node.
+ const char* scan; // Current node.
+ const char* next; // Next node.
scan = prog;
@@ -1016,8 +1016,8 @@ static int regmatch (const char* prog) {
reginput++;
break;
case EXACTLY:{
- register size_t len;
- register const char* opnd;
+ size_t len;
+ const char* opnd;
opnd = OPERAND(scan);
// Inline the first character, for speed.
@@ -1052,8 +1052,8 @@ static int regmatch (const char* prog) {
case OPEN + 7:
case OPEN + 8:
case OPEN + 9:{
- register int no;
- register const char* save;
+ int no;
+ const char* save;
no = OP(scan) - OPEN;
save = reginput;
@@ -1081,8 +1081,8 @@ static int regmatch (const char* prog) {
case CLOSE + 7:
case CLOSE + 8:
case CLOSE + 9:{
- register int no;
- register const char* save;
+ int no;
+ const char* save;
no = OP(scan) - CLOSE;
save = reginput;
@@ -1103,7 +1103,7 @@ static int regmatch (const char* prog) {
// break;
case BRANCH:{
- register const char* save;
+ const char* save;
if (OP(next) != BRANCH) // No choice.
next = OPERAND(scan); // Avoid recursion.
@@ -1122,10 +1122,10 @@ static int regmatch (const char* prog) {
break;
case STAR:
case PLUS:{
- register char nextch;
- register int no;
- register const char* save;
- register int min_no;
+ char nextch;
+ int no;
+ const char* save;
+ int min_no;
//
// Lookahead to avoid useless match attempts when we know
@@ -1174,9 +1174,9 @@ static int regmatch (const char* prog) {
- regrepeat - repeatedly match something simple, report how many
*/
static int regrepeat (const char* p) {
- register int count = 0;
- register const char* scan;
- register const char* opnd;
+ int count = 0;
+ const char* scan;
+ const char* opnd;
scan = reginput;
opnd = OPERAND(p);
@@ -1216,8 +1216,8 @@ static int regrepeat (const char* p) {
/*
- regnext - dig the "next" pointer out of a node
*/
-static const char* regnext (register const char* p) {
- register int offset;
+static const char* regnext (const char* p) {
+ int offset;
if (p == &regdummy)
return (0);
@@ -1232,8 +1232,8 @@ static const char* regnext (register const char* p) {
return (p + offset);
}
-static char* regnext (register char* p) {
- register int offset;
+static char* regnext (char* p) {
+ int offset;
if (p == &regdummy)
return (0);
diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in
index 8521099ad..8bbc74ac2 100644
--- a/Source/kwsys/SharedForward.h.in
+++ b/Source/kwsys/SharedForward.h.in
@@ -772,7 +772,7 @@ static int kwsys_shared_forward_get_settings(const char* self_path,
const char** dir;
for(dir = search_path; *dir; ++dir)
{
- /* Add seperator between path components. */
+ /* Add separator between path components. */
if(dir != search_path)
{
strcat(ldpath, kwsys_shared_forward_path_sep);
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 9e2a93d7c..beefd7d73 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -18,6 +18,10 @@
# include <winsock.h> // WSADATA, include before sys/types.h
#endif
+#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+#endif
+
// TODO:
// We need an alternative implementation for many functions in this file
// when USE_ASM_INSTRUCTIONS gets defined as 0.
@@ -114,8 +118,15 @@ typedef int siginfo_t;
# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
# endif
# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 >= 1050
-# include <execinfo.h>
-# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+# include <execinfo.h>
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+# include <cxxabi.h>
+# endif
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# include <dlfcn.h>
+# endif
+# endif
# endif
#endif
@@ -130,10 +141,13 @@ typedef int siginfo_t;
# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
# endif
# endif
-# if defined(__GNUC__)
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
# include <execinfo.h>
-# if !(defined(__LSB_VERSION__) && __LSB_VERSION__ < 41)
-# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+# include <cxxabi.h>
+# endif
+# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+# include <dlfcn.h>
# endif
# endif
# if defined(KWSYS_CXX_HAS_RLIMIT64)
@@ -357,6 +371,10 @@ public:
static
void SetStackTraceOnError(int enable);
+ // get current stack
+ static
+ kwsys_stl::string GetProgramStack(int firstFrame, int wholePath);
+
/** Run the different checks */
void RunCPUCheck();
void RunOSCheck();
@@ -812,6 +830,11 @@ void SystemInformation::SetStackTraceOnError(int enable)
SystemInformationImplementation::SetStackTraceOnError(enable);
}
+kwsys_stl::string SystemInformation::GetProgramStack(int firstFrame, int wholePath)
+{
+ return SystemInformationImplementation::GetProgramStack(firstFrame, wholePath);
+}
+
/** Run the different checks */
void SystemInformation::RunCPUCheck()
{
@@ -908,6 +931,12 @@ int LoadLines(
}
continue;
}
+ char *pBuf=buf;
+ while(*pBuf)
+ {
+ if (*pBuf=='\n') *pBuf='\0';
+ pBuf+=1;
+ }
lines.push_back(buf);
++nRead;
}
@@ -1046,12 +1075,29 @@ void StacktraceSignalHandler(
#if defined(__linux) || defined(__APPLE__)
kwsys_ios::ostringstream oss;
oss
+ << kwsys_ios::endl
<< "=========================================================" << kwsys_ios::endl
<< "Process id " << getpid() << " ";
switch (sigNo)
{
+ case SIGINT:
+ oss << "Caught SIGINT";
+ break;
+
+ case SIGTERM:
+ oss << "Caught SIGTERM";
+ break;
+
+ case SIGABRT:
+ oss << "Caught SIGABRT";
+ break;
+
case SIGFPE:
- oss << "Caught SIGFPE ";
+ oss
+ << "Caught SIGFPE at "
+ << (sigInfo->si_addr==0?"0x":"")
+ << sigInfo->si_addr
+ << " ";
switch (sigInfo->si_code)
{
# if defined(FPE_INTDIV)
@@ -1099,7 +1145,11 @@ void StacktraceSignalHandler(
break;
case SIGSEGV:
- oss << "Caught SIGSEGV ";
+ oss
+ << "Caught SIGSEGV at "
+ << (sigInfo->si_addr==0?"0x":"")
+ << sigInfo->si_addr
+ << " ";
switch (sigInfo->si_code)
{
case SEGV_MAPERR:
@@ -1116,16 +1166,12 @@ void StacktraceSignalHandler(
}
break;
- case SIGINT:
- oss << "Caught SIGTERM";
- break;
-
- case SIGTERM:
- oss << "Caught SIGTERM";
- break;
-
case SIGBUS:
- oss << "Caught SIGBUS type ";
+ oss
+ << "Caught SIGBUS at "
+ << (sigInfo->si_addr==0?"0x":"")
+ << sigInfo->si_addr
+ << " ";
switch (sigInfo->si_code)
{
case BUS_ADRALN:
@@ -1134,13 +1180,25 @@ void StacktraceSignalHandler(
# if defined(BUS_ADRERR)
case BUS_ADRERR:
- oss << "non-exestent physical address";
+ oss << "nonexistent physical address";
break;
# endif
# if defined(BUS_OBJERR)
case BUS_OBJERR:
- oss << "object specific hardware error";
+ oss << "object-specific hardware error";
+ break;
+# endif
+
+# if defined(BUS_MCEERR_AR)
+ case BUS_MCEERR_AR:
+ oss << "Hardware memory error consumed on a machine check; action required.";
+ break;
+# endif
+
+# if defined(BUS_MCEERR_AO)
+ case BUS_MCEERR_AO:
+ oss << "Hardware memory error detected in process but not consumed; action optional.";
break;
# endif
@@ -1151,7 +1209,11 @@ void StacktraceSignalHandler(
break;
case SIGILL:
- oss << "Caught SIGILL ";
+ oss
+ << "Caught SIGILL at "
+ << (sigInfo->si_addr==0?"0x":"")
+ << sigInfo->si_addr
+ << " ";
switch (sigInfo->si_code)
{
case ILL_ILLOPC:
@@ -1205,20 +1267,16 @@ void StacktraceSignalHandler(
oss << "Caught " << sigNo << " code " << sigInfo->si_code;
break;
}
- oss << kwsys_ios::endl;
-#if defined(KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE)
- oss << "Program Stack:" << kwsys_ios::endl;
- void *stackSymbols[128];
- int n=backtrace(stackSymbols,128);
- char **stackText=backtrace_symbols(stackSymbols,n);
- for (int i=0; i<n; ++i)
- {
- oss << " " << stackText[i] << kwsys_ios::endl;
- }
-#endif
oss
- << "=========================================================" << kwsys_ios::endl;
+ << kwsys_ios::endl
+ << "Program Stack:" << kwsys_ios::endl
+ << SystemInformationImplementation::GetProgramStack(2,0)
+ << "=========================================================" << kwsys_ios::endl;
kwsys_ios::cerr << oss.str() << kwsys_ios::endl;
+
+ // restore the previously registered handlers
+ // and abort
+ SystemInformationImplementation::SetStackTraceOnError(0);
abort();
#else
// avoid warning C4100
@@ -1227,8 +1285,213 @@ void StacktraceSignalHandler(
#endif
}
#endif
+
+#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+#define safes(_arg)((_arg)?(_arg):"???")
+
+// Description:
+// A container for symbol properties. Each instance
+// must be Initialized.
+class SymbolProperties
+{
+public:
+ SymbolProperties();
+
+ // Description:
+ // The SymbolProperties instance must be initialized by
+ // passing a stack address.
+ void Initialize(void *address);
+
+ // Description:
+ // Get the symbol's stack address.
+ void *GetAddress() const { return this->Address; }
+
+ // Description:
+ // If not set paths will be removed. eg, from a binary
+ // or source file.
+ void SetReportPath(int rp){ this->ReportPath=rp; }
+
+ // Description:
+ // Set/Get the name of the binary file that the symbol
+ // is found in.
+ void SetBinary(const char *binary)
+ { this->Binary=safes(binary); }
+
+ kwsys_stl::string GetBinary() const;
+
+ // Description:
+ // Set the name of the function that the symbol is found in.
+ // If c++ demangling is supported it will be demangled.
+ void SetFunction(const char *function)
+ { this->Function=this->Demangle(function); }
+
+ kwsys_stl::string GetFunction() const
+ { return this->Function; }
+
+ // Description:
+ // Set/Get the name of the source file where the symbol
+ // is defined.
+ void SetSourceFile(const char *sourcefile)
+ { this->SourceFile=safes(sourcefile); }
+
+ kwsys_stl::string GetSourceFile() const
+ { return this->GetFileName(this->SourceFile); }
+
+ // Description:
+ // Set/Get the line number where the symbol is defined
+ void SetLineNumber(long linenumber){ this->LineNumber=linenumber; }
+ long GetLineNumber() const { return this->LineNumber; }
+
+ // Description:
+ // Set the address where the biinary image is mapped
+ // into memory.
+ void SetBinaryBaseAddress(void *address)
+ { this->BinaryBaseAddress=address; }
+
+private:
+ void *GetRealAddress() const
+ { return (void*)((char*)this->Address-(char*)this->BinaryBaseAddress); }
+
+ kwsys_stl::string GetFileName(const kwsys_stl::string &path) const;
+ kwsys_stl::string Demangle(const char *symbol) const;
+
+private:
+ kwsys_stl::string Binary;
+ void *BinaryBaseAddress;
+ void *Address;
+ kwsys_stl::string SourceFile;
+ kwsys_stl::string Function;
+ long LineNumber;
+ int ReportPath;
+};
+
+// --------------------------------------------------------------------------
+kwsys_ios::ostream &operator<<(
+ kwsys_ios::ostream &os,
+ const SymbolProperties &sp)
+{
+#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+ os
+ << kwsys_ios::hex << sp.GetAddress() << " : "
+ << sp.GetFunction()
+ << " [(" << sp.GetBinary() << ") "
+ << sp.GetSourceFile() << ":"
+ << kwsys_ios::dec << sp.GetLineNumber() << "]";
+#elif defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+ void *addr = sp.GetAddress();
+ char **syminfo = backtrace_symbols(&addr,1);
+ os << safes(syminfo[0]);
+ free(syminfo);
+#else
+ (void)os;
+ (void)sp;
+#endif
+ return os;
+}
+
+// --------------------------------------------------------------------------
+SymbolProperties::SymbolProperties()
+{
+ // not using an initializer list
+ // to avoid some PGI compiler warnings
+ this->SetBinary("???");
+ this->SetBinaryBaseAddress(NULL);
+ this->Address = NULL;
+ this->SetSourceFile("???");
+ this->SetFunction("???");
+ this->SetLineNumber(-1);
+ this->SetReportPath(0);
+ // avoid PGI compiler warnings
+ this->GetRealAddress();
+ this->GetFunction();
+ this->GetSourceFile();
+ this->GetLineNumber();
+}
+
+// --------------------------------------------------------------------------
+kwsys_stl::string SymbolProperties::GetFileName(const kwsys_stl::string &path) const
+{
+ kwsys_stl::string file(path);
+ if (!this->ReportPath)
+ {
+ size_t at = file.rfind("/");
+ if (at!=kwsys_stl::string::npos)
+ {
+ file = file.substr(at+1,kwsys_stl::string::npos);
+ }
+ }
+ return file;
+}
+
+// --------------------------------------------------------------------------
+kwsys_stl::string SymbolProperties::GetBinary() const
+{
+// only linux has proc fs
+#if defined(__linux__)
+ if (this->Binary=="/proc/self/exe")
+ {
+ kwsys_stl::string binary;
+ char buf[1024]={'\0'};
+ ssize_t ll=0;
+ if ((ll=readlink("/proc/self/exe",buf,1024))>0)
+ {
+ buf[ll]='\0';
+ binary=buf;
+ }
+ else
+ {
+ binary="/proc/self/exe";
+ }
+ return this->GetFileName(binary);
+ }
+#endif
+ return this->GetFileName(this->Binary);
+}
+
+// --------------------------------------------------------------------------
+kwsys_stl::string SymbolProperties::Demangle(const char *symbol) const
+{
+ kwsys_stl::string result = safes(symbol);
+#if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+ int status = 0;
+ size_t bufferLen = 1024;
+ char *buffer = (char*)malloc(1024);
+ char *demangledSymbol =
+ abi::__cxa_demangle(symbol, buffer, &bufferLen, &status);
+ if (!status)
+ {
+ result = demangledSymbol;
+ }
+ free(buffer);
+#else
+ (void)symbol;
+#endif
+ return result;
+}
+
+// --------------------------------------------------------------------------
+void SymbolProperties::Initialize(void *address)
+{
+ this->Address = address;
+#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+ // first fallback option can demangle c++ functions
+ Dl_info info;
+ int ierr=dladdr(this->Address,&info);
+ if (ierr && info.dli_sname && info.dli_saddr)
+ {
+ this->SetBinary(info.dli_fname);
+ this->SetFunction(info.dli_sname);
+ }
+#else
+ // second fallback use builtin backtrace_symbols
+ // to decode the bactrace.
+#endif
+}
+#endif // don't define this class if we're not using it
+
} // anonymous namespace
+
SystemInformationImplementation::SystemInformationImplementation()
{
this->TotalVirtualMemory = 0;
@@ -1471,7 +1734,7 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
{
char host[NI_MAXHOST]={'\0'};
- int addrlen
+ socklen_t addrlen
= (fam==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6));
ierr=getnameinfo(
@@ -3336,12 +3599,61 @@ SystemInformationImplementation::GetProcessId()
}
/**
+return current program stack in a string
+demangle cxx symbols if possible.
+*/
+kwsys_stl::string SystemInformationImplementation::GetProgramStack(
+ int firstFrame,
+ int wholePath)
+{
+ kwsys_stl::string programStack = ""
+#if !defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+ "WARNING: The stack could not be examined "
+ "because backtrace is not supported.\n"
+#elif !defined(KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD)
+ "WARNING: The stack trace will not use advanced "
+ "capabilities because this is a release build.\n"
+#else
+# if !defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP)
+ "WARNING: Function names will not be demangled because "
+ "dladdr is not available.\n"
+# endif
+# if !defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE)
+ "WARNING: Function names will not be demangled "
+ "because cxxabi is not available.\n"
+# endif
+#endif
+ ;
+
+ kwsys_ios::ostringstream oss;
+#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
+ void *stackSymbols[256];
+ int nFrames=backtrace(stackSymbols,256);
+ for (int i=firstFrame; i<nFrames; ++i)
+ {
+ SymbolProperties symProps;
+ symProps.SetReportPath(wholePath);
+ symProps.Initialize(stackSymbols[i]);
+ oss << symProps << kwsys_ios::endl;
+ }
+#else
+ (void)firstFrame;
+ (void)wholePath;
+#endif
+ programStack += oss.str();
+
+ return programStack;
+}
+
+
+/**
when set print stack trace in response to common signals.
*/
void SystemInformationImplementation::SetStackTraceOnError(int enable)
{
#if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
static int saOrigValid=0;
+ static struct sigaction saABRTOrig;
static struct sigaction saSEGVOrig;
static struct sigaction saTERMOrig;
static struct sigaction saINTOrig;
@@ -3349,9 +3661,11 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
static struct sigaction saBUSOrig;
static struct sigaction saFPEOrig;
+
if (enable && !saOrigValid)
{
// save the current actions
+ sigaction(SIGABRT,0,&saABRTOrig);
sigaction(SIGSEGV,0,&saSEGVOrig);
sigaction(SIGTERM,0,&saTERMOrig);
sigaction(SIGINT,0,&saINTOrig);
@@ -3365,9 +3679,10 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
// install ours
struct sigaction sa;
sa.sa_sigaction=(SigAction)StacktraceSignalHandler;
- sa.sa_flags=SA_SIGINFO|SA_RESTART;
+ sa.sa_flags=SA_SIGINFO|SA_RESTART|SA_RESETHAND;
sigemptyset(&sa.sa_mask);
+ sigaction(SIGABRT,&sa,0);
sigaction(SIGSEGV,&sa,0);
sigaction(SIGTERM,&sa,0);
sigaction(SIGINT,&sa,0);
@@ -3379,6 +3694,7 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
if (!enable && saOrigValid)
{
// restore previous actions
+ sigaction(SIGABRT,&saABRTOrig,0);
sigaction(SIGSEGV,&saSEGVOrig,0);
sigaction(SIGTERM,&saTERMOrig,0);
sigaction(SIGINT,&saINTOrig,0);
@@ -3487,7 +3803,7 @@ bool SystemInformationImplementation::QueryLinuxMemory()
bool have[6] = { false, false, false, false, false, false };
unsigned long value[6];
int count = 0;
- while(fgets(buffer, sizeof(buffer), fd))
+ while(fgets(buffer, static_cast<int>(sizeof(buffer)), fd))
{
for(int i=0; i < 6; ++i)
{
diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in
index 8f4cb4e5a..a9fd05def 100644
--- a/Source/kwsys/SystemInformation.hxx.in
+++ b/Source/kwsys/SystemInformation.hxx.in
@@ -117,8 +117,8 @@ public:
// Get total system RAM in units of KiB available to this process.
// This may differ from the host available if a per-process resource
// limit is applied. per-process memory limits are applied on unix
- // system via rlimit api. Resource limits that are not imposed via
- // rlimit api may be reported to us via an application specified
+ // system via rlimit API. Resource limits that are not imposed via
+ // rlimit API may be reported to us via an application specified
// environment variable.
LongLong GetProcMemoryAvailable(
const char *hostLimitEnvVarName=NULL,
@@ -136,6 +136,12 @@ public:
static
void SetStackTraceOnError(int enable);
+ // format and return the current program stack in a string. In
+ // order to produce an informative stack trace the application
+ // should be dynamically linked and compiled with debug symbols.
+ static
+ kwsys_stl::string GetProgramStack(int firstFrame, int wholePath);
+
/** Run the different checks */
void RunCPUCheck();
void RunOSCheck();
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 8b25d608d..e9a1fd37d 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -605,7 +605,7 @@ bool SystemTools::MakeDirectory(const char* path)
}
if(SystemTools::FileExists(path))
{
- return true;
+ return SystemTools::FileIsDirectory(path);
}
kwsys_stl::string dir = path;
if(dir.size() == 0)
@@ -695,6 +695,52 @@ void SystemTools::ReplaceString(kwsys_stl::string& source,
#endif
#if defined(_WIN32) && !defined(__CYGWIN__)
+static bool SystemToolsParseRegistryKey(const char* key,
+ HKEY& primaryKey,
+ kwsys_stl::string& second,
+ kwsys_stl::string& valuename)
+{
+ kwsys_stl::string primary = key;
+
+ size_t start = primary.find("\\");
+ if (start == kwsys_stl::string::npos)
+ {
+ return false;
+ }
+
+ size_t valuenamepos = primary.find(";");
+ if (valuenamepos != kwsys_stl::string::npos)
+ {
+ valuename = primary.substr(valuenamepos+1);
+ }
+
+ second = primary.substr(start+1, valuenamepos-start-1);
+ primary = primary.substr(0, start);
+
+ if (primary == "HKEY_CURRENT_USER")
+ {
+ primaryKey = HKEY_CURRENT_USER;
+ }
+ if (primary == "HKEY_CURRENT_CONFIG")
+ {
+ primaryKey = HKEY_CURRENT_CONFIG;
+ }
+ if (primary == "HKEY_CLASSES_ROOT")
+ {
+ primaryKey = HKEY_CLASSES_ROOT;
+ }
+ if (primary == "HKEY_LOCAL_MACHINE")
+ {
+ primaryKey = HKEY_LOCAL_MACHINE;
+ }
+ if (primary == "HKEY_USERS")
+ {
+ primaryKey = HKEY_USERS;
+ }
+
+ return true;
+}
+
static DWORD SystemToolsMakeRegistryMode(DWORD mode,
SystemTools::KeyWOW64 view)
{
@@ -718,6 +764,55 @@ static DWORD SystemToolsMakeRegistryMode(DWORD mode,
}
#endif
+#if defined(_WIN32) && !defined(__CYGWIN__)
+bool
+SystemTools::GetRegistrySubKeys(const char *key,
+ kwsys_stl::vector<kwsys_stl::string>& subkeys,
+ KeyWOW64 view)
+{
+ HKEY primaryKey = HKEY_CURRENT_USER;
+ kwsys_stl::string second;
+ kwsys_stl::string valuename;
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
+ {
+ return false;
+ }
+
+ HKEY hKey;
+ if(RegOpenKeyEx(primaryKey,
+ second.c_str(),
+ 0,
+ SystemToolsMakeRegistryMode(KEY_READ, view),
+ &hKey) != ERROR_SUCCESS)
+ {
+ return false;
+ }
+ else
+ {
+ char name[1024];
+ DWORD dwNameSize = sizeof(name)/sizeof(name[0]);
+
+ DWORD i = 0;
+ while (RegEnumKey(hKey, i, name, dwNameSize) == ERROR_SUCCESS)
+ {
+ subkeys.push_back(name);
+ ++i;
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ return true;
+}
+#else
+bool SystemTools::GetRegistrySubKeys(const char *,
+ kwsys_stl::vector<kwsys_stl::string>&,
+ KeyWOW64)
+{
+ return false;
+}
+#endif
+
// Read a registry value.
// Example :
// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
@@ -730,47 +825,14 @@ bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value,
KeyWOW64 view)
{
bool valueset = false;
- kwsys_stl::string primary = key;
+ HKEY primaryKey = HKEY_CURRENT_USER;
kwsys_stl::string second;
kwsys_stl::string valuename;
-
- size_t start = primary.find("\\");
- if (start == kwsys_stl::string::npos)
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
{
return false;
}
- size_t valuenamepos = primary.find(";");
- if (valuenamepos != kwsys_stl::string::npos)
- {
- valuename = primary.substr(valuenamepos+1);
- }
-
- second = primary.substr(start+1, valuenamepos-start-1);
- primary = primary.substr(0, start);
-
- HKEY primaryKey = HKEY_CURRENT_USER;
- if (primary == "HKEY_CURRENT_USER")
- {
- primaryKey = HKEY_CURRENT_USER;
- }
- if (primary == "HKEY_CURRENT_CONFIG")
- {
- primaryKey = HKEY_CURRENT_CONFIG;
- }
- if (primary == "HKEY_CLASSES_ROOT")
- {
- primaryKey = HKEY_CLASSES_ROOT;
- }
- if (primary == "HKEY_LOCAL_MACHINE")
- {
- primaryKey = HKEY_LOCAL_MACHINE;
- }
- if (primary == "HKEY_USERS")
- {
- primaryKey = HKEY_USERS;
- }
-
HKEY hKey;
if(RegOpenKeyEx(primaryKey,
second.c_str(),
@@ -834,47 +896,14 @@ bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &,
bool SystemTools::WriteRegistryValue(const char *key, const char *value,
KeyWOW64 view)
{
- kwsys_stl::string primary = key;
+ HKEY primaryKey = HKEY_CURRENT_USER;
kwsys_stl::string second;
kwsys_stl::string valuename;
-
- size_t start = primary.find("\\");
- if (start == kwsys_stl::string::npos)
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
{
return false;
}
- size_t valuenamepos = primary.find(";");
- if (valuenamepos != kwsys_stl::string::npos)
- {
- valuename = primary.substr(valuenamepos+1);
- }
-
- second = primary.substr(start+1, valuenamepos-start-1);
- primary = primary.substr(0, start);
-
- HKEY primaryKey = HKEY_CURRENT_USER;
- if (primary == "HKEY_CURRENT_USER")
- {
- primaryKey = HKEY_CURRENT_USER;
- }
- if (primary == "HKEY_CURRENT_CONFIG")
- {
- primaryKey = HKEY_CURRENT_CONFIG;
- }
- if (primary == "HKEY_CLASSES_ROOT")
- {
- primaryKey = HKEY_CLASSES_ROOT;
- }
- if (primary == "HKEY_LOCAL_MACHINE")
- {
- primaryKey = HKEY_LOCAL_MACHINE;
- }
- if (primary == "HKEY_USERS")
- {
- primaryKey = HKEY_USERS;
- }
-
HKEY hKey;
DWORD dwDummy;
char lpClass[] = "";
@@ -919,47 +948,14 @@ bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64)
#if defined(_WIN32) && !defined(__CYGWIN__)
bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view)
{
- kwsys_stl::string primary = key;
+ HKEY primaryKey = HKEY_CURRENT_USER;
kwsys_stl::string second;
kwsys_stl::string valuename;
-
- size_t start = primary.find("\\");
- if (start == kwsys_stl::string::npos)
+ if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename))
{
return false;
}
- size_t valuenamepos = primary.find(";");
- if (valuenamepos != kwsys_stl::string::npos)
- {
- valuename = primary.substr(valuenamepos+1);
- }
-
- second = primary.substr(start+1, valuenamepos-start-1);
- primary = primary.substr(0, start);
-
- HKEY primaryKey = HKEY_CURRENT_USER;
- if (primary == "HKEY_CURRENT_USER")
- {
- primaryKey = HKEY_CURRENT_USER;
- }
- if (primary == "HKEY_CURRENT_CONFIG")
- {
- primaryKey = HKEY_CURRENT_CONFIG;
- }
- if (primary == "HKEY_CLASSES_ROOT")
- {
- primaryKey = HKEY_CLASSES_ROOT;
- }
- if (primary == "HKEY_LOCAL_MACHINE")
- {
- primaryKey = HKEY_LOCAL_MACHINE;
- }
- if (primary == "HKEY_USERS")
- {
- primaryKey = HKEY_USERS;
- }
-
HKEY hKey;
if(RegOpenKeyEx(primaryKey,
second.c_str(),
@@ -1124,22 +1120,58 @@ bool SystemTools::Touch(const char* filename, bool create)
}
return false;
}
-#ifdef _MSC_VER
-#define utime _utime
-#define utimbuf _utimbuf
-#endif
- struct stat fromStat;
- if(stat(filename, &fromStat) < 0)
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ HANDLE h = CreateFile(filename, FILE_WRITE_ATTRIBUTES,
+ FILE_SHARE_WRITE, 0, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, 0);
+ if(!h)
+ {
+ return false;
+ }
+ FILETIME mtime;
+ GetSystemTimeAsFileTime(&mtime);
+ if(!SetFileTime(h, 0, 0, &mtime))
+ {
+ CloseHandle(h);
+ return false;
+ }
+ CloseHandle(h);
+#elif KWSYS_CXX_HAS_UTIMENSAT
+ struct timespec times[2] = {{0,UTIME_OMIT},{0,UTIME_NOW}};
+ if(utimensat(AT_FDCWD, filename, times, 0) < 0)
+ {
+ return false;
+ }
+#else
+ struct stat st;
+ if(stat(filename, &st) < 0)
{
return false;
}
- struct utimbuf buf;
- buf.actime = fromStat.st_atime;
- buf.modtime = static_cast<time_t>(SystemTools::GetTime());
- if(utime(filename, &buf) < 0)
+ struct timeval mtime;
+ gettimeofday(&mtime, 0);
+# if KWSYS_CXX_HAS_UTIMES
+ struct timeval times[2] =
+ {
+# if KWSYS_STAT_HAS_ST_MTIM
+ {st.st_atim.tv_sec, st.st_atim.tv_nsec/1000}, /* tv_sec, tv_usec */
+# else
+ {st.st_atime, 0},
+# endif
+ mtime
+ };
+ if(utimes(filename, times) < 0)
+ {
+ return false;
+ }
+# else
+ struct utimbuf times = {st.st_atime, mtime.tv_sec};
+ if(utime(filename, &times) < 0)
{
return false;
}
+# endif
+#endif
return true;
}
@@ -2741,12 +2773,12 @@ bool SystemTools::FileIsDirectory(const char* name)
return false;
}
- // Remove any trailing slash from the name.
+ // Remove any trailing slash from the name except in a root component.
char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
std::string string_buffer;
size_t last = length-1;
if(last > 0 && (name[last] == '/' || name[last] == '\\')
- && strcmp(name, "/") !=0)
+ && strcmp(name, "/") !=0 && name[last-1] != ':')
{
if(last < sizeof(local_buffer))
{
@@ -3049,7 +3081,7 @@ SystemToolsAppendComponents(
{
if(*i == "..")
{
- if(out_components.begin() != out_components.end())
+ if(out_components.size() > 1)
{
out_components.erase(out_components.end()-1, out_components.end());
}
@@ -4011,7 +4043,7 @@ void SystemTools::SplitProgramFromArgs(const char* path,
args = dir.substr(spacePos, dir.size()-spacePos);
return;
}
- // Now try and find the the program in the path
+ // Now try and find the program in the path
findProg = SystemTools::FindProgram(tryProg.c_str(), e);
if(findProg.size())
{
@@ -4225,17 +4257,13 @@ bool SystemTools::IsSubDirectory(const char* cSubdir, const char* cDir)
}
kwsys_stl::string subdir = cSubdir;
kwsys_stl::string dir = cDir;
+ SystemTools::ConvertToUnixSlashes(subdir);
SystemTools::ConvertToUnixSlashes(dir);
- kwsys_stl::string path = subdir;
- do
+ if(subdir.size() > dir.size() && subdir[dir.size()] == '/')
{
- path = SystemTools::GetParentDirectory(path.c_str());
- if(SystemTools::ComparePath(dir.c_str(), path.c_str()))
- {
- return true;
- }
+ std::string s = subdir.substr(0, dir.size());
+ return SystemTools::ComparePath(s.c_str(), dir.c_str());
}
- while ( path.size() > dir.size() );
return false;
}
@@ -4837,7 +4865,8 @@ static int SystemToolsDebugReport(int, char* message, int*)
void SystemTools::EnableMSVCDebugHook()
{
- if (getenv("DART_TEST_FROM_DART"))
+ if (getenv("DART_TEST_FROM_DART") ||
+ getenv("DASHBOARD_TEST_FROM_CTEST"))
{
_CrtSetReportHook(SystemToolsDebugReport);
}
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 9c56e96b0..d6dae3986 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -716,6 +716,13 @@ public:
enum KeyWOW64 { KeyWOW64_Default, KeyWOW64_32, KeyWOW64_64 };
/**
+ * Get a list of subkeys.
+ */
+ static bool GetRegistrySubKeys(const char *key,
+ kwsys_stl::vector<kwsys_stl::string>& subkeys,
+ KeyWOW64 view = KeyWOW64_Default);
+
+ /**
* Read a registry value
*/
static bool ReadRegistryValue(const char *key, kwsys_stl::string &value,
@@ -766,7 +773,7 @@ public:
static kwsys_stl::string GetCurrentWorkingDirectory(bool collapse =true);
/**
- * Change directory the the directory specified
+ * Change directory to the directory specified
*/
static int ChangeDirectory(const char* dir);
diff --git a/Source/kwsys/auto_ptr.hxx.in b/Source/kwsys/auto_ptr.hxx.in
index 857b1db3c..ad9654cb4 100644
--- a/Source/kwsys/auto_ptr.hxx.in
+++ b/Source/kwsys/auto_ptr.hxx.in
@@ -31,6 +31,17 @@
# define @KWSYS_NAMESPACE@_AUTO_PTR_CAST(a) a
#endif
+// In C++11, clang will warn about using dynamic exception specifications
+// as they are deprecated. But as this class is trying to faithfully
+// mimic std::auto_ptr, we want to keep the 'throw()' decorations below.
+// So we suppress the warning.
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated"
+# endif
+#endif
+
namespace @KWSYS_NAMESPACE@
{
@@ -198,4 +209,11 @@ public:
} // namespace @KWSYS_NAMESPACE@
+// Undo warning suppression.
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic pop
+# endif
+#endif
+
#endif
diff --git a/Source/kwsys/hashtable.hxx.in b/Source/kwsys/hashtable.hxx.in
index c83550304..651de82bf 100644
--- a/Source/kwsys/hashtable.hxx.in
+++ b/Source/kwsys/hashtable.hxx.in
@@ -62,6 +62,17 @@
# pragma set woff 3970 /* pointer to int conversion */ 3321 3968
#endif
+// In C++11, clang will warn about using dynamic exception specifications
+// as they are deprecated. But as this class is trying to faithfully
+// mimic unordered_set and unordered_map, we want to keep the 'throw()'
+// decorations below. So we suppress the warning.
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated"
+# endif
+#endif
+
#if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE
# define @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(T) @KWSYS_NAMESPACE@_stl::allocator< T >
#elif @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE
@@ -1268,6 +1279,13 @@ using @KWSYS_NAMESPACE@::operator==;
using @KWSYS_NAMESPACE@::operator!=;
#endif
+// Undo warning suppression.
+#if defined(__clang__) && defined(__has_warning)
+# if __has_warning("-Wdeprecated")
+# pragma clang diagnostic pop
+# endif
+#endif
+
#if defined(_MSC_VER)
# pragma warning (pop)
#endif
diff --git a/Source/kwsys/kwsysPlatformTests.cmake b/Source/kwsys/kwsysPlatformTests.cmake
index d042450ee..f9ee254f0 100644
--- a/Source/kwsys/kwsysPlatformTests.cmake
+++ b/Source/kwsys/kwsysPlatformTests.cmake
@@ -19,6 +19,7 @@ MACRO(KWSYS_PLATFORM_TEST lang var description invert)
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}}
COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_TEST_DEFINES} ${KWSYS_PLATFORM_TEST_EXTRA_FLAGS}
+ CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${KWSYS_PLATFORM_TEST_LINK_LIBRARIES}"
OUTPUT_VARIABLE OUTPUT)
IF(${var}_COMPILED)
FILE(APPEND
@@ -150,9 +151,11 @@ ENDMACRO(KWSYS_PLATFORM_C_TEST_RUN)
MACRO(KWSYS_PLATFORM_CXX_TEST var description invert)
SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES})
SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS})
+ SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES ${KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES})
KWSYS_PLATFORM_TEST(CXX "${var}" "${description}" "${invert}")
SET(KWSYS_PLATFORM_TEST_DEFINES)
SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS)
+ SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES)
ENDMACRO(KWSYS_PLATFORM_CXX_TEST)
MACRO(KWSYS_PLATFORM_CXX_TEST_RUN var description invert)
diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx
index 48976c442..be7a09ee2 100644
--- a/Source/kwsys/kwsysPlatformTestsCXX.cxx
+++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx
@@ -494,6 +494,73 @@ int main()
}
#endif
+#ifdef TEST_KWSYS_CXX_HAS_UTIMES
+#include <sys/time.h>
+int main()
+{
+ struct timeval* current_time = 0;
+ return utimes("/example", current_time);
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_UTIMENSAT
+#include <fcntl.h>
+#include <sys/stat.h>
+int main()
+{
+ struct timespec times[2] = {{0,UTIME_OMIT},{0,UTIME_NOW}};
+ return utimensat(AT_FDCWD, "/example", times, AT_SYMLINK_NOFOLLOW);
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_BACKTRACE
+#if defined(__PATHSCALE__) || defined(__PATHCC__) \
+ || (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41))
+backtrace doesnt work with this compiler or os
+#endif
+#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+#endif
+#include <execinfo.h>
+int main()
+{
+ void *stackSymbols[256];
+ backtrace(stackSymbols,256);
+ backtrace_symbols(&stackSymbols[0],1);
+ return 0;
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_DLADDR
+#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+#endif
+#include <dlfcn.h>
+int main()
+{
+ Dl_info info;
+ int ierr=dladdr((void*)main,&info);
+ return 0;
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_CXXABI
+#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
+# define _GNU_SOURCE
+#endif
+#include <cxxabi.h>
+int main()
+{
+ int status = 0;
+ size_t bufferLen = 512;
+ char buffer[512] = {'\0'};
+ const char *function="_ZN5kwsys17SystemInformation15GetProgramStackEii";
+ char *demangledFunction =
+ abi::__cxa_demangle(function, buffer, &bufferLen, &status);
+ return status;
+}
+#endif
+
#ifdef TEST_KWSYS_CXX_TYPE_INFO
/* Collect fundamental type information and save it to a CMake script. */
diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx
index 61c157291..dd6d60390 100644
--- a/Source/kwsys/testDynamicLoader.cxx
+++ b/Source/kwsys/testDynamicLoader.cxx
@@ -109,9 +109,9 @@ int testDynamicLoader(int argc, char *argv[])
// dlopen() on Syllable before 11/22/2007 doesn't return 0 on error
#ifndef __SYLLABLE__
- // Make sure that inexistant lib is giving correct result
+ // Make sure that inexistent lib is giving correct result
res += TestDynamicLoader("azerty_", "foo_bar",0,0,0);
- // Make sure that random binary file cannnot be assimilated as dylib
+ // Make sure that random binary file cannot be assimilated as dylib
res += TestDynamicLoader(TEST_SYSTEMTOOLS_BIN_FILE, "wp",0,0,0);
#endif
diff --git a/Source/kwsys/testIOS.cxx b/Source/kwsys/testIOS.cxx
index 3b971e268..f0c7f1a7b 100644
--- a/Source/kwsys/testIOS.cxx
+++ b/Source/kwsys/testIOS.cxx
@@ -48,7 +48,7 @@ int testIOS(int, char*[])
return 1;
}
static const unsigned char array[] = { 0xff,0x4f,0xff,0x51,0x00,0x29,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x01,0x01,0xff,0x52,0x00,0x0c,0x00,0x00,0x00,0x01,0x00,0x05,0x04,0x04,0x00,0x01,0xff,0x5c,0x00,0x13,0x40,0x40,0x48,0x48,0x50,0x48,0x48,0x50,0x48,0x48,0x50,0x48,0x48,0x50,0x48,0x48,0x50,0xff,0x64,0x00,0x2c,0x00,0x00,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x62,0x79,0x20,0x49,0x54,0x4b,0x2f,0x47,0x44,0x43,0x4d,0x2f,0x4f,0x70,0x65,0x6e,0x4a,0x50,0x45,0x47,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x31,0x2e,0x30,0xff,0x90,0x00,0x0a,0x00,0x00,0x00,0x00,0x06,0x2c,0x00,0x01,0xff,0x93,0xcf,0xb0,0x18,0x08,0x7f,0xc6,0x99,0xbf,0xff,0xc0,0xf8,0xc1,0xc1,0xf3,0x05,0x81,0xf2,0x83,0x0a,0xa5,0xff,0x10,0x90,0xbf,0x2f,0xff,0x04,0xa8,0x7f,0xc0,0xf8,0xc4,0xc1,0xf3,0x09,0x81,0xf3,0x0c,0x19,0x34 };
- const unsigned int narray = sizeof(array); // 180
+ const size_t narray = sizeof(array); // 180
kwsys_ios::stringstream strstr;
strstr.write( (char*)array, narray );
//strstr.seekp( narray / 2 ); // set position of put pointer in mid string
diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx
index 49a686c17..53d51ac40 100644
--- a/Source/kwsys/testSystemInformation.cxx
+++ b/Source/kwsys/testSystemInformation.cxx
@@ -88,14 +88,31 @@ int testSystemInformation(int, char*[])
printMethod3(info, GetHostMemoryUsed(), "KiB");
printMethod3(info, GetProcMemoryUsed(), "KiB");
- for (int i = 0; i <= 31; i++)
+ for (long int i = 0; i <= 31; i++)
{
- if (info.DoesCPUSupportFeature(1 << i))
+ if (info.DoesCPUSupportFeature(static_cast<long int>(1) << i))
{
kwsys_ios::cout << "CPU feature " << i << "\n";
}
}
- //int GetProcessorCacheXSize(long int);
-// bool DoesCPUSupportFeature(long int);
+
+ /* test stack trace
+ */
+ kwsys_ios::cout
+ << "Program Stack:" << kwsys_ios::endl
+ << kwsys::SystemInformation::GetProgramStack(0,0) << kwsys_ios::endl
+ << kwsys_ios::endl;
+
+ /* test segv handler
+ info.SetStackTraceOnError(1);
+ double *d = (double*)100;
+ *d=0;
+ */
+
+ /* test abort handler
+ info.SetStackTraceOnError(1);
+ abort();
+ */
+
return 0;
}