summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2013-08-13 11:48:01 (GMT)
committerAnas Nashif <anas.nashif@intel.com>2013-08-13 11:48:01 (GMT)
commit297c63fa65327491a2b50e521b661c5835a19fe4 (patch)
treecf30d58014e240eb5e4417727d8f137cdbe75828 /Source
parentef8aa19c33e83ff019595fd7f8fdc29c35c336a3 (diff)
downloadcmake-297c63fa65327491a2b50e521b661c5835a19fe4.zip
cmake-297c63fa65327491a2b50e521b661c5835a19fe4.tar.gz
cmake-297c63fa65327491a2b50e521b661c5835a19fe4.tar.bz2
Imported Upstream version 2.8.11.2upstream/2.8.11.2sandbox/pcoval/previous/upstream
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt31
-rw-r--r--Source/CMakeVersion.cmake4
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx571
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.h101
-rw-r--r--Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx137
-rw-r--r--Source/CPack/WiX/cmWIXRichTextFormatWriter.h46
-rw-r--r--Source/CPack/WiX/cmWIXSourceWriter.cxx189
-rw-r--r--Source/CPack/WiX/cmWIXSourceWriter.h67
-rw-r--r--Source/CPack/cmCPackComponentGroup.h4
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx20
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx17
-rw-r--r--Source/CPack/cmCPackGenerator.cxx6
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.cxx17
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx80
-rw-r--r--Source/CPack/cmCPackNSISGenerator.h7
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.cxx126
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.h3
-rw-r--r--Source/CPack/cmCPackRPMGenerator.cxx12
-rw-r--r--Source/CPack/cpack.cxx8
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx24
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.h1
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx9
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx15
-rw-r--r--Source/CTest/cmCTestGIT.cxx4
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx2
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx7
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx3
-rw-r--r--Source/CursesDialog/cmCursesStringWidget.cxx2
-rw-r--r--Source/QtDialog/CMakeLists.txt2
-rw-r--r--Source/QtDialog/QCMakeCacheView.cxx6
-rw-r--r--Source/cmAddCustomCommandCommand.h5
-rw-r--r--Source/cmAddDependenciesCommand.cxx12
-rw-r--r--Source/cmAddLibraryCommand.h4
-rw-r--r--Source/cmAddSubDirectoryCommand.cxx15
-rw-r--r--Source/cmBootstrapCommands.cxx1
-rw-r--r--Source/cmBuildCommand.cxx8
-rw-r--r--Source/cmCTest.cxx5
-rw-r--r--Source/cmCTest.h2
-rw-r--r--Source/cmCacheManager.cxx24
-rw-r--r--Source/cmCommandArgumentParser.cxx4
-rw-r--r--Source/cmCommands.cxx5
-rw-r--r--Source/cmComputeLinkDepends.cxx11
-rw-r--r--Source/cmComputeLinkDepends.h3
-rw-r--r--Source/cmComputeLinkInformation.cxx105
-rw-r--r--Source/cmComputeLinkInformation.h5
-rw-r--r--Source/cmComputeTargetDepends.cxx98
-rw-r--r--Source/cmComputeTargetDepends.h6
-rw-r--r--Source/cmConfigureFileCommand.h22
-rw-r--r--Source/cmCoreTryCompile.cxx109
-rw-r--r--Source/cmCryptoHash.cxx6
-rw-r--r--Source/cmCustomCommandGenerator.cxx4
-rw-r--r--Source/cmDepends.cxx19
-rw-r--r--Source/cmDepends.h6
-rw-r--r--Source/cmDependsC.cxx243
-rw-r--r--Source/cmDependsC.h7
-rw-r--r--Source/cmDependsFortran.cxx52
-rw-r--r--Source/cmDependsFortran.h2
-rw-r--r--Source/cmDependsJava.cxx6
-rw-r--r--Source/cmDependsJava.h3
-rw-r--r--Source/cmDocumentGeneratorExpressions.h27
-rw-r--r--Source/cmDocumentVariables.cxx81
-rw-r--r--Source/cmEnableLanguageCommand.h7
-rw-r--r--Source/cmExportBuildFileGenerator.cxx52
-rw-r--r--Source/cmExportBuildFileGenerator.h3
-rw-r--r--Source/cmExportFileGenerator.cxx663
-rw-r--r--Source/cmExportFileGenerator.h56
-rw-r--r--Source/cmExportInstallFileGenerator.cxx171
-rw-r--r--Source/cmExportInstallFileGenerator.h11
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx114
-rw-r--r--Source/cmExportTryCompileFileGenerator.h55
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx11
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx25
-rw-r--r--Source/cmExtraEclipseCDT4Generator.h1
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx503
-rw-r--r--Source/cmExtraSublimeTextGenerator.h89
-rw-r--r--Source/cmFLTKWrapUICommand.cxx6
-rw-r--r--Source/cmFileCommand.cxx75
-rw-r--r--Source/cmFileCommand.h12
-rw-r--r--Source/cmFindBase.cxx19
-rw-r--r--Source/cmFindBase.h2
-rw-r--r--Source/cmFindLibraryCommand.cxx197
-rw-r--r--Source/cmFindLibraryCommand.h4
-rw-r--r--Source/cmFindPackageCommand.cxx3
-rw-r--r--Source/cmFindPathCommand.cxx6
-rw-r--r--Source/cmFunctionCommand.h4
-rw-r--r--Source/cmGeneratorExpression.cxx315
-rw-r--r--Source/cmGeneratorExpression.h66
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx80
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h19
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx517
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h18
-rw-r--r--Source/cmGeneratorExpressionParser.cxx10
-rw-r--r--Source/cmGeneratorTarget.cxx107
-rw-r--r--Source/cmGeneratorTarget.h8
-rw-r--r--Source/cmGetFilenameComponentCommand.h19
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx4
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.h7
-rw-r--r--Source/cmGlobalGenerator.cxx77
-rw-r--r--Source/cmGlobalGenerator.h6
-rw-r--r--Source/cmGlobalGeneratorFactory.h59
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.cxx4
-rw-r--r--Source/cmGlobalJOMMakefileGenerator.h7
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.cxx4
-rw-r--r--Source/cmGlobalMSYSMakefileGenerator.h7
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.cxx32
-rw-r--r--Source/cmGlobalMinGWMakefileGenerator.h7
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.cxx4
-rw-r--r--Source/cmGlobalNMakeMakefileGenerator.h7
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx76
-rw-r--r--Source/cmGlobalNinjaGenerator.h7
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx4
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h8
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx88
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h16
-rw-r--r--Source/cmGlobalVisualStudio10IA64Generator.cxx50
-rw-r--r--Source/cmGlobalVisualStudio10IA64Generator.h40
-rw-r--r--Source/cmGlobalVisualStudio10Win64Generator.cxx50
-rw-r--r--Source/cmGlobalVisualStudio10Win64Generator.h40
-rw-r--r--Source/cmGlobalVisualStudio11ARMGenerator.cxx29
-rw-r--r--Source/cmGlobalVisualStudio11ARMGenerator.h35
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx74
-rw-r--r--Source/cmGlobalVisualStudio11Generator.h17
-rw-r--r--Source/cmGlobalVisualStudio11Win64Generator.cxx37
-rw-r--r--Source/cmGlobalVisualStudio11Win64Generator.h37
-rw-r--r--Source/cmGlobalVisualStudio12Generator.cxx111
-rw-r--r--Source/cmGlobalVisualStudio12Generator.h40
-rw-r--r--Source/cmGlobalVisualStudio6Generator.cxx8
-rw-r--r--Source/cmGlobalVisualStudio6Generator.h8
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx29
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h16
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx137
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h22
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx143
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h36
-rw-r--r--Source/cmGlobalVisualStudio8Win64Generator.cxx40
-rw-r--r--Source/cmGlobalVisualStudio8Win64Generator.h47
-rw-r--r--Source/cmGlobalVisualStudio9Generator.cxx99
-rw-r--r--Source/cmGlobalVisualStudio9Generator.h17
-rw-r--r--Source/cmGlobalVisualStudio9IA64Generator.cxx37
-rw-r--r--Source/cmGlobalVisualStudio9IA64Generator.h47
-rw-r--r--Source/cmGlobalVisualStudio9Win64Generator.cxx37
-rw-r--r--Source/cmGlobalVisualStudio9Win64Generator.h47
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx22
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h9
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.cxx4
-rw-r--r--Source/cmGlobalWatcomWMakeGenerator.h6
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx204
-rw-r--r--Source/cmGlobalXCodeGenerator.h8
-rw-r--r--Source/cmGraphVizWriter.cxx4
-rw-r--r--Source/cmIDEOptions.cxx11
-rw-r--r--Source/cmIDEOptions.h1
-rw-r--r--Source/cmIncludeDirectoryCommand.cxx97
-rw-r--r--Source/cmIncludeDirectoryCommand.h13
-rw-r--r--Source/cmInstallExportGenerator.h2
-rw-r--r--Source/cmInstallTargetGenerator.cxx30
-rw-r--r--Source/cmInstallTargetGenerator.h5
-rw-r--r--Source/cmLinkDirectoriesCommand.h6
-rw-r--r--Source/cmListCommand.cxx36
-rw-r--r--Source/cmListFileCache.h9
-rw-r--r--Source/cmLocalGenerator.cxx52
-rw-r--r--Source/cmLocalGenerator.h18
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx37
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h3
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx35
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx85
-rw-r--r--Source/cmLocalVisualStudio7Generator.h3
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx1
-rw-r--r--Source/cmLocalVisualStudioGenerator.h3
-rw-r--r--Source/cmMacroCommand.h8
-rw-r--r--Source/cmMakefile.cxx252
-rw-r--r--Source/cmMakefile.h22
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx2
-rw-r--r--Source/cmMakefileTargetGenerator.cxx48
-rw-r--r--Source/cmMathCommand.h4
-rw-r--r--Source/cmMessageCommand.h5
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx6
-rw-r--r--Source/cmNinjaTargetGenerator.cxx28
-rw-r--r--Source/cmPolicies.cxx40
-rw-r--r--Source/cmPolicies.h2
-rw-r--r--Source/cmQtAutomoc.cxx216
-rw-r--r--Source/cmQtAutomoc.h13
-rw-r--r--Source/cmSetTargetPropertiesCommand.h4
-rw-r--r--Source/cmSourceFile.cxx2
-rw-r--r--Source/cmSourceGroup.cxx9
-rw-r--r--Source/cmSourceGroupCommand.h2
-rw-r--r--Source/cmStringCommand.cxx54
-rw-r--r--Source/cmStringCommand.h41
-rw-r--r--Source/cmSystemTools.cxx56
-rw-r--r--Source/cmTarget.cxx1426
-rw-r--r--Source/cmTarget.h92
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.cxx66
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.h88
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.cxx74
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.h93
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx2
-rw-r--r--Source/cmTargetLinkLibrariesCommand.h27
-rw-r--r--Source/cmTargetPropCommandBase.cxx144
-rw-r--r--Source/cmTargetPropCommandBase.h55
-rw-r--r--Source/cmTestGenerator.cxx4
-rw-r--r--Source/cmTimestamp.cxx134
-rw-r--r--Source/cmTimestamp.h40
-rw-r--r--Source/cmTryCompileCommand.h8
-rw-r--r--Source/cmTryRunCommand.h2
-rw-r--r--Source/cmVS10LinkFlagTable.h6
-rw-r--r--Source/cmVS12CLFlagTable.h297
-rw-r--r--Source/cmVS12LibFlagTable.h102
-rw-r--r--Source/cmVS12LinkFlagTable.h343
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx224
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h3
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx1
-rw-r--r--Source/cmVisualStudioWCEPlatformParser.cxx175
-rw-r--r--Source/cmVisualStudioWCEPlatformParser.h68
-rw-r--r--Source/cmWin32ProcessExecution.cxx56
-rw-r--r--Source/cmXCodeObject.cxx1
-rw-r--r--Source/cmXCodeObject.h9
-rw-r--r--Source/cmake.cxx299
-rw-r--r--Source/cmake.h28
-rw-r--r--Source/cmakemain.cxx8
-rw-r--r--Source/cmcldeps.cxx4
-rwxr-xr-xSource/cmparseMSBuildXML.py3
-rw-r--r--Source/cmw9xcom.cxx10
-rw-r--r--Source/ctest.cxx6
-rw-r--r--Source/kwsys/CMakeLists.txt186
-rw-r--r--Source/kwsys/CPU.h.in8
-rw-r--r--Source/kwsys/CTestConfig.cmake11
-rw-r--r--Source/kwsys/Configure.h.in14
-rw-r--r--Source/kwsys/DynamicLoader.cxx52
-rw-r--r--Source/kwsys/EncodeExecutable.c114
-rw-r--r--Source/kwsys/Glob.cxx2
-rw-r--r--Source/kwsys/IOStream.cxx1
-rw-r--r--Source/kwsys/IOStream.hxx.in6
-rw-r--r--Source/kwsys/ProcessFwd9x.c211
-rw-r--r--Source/kwsys/ProcessUNIX.c18
-rw-r--r--Source/kwsys/ProcessWin32.c287
-rw-r--r--Source/kwsys/Registry.cxx818
-rw-r--r--Source/kwsys/Registry.hxx.in107
-rw-r--r--Source/kwsys/SystemInformation.cxx3095
-rw-r--r--Source/kwsys/SystemInformation.hxx.in87
-rw-r--r--Source/kwsys/SystemTools.cxx78
-rw-r--r--Source/kwsys/SystemTools.hxx.in9
-rw-r--r--Source/kwsys/kwsysPlatformTestsCXX.cxx93
-rw-r--r--Source/kwsys/testCommandLineArguments.cxx16
-rw-r--r--Source/kwsys/testDynamicLoader.cxx4
-rw-r--r--Source/kwsys/testProcess.c39
-rw-r--r--Source/kwsys/testRegistry.cxx109
-rw-r--r--Source/kwsys/testSystemInformation.cxx44
-rw-r--r--Source/kwsys/testSystemTools.cxx26
247 files changed, 12950 insertions, 5324 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 8bf6c40..f0519fe 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -176,6 +176,8 @@ set(SRCS
cmExportFileGenerator.cxx
cmExportInstallFileGenerator.h
cmExportInstallFileGenerator.cxx
+ cmExportTryCompileFileGenerator.h
+ cmExportTryCompileFileGenerator.cxx
cmExportSet.h
cmExportSet.cxx
cmExportSetMap.h
@@ -184,6 +186,8 @@ set(SRCS
cmExtraCodeBlocksGenerator.h
cmExtraEclipseCDT4Generator.cxx
cmExtraEclipseCDT4Generator.h
+ cmExtraSublimeTextGenerator.cxx
+ cmExtraSublimeTextGenerator.h
cmFileTimeComparison.cxx
cmFileTimeComparison.h
cmGeneratedFileStream.cxx
@@ -201,6 +205,7 @@ set(SRCS
cmGeneratorTarget.h
cmGlobalGenerator.cxx
cmGlobalGenerator.h
+ cmGlobalGeneratorFactory.h
cmGlobalUnixMakefileGenerator3.cxx
cmGlobalUnixMakefileGenerator3.h
cmGraphAdjacencyList.h
@@ -330,12 +335,6 @@ if (WIN32)
cmGlobalVisualStudio8Generator.h
cmGlobalVisualStudio9Generator.cxx
cmGlobalVisualStudio9Generator.h
- cmGlobalVisualStudio8Win64Generator.cxx
- cmGlobalVisualStudio8Win64Generator.h
- cmGlobalVisualStudio9Win64Generator.cxx
- cmGlobalVisualStudio9Win64Generator.h
- cmGlobalVisualStudio9IA64Generator.cxx
- cmGlobalVisualStudio9IA64Generator.h
cmVisualStudioGeneratorOptions.h
cmVisualStudioGeneratorOptions.cxx
cmVisualStudio10TargetGenerator.h
@@ -344,16 +343,10 @@ if (WIN32)
cmLocalVisualStudio10Generator.h
cmGlobalVisualStudio10Generator.h
cmGlobalVisualStudio10Generator.cxx
- cmGlobalVisualStudio10Win64Generator.h
- cmGlobalVisualStudio10Win64Generator.cxx
- cmGlobalVisualStudio10IA64Generator.h
- cmGlobalVisualStudio10IA64Generator.cxx
cmGlobalVisualStudio11Generator.h
cmGlobalVisualStudio11Generator.cxx
- cmGlobalVisualStudio11Win64Generator.h
- cmGlobalVisualStudio11Win64Generator.cxx
- cmGlobalVisualStudio11ARMGenerator.h
- cmGlobalVisualStudio11ARMGenerator.cxx
+ cmGlobalVisualStudio12Generator.h
+ cmGlobalVisualStudio12Generator.cxx
cmGlobalVisualStudioGenerator.cxx
cmGlobalVisualStudioGenerator.h
cmGlobalWatcomWMakeGenerator.cxx
@@ -366,6 +359,8 @@ if (WIN32)
cmLocalVisualStudio7Generator.h
cmLocalVisualStudioGenerator.cxx
cmLocalVisualStudioGenerator.h
+ cmVisualStudioWCEPlatformParser.h
+ cmVisualStudioWCEPlatformParser.cxx
cmWin32ProcessExecution.cxx
cmWin32ProcessExecution.h
)
@@ -510,6 +505,14 @@ if(UNIX)
)
endif()
+if(WIN32)
+ set(CPACK_SRCS ${CPACK_SRCS}
+ CPack/WiX/cmCPackWIXGenerator.cxx
+ CPack/WiX/cmWIXSourceWriter.cxx
+ CPack/WiX/cmWIXRichTextFormatWriter.cxx
+ )
+endif()
+
if(APPLE)
set(CPACK_SRCS ${CPACK_SRCS}
CPack/cmCPackBundleGenerator.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index c59c618..a8b8907 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 10)
+set(CMake_VERSION_PATCH 11)
set(CMake_VERSION_TWEAK 2)
-#set(CMake_VERSION_RC 3)
+#set(CMake_VERSION_RC 0)
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
new file mode 100644
index 0000000..e8b0ea9
--- /dev/null
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -0,0 +1,571 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2012 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 "cmCPackWIXGenerator.h"
+
+#include <cmSystemTools.h>
+#include <cmGeneratedFileStream.h>
+#include <CPack/cmCPackLog.h>
+#include <CPack/cmCPackComponentGroup.h>
+
+#include "cmWIXSourceWriter.h"
+#include "cmWIXRichTextFormatWriter.h"
+
+#include <cmsys/SystemTools.hxx>
+#include <cmsys/Directory.hxx>
+
+#include <rpc.h> // for GUID generation
+
+int cmCPackWIXGenerator::InitializeInternal()
+{
+ componentPackageMethod = ONE_PACKAGE;
+
+ return this->Superclass::InitializeInternal();
+}
+
+bool cmCPackWIXGenerator::RunWiXCommand(const std::string& command)
+{
+ std::string cpackTopLevel;
+ if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
+ {
+ return false;
+ }
+
+ std::string logFileName = cpackTopLevel + "/wix.log";
+
+ cmCPackLogger(cmCPackLog::LOG_DEBUG,
+ "Running WiX command: " << command << std::endl);
+
+ std::string output;
+
+ int returnValue = 0;
+ bool status = cmSystemTools::RunSingleCommand(command.c_str(), &output,
+ &returnValue, 0, cmSystemTools::OUTPUT_NONE);
+
+ std::ofstream logFile(logFileName.c_str(), std::ios::app);
+ logFile << command << std::endl;
+ logFile << output;
+ logFile.close();
+
+ if(!status || returnValue)
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem running WiX candle. "
+ "Please check '" << logFileName << "' for errors." << std::endl);
+
+ return false;
+ }
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::RunCandleCommand(
+ const std::string& sourceFile, const std::string& objectFile)
+{
+ std::string executable;
+ if(!RequireOption("CPACK_WIX_CANDLE_EXECUTABLE", executable))
+ {
+ return false;
+ }
+
+ std::stringstream command;
+ command << QuotePath(executable);
+ command << " -nologo";
+ command << " -arch " << GetArchitecture();
+ command << " -out " << QuotePath(objectFile);
+ command << " " << QuotePath(sourceFile);
+
+ return RunWiXCommand(command.str());
+}
+
+bool cmCPackWIXGenerator::RunLightCommand(const std::string& objectFiles)
+{
+ std::string executable;
+ if(!RequireOption("CPACK_WIX_LIGHT_EXECUTABLE", executable))
+ {
+ return false;
+ }
+
+ std::stringstream command;
+ command << QuotePath(executable);
+ command << " -nologo";
+ command << " -out " << QuotePath(packageFileNames.at(0));
+ command << " -ext WixUIExtension";
+ command << " " << objectFiles;
+
+ return RunWiXCommand(command.str());
+}
+
+int cmCPackWIXGenerator::PackageFiles()
+{
+ if(!PackageFilesImpl() || cmSystemTools::GetErrorOccuredFlag())
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Fatal WiX Generator Error" << std::endl);
+ return false;
+ }
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::InitializeWiXConfiguration()
+{
+ if(!ReadListFile("CPackWIX.cmake"))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Error while executing CPackWIX.cmake" << std::endl);
+ return false;
+ }
+
+ if(GetOption("CPACK_WIX_PRODUCT_GUID") == 0)
+ {
+ std::string guid = GenerateGUID();
+ SetOption("CPACK_WIX_PRODUCT_GUID", guid.c_str());
+
+ cmCPackLogger(cmCPackLog::LOG_VERBOSE,
+ "CPACK_WIX_PRODUCT_GUID implicitly set to " << guid << " . "
+ << std::endl);
+ }
+
+ if(GetOption("CPACK_WIX_UPGRADE_GUID") == 0)
+ {
+ std::string guid = GenerateGUID();
+ SetOption("CPACK_WIX_UPGRADE_GUID", guid.c_str());
+
+ cmCPackLogger(cmCPackLog::LOG_WARNING,
+ "CPACK_WIX_UPGRADE_GUID implicitly set to " << guid << " . "
+ "Please refer to the documentation on how and why "
+ "you might want to set this explicitly." << std::endl);
+ }
+
+ std::string cpackTopLevel;
+ if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
+ {
+ return false;
+ }
+
+ if(GetOption("CPACK_WIX_LICENSE_RTF") == 0)
+ {
+ std::string licenseFilename = cpackTopLevel + "/License.rtf";
+ SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename.c_str());
+
+ if(!CreateLicenseFile())
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::PackageFilesImpl()
+{
+ if(!InitializeWiXConfiguration())
+ {
+ return false;
+ }
+
+ if(!CreateWiXVariablesIncludeFile())
+ {
+ return false;
+ }
+
+ if(!CreateWiXSourceFiles())
+ {
+ return false;
+ }
+
+ std::stringstream objectFiles;
+ for(size_t i = 0; i < wixSources.size(); ++i)
+ {
+ const std::string& sourceFilename = wixSources[i];
+
+ std::string objectFilename =
+ cmSystemTools::GetFilenameWithoutExtension(sourceFilename) + ".wixobj";
+
+ if(!RunCandleCommand(sourceFilename, objectFilename))
+ {
+ return false;
+ }
+
+ objectFiles << " " << QuotePath(objectFilename);
+ }
+
+ return RunLightCommand(objectFiles.str());
+}
+
+bool cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
+{
+ std::string cpackTopLevel;
+ if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
+ {
+ return false;
+ }
+
+ std::string includeFilename =
+ cpackTopLevel + "/cpack_variables.wxi";
+
+ cmWIXSourceWriter includeFile(Logger, includeFilename, true);
+ CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_GUID");
+ CopyDefinition(includeFile, "CPACK_WIX_UPGRADE_GUID");
+ CopyDefinition(includeFile, "CPACK_PACKAGE_VENDOR");
+ CopyDefinition(includeFile, "CPACK_PACKAGE_NAME");
+ CopyDefinition(includeFile, "CPACK_PACKAGE_VERSION");
+ CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF");
+ CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON");
+ CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER");
+ CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG");
+
+ return true;
+}
+
+void cmCPackWIXGenerator::CopyDefinition(
+ cmWIXSourceWriter &source, const std::string &name)
+{
+ const char* value = GetOption(name.c_str());
+ if(value)
+ {
+ AddDefinition(source, name, value);
+ }
+}
+
+void cmCPackWIXGenerator::AddDefinition(cmWIXSourceWriter& source,
+ const std::string& name, const std::string& value)
+{
+ std::stringstream tmp;
+ tmp << name << "=\"" << value << '"';
+
+ source.AddProcessingInstruction("define",
+ cmWIXSourceWriter::WindowsCodepageToUtf8(tmp.str()));
+}
+
+bool cmCPackWIXGenerator::CreateWiXSourceFiles()
+{
+ std::string cpackTopLevel;
+ if(!RequireOption("CPACK_TOPLEVEL_DIRECTORY", cpackTopLevel))
+ {
+ return false;
+ }
+
+ std::string directoryDefinitionsFilename =
+ cpackTopLevel + "/directories.wxs";
+
+ wixSources.push_back(directoryDefinitionsFilename);
+
+ cmWIXSourceWriter directoryDefinitions(Logger, directoryDefinitionsFilename);
+ directoryDefinitions.BeginElement("Fragment");
+
+ directoryDefinitions.BeginElement("Directory");
+ directoryDefinitions.AddAttribute("Id", "TARGETDIR");
+ directoryDefinitions.AddAttribute("Name", "SourceDir");
+
+ directoryDefinitions.BeginElement("Directory");
+ if(GetArchitecture() == "x86")
+ {
+ directoryDefinitions.AddAttribute("Id", "ProgramFilesFolder");
+ }
+ else
+ {
+ directoryDefinitions.AddAttribute("Id", "ProgramFiles64Folder");
+ }
+
+ std::vector<std::string> install_root;
+
+ std::string tmp;
+ if(!RequireOption("CPACK_PACKAGE_INSTALL_DIRECTORY", tmp))
+ {
+ return false;
+ }
+
+ cmSystemTools::SplitPath(tmp.c_str(), install_root);
+
+ if(!install_root.empty() && install_root.back().empty())
+ {
+ install_root.pop_back();
+ }
+
+ for(size_t i = 1; i < install_root.size(); ++i)
+ {
+ directoryDefinitions.BeginElement("Directory");
+
+ if(i == install_root.size() - 1)
+ {
+ directoryDefinitions.AddAttribute("Id", "INSTALL_ROOT");
+ }
+ else
+ {
+ std::stringstream ss;
+ ss << "INSTALL_PREFIX_" << i;
+ directoryDefinitions.AddAttribute("Id", ss.str());
+ }
+
+ directoryDefinitions.AddAttribute("Name", install_root[i]);
+ }
+
+ size_t directoryCounter = 0;
+ size_t fileCounter = 0;
+
+ std::string fileDefinitionsFilename =
+ cpackTopLevel + "/files.wxs";
+
+ wixSources.push_back(fileDefinitionsFilename);
+
+ cmWIXSourceWriter fileDefinitions(Logger, fileDefinitionsFilename);
+ fileDefinitions.BeginElement("Fragment");
+
+ std::string featureDefinitionsFilename =
+ cpackTopLevel +"/features.wxs";
+
+ wixSources.push_back(featureDefinitionsFilename);
+
+ cmWIXSourceWriter featureDefinitions(Logger, featureDefinitionsFilename);
+ featureDefinitions.BeginElement("Fragment");
+
+ featureDefinitions.BeginElement("Feature");
+ featureDefinitions.AddAttribute("Id", "ProductFeature");
+ featureDefinitions.AddAttribute("Title", Name);
+ featureDefinitions.AddAttribute("Level", "1");
+ featureDefinitions.EndElement();
+
+ featureDefinitions.BeginElement("FeatureRef");
+ featureDefinitions.AddAttribute("Id", "ProductFeature");
+
+ AddDirectoryAndFileDefinitons(
+ toplevel, "INSTALL_ROOT",
+ directoryDefinitions, fileDefinitions, featureDefinitions,
+ directoryCounter, fileCounter);
+
+ featureDefinitions.EndElement();
+ featureDefinitions.EndElement();
+ fileDefinitions.EndElement();
+
+ for(size_t i = 1; i < install_root.size(); ++i)
+ {
+ directoryDefinitions.EndElement();
+ }
+
+ directoryDefinitions.EndElement();
+ directoryDefinitions.EndElement();
+ directoryDefinitions.EndElement();
+
+ std::string wixTemplate = FindTemplate("WIX.template.in");
+ if(wixTemplate.empty())
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Could not find CPack WiX template file WIX.template.in" << std::endl);
+ return false;
+ }
+
+ std::string mainSourceFilePath = cpackTopLevel + "/main.wxs";
+
+ if(!ConfigureFile(wixTemplate.c_str(), mainSourceFilePath .c_str()))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed creating '" << mainSourceFilePath <<
+ "'' from template." << std::endl);
+
+ return false;
+ }
+
+ wixSources.push_back(mainSourceFilePath);
+
+ return true;
+}
+
+bool cmCPackWIXGenerator::CreateLicenseFile()
+{
+ std::string licenseSourceFilename;
+ if(!RequireOption("CPACK_RESOURCE_FILE_LICENSE", licenseSourceFilename))
+ {
+ return false;
+ }
+
+ std::string licenseDestinationFilename;
+ if(!RequireOption("CPACK_WIX_LICENSE_RTF", licenseDestinationFilename))
+ {
+ return false;
+ }
+
+ std::string extension = GetRightmostExtension(licenseSourceFilename);
+
+ if(extension == ".rtf")
+ {
+ cmSystemTools::CopyAFile(
+ licenseSourceFilename.c_str(),
+ licenseDestinationFilename.c_str());
+ }
+ else if(extension == ".txt")
+ {
+ cmWIXRichTextFormatWriter rtfWriter(licenseDestinationFilename);
+
+ std::ifstream licenseSource(licenseSourceFilename.c_str());
+
+ std::string line;
+ while(std::getline(licenseSource, line))
+ {
+ rtfWriter.AddText(line);
+ rtfWriter.AddText("\n");
+ }
+ }
+ else
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "unsupported WiX License file extension '" <<
+ extension << "'" << std::endl);
+
+ return false;
+ }
+
+ return true;
+}
+
+void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
+ const std::string& topdir,
+ const std::string& directoryId,
+ cmWIXSourceWriter& directoryDefinitions,
+ cmWIXSourceWriter& fileDefinitions,
+ cmWIXSourceWriter& featureDefinitions,
+ size_t& directoryCounter,
+ size_t& fileCounter)
+{
+ cmsys::Directory dir;
+ dir.Load(topdir.c_str());
+
+ for(size_t i = 0; i < dir.GetNumberOfFiles(); ++i)
+ {
+ std::string fileName = dir.GetFile(static_cast<unsigned long>(i));
+
+ if(fileName == "." || fileName == "..")
+ {
+ continue;
+ }
+
+ std::string fullPath = topdir + "/" + fileName;
+
+ if(cmSystemTools::FileIsDirectory(fullPath.c_str()))
+ {
+ std::stringstream tmp;
+ tmp << "DIR_ID_" << ++directoryCounter;
+ std::string subDirectoryId = tmp.str();
+
+ directoryDefinitions.BeginElement("Directory");
+ directoryDefinitions.AddAttribute("Id", subDirectoryId);
+ directoryDefinitions.AddAttribute("Name", fileName);
+
+ AddDirectoryAndFileDefinitons(
+ fullPath, subDirectoryId,
+ directoryDefinitions,
+ fileDefinitions,
+ featureDefinitions,
+ directoryCounter,
+ fileCounter);
+
+ directoryDefinitions.EndElement();
+ }
+ else
+ {
+ std::stringstream tmp;
+ tmp << "_ID_" << ++fileCounter;
+ std::string idSuffix = tmp.str();
+
+ std::string componentId = std::string("CMP") + idSuffix;
+ std::string fileId = std::string("FILE") + idSuffix;
+
+ fileDefinitions.BeginElement("DirectoryRef");
+ fileDefinitions.AddAttribute("Id", directoryId);
+
+ fileDefinitions.BeginElement("Component");
+ fileDefinitions.AddAttribute("Id", componentId);
+ fileDefinitions.AddAttribute("Guid", "*");
+
+ fileDefinitions.BeginElement("File");
+ fileDefinitions.AddAttribute("Id", fileId);
+ fileDefinitions.AddAttribute("Source", fullPath);
+ fileDefinitions.AddAttribute("KeyPath", "yes");
+
+ fileDefinitions.EndElement();
+ fileDefinitions.EndElement();
+ fileDefinitions.EndElement();
+
+ featureDefinitions.BeginElement("ComponentRef");
+ featureDefinitions.AddAttribute("Id", componentId);
+ featureDefinitions.EndElement();
+ }
+ }
+}
+
+bool cmCPackWIXGenerator::RequireOption(
+ const std::string& name, std::string &value) const
+{
+ const char* tmp = GetOption(name.c_str());
+ if(tmp)
+ {
+ value = tmp;
+
+ return true;
+ }
+ else
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Required variable " << name << " not set" << std::endl);
+
+ return false;
+ }
+}
+
+std::string cmCPackWIXGenerator::GetArchitecture() const
+{
+ std::string void_p_size;
+ RequireOption("CPACK_WIX_SIZEOF_VOID_P", void_p_size);
+
+ if(void_p_size == "8")
+ {
+ return "x64";
+ }
+ else
+ {
+ return "x86";
+ }
+}
+
+std::string cmCPackWIXGenerator::GenerateGUID()
+{
+ UUID guid;
+ UuidCreate(&guid);
+
+ unsigned char *tmp = 0;
+ UuidToString(&guid, &tmp);
+
+ std::string result(reinterpret_cast<char*>(tmp));
+ RpcStringFree(&tmp);
+
+ return cmSystemTools::UpperCase(result);
+}
+
+std::string cmCPackWIXGenerator::QuotePath(const std::string& path)
+{
+ return std::string("\"") + path + '"';
+}
+
+std::string cmCPackWIXGenerator::GetRightmostExtension(
+ const std::string& filename)
+{
+ std::string extension;
+
+ std::string::size_type i = filename.rfind(".");
+ if(i != std::string::npos)
+ {
+ extension = filename.substr(i);
+ }
+
+ return cmSystemTools::LowerCase(extension);
+}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
new file mode 100644
index 0000000..0e95d70
--- /dev/null
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -0,0 +1,101 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2012 Kitware, Inc.
+
+ 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 cmCPackWIXGenerator_h
+#define cmCPackWIXGenerator_h
+
+#include <CPack/cmCPackGenerator.h>
+
+#include <string>
+#include <map>
+
+class cmWIXSourceWriter;
+
+/** \class cmCPackWIXGenerator
+ * \brief A generator for WIX files
+ */
+class cmCPackWIXGenerator : public cmCPackGenerator
+{
+public:
+ cmCPackTypeMacro(cmCPackWIXGenerator, cmCPackGenerator);
+
+protected:
+ virtual int InitializeInternal();
+
+ virtual int PackageFiles();
+
+ virtual const char* GetOutputExtension()
+ {
+ return ".msi";
+ }
+
+ virtual enum CPackSetDestdirSupport SupportsSetDestdir() const
+ {
+ return SETDESTDIR_UNSUPPORTED;
+ }
+
+ virtual bool SupportsAbsoluteDestination() const
+ {
+ return false;
+ }
+
+ virtual bool SupportsComponentInstallation() const
+ {
+ return false;
+ }
+
+private:
+ bool InitializeWiXConfiguration();
+
+ bool PackageFilesImpl();
+
+ bool CreateWiXVariablesIncludeFile();
+
+ void CopyDefinition(
+ cmWIXSourceWriter &source, const std::string &name);
+
+ void AddDefinition(cmWIXSourceWriter& source,
+ const std::string& name, const std::string& value);
+
+ bool CreateWiXSourceFiles();
+
+ bool CreateLicenseFile();
+
+ bool RunWiXCommand(const std::string& command);
+
+ bool RunCandleCommand(
+ const std::string& sourceFile, const std::string& objectFile);
+
+ bool RunLightCommand(const std::string& objectFiles);
+
+ void AddDirectoryAndFileDefinitons(const std::string& topdir,
+ const std::string& directoryId,
+ cmWIXSourceWriter& directoryDefinitions,
+ cmWIXSourceWriter& fileDefinitions,
+ cmWIXSourceWriter& featureDefinitions,
+ size_t& directoryCounter,
+ size_t& fileCounter);
+
+ bool RequireOption(const std::string& name, std::string& value) const;
+
+ std::string GetArchitecture() const;
+
+ static std::string GenerateGUID();
+
+ static std::string QuotePath(const std::string& path);
+
+ static std::string GetRightmostExtension(const std::string& filename);
+
+ std::vector<std::string> wixSources;
+};
+
+#endif
diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
new file mode 100644
index 0000000..774c22c
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.cxx
@@ -0,0 +1,137 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2012 Kitware, Inc.
+
+ 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 "cmWIXRichTextFormatWriter.h"
+
+#include <cmVersion.h>
+
+cmWIXRichTextFormatWriter::cmWIXRichTextFormatWriter(
+ const std::string& filename):
+ file(filename.c_str(), std::ios::binary)
+{
+ StartGroup();
+ WriteHeader();
+ WriteDocumentPrefix();
+}
+
+cmWIXRichTextFormatWriter::~cmWIXRichTextFormatWriter()
+{
+ EndGroup();
+
+ /* I haven't seen this in the RTF spec but
+ * wordpad terminates its RTF like this */
+ file << "\r\n";
+ file.put(0);
+}
+
+void cmWIXRichTextFormatWriter::AddText(const std::string& text)
+{
+ typedef unsigned char rtf_byte_t;
+
+ for(size_t i = 0; i < text.size(); ++i)
+ {
+ rtf_byte_t c = rtf_byte_t(text[i]);
+
+ switch(c)
+ {
+ case '\\':
+ file << "\\\\";
+ break;
+ case '{':
+ file << "\\{";
+ break;
+ case '}':
+ file << "\\}";
+ break;
+ case '\n':
+ file << "\\par\r\n";
+ break;
+ case '\r':
+ continue;
+ default:
+ {
+ if(c <= 0x7F)
+ {
+ file << c;
+ }
+ else
+ {
+ file << "[NON-ASCII-" << int(c) << "]";
+ }
+ }
+ break;
+ }
+ }
+}
+
+void cmWIXRichTextFormatWriter::WriteHeader()
+{
+ ControlWord("rtf1");
+ ControlWord("ansi");
+ ControlWord("ansicpg1252");
+ ControlWord("deff0");
+ ControlWord("deflang1031");
+
+ WriteFontTable();
+ WriteGenerator();
+}
+
+void cmWIXRichTextFormatWriter::WriteFontTable()
+{
+ StartGroup();
+ ControlWord("fonttbl");
+
+ StartGroup();
+ ControlWord("f0");
+ ControlWord("fswiss");
+ ControlWord("fcharset0 Arial;");
+ EndGroup();
+
+ EndGroup();
+}
+
+void cmWIXRichTextFormatWriter::WriteGenerator()
+{
+ StartGroup();
+ NewControlWord("generator");
+ file << " CPack WiX Generator (" << cmVersion::GetCMakeVersion() << ");";
+ EndGroup();
+}
+
+void cmWIXRichTextFormatWriter::WriteDocumentPrefix()
+{
+ ControlWord("viewkind4");
+ ControlWord("uc1");
+ ControlWord("pard");
+ ControlWord("f0");
+ ControlWord("fs20");
+}
+
+void cmWIXRichTextFormatWriter::ControlWord(const std::string& keyword)
+{
+ file << "\\" << keyword;
+}
+
+void cmWIXRichTextFormatWriter::NewControlWord(const std::string& keyword)
+{
+ file << "\\*\\" << keyword;
+}
+
+void cmWIXRichTextFormatWriter::StartGroup()
+{
+ file.put('{');
+}
+
+void cmWIXRichTextFormatWriter::EndGroup()
+{
+ file.put('}');
+}
diff --git a/Source/CPack/WiX/cmWIXRichTextFormatWriter.h b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
new file mode 100644
index 0000000..10b67c3
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXRichTextFormatWriter.h
@@ -0,0 +1,46 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2012 Kitware, Inc.
+
+ 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 cmWIXRichTextFormatWriter_h
+#define cmWIXRichTextFormatWriter_h
+
+#include <fstream>
+
+/** \class cmWIXRichtTextFormatWriter
+ * \brief Helper class to generate Rich Text Format (RTF) documents
+ * from plain text (e.g. for license and welcome text)
+ */
+class cmWIXRichTextFormatWriter
+{
+public:
+ cmWIXRichTextFormatWriter(const std::string& filename);
+ ~cmWIXRichTextFormatWriter();
+
+ void AddText(const std::string& text);
+
+private:
+ void WriteHeader();
+ void WriteFontTable();
+ void WriteGenerator();
+
+ void WriteDocumentPrefix();
+
+ void ControlWord(const std::string& keyword);
+ void NewControlWord(const std::string& keyword);
+
+ void StartGroup();
+ void EndGroup();
+
+ std::ofstream file;
+};
+
+#endif
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.cxx b/Source/CPack/WiX/cmWIXSourceWriter.cxx
new file mode 100644
index 0000000..af7ba80
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXSourceWriter.cxx
@@ -0,0 +1,189 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 Kitware, Inc.
+
+ 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 "cmWIXSourceWriter.h"
+
+#include <CPack/cmCPackGenerator.h>
+
+#include <windows.h>
+
+cmWIXSourceWriter::cmWIXSourceWriter(cmCPackLog* logger,
+ const std::string& filename,
+ bool isIncludeFile):
+ Logger(logger),
+ file(filename.c_str()),
+ state(DEFAULT)
+{
+ WriteXMLDeclaration();
+
+ if(isIncludeFile)
+ {
+ BeginElement("Include");
+ }
+ else
+ {
+ BeginElement("Wix");
+ }
+
+ AddAttribute("xmlns", "http://schemas.microsoft.com/wix/2006/wi");
+}
+
+cmWIXSourceWriter::~cmWIXSourceWriter()
+{
+ while(elements.size())
+ {
+ EndElement();
+ }
+}
+
+void cmWIXSourceWriter::BeginElement(const std::string& name)
+{
+ if(state == BEGIN)
+ {
+ file << ">";
+ }
+
+ file << "\n";
+ Indent(elements.size());
+ file << "<" << name;
+
+ elements.push_back(name);
+ state = BEGIN;
+}
+
+void cmWIXSourceWriter::EndElement()
+{
+ if(elements.empty())
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "can not end WiX element with no open elements" << std::endl);
+ return;
+ }
+
+ if(state == DEFAULT)
+ {
+ file << "\n";
+ Indent(elements.size()-1);
+ file << "</" << elements.back() << ">";
+ }
+ else
+ {
+ file << "/>";
+ }
+
+ elements.pop_back();
+ state = DEFAULT;
+}
+
+void cmWIXSourceWriter::AddProcessingInstruction(
+ const std::string& target, const std::string& content)
+{
+ if(state == BEGIN)
+ {
+ file << ">";
+ }
+
+ file << "\n";
+ Indent(elements.size());
+ file << "<?" << target << " " << content << "?>";
+
+ state = DEFAULT;
+}
+
+void cmWIXSourceWriter::AddAttribute(
+ const std::string& key, const std::string& value)
+{
+ std::string utf8 = WindowsCodepageToUtf8(value);
+
+ file << " " << key << "=\"" << EscapeAttributeValue(utf8) << '"';
+}
+
+std::string cmWIXSourceWriter::WindowsCodepageToUtf8(const std::string& value)
+{
+ if(value.empty())
+ {
+ return std::string();
+ }
+
+ int characterCount = MultiByteToWideChar(
+ CP_ACP, 0, value.c_str(), static_cast<int>(value.size()), 0, 0);
+
+ if(characterCount == 0)
+ {
+ return std::string();
+ }
+
+ std::vector<wchar_t> utf16(characterCount);
+
+ MultiByteToWideChar(
+ CP_ACP, 0, value.c_str(), static_cast<int>(value.size()),
+ &utf16[0], static_cast<int>(utf16.size()));
+
+ int utf8ByteCount = WideCharToMultiByte(
+ CP_UTF8, 0, &utf16[0], static_cast<int>(utf16.size()), 0, 0, 0, 0);
+
+ if(utf8ByteCount == 0)
+ {
+ return std::string();
+ }
+
+ std::vector<char> utf8(utf8ByteCount);
+
+ WideCharToMultiByte(CP_UTF8, 0, &utf16[0], static_cast<int>(utf16.size()),
+ &utf8[0], static_cast<int>(utf8.size()), 0, 0);
+
+ return std::string(&utf8[0], utf8.size());
+}
+
+
+void cmWIXSourceWriter::WriteXMLDeclaration()
+{
+ file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
+}
+
+void cmWIXSourceWriter::Indent(size_t count)
+{
+ for(size_t i = 0; i < count; ++i)
+ {
+ file << " ";
+ }
+}
+
+std::string cmWIXSourceWriter::EscapeAttributeValue(
+ const std::string& value)
+{
+ std::string result;
+ result.reserve(value.size());
+
+ char c = 0;
+ for(size_t i = 0 ; i < value.size(); ++i)
+ {
+ c = value[i];
+ switch(c)
+ {
+ case '<':
+ result += "&lt;";
+ break;
+ case '&':
+ result +="&amp;";
+ break;
+ case '"':
+ result += "&quot;";
+ break;
+ default:
+ result += c;
+ break;
+ }
+ }
+
+ return result;
+}
diff --git a/Source/CPack/WiX/cmWIXSourceWriter.h b/Source/CPack/WiX/cmWIXSourceWriter.h
new file mode 100644
index 0000000..1dafc1f
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXSourceWriter.h
@@ -0,0 +1,67 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 Kitware, Inc.
+
+ 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 cmWIXSourceWriter_h
+#define cmWIXSourceWriter_h
+
+#include <vector>
+#include <string>
+#include <fstream>
+
+#include <CPack/cmCPackLog.h>
+
+/** \class cmWIXSourceWriter
+ * \brief Helper class to generate XML WiX source files
+ */
+class cmWIXSourceWriter
+{
+public:
+ cmWIXSourceWriter(cmCPackLog* logger,
+ const std::string& filename, bool isIncludeFile = false);
+
+ ~cmWIXSourceWriter();
+
+ void BeginElement(const std::string& name);
+
+ void EndElement();
+
+ void AddProcessingInstruction(
+ const std::string& target, const std::string& content);
+
+ void AddAttribute(
+ const std::string& key, const std::string& value);
+
+ static std::string WindowsCodepageToUtf8(const std::string& value);
+
+private:
+ enum State
+ {
+ DEFAULT,
+ BEGIN
+ };
+
+ void WriteXMLDeclaration();
+
+ void Indent(size_t count);
+
+ static std::string EscapeAttributeValue(const std::string& value);
+
+ cmCPackLog* Logger;
+
+ std::ofstream file;
+
+ State state;
+
+ std::vector<std::string> elements;
+};
+
+#endif
diff --git a/Source/CPack/cmCPackComponentGroup.h b/Source/CPack/cmCPackComponentGroup.h
index 48d935c..abae372 100644
--- a/Source/CPack/cmCPackComponentGroup.h
+++ b/Source/CPack/cmCPackComponentGroup.h
@@ -42,7 +42,9 @@ public:
class cmCPackComponent
{
public:
- cmCPackComponent() : Group(0), TotalSize(0) { }
+ cmCPackComponent() : Group(0), IsRequired(true), IsHidden(false),
+ IsDisabledByDefault(false), IsDownloaded(false),
+ TotalSize(0) { }
/// The name of the component (used to reference the component).
std::string Name;
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 4bd5d5c..4494e8a 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -76,6 +76,11 @@ int cmCPackDebGenerator::PackageOnePack(std::string initialTopLevel,
packageFileName.c_str());
// Tell CPackDeb.cmake the name of the component GROUP.
this->SetOption("CPACK_DEB_PACKAGE_COMPONENT",packageName.c_str());
+ // Tell CPackDeb.cmake the path where the component is.
+ std::string component_path = "/";
+ component_path += packageName;
+ this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
+ component_path.c_str());
if (!this->ReadListFile("CPackDeb.cmake"))
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -198,8 +203,11 @@ int cmCPackDebGenerator::PackageComponentsAllInOne()
/* replace the TEMPORARY package file name */
this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
packageFileName.c_str());
- // Tell CPackDeb.cmake the name of the component GROUP.
- this->SetOption("CPACK_DEB_PACKAGE_COMPONENT",compInstDirName.c_str());
+ // Tell CPackDeb.cmake the path where the component is.
+ std::string component_path = "/";
+ component_path += compInstDirName;
+ this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
+ component_path.c_str());
if (!this->ReadListFile("CPackDeb.cmake"))
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -763,13 +771,13 @@ static int put_arobj(CF *cfp, struct stat *sb)
}
if (lname > sizeof(hdr->ar_name) || strchr(name, ' '))
(void)sprintf(ar_hb, HDR1, AR_EFMT1, (int)lname,
- (long int)sb->st_mtime, uid, gid, sb->st_mode,
- (long long)sb->st_size + lname, ARFMAG);
+ (long int)sb->st_mtime, (unsigned)uid, (unsigned)gid,
+ sb->st_mode, (long long)sb->st_size + lname, ARFMAG);
else {
lname = 0;
(void)sprintf(ar_hb, HDR2, name,
- (long int)sb->st_mtime, uid, gid, sb->st_mode,
- (long long)sb->st_size, ARFMAG);
+ (long int)sb->st_mtime, (unsigned)uid, (unsigned)gid,
+ sb->st_mode, (long long)sb->st_size, ARFMAG);
}
off_t size = sb->st_size;
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 78cb1b6..d973c01 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -442,7 +442,22 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
line.replace(pos, 1, "\\\"");
pos = line.find('\"', pos+2);
}
- osf << " \"" << line << "\\n\"\n";
+ // break up long lines to avoid Rez errors
+ std::vector<std::string> lines;
+ const size_t max_line_length = 512;
+ for(size_t i=0; i<line.size(); i+= max_line_length)
+ {
+ int line_length = max_line_length;
+ if(i+max_line_length > line.size())
+ line_length = line.size()-i;
+ lines.push_back(line.substr(i, line_length));
+ }
+
+ for(size_t i=0; i<lines.size(); i++)
+ {
+ osf << " \"" << lines[i] << "\"\n";
+ }
+ osf << " \"\\n\"\n";
}
osf << "};\n";
osf << "\n";
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index e964696..7cc1522 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -23,7 +23,6 @@
#include <cmsys/SystemTools.hxx>
#include <cmsys/Glob.hxx>
-#include <memory> // auto_ptr
#include <algorithm>
#if defined(__HAIKU__)
@@ -97,7 +96,6 @@ int cmCPackGenerator::PrepareNames()
}
tempDirectory += this->GetOption("CPACK_GENERATOR");
std::string topDirectory = tempDirectory;
- this->GetOption("CPACK_PACKAGE_FILE_NAME");
const char* pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME");
if(!pfname)
{
@@ -208,7 +206,7 @@ int cmCPackGenerator::InstallProject()
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: "
- << (tempInstallDirectory ? tempInstallDirectory : "(NULL}")
+ << (tempInstallDirectory ? tempInstallDirectory : "(NULL)")
<< std::endl);
return 0;
}
@@ -697,7 +695,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
cm.SetProgressCallback(cmCPackGeneratorProgress, this);
cmGlobalGenerator gg;
gg.SetCMakeInstance(&cm);
- std::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
+ cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
cmMakefile *mf = lg->GetMakefile();
std::string realInstallDirectory = tempInstallDirectory;
if ( !installSubDirectory.empty() && installSubDirectory != "/" )
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index 37ff460..b36c2a2 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -19,6 +19,7 @@
#include "cmCPackZIPGenerator.h"
#include "cmCPackSTGZGenerator.h"
#include "cmCPackNSISGenerator.h"
+
#ifdef __APPLE__
# include "cmCPackDragNDropGenerator.h"
# include "cmCPackBundleGenerator.h"
@@ -32,11 +33,14 @@
#endif
#if !defined(_WIN32) \
- && !defined(__QNXNTO__) && !defined(__BEOS__)
+ && !defined(__QNXNTO__) && !defined(__BEOS__) && !defined(__HAIKU__)
# include "cmCPackDebGenerator.h"
# include "cmCPackRPMGenerator.h"
#endif
+#ifdef _WIN32
+# include "WiX/cmCPackWIXGenerator.h"
+#endif
#include "cmCPackLog.h"
@@ -61,6 +65,8 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
{
this->RegisterGenerator("NSIS", "Null Soft Installer",
cmCPackNSISGenerator::CreateGenerator);
+ this->RegisterGenerator("NSIS64", "Null Soft Installer (64-bit)",
+ cmCPackNSISGenerator::CreateGenerator64);
}
#ifdef __CYGWIN__
if (cmCPackCygwinBinaryGenerator::CanGenerate())
@@ -80,6 +86,13 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
this->RegisterGenerator("ZIP", "ZIP file format",
cmCPackZIPGenerator::CreateGenerator);
}
+#ifdef _WIN32
+ if (cmCPackWIXGenerator::CanGenerate())
+ {
+ this->RegisterGenerator("WIX", "MSI file format via WiX tools",
+ cmCPackWIXGenerator::CreateGenerator);
+ }
+#endif
if (cmCPackTarBZip2Generator::CanGenerate())
{
this->RegisterGenerator("TBZ2", "Tar BZip2 compression",
@@ -113,7 +126,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
}
#endif
#if !defined(_WIN32) \
- && !defined(__QNXNTO__) && !defined(__BEOS__)
+ && !defined(__QNXNTO__) && !defined(__BEOS__) && !defined(__HAIKU__)
if (cmCPackDebGenerator::CanGenerate())
{
this->RegisterGenerator("DEB", "Debian packages",
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index b2e57a2..62bfa91 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -33,8 +33,9 @@
#endif
//----------------------------------------------------------------------
-cmCPackNSISGenerator::cmCPackNSISGenerator()
+cmCPackNSISGenerator::cmCPackNSISGenerator(bool nsis64)
{
+ Nsis64 = nsis64;
}
//----------------------------------------------------------------------
@@ -356,19 +357,46 @@ int cmCPackNSISGenerator::InitializeInternal()
<< std::endl);
std::vector<std::string> path;
std::string nsisPath;
- bool gotRegValue = true;
+ bool gotRegValue = false;
#ifdef _WIN32
- if ( !cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
- cmsys::SystemTools::KeyWOW64_32) )
+ if (Nsis64)
{
- if ( !cmsys::SystemTools::ReadRegistryValue(
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath) )
+ if ( !gotRegValue && cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath,
+ cmsys::SystemTools::KeyWOW64_64) )
{
- gotRegValue = false;
+ gotRegValue = true;
+ }
+ if ( !gotRegValue && cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
+ cmsys::SystemTools::KeyWOW64_64) )
+ {
+ gotRegValue = true;
}
}
+ if ( !gotRegValue && cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath,
+ cmsys::SystemTools::KeyWOW64_32) )
+ {
+ gotRegValue = true;
+ }
+ if ( !gotRegValue && cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS\\Unicode", nsisPath) )
+ {
+ gotRegValue = true;
+ }
+ if ( !gotRegValue && cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath,
+ cmsys::SystemTools::KeyWOW64_32) )
+ {
+ gotRegValue = true;
+ }
+ if ( !gotRegValue && cmsys::SystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS", nsisPath) )
+ {
+ gotRegValue = true;
+ }
if (gotRegValue)
{
@@ -404,11 +432,14 @@ int cmCPackNSISGenerator::InitializeInternal()
int retVal = 1;
bool resS = cmSystemTools::RunSingleCommand(nsisCmd.c_str(),
&output, &retVal, 0, this->GeneratorVerbose, 0);
-
cmsys::RegularExpression versionRex("v([0-9]+.[0-9]+)");
- if ( !resS || retVal || !versionRex.find(output))
+ cmsys::RegularExpression versionRexCVS("v(.*)\\.cvs");
+ if ( !resS || retVal ||
+ (!versionRex.find(output) && !versionRexCVS.find(output))
+ )
{
- std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ const char* topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
+ std::string tmpFile = topDir ? topDir : ".";
tmpFile += "/NSISOutput.log";
cmGeneratedFileStream ofs(tmpFile.c_str());
ofs << "# Run command: " << nsisCmd.c_str() << std::endl
@@ -420,17 +451,26 @@ int cmCPackNSISGenerator::InitializeInternal()
<< "Please check " << tmpFile.c_str() << " for errors" << std::endl);
return 0;
}
- double nsisVersion = atof(versionRex.match(1).c_str());
- double minNSISVersion = 2.09;
- cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: "
- << nsisVersion << std::endl);
- if ( nsisVersion < minNSISVersion )
+ if ( versionRex.find(output))
{
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "CPack requires NSIS Version 2.09 or greater. NSIS found on the system "
- "was: "
+ double nsisVersion = atof(versionRex.match(1).c_str());
+ double minNSISVersion = 2.09;
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: "
<< nsisVersion << std::endl);
- return 0;
+ if ( nsisVersion < minNSISVersion )
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "CPack requires NSIS Version 2.09 or greater. "
+ "NSIS found on the system was: "
+ << nsisVersion << std::endl);
+ return 0;
+ }
+ }
+ if ( versionRexCVS.find(output))
+ {
+ // No version check for NSIS cvs build
+ cmCPackLogger(cmCPackLog::LOG_DEBUG, "NSIS Version: CVS "
+ << versionRexCVS.match(1).c_str() << std::endl);
}
this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath.c_str());
this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLES_DIRECTORY", "bin");
diff --git a/Source/CPack/cmCPackNSISGenerator.h b/Source/CPack/cmCPackNSISGenerator.h
index 8224854..e46fbda 100644
--- a/Source/CPack/cmCPackNSISGenerator.h
+++ b/Source/CPack/cmCPackNSISGenerator.h
@@ -27,10 +27,13 @@ class cmCPackNSISGenerator : public cmCPackGenerator
public:
cmCPackTypeMacro(cmCPackNSISGenerator, cmCPackGenerator);
+ static cmCPackGenerator* CreateGenerator64()
+ { return new cmCPackNSISGenerator(true); }
+
/**
* Construct generator
*/
- cmCPackNSISGenerator();
+ cmCPackNSISGenerator(bool nsis64 = false);
virtual ~cmCPackNSISGenerator();
protected:
@@ -77,6 +80,8 @@ protected:
/// Translations any newlines found in the string into \\r\\n, so that the
/// resulting string can be used within NSIS.
static std::string TranslateNewlines(std::string str);
+
+ bool Nsis64;
};
#endif
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index edbe838..c617a3e 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -106,56 +106,101 @@ int cmCPackPackageMakerGenerator::PackageFiles()
resDir += "/en.lproj";
}
-
- // Create directory structure
- std::string preflightDirName = resDir + "/PreFlight";
- std::string postflightDirName = resDir + "/PostFlight";
const char* preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT");
const char* postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT");
const char* postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT");
- // if preflight or postflight scripts not there create directories
- // of the same name, I think this makes it work
- if(!preflight)
+
+ if(this->Components.empty())
{
- if ( !cmsys::SystemTools::MakeDirectory(preflightDirName.c_str()))
+ // Create directory structure
+ std::string preflightDirName = resDir + "/PreFlight";
+ std::string postflightDirName = resDir + "/PostFlight";
+ // if preflight or postflight scripts not there create directories
+ // of the same name, I think this makes it work
+ if(!preflight)
{
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem creating installer directory: "
- << preflightDirName.c_str() << std::endl);
- return 0;
+ if ( !cmsys::SystemTools::MakeDirectory(preflightDirName.c_str()))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating installer directory: "
+ << preflightDirName.c_str() << std::endl);
+ return 0;
+ }
+ }
+ if(!postflight)
+ {
+ if ( !cmsys::SystemTools::MakeDirectory(postflightDirName.c_str()))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating installer directory: "
+ << postflightDirName.c_str() << std::endl);
+ return 0;
+ }
+ }
+ // if preflight, postflight, or postupgrade are set
+ // then copy them into the resource directory and make
+ // them executable
+ if(preflight)
+ {
+ this->CopyInstallScript(resDir.c_str(),
+ preflight,
+ "preflight");
+ }
+ if(postflight)
+ {
+ this->CopyInstallScript(resDir.c_str(),
+ postflight,
+ "postflight");
+ }
+ if(postupgrade)
+ {
+ this->CopyInstallScript(resDir.c_str(),
+ postupgrade,
+ "postupgrade");
}
}
- if(!postflight)
+ else if(postflight)
{
- if ( !cmsys::SystemTools::MakeDirectory(postflightDirName.c_str()))
+ // create a postflight component to house the script
+ this->PostFlightComponent.Name = "PostFlight";
+ this->PostFlightComponent.DisplayName = "PostFlight";
+ this->PostFlightComponent.Description = "PostFlight";
+ this->PostFlightComponent.IsHidden = true;
+
+ // empty directory for pkg contents
+ std::string packageDir = toplevel + "/" + PostFlightComponent.Name;
+ if (!cmsys::SystemTools::MakeDirectory(packageDir.c_str()))
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Problem creating installer directory: "
- << postflightDirName.c_str() << std::endl);
+ "Problem creating component packages directory: "
+ << packageDir.c_str() << std::endl);
return 0;
}
- }
- // if preflight, postflight, or postupgrade are set
- // then copy them into the resource directory and make
- // them executable
- if(preflight)
- {
- this->CopyInstallScript(resDir.c_str(),
- preflight,
- "preflight");
- }
- if(postflight)
- {
- this->CopyInstallScript(resDir.c_str(),
+
+ // create package
+ std::string packageFileDir = packageDirFileName + "/Contents/Packages/";
+ if (!cmsys::SystemTools::MakeDirectory(packageFileDir.c_str()))
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Problem creating component PostFlight Packages directory: "
+ << packageFileDir.c_str() << std::endl);
+ return 0;
+ }
+ std::string packageFile = packageFileDir +
+ this->GetPackageName(PostFlightComponent);
+ if (!this->GenerateComponentPackage(packageFile.c_str(),
+ packageDir.c_str(),
+ PostFlightComponent))
+ {
+ return 0;
+ }
+
+ // copy postflight script into resource directory of .pkg
+ std::string resourceDir = packageFile + "/Contents/Resources";
+ this->CopyInstallScript(resourceDir.c_str(),
postflight,
"postflight");
}
- if(postupgrade)
- {
- this->CopyInstallScript(resDir.c_str(),
- postupgrade,
- "postupgrade");
- }
if (!this->Components.empty())
{
@@ -778,6 +823,11 @@ WriteDistributionFile(const char* metapackageFile)
<< std::endl;
}
}
+ if(!this->PostFlightComponent.Name.empty())
+ {
+ choiceOut << "<line choice=\"" << PostFlightComponent.Name
+ << "Choice\"></line>" << std::endl;
+ }
choiceOut << "</choices-outline>" << std::endl;
// Create the actual choices
@@ -792,6 +842,12 @@ WriteDistributionFile(const char* metapackageFile)
{
CreateChoice(compIt->second, choiceOut);
}
+
+ if(!this->PostFlightComponent.Name.empty())
+ {
+ CreateChoice(PostFlightComponent, choiceOut);
+ }
+
this->SetOption("CPACK_PACKAGEMAKER_CHOICES", choiceOut.str().c_str());
// Create the distribution.dist file in the metapackage to turn it
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.h b/Source/CPack/cmCPackPackageMakerGenerator.h
index 101813f..ba3d968 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.h
+++ b/Source/CPack/cmCPackPackageMakerGenerator.h
@@ -112,6 +112,9 @@ protected:
// value.
std::string EscapeForXML(std::string str);
+ // The PostFlight component when creating a metapackage
+ cmCPackComponent PostFlightComponent;
+
double PackageMakerVersion;
double PackageCompatibilityVersion;
};
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index 13aa6d8..66a4194 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -77,6 +77,11 @@ int cmCPackRPMGenerator::PackageOnePack(std::string initialToplevel,
packageFileName.c_str());
// Tell CPackRPM.cmake the name of the component NAME.
this->SetOption("CPACK_RPM_PACKAGE_COMPONENT",packageName.c_str());
+ // Tell CPackRPM.cmake the path where the component is.
+ std::string component_path = "/";
+ component_path += packageName;
+ this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
+ component_path.c_str());
if (!this->ReadListFile("CPackRPM.cmake"))
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -178,8 +183,11 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne()
/* replace the TEMPORARY package file name */
this->SetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME",
packageFileName.c_str());
- // Tell CPackRPM.cmake the name of the component GROUP.
- this->SetOption("CPACK_RPM_PACKAGE_COMPONENT",compInstDirName.c_str());
+ // Tell CPackRPM.cmake the path where the component is.
+ std::string component_path = "/";
+ component_path += compInstDirName;
+ this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
+ component_path.c_str());
if (!this->ReadListFile("CPackRPM.cmake"))
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index b603585..b188918 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -27,7 +27,6 @@
#include <cmsys/CommandLineArguments.hxx>
#include <cmsys/SystemTools.hxx>
-#include <memory> // auto_ptr
//----------------------------------------------------------------------------
static const char * cmDocumentationName[][3] =
@@ -181,7 +180,6 @@ int main (int argc, char *argv[])
{
cmSystemTools::FindExecutableDirectory(argv[0]);
cmCPackLog log;
- int nocwd = 0;
log.SetErrorPrefix("CPack Error: ");
log.SetWarningPrefix("CPack Warning: ");
@@ -194,7 +192,7 @@ int main (int argc, char *argv[])
{
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Current working directory cannot be established." << std::endl);
- nocwd = 1;
+ return 1;
}
std::string generator;
@@ -276,7 +274,7 @@ int main (int argc, char *argv[])
cminst.RemoveUnscriptableCommands();
cmGlobalGenerator cmgg;
cmgg.SetCMakeInstance(&cminst);
- std::auto_ptr<cmLocalGenerator> cmlg(cmgg.CreateLocalGenerator());
+ cmsys::auto_ptr<cmLocalGenerator> cmlg(cmgg.CreateLocalGenerator());
cmMakefile* globalMF = cmlg->GetMakefile();
bool cpackConfigFileSpecified = true;
@@ -298,7 +296,7 @@ int main (int argc, char *argv[])
* should launch cpack using "cpackConfigFile" if it exists
* in the current directory.
*/
- if((doc.CheckOptions(argc, argv,"-G") || nocwd) && !(argc==1))
+ if((doc.CheckOptions(argc, argv,"-G")) && !(argc==1))
{
help = true;
}
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 554efb5..4fa3c53 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -67,6 +67,12 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
generator += this->BuildGenerator;
args.push_back(generator);
}
+ if(this->BuildGeneratorToolset.size())
+ {
+ std::string toolset = "-T";
+ toolset += this->BuildGeneratorToolset;
+ args.push_back(toolset);
+ }
const char* config = 0;
if ( this->CTest->GetConfigType().size() > 0 )
@@ -229,10 +235,14 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
// should we cmake?
cmake cm;
cm.SetProgressCallback(CMakeProgressCallback, &cmakeOutString);
- cm.SetGlobalGenerator(cm.CreateGlobalGenerator(
- this->BuildGenerator.c_str()));
- if(!this->BuildNoCMake)
+ if(this->BuildNoCMake)
+ {
+ cm.SetGlobalGenerator(cm.CreateGlobalGenerator(
+ this->BuildGenerator.c_str()));
+ cm.SetGeneratorToolset(this->BuildGeneratorToolset);
+ }
+ else
{
// do the cmake step, no timeout here since it is not a sub process
if (this->RunCMake(outstring,out,cmakeOutString,cwd,&cm))
@@ -466,11 +476,17 @@ int cmCTestBuildAndTestHandler::ProcessCommandLineArguments(
idx++;
this->Timeout = atof(allArgs[idx].c_str());
}
- if(currentArg.find("--build-generator",0) == 0 && idx < allArgs.size() - 1)
+ if(currentArg == "--build-generator" && idx < allArgs.size() - 1)
{
idx++;
this->BuildGenerator = allArgs[idx];
}
+ if(currentArg == "--build-generator-toolset" &&
+ idx < allArgs.size() - 1)
+ {
+ idx++;
+ this->BuildGeneratorToolset = allArgs[idx];
+ }
if(currentArg.find("--build-project",0) == 0 && idx < allArgs.size() - 1)
{
idx++;
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h
index 9029600..ca50c64 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.h
+++ b/Source/CTest/cmCTestBuildAndTestHandler.h
@@ -57,6 +57,7 @@ protected:
cmStdString Output;
std::string BuildGenerator;
+ std::string BuildGeneratorToolset;
std::vector<std::string> BuildOptions;
bool BuildTwoConfig;
std::string BuildMakeProgram;
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index 7a99ddf..d6d39a9 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -144,6 +144,15 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
cmakeConfigureCommand += cmakeGeneratorName;
cmakeConfigureCommand += "\"";
+ const char* cmakeGeneratorToolset =
+ this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_TOOLSET");
+ if(cmakeGeneratorToolset && *cmakeGeneratorToolset)
+ {
+ cmakeConfigureCommand += " \"-T";
+ cmakeConfigureCommand += cmakeGeneratorToolset;
+ cmakeConfigureCommand += "\"";
+ }
+
cmakeConfigureCommand += " \"";
cmakeConfigureCommand += source_dir;
cmakeConfigureCommand += "\"";
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 4d1e249..20aded2 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -1097,10 +1097,17 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
}
else
{
- cmCTestLog(this->CTest, ERROR_MESSAGE,
- "Unknown gcov output line: [" << line->c_str() << "]" << std::endl);
- cont->Error ++;
- //abort();
+ // gcov 4.7 can have output lines saying "No executable lines" and
+ // "Removing 'filename.gcov'"... Don't log those as "errors."
+ if(*line != "No executable lines" &&
+ !cmSystemTools::StringStartsWith(line->c_str(), "Removing "))
+ {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unknown gcov output line: [" << line->c_str() << "]"
+ << std::endl);
+ cont->Error ++;
+ //abort();
+ }
}
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index 2c1a0af..5b34491 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -68,7 +68,7 @@ std::string cmCTestGIT::GetWorkingRevision()
{
// Run plumbing "git rev-list" to get work tree revision.
const char* git = this->CommandLineTool.c_str();
- const char* git_rev_list[] = {git, "rev-list", "-n", "1", "HEAD", 0};
+ const char* git_rev_list[] = {git, "rev-list", "-n", "1", "HEAD", "--", 0};
std::string rev;
OneLineParser out(this, "rl-out> ", rev);
OutputLogger err(this->Log, "rl-err> ");
@@ -639,7 +639,7 @@ void cmCTestGIT::LoadModifications()
this->RunChild(git_update_index, &ui_out, &ui_err);
// Use 'git diff-index' to get modified files.
- const char* git_diff_index[] = {git, "diff-index", "-z", "HEAD", 0};
+ const char* git_diff_index[] = {git, "diff-index", "-z", "HEAD", "--", 0};
DiffParser out(this, "di-out> ");
OutputLogger err(this->Log, "di-err> ");
this->RunChild(git_diff_index, &out, &err);
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 0da8aae..453e32c 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -121,7 +121,7 @@ bool cmCTestHandlerCommand
}
if ( this->Values[ct_SUBMIT_INDEX] )
{
- if ( this->CTest->GetDartVersion() <= 1 )
+ if(!this->CTest->GetDropSiteCDash() && this->CTest->GetDartVersion() <= 1)
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Dart before version 2.0 does not support collecting submissions."
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index ebef1ed..76ddeea 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -248,7 +248,12 @@ bool cmCTestMultiProcessHandler::StartTest(int test)
//---------------------------------------------------------
void cmCTestMultiProcessHandler::StartNextTests()
{
- size_t numToStart = this->ParallelLevel - this->RunningCount;
+ size_t numToStart = 0;
+ if(this->RunningCount < this->ParallelLevel)
+ {
+ numToStart = this->ParallelLevel - this->RunningCount;
+ }
+
if(numToStart == 0)
{
return;
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index b796b83..e7491bb 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -32,7 +32,6 @@
#include <math.h>
#include <float.h>
-#include <memory> // auto_ptr
#include <set>
//----------------------------------------------------------------------
@@ -1547,7 +1546,7 @@ void cmCTestTestHandler::GetListOfTests()
cmake cm;
cmGlobalGenerator gg;
gg.SetCMakeInstance(&cm);
- std::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
+ cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
cmMakefile *mf = lg->GetMakefile();
mf->AddDefinition("CTEST_CONFIGURATION_TYPE",
this->CTest->GetConfigType().c_str());
diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx
index 5c7414f..bd1ff71 100644
--- a/Source/CursesDialog/cmCursesStringWidget.cxx
+++ b/Source/CursesDialog/cmCursesStringWidget.cxx
@@ -175,7 +175,7 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
}
else if ( key == ctrl('d') ||key == KEY_DC )
{
- if ( form->curcol > 0 )
+ if ( form->curcol >= 0 )
{
form_driver(form, REQ_DEL_CHAR);
}
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 29daffd..1684fb2 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -27,6 +27,8 @@ if (Qt5Widgets_FOUND)
set(QT_LIBRARIES ${Qt5Widgets_LIBRARIES})
# Remove this when the minimum version of Qt is 4.6.
add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0)
+
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
else()
set(QT_MIN_VERSION "4.4.0")
find_package(Qt4 REQUIRED)
diff --git a/Source/QtDialog/QCMakeCacheView.cxx b/Source/QtDialog/QCMakeCacheView.cxx
index 1d21d42..6006758 100644
--- a/Source/QtDialog/QCMakeCacheView.cxx
+++ b/Source/QtDialog/QCMakeCacheView.cxx
@@ -490,7 +490,11 @@ QCMakePropertyList QCMakeCacheModel::properties() const
}
// go to the next in the tree
- while(!idxs.isEmpty() && !idxs.last().sibling(idxs.last().row()+1, 0).isValid())
+ while(!idxs.isEmpty() && (
+#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(5, 1, 0)
+ (idxs.last().row()+1) >= rowCount(idxs.last().parent()) ||
+#endif
+ !idxs.last().sibling(idxs.last().row()+1, 0).isValid()))
{
idxs.removeLast();
}
diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h
index c5252b7..1cc1e3a 100644
--- a/Source/cmAddCustomCommandCommand.h
+++ b/Source/cmAddCustomCommandCommand.h
@@ -68,7 +68,8 @@ public:
" [COMMAND command2 [ARGS] [args2...] ...]\n"
" [MAIN_DEPENDENCY depend]\n"
" [DEPENDS [depends...]]\n"
- " [IMPLICIT_DEPENDS <lang1> depend1 ...]\n"
+ " [IMPLICIT_DEPENDS <lang1> depend1\n"
+ " [<lang2> depend2] ...]\n"
" [WORKING_DIRECTORY dir]\n"
" [COMMENT comment] [VERBATIM] [APPEND])\n"
"This defines a command to generate specified OUTPUT file(s). "
@@ -142,6 +143,8 @@ public:
"dependencies of an input file. The language given specifies the "
"programming language whose corresponding dependency scanner should "
"be used. Currently only C and CXX language scanners are supported. "
+ "The language has to be specified for every file in the "
+ "IMPLICIT_DEPENDS list. "
"Dependencies discovered from the scanning are added to those of "
"the custom command at build time. Note that the IMPLICIT_DEPENDS "
"option is currently supported only for Makefile generators and "
diff --git a/Source/cmAddDependenciesCommand.cxx b/Source/cmAddDependenciesCommand.cxx
index a77140d..04a304e 100644
--- a/Source/cmAddDependenciesCommand.cxx
+++ b/Source/cmAddDependenciesCommand.cxx
@@ -35,10 +35,14 @@ bool cmAddDependenciesCommand
}
else
{
- std::string error = "Adding dependency to non-existent target: ";
- error += target_name;
- this->SetError(error.c_str());
- return false;
+ cmOStringStream e;
+ e << "Cannot add target-level dependencies to non-existent target \""
+ << target_name << "\".\n"
+ << "The add_dependencies works for top-level logical targets created "
+ << "by the add_executable, add_library, or add_custom_target commands. "
+ << "If you want to add file-level dependencies see the DEPENDS option "
+ << "of the add_custom_target and add_custom_command commands.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
return true;
diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h
index c144565..e5f27cb 100644
--- a/Source/cmAddLibraryCommand.h
+++ b/Source/cmAddLibraryCommand.h
@@ -134,6 +134,10 @@ public:
"They may contain custom commands generating such sources, but not "
"PRE_BUILD, PRE_LINK, or POST_BUILD commands. "
"Object libraries cannot be imported, exported, installed, or linked."
+ " "
+ "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>."
;
}
diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx
index 9efeda4..5b1c9c6 100644
--- a/Source/cmAddSubDirectoryCommand.cxx
+++ b/Source/cmAddSubDirectoryCommand.cxx
@@ -78,7 +78,7 @@ bool cmAddSubDirectoryCommand::InitialPass
// No binary directory was specified. If the source directory is
// not a subdirectory of the current directory then it is an
// error.
- if(!cmSystemTools::FindLastString(srcPath.c_str(),
+ if(!cmSystemTools::IsSubDirectory(srcPath.c_str(),
this->Makefile->GetCurrentDirectory()))
{
cmOStringStream e;
@@ -93,10 +93,15 @@ bool cmAddSubDirectoryCommand::InitialPass
// Remove the CurrentDirectory from the srcPath and replace it
// with the CurrentOutputDirectory.
- binPath = srcPath;
- cmSystemTools::ReplaceString(binPath,
- this->Makefile->GetCurrentDirectory(),
- this->Makefile->GetCurrentOutputDirectory());
+ const char* src = this->Makefile->GetCurrentDirectory();
+ const char* bin = this->Makefile->GetCurrentOutputDirectory();
+ size_t srcLen = strlen(src);
+ size_t binLen = strlen(bin);
+ if(srcLen > 0 && src[srcLen-1] == '/')
+ { --srcLen; }
+ if(binLen > 0 && bin[binLen-1] == '/')
+ { --binLen; }
+ binPath = std::string(bin, binLen) + srcPath.substr(srcLen);
}
else
{
diff --git a/Source/cmBootstrapCommands.cxx b/Source/cmBootstrapCommands.cxx
index 9097a74..e3a2ad4 100644
--- a/Source/cmBootstrapCommands.cxx
+++ b/Source/cmBootstrapCommands.cxx
@@ -89,6 +89,7 @@
#include "cmStringCommand.cxx"
#include "cmSubdirCommand.cxx"
#include "cmTargetLinkLibrariesCommand.cxx"
+#include "cmTimestamp.cxx"
#include "cmTryCompileCommand.cxx"
#include "cmTryRunCommand.cxx"
#include "cmUnsetCommand.cxx"
diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx
index 3722ab6..91d55a5 100644
--- a/Source/cmBuildCommand.cxx
+++ b/Source/cmBuildCommand.cxx
@@ -87,6 +87,14 @@ bool cmBuildCommand
const char* makeprogram
= this->Makefile->GetDefinition("CMAKE_MAKE_PROGRAM");
+ if(!makeprogram)
+ {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "build_command() requires CMAKE_MAKE_PROGRAM to be defined. "
+ "Call project() or enable_language() first.");
+ return true;
+ }
// If null/empty CONFIGURATION argument, GenerateBuildCommand uses 'Debug'
// in the currently implemented multi-configuration global generators...
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index a6d04b7..322a6a2 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -53,7 +53,7 @@
#include <cm_zlib.h>
#include <cmsys/Base64.h>
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__)
#include <be/kernel/OS.h> /* disable_debugger() API. */
#endif
@@ -327,6 +327,7 @@ cmCTest::cmCTest()
this->OutputLogFileLastTag = -1;
this->SuppressUpdatingCTestConfiguration = false;
this->DartVersion = 1;
+ this->DropSiteCDash = false;
this->OutputTestOutputOnTestFailure = false;
this->ComputedCompressTestOutput = false;
this->ComputedCompressMemCheckOutput = false;
@@ -653,6 +654,7 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
= this->GetCTestConfiguration("SourceDirectory").c_str();
std::string bld_dir = this->GetCTestConfiguration("BuildDirectory").c_str();
this->DartVersion = 1;
+ this->DropSiteCDash = false;
for(Part p = PartStart; p != PartCount; p = Part(p+1))
{
this->Parts[p].SubmitFiles.clear();
@@ -719,6 +721,7 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
return false;
}
}
+ this->DropSiteCDash = mf->IsOn("CTEST_DROP_SITE_CDASH");
if ( !this->Initialize(bld_dir.c_str(), command) )
{
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index f2638fe..587a6db 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -384,6 +384,7 @@ public:
//! Get the version of dart server
int GetDartVersion() { return this->DartVersion; }
+ int GetDropSiteCDash() { return this->DropSiteCDash; }
//! Add file to be submitted
void AddSubmitFile(Part part, const char* name);
@@ -561,6 +562,7 @@ private:
bool Quiet;
int DartVersion;
+ bool DropSiteCDash;
std::vector<cmStdString> InitialCommandLineArguments;
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 4231243..3d5b24b 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -584,23 +584,15 @@ bool cmCacheManager::DeleteCache(const char* path)
cmSystemTools::ConvertToUnixSlashes(cacheFile);
std::string cmakeFiles = cacheFile;
cacheFile += "/CMakeCache.txt";
- cmSystemTools::RemoveFile(cacheFile.c_str());
- // now remove the files in the CMakeFiles directory
- // this cleans up language cache files
- cmsys::Directory dir;
- cmakeFiles += cmake::GetCMakeFilesDirectory();
- dir.Load(cmakeFiles.c_str());
- for (unsigned long fileNum = 0;
- fileNum < dir.GetNumberOfFiles();
- ++fileNum)
- {
- if(!cmSystemTools::
- FileIsDirectory(dir.GetFile(fileNum)))
+ if(cmSystemTools::FileExists(cacheFile.c_str()))
+ {
+ cmSystemTools::RemoveFile(cacheFile.c_str());
+ // now remove the files in the CMakeFiles directory
+ // this cleans up language cache files
+ cmakeFiles += cmake::GetCMakeFilesDirectory();
+ if(cmSystemTools::FileIsDirectory(cmakeFiles.c_str()))
{
- std::string fullPath = cmakeFiles;
- fullPath += "/";
- fullPath += dir.GetFile(fileNum);
- cmSystemTools::RemoveFile(fullPath.c_str());
+ cmSystemTools::RemoveADirectory(cmakeFiles.c_str());
}
}
return true;
diff --git a/Source/cmCommandArgumentParser.cxx b/Source/cmCommandArgumentParser.cxx
index 696a6a8..c5146c5 100644
--- a/Source/cmCommandArgumentParser.cxx
+++ b/Source/cmCommandArgumentParser.cxx
@@ -279,7 +279,7 @@ typedef short int yytype_int16;
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -701,7 +701,7 @@ while (YYID (0))
we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 49ed967..227b226 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -28,6 +28,9 @@
#include "cmRemoveDefinitionsCommand.cxx"
#include "cmSourceGroupCommand.cxx"
#include "cmSubdirDependsCommand.cxx"
+#include "cmTargetCompileDefinitionsCommand.cxx"
+#include "cmTargetIncludeDirectoriesCommand.cxx"
+#include "cmTargetPropCommandBase.cxx"
#include "cmUseMangledMesaCommand.cxx"
#include "cmUtilitySourceCommand.cxx"
#include "cmVariableRequiresCommand.cxx"
@@ -66,6 +69,8 @@ void GetPredefinedCommands(std::list<cmCommand*>&
commands.push_back(new cmRemoveDefinitionsCommand);
commands.push_back(new cmSourceGroupCommand);
commands.push_back(new cmSubdirDependsCommand);
+ commands.push_back(new cmTargetIncludeDirectoriesCommand);
+ commands.push_back(new cmTargetCompileDefinitionsCommand);
commands.push_back(new cmUseMangledMesaCommand);
commands.push_back(new cmUtilitySourceCommand);
commands.push_back(new cmVariableRequiresCommand);
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index 055aab0..dec2b54 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -172,10 +172,11 @@ satisfy dependencies.
//----------------------------------------------------------------------------
cmComputeLinkDepends
-::cmComputeLinkDepends(cmTarget* target, const char* config)
+::cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget* head)
{
// Store context information.
this->Target = target;
+ this->HeadTarget = head;
this->Makefile = this->Target->GetMakefile();
this->LocalGenerator = this->Makefile->GetLocalGenerator();
this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
@@ -352,7 +353,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
{
// Follow the target dependencies.
if(cmTarget::LinkInterface const* iface =
- entry.Target->GetLinkInterface(this->Config))
+ entry.Target->GetLinkInterface(this->Config, this->HeadTarget))
{
// This target provides its own link interface information.
this->AddLinkEntries(depender_index, iface->Libraries);
@@ -444,7 +445,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
if(entry.Target)
{
if(cmTarget::LinkInterface const* iface =
- entry.Target->GetLinkInterface(this->Config))
+ entry.Target->GetLinkInterface(this->Config, this->HeadTarget))
{
// Follow public and private dependencies transitively.
this->FollowSharedDeps(index, iface, true);
@@ -533,7 +534,7 @@ void cmComputeLinkDepends::AddDirectLinkEntries()
{
// Add direct link dependencies in this configuration.
cmTarget::LinkImplementation const* impl =
- this->Target->GetLinkImplementation(this->Config);
+ this->Target->GetLinkImplementation(this->Config, this->HeadTarget);
this->AddLinkEntries(-1, impl->Libraries);
for(std::vector<std::string>::const_iterator
wi = impl->WrongConfigLibraries.begin();
@@ -944,7 +945,7 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
if(cmTarget* target = this->EntryList[*ni].Target)
{
if(cmTarget::LinkInterface const* iface =
- target->GetLinkInterface(this->Config))
+ target->GetLinkInterface(this->Config, this->HeadTarget))
{
if(iface->Multiplicity > count)
{
diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h
index 80a0454..1d5d1b9 100644
--- a/Source/cmComputeLinkDepends.h
+++ b/Source/cmComputeLinkDepends.h
@@ -32,7 +32,7 @@ class cmake;
class cmComputeLinkDepends
{
public:
- cmComputeLinkDepends(cmTarget* target, const char* config);
+ cmComputeLinkDepends(cmTarget* target, const char* config, cmTarget *head);
~cmComputeLinkDepends();
// Basic information about each link item.
@@ -59,6 +59,7 @@ private:
// Context information.
cmTarget* Target;
+ cmTarget* HeadTarget;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
cmGlobalGenerator* GlobalGenerator;
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index cd3ef59..896b50a 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -239,10 +239,12 @@ because this need be done only for shared libraries without soname-s.
//----------------------------------------------------------------------------
cmComputeLinkInformation
-::cmComputeLinkInformation(cmTarget* target, const char* config)
+::cmComputeLinkInformation(cmTarget* target, const char* config,
+ cmTarget *headTarget)
{
// Store context information.
this->Target = target;
+ this->HeadTarget = headTarget;
this->Makefile = this->Target->GetMakefile();
this->LocalGenerator = this->Makefile->GetLocalGenerator();
this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
@@ -265,7 +267,7 @@ cmComputeLinkInformation
this->OrderDependentRPath = 0;
// Get the language used for linking this target.
- this->LinkLanguage = this->Target->GetLinkerLanguage(config);
+ this->LinkLanguage = this->Target->GetLinkerLanguage(config, headTarget);
if(!this->LinkLanguage)
{
// The Compute method will do nothing, so skip the rest of the
@@ -277,6 +279,10 @@ cmComputeLinkInformation
this->UseImportLibrary =
this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")?true:false;
+ // Check whether we should skip dependencies on shared library files.
+ this->LinkDependsNoShared =
+ this->Target->GetPropertyAsBool("LINK_DEPENDS_NO_SHARED");
+
// On platforms without import libraries there may be a special flag
// to use when creating a plugin (module) that obtains symbols from
// the program that will load it.
@@ -499,7 +505,7 @@ bool cmComputeLinkInformation::Compute()
}
// Compute the ordered link line items.
- cmComputeLinkDepends cld(this->Target, this->Config);
+ cmComputeLinkDepends cld(this->Target, this->Config, this->HeadTarget);
cld.SetOldLinkDirMode(this->OldLinkDirMode);
cmComputeLinkDepends::EntryVector const& linkEntries = cld.Compute();
@@ -565,7 +571,8 @@ bool cmComputeLinkInformation::Compute()
void cmComputeLinkInformation::AddImplicitLinkInfo()
{
// The link closure lists all languages whose implicit info is needed.
- cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config);
+ cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config,
+ this->HeadTarget);
for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
li != lc->Languages.end(); ++li)
{
@@ -650,7 +657,11 @@ void cmComputeLinkInformation::AddItem(std::string const& item, cmTarget* tgt)
// Pass the full path to the target file.
std::string lib = tgt->GetFullPath(config, implib, true);
- this->Depends.push_back(lib);
+ if(!this->LinkDependsNoShared ||
+ tgt->GetType() != cmTarget::SHARED_LIBRARY)
+ {
+ this->Depends.push_back(lib);
+ }
this->AddTargetItem(lib, tgt);
this->AddLibraryRuntimeInfo(lib, tgt);
@@ -1368,10 +1379,31 @@ void cmComputeLinkInformation::DropDirectoryItem(std::string const& item)
//----------------------------------------------------------------------------
void cmComputeLinkInformation::ComputeFrameworkInfo()
{
- // Avoid adding system framework paths. See "man ld" on OS X.
- this->FrameworkPathsEmmitted.insert("/Library/Frameworks");
- this->FrameworkPathsEmmitted.insert("/Network/Library/Frameworks");
- this->FrameworkPathsEmmitted.insert("/System/Library/Frameworks");
+ // Avoid adding implicit framework paths.
+ std::vector<std::string> implicitDirVec;
+
+ // Get platform-wide implicit directories.
+ if(const char* implicitLinks = this->Makefile->GetDefinition
+ ("CMAKE_PLATFORM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES"))
+ {
+ cmSystemTools::ExpandListArgument(implicitLinks, implicitDirVec);
+ }
+
+ // Get language-specific implicit directories.
+ std::string implicitDirVar = "CMAKE_";
+ implicitDirVar += this->LinkLanguage;
+ implicitDirVar += "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES";
+ if(const char* implicitDirs =
+ this->Makefile->GetDefinition(implicitDirVar.c_str()))
+ {
+ cmSystemTools::ExpandListArgument(implicitDirs, implicitDirVec);
+ }
+
+ for(std::vector<std::string>::const_iterator i = implicitDirVec.begin();
+ i != implicitDirVec.end(); ++i)
+ {
+ this->FrameworkPathsEmmitted.insert(*i);
+ }
// Regular expression to extract a framework path and name.
this->SplitFramework.compile("(.*)/(.*)\\.framework$");
@@ -1752,6 +1784,22 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath)
}
//----------------------------------------------------------------------------
+static void cmCLI_ExpandListUnique(const char* str,
+ std::vector<std::string>& out,
+ std::set<cmStdString>& emitted)
+{
+ std::vector<std::string> tmp;
+ cmSystemTools::ExpandListArgument(str, tmp);
+ for(std::vector<std::string>::iterator i = tmp.begin(); i != tmp.end(); ++i)
+ {
+ if(emitted.insert(*i).second)
+ {
+ out.push_back(*i);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
bool for_install)
{
@@ -1768,7 +1816,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
(outputRuntime && this->Target->HaveInstallTreeRPATH() &&
linking_for_install);
bool use_build_rpath =
- (outputRuntime && this->Target->HaveBuildTreeRPATH() &&
+ (outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) &&
!linking_for_install);
bool use_link_rpath =
outputRuntime && linking_for_install &&
@@ -1776,10 +1824,11 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
// Construct the RPATH.
+ std::set<cmStdString> emitted;
if(use_install_rpath)
{
const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH");
- cmSystemTools::ExpandListArgument(install_rpath, runtimeDirs);
+ cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted);
}
if(use_build_rpath || use_link_rpath)
{
@@ -1791,7 +1840,10 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
// support or if using the link path as an rpath.
if(use_build_rpath)
{
- runtimeDirs.push_back(*ri);
+ if(emitted.insert(*ri).second)
+ {
+ runtimeDirs.push_back(*ri);
+ }
}
else if(use_link_rpath)
{
@@ -1803,15 +1855,40 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
!cmSystemTools::IsSubDirectory(ri->c_str(), topSourceDir) &&
!cmSystemTools::IsSubDirectory(ri->c_str(), topBinaryDir))
{
- runtimeDirs.push_back(*ri);
+ if(emitted.insert(*ri).second)
+ {
+ runtimeDirs.push_back(*ri);
+ }
}
}
}
}
+ // Add runtime paths required by the languages to always be
+ // present. This is done even when skipping rpath support.
+ {
+ cmTarget::LinkClosure const* lc =
+ this->Target->GetLinkClosure(this->Config, this->HeadTarget);
+ for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
+ li != lc->Languages.end(); ++li)
+ {
+ std::string useVar = "CMAKE_" + *li +
+ "_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH";
+ if(this->Makefile->IsOn(useVar.c_str()))
+ {
+ std::string dirVar = "CMAKE_" + *li +
+ "_IMPLICIT_LINK_DIRECTORIES";
+ if(const char* dirs = this->Makefile->GetDefinition(dirVar.c_str()))
+ {
+ cmCLI_ExpandListUnique(dirs, runtimeDirs, emitted);
+ }
+ }
+ }
+ }
+
// Add runtime paths required by the platform to always be
// present. This is done even when skipping rpath support.
- cmSystemTools::ExpandListArgument(this->RuntimeAlways.c_str(), runtimeDirs);
+ cmCLI_ExpandListUnique(this->RuntimeAlways.c_str(), runtimeDirs, emitted);
}
//----------------------------------------------------------------------------
diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h
index f60f8d3..1a76922 100644
--- a/Source/cmComputeLinkInformation.h
+++ b/Source/cmComputeLinkInformation.h
@@ -29,7 +29,8 @@ class cmOrderDirectories;
class cmComputeLinkInformation
{
public:
- cmComputeLinkInformation(cmTarget* target, const char* config);
+ cmComputeLinkInformation(cmTarget* target, const char* config,
+ cmTarget* headTarget);
~cmComputeLinkInformation();
bool Compute();
@@ -74,6 +75,7 @@ private:
// Context information.
cmTarget* Target;
+ cmTarget* HeadTarget;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
cmGlobalGenerator* GlobalGenerator;
@@ -82,6 +84,7 @@ private:
// Configuration information.
const char* Config;
const char* LinkLanguage;
+ bool LinkDependsNoShared;
// Modes for dealing with dependent shared libraries.
enum SharedDepMode
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index ab77c6b..8fd95b9 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -200,20 +200,48 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
// Get the depender.
cmTarget* depender = this->Targets[depender_index];
- // Loop over all targets linked directly.
+ // Loop over all targets linked directly in all configs.
+ // We need to make targets depend on the union of all config-specific
+ // dependencies in all targets, because the generated build-systems can't
+ // deal with config-specific dependencies.
{
- cmTarget::LinkLibraryVectorType const& tlibs =
- depender->GetOriginalLinkLibraries();
std::set<cmStdString> emitted;
+ {
+ std::vector<std::string> tlibs;
+ depender->GetDirectLinkLibraries(0, tlibs, depender);
// A target should not depend on itself.
emitted.insert(depender->GetName());
- for(cmTarget::LinkLibraryVectorType::const_iterator lib = tlibs.begin();
+ for(std::vector<std::string>::const_iterator lib = tlibs.begin();
lib != tlibs.end(); ++lib)
{
// Don't emit the same library twice for this target.
- if(emitted.insert(lib->first).second)
+ if(emitted.insert(*lib).second)
{
- this->AddTargetDepend(depender_index, lib->first.c_str(), true);
+ this->AddTargetDepend(depender_index, lib->c_str(), true);
+ this->AddInterfaceDepends(depender_index, lib->c_str(),
+ true, emitted);
+ }
+ }
+ }
+ std::vector<std::string> configs;
+ depender->GetMakefile()->GetConfigurations(configs);
+ for (std::vector<std::string>::const_iterator it = configs.begin();
+ it != configs.end(); ++it)
+ {
+ std::vector<std::string> tlibs;
+ depender->GetDirectLinkLibraries(it->c_str(), tlibs, depender);
+ // A target should not depend on itself.
+ emitted.insert(depender->GetName());
+ for(std::vector<std::string>::const_iterator lib = tlibs.begin();
+ lib != tlibs.end(); ++lib)
+ {
+ // Don't emit the same library twice for this target.
+ if(emitted.insert(*lib).second)
+ {
+ this->AddTargetDepend(depender_index, lib->c_str(), true);
+ this->AddInterfaceDepends(depender_index, lib->c_str(),
+ true, emitted);
+ }
}
}
}
@@ -237,6 +265,64 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
}
//----------------------------------------------------------------------------
+void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
+ cmTarget* dependee,
+ const char *config,
+ std::set<cmStdString> &emitted)
+{
+ cmTarget* depender = this->Targets[depender_index];
+ if(cmTarget::LinkInterface const* iface =
+ dependee->GetLinkInterface(config, depender))
+ {
+ for(std::vector<std::string>::const_iterator
+ lib = iface->Libraries.begin();
+ lib != iface->Libraries.end(); ++lib)
+ {
+ // Don't emit the same library twice for this target.
+ if(emitted.insert(*lib).second)
+ {
+ this->AddTargetDepend(depender_index, lib->c_str(), true);
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmComputeTargetDepends::AddInterfaceDepends(int depender_index,
+ const char* dependee_name,
+ bool linking,
+ std::set<cmStdString> &emitted)
+{
+ cmTarget* depender = this->Targets[depender_index];
+ cmTarget* dependee =
+ depender->GetMakefile()->FindTargetToUse(dependee_name);
+ // Skip targets that will not really be linked. This is probably a
+ // name conflict between an external library and an executable
+ // within the project.
+ if(linking && dependee &&
+ dependee->GetType() == cmTarget::EXECUTABLE &&
+ !dependee->IsExecutableWithExports())
+ {
+ dependee = 0;
+ }
+
+ if(dependee)
+ {
+ this->AddInterfaceDepends(depender_index, dependee, 0, emitted);
+ std::vector<std::string> configs;
+ depender->GetMakefile()->GetConfigurations(configs);
+ for (std::vector<std::string>::const_iterator it = configs.begin();
+ it != configs.end(); ++it)
+ {
+ // A target should not depend on itself.
+ emitted.insert(depender->GetName());
+ this->AddInterfaceDepends(depender_index, dependee,
+ it->c_str(), emitted);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
void cmComputeTargetDepends::AddTargetDepend(int depender_index,
const char* dependee_name,
bool linking)
diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h
index 67bce72..d6131cf 100644
--- a/Source/cmComputeTargetDepends.h
+++ b/Source/cmComputeTargetDepends.h
@@ -48,7 +48,11 @@ private:
bool linking);
void AddTargetDepend(int depender_index, cmTarget* dependee, bool linking);
bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
-
+ void AddInterfaceDepends(int depender_index, const char* dependee_name,
+ bool linking, std::set<cmStdString> &emitted);
+ void AddInterfaceDepends(int depender_index, cmTarget* dependee,
+ const char *config,
+ std::set<cmStdString> &emitted);
cmGlobalGenerator* GlobalGenerator;
bool DebugMode;
bool NoCycles;
diff --git a/Source/cmConfigureFileCommand.h b/Source/cmConfigureFileCommand.h
index 347174a..0393ecf 100644
--- a/Source/cmConfigureFileCommand.h
+++ b/Source/cmConfigureFileCommand.h
@@ -68,6 +68,9 @@ public:
"If <output> names an existing directory the input file is placed "
"in that directory with its original name. "
"\n"
+ "If the <input> file is modified the build system will re-run CMake "
+ "to re-configure the file and generate the build system again."
+ "\n"
"This command replaces any variables in the input file referenced as "
"${VAR} or @VAR@ with their values as determined by CMake. If a "
"variable is not defined, it will be replaced with nothing. "
@@ -76,13 +79,18 @@ public:
"will be C-style escaped. "
"The file will be configured with the current values of CMake "
"variables. If @ONLY is specified, only variables "
- "of the form @VAR@ will be replaces and ${VAR} will be ignored. "
- "This is useful for configuring scripts that use ${VAR}. "
- "Any occurrences of #cmakedefine VAR will be replaced with "
- "either #define VAR or /* #undef VAR */ depending on "
- "the setting of VAR in CMake. Any occurrences of #cmakedefine01 VAR "
- "will be replaced with either #define VAR 1 or #define VAR 0 "
- "depending on whether VAR evaluates to TRUE or FALSE in CMake.\n"
+ "of the form @VAR@ will be replaced and ${VAR} will be ignored. "
+ "This is useful for configuring scripts that use ${VAR}."
+ "\n"
+ "Input file lines of the form \"#cmakedefine VAR ...\" "
+ "will be replaced with either \"#define VAR ...\" or "
+ "\"/* #undef VAR */\" depending on whether VAR is set in CMake to "
+ "any value not considered a false constant by the if() command. "
+ "(Content of \"...\", if any, is processed as above.) "
+ "Input file lines of the form \"#cmakedefine01 VAR\" "
+ "will be replaced with either \"#define VAR 1\" or "
+ "\"#define VAR 0\" similarly."
+ "\n"
"With NEWLINE_STYLE the line ending could be adjusted: \n"
" 'UNIX' or 'LF' for \\n, 'DOS', 'WIN32' or 'CRLF' for \\r\\n.\n"
"COPYONLY must not be used with NEWLINE_STYLE.\n";
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 1ae7035..85e49a9 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -13,8 +13,11 @@
#include "cmake.h"
#include "cmCacheManager.h"
#include "cmGlobalGenerator.h"
+#include "cmExportTryCompileFileGenerator.h"
#include <cmsys/Directory.hxx>
+#include <assert.h>
+
int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
{
this->BinaryDirectory = argv[1].c_str();
@@ -39,7 +42,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
// 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] != "OUTPUT_VARIABLE" &&
+ argv[i] != "LINK_LIBRARIES";
++i)
{
extraArgs++;
@@ -75,7 +79,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
{
extraArgs++;
for (i = i + 1; i < argv.size() && argv[i] != "CMAKE_FLAGS" &&
- argv[i] != "OUTPUT_VARIABLE";
+ argv[i] != "OUTPUT_VARIABLE" &&
+ argv[i] != "LINK_LIBRARIES";
++i)
{
extraArgs++;
@@ -85,6 +90,61 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
}
}
+ std::vector<cmTarget*> targets;
+ std::string libsToLink = " ";
+ bool useOldLinkLibs = true;
+ for (i = 3; i < argv.size(); ++i)
+ {
+ 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;
+ useOldLinkLibs = false;
+ for ( ; i < argv.size() && argv[i] != "CMAKE_FLAGS"
+ && argv[i] != "COMPILE_DEFINITIONS" && argv[i] != "OUTPUT_VARIABLE";
+ ++i)
+ {
+ 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())
+ {
+ 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);
+ }
+ break;
+ }
+ }
+
// look for COPY_FILE
std::string copyFile;
for (i = 3; i < argv.size(); ++i)
@@ -247,6 +307,33 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
fprintf(fout, ")\n");
}
+ /* Use a random file name to avoid rapid creation and deletion
+ of the same executable name (some filesystems fail on that). */
+ sprintf(targetNameBuf, "cmTryCompileExec%u",
+ cmSystemTools::RandomSeed());
+ targetName = targetNameBuf;
+
+ if (!targets.empty())
+ {
+ std::string fname = "/" + std::string(targetName) + "Targets.cmake";
+ cmExportTryCompileFileGenerator tcfg;
+ tcfg.SetExportFile((this->BinaryDirectory + fname).c_str());
+ tcfg.SetExports(targets);
+ tcfg.SetConfig(this->Makefile->GetDefinition(
+ "CMAKE_TRY_COMPILE_CONFIGURATION"));
+
+ if(!tcfg.GenerateImportFile())
+ {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "could not write export file.");
+ fclose(fout);
+ return -1;
+ }
+ fprintf(fout,
+ "\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/%s\")\n\n",
+ fname.c_str());
+ }
+
/* for the TRY_COMPILEs we want to be able to specify the architecture.
So the user can set CMAKE_OSX_ARCHITECTURE to i386;ppc and then set
CMAKE_TRY_COMPILE_OSX_ARCHITECTURE first to i386 and then to ppc to
@@ -286,18 +373,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
fprintf(fout, "SET(CMAKE_POSITION_INDEPENDENT_CODE \"ON\")\n");
}
- /* Use a random file name to avoid rapid creation and deletion
- of the same executable name (some filesystems fail on that). */
- sprintf(targetNameBuf, "cmTryCompileExec%u",
- cmSystemTools::RandomSeed());
- targetName = targetNameBuf;
-
/* Put the executable at a known location (for COPY_FILE). */
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, "TARGET_LINK_LIBRARIES(%s ${LINK_LIBRARIES})\n",targetName);
+ if (useOldLinkLibs)
+ {
+ fprintf(fout,
+ "TARGET_LINK_LIBRARIES(%s ${LINK_LIBRARIES})\n",targetName);
+ }
+ else
+ {
+ fprintf(fout, "TARGET_LINK_LIBRARIES(%s %s)\n",
+ targetName,
+ libsToLink.c_str());
+ }
fclose(fout);
projectName = "CMAKE_TRY_COMPILE";
// if the source is not in CMakeTmp
diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx
index a1505bd..a4f6ac4 100644
--- a/Source/cmCryptoHash.cxx
+++ b/Source/cmCryptoHash.cxx
@@ -54,8 +54,8 @@ std::string cmCryptoHash::HashFile(const char* file)
this->Initialize();
// Should be efficient enough on most system:
- const int bufferSize = 4096;
- char buffer[bufferSize];
+ cm_sha2_uint64_t buffer[512];
+ char* buffer_c = reinterpret_cast<char*>(buffer);
unsigned char const* buffer_uc =
reinterpret_cast<unsigned char const*>(buffer);
// This copy loop is very sensitive on certain platforms with
@@ -65,7 +65,7 @@ std::string cmCryptoHash::HashFile(const char* file)
// error occurred. Therefore, the loop should be safe everywhere.
while(fin)
{
- fin.read(buffer, bufferSize);
+ fin.read(buffer_c, sizeof(buffer));
if(int gcount = static_cast<int>(fin.gcount()))
{
this->Append(buffer_uc, gcount);
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 07df7d5..f2f77ee 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -47,7 +47,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
{
return target->GetLocation(this->Config);
}
- return this->GE->Parse(argv0).Evaluate(this->Makefile, this->Config);
+ return this->GE->Parse(argv0)->Evaluate(this->Makefile, this->Config);
}
//----------------------------------------------------------------------------
@@ -58,7 +58,7 @@ cmCustomCommandGenerator
cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c];
for(unsigned int j=1;j < commandLine.size(); ++j)
{
- std::string arg = this->GE->Parse(commandLine[j]).Evaluate(this->Makefile,
+ std::string arg = this->GE->Parse(commandLine[j])->Evaluate(this->Makefile,
this->Config);
cmd += " ";
if(this->OldStyle)
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index 166a584..74a0ccb 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -50,6 +50,7 @@ bool cmDepends::Write(std::ostream &makeDepends,
std::vector<std::string> pairs;
cmSystemTools::ExpandListArgument(srcStr, pairs);
+ std::map<std::string, std::set<std::string> > dependencies;
for(std::vector<std::string>::iterator si = pairs.begin();
si != pairs.end();)
{
@@ -62,9 +63,14 @@ bool cmDepends::Write(std::ostream &makeDepends,
obj = this->LocalGenerator->Convert(obj.c_str(),
cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::MAKEFILE);
+ dependencies[obj].insert(src);
+ }
+ for(std::map<std::string, std::set<std::string> >::const_iterator
+ it = dependencies.begin(); it != dependencies.end(); ++it)
+ {
// Write the dependencies for this pair.
- if(!this->WriteDependencies(src.c_str(), obj.c_str(),
+ if(!this->WriteDependencies(it->second, it->first,
makeDepends, internalDepends))
{
return false;
@@ -134,8 +140,9 @@ void cmDepends::Clear(const char *file)
}
//----------------------------------------------------------------------------
-bool cmDepends::WriteDependencies(const char*, const char*,
- std::ostream&, std::ostream&)
+bool cmDepends::WriteDependencies(
+ const std::set<std::string>&, const std::string&,
+ std::ostream&, std::ostream&)
{
// This should be implemented by the subclass.
return false;
@@ -174,8 +181,10 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends,
// kdelibs/khtml this reduces the number of calls from 184k down to 92k,
// or the time for cmake -E cmake_depends from 0.3 s down to 0.21 s.
dependerExists = cmSystemTools::FileExists(this->Depender);
- DependencyVector tmp;
- validDeps[this->Depender] = tmp;
+ // If we erase validDeps[this->Depender] by overwriting it with an empty
+ // vector, we lose dependencies for dependers that have multiple
+ // entries. No need to initialize the entry, std::map will do so on first
+ // access.
currentDependencies = &validDeps[this->Depender];
continue;
}
diff --git a/Source/cmDepends.h b/Source/cmDepends.h
index f7dc881..d787edd 100644
--- a/Source/cmDepends.h
+++ b/Source/cmDepends.h
@@ -76,8 +76,10 @@ protected:
// Write dependencies for the target file to the given stream.
// Return true for success and false for failure.
- virtual bool WriteDependencies(const char *src, const char* obj,
- std::ostream& makeDepends, std::ostream& internalDepends);
+ virtual bool WriteDependencies(const std::set<std::string>& sources,
+ const std::string& obj,
+ std::ostream& makeDepends,
+ std::ostream& internalDepends);
// Check dependencies for the target file in the given stream.
// Return false if dependencies must be regenerated and true
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 44841a9..43b7b8a 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -98,176 +98,179 @@ cmDependsC::~cmDependsC()
}
//----------------------------------------------------------------------------
-bool cmDependsC::WriteDependencies(const char *src, const char *obj,
- std::ostream& makeDepends, std::ostream& internalDepends)
+bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
+ const std::string& obj,
+ std::ostream& makeDepends,
+ std::ostream& internalDepends)
{
// Make sure this is a scanning instance.
- if(!src || src[0] == '\0')
+ if(sources.empty() || sources.begin()->empty())
{
cmSystemTools::Error("Cannot scan dependencies without a source file.");
return false;
}
- if(!obj || obj[0] == '\0')
+ if(obj.empty())
{
cmSystemTools::Error("Cannot scan dependencies without an object file.");
return false;
}
+ std::set<cmStdString> dependencies;
+ bool haveDeps = false;
+
if (this->ValidDeps != 0)
{
std::map<std::string, DependencyVector>::const_iterator tmpIt =
this->ValidDeps->find(obj);
if (tmpIt!= this->ValidDeps->end())
{
- // Write the dependencies to the output stream. Makefile rules
- // written by the original local generator for this directory
- // convert the dependencies to paths relative to the home output
- // directory. We must do the same here.
- internalDepends << obj << std::endl;
for(DependencyVector::const_iterator i=tmpIt->second.begin();
i != tmpIt->second.end(); ++i)
{
- makeDepends << obj << ": " <<
- this->LocalGenerator->Convert(i->c_str(),
- cmLocalGenerator::HOME_OUTPUT,
- cmLocalGenerator::MAKEFILE)
- << std::endl;
- internalDepends << " " << i->c_str() << std::endl;
+ dependencies.insert(*i);
}
- makeDepends << std::endl;
- return true;
+ haveDeps = true;
}
}
- // Walk the dependency graph starting with the source file.
- bool first = true;
- UnscannedEntry root;
- root.FileName = src;
- this->Unscanned.push(root);
- this->Encountered.clear();
- this->Encountered.insert(src);
- std::set<cmStdString> dependencies;
- std::set<cmStdString> scanned;
+ if (!haveDeps)
+ {
+ // Walk the dependency graph starting with the source file.
+ int srcFiles = (int)sources.size();
+ this->Encountered.clear();
+
+ for(std::set<std::string>::const_iterator srcIt = sources.begin();
+ srcIt != sources.end(); ++srcIt)
+ {
+ UnscannedEntry root;
+ root.FileName = *srcIt;
+ this->Unscanned.push(root);
+ this->Encountered.insert(*srcIt);
+ }
- // Use reserve to allocate enough memory for tempPathStr
- // so that during the loops no memory is allocated or freed
- std::string tempPathStr;
- tempPathStr.reserve(4*1024);
+ std::set<cmStdString> scanned;
- while(!this->Unscanned.empty())
- {
- // Get the next file to scan.
- UnscannedEntry current = this->Unscanned.front();
- this->Unscanned.pop();
+ // Use reserve to allocate enough memory for tempPathStr
+ // so that during the loops no memory is allocated or freed
+ std::string tempPathStr;
+ tempPathStr.reserve(4*1024);
- // If not a full path, find the file in the include path.
- std::string fullName;
- if(first || cmSystemTools::FileIsFullPath(current.FileName.c_str()))
+ while(!this->Unscanned.empty())
{
- if(cmSystemTools::FileExists(current.FileName.c_str(), true))
+ // Get the next file to scan.
+ UnscannedEntry current = this->Unscanned.front();
+ this->Unscanned.pop();
+
+ // If not a full path, find the file in the include path.
+ std::string fullName;
+ if((srcFiles>0)
+ || cmSystemTools::FileIsFullPath(current.FileName.c_str()))
{
- fullName = current.FileName;
+ if(cmSystemTools::FileExists(current.FileName.c_str(), true))
+ {
+ fullName = current.FileName;
+ }
}
- }
- else if(!current.QuotedLocation.empty() &&
- cmSystemTools::FileExists(current.QuotedLocation.c_str(), true))
- {
- // The include statement producing this entry was a double-quote
- // include and the included file is present in the directory of
- // the source containing the include statement.
- fullName = current.QuotedLocation;
- }
- else
- {
- std::map<cmStdString, cmStdString>::iterator
- headerLocationIt=this->HeaderLocationCache.find(current.FileName);
- if (headerLocationIt!=this->HeaderLocationCache.end())
+ else if(!current.QuotedLocation.empty() &&
+ cmSystemTools::FileExists(current.QuotedLocation.c_str(), true))
{
- fullName=headerLocationIt->second;
+ // The include statement producing this entry was a double-quote
+ // include and the included file is present in the directory of
+ // the source containing the include statement.
+ fullName = current.QuotedLocation;
}
- else for(std::vector<std::string>::const_iterator i =
- this->IncludePath.begin(); i != this->IncludePath.end(); ++i)
+ else
{
- // Construct the name of the file as if it were in the current
- // include directory. Avoid using a leading "./".
-
- tempPathStr = "";
- if((*i) == ".")
+ std::map<cmStdString, cmStdString>::iterator
+ headerLocationIt=this->HeaderLocationCache.find(current.FileName);
+ if (headerLocationIt!=this->HeaderLocationCache.end())
{
- tempPathStr += current.FileName;
+ fullName=headerLocationIt->second;
}
- else
+ else for(std::vector<std::string>::const_iterator i =
+ this->IncludePath.begin(); i != this->IncludePath.end(); ++i)
{
- tempPathStr += *i;
- tempPathStr+="/";
- tempPathStr+=current.FileName;
- }
+ // Construct the name of the file as if it were in the current
+ // include directory. Avoid using a leading "./".
- // Look for the file in this location.
- if(cmSystemTools::FileExists(tempPathStr.c_str(), true))
- {
- fullName = tempPathStr;
- HeaderLocationCache[current.FileName]=fullName;
- break;
+ tempPathStr = "";
+ if((*i) == ".")
+ {
+ tempPathStr += current.FileName;
+ }
+ else
+ {
+ tempPathStr += *i;
+ tempPathStr+="/";
+ tempPathStr+=current.FileName;
+ }
+
+ // Look for the file in this location.
+ if(cmSystemTools::FileExists(tempPathStr.c_str(), true))
+ {
+ fullName = tempPathStr;
+ HeaderLocationCache[current.FileName]=fullName;
+ break;
+ }
}
}
- }
-
- // Complain if the file cannot be found and matches the complain
- // regex.
- if(fullName.empty() &&
- this->IncludeRegexComplain.find(current.FileName.c_str()))
- {
- cmSystemTools::Error("Cannot find file \"",
- current.FileName.c_str(), "\".");
- return false;
- }
- // Scan the file if it was found and has not been scanned already.
- if(!fullName.empty() && (scanned.find(fullName) == scanned.end()))
- {
- // Record scanned files.
- scanned.insert(fullName);
+ // Complain if the file cannot be found and matches the complain
+ // regex.
+ if(fullName.empty() &&
+ this->IncludeRegexComplain.find(current.FileName.c_str()))
+ {
+ cmSystemTools::Error("Cannot find file \"",
+ current.FileName.c_str(), "\".");
+ return false;
+ }
- // Check whether this file is already in the cache
- std::map<cmStdString, cmIncludeLines*>::iterator fileIt=
- this->FileCache.find(fullName);
- if (fileIt!=this->FileCache.end())
+ // Scan the file if it was found and has not been scanned already.
+ if(!fullName.empty() && (scanned.find(fullName) == scanned.end()))
{
- fileIt->second->Used=true;
- dependencies.insert(fullName);
- for (std::vector<UnscannedEntry>::const_iterator incIt=
- fileIt->second->UnscannedEntries.begin();
- incIt!=fileIt->second->UnscannedEntries.end(); ++incIt)
+ // Record scanned files.
+ scanned.insert(fullName);
+
+ // Check whether this file is already in the cache
+ std::map<cmStdString, cmIncludeLines*>::iterator fileIt=
+ this->FileCache.find(fullName);
+ if (fileIt!=this->FileCache.end())
{
- if (this->Encountered.find(incIt->FileName) ==
- this->Encountered.end())
+ fileIt->second->Used=true;
+ dependencies.insert(fullName);
+ for (std::vector<UnscannedEntry>::const_iterator incIt=
+ fileIt->second->UnscannedEntries.begin();
+ incIt!=fileIt->second->UnscannedEntries.end(); ++incIt)
{
- this->Encountered.insert(incIt->FileName);
- this->Unscanned.push(*incIt);
+ if (this->Encountered.find(incIt->FileName) ==
+ this->Encountered.end())
+ {
+ this->Encountered.insert(incIt->FileName);
+ this->Unscanned.push(*incIt);
+ }
}
}
- }
- else
- {
-
- // Try to scan the file. Just leave it out if we cannot find
- // it.
- std::ifstream fin(fullName.c_str());
- if(fin)
+ else
{
- // Add this file as a dependency.
- dependencies.insert(fullName);
- // Scan this file for new dependencies. Pass the directory
- // containing the file to handle double-quote includes.
- std::string dir = cmSystemTools::GetFilenamePath(fullName);
- this->Scan(fin, dir.c_str(), fullName);
+ // Try to scan the file. Just leave it out if we cannot find
+ // it.
+ std::ifstream fin(fullName.c_str());
+ if(fin)
+ {
+ // Add this file as a dependency.
+ dependencies.insert(fullName);
+
+ // Scan this file for new dependencies. Pass the directory
+ // containing the file to handle double-quote includes.
+ std::string dir = cmSystemTools::GetFilenamePath(fullName);
+ this->Scan(fin, dir.c_str(), fullName);
+ }
}
}
- }
- first = false;
+ srcFiles--;
+ }
}
// Write the dependencies to the output stream. Makefile rules
@@ -275,7 +278,7 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
// convert the dependencies to paths relative to the home output
// directory. We must do the same here.
internalDepends << obj << std::endl;
- for(std::set<cmStdString>::iterator i=dependencies.begin();
+ for(std::set<cmStdString>::const_iterator i=dependencies.begin();
i != dependencies.end(); ++i)
{
makeDepends << obj << ": " <<
diff --git a/Source/cmDependsC.h b/Source/cmDependsC.h
index bd9a4b7..16dfad7 100644
--- a/Source/cmDependsC.h
+++ b/Source/cmDependsC.h
@@ -32,11 +32,9 @@ public:
virtual ~cmDependsC();
protected:
- typedef std::vector<char> t_CharBuffer;
-
// Implement writing/checking methods required by superclass.
- virtual bool WriteDependencies(const char *src,
- const char *file,
+ virtual bool WriteDependencies(const std::set<std::string>& sources,
+ const std::string& obj,
std::ostream& makeDepends,
std::ostream& internalDepends);
@@ -82,7 +80,6 @@ protected:
const std::map<std::string, DependencyVector>* ValidDeps;
std::set<cmStdString> Encountered;
std::queue<UnscannedEntry> Unscanned;
- t_CharBuffer Buffer;
std::map<cmStdString, cmIncludeLines *> FileCache;
std::map<cmStdString, cmStdString> HeaderLocationCache;
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 3e66058..e41e5ea 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -170,44 +170,50 @@ cmDependsFortran::~cmDependsFortran()
}
//----------------------------------------------------------------------------
-bool cmDependsFortran::WriteDependencies(const char *src, const char *obj,
- std::ostream&, std::ostream&)
+bool cmDependsFortran::WriteDependencies(
+ const std::set<std::string>& sources, const std::string& obj,
+ std::ostream&, std::ostream&)
{
// Make sure this is a scanning instance.
- if(!src || src[0] == '\0')
+ if(sources.empty() || sources.begin()->empty())
{
- cmSystemTools::Error("Cannot scan dependencies without an source file.");
+ cmSystemTools::Error("Cannot scan dependencies without a source file.");
return false;
}
- if(!obj || obj[0] == '\0')
+ if(obj.empty())
{
cmSystemTools::Error("Cannot scan dependencies without an object file.");
return false;
}
- // Get the information object for this source.
- cmDependsFortranSourceInfo& info =
- this->Internal->CreateObjectInfo(obj, src);
+ bool okay = true;
+ for(std::set<std::string>::const_iterator it = sources.begin();
+ it != sources.end(); ++it)
+ {
+ const std::string& src = *it;
+ // Get the information object for this source.
+ cmDependsFortranSourceInfo& info =
+ this->Internal->CreateObjectInfo(obj.c_str(), src.c_str());
- // Make a copy of the macros defined via ADD_DEFINITIONS
- std::set<std::string> ppDefines(this->PPDefinitions.begin(),
- this->PPDefinitions.end());
+ // Make a copy of the macros defined via ADD_DEFINITIONS
+ std::set<std::string> ppDefines(this->PPDefinitions.begin(),
+ this->PPDefinitions.end());
- // Create the parser object. The constructor takes ppMacro and info per
- // reference, so we may look into the resulting objects later.
- cmDependsFortranParser parser(this, ppDefines, info);
+ // Create the parser object. The constructor takes ppMacro and info per
+ // reference, so we may look into the resulting objects later.
+ cmDependsFortranParser parser(this, ppDefines, info);
- // Push on the starting file.
- cmDependsFortranParser_FilePush(&parser, src);
+ // Push on the starting file.
+ cmDependsFortranParser_FilePush(&parser, src.c_str());
- // Parse the translation unit.
- if(cmDependsFortran_yyparse(parser.Scanner) != 0)
- {
- // Failed to parse the file. Report failure to write dependencies.
- return false;
+ // Parse the translation unit.
+ if(cmDependsFortran_yyparse(parser.Scanner) != 0)
+ {
+ // Failed to parse the file. Report failure to write dependencies.
+ okay = false;
+ }
}
-
- return true;
+ return okay;
}
//----------------------------------------------------------------------------
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index cdfde6e..cb40796 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -66,7 +66,7 @@ protected:
// Implement writing/checking methods required by superclass.
virtual bool WriteDependencies(
- const char *src, const char *file,
+ const std::set<std::string>& sources, const std::string& file,
std::ostream& makeDepends, std::ostream& internalDepends);
// Actually write the depenencies to the streams.
diff --git a/Source/cmDependsJava.cxx b/Source/cmDependsJava.cxx
index ba0e8fb..949d465 100644
--- a/Source/cmDependsJava.cxx
+++ b/Source/cmDependsJava.cxx
@@ -25,11 +25,11 @@ cmDependsJava::~cmDependsJava()
}
//----------------------------------------------------------------------------
-bool cmDependsJava::WriteDependencies(const char *src, const char *,
- std::ostream&, std::ostream&)
+bool cmDependsJava::WriteDependencies(const std::set<std::string>& sources,
+ const std::string&, std::ostream&, std::ostream&)
{
// Make sure this is a scanning instance.
- if(!src || src[0] == '\0')
+ if(sources.empty() || sources.begin()->empty())
{
cmSystemTools::Error("Cannot scan dependencies without an source file.");
return false;
diff --git a/Source/cmDependsJava.h b/Source/cmDependsJava.h
index bf7e234..22af53f 100644
--- a/Source/cmDependsJava.h
+++ b/Source/cmDependsJava.h
@@ -29,7 +29,8 @@ public:
protected:
// Implement writing/checking methods required by superclass.
- virtual bool WriteDependencies(const char *src, const char *file,
+ virtual bool WriteDependencies(
+ const std::set<std::string>& sources, const std::string& file,
std::ostream& makeDepends, std::ostream& internalDepends);
virtual bool CheckDependencies(std::istream& internalDepends,
const char* internalDependsFileName,
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 445fd0e..6cc3f25 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -26,6 +26,18 @@
"strings which contain a '>' for example.\n" \
" $<COMMA> = A literal ','. Used to compare " \
"strings which contain a ',' for example.\n" \
+ " $<SEMICOLON> = A literal ';'. Used to prevent " \
+ "list expansion on an argument with ';'.\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 " \
+ "target- it may not contain generator expressions.\n" \
+ " $<INSTALL_INTERFACE:...> = content of \"...\" when the property " \
+ "is exported using install(EXPORT), and empty otherwise.\n" \
+ " $<BUILD_INTERFACE:...> = content of \"...\" when the property " \
+ "is exported using export(), or when the target is used by another " \
+ "target in the same buildsystem. Expands to the empty string " \
+ "otherwise.\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" \
@@ -36,9 +48,16 @@
" $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \
" $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n" \
"\n" \
- " $<TARGET_PROPERTY:tgt,prop> = The value of the property prop\n" \
- "on the target tgt. Note that tgt is not added as a dependency of\n" \
- "the target this expression is evaluated on.\n" \
+ " $<TARGET_PROPERTY:tgt,prop> = The value of the property prop " \
+ "on the target tgt.\n" \
+ "Note that tgt is not added as a dependency of the target this " \
+ "expression is evaluated on.\n" \
+ " $<TARGET_POLICY:pol> = '1' if the policy was NEW when " \
+ "the 'head' target was created, else '0'. If the policy was not " \
+ "set, the warning message for the policy will be emitted. This " \
+ "generator expression only works for a subset of policies.\n" \
+ " $<INSTALL_PREFIX> = Content of the install prefix when " \
+ "the target is exported via INSTALL(EXPORT) and empty otherwise.\n" \
"Boolean expressions:\n" \
" $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \
" $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \
@@ -49,7 +68,7 @@
#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \
CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
"Expressions with an implicit 'this' target:\n" \
- " $<TARGET_PROPERTY:prop> = The value of the property prop on\n" \
+ " $<TARGET_PROPERTY:prop> = The value of the property prop on " \
"the target on which the generator expression is evaluated.\n" \
""
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 8db0e8f..61f9f5a 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -255,6 +255,14 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"CMAKE_EXTRA_GENERATOR (e.g. \"Eclipse CDT4\").",false,
"Variables that Provide Information");
cm->DefineProperty
+ ("CMAKE_GENERATOR_TOOLSET", cmProperty::VARIABLE,
+ "Native build system toolset name specified by user.",
+ "Some CMake generators support a toolset name to be given to the "
+ "native build system to choose a compiler. "
+ "If the user specifies a toolset name (e.g. via the cmake -T option) "
+ "the value will be available in this variable.",false,
+ "Variables that Provide Information");
+ cm->DefineProperty
("CMAKE_HOME_DIRECTORY", cmProperty::VARIABLE,
"Path to top of source tree.",
"This is the path to the top level of the source tree.",false,
@@ -295,6 +303,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
,false,
"Variables that Provide Information");
cm->DefineProperty
+ ("CMAKE_XCODE_PLATFORM_TOOLSET", cmProperty::VARIABLE,
+ "Xcode compiler selection.",
+ "Xcode supports selection of a compiler from one of the installed "
+ "toolsets. "
+ "CMake provides the name of the chosen toolset in this variable, "
+ "if any is explicitly selected (e.g. via the cmake -T option)."
+ ,false,
+ "Variables that Provide Information");
+ cm->DefineProperty
("CMAKE_MINOR_VERSION", cmProperty::VARIABLE,
"The Minor version of cmake (i.e. the 4 in X.4.X).",
"This specifies the minor version of the CMake"
@@ -896,6 +913,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
" script, it may get fatal error messages from the script.",false,
"Variables That Change Behavior");
+ cm->DefineProperty
+ ("CMAKE_DEBUG_TARGET_PROPERTIES", cmProperty::VARIABLE,
+ "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");
+
// Variables defined by CMake that describe the system
cm->DefineProperty
@@ -996,7 +1022,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
false,
"Variables That Describe the System");
- int msvc_versions[] = { 60, 70, 71, 80, 90, 100, 110, 0 };
+ int msvc_versions[] = { 60, 70, 71, 80, 90, 100, 110, 120, 0 };
for (int i = 0; msvc_versions[i] != 0; i ++)
{
const char minor = (char)('0' + (msvc_versions[i] % 10));
@@ -1043,6 +1069,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
" 1500 = VS 9.0\n"
" 1600 = VS 10.0\n"
" 1700 = VS 11.0\n"
+ " 1800 = VS 12.0\n"
"",
false,
"Variables That Describe the System");
@@ -1138,6 +1165,18 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Variables that Control the Build");
cm->DefineProperty
+ ("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE", cmProperty::VARIABLE,
+ "Automatically add the current source- and build directories "
+ "to the INTERFACE_INCLUDE_DIRECTORIES.",
+ "If this variable is enabled, CMake automatically adds for each shared "
+ "library target, static library target, module target and executable "
+ "target, ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR} to "
+ "the INTERFACE_INCLUDE_DIRECTORIES."
+ "By default CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE is OFF.",
+ false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
("CMAKE_INSTALL_RPATH", cmProperty::VARIABLE,
"The rpath to use for installed targets.",
"A semicolon-separated list specifying the rpath "
@@ -1222,6 +1261,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Variables that Control the Build");
cm->DefineProperty
+ ("CMAKE_LINK_DEPENDS_NO_SHARED", cmProperty::VARIABLE,
+ "Whether to skip link dependencies on shared library files.",
+ "This variable initializes the LINK_DEPENDS_NO_SHARED "
+ "property on targets when they are created. "
+ "See that target property for additional information.",
+ false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
("CMAKE_AUTOMOC", cmProperty::VARIABLE,
"Whether to handle moc automatically for Qt targets.",
"This variable is used to initialize the "
@@ -1452,7 +1500,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
" PathScale = PathScale (pathscale.com)\n"
" SDCC = Small Device C Compiler (sdcc.sourceforge.net)\n"
" SunPro = Oracle Solaris Studio (oracle.com)\n"
- " TI_DSP = Texas Instruments (ti.com)\n"
+ " TI = Texas Instruments (ti.com)\n"
" TinyCC = Tiny C Compiler (tinycc.org)\n"
" Watcom = Open Watcom (openwatcom.org)\n"
" XL, VisualAge, zOS = IBM XL (ibm.com)\n"
@@ -1504,7 +1552,14 @@ 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.",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"
+ " CC = C compiler\n"
+ " CXX = C++ compiler\n"
+ " G77 = Fortran compiler",
+ false,
"Variables for Languages");
cm->DefineProperty
@@ -1612,6 +1667,23 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"These paths are implicit linker search directories for the compiler's "
"language. "
"CMake automatically detects these directories for each language and "
+ "reports the results in this variable."
+ "\n"
+ "When a library in one of these directories is given by full path to "
+ "target_link_libraries() CMake will generate the -l<name> form on "
+ "link lines to ensure the linker searches its implicit directories "
+ "for the library. "
+ "Note that some toolchains read implicit directories from an "
+ "environment variable such as LIBRARY_PATH so keep its value "
+ "consistent when operating in a given build tree.",false,
+ "Variables for Languages");
+
+ cm->DefineProperty
+ ("CMAKE_<LANG>_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES", cmProperty::VARIABLE,
+ "Implicit linker framework search path detected for language <LANG>.",
+ "These paths are implicit linker framework search directories for "
+ "the compiler's language. "
+ "CMake automatically detects these directories for each language and "
"reports the results in this variable.", false,
"Variables for Languages");
@@ -1803,6 +1875,9 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cmProperty::VARIABLE,0,0);
cm->DefineProperty("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH",
cmProperty::VARIABLE,0,0);
+ cm->DefineProperty(
+ "CMAKE_<LANG>_USE_IMPLICIT_LINK_DIRECTORIES_IN_RUNTIME_PATH",
+ cmProperty::VARIABLE,0,0);
cm->DefineProperty("CMAKE_SHARED_MODULE_CREATE_<LANG>_FLAGS",
cmProperty::VARIABLE,0,0);
cm->DefineProperty("CMAKE_SHARED_MODULE_<LANG>_FLAGS",
diff --git a/Source/cmEnableLanguageCommand.h b/Source/cmEnableLanguageCommand.h
index e4bb251..ee963f9 100644
--- a/Source/cmEnableLanguageCommand.h
+++ b/Source/cmEnableLanguageCommand.h
@@ -65,7 +65,12 @@ public:
"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.";
+ "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.";
}
cmTypeMacro(cmEnableLanguageCommand, cmCommand);
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index fb3f39f..7147f86 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -22,15 +22,20 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator()
//----------------------------------------------------------------------------
bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
{
- // Create all the imported targets.
+ std::vector<cmTarget*> allTargets;
+ {
+ std::string expectedTargets;
+ std::string sep;
for(std::vector<cmTarget*>::const_iterator
tei = this->Exports->begin();
tei != this->Exports->end(); ++tei)
{
+ expectedTargets += sep + this->Namespace + (*tei)->GetName();
+ sep = " ";
cmTarget* te = *tei;
if(this->ExportedTargets.insert(te).second)
{
- this->GenerateImportTargetCode(os, te);
+ allTargets.push_back(te);
}
else
{
@@ -44,14 +49,46 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
}
}
+ this->GenerateExpectedTargetsCode(os, expectedTargets);
+ }
+
+ std::vector<std::string> missingTargets;
+
+ // Create all the imported targets.
+ for(std::vector<cmTarget*>::const_iterator
+ tei = allTargets.begin();
+ tei != allTargets.end(); ++tei)
+ {
+ cmTarget* te = *tei;
+ this->GenerateImportTargetCode(os, te);
+
+ te->AppendBuildInterfaceIncludes();
+
+ ImportPropertyMap properties;
+
+ this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te,
+ cmGeneratorExpression::BuildInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
+ te, properties);
+ this->PopulateCompatibleInterfaceProperties(te, properties);
+
+ this->GenerateInterfaceProperties(te, os, properties);
+ }
+
// Generate import file content for each configuration.
for(std::vector<std::string>::const_iterator
ci = this->Configurations.begin();
ci != this->Configurations.end(); ++ci)
{
- this->GenerateImportConfig(os, ci->c_str());
+ this->GenerateImportConfig(os, ci->c_str(), missingTargets);
}
+ this->GenerateMissingTargetsCheckCode(os, missingTargets);
+
return true;
}
@@ -59,7 +96,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
void
cmExportBuildFileGenerator
::GenerateImportTargetsConfig(std::ostream& os,
- const char* config, std::string const& suffix)
+ const char* config, std::string const& suffix,
+ std::vector<std::string> &missingTargets)
{
for(std::vector<cmTarget*>::const_iterator
tei = this->Exports->begin();
@@ -72,9 +110,12 @@ cmExportBuildFileGenerator
if(!properties.empty())
{
// Get the rest of the target details.
- std::vector<std::string> missingTargets;
this->SetImportDetailProperties(config, suffix,
target, properties, missingTargets);
+ this->SetImportLinkInterface(config, suffix,
+ cmGeneratorExpression::BuildInterface,
+ target, properties, missingTargets);
+
// TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
@@ -83,7 +124,6 @@ cmExportBuildFileGenerator
// properties);
// Generate code in the export file.
- this->GenerateMissingTargetsCheckCode(os, missingTargets);
this->GenerateImportPropertyCode(os, config, target, properties);
}
}
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 726537b..5e1be16 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -44,7 +44,8 @@ protected:
virtual bool GenerateMainFile(std::ostream& os);
virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config,
- std::string const& suffix);
+ std::string const& suffix,
+ std::vector<std::string> &missingTargets);
virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmMakefile* mf,
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 8dffae4..27ec56b 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -21,8 +21,10 @@
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmVersion.h"
+#include "cmComputeLinkInformation.h"
#include <cmsys/auto_ptr.hxx>
+#include <assert.h>
//----------------------------------------------------------------------------
cmExportFileGenerator::cmExportFileGenerator()
@@ -81,16 +83,16 @@ bool cmExportFileGenerator::GenerateImportFile()
// Protect that file against use with older CMake versions.
os << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n";
- os << "IF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
- << " MESSAGE(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
- << "ENDIF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n";
+ os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
+ << " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
+ << "endif()\n";
// Isolate the file policy level.
// We use 2.6 here instead of the current version because newer
// versions of CMake should be able to export files imported by 2.6
// until the import format changes.
- os << "CMAKE_POLICY(PUSH)\n"
- << "CMAKE_POLICY(VERSION 2.6)\n";
+ os << "cmake_policy(PUSH)\n"
+ << "cmake_policy(VERSION 2.6)\n";
// Start with the import file header.
this->GenerateImportHeaderCode(os);
@@ -100,14 +102,15 @@ bool cmExportFileGenerator::GenerateImportFile()
// End with the import file footer.
this->GenerateImportFooterCode(os);
- os << "CMAKE_POLICY(POP)\n";
+ os << "cmake_policy(POP)\n";
return result;
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
- const char* config)
+ const char* config,
+ std::vector<std::string> &missingTargets)
{
// Construct the property configuration suffix.
std::string suffix = "_";
@@ -121,7 +124,480 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
}
// Generate the per-config target information.
- this->GenerateImportTargetsConfig(os, config, suffix);
+ this->GenerateImportTargetsConfig(os, config, suffix, missingTargets);
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
+ cmTarget *target,
+ ImportPropertyMap &properties)
+{
+ const char *input = target->GetProperty(propName);
+ if (input)
+ {
+ properties[propName] = input;
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
+ const char *outputName,
+ cmTarget *target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap &properties,
+ std::vector<std::string> &missingTargets)
+{
+ const char *input = target->GetProperty(propName);
+ if (input)
+ {
+ if (!*input)
+ {
+ // Set to empty
+ properties[outputName] = "";
+ return;
+ }
+
+ std::string prepro = cmGeneratorExpression::Preprocess(input,
+ preprocessRule);
+ if (!prepro.empty())
+ {
+ this->ResolveTargetsInGeneratorExpressions(prepro, target,
+ missingTargets);
+ properties[outputName] = prepro;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+static bool isSubDirectory(const char* a, const char* b)
+{
+ return (cmSystemTools::ComparePath(a, b) ||
+ cmSystemTools::IsSubDirectory(a, b));
+}
+
+//----------------------------------------------------------------------------
+static bool checkInterfaceDirs(const std::string &prepro,
+ cmTarget *target)
+{
+ const char* installDir =
+ target->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+ const char* topSourceDir = target->GetMakefile()->GetHomeDirectory();
+ const char* topBinaryDir = target->GetMakefile()->GetHomeOutputDirectory();
+
+ std::vector<std::string> parts;
+ cmGeneratorExpression::Split(prepro, parts);
+
+ const bool inSourceBuild = strcmp(topSourceDir, topBinaryDir) == 0;
+
+ for(std::vector<std::string>::iterator li = parts.begin();
+ li != parts.end(); ++li)
+ {
+ if (cmGeneratorExpression::Find(*li) != std::string::npos)
+ {
+ continue;
+ }
+ if (strncmp(li->c_str(), "${_IMPORT_PREFIX}", 17) == 0)
+ {
+ continue;
+ }
+ if (!cmSystemTools::FileIsFullPath(li->c_str()))
+ {
+ cmOStringStream e;
+ e << "Target \"" << target->GetName() << "\" "
+ "INTERFACE_INCLUDE_DIRECTORIES property contains relative path:\n"
+ " \"" << *li << "\"";
+ target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
+ e.str().c_str());
+ return false;
+ }
+ if (isSubDirectory(li->c_str(), installDir))
+ {
+ continue;
+ }
+ if (isSubDirectory(li->c_str(), topBinaryDir))
+ {
+ cmOStringStream e;
+ e << "Target \"" << target->GetName() << "\" "
+ "INTERFACE_INCLUDE_DIRECTORIES property contains path:\n"
+ " \"" << *li << "\"\nwhich is prefixed in the build directory.";
+ target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
+ e.str().c_str());
+ return false;
+ }
+ if (!inSourceBuild)
+ {
+ if (isSubDirectory(li->c_str(), topSourceDir))
+ {
+ cmOStringStream e;
+ e << "Target \"" << target->GetName() << "\" "
+ "INTERFACE_INCLUDE_DIRECTORIES property contains path:\n"
+ " \"" << *li << "\"\nwhich is prefixed in the source directory.";
+ target->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
+ e.str().c_str());
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateIncludeDirectoriesInterface(
+ cmTarget *target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap &properties,
+ std::vector<std::string> &missingTargets)
+{
+ assert(preprocessRule == cmGeneratorExpression::InstallInterface);
+
+ const char *propName = "INTERFACE_INCLUDE_DIRECTORIES";
+ const char *input = target->GetProperty(propName);
+ if (!input)
+ {
+ return;
+ }
+ if (!*input)
+ {
+ // Set to empty
+ properties[propName] = "";
+ return;
+ }
+
+ std::string prepro = cmGeneratorExpression::Preprocess(input,
+ preprocessRule);
+ if (!prepro.empty())
+ {
+ this->ResolveTargetsInGeneratorExpressions(prepro, target,
+ missingTargets);
+
+ if (!checkInterfaceDirs(prepro, target))
+ {
+ return;
+ }
+ properties[propName] = prepro;
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
+ cmTarget *target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap &properties,
+ std::vector<std::string> &missingTargets)
+{
+ this->PopulateInterfaceProperty(propName, propName, target, preprocessRule,
+ properties, missingTargets);
+}
+
+
+//----------------------------------------------------------------------------
+void getPropertyContents(cmTarget *tgt, const char *prop,
+ std::set<std::string> &ifaceProperties)
+{
+ const char *p = tgt->GetProperty(prop);
+ if (!p)
+ {
+ return;
+ }
+ std::vector<std::string> content;
+ cmSystemTools::ExpandListArgument(p, content);
+ for (std::vector<std::string>::const_iterator ci = content.begin();
+ ci != content.end(); ++ci)
+ {
+ ifaceProperties.insert(*ci);
+ }
+}
+
+//----------------------------------------------------------------------------
+void getCompatibleInterfaceProperties(cmTarget *target,
+ std::set<std::string> &ifaceProperties,
+ const char *config)
+{
+ cmComputeLinkInformation *info = target->GetLinkInformation(config);
+
+ const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
+
+ for(cmComputeLinkInformation::ItemVector::const_iterator li =
+ deps.begin();
+ li != deps.end(); ++li)
+ {
+ if (!li->Target)
+ {
+ continue;
+ }
+ getPropertyContents(li->Target,
+ "COMPATIBLE_INTERFACE_BOOL",
+ ifaceProperties);
+ getPropertyContents(li->Target,
+ "COMPATIBLE_INTERFACE_STRING",
+ ifaceProperties);
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
+ cmTarget *target,
+ ImportPropertyMap &properties)
+{
+ this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL",
+ target, properties);
+ this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING",
+ target, properties);
+
+ std::set<std::string> ifaceProperties;
+
+ getPropertyContents(target, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties);
+ getPropertyContents(target, "COMPATIBLE_INTERFACE_STRING", ifaceProperties);
+
+ getCompatibleInterfaceProperties(target, ifaceProperties, 0);
+
+ std::vector<std::string> configNames;
+ target->GetMakefile()->GetConfigurations(configNames);
+
+ for (std::vector<std::string>::const_iterator ci = configNames.begin();
+ ci != configNames.end(); ++ci)
+ {
+ getCompatibleInterfaceProperties(target, ifaceProperties, ci->c_str());
+ }
+
+ for (std::set<std::string>::const_iterator it = ifaceProperties.begin();
+ it != ifaceProperties.end(); ++it)
+ {
+ this->PopulateInterfaceProperty(("INTERFACE_" + *it).c_str(),
+ target, properties);
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
+ std::ostream& os,
+ const ImportPropertyMap &properties)
+{
+ if (!properties.empty())
+ {
+ std::string targetName = this->Namespace;
+ targetName += target->GetName();
+ os << "set_target_properties(" << targetName << " PROPERTIES\n";
+ for(ImportPropertyMap::const_iterator pi = properties.begin();
+ pi != properties.end(); ++pi)
+ {
+ os << " " << pi->first << " \"" << pi->second << "\"\n";
+ }
+ os << ")\n\n";
+ }
+}
+
+//----------------------------------------------------------------------------
+bool
+cmExportFileGenerator::AddTargetNamespace(std::string &input,
+ cmTarget* target,
+ std::vector<std::string> &missingTargets)
+{
+ cmMakefile *mf = target->GetMakefile();
+
+ cmTarget *tgt = mf->FindTargetToUse(input.c_str());
+ if (!tgt)
+ {
+ return false;
+ }
+
+ if(tgt->IsImported())
+ {
+ return true;
+ }
+ if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
+ {
+ input = this->Namespace + input;
+ }
+ else
+ {
+ std::string namespacedTarget;
+ this->HandleMissingTarget(namespacedTarget, missingTargets,
+ mf, target, tgt);
+ if (!namespacedTarget.empty())
+ {
+ input = namespacedTarget;
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
+ std::string &input,
+ cmTarget* target,
+ std::vector<std::string> &missingTargets,
+ FreeTargetsReplace replace)
+{
+ if (replace == NoReplaceFreeTargets)
+ {
+ this->ResolveTargetsInGeneratorExpression(input, target, missingTargets);
+ return;
+ }
+ std::vector<std::string> parts;
+ cmGeneratorExpression::Split(input, parts);
+
+ std::string sep;
+ input = "";
+ for(std::vector<std::string>::iterator li = parts.begin();
+ li != parts.end(); ++li)
+ {
+ if (cmGeneratorExpression::Find(*li) == std::string::npos)
+ {
+ this->AddTargetNamespace(*li, target, missingTargets);
+ }
+ else
+ {
+ this->ResolveTargetsInGeneratorExpression(
+ *li,
+ target,
+ missingTargets);
+ }
+ input += sep + *li;
+ sep = ";";
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
+ std::string &input,
+ cmTarget* target,
+ std::vector<std::string> &missingTargets)
+{
+ std::string::size_type pos = 0;
+ std::string::size_type lastPos = pos;
+
+ cmMakefile *mf = target->GetMakefile();
+
+ while((pos = input.find("$<TARGET_PROPERTY:", lastPos)) != input.npos)
+ {
+ std::string::size_type nameStartPos = pos +
+ sizeof("$<TARGET_PROPERTY:") - 1;
+ std::string::size_type closePos = input.find(">", nameStartPos);
+ std::string::size_type commaPos = input.find(",", nameStartPos);
+ std::string::size_type nextOpenPos = input.find("$<", nameStartPos);
+ if (commaPos == input.npos // Implied 'this' target
+ || closePos == input.npos // Imcomplete expression.
+ || closePos < commaPos // Implied 'this' target
+ || nextOpenPos < commaPos) // Non-literal
+ {
+ lastPos = nameStartPos;
+ continue;
+ }
+
+ std::string targetName = input.substr(nameStartPos,
+ commaPos - nameStartPos);
+
+ if (this->AddTargetNamespace(targetName, target, missingTargets))
+ {
+ input.replace(nameStartPos, commaPos - nameStartPos, targetName);
+ }
+ lastPos = nameStartPos + targetName.size() + 1;
+ }
+
+ std::string errorString;
+ pos = 0;
+ lastPos = pos;
+ while((pos = input.find("$<TARGET_NAME:", lastPos)) != input.npos)
+ {
+ std::string::size_type nameStartPos = pos + sizeof("$<TARGET_NAME:") - 1;
+ std::string::size_type endPos = input.find(">", nameStartPos);
+ if (endPos == input.npos)
+ {
+ errorString = "$<TARGET_NAME:...> expression incomplete";
+ break;
+ }
+ std::string targetName = input.substr(nameStartPos,
+ endPos - nameStartPos);
+ if(targetName.find("$<") != input.npos)
+ {
+ errorString = "$<TARGET_NAME:...> requires its parameter to be a "
+ "literal.";
+ break;
+ }
+ if (!this->AddTargetNamespace(targetName, target, missingTargets))
+ {
+ errorString = "$<TARGET_NAME:...> requires its parameter to be a "
+ "reachable target.";
+ break;
+ }
+ input.replace(pos, endPos - pos + 1, targetName);
+ lastPos = endPos;
+ }
+
+ this->ReplaceInstallPrefix(input);
+
+ if (!errorString.empty())
+ {
+ mf->IssueMessage(cmake::FATAL_ERROR, errorString);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator::ReplaceInstallPrefix(std::string &)
+{
+ // Do nothing
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportFileGenerator
+::SetImportLinkInterface(const char* config, std::string const& suffix,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmTarget* target, ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets)
+{
+ // Add the transitive link dependencies for this configuration.
+ cmTarget::LinkInterface const* iface = target->GetLinkInterface(config,
+ target);
+ if (!iface)
+ {
+ return;
+ }
+
+ if (iface->ImplementationIsInterface)
+ {
+ this->SetImportLinkProperty(suffix, target,
+ "IMPORTED_LINK_INTERFACE_LIBRARIES",
+ iface->Libraries, properties, missingTargets);
+ return;
+ }
+
+ const char *propContent;
+
+ if (const char *prop_suffixed = target->GetProperty(
+ ("LINK_INTERFACE_LIBRARIES" + suffix).c_str()))
+ {
+ propContent = prop_suffixed;
+ }
+ else if (const char *prop = target->GetProperty(
+ "LINK_INTERFACE_LIBRARIES"))
+ {
+ propContent = prop;
+ }
+ else
+ {
+ return;
+ }
+
+ if (!*propContent)
+ {
+ properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = "";
+ return;
+ }
+
+ std::string prepro = cmGeneratorExpression::Preprocess(propContent,
+ preprocessRule);
+ if (!prepro.empty())
+ {
+ this->ResolveTargetsInGeneratorExpressions(prepro, target,
+ missingTargets,
+ ReplaceFreeTargets);
+ properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
+ }
}
//----------------------------------------------------------------------------
@@ -162,14 +638,13 @@ cmExportFileGenerator
}
// Add the transitive link dependencies for this configuration.
- if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config))
+ if(cmTarget::LinkInterface const* iface = target->GetLinkInterface(config,
+ target))
{
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LANGUAGES",
iface->Languages, properties, missingTargets);
- this->SetImportLinkProperty(suffix, target,
- "IMPORTED_LINK_INTERFACE_LIBRARIES",
- iface->Libraries, properties, missingTargets);
+
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
iface->SharedDeps, properties, missingTargets);
@@ -201,9 +676,6 @@ cmExportFileGenerator
return;
}
- // Get the makefile in which to lookup target information.
- cmMakefile* mf = target->GetMakefile();
-
// Construct the property value.
std::string link_libs;
const char* sep = "";
@@ -214,33 +686,9 @@ cmExportFileGenerator
link_libs += sep;
sep = ";";
- // Append this entry.
- if(cmTarget* tgt = mf->FindTargetToUse(li->c_str()))
- {
- // This is a target.
- if(tgt->IsImported())
- {
- // The target is imported (and therefore is not in the
- // export). Append the raw name.
- link_libs += *li;
- }
- else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
- {
- // The target is in the export. Append it with the export
- // namespace.
- link_libs += this->Namespace;
- link_libs += *li;
- }
- else
- {
- this->HandleMissingTarget(link_libs, missingTargets, mf, target, tgt);
- }
- }
- else
- {
- // Append the raw name.
- link_libs += *li;
- }
+ std::string temp = *li;
+ this->AddTargetNamespace(temp, target, missingTargets);
+ link_libs += temp;
}
// Store the property.
@@ -273,7 +721,7 @@ void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
{
os << "# Commands beyond this point should not need to know the version.\n"
- << "SET(CMAKE_IMPORT_FILE_VERSION)\n";
+ << "set(CMAKE_IMPORT_FILE_VERSION)\n";
}
//----------------------------------------------------------------------------
@@ -282,11 +730,42 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
// Store an import file format version. This will let us change the
// format later while still allowing old import files to work.
os << "# Commands may need to know the format version.\n"
- << "SET(CMAKE_IMPORT_FILE_VERSION 1)\n"
+ << "set(CMAKE_IMPORT_FILE_VERSION 1)\n"
<< "\n";
}
//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os,
+ const std::string &expectedTargets)
+{
+ os << "set(_targetsDefined)\n"
+ "set(_targetsNotDefined)\n"
+ "set(_expectedTargets)\n"
+ "foreach(_expectedTarget " << expectedTargets << ")\n"
+ " list(APPEND _expectedTargets ${_expectedTarget})\n"
+ " if(NOT TARGET ${_expectedTarget})\n"
+ " list(APPEND _targetsNotDefined ${_expectedTarget})\n"
+ " endif()\n"
+ " if(TARGET ${_expectedTarget})\n"
+ " list(APPEND _targetsDefined ${_expectedTarget})\n"
+ " endif()\n"
+ "endforeach()\n"
+ "if(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
+ " set(CMAKE_IMPORT_FILE_VERSION)\n"
+ " cmake_policy(POP)\n"
+ " return()\n"
+ "endif()\n"
+ "if(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
+ " message(FATAL_ERROR \"Some (but not all) targets in this export "
+ "set were already defined.\\nTargets Defined: ${_targetsDefined}\\n"
+ "Targets not yet defined: ${_targetsNotDefined}\\n\")\n"
+ "endif()\n"
+ "unset(_targetsDefined)\n"
+ "unset(_targetsNotDefined)\n"
+ "unset(_expectedTargets)\n"
+ "\n\n";
+}
+//----------------------------------------------------------------------------
void
cmExportFileGenerator
::GenerateImportTargetCode(std::ostream& os, cmTarget* target)
@@ -300,16 +779,19 @@ cmExportFileGenerator
switch(target->GetType())
{
case cmTarget::EXECUTABLE:
- os << "ADD_EXECUTABLE(" << targetName << " IMPORTED)\n";
+ os << "add_executable(" << targetName << " IMPORTED)\n";
break;
case cmTarget::STATIC_LIBRARY:
- os << "ADD_LIBRARY(" << targetName << " STATIC IMPORTED)\n";
+ os << "add_library(" << targetName << " STATIC IMPORTED)\n";
break;
case cmTarget::SHARED_LIBRARY:
- os << "ADD_LIBRARY(" << targetName << " SHARED IMPORTED)\n";
+ os << "add_library(" << targetName << " SHARED IMPORTED)\n";
break;
case cmTarget::MODULE_LIBRARY:
- os << "ADD_LIBRARY(" << targetName << " MODULE IMPORTED)\n";
+ os << "add_library(" << targetName << " MODULE IMPORTED)\n";
+ break;
+ case cmTarget::UNKNOWN_LIBRARY:
+ os << "add_library(" << targetName << " UNKNOWN IMPORTED)\n";
break;
default: // should never happen
break;
@@ -318,27 +800,27 @@ cmExportFileGenerator
// Mark the imported executable if it has exports.
if(target->IsExecutableWithExports())
{
- os << "SET_PROPERTY(TARGET " << targetName
+ os << "set_property(TARGET " << targetName
<< " PROPERTY ENABLE_EXPORTS 1)\n";
}
// Mark the imported library if it is a framework.
if(target->IsFrameworkOnApple())
{
- os << "SET_PROPERTY(TARGET " << targetName
+ os << "set_property(TARGET " << targetName
<< " PROPERTY FRAMEWORK 1)\n";
}
// Mark the imported executable if it is an application bundle.
if(target->IsAppBundleOnApple())
{
- os << "SET_PROPERTY(TARGET " << targetName
+ os << "set_property(TARGET " << targetName
<< " PROPERTY MACOSX_BUNDLE 1)\n";
}
if (target->IsCFBundleOnApple())
{
- os << "SET_PROPERTY(TARGET " << targetName
+ os << "set_property(TARGET " << targetName
<< " PROPERTY BUNDLE 1)\n";
}
os << "\n";
@@ -358,7 +840,7 @@ cmExportFileGenerator
// Set the import properties.
os << "# Import target \"" << targetName << "\" for configuration \""
<< config << "\"\n";
- os << "SET_PROPERTY(TARGET " << targetName
+ os << "set_property(TARGET " << targetName
<< " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
if(config && *config)
{
@@ -369,7 +851,7 @@ cmExportFileGenerator
os << "NOCONFIG";
}
os << ")\n";
- os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
+ os << "set_target_properties(" << targetName << " PROPERTIES\n";
for(ImportPropertyMap::const_iterator pi = properties.begin();
pi != properties.end(); ++pi)
{
@@ -384,23 +866,48 @@ cmExportFileGenerator
void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os,
const std::vector<std::string>& missingTargets)
{
+ if (missingTargets.empty())
+ {
+ os << "# This file does not depend on other imported targets which have\n"
+ "# been exported from the same project but in a separate "
+ "export set.\n\n";
+ return;
+ }
os << "# Make sure the targets which have been exported in some other \n"
- "# export set exist.\n";
+ "# export set exist.\n"
+ "unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
+ "foreach(_target ";
+ std::set<std::string> emitted;
for(unsigned int i=0; i<missingTargets.size(); ++i)
{
- os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n"
- << " IF(CMAKE_FIND_PACKAGE_NAME)\n"
- << " SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
- << " SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
- << "\"Required imported target \\\"" << missingTargets[i]
- << "\\\" not found ! \")\n"
- << " ELSE()\n"
- << " MESSAGE(FATAL_ERROR \"Required imported target \\\""
- << missingTargets[i] << "\\\" not found ! \")\n"
- << " ENDIF()\n"
- << "ENDIF()\n";
+ if (emitted.insert(missingTargets[i]).second)
+ {
+ os << "\"" << missingTargets[i] << "\" ";
+ }
}
- os << "\n";
+ os << ")\n"
+ " if(NOT TARGET \"${_target}\" )\n"
+ " set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets \""
+ "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets} ${_target}\")"
+ "\n"
+ " endif()\n"
+ "endforeach()\n"
+ "\n"
+ "if(DEFINED ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
+ " if(CMAKE_FIND_PACKAGE_NAME)\n"
+ " set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
+ " set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
+ "\"The following imported targets are "
+ "referenced, but are missing: "
+ "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}\")\n"
+ " else()\n"
+ " message(FATAL_ERROR \"The following imported targets are "
+ "referenced, but are missing: "
+ "${${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets}\")\n"
+ " endif()\n"
+ "endif()\n"
+ "unset(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE_targets)\n"
+ "\n";
}
@@ -416,10 +923,10 @@ cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
// on SUSE with a mysql pkg-config file, which claimed everything is fine,
// but the development package was not installed.).
os << "# Loop over all imported files and verify that they actually exist\n"
- "FOREACH(target ${_IMPORT_CHECK_TARGETS} )\n"
- " FOREACH(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n"
- " IF(NOT EXISTS \"${file}\" )\n"
- " MESSAGE(FATAL_ERROR \"The imported target \\\"${target}\\\""
+ "foreach(target ${_IMPORT_CHECK_TARGETS} )\n"
+ " foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n"
+ " if(NOT EXISTS \"${file}\" )\n"
+ " message(FATAL_ERROR \"The imported target \\\"${target}\\\""
" references the file\n"
" \\\"${file}\\\"\n"
"but this file does not exist. Possible reasons include:\n"
@@ -429,11 +936,11 @@ cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
" \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n"
"but not all the files it references.\n"
"\")\n"
- " ENDIF()\n"
- " ENDFOREACH()\n"
- " UNSET(_IMPORT_CHECK_FILES_FOR_${target})\n"
- "ENDFOREACH()\n"
- "UNSET(_IMPORT_CHECK_TARGETS)\n"
+ " endif()\n"
+ " endforeach()\n"
+ " unset(_IMPORT_CHECK_FILES_FOR_${target})\n"
+ "endforeach()\n"
+ "unset(_IMPORT_CHECK_TARGETS)\n"
"\n";
}
@@ -449,8 +956,8 @@ cmExportFileGenerator
std::string targetName = this->Namespace;
targetName += target->GetName();
- os << "LIST(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n"
- "LIST(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " ";
+ os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n"
+ "list(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " ";
for(std::set<std::string>::const_iterator li = importedLocations.begin();
li != importedLocations.end();
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 70bc65d..9f958a2 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -13,6 +13,7 @@
#define cmExportFileGenerator_h
#include "cmCommand.h"
+#include "cmGeneratorExpression.h"
/** \class cmExportFileGenerator
* \brief Generate a file exporting targets from a build or install tree.
@@ -46,7 +47,8 @@ protected:
// Generate per-configuration target information to the given output
// stream.
- void GenerateImportConfig(std::ostream& os, const char* config);
+ void GenerateImportConfig(std::ostream& os, const char* config,
+ std::vector<std::string> &missingTargets);
// Methods to implement export file code generation.
void GenerateImportHeaderCode(std::ostream& os, const char* config = 0);
@@ -63,6 +65,8 @@ protected:
void GenerateMissingTargetsCheckCode(std::ostream& os,
const std::vector<std::string>& missingTargets);
+ void GenerateExpectedTargetsCode(std::ostream& os,
+ const std::string &expectedTargets);
// Collect properties with detailed information about targets beyond
// their location on disk.
@@ -82,7 +86,8 @@ protected:
/** Each subclass knows where the target files are located. */
virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config,
- std::string const& suffix) = 0;
+ std::string const& suffix,
+ std::vector<std::string> &missingTargets) = 0;
/** Each subclass knows how to deal with a target that is missing from an
* export set. */
@@ -91,6 +96,37 @@ protected:
cmMakefile* mf,
cmTarget* depender,
cmTarget* dependee) = 0;
+ void PopulateInterfaceProperty(const char *,
+ cmTarget *target,
+ cmGeneratorExpression::PreprocessContext,
+ ImportPropertyMap &properties,
+ std::vector<std::string> &missingTargets);
+ void PopulateInterfaceProperty(const char *propName, cmTarget *target,
+ ImportPropertyMap &properties);
+ void PopulateCompatibleInterfaceProperties(cmTarget *target,
+ ImportPropertyMap &properties);
+ void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
+ const ImportPropertyMap &properties);
+ void PopulateIncludeDirectoriesInterface(
+ cmTarget *target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap &properties,
+ std::vector<std::string> &missingTargets);
+
+ void SetImportLinkInterface(const char* config, std::string const& suffix,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ cmTarget* target, ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets);
+
+ enum FreeTargetsReplace {
+ ReplaceFreeTargets,
+ NoReplaceFreeTargets
+ };
+
+ void ResolveTargetsInGeneratorExpressions(std::string &input,
+ cmTarget* target,
+ std::vector<std::string> &missingTargets,
+ FreeTargetsReplace replace = NoReplaceFreeTargets);
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
@@ -107,6 +143,22 @@ protected:
// The set of targets included in the export.
std::set<cmTarget*> ExportedTargets;
+
+private:
+ void PopulateInterfaceProperty(const char *, const char *,
+ cmTarget *target,
+ cmGeneratorExpression::PreprocessContext,
+ ImportPropertyMap &properties,
+ std::vector<std::string> &missingTargets);
+
+ bool AddTargetNamespace(std::string &input, cmTarget* target,
+ std::vector<std::string> &missingTargets);
+
+ void ResolveTargetsInGeneratorExpression(std::string &input,
+ cmTarget* target,
+ std::vector<std::string> &missingTargets);
+
+ virtual void ReplaceInstallPrefix(std::string &input);
};
#endif
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 7841731..ad12b5a 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -39,20 +39,25 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
//----------------------------------------------------------------------------
bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{
- // Create all the imported targets.
+ std::vector<cmTarget*> allTargets;
+ {
+ std::string expectedTargets;
+ std::string sep;
for(std::vector<cmTargetExport*>::const_iterator
tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
{
+ expectedTargets += sep + this->Namespace + (*tei)->Target->GetName();
+ sep = " ";
cmTargetExport const* te = *tei;
if(this->ExportedTargets.insert(te->Target).second)
{
- this->GenerateImportTargetCode(os, te->Target);
+ allTargets.push_back(te->Target);
}
else
{
cmOStringStream e;
- e << "INSTALL(EXPORT \""
+ e << "install(EXPORT \""
<< this->IEGen->GetExportSet()->GetName()
<< "\" ...) " << "includes target \"" << te->Target->GetName()
<< "\" more than once in the export set.";
@@ -61,33 +66,133 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
}
}
+ this->GenerateExpectedTargetsCode(os, expectedTargets);
+ }
+
+ // Add code to compute the installation prefix relative to the
+ // import file location.
+ const char* installDest = this->IEGen->GetDestination();
+ if(!cmSystemTools::FileIsFullPath(installDest))
+ {
+ std::string installPrefix =
+ this->IEGen->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+ std::string absDest = installPrefix + "/" + installDest;
+ std::string absDestS = absDest + "/";
+ os << "# Compute the installation prefix relative to this file.\n"
+ << "get_filename_component(_IMPORT_PREFIX"
+ << " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
+ if(strncmp(absDestS.c_str(), "/lib/", 5) == 0 ||
+ strncmp(absDestS.c_str(), "/lib64/", 7) == 0 ||
+ strncmp(absDestS.c_str(), "/usr/lib/", 9) == 0 ||
+ strncmp(absDestS.c_str(), "/usr/lib64/", 11) == 0)
+ {
+ // Handle "/usr move" symlinks created by some Linux distros.
+ os <<
+ "# Use original install prefix when loaded through a\n"
+ "# cross-prefix symbolic link such as /lib -> /usr/lib.\n"
+ "get_filename_component(_realCurr \"${_IMPORT_PREFIX}\" REALPATH)\n"
+ "get_filename_component(_realOrig \"" << absDest << "\" REALPATH)\n"
+ "if(_realCurr STREQUAL _realOrig)\n"
+ " set(_IMPORT_PREFIX \"" << absDest << "\")\n"
+ "endif()\n"
+ "unset(_realOrig)\n"
+ "unset(_realCurr)\n";
+ }
+ std::string dest = installDest;
+ while(!dest.empty())
+ {
+ os <<
+ "get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
+ dest = cmSystemTools::GetFilenamePath(dest);
+ }
+ os << "\n";
+
+ // Import location properties may reference this variable.
+ this->ImportPrefix = "${_IMPORT_PREFIX}/";
+ }
+
+ std::vector<std::string> missingTargets;
+
+ // Create all the imported targets.
+ for(std::vector<cmTarget*>::const_iterator
+ tei = allTargets.begin();
+ tei != allTargets.end(); ++tei)
+ {
+ cmTarget* te = *tei;
+ this->GenerateImportTargetCode(os, te);
+
+ ImportPropertyMap properties;
+
+ this->PopulateIncludeDirectoriesInterface(te,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS",
+ te,
+ cmGeneratorExpression::InstallInterface,
+ properties, missingTargets);
+ this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
+ te, properties);
+ this->PopulateCompatibleInterfaceProperties(te, properties);
+
+ this->GenerateInterfaceProperties(te, os, properties);
+ }
+
+
// Now load per-configuration properties for them.
os << "# Load information for each installed configuration.\n"
- << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
- << "FILE(GLOB CONFIG_FILES \"${_DIR}/"
+ << "get_filename_component(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
+ << "file(GLOB CONFIG_FILES \"${_DIR}/"
<< this->GetConfigImportFileGlob() << "\")\n"
- << "FOREACH(f ${CONFIG_FILES})\n"
- << " INCLUDE(${f})\n"
- << "ENDFOREACH(f)\n"
+ << "foreach(f ${CONFIG_FILES})\n"
+ << " include(${f})\n"
+ << "endforeach()\n"
<< "\n";
+ // Cleanup the import prefix variable.
+ if(!this->ImportPrefix.empty())
+ {
+ os << "# Cleanup temporary variables.\n"
+ << "set(_IMPORT_PREFIX)\n"
+ << "\n";
+ }
+ this->GenerateImportedFileCheckLoop(os);
+
// Generate an import file for each configuration.
bool result = true;
for(std::vector<std::string>::const_iterator
ci = this->Configurations.begin();
ci != this->Configurations.end(); ++ci)
{
- if(!this->GenerateImportFileConfig(ci->c_str()))
+ if(!this->GenerateImportFileConfig(ci->c_str(), missingTargets))
{
result = false;
}
}
+
+ this->GenerateMissingTargetsCheckCode(os, missingTargets);
+
return result;
}
//----------------------------------------------------------------------------
+void
+cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string &input)
+{
+ std::string::size_type pos = 0;
+ std::string::size_type lastPos = pos;
+
+ while((pos = input.find("$<INSTALL_PREFIX>", lastPos)) != input.npos)
+ {
+ std::string::size_type endPos = pos + sizeof("$<INSTALL_PREFIX>") - 1;
+ input.replace(pos, endPos - pos, "${_IMPORT_PREFIX}");
+ lastPos = endPos;
+ }
+}
+
+//----------------------------------------------------------------------------
bool
-cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
+cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config,
+ std::vector<std::string> &missingTargets)
{
// Skip configurations not enabled for this export.
if(!this->IEGen->InstallsForConfig(config))
@@ -127,7 +232,7 @@ cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
this->GenerateImportHeaderCode(os, config);
// Generate the per-config target information.
- this->GenerateImportConfig(os, config);
+ this->GenerateImportConfig(os, config, missingTargets);
// End with the import file footer.
this->GenerateImportFooterCode(os);
@@ -142,29 +247,9 @@ cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
void
cmExportInstallFileGenerator
::GenerateImportTargetsConfig(std::ostream& os,
- const char* config, std::string const& suffix)
+ const char* config, std::string const& suffix,
+ std::vector<std::string> &missingTargets)
{
- // Add code to compute the installation prefix relative to the
- // import file location.
- const char* installDest = this->IEGen->GetDestination();
- if(!cmSystemTools::FileIsFullPath(installDest))
- {
- std::string dest = installDest;
- os << "# Compute the installation prefix relative to this file.\n"
- << "GET_FILENAME_COMPONENT(_IMPORT_PREFIX "
- << "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
- while(!dest.empty())
- {
- os <<
- "GET_FILENAME_COMPONENT(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
- dest = cmSystemTools::GetFilenamePath(dest);
- }
- os << "\n";
-
- // Import location properties may reference this variable.
- this->ImportPrefix = "${_IMPORT_PREFIX}/";
- }
-
// Add each target in the set to the export.
for(std::vector<cmTargetExport*>::const_iterator
tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
@@ -191,10 +276,13 @@ cmExportInstallFileGenerator
if(!properties.empty())
{
// Get the rest of the target details.
- std::vector<std::string> missingTargets;
this->SetImportDetailProperties(config, suffix,
te->Target, properties, missingTargets);
+ this->SetImportLinkInterface(config, suffix,
+ cmGeneratorExpression::InstallInterface,
+ te->Target, properties, missingTargets);
+
// TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
// is done. Then this can be a propagated include directory.
@@ -202,22 +290,11 @@ cmExportInstallFileGenerator
// properties);
// Generate code in the export file.
- this->GenerateMissingTargetsCheckCode(os, missingTargets);
this->GenerateImportPropertyCode(os, config, te->Target, properties);
this->GenerateImportedFileChecksCode(os, te->Target, properties,
importedLocations);
}
}
-
- this->GenerateImportedFileCheckLoop(os);
-
- // Cleanup the import prefix variable.
- if(!this->ImportPrefix.empty())
- {
- os << "# Cleanup temporary variables.\n"
- << "SET(_IMPORT_PREFIX)\n"
- << "\n";
- }
}
//----------------------------------------------------------------------------
@@ -385,7 +462,7 @@ cmExportInstallFileGenerator
{
const char* installDest = this->IEGen->GetDestination();
cmOStringStream e;
- e << "INSTALL(EXPORT \""
+ e << "install(EXPORT \""
<< this->IEGen->GetExportSet()->GetName()
<< "\") given absolute "
<< "DESTINATION \"" << installDest << "\" but the export "
@@ -403,7 +480,7 @@ cmExportInstallFileGenerator
int occurrences)
{
cmOStringStream e;
- e << "INSTALL(EXPORT \""
+ e << "install(EXPORT \""
<< this->IEGen->GetExportSet()->GetName()
<< "\" ...) "
<< "includes target \"" << depender->GetName()
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index e719ecc..20dd57a 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -15,10 +15,7 @@
#include "cmExportFileGenerator.h"
class cmInstallExportGenerator;
-class cmInstallFilesGenerator;
class cmInstallTargetGenerator;
-class cmTargetExport;
-class cmExportSet;
/** \class cmExportInstallFileGenerator
* \brief Generate a file exporting targets from an install tree.
@@ -56,13 +53,16 @@ protected:
virtual bool GenerateMainFile(std::ostream& os);
virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config,
- std::string const& suffix);
+ std::string const& suffix,
+ std::vector<std::string> &missingTargets);
virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmMakefile* mf,
cmTarget* depender,
cmTarget* dependee);
+ virtual void ReplaceInstallPrefix(std::string &input);
+
void ComplainAboutMissingTarget(cmTarget* depender,
cmTarget* dependee,
int occurrences);
@@ -72,7 +72,8 @@ protected:
/** Generate a per-configuration file for the targets. */
- bool GenerateImportFileConfig(const char* config);
+ bool GenerateImportFileConfig(const char* config,
+ std::vector<std::string> &missingTargets);
/** Fill in properties indicating installed file locations. */
void SetImportLocationProperty(const char* config,
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
new file mode 100644
index 0000000..75f2651
--- /dev/null
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -0,0 +1,114 @@
+/*============================================================================
+ 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 "cmExportTryCompileFileGenerator.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorExpressionDAGChecker.h"
+
+//----------------------------------------------------------------------------
+bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
+{
+ std::set<cmTarget*> emitted;
+ std::set<cmTarget*> emittedDeps;
+ while(!this->Exports.empty())
+ {
+ cmTarget* te = this->Exports.back();
+ this->Exports.pop_back();
+ if (emitted.insert(te).second)
+ {
+ emittedDeps.insert(te);
+ this->GenerateImportTargetCode(os, te);
+
+ ImportPropertyMap properties;
+
+ this->FindTargets("INTERFACE_INCLUDE_DIRECTORIES", te, emittedDeps);
+ this->FindTargets("INTERFACE_COMPILE_DEFINITIONS", te, emittedDeps);
+
+ this->PopulateProperties(te, properties, emittedDeps);
+
+ this->GenerateInterfaceProperties(te, os, properties);
+ }
+ }
+ return true;
+}
+
+std::string cmExportTryCompileFileGenerator::FindTargets(const char *propName,
+ cmTarget *tgt,
+ std::set<cmTarget*> &emitted)
+{
+ const char *prop = tgt->GetProperty(propName);
+ if(!prop)
+ {
+ return std::string();
+ }
+
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ tgt->GetName(),
+ propName, 0, 0);
+
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
+
+ cmTarget dummyHead;
+ dummyHead.SetType(cmTarget::EXECUTABLE, "try_compile_dummy_exe");
+ dummyHead.SetMakefile(tgt->GetMakefile());
+
+ std::string result = cge->Evaluate(tgt->GetMakefile(), this->Config,
+ false, &dummyHead, tgt, &dagChecker);
+
+ const std::set<cmTarget*> &allTargets = cge->GetAllTargetsSeen();
+ for(std::set<cmTarget*>::const_iterator li = allTargets.begin();
+ li != allTargets.end(); ++li)
+ {
+ if(emitted.insert(*li).second)
+ {
+ this->Exports.push_back(*li);
+ }
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportTryCompileFileGenerator::PopulateProperties(cmTarget* target,
+ ImportPropertyMap& properties,
+ std::set<cmTarget*> &emitted)
+{
+ cmPropertyMap props = target->GetProperties();
+ for(cmPropertyMap::const_iterator i = props.begin(); i != props.end(); ++i)
+ {
+ properties[i->first] = i->second.GetValue();
+
+ if(i->first.find("IMPORTED_LINK_INTERFACE_LIBRARIES") == 0)
+ {
+ const std::string libs = i->second.GetValue();
+
+ std::string evalResult = this->FindTargets(i->first.c_str(),
+ target, emitted);
+
+ std::vector<std::string> depends;
+ cmSystemTools::ExpandListArgument(evalResult, depends);
+ for(std::vector<std::string>::const_iterator li = depends.begin();
+ li != depends.end(); ++li)
+ {
+ cmTarget *tgt = target->GetMakefile()->FindTargetToUse(li->c_str());
+ if(tgt && emitted.insert(tgt).second)
+ {
+ this->Exports.push_back(tgt);
+ }
+ }
+ }
+ }
+}
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
new file mode 100644
index 0000000..ed393ab
--- /dev/null
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -0,0 +1,55 @@
+/*============================================================================
+ 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 cmExportInstallFileGenerator_h
+#define cmExportInstallFileGenerator_h
+
+#include "cmExportFileGenerator.h"
+
+class cmInstallExportGenerator;
+class cmInstallTargetGenerator;
+
+class cmExportTryCompileFileGenerator: public cmExportFileGenerator
+{
+public:
+ /** Set the list of targets to export. */
+ void SetExports(const std::vector<cmTarget*> &exports)
+ { this->Exports = exports; }
+ void SetConfig(const char *config) { this->Config = config; }
+protected:
+
+ // Implement virtual methods from the superclass.
+ virtual bool GenerateMainFile(std::ostream& os);
+
+ virtual void GenerateImportTargetsConfig(std::ostream&,
+ const char*,
+ std::string const&,
+ std::vector<std::string>&) {}
+ virtual void HandleMissingTarget(std::string&,
+ std::vector<std::string>&,
+ cmMakefile*,
+ cmTarget*,
+ cmTarget*) {}
+
+ void PopulateProperties(cmTarget* target,
+ ImportPropertyMap& properties,
+ std::set<cmTarget*> &emitted);
+
+private:
+ std::string FindTargets(const char *prop, cmTarget *tgt,
+ std::set<cmTarget*> &emitted);
+
+
+ std::vector<cmTarget*> Exports;
+ const char *Config;
+};
+
+#endif
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 25b13e5..f6f4cef 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -621,7 +621,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
->GetGeneratorTarget(target);
// the compilerdefines for this target
- std::string cdefs = gtgt->GetCompileDefinitions();
+ std::string cdefs = target->GetCompileDefinitions(buildType);
if(!cdefs.empty())
{
@@ -640,10 +640,8 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
std::set<std::string> uniqIncludeDirs;
std::vector<std::string> includes;
- const char *config = target->GetMakefile()
- ->GetDefinition("CMAKE_BUILD_TYPE");
target->GetMakefile()->GetLocalGenerator()->
- GetIncludeDirectories(includes, gtgt, "C", config);
+ GetIncludeDirectories(includes, gtgt, "C", buildType);
for(std::vector<std::string>::const_iterator dirIt=includes.begin();
dirIt != includes.end();
++dirIt)
@@ -811,6 +809,11 @@ std::string cmExtraCodeBlocksGenerator::BuildMakeCommand(
command += " VERBOSE=1 ";
command += target;
}
+ else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
+ {
+ command += " -v ";
+ command += target;
+ }
else
{
std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 96b8a09..97ab086 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -38,6 +38,7 @@ cmExtraEclipseCDT4Generator
this->SupportedGlobalGenerators.push_back("Unix Makefiles");
this->SupportsVirtualFolders = true;
+ this->GenerateLinkedResources = true;
}
//----------------------------------------------------------------------------
@@ -83,6 +84,9 @@ void cmExtraEclipseCDT4Generator::Generate()
this->HomeDirectory = mf->GetHomeDirectory();
this->HomeOutputDirectory = mf->GetHomeOutputDirectory();
+ this->GenerateLinkedResources = mf->IsOn(
+ "CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES");
+
this->IsOutOfSourceBuild = (this->HomeDirectory!=this->HomeOutputDirectory);
this->GenerateSourceProject = (this->IsOutOfSourceBuild &&
@@ -501,6 +505,10 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(
linkName2 += ti->first;
this->AppendLinkedResource(fout, linkName2, "virtual:/virtual",
VirtualFolder);
+ if (!this->GenerateLinkedResources)
+ {
+ break; // skip generating the linked resources to the source files
+ }
std::vector<cmSourceGroup> sourceGroups=makefile->GetSourceGroups();
// get the files from the source lists then add them to the groups
cmTarget* tgt = const_cast<cmTarget*>(&ti->second);
@@ -555,6 +563,11 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(
void cmExtraEclipseCDT4Generator::CreateLinksToSubprojects(
cmGeneratedFileStream& fout, const std::string& baseDir)
{
+ if (!this->GenerateLinkedResources)
+ {
+ return;
+ }
+
// for each sub project create a linked resource to the source dir
// - only if it is an out-of-source build
this->AppendLinkedResource(fout, "[Subprojects]",
@@ -579,7 +592,8 @@ void cmExtraEclipseCDT4Generator::CreateLinksToSubprojects(
this->GetEclipsePath(linkSourceDirectory),
LinkToFolder
);
- this->SrcLinkedResources.push_back(it->first);
+ // Don't add it to the srcLinkedResources, because listing multiple
+ // directories confuses the Eclipse indexer (#13596).
}
}
}
@@ -730,15 +744,16 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
/* I don't know what the pathentry kind="src" are good for, e.g. autocompletion
* works also without them. Done wrong, the indexer complains, see #12417
* and #12213.
+ * According to #13596, this entry at least limits the directories the
+ * indexer is searching for files. So now the "src" entry contains only
+ * the linked resource to CMAKE_SOURCE_DIR.
* The CDT documentation is very terse on that:
* "CDT_SOURCE: Entry kind constant describing a path entry identifying a
* folder containing source code to be compiled."
* Also on the cdt-dev list didn't bring any information:
* http://web.archiveorange.com/archive/v/B4NlJDNIpYoOS1SbxFNy
- * So I'm disabling them for now, hoping that somebody will report if something
- * is not workging anymore.
* Alex */
-#ifdef DO_CREATE_SRC_PATH_ENTRIES
+
for (std::vector<std::string>::const_iterator
it = this->SrcLinkedResources.begin();
it != this->SrcLinkedResources.end();
@@ -755,7 +770,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
excludeFromOut += this->EscapeForXML(*it) + "/|";
}
}
-#endif
+
excludeFromOut += "**/CMakeFiles/";
fout << "<pathentry excluding=\"" << excludeFromOut
<< "\" kind=\"out\" path=\"\"/>\n";
diff --git a/Source/cmExtraEclipseCDT4Generator.h b/Source/cmExtraEclipseCDT4Generator.h
index 37ce65e..31ad68d 100644
--- a/Source/cmExtraEclipseCDT4Generator.h
+++ b/Source/cmExtraEclipseCDT4Generator.h
@@ -109,6 +109,7 @@ private:
std::string HomeOutputDirectory;
bool IsOutOfSourceBuild;
bool GenerateSourceProject;
+ bool GenerateLinkedResources;
bool SupportsVirtualFolders;
};
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
new file mode 100644
index 0000000..e4802d5
--- /dev/null
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -0,0 +1,503 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2004-2009 Kitware, Inc.
+ Copyright 2004 Alexander Neundorf (neundorf@kde.org)
+
+ 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 "cmExtraSublimeTextGenerator.h"
+#include "cmake.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalUnixMakefileGenerator3.h"
+#include "cmLocalGenerator.h"
+#include "cmLocalUnixMakefileGenerator3.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmXMLSafe.h"
+
+#include <cmsys/SystemTools.hxx>
+
+/*
+Sublime Text 2 Generator
+Author: Morné Chamberlain
+This generator was initially based off of the CodeBlocks generator.
+
+Some useful URLs:
+Homepage:
+http://www.sublimetext.com/
+
+File format docs:
+http://www.sublimetext.com/docs/2/projects.html
+http://sublimetext.info/docs/en/reference/build_systems.html
+*/
+
+//----------------------------------------------------------------------------
+void cmExtraSublimeTextGenerator
+::GetDocumentation(cmDocumentationEntry& entry, const char*) const
+{
+ entry.Name = this->GetName();
+ entry.Brief = "Generates Sublime Text 2 project files.";
+ entry.Full =
+ "Project files for Sublime Text 2 will be created in the top directory "
+ "and in every subdirectory which features a CMakeLists.txt file "
+ "containing a PROJECT() call. "
+ "Additionally Makefiles (or build.ninja files) are 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.";
+}
+
+cmExtraSublimeTextGenerator::cmExtraSublimeTextGenerator()
+:cmExternalMakefileProjectGenerator()
+{
+#if defined(_WIN32)
+ this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
+ this->SupportedGlobalGenerators.push_back("NMake Makefiles");
+// disable until somebody actually tests it:
+// this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
+#endif
+ this->SupportedGlobalGenerators.push_back("Ninja");
+ this->SupportedGlobalGenerators.push_back("Unix Makefiles");
+}
+
+
+void cmExtraSublimeTextGenerator::Generate()
+{
+ // for each sub project in the project create a sublime text 2 project
+ for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
+ it = this->GlobalGenerator->GetProjectMap().begin();
+ it!= this->GlobalGenerator->GetProjectMap().end();
+ ++it)
+ {
+ // create a project file
+ this->CreateProjectFile(it->second);
+ }
+}
+
+
+void cmExtraSublimeTextGenerator::CreateProjectFile(
+ const std::vector<cmLocalGenerator*>& lgs)
+{
+ const cmMakefile* mf=lgs[0]->GetMakefile();
+ std::string outputDir=mf->GetStartOutputDirectory();
+ std::string projectName=mf->GetProjectName();
+
+ const std::string filename =
+ outputDir + "/" + projectName + ".sublime-project";
+
+ this->CreateNewProjectFile(lgs, filename);
+}
+
+void cmExtraSublimeTextGenerator
+ ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
+ const std::string& filename)
+{
+ const cmMakefile* mf=lgs[0]->GetMakefile();
+ cmGeneratedFileStream fout(filename.c_str());
+ if(!fout)
+ {
+ return;
+ }
+
+ const std::string &sourceRootRelativeToOutput = cmSystemTools::RelativePath(
+ mf->GetHomeOutputDirectory(),
+ mf->GetHomeDirectory());
+ // Write the folder entries to the project file
+ fout << "{\n";
+ fout << "\t\"folders\":\n\t[\n\t";
+ if (!sourceRootRelativeToOutput.empty())
+ {
+ fout << "\t{\n\t\t\t\"path\": \"" << sourceRootRelativeToOutput << "\"";
+ const std::string &outputRelativeToSourceRoot =
+ cmSystemTools::RelativePath(mf->GetHomeDirectory(),
+ mf->GetHomeOutputDirectory());
+ if ((!outputRelativeToSourceRoot.empty()) &&
+ ((outputRelativeToSourceRoot.length() < 3) ||
+ (outputRelativeToSourceRoot.substr(0, 3) != "../")))
+ {
+ fout << ",\n\t\t\t\"folder_exclude_patterns\": [\"" <<
+ outputRelativeToSourceRoot << "\"]";
+ }
+ }
+ else
+ {
+ fout << "\t{\n\t\t\t\"path\": \"./\"";
+ }
+ fout << "\n\t\t}";
+ // End of the folders section
+ fout << "\n\t]";
+
+ // Write the beginning of the build systems section to the project file
+ fout << ",\n\t\"build_systems\":\n\t[\n\t";
+
+ // Set of include directories over all targets (sublime text/sublimeclang
+ // doesn't currently support these settings per build system, only project
+ // wide
+ MapSourceFileFlags sourceFileFlags;
+ AppendAllTargets(lgs, mf, fout, sourceFileFlags);
+
+ // End of build_systems
+ fout << "\n\t]";
+ fout << "\n\t}";
+}
+
+
+void cmExtraSublimeTextGenerator::
+ AppendAllTargets(const std::vector<cmLocalGenerator*>& lgs,
+ const cmMakefile* mf,
+ cmGeneratedFileStream& fout,
+ MapSourceFileFlags& sourceFileFlags)
+{
+ std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ std::string compiler = "";
+ if (!lgs.empty())
+ {
+ this->AppendTarget(fout, "all", lgs[0], 0, make.c_str(), mf,
+ compiler.c_str(), sourceFileFlags, true);
+ this->AppendTarget(fout, "clean", lgs[0], 0, make.c_str(), mf,
+ compiler.c_str(), sourceFileFlags, false);
+ }
+
+ // add all executable and library targets and some of the GLOBAL
+ // and UTILITY targets
+ for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
+ lg!=lgs.end(); lg++)
+ {
+ cmMakefile* makefile=(*lg)->GetMakefile();
+ cmTargets& targets=makefile->GetTargets();
+ for (cmTargets::iterator ti = targets.begin();
+ ti != targets.end(); ti++)
+ {
+ switch(ti->second.GetType())
+ {
+ case cmTarget::GLOBAL_TARGET:
+ {
+ bool insertTarget = false;
+ // Only add the global targets from CMAKE_BINARY_DIR,
+ // not from the subdirs
+ if (strcmp(makefile->GetStartOutputDirectory(),
+ makefile->GetHomeOutputDirectory())==0)
+ {
+ insertTarget = true;
+ // only add the "edit_cache" target if it's not ccmake, because
+ // this will not work within the IDE
+ if (ti->first == "edit_cache")
+ {
+ const char* editCommand = makefile->GetDefinition
+ ("CMAKE_EDIT_COMMAND");
+ if (editCommand == 0)
+ {
+ insertTarget = false;
+ }
+ else if (strstr(editCommand, "ccmake")!=NULL)
+ {
+ insertTarget = false;
+ }
+ }
+ }
+ if (insertTarget)
+ {
+ this->AppendTarget(fout, ti->first.c_str(), *lg, 0,
+ make.c_str(), makefile, compiler.c_str(),
+ sourceFileFlags, false);
+ }
+ }
+ break;
+ case cmTarget::UTILITY:
+ // Add all utility targets, except the Nightly/Continuous/
+ // Experimental-"sub"targets as e.g. NightlyStart
+ if (((ti->first.find("Nightly")==0) &&(ti->first!="Nightly"))
+ || ((ti->first.find("Continuous")==0)&&(ti->first!="Continuous"))
+ || ((ti->first.find("Experimental")==0)
+ && (ti->first!="Experimental")))
+ {
+ break;
+ }
+
+ this->AppendTarget(fout, ti->first.c_str(), *lg, 0,
+ make.c_str(), makefile, compiler.c_str(),
+ sourceFileFlags, false);
+ break;
+ case cmTarget::EXECUTABLE:
+ case cmTarget::STATIC_LIBRARY:
+ case cmTarget::SHARED_LIBRARY:
+ case cmTarget::MODULE_LIBRARY:
+ case cmTarget::OBJECT_LIBRARY:
+ {
+ this->AppendTarget(fout, ti->first.c_str(), *lg, &ti->second,
+ make.c_str(), makefile, compiler.c_str(),
+ sourceFileFlags, false);
+ std::string fastTarget = ti->first;
+ fastTarget += "/fast";
+ this->AppendTarget(fout, fastTarget.c_str(), *lg, &ti->second,
+ make.c_str(), makefile, compiler.c_str(),
+ sourceFileFlags, false);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+void cmExtraSublimeTextGenerator::
+ AppendTarget(cmGeneratedFileStream& fout,
+ const char* targetName,
+ cmLocalGenerator* lg,
+ cmTarget* target,
+ const char* make,
+ const cmMakefile* makefile,
+ const char*, //compiler
+ MapSourceFileFlags& sourceFileFlags,
+ bool firstTarget)
+{
+
+ if (target != 0)
+ {
+ cmGeneratorTarget *gtgt = this->GlobalGenerator
+ ->GetGeneratorTarget(target);
+ std::vector<cmSourceFile*> const& sourceFiles = target->GetSourceFiles();
+ std::vector<cmSourceFile*>::const_iterator sourceFilesEnd =
+ sourceFiles.end();
+ for (std::vector<cmSourceFile*>::const_iterator iter =
+ sourceFiles.begin(); iter != sourceFilesEnd; ++iter)
+ {
+ cmSourceFile* sourceFile = *iter;
+ MapSourceFileFlags::iterator sourceFileFlagsIter =
+ sourceFileFlags.find(sourceFile->GetFullPath());
+ if (sourceFileFlagsIter == sourceFileFlags.end())
+ {
+ sourceFileFlagsIter =
+ sourceFileFlags.insert(MapSourceFileFlags::value_type(
+ sourceFile->GetFullPath(), std::vector<std::string>())).first;
+ }
+ std::vector<std::string>& flags = sourceFileFlagsIter->second;
+ std::string flagsString =
+ this->ComputeFlagsForObject(*iter, lg, target, gtgt);
+ std::string definesString =
+ this->ComputeDefines(*iter, lg, target, gtgt);
+ flags.clear();
+ cmsys::RegularExpression flagRegex;
+ // Regular expression to extract compiler flags from a string
+ // https://gist.github.com/3944250
+ const char* regexString =
+ "(^|[ ])-[DIOUWfgs][^= ]+(=\\\"[^\"]+\\\"|=[^\"][^ ]+)?";
+ flagRegex.compile(regexString);
+ std::string workString = flagsString + " " + definesString;
+ while (flagRegex.find(workString))
+ {
+ std::string::size_type start = flagRegex.start();
+ if (workString[start] == ' ')
+ {
+ start++;
+ }
+ flags.push_back(workString.substr(start,
+ flagRegex.end() - start));
+ if (flagRegex.end() < workString.size())
+ {
+ workString = workString.substr(flagRegex.end());
+ }
+ else
+ {
+ workString = "";
+ }
+ }
+ }
+ }
+
+ // Ninja uses ninja.build files (look for a way to get the output file name
+ // from cmMakefile or something)
+ std::string makefileName;
+ if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
+ {
+ makefileName = "build.ninja";
+ }
+ else
+ {
+ makefileName = "Makefile";
+ }
+ if (!firstTarget)
+ {
+ fout << ",\n\t";
+ }
+ fout << "\t{\n\t\t\t\"name\": \"" << makefile->GetProjectName() << " - " <<
+ targetName << "\",\n";
+ fout << "\t\t\t\"cmd\": [" <<
+ this->BuildMakeCommand(make, makefileName.c_str(), targetName) <<
+ "],\n";
+ fout << "\t\t\t\"working_dir\": \"${project_path}\",\n";
+ fout << "\t\t\t\"file_regex\": \"^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$\"\n";
+ fout << "\t\t}";
+}
+
+// Create the command line for building the given target using the selected
+// make
+std::string cmExtraSublimeTextGenerator::BuildMakeCommand(
+ const std::string& make, const char* makefile, const char* target)
+{
+ std::string command = "\"";
+ command += make + "\"";
+ if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0)
+ {
+ std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
+ command += ", \"/NOLOGO\", \"/f\", \"";
+ command += makefileName + "\"";
+ command += ", \"VERBOSE=1\", \"";
+ command += target;
+ command += "\"";
+ }
+ else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
+ {
+ std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
+ command += ", \"-f\", \"";
+ command += makefileName + "\"";
+ command += ", \"-v\", \"";
+ command += target;
+ command += "\"";
+ }
+ else
+ {
+ std::string makefileName;
+ if (strcmp(this->GlobalGenerator->GetName(), "MinGW Makefiles")==0)
+ {
+ // no escaping of spaces in this case, see
+ // http://public.kitware.com/Bug/view.php?id=10014
+ makefileName = makefile;
+ }
+ else
+ {
+ makefileName = cmSystemTools::ConvertToOutputPath(makefile);
+ }
+ command += ", \"-f\", \"";
+ command += makefileName + "\"";
+ command += ", \"VERBOSE=1\", \"";
+ command += target;
+ command += "\"";
+ }
+ return command;
+}
+
+// TODO: Most of the code is picked up from the Ninja generator, refactor it.
+std::string
+cmExtraSublimeTextGenerator::ComputeFlagsForObject(cmSourceFile* source,
+ cmLocalGenerator* lg,
+ cmTarget *target,
+ cmGeneratorTarget* gtgt)
+{
+ std::string flags;
+
+ cmMakefile *makefile = lg->GetMakefile();
+ const char* language = source->GetLanguage();
+ if (language == NULL)
+ {
+ language = "C";
+ }
+ const char* config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ // Add language-specific flags.
+ lg->AddLanguageFlags(flags, language, config);
+
+ lg->AddArchitectureFlags(flags, gtgt, language, config);
+
+ // TODO: Fortran support.
+ // // Fortran-specific flags computed for this target.
+ // if(*l == "Fortran")
+ // {
+ // this->AddFortranFlags(flags);
+ // }
+
+ // Add shared-library flags if needed.
+ lg->AddCMP0018Flags(flags, target, language, config);
+
+ // Add include directory flags.
+ {
+ std::vector<std::string> includes;
+ lg->GetIncludeDirectories(includes, gtgt, language, config);
+ std::string includeFlags =
+ lg->GetIncludeFlags(includes, language, true); // full include paths
+ lg->AppendFlags(flags, includeFlags.c_str());
+ }
+
+ // Append old-style preprocessor definition flags.
+ 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"));
+ }
+ }
+
+ // Add source file specific flags.
+ lg->AppendFlags(flags, target->GetProperty("COMPILE_FLAGS"));
+
+ // TODO: Handle Apple frameworks.
+
+ return flags;
+}
+
+// TODO: Refactor with
+// void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
+std::string
+cmExtraSublimeTextGenerator::
+ComputeDefines(cmSourceFile *source, cmLocalGenerator* lg, cmTarget *target,
+ cmGeneratorTarget*)
+
+{
+ std::set<std::string> defines;
+ cmMakefile *makefile = lg->GetMakefile();
+ const char* language = source->GetLanguage();
+ if (language == NULL)
+ {
+ language = "";
+ }
+ const char* config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+
+ // Add the export symbol definition for shared library objects.
+ if(const char* exportMacro = target->GetExportMacro())
+ {
+ lg->AppendDefines(defines, exportMacro);
+ }
+
+ // Add preprocessor definitions for this target and configuration.
+ lg->AppendDefines(defines, target->GetCompileDefinitions(config));
+ lg->AppendDefines(defines, source->GetProperty("COMPILE_DEFINITIONS"));
+ {
+ std::string defPropName = "COMPILE_DEFINITIONS_";
+ defPropName += cmSystemTools::UpperCase(config);
+ lg->AppendDefines(defines, source->GetProperty(defPropName.c_str()));
+ }
+
+ std::string definesString;
+ lg->JoinDefines(defines, definesString, language);
+
+ return definesString;
+}
diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h
new file mode 100644
index 0000000..7902593
--- /dev/null
+++ b/Source/cmExtraSublimeTextGenerator.h
@@ -0,0 +1,89 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2004-2009 Kitware, Inc.
+ Copyright 2004 Alexander Neundorf (neundorf@kde.org)
+
+ 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 cmExtraSublimeTextGenerator_h
+#define cmExtraSublimeTextGenerator_h
+
+#include "cmExternalMakefileProjectGenerator.h"
+#include "cmSourceFile.h"
+
+class cmLocalGenerator;
+class cmMakefile;
+class cmTarget;
+class cmGeneratedFileStream;
+class cmGeneratorTarget;
+
+/** \class cmExtraSublimeTextGenerator
+ * \brief Write Sublime Text 2 project files for Makefile based projects
+ */
+class cmExtraSublimeTextGenerator : public cmExternalMakefileProjectGenerator
+{
+public:
+ typedef std::map<std::string, std::vector<std::string> > MapSourceFileFlags;
+ cmExtraSublimeTextGenerator();
+
+ virtual const char* GetName() const
+ { return cmExtraSublimeTextGenerator::GetActualName();}
+ static const char* GetActualName()
+ { return "Sublime Text 2";}
+ static cmExternalMakefileProjectGenerator* New()
+ { return new cmExtraSublimeTextGenerator; }
+ /** Get the documentation entry for this generator. */
+ virtual void GetDocumentation(cmDocumentationEntry& entry,
+ const char* fullName) const;
+
+ virtual void Generate();
+private:
+
+ void CreateProjectFile(const std::vector<cmLocalGenerator*>& lgs);
+
+ void CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
+ const std::string& filename);
+
+ /** Appends all targets as build systems to the project file and get all
+ * include directories and compiler definitions used.
+ */
+ void AppendAllTargets(const std::vector<cmLocalGenerator*>& lgs,
+ const cmMakefile* mf,
+ cmGeneratedFileStream& fout,
+ MapSourceFileFlags& sourceFileFlags);
+ /** Returns the build command that needs to be executed to build the
+ * specified target.
+ */
+ std::string BuildMakeCommand(const std::string& make, const char* makefile,
+ const char* target);
+ /** Appends the specified target to the generated project file as a Sublime
+ * Text build system.
+ */
+ void AppendTarget(cmGeneratedFileStream& fout,
+ const char* targetName,
+ cmLocalGenerator* lg,
+ cmTarget* target,
+ const char* make,
+ const cmMakefile* makefile,
+ const char* compiler,
+ MapSourceFileFlags& sourceFileFlags, bool firstTarget);
+ /**
+ * Compute the flags for compilation of object files for a given @a language.
+ * @note Generally it is the value of the variable whose name is computed
+ * by LanguageFlagsVarName().
+ */
+ std::string ComputeFlagsForObject(cmSourceFile *source,
+ cmLocalGenerator* lg,
+ cmTarget *target,
+ cmGeneratorTarget* gtgt);
+
+ std::string ComputeDefines(cmSourceFile *source, cmLocalGenerator* lg,
+ cmTarget *target, cmGeneratorTarget* gtgt);
+};
+
+#endif
diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index a4aa75a..b08c335 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -37,9 +37,13 @@ bool cmFLTKWrapUICommand
// get the list of GUI files from which .cxx and .h will be generated
std::string outputDirectory = this->Makefile->GetCurrentOutputDirectory();
+ {
// Some of the generated files are *.h so the directory "GUI"
// where they are created have to be added to the include path
- this->Makefile->AddIncludeDirectory( outputDirectory.c_str() );
+ std::vector<std::string> outputDirectories;
+ outputDirectories.push_back(outputDirectory);
+ this->Makefile->AddIncludeDirectories( outputDirectories );
+ }
for(std::vector<std::string>::iterator i = (newArgs.begin() + 1);
i != newArgs.end(); i++)
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 8de24b3..018ce7e 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -17,11 +17,14 @@
#include "cmFileTimeComparison.h"
#include "cmCryptoHash.h"
+#include "cmTimestamp.h"
+
#if defined(CMAKE_BUILD_WITH_CMAKE)
#include "cm_curl.h"
#endif
#undef GetCurrentDirectory
+#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -160,6 +163,10 @@ bool cmFileCommand
{
return this->HandleCMakePathCommand(args, true);
}
+ else if ( subCommand == "TIMESTAMP" )
+ {
+ return this->HandleTimestampCommand(args);
+ }
std::string e = "does not recognize sub-command "+subCommand;
this->SetError(e.c_str());
@@ -705,11 +712,8 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
bool recurse)
{
- if ( args.size() < 2 )
- {
- this->SetError("GLOB requires at least a variable name");
- return false;
- }
+ // File commands has at least one argument
+ assert(args.size() > 1);
std::vector<std::string>::const_iterator i = args.begin();
@@ -843,11 +847,8 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
bool cmFileCommand::HandleMakeDirectoryCommand(
std::vector<std::string> const& args)
{
- if(args.size() < 2 )
- {
- this->SetError("called with incorrect number of arguments");
- return false;
- }
+ // File command has at least one argument
+ assert(args.size() > 1);
std::vector<std::string>::const_iterator i = args.begin();
@@ -2408,7 +2409,8 @@ bool cmFileCommand::HandleRemove(std::vector<std::string> const& args,
fileName += "/" + *i;
}
- if(cmSystemTools::FileIsDirectory(fileName.c_str()) && recurse)
+ if(cmSystemTools::FileIsDirectory(fileName.c_str()) &&
+ !cmSystemTools::FileIsSymlink(fileName.c_str()) && recurse)
{
cmSystemTools::RemoveADirectory(fileName.c_str());
}
@@ -3246,3 +3248,54 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
return false;
#endif
}
+
+//----------------------------------------------------------------------------
+bool cmFileCommand::HandleTimestampCommand(
+ std::vector<std::string> const& args)
+{
+ if(args.size() < 3)
+ {
+ this->SetError("sub-command TIMESTAMP requires at least two arguments.");
+ return false;
+ }
+ else if(args.size() > 5)
+ {
+ this->SetError("sub-command TIMESTAMP takes at most four arguments.");
+ return false;
+ }
+
+ unsigned int argsIndex = 1;
+
+ const std::string& filename = args[argsIndex++];
+
+ const std::string& outputVariable = args[argsIndex++];
+
+ std::string formatString;
+ if(args.size() > argsIndex && args[argsIndex] != "UTC")
+ {
+ formatString = args[argsIndex++];
+ }
+
+ bool utcFlag = false;
+ if(args.size() > argsIndex)
+ {
+ if(args[argsIndex] == "UTC")
+ {
+ utcFlag = true;
+ }
+ else
+ {
+ std::string e = " TIMESTAMP sub-command does not recognize option " +
+ args[argsIndex] + ".";
+ this->SetError(e.c_str());
+ return false;
+ }
+ }
+
+ cmTimestamp timestamp;
+ std::string result = timestamp.FileModificationTime(
+ filename.c_str(), formatString, utcFlag);
+ this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str());
+
+ return true;
+}
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index b4aa903..5973fa7 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -87,9 +87,11 @@ public:
" [TLS_VERIFY on|off] [TLS_CAINFO file])\n"
" 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"
"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.\n"
+ "if it does not exist. (If the file is a build input, use "
+ "configure_file to update the file only when its content changes.)\n"
"APPEND will write a message into a file same as WRITE, except "
"it will append it to the end of the file\n"
"READ will read the content of a file and store it into the "
@@ -199,6 +201,12 @@ public:
"If SHOW_PROGRESS is specified, progress information will be printed "
"as status messages until the operation is complete."
"\n"
+ "TIMESTAMP will write a string representation of "
+ "the modification time of filename to variable.\n"
+ "Should the command be unable to obtain a timestamp "
+ "variable will be set to the empty string \"\".\n"
+ "See documentation of the string TIMESTAMP sub-command for more details."
+ "\n"
"The file() command also provides COPY and INSTALL signatures:\n"
" file(<COPY|INSTALL> files... DESTINATION <dir>\n"
" [FILE_PERMISSIONS permissions...]\n"
@@ -259,6 +267,8 @@ protected:
bool HandleInstallCommand(std::vector<std::string> const& args);
bool HandleDownloadCommand(std::vector<std::string> const& args);
bool HandleUploadCommand(std::vector<std::string> const& args);
+
+ bool HandleTimestampCommand(std::vector<std::string> const& args);
};
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index a54bf7c..7ce0032 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -15,6 +15,8 @@ cmFindBase::cmFindBase()
{
this->AlreadyInCache = false;
this->AlreadyInCacheWithoutMetaInfo = false;
+ this->NamesPerDir = false;
+ this->NamesPerDirAllowed = false;
}
//----------------------------------------------------------------------------
@@ -213,6 +215,19 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
compatibility = false;
newStyle = true;
}
+ else if (args[j] == "NAMES_PER_DIR")
+ {
+ doing = DoingNone;
+ if(this->NamesPerDirAllowed)
+ {
+ this->NamesPerDir = true;
+ }
+ else
+ {
+ this->SetError("does not support NAMES_PER_DIR");
+ return false;
+ }
+ }
else if (args[j] == "NO_SYSTEM_PATH")
{
doing = DoingNone;
@@ -345,13 +360,13 @@ void cmFindBase::AddPrefixPaths(std::vector<std::string> const& in_paths,
{
dir += "/";
}
- if(subdir == "lib")
+ if(subdir == "include" || subdir == "lib")
{
const char* arch =
this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE");
if(arch && *arch)
{
- this->AddPathInternal(dir+"lib/"+arch, pathType);
+ this->AddPathInternal(dir+subdir+"/"+arch, pathType);
}
}
std::string add = dir + subdir;
diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h
index eac1885..84b0330 100644
--- a/Source/cmFindBase.h
+++ b/Source/cmFindBase.h
@@ -49,6 +49,8 @@ protected:
cmStdString VariableDocumentation;
cmStdString VariableName;
std::vector<std::string> Names;
+ bool NamesPerDir;
+ bool NamesPerDirAllowed;
// CMAKE_*_PATH CMAKE_SYSTEM_*_PATH FRAMEWORK|LIBRARY|INCLUDE|PROGRAM
cmStdString EnvironmentPath; // LIB,INCLUDE
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index 0080e55..4af7e11 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -17,6 +17,7 @@
cmFindLibraryCommand::cmFindLibraryCommand()
{
this->EnvironmentPath = "LIB";
+ this->NamesPerDirAllowed = true;
}
//----------------------------------------------------------------------------
@@ -44,6 +45,9 @@ void cmFindLibraryCommand::GenerateDocumentation()
"SEARCH_XXX", "library");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"XXX_SUBDIR", "lib");
+ cmSystemTools::ReplaceString(this->GenericDocumentation,
+ "NAMES name1 [name2 ...]",
+ "NAMES name1 [name2 ...] [NAMES_PER_DIR]");
cmSystemTools::ReplaceString(
this->GenericDocumentation,
"XXX_EXTRA_PREFIX_ENTRY",
@@ -53,6 +57,12 @@ void cmFindLibraryCommand::GenerateDocumentation()
"CMAKE_FIND_ROOT_PATH_MODE_LIBRARY");
this->GenericDocumentation +=
"\n"
+ "When more than one value is given to the NAMES option this command "
+ "by default will consider one name at a time and search every directory "
+ "for it. "
+ "The NAMES_PER_DIR option tells this command to consider one directory "
+ "at a time and search for all names in it."
+ "\n"
"If the library found is a framework, then VAR will be set to "
"the full path to the framework <fullPath>/A.framework. "
"When a full path to a framework is used as a library, "
@@ -220,18 +230,19 @@ struct cmFindLibraryHelper
// Keep track of the best library file found so far.
typedef std::vector<std::string>::size_type size_type;
std::string BestPath;
- size_type BestPrefix;
- size_type BestSuffix;
// Support for OpenBSD shared library naming: lib<name>.so.<major>.<minor>
bool OpenBSD;
- unsigned int BestMajor;
- unsigned int BestMinor;
- // Current name under consideration.
- cmsys::RegularExpression NameRegex;
- bool TryRawName;
- std::string RawName;
+ // Current names under consideration.
+ struct Name
+ {
+ bool TryRaw;
+ std::string Raw;
+ cmsys::RegularExpression Regex;
+ Name(): TryRaw(false) {}
+ };
+ std::vector<Name> Names;
// Current full path under consideration.
std::string TestPath;
@@ -249,8 +260,9 @@ struct cmFindLibraryHelper
suffix) - this->Suffixes.begin();
}
bool HasValidSuffix(std::string const& name);
- void SetName(std::string const& name);
+ void AddName(std::string const& name);
bool CheckDirectory(std::string const& path);
+ bool CheckDirectoryForName(std::string const& path, Name& name);
};
//----------------------------------------------------------------------------
@@ -273,14 +285,6 @@ cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf):
this->OpenBSD =
this->Makefile->GetCMakeInstance()
->GetPropertyAsBool("FIND_LIBRARY_USE_OPENBSD_VERSIONING");
-
- this->TryRawName = false;
-
- // No library file has yet been found.
- this->BestPrefix = this->Prefixes.size();
- this->BestSuffix = this->Suffixes.size();
- this->BestMajor = 0;
- this->BestMinor = 0;
}
//----------------------------------------------------------------------------
@@ -353,11 +357,13 @@ bool cmFindLibraryHelper::HasValidSuffix(std::string const& name)
}
//----------------------------------------------------------------------------
-void cmFindLibraryHelper::SetName(std::string const& name)
+void cmFindLibraryHelper::AddName(std::string const& name)
{
+ Name entry;
+
// Consider checking the raw name too.
- this->TryRawName = this->HasValidSuffix(name);
- this->RawName = name;
+ entry.TryRaw = this->HasValidSuffix(name);
+ entry.Raw = name;
// Build a regular expression to match library names.
std::string regex = "^";
@@ -369,21 +375,37 @@ void cmFindLibraryHelper::SetName(std::string const& name)
regex += "(\\.[0-9]+\\.[0-9]+)?";
}
regex += "$";
- this->NameRegex.compile(regex.c_str());
+ entry.Regex.compile(regex.c_str());
+ this->Names.push_back(entry);
}
//----------------------------------------------------------------------------
bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
{
+ for(std::vector<Name>::iterator i = this->Names.begin();
+ i != this->Names.end(); ++i)
+ {
+ if(this->CheckDirectoryForName(path, *i))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------------
+bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
+ Name& name)
+{
// If the original library name provided by the user matches one of
// the suffixes, try it first. This allows users to search
// specifically for a static library on some platforms (on MS tools
// one cannot tell just from the library name whether it is a static
// library or an import library).
- if(this->TryRawName)
+ if(name.TryRaw)
{
this->TestPath = path;
- this->TestPath += this->RawName;
+ this->TestPath += name.Raw;
if(cmSystemTools::FileExists(this->TestPath.c_str(), true))
{
this->BestPath =
@@ -393,6 +415,12 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
}
}
+ // No library file has yet been found.
+ size_type bestPrefix = this->Prefixes.size();
+ size_type bestSuffix = this->Suffixes.size();
+ unsigned int bestMajor = 0;
+ unsigned int bestMinor = 0;
+
// Search for a file matching the library name regex.
std::string dir = path;
cmSystemTools::ConvertToUnixSlashes(dir);
@@ -406,7 +434,7 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
#else
std::string const& testName = origName;
#endif
- if(this->NameRegex.find(testName))
+ if(name.Regex.find(testName))
{
this->TestPath = path;
this->TestPath += origName;
@@ -416,25 +444,25 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
// best name found so far. Earlier prefixes are preferred,
// followed by earlier suffixes. For OpenBSD, shared library
// version extensions are compared.
- size_type prefix = this->GetPrefixIndex(this->NameRegex.match(1));
- size_type suffix = this->GetSuffixIndex(this->NameRegex.match(2));
+ size_type prefix = this->GetPrefixIndex(name.Regex.match(1));
+ size_type suffix = this->GetSuffixIndex(name.Regex.match(2));
unsigned int major = 0;
unsigned int minor = 0;
if(this->OpenBSD)
{
- sscanf(this->NameRegex.match(3).c_str(), ".%u.%u", &major, &minor);
+ sscanf(name.Regex.match(3).c_str(), ".%u.%u", &major, &minor);
}
- if(this->BestPath.empty() || prefix < this->BestPrefix ||
- (prefix == this->BestPrefix && suffix < this->BestSuffix) ||
- (prefix == this->BestPrefix && suffix == this->BestSuffix &&
- (major > this->BestMajor ||
- (major == this->BestMajor && minor > this->BestMinor))))
+ if(this->BestPath.empty() || prefix < bestPrefix ||
+ (prefix == bestPrefix && suffix < bestSuffix) ||
+ (prefix == bestPrefix && suffix == bestSuffix &&
+ (major > bestMajor ||
+ (major == bestMajor && minor > bestMinor))))
{
this->BestPath = this->TestPath;
- this->BestPrefix = prefix;
- this->BestSuffix = suffix;
- this->BestMajor = major;
- this->BestMinor = minor;
+ bestPrefix = prefix;
+ bestSuffix = suffix;
+ bestMajor = major;
+ bestMinor = minor;
}
}
}
@@ -447,6 +475,42 @@ bool cmFindLibraryHelper::CheckDirectory(std::string const& path)
//----------------------------------------------------------------------------
std::string cmFindLibraryCommand::FindNormalLibrary()
{
+ if(this->NamesPerDir)
+ {
+ return this->FindNormalLibraryNamesPerDir();
+ }
+ else
+ {
+ return this->FindNormalLibraryDirsPerName();
+ }
+}
+
+//----------------------------------------------------------------------------
+std::string cmFindLibraryCommand::FindNormalLibraryNamesPerDir()
+{
+ // Search for all names in each directory.
+ cmFindLibraryHelper helper(this->Makefile);
+ for(std::vector<std::string>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end() ; ++ni)
+ {
+ helper.AddName(*ni);
+ }
+ // Search every directory.
+ for(std::vector<std::string>::const_iterator
+ p = this->SearchPaths.begin(); p != this->SearchPaths.end(); ++p)
+ {
+ if(helper.CheckDirectory(*p))
+ {
+ return helper.BestPath;
+ }
+ }
+ // Couldn't find the library.
+ return "";
+}
+
+//----------------------------------------------------------------------------
+std::string cmFindLibraryCommand::FindNormalLibraryDirsPerName()
+{
// Search the entire path for each name.
cmFindLibraryHelper helper(this->Makefile);
for(std::vector<std::string>::const_iterator ni = this->Names.begin();
@@ -454,7 +518,7 @@ std::string cmFindLibraryCommand::FindNormalLibrary()
{
// Switch to searching for this name.
std::string const& name = *ni;
- helper.SetName(name);
+ helper.AddName(name);
// Search every directory.
for(std::vector<std::string>::const_iterator
@@ -474,19 +538,60 @@ std::string cmFindLibraryCommand::FindNormalLibrary()
//----------------------------------------------------------------------------
std::string cmFindLibraryCommand::FindFrameworkLibrary()
{
- // Search for a framework of each name in the entire search path.
+ if(this->NamesPerDir)
+ {
+ return this->FindFrameworkLibraryNamesPerDir();
+ }
+ else
+ {
+ return this->FindFrameworkLibraryDirsPerName();
+ }
+}
+
+//----------------------------------------------------------------------------
+std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir()
+{
+ std::string fwPath;
+ // Search for all names in each search path.
+ for(std::vector<std::string>::const_iterator di = this->SearchPaths.begin();
+ di != this->SearchPaths.end(); ++di)
+ {
+ for(std::vector<std::string>::const_iterator ni = this->Names.begin();
+ ni != this->Names.end() ; ++ni)
+ {
+ fwPath = *di;
+ fwPath += *ni;
+ fwPath += ".framework";
+ if(cmSystemTools::FileIsDirectory(fwPath.c_str()))
+ {
+ return cmSystemTools::CollapseFullPath(fwPath.c_str());
+ }
+ }
+ }
+
+ // No framework found.
+ return "";
+}
+
+//----------------------------------------------------------------------------
+std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName()
+{
+ std::string fwPath;
+ // Search for each name in all search paths.
for(std::vector<std::string>::const_iterator ni = this->Names.begin();
ni != this->Names.end() ; ++ni)
{
- // Search the paths for a framework with this name.
- std::string fwName = *ni;
- fwName += ".framework";
- std::string fwPath = cmSystemTools::FindDirectory(fwName.c_str(),
- this->SearchPaths,
- true);
- if(!fwPath.empty())
+ for(std::vector<std::string>::const_iterator
+ di = this->SearchPaths.begin();
+ di != this->SearchPaths.end(); ++di)
{
- return fwPath;
+ fwPath = *di;
+ fwPath += *ni;
+ fwPath += ".framework";
+ if(cmSystemTools::FileIsDirectory(fwPath.c_str()))
+ {
+ return cmSystemTools::CollapseFullPath(fwPath.c_str());
+ }
}
}
diff --git a/Source/cmFindLibraryCommand.h b/Source/cmFindLibraryCommand.h
index 455348a..cd0fce8 100644
--- a/Source/cmFindLibraryCommand.h
+++ b/Source/cmFindLibraryCommand.h
@@ -70,7 +70,11 @@ protected:
virtual void GenerateDocumentation();
private:
std::string FindNormalLibrary();
+ std::string FindNormalLibraryNamesPerDir();
+ std::string FindNormalLibraryDirsPerName();
std::string FindFrameworkLibrary();
+ std::string FindFrameworkLibraryNamesPerDir();
+ std::string FindFrameworkLibraryDirsPerName();
};
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 470ceca..aa3a73d 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -95,7 +95,8 @@ void cmFindPackageCommand::GenerateDocumentation()
"Finds and loads settings from an external project. "
"<package>_FOUND will be set to indicate whether the package was found. "
"When the package is found package-specific information is provided "
- "through variables documented by the package itself. "
+ "through variables and imported targets documented by the package "
+ "itself. "
"The QUIET option disables messages if the package cannot be found. "
"The MODULE option disables the second signature documented below. "
"The REQUIRED option stops processing with an error message if the "
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index 9524924..6a43298 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -45,8 +45,10 @@ void cmFindPathCommand::GenerateDocumentation()
"SEARCH_XXX", "file in a directory");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"XXX_SUBDIR", "include");
- cmSystemTools::ReplaceString(this->GenericDocumentation,
- "XXX_EXTRA_PREFIX_ENTRY", "");
+ cmSystemTools::ReplaceString(
+ this->GenericDocumentation,
+ "XXX_EXTRA_PREFIX_ENTRY",
+ " <prefix>/include/<arch> if CMAKE_LIBRARY_ARCHITECTURE is set, and\n");
cmSystemTools::ReplaceString(this->GenericDocumentation,
"CMAKE_FIND_ROOT_PATH_MODE_XXX",
"CMAKE_FIND_ROOT_PATH_MODE_INCLUDE");
diff --git a/Source/cmFunctionCommand.h b/Source/cmFunctionCommand.h
index 730a7a7..0a029dc 100644
--- a/Source/cmFunctionCommand.h
+++ b/Source/cmFunctionCommand.h
@@ -90,7 +90,9 @@ public:
"will have the actual values of the arguments passed in. This "
"facilitates creating functions with optional arguments. Additionally "
"ARGV holds the list of all arguments given to the function and ARGN "
- "holds the list of argument past the last expected argument."
+ "holds the list of arguments past the last expected argument."
+ "\n"
+ "A function opens a new scope: see set(var PARENT_SCOPE) for details."
"\n"
"See the cmake_policy() command documentation for the behavior of "
"policies inside functions."
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 7d8df37..ab8bd13 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -25,55 +25,55 @@
//----------------------------------------------------------------------------
cmGeneratorExpression::cmGeneratorExpression(
cmListFileBacktrace const& backtrace):
- Backtrace(backtrace), CompiledExpression(0)
+ Backtrace(backtrace)
{
}
//----------------------------------------------------------------------------
-const cmCompiledGeneratorExpression &
+cmsys::auto_ptr<cmCompiledGeneratorExpression>
cmGeneratorExpression::Parse(std::string const& input)
{
return this->Parse(input.c_str());
}
//----------------------------------------------------------------------------
-const cmCompiledGeneratorExpression &
+cmsys::auto_ptr<cmCompiledGeneratorExpression>
cmGeneratorExpression::Parse(const char* input)
{
- cmGeneratorExpressionLexer l;
- std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(input);
- bool needsParsing = l.GetSawGeneratorExpression();
- std::vector<cmGeneratorExpressionEvaluator*> evaluators;
-
- if (needsParsing)
- {
- cmGeneratorExpressionParser p(tokens);
- p.Parse(evaluators);
- }
-
- delete this->CompiledExpression;
- this->CompiledExpression = new cmCompiledGeneratorExpression(
- this->Backtrace,
- evaluators,
- input,
- needsParsing);
- return *this->CompiledExpression;
+ return cmsys::auto_ptr<cmCompiledGeneratorExpression>(
+ new cmCompiledGeneratorExpression(
+ this->Backtrace,
+ input));
}
cmGeneratorExpression::~cmGeneratorExpression()
{
- delete this->CompiledExpression;
}
//----------------------------------------------------------------------------
const char *cmCompiledGeneratorExpression::Evaluate(
cmMakefile* mf, const char* config, bool quiet,
- cmGeneratorTarget *target,
+ cmTarget *headTarget,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+{
+ return this->Evaluate(mf,
+ config,
+ quiet,
+ headTarget,
+ headTarget,
+ dagChecker);
+}
+
+//----------------------------------------------------------------------------
+const char *cmCompiledGeneratorExpression::Evaluate(
+ cmMakefile* mf, const char* config, bool quiet,
+ cmTarget *headTarget,
+ cmTarget *currentTarget,
cmGeneratorExpressionDAGChecker *dagChecker) const
{
if (!this->NeedsParsing)
{
- return this->Input;
+ return this->Input.c_str();
}
this->Output = "";
@@ -88,32 +88,54 @@ const char *cmCompiledGeneratorExpression::Evaluate(
context.Config = config;
context.Quiet = quiet;
context.HadError = false;
- context.Target = target;
+ context.HadContextSensitiveCondition = false;
+ context.HeadTarget = headTarget;
+ context.CurrentTarget = currentTarget ? currentTarget : headTarget;
context.Backtrace = this->Backtrace;
for ( ; it != end; ++it)
{
this->Output += (*it)->Evaluate(&context, dagChecker);
+
+ for(std::set<cmStdString>::const_iterator
+ p = context.SeenTargetProperties.begin();
+ p != context.SeenTargetProperties.end(); ++p)
+ {
+ this->SeenTargetProperties.insert(*p);
+ }
if (context.HadError)
{
this->Output = "";
break;
}
}
+ if (!context.HadError)
+ {
+ this->HadContextSensitiveCondition = context.HadContextSensitiveCondition;
+ }
- this->Targets = context.Targets;
+ this->DependTargets = context.DependTargets;
+ this->AllTargetsSeen = context.AllTargets;
// TODO: Return a std::string from here instead?
return this->Output.c_str();
}
cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
cmListFileBacktrace const& backtrace,
- const std::vector<cmGeneratorExpressionEvaluator*> &evaluators,
- const char *input, bool needsParsing)
- : Backtrace(backtrace), Evaluators(evaluators), Input(input),
- NeedsParsing(needsParsing)
+ const char *input)
+ : Backtrace(backtrace), Input(input ? input : ""),
+ HadContextSensitiveCondition(false)
{
+ cmGeneratorExpressionLexer l;
+ std::vector<cmGeneratorExpressionToken> tokens =
+ l.Tokenize(this->Input.c_str());
+ this->NeedsParsing = l.GetSawGeneratorExpression();
+ if (this->NeedsParsing)
+ {
+ cmGeneratorExpressionParser p(tokens);
+ p.Parse(this->Evaluators);
+ }
}
@@ -131,15 +153,42 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
}
}
-std::string cmGeneratorExpression::Preprocess(const std::string &input,
- PreprocessContext context)
+//----------------------------------------------------------------------------
+std::string cmGeneratorExpression::StripEmptyListElements(
+ const std::string &input)
{
- if (context != StripAllGeneratorExpressions)
- {
- assert(!"cmGeneratorExpression::Preprocess called with invalid args");
- return std::string();
- }
+ std::string result;
+
+ const char *c = input.c_str();
+ bool skipSemiColons = true;
+ for ( ; *c; ++c)
+ {
+ if(c[0] == ';')
+ {
+ if(skipSemiColons)
+ {
+ continue;
+ }
+ skipSemiColons = true;
+ }
+ else
+ {
+ skipSemiColons = false;
+ }
+ result += *c;
+ }
+
+ if (!result.empty() && *(result.end() - 1) == ';')
+ {
+ result.resize(result.size() - 1);
+ }
+
+ return result;
+}
+//----------------------------------------------------------------------------
+static std::string stripAllGeneratorExpressions(const std::string &input)
+{
std::string result;
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
@@ -176,5 +225,195 @@ std::string cmGeneratorExpression::Preprocess(const std::string &input,
lastPos = pos;
}
result += input.substr(lastPos);
- return result;
+ return cmGeneratorExpression::StripEmptyListElements(result);
+}
+
+//----------------------------------------------------------------------------
+static std::string stripExportInterface(const std::string &input,
+ cmGeneratorExpression::PreprocessContext context)
+{
+ std::string result;
+
+ std::string::size_type pos = 0;
+ std::string::size_type lastPos = pos;
+ while (true)
+ {
+ std::string::size_type bPos = input.find("$<BUILD_INTERFACE:", lastPos);
+ std::string::size_type iPos = input.find("$<INSTALL_INTERFACE:", lastPos);
+
+ if (bPos == std::string::npos && iPos == std::string::npos)
+ {
+ break;
+ }
+
+ if (bPos == std::string::npos)
+ {
+ pos = iPos;
+ }
+ else if (iPos == std::string::npos)
+ {
+ pos = bPos;
+ }
+ else
+ {
+ pos = (bPos < iPos) ? bPos : iPos;
+ }
+
+ result += input.substr(lastPos, pos - lastPos);
+ const bool gotInstallInterface = input[pos + 2] == 'I';
+ pos += gotInstallInterface ? sizeof("$<INSTALL_INTERFACE:") - 1
+ : sizeof("$<BUILD_INTERFACE:") - 1;
+ int nestingLevel = 1;
+ const char *c = input.c_str() + pos;
+ const char * const cStart = c;
+ for ( ; *c; ++c)
+ {
+ if(c[0] == '$' && c[1] == '<')
+ {
+ ++nestingLevel;
+ ++c;
+ continue;
+ }
+ if(c[0] == '>')
+ {
+ --nestingLevel;
+ if (nestingLevel != 0)
+ {
+ continue;
+ }
+ if(context == cmGeneratorExpression::BuildInterface
+ && !gotInstallInterface)
+ {
+ result += input.substr(pos, c - cStart);
+ }
+ else if(context == cmGeneratorExpression::InstallInterface
+ && gotInstallInterface)
+ {
+ result += input.substr(pos, c - cStart);
+ }
+ break;
+ }
+ }
+ const std::string::size_type traversed = (c - cStart) + 1;
+ if (!*c)
+ {
+ result += std::string(gotInstallInterface ? "$<INSTALL_INTERFACE:"
+ : "$<BUILD_INTERFACE:")
+ + input.substr(pos, traversed);
+ }
+ pos += traversed;
+ lastPos = pos;
+ }
+ result += input.substr(lastPos);
+
+ return cmGeneratorExpression::StripEmptyListElements(result);
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorExpression::Split(const std::string &input,
+ std::vector<std::string> &output)
+{
+ std::string::size_type pos = 0;
+ std::string::size_type lastPos = pos;
+ while((pos = input.find("$<", lastPos)) != input.npos)
+ {
+ std::string part = input.substr(lastPos, pos - lastPos);
+ std::string preGenex;
+ if (!part.empty())
+ {
+ std::string::size_type startPos = input.rfind(";", pos);
+ if (startPos == std::string::npos)
+ {
+ preGenex = part;
+ part = "";
+ }
+ else if (startPos != pos - 1 && startPos >= lastPos)
+ {
+ part = input.substr(lastPos, startPos - lastPos);
+ preGenex = input.substr(startPos + 1, pos - startPos - 1);
+ }
+ if(!part.empty())
+ {
+ cmSystemTools::ExpandListArgument(part.c_str(), output);
+ }
+ }
+ pos += 2;
+ int nestingLevel = 1;
+ const char *c = input.c_str() + pos;
+ const char * const cStart = c;
+ for ( ; *c; ++c)
+ {
+ if(c[0] == '$' && c[1] == '<')
+ {
+ ++nestingLevel;
+ ++c;
+ continue;
+ }
+ if(c[0] == '>')
+ {
+ --nestingLevel;
+ if (nestingLevel == 0)
+ {
+ break;
+ }
+ }
+ }
+ for ( ; *c; ++c)
+ {
+ // Capture the part after the genex and before the next ';'
+ if(c[0] == ';')
+ {
+ --c;
+ break;
+ }
+ }
+ const std::string::size_type traversed = (c - cStart) + 1;
+ output.push_back(preGenex + "$<" + input.substr(pos, traversed));
+ pos += traversed;
+ lastPos = pos;
+ }
+ if (lastPos < input.size())
+ {
+ cmSystemTools::ExpandListArgument(input.substr(lastPos), output);
+ }
+}
+
+//----------------------------------------------------------------------------
+std::string cmGeneratorExpression::Preprocess(const std::string &input,
+ PreprocessContext context)
+{
+ if (context == StripAllGeneratorExpressions)
+ {
+ return stripAllGeneratorExpressions(input);
+ }
+ else if (context == BuildInterface || context == InstallInterface)
+ {
+ return stripExportInterface(input, context);
+ }
+
+ assert(!"cmGeneratorExpression::Preprocess called with invalid args");
+ return std::string();
+}
+
+//----------------------------------------------------------------------------
+std::string::size_type cmGeneratorExpression::Find(const std::string &input)
+{
+ const std::string::size_type openpos = input.find("$<");
+ if (openpos != std::string::npos
+ && input.find(">", openpos) != std::string::npos)
+ {
+ return openpos;
+ }
+ return std::string::npos;
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpression::IsValidTargetName(const std::string &input)
+{
+ cmsys::RegularExpression targetNameValidator;
+ // The ':' is supported to allow use with IMPORTED targets. At least
+ // Qt 4 and 5 IMPORTED targets use ':' as the namespace delimiter.
+ targetNameValidator.compile("^[A-Za-z0-9_.:+-]+$");
+
+ return targetNameValidator.find(input.c_str());
}
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 29d3f44..86b6f25 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -14,13 +14,14 @@
#define cmGeneratorExpression_h
#include "cmStandardIncludes.h"
+#include "cmListFileCache.h"
#include <stack>
#include <cmsys/RegularExpression.hxx>
+#include <cmsys/auto_ptr.hxx>
class cmTarget;
-class cmGeneratorTarget;
class cmMakefile;
class cmListFileBacktrace;
@@ -45,22 +46,32 @@ public:
cmGeneratorExpression(cmListFileBacktrace const& backtrace);
~cmGeneratorExpression();
- const cmCompiledGeneratorExpression& Parse(std::string const& input);
- const cmCompiledGeneratorExpression& Parse(const char* input);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse(
+ std::string const& input);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse(const char* input);
enum PreprocessContext {
- StripAllGeneratorExpressions
+ StripAllGeneratorExpressions,
+ BuildInterface,
+ InstallInterface
};
static std::string Preprocess(const std::string &input,
PreprocessContext context);
+ static void Split(const std::string &input,
+ std::vector<std::string> &output);
+
+ static std::string::size_type Find(const std::string &input);
+
+ static bool IsValidTargetName(const std::string &input);
+
+ static std::string StripEmptyListElements(const std::string &input);
private:
cmGeneratorExpression(const cmGeneratorExpression &);
void operator=(const cmGeneratorExpression &);
cmListFileBacktrace const& Backtrace;
- cmCompiledGeneratorExpression *CompiledExpression;
};
class cmCompiledGeneratorExpression
@@ -68,32 +79,59 @@ class cmCompiledGeneratorExpression
public:
const char* Evaluate(cmMakefile* mf, const char* config,
bool quiet = false,
- cmGeneratorTarget *target = 0,
+ cmTarget *headTarget = 0,
+ cmTarget *currentTarget = 0,
cmGeneratorExpressionDAGChecker *dagChecker = 0) const;
+ const char* Evaluate(cmMakefile* mf, const char* config,
+ bool quiet,
+ cmTarget *headTarget,
+ cmGeneratorExpressionDAGChecker *dagChecker) const;
/** Get set of targets found during evaluations. */
std::set<cmTarget*> const& GetTargets() const
- { return this->Targets; }
+ { return this->DependTargets; }
+
+ std::set<cmStdString> const& GetSeenTargetProperties() const
+ { return this->SeenTargetProperties; }
+
+ std::set<cmTarget*> const& GetAllTargetsSeen() const
+ { return this->AllTargetsSeen; }
~cmCompiledGeneratorExpression();
+ std::string GetInput() const
+ {
+ return this->Input;
+ }
+
+ cmListFileBacktrace GetBacktrace() const
+ {
+ return this->Backtrace;
+ }
+ bool GetHadContextSensitiveCondition() const
+ {
+ return this->HadContextSensitiveCondition;
+ }
+
private:
cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
- const std::vector<cmGeneratorExpressionEvaluator*> &evaluators,
- const char *input, bool needsParsing);
+ const char *input);
friend class cmGeneratorExpression;
cmCompiledGeneratorExpression(const cmCompiledGeneratorExpression &);
void operator=(const cmCompiledGeneratorExpression &);
- cmListFileBacktrace const& Backtrace;
- const std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
- const char* const Input;
- const bool NeedsParsing;
+ cmListFileBacktrace Backtrace;
+ std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
+ const std::string Input;
+ bool NeedsParsing;
- mutable std::set<cmTarget*> Targets;
+ mutable std::set<cmTarget*> DependTargets;
+ mutable std::set<cmTarget*> AllTargetsSeen;
+ mutable std::set<cmStdString> SeenTargetProperties;
mutable std::string Output;
+ mutable bool HadContextSensitiveCondition;
};
#endif
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index bfb0ddf..5cb50b9 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -24,13 +24,40 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
: Parent(parent), Target(target), Property(property),
Content(content), Backtrace(backtrace)
{
- this->IsDAG = this->isDAG();
+ const cmGeneratorExpressionDAGChecker *top = this;
+ const cmGeneratorExpressionDAGChecker *p = this->Parent;
+ while (p)
+ {
+ top = p;
+ p = p->Parent;
+ }
+ this->CheckResult = this->checkGraph();
+
+ if (CheckResult == DAG && (top->EvaluatingIncludeDirectories()
+ || top->EvaluatingCompileDefinitions()))
+ {
+ std::map<cmStdString, std::set<cmStdString> >::const_iterator it
+ = top->Seen.find(target);
+ if (it != top->Seen.end())
+ {
+ const std::set<cmStdString> &propSet = it->second;
+ const std::set<cmStdString>::const_iterator i = propSet.find(property);
+ if (i != propSet.end())
+ {
+ this->CheckResult = ALREADY_SEEN;
+ return;
+ }
+ }
+ const_cast<cmGeneratorExpressionDAGChecker *>(top)
+ ->Seen[target].insert(property);
+ }
}
//----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::check() const
+cmGeneratorExpressionDAGChecker::Result
+cmGeneratorExpressionDAGChecker::check() const
{
- return this->IsDAG;
+ return this->CheckResult;
}
//----------------------------------------------------------------------------
@@ -38,7 +65,7 @@ void cmGeneratorExpressionDAGChecker::reportError(
cmGeneratorExpressionContext *context,
const std::string &expr)
{
- if (this->IsDAG)
+ if (this->CheckResult == DAG)
{
return;
}
@@ -57,7 +84,7 @@ void cmGeneratorExpressionDAGChecker::reportError(
e << "Error evaluating generator expression:\n"
<< " " << expr << "\n"
<< "Self reference on target \""
- << context->Target->GetName() << "\".\n";
+ << context->HeadTarget->GetName() << "\".\n";
context->Makefile->GetCMakeInstance()
->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
parent->Backtrace);
@@ -91,16 +118,53 @@ void cmGeneratorExpressionDAGChecker::reportError(
}
//----------------------------------------------------------------------------
-bool cmGeneratorExpressionDAGChecker::isDAG() const
+cmGeneratorExpressionDAGChecker::Result
+cmGeneratorExpressionDAGChecker::checkGraph() const
{
const cmGeneratorExpressionDAGChecker *parent = this->Parent;
while (parent)
{
if (this->Target == parent->Target && this->Property == parent->Property)
{
- return false;
+ return (parent == this->Parent) ? SELF_REFERENCE : CYCLIC_REFERENCE;
}
parent = parent->Parent;
}
- return true;
+ return DAG;
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries()
+{
+ const cmGeneratorExpressionDAGChecker *top = this;
+ const cmGeneratorExpressionDAGChecker *parent = this->Parent;
+ while (parent)
+ {
+ top = parent;
+ parent = parent->Parent;
+ }
+
+ const char *prop = top->Property.c_str();
+ 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);
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::EvaluatingIncludeDirectories() const
+{
+ const char *prop = this->Property.c_str();
+ return (strcmp(prop, "INCLUDE_DIRECTORIES") == 0
+ || strcmp(prop, "INTERFACE_INCLUDE_DIRECTORIES") == 0 );
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const
+{
+ const char *prop = this->Property.c_str();
+ return (strcmp(prop, "COMPILE_DEFINITIONS") == 0
+ || strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0
+ || strncmp(prop, "COMPILE_DEFINITIONS_", 20) == 0);
}
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index ffc84f8..62a5cdf 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -25,20 +25,33 @@ struct cmGeneratorExpressionDAGChecker
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *parent);
- bool check() const;
+ enum Result {
+ DAG,
+ SELF_REFERENCE,
+ CYCLIC_REFERENCE,
+ ALREADY_SEEN
+ };
+
+ Result check() const;
void reportError(cmGeneratorExpressionContext *context,
const std::string &expr);
+
+ bool EvaluatingLinkLibraries();
+ bool EvaluatingIncludeDirectories() const;
+ bool EvaluatingCompileDefinitions() const;
+
private:
- bool isDAG() const;
+ Result checkGraph() const;
private:
const cmGeneratorExpressionDAGChecker * const Parent;
const std::string Target;
const std::string Property;
+ std::map<cmStdString, std::set<cmStdString> > Seen;
const GeneratorExpressionContent * const Content;
const cmListFileBacktrace Backtrace;
- bool IsDAG;
+ Result CheckResult;
};
#endif
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 2e123a4..a01a0f8 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -18,6 +18,8 @@
#include <cmsys/String.h>
+#include <assert.h>
+
//----------------------------------------------------------------------------
#if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x510
static
@@ -47,6 +49,8 @@ struct cmGeneratorExpressionNode
virtual bool GeneratesContent() const { return true; }
+ virtual bool RequiresLiteralInput() const { return false; }
+
virtual bool AcceptsSingleArbitraryContentParameter() const
{ return false; }
@@ -66,6 +70,8 @@ static const struct ZeroNode : public cmGeneratorExpressionNode
virtual bool GeneratesContent() const { return false; }
+ virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
+
std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *,
const GeneratorExpressionContent *,
@@ -94,6 +100,12 @@ static const struct OneNode : public cmGeneratorExpressionNode
} oneNode;
//----------------------------------------------------------------------------
+static const struct OneNode buildInterfaceNode;
+
+//----------------------------------------------------------------------------
+static const struct ZeroNode installInterfaceNode;
+
+//----------------------------------------------------------------------------
#define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
static const struct OP ## Node : public cmGeneratorExpressionNode \
{ \
@@ -215,6 +227,22 @@ static const struct CommaNode : public cmGeneratorExpressionNode
} commaNode;
//----------------------------------------------------------------------------
+static const struct SemicolonNode : public cmGeneratorExpressionNode
+{
+ SemicolonNode() {}
+
+ virtual int NumExpectedParameters() const { return 0; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return ";";
+ }
+} semicolonNode;
+
+//----------------------------------------------------------------------------
static const struct ConfigurationNode : public cmGeneratorExpressionNode
{
ConfigurationNode() {}
@@ -226,6 +254,7 @@ static const struct ConfigurationNode : public cmGeneratorExpressionNode
const GeneratorExpressionContent *,
cmGeneratorExpressionDAGChecker *) const
{
+ context->HadContextSensitiveCondition = true;
return context->Config ? context->Config : "";
}
} configurationNode;
@@ -250,16 +279,94 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
"Expression syntax not recognized.");
return std::string();
}
+ context->HadContextSensitiveCondition = true;
if (!context->Config)
{
return parameters.front().empty() ? "1" : "0";
}
- return cmsysString_strcasecmp(parameters.begin()->c_str(),
- context->Config) == 0 ? "1" : "0";
+ if (cmsysString_strcasecmp(parameters.begin()->c_str(),
+ context->Config) == 0)
+ {
+ return "1";
+ }
+
+ if (context->CurrentTarget
+ && context->CurrentTarget->IsImported())
+ {
+ const char* loc = 0;
+ const char* imp = 0;
+ std::string suffix;
+ return context->CurrentTarget->GetMappedConfig(context->Config,
+ &loc,
+ &imp,
+ suffix) ? "1" : "0";
+ }
+ return "0";
}
} configurationTestNode;
+
+//----------------------------------------------------------------------------
+static const char* targetPropertyTransitiveWhitelist[] = {
+ "INTERFACE_INCLUDE_DIRECTORIES"
+ , "INTERFACE_COMPILE_DEFINITIONS"
+};
+
+std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
+ cmTarget *target,
+ cmTarget *headTarget,
+ cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ const std::string &interfacePropertyName)
+{
+ cmGeneratorExpression ge(context->Backtrace);
+
+ std::string sep;
+ std::string depString;
+ for (std::vector<std::string>::const_iterator
+ it = libraries.begin();
+ it != libraries.end(); ++it)
+ {
+ if (*it == target->GetName())
+ {
+ // Broken code can have a target in its own link interface.
+ // Don't follow such link interface entries so as not to create a
+ // self-referencing loop.
+ continue;
+ }
+ if (context->Makefile->FindTargetToUse(it->c_str()))
+ {
+ depString +=
+ sep + "$<TARGET_PROPERTY:" + *it + "," + interfacePropertyName + ">";
+ sep = ";";
+ }
+ }
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(depString);
+ std::string linkedTargetsContent = cge->Evaluate(context->Makefile,
+ context->Config,
+ context->Quiet,
+ headTarget,
+ target,
+ dagChecker);
+ if (cge->GetHadContextSensitiveCondition())
+ {
+ context->HadContextSensitiveCondition = true;
+ }
+ return linkedTargetsContent;
+}
+
+//----------------------------------------------------------------------------
+struct TransitiveWhitelistCompare
+{
+ explicit TransitiveWhitelistCompare(const std::string &needle)
+ : Needle(needle) {}
+ bool operator() (const char *item)
+ { return strcmp(item, this->Needle.c_str()) == 0; }
+private:
+ std::string Needle;
+};
+
//----------------------------------------------------------------------------
static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{
@@ -280,15 +387,22 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
"$<TARGET_PROPERTY:...> expression requires one or two parameters");
return std::string();
}
- cmsys::RegularExpression targetNameValidator;
- // The ':' is supported to allow use with IMPORTED targets. At least
- // Qt 4 and 5 IMPORTED targets use ':' as the namespace delimiter.
- targetNameValidator.compile("^[A-Za-z0-9_.:-]+$");
cmsys::RegularExpression propertyNameValidator;
propertyNameValidator.compile("^[A-Za-z0-9_]+$");
- cmGeneratorTarget* target = context->Target;
+ cmTarget* target = context->HeadTarget;
std::string propertyName = *parameters.begin();
+
+ if (!target && parameters.size() == 1)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:prop> may only be used with targets. It may not "
+ "be used with add_custom_command. Specify the target to read a "
+ "property from using the $<TARGET_PROPERTY:tgt,prop> signature "
+ "instead.");
+ return std::string();
+ }
+
if (parameters.size() == 2)
{
if (parameters.begin()->empty() && parameters[1].empty())
@@ -308,7 +422,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
std::string targetName = parameters.front();
propertyName = parameters[1];
- if (!targetNameValidator.find(targetName.c_str()))
+ if (!cmGeneratorExpression::IsValidTargetName(targetName))
{
if (!propertyNameValidator.find(propertyName.c_str()))
{
@@ -320,7 +434,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
"Target name not supported.");
return std::string();
}
- target = context->Makefile->FindGeneratorTargetToUse(
+ target = context->Makefile->FindTargetToUse(
targetName.c_str());
if (!target)
@@ -332,6 +446,16 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
+ context->AllTargets.insert(target);
+ }
+
+ if (target == context->HeadTarget)
+ {
+ // Keep track of the properties seen while processing.
+ // The evaluation of the LINK_LIBRARIES generator expressions
+ // will check this to ensure that properties have one consistent
+ // value for all evaluations.
+ context->SeenTargetProperties.insert(propertyName);
}
if (propertyName.empty())
@@ -349,24 +473,317 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
return std::string();
}
+ assert(target);
+
cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
target->GetName(),
propertyName,
content,
dagCheckerParent);
- if (!dagChecker.check())
+ switch (dagChecker.check())
{
+ case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
dagChecker.reportError(context, content->GetOriginalExpression());
return std::string();
+ case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+ // No error. We just skip cyclic references.
+ return std::string();
+ case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+ for (size_t i = 0;
+ i < (sizeof(targetPropertyTransitiveWhitelist) /
+ sizeof(*targetPropertyTransitiveWhitelist));
+ ++i)
+ {
+ if (targetPropertyTransitiveWhitelist[i] == propertyName)
+ {
+ // No error. We're not going to find anything new here.
+ return std::string();
+ }
+ }
+ case cmGeneratorExpressionDAGChecker::DAG:
+ break;
}
const char *prop = target->GetProperty(propertyName.c_str());
- return prop ? prop : "";
+
+ if (dagCheckerParent)
+ {
+ if (dagCheckerParent->EvaluatingLinkLibraries())
+ {
+ if(!prop)
+ {
+ return std::string();
+ }
+ }
+ else
+ {
+ assert(dagCheckerParent->EvaluatingIncludeDirectories()
+ || dagCheckerParent->EvaluatingCompileDefinitions());
+ }
+ }
+
+ std::string linkedTargetsContent;
+
+ std::string interfacePropertyName;
+
+ if (propertyName == "INTERFACE_INCLUDE_DIRECTORIES"
+ || propertyName == "INCLUDE_DIRECTORIES")
+ {
+ interfacePropertyName = "INTERFACE_INCLUDE_DIRECTORIES";
+ }
+ else if (propertyName == "INTERFACE_COMPILE_DEFINITIONS"
+ || propertyName == "COMPILE_DEFINITIONS"
+ || strncmp(propertyName.c_str(), "COMPILE_DEFINITIONS_", 20) == 0)
+ {
+ interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
+ }
+
+ cmTarget *headTarget = context->HeadTarget ? context->HeadTarget : target;
+
+ const char **transBegin = targetPropertyTransitiveWhitelist;
+ 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)
+ {
+ linkedTargetsContent =
+ getLinkedTargetsContent(iface->Libraries, target,
+ headTarget,
+ context, &dagChecker,
+ interfacePropertyName);
+ }
+ }
+ else if (std::find_if(transBegin, transEnd,
+ TransitiveWhitelistCompare(interfacePropertyName)) != transEnd)
+ {
+ const cmTarget::LinkImplementation *impl = target->GetLinkImplementation(
+ context->Config,
+ headTarget);
+ if(impl)
+ {
+ linkedTargetsContent =
+ getLinkedTargetsContent(impl->Libraries, target,
+ headTarget,
+ context, &dagChecker,
+ interfacePropertyName);
+ }
+ }
+
+ linkedTargetsContent =
+ cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
+
+ if (!prop)
+ {
+ if (target->IsImported())
+ {
+ return linkedTargetsContent;
+ }
+ if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
+ context->Config))
+ {
+ context->HadContextSensitiveCondition = true;
+ return target->GetLinkInterfaceDependentBoolProperty(
+ propertyName,
+ context->Config) ? "1" : "0";
+ }
+ if (target->IsLinkInterfaceDependentStringProperty(propertyName,
+ context->Config))
+ {
+ context->HadContextSensitiveCondition = true;
+ const char *propContent =
+ target->GetLinkInterfaceDependentStringProperty(
+ propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+
+ return linkedTargetsContent;
+ }
+
+ for (size_t i = 0;
+ i < (sizeof(targetPropertyTransitiveWhitelist) /
+ sizeof(*targetPropertyTransitiveWhitelist));
+ ++i)
+ {
+ if (targetPropertyTransitiveWhitelist[i] == interfacePropertyName)
+ {
+ cmGeneratorExpression ge(context->Backtrace);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
+ std::string result = cge->Evaluate(context->Makefile,
+ context->Config,
+ context->Quiet,
+ headTarget,
+ target,
+ &dagChecker);
+
+ if (cge->GetHadContextSensitiveCondition())
+ {
+ context->HadContextSensitiveCondition = true;
+ }
+ if (!linkedTargetsContent.empty())
+ {
+ result += (result.empty() ? "" : ";") + linkedTargetsContent;
+ }
+ return result;
+ }
+ }
+ return prop;
}
} targetPropertyNode;
//----------------------------------------------------------------------------
+static const struct TargetNameNode : public cmGeneratorExpressionNode
+{
+ TargetNameNode() {}
+
+ virtual bool GeneratesContent() const { return true; }
+
+ virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
+ virtual bool RequiresLiteralInput() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return parameters.front();
+ }
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+} targetNameNode;
+
+//----------------------------------------------------------------------------
+static const char* targetPolicyWhitelist[] = {
+ "CMP0003"
+ , "CMP0004"
+ , "CMP0008"
+ , "CMP0020"
+};
+
+cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy)
+{
+#define RETURN_POLICY(POLICY) \
+ if (strcmp(policy, #POLICY) == 0) \
+ { \
+ return tgt->GetPolicyStatus ## POLICY (); \
+ } \
+
+ RETURN_POLICY(CMP0003)
+ RETURN_POLICY(CMP0004)
+ RETURN_POLICY(CMP0008)
+ RETURN_POLICY(CMP0020)
+
+#undef RETURN_POLICY
+
+ assert("!Unreachable code. Not a valid policy");
+ return cmPolicies::WARN;
+}
+
+cmPolicies::PolicyID policyForString(const char *policy_id)
+{
+#define RETURN_POLICY_ID(POLICY_ID) \
+ if (strcmp(policy_id, #POLICY_ID) == 0) \
+ { \
+ return cmPolicies:: POLICY_ID; \
+ } \
+
+ RETURN_POLICY_ID(CMP0003)
+ RETURN_POLICY_ID(CMP0004)
+ RETURN_POLICY_ID(CMP0008)
+ RETURN_POLICY_ID(CMP0020)
+
+#undef RETURN_POLICY_ID
+
+ assert("!Unreachable code. Not a valid policy");
+ return cmPolicies::CMP0002;
+}
+
+//----------------------------------------------------------------------------
+static const struct TargetPolicyNode : public cmGeneratorExpressionNode
+{
+ TargetPolicyNode() {}
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context ,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ if (!context->HeadTarget)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_POLICY:prop> may only be used with targets. It may not "
+ "be used with add_custom_command.");
+ return std::string();
+ }
+
+ context->HadContextSensitiveCondition = true;
+
+ for (size_t i = 0;
+ i < (sizeof(targetPolicyWhitelist) /
+ sizeof(*targetPolicyWhitelist));
+ ++i)
+ {
+ const char *policy = targetPolicyWhitelist[i];
+ if (parameters.front() == policy)
+ {
+ cmMakefile *mf = context->HeadTarget->GetMakefile();
+ switch(statusForTarget(context->HeadTarget, policy))
+ {
+ case cmPolicies::WARN:
+ mf->IssueMessage(cmake::AUTHOR_WARNING,
+ mf->GetPolicies()->
+ GetPolicyWarning(policyForString(policy)));
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::OLD:
+ return "0";
+ case cmPolicies::NEW:
+ return "1";
+ }
+ }
+ }
+ 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."
+ );
+ return std::string();
+ }
+
+} targetPolicyNode;
+
+//----------------------------------------------------------------------------
+static const struct InstallPrefixNode : public cmGeneratorExpressionNode
+{
+ InstallPrefixNode() {}
+
+ virtual bool GeneratesContent() const { return true; }
+ virtual int NumExpectedParameters() const { return 0; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "INSTALL_PREFIX is a marker for install(EXPORT) only. It "
+ "should never be evaluated.");
+ return std::string();
+ }
+
+} installPrefixNode;
+
+//----------------------------------------------------------------------------
template<bool linker, bool soname>
struct TargetFilesystemArtifactResultCreator
{
@@ -486,10 +903,7 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
// Lookup the referenced target.
std::string name = *parameters.begin();
- cmsys::RegularExpression targetValidator;
- // The ':' is supported to allow use with IMPORTED targets.
- targetValidator.compile("^[A-Za-z0-9_.:-]+$");
- if (!targetValidator.find(name.c_str()))
+ if (!cmGeneratorExpression::IsValidTargetName(name))
{
::reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
@@ -509,7 +923,8 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
"Target \"" + name + "\" is not an executable or library.");
return std::string();
}
- context->Targets.insert(target);
+ context->DependTargets.insert(target);
+ context->AllTargets.insert(target);
std::string result =
TargetFilesystemArtifactResultCreator<linker, soname>::Create(
@@ -551,13 +966,13 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
{
if (identifier == "0")
return &zeroNode;
- if (identifier == "1")
+ else if (identifier == "1")
return &oneNode;
- if (identifier == "AND")
+ else if (identifier == "AND")
return &andNode;
- if (identifier == "OR")
+ else if (identifier == "OR")
return &orNode;
- if (identifier == "NOT")
+ else if (identifier == "NOT")
return &notNode;
else if (identifier == "CONFIGURATION")
return &configurationNode;
@@ -589,8 +1004,20 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &angle_rNode;
else if (identifier == "COMMA")
return &commaNode;
+ else if (identifier == "SEMICOLON")
+ return &semicolonNode;
else if (identifier == "TARGET_PROPERTY")
return &targetPropertyNode;
+ else if (identifier == "TARGET_NAME")
+ return &targetNameNode;
+ else if (identifier == "TARGET_POLICY")
+ return &targetPolicyNode;
+ else if (identifier == "BUILD_INTERFACE")
+ return &buildInterfaceNode;
+ else if (identifier == "INSTALL_INTERFACE")
+ return &installInterfaceNode;
+ else if (identifier == "INSTALL_PREFIX")
+ return &installPrefixNode;
return 0;
}
@@ -642,6 +1069,20 @@ std::string GeneratorExpressionContent::Evaluate(
if (!node->GeneratesContent())
{
+ if (node->AcceptsSingleArbitraryContentParameter())
+ {
+ if (this->ParamChildren.empty())
+ {
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier + "> expression requires a parameter.");
+ }
+ }
+ else
+ {
+ std::vector<std::string> parameters;
+ this->EvaluateParameters(node, identifier, context, dagChecker,
+ parameters);
+ }
return std::string();
}
@@ -666,6 +1107,15 @@ std::string GeneratorExpressionContent::Evaluate(
= 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)
{
@@ -673,10 +1123,33 @@ std::string GeneratorExpressionContent::Evaluate(
}
}
}
+ if (node->RequiresLiteralInput())
+ {
+ std::vector<std::string> parameters;
+ parameters.push_back(result);
+ return node->Evaluate(parameters, context, this, dagChecker);
+ }
return result;
}
std::vector<std::string> parameters;
+ this->EvaluateParameters(node, identifier, context, dagChecker, parameters);
+ if (context->HadError)
+ {
+ return std::string();
+ }
+
+ return node->Evaluate(parameters, context, this, dagChecker);
+}
+
+//----------------------------------------------------------------------------
+std::string GeneratorExpressionContent::EvaluateParameters(
+ const cmGeneratorExpressionNode *node,
+ const std::string &identifier,
+ cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ std::vector<std::string> &parameters) const
+{
{
std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
pit = this->ParamChildren.begin();
@@ -732,10 +1205,8 @@ std::string GeneratorExpressionContent::Evaluate(
{
reportError(context, this->GetOriginalExpression(), "$<" + identifier
+ "> expression requires at least one parameter.");
- return std::string();
}
-
- return node->Evaluate(parameters, context, this, dagChecker);
+ return std::string();
}
//----------------------------------------------------------------------------
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 04a2acd..ce7ad69 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -18,21 +18,26 @@
#include "cmListFileCache.h"
class cmTarget;
-class cmGeneratorTarget;
//----------------------------------------------------------------------------
struct cmGeneratorExpressionContext
{
cmListFileBacktrace Backtrace;
- std::set<cmTarget*> Targets;
+ std::set<cmTarget*> DependTargets;
+ std::set<cmTarget*> AllTargets;
+ std::set<cmStdString> SeenTargetProperties;
cmMakefile *Makefile;
const char *Config;
- cmGeneratorTarget *Target;
+ cmTarget *HeadTarget; // The target whose property is being evaluated.
+ cmTarget *CurrentTarget; // The dependent of HeadTarget which appears
+ // directly or indirectly in the property.
bool Quiet;
bool HadError;
+ bool HadContextSensitiveCondition;
};
struct cmGeneratorExpressionDAGChecker;
+struct cmGeneratorExpressionNode;
//----------------------------------------------------------------------------
struct cmGeneratorExpressionEvaluator
@@ -118,6 +123,13 @@ struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
~GeneratorExpressionContent();
private:
+ std::string EvaluateParameters(const cmGeneratorExpressionNode *node,
+ const std::string &identifier,
+ cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ std::vector<std::string> &parameters) const;
+
+private:
std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren;
std::vector<std::vector<cmGeneratorExpressionEvaluator*> > ParamChildren;
const char *StartContent;
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index 7a8fc51..a619cec 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -88,7 +88,15 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression
&& this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator)
{
- this->ParseContent(identifier);
+ if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
+ {
+ extendText(identifier, this->it);
+ ++this->it;
+ }
+ else
+ {
+ this->ParseContent(identifier);
+ }
if (this->it == this->Tokens.end())
{
break;
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 19b55c6..335ba0f 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -14,14 +14,11 @@
#include "cmTarget.h"
#include "cmMakefile.h"
#include "cmLocalGenerator.h"
-#include "cmComputeLinkInformation.h"
#include "cmGlobalGenerator.h"
#include "cmSourceFile.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
-#include <assert.h>
-
//----------------------------------------------------------------------------
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t)
{
@@ -32,15 +29,6 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t)
this->LookupObjectLibraries();
}
-cmGeneratorTarget::~cmGeneratorTarget()
-{
- for(std::map<cmStdString, cmComputeLinkInformation*>::iterator i
- = LinkInformation.begin(); i != LinkInformation.end(); ++i)
- {
- delete i->second;
- }
-}
-
//----------------------------------------------------------------------------
int cmGeneratorTarget::GetType() const
{
@@ -221,32 +209,6 @@ void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs)
}
//----------------------------------------------------------------------------
-cmComputeLinkInformation*
-cmGeneratorTarget::GetLinkInformation(const char* config)
-{
- // Lookup any existing information for this configuration.
- std::map<cmStdString, cmComputeLinkInformation*>::iterator
- i = this->LinkInformation.find(config?config:"");
- if(i == this->LinkInformation.end())
- {
- // Compute information for this configuration.
- cmComputeLinkInformation* info =
- new cmComputeLinkInformation(this->Target, config);
- if(!info || !info->Compute())
- {
- delete info;
- info = 0;
- }
-
- // Store the information for this configuration.
- std::map<cmStdString, cmComputeLinkInformation*>::value_type
- entry(config?config:"", info);
- i = this->LinkInformation.insert(entry).first;
- }
- return i->second;
-}
-
-//----------------------------------------------------------------------------
void cmGeneratorTarget::GetAppleArchs(const char* config,
std::vector<std::string>& archVec)
{
@@ -290,72 +252,5 @@ const char* cmGeneratorTarget::GetCreateRuleVariable()
std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
const char *config)
{
- std::vector<std::string> includes;
- const char *prop = this->Target->GetProperty("INCLUDE_DIRECTORIES");
- if(!prop)
- {
- return includes;
- }
-
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
-
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "INCLUDE_DIRECTORIES", 0, 0);
-
- cmSystemTools::ExpandListArgument(ge.Parse(prop)
- .Evaluate(this->Makefile,
- config,
- false,
- this,
- &dagChecker),
- includes);
-
- std::set<std::string> uniqueIncludes;
- std::vector<std::string> orderedAndUniqueIncludes;
- for(std::vector<std::string>::const_iterator
- li = includes.begin(); li != includes.end(); ++li)
- {
- std::string inc = *li;
- if (!cmSystemTools::IsOff(inc.c_str()))
- {
- cmSystemTools::ConvertToUnixSlashes(inc);
- }
- if(uniqueIncludes.insert(inc).second)
- {
- orderedAndUniqueIncludes.push_back(inc);
- }
- }
-
- return orderedAndUniqueIncludes;
-}
-
-//----------------------------------------------------------------------------
-std::string cmGeneratorTarget::GetCompileDefinitions(const char *config)
-{
- std::string defPropName = "COMPILE_DEFINITIONS";
- if (config)
- {
- defPropName += "_" + cmSystemTools::UpperCase(config);
- }
-
- const char *prop = this->Target->GetProperty(defPropName.c_str());
-
- if (!prop)
- {
- return "";
- }
-
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
-
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- defPropName, 0, 0);
- return ge.Parse(prop).Evaluate(this->Makefile,
- config,
- false,
- this,
- &dagChecker);
+ return this->Target->GetIncludeDirectories(config);
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index a29a9f9..cbcd8a5 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -14,7 +14,6 @@
#include "cmStandardIncludes.h"
-class cmComputeLinkInformation;
class cmCustomCommand;
class cmGlobalGenerator;
class cmLocalGenerator;
@@ -26,7 +25,6 @@ class cmGeneratorTarget
{
public:
cmGeneratorTarget(cmTarget*);
- ~cmGeneratorTarget();
int GetType() const;
const char *GetName() const;
@@ -60,10 +58,6 @@ public:
void UseObjectLibraries(std::vector<std::string>& objs);
- std::map<cmStdString, cmComputeLinkInformation*> LinkInformation;
-
- cmComputeLinkInformation* GetLinkInformation(const char* config);
-
void GetAppleArchs(const char* config,
std::vector<std::string>& archVec);
@@ -74,8 +68,6 @@ public:
/** Get the include directories for this target. */
std::vector<std::string> GetIncludeDirectories(const char *config);
- std::string GetCompileDefinitions(const char *config = 0);
-
private:
void ClassifySources();
void LookupObjectLibraries();
diff --git a/Source/cmGetFilenameComponentCommand.h b/Source/cmGetFilenameComponentCommand.h
index c461016..f294daa 100644
--- a/Source/cmGetFilenameComponentCommand.h
+++ b/Source/cmGetFilenameComponentCommand.h
@@ -62,15 +62,16 @@ public:
virtual const char* GetFullDocumentation() const
{
return
- " get_filename_component(<VAR> FileName\n"
- " PATH|ABSOLUTE|NAME|EXT|NAME_WE|REALPATH\n"
- " [CACHE])\n"
- "Set <VAR> to be the path (PATH), file name (NAME), file "
- "extension (EXT), file name without extension (NAME_WE) of FileName, "
- "the full path (ABSOLUTE), or the full path with all symlinks "
- "resolved (REALPATH). "
- "Note that the path is converted to Unix slashes format and has no "
- "trailing slashes. The longest file extension is always considered. "
+ " 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"
+ " 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"
+ "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 "
"added to the cache.\n"
" get_filename_component(<VAR> FileName\n"
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 8c6787a..2a7d61d 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -55,9 +55,9 @@ cmLocalGenerator *cmGlobalBorlandMakefileGenerator::CreateLocalGenerator()
//----------------------------------------------------------------------------
void cmGlobalBorlandMakefileGenerator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalBorlandMakefileGenerator::GetActualName();
entry.Brief = "Generates Borland makefiles.";
entry.Full = "";
}
diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h
index c0cb8a6..bd3db3e 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.h
+++ b/Source/cmGlobalBorlandMakefileGenerator.h
@@ -23,8 +23,9 @@ class cmGlobalBorlandMakefileGenerator : public cmGlobalNMakeMakefileGenerator
{
public:
cmGlobalBorlandMakefileGenerator();
- static cmGlobalGenerator* New()
- { return new cmGlobalBorlandMakefileGenerator; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory
+ <cmGlobalBorlandMakefileGenerator>(); }
///! Get the name for the generator.
virtual const char* GetName() const {
@@ -32,7 +33,7 @@ public:
static const char* GetActualName() {return "Borland Makefiles";}
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 6c95ea8..df14331 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -79,6 +79,20 @@ cmGlobalGenerator::~cmGlobalGenerator()
this->ClearGeneratorTargets();
}
+bool cmGlobalGenerator::SetGeneratorToolset(std::string const& ts)
+{
+ cmOStringStream e;
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "does not support toolset specification, but toolset\n"
+ " " << ts << "\n"
+ "was specified.";
+ this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ cmListFileBacktrace());
+ return false;
+}
+
void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang,
cmMakefile *mf,
bool optional)
@@ -938,6 +952,11 @@ void cmGlobalGenerator::Generate()
(*targets)[tit->first] = tit->second;
(*targets)[tit->first].SetMakefile(mf);
}
+
+ for ( tit = targets->begin(); tit != targets->end(); ++ tit )
+ {
+ tit->second.AppendBuildInterfaceIncludes();
+ }
}
// Add generator specific helper commands
@@ -975,6 +994,7 @@ void cmGlobalGenerator::Generate()
// Generate project files
for (i = 0; i < this->LocalGenerators.size(); ++i)
{
+ this->LocalGenerators[i]->GetMakefile()->SetGeneratingBuildSystem();
this->SetCurrentLocalGenerator(this->LocalGenerators[i]);
this->LocalGenerators[i]->Generate();
this->LocalGenerators[i]->GenerateInstallRules();
@@ -1047,6 +1067,8 @@ bool cmGlobalGenerator::CheckTargets()
void cmGlobalGenerator::CreateAutomocTargets()
{
#ifdef CMAKE_BUILD_WITH_CMAKE
+ typedef std::vector<std::pair<cmQtAutomoc, cmTarget*> > Automocs;
+ Automocs automocs;
for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
{
cmTargets& targets =
@@ -1058,16 +1080,25 @@ void cmGlobalGenerator::CreateAutomocTargets()
if(target.GetType() == cmTarget::EXECUTABLE ||
target.GetType() == cmTarget::STATIC_LIBRARY ||
target.GetType() == cmTarget::SHARED_LIBRARY ||
- target.GetType() == cmTarget::MODULE_LIBRARY)
+ target.GetType() == cmTarget::MODULE_LIBRARY ||
+ target.GetType() == cmTarget::OBJECT_LIBRARY)
{
if(target.GetPropertyAsBool("AUTOMOC") && !target.IsImported())
{
cmQtAutomoc automoc;
- automoc.SetupAutomocTarget(&target);
+ if(automoc.InitializeMocSourceFile(&target))
+ {
+ automocs.push_back(std::make_pair(automoc, &target));
+ }
}
}
}
}
+ for (Automocs::iterator it = automocs.begin(); it != automocs.end();
+ ++it)
+ {
+ it->first.SetupAutomocTarget(it->second);
+ }
#endif
}
@@ -1556,14 +1587,6 @@ void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen)
}
}
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::GetDocumentation(cmDocumentationEntry& entry) const
-{
- entry.Name = this->GetName();
- entry.Brief = "";
- entry.Full = "";
-}
-
bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
cmLocalGenerator* gen)
{
@@ -2055,12 +2078,44 @@ bool cmGlobalGenerator::UseFolderProperty()
}
// By default, this feature is OFF, since it is not supported in the
- // Visual Studio Express editions:
+ // Visual Studio Express editions until VS11:
//
return false;
}
//----------------------------------------------------------------------------
+void cmGlobalGenerator::EnableMinGWLanguage(cmMakefile *mf)
+{
+ this->FindMakeProgram(mf);
+ std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
+ std::vector<std::string> locations;
+ locations.push_back(cmSystemTools::GetProgramPath(makeProgram.c_str()));
+ locations.push_back("/mingw/bin");
+ locations.push_back("c:/mingw/bin");
+ std::string tgcc = cmSystemTools::FindProgram("gcc", locations);
+ std::string gcc = "gcc.exe";
+ if(tgcc.size())
+ {
+ gcc = tgcc;
+ }
+ std::string tgxx = cmSystemTools::FindProgram("g++", locations);
+ std::string gxx = "g++.exe";
+ if(tgxx.size())
+ {
+ gxx = tgxx;
+ }
+ std::string trc = cmSystemTools::FindProgram("windres", locations);
+ std::string rc = "windres.exe";
+ if(trc.size())
+ {
+ rc = trc;
+ }
+ mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str());
+ mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str());
+ mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str());
+}
+
+//----------------------------------------------------------------------------
cmTarget cmGlobalGenerator::CreateGlobalTarget(
const char* name, const char* message,
const cmCustomCommandLines* commandLines,
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 0aab2d6..11616e0 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -49,8 +49,9 @@ public:
///! Get the name for this generator
virtual const char *GetName() const { return "Generic"; };
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ /** Set the generator-specific toolset name. Returns true if toolset
+ is supported and false otherwise. */
+ virtual bool SetGeneratorToolset(std::string const& ts);
/**
* Create LocalGenerators and process the CMakeLists files. This does not
@@ -339,6 +340,7 @@ protected:
virtual const char* GetPredefinedTargetsFolder();
virtual bool UseFolderProperty();
+ void EnableMinGWLanguage(cmMakefile *mf);
private:
cmMakefile* TryCompileOuterMakefile;
diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h
new file mode 100644
index 0000000..fd1d65f
--- /dev/null
+++ b/Source/cmGlobalGeneratorFactory.h
@@ -0,0 +1,59 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2012 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 cmGlobalGeneratorFactory_h
+#define cmGlobalGeneratorFactory_h
+
+#include "cmStandardIncludes.h"
+
+class cmGlobalGenerator;
+struct cmDocumentationEntry;
+
+/** \class cmGlobalGeneratorFactory
+ * \brief Responable for creating cmGlobalGenerator instances
+ *
+ * Subclasses of this class generate instances of cmGlobalGenerator.
+ */
+class cmGlobalGeneratorFactory
+{
+public:
+ virtual ~cmGlobalGeneratorFactory() {}
+
+ /** Create a GlobalGenerator */
+ virtual cmGlobalGenerator* CreateGlobalGenerator(const char* n) const = 0;
+
+ /** Get the documentation entry for this factory */
+ virtual void GetDocumentation(cmDocumentationEntry& entry) const = 0;
+
+ /** Get the names of the current registered generators */
+ virtual void GetGenerators(std::vector<std::string>& names) const = 0;
+};
+
+template<class T>
+class cmGlobalGeneratorSimpleFactory : public cmGlobalGeneratorFactory
+{
+public:
+ /** Create a GlobalGenerator */
+ virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
+ if (strcmp(name, T::GetActualName())) return 0;
+ return new T; }
+
+ /** Get the documentation entry for this factory */
+ virtual void GetDocumentation(cmDocumentationEntry& entry) const {
+ T::GetDocumentation(entry); }
+
+ /** Get the names of the current registered generators */
+ virtual void GetGenerators(std::vector<std::string>& names) const {
+ names.push_back(T::GetActualName()); }
+};
+
+#endif
diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx
index ef42bd4..4af0607 100644
--- a/Source/cmGlobalJOMMakefileGenerator.cxx
+++ b/Source/cmGlobalJOMMakefileGenerator.cxx
@@ -61,9 +61,9 @@ cmLocalGenerator *cmGlobalJOMMakefileGenerator::CreateLocalGenerator()
//----------------------------------------------------------------------------
void cmGlobalJOMMakefileGenerator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalJOMMakefileGenerator::GetActualName();
entry.Brief = "Generates JOM makefiles.";
entry.Full = "";
}
diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h
index 691ebdb..28893bf 100644
--- a/Source/cmGlobalJOMMakefileGenerator.h
+++ b/Source/cmGlobalJOMMakefileGenerator.h
@@ -23,8 +23,9 @@ class cmGlobalJOMMakefileGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
cmGlobalJOMMakefileGenerator();
- static cmGlobalGenerator* New() {
- return new cmGlobalJOMMakefileGenerator; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory
+ <cmGlobalJOMMakefileGenerator>(); }
///! Get the name for the generator.
virtual const char* GetName() const {
return cmGlobalJOMMakefileGenerator::GetActualName();}
@@ -33,7 +34,7 @@ public:
static const char* GetActualName() {return "NMake Makefiles JOM";}
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx
index 80526aa..d49639b 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.cxx
+++ b/Source/cmGlobalMSYSMakefileGenerator.cxx
@@ -106,9 +106,9 @@ cmLocalGenerator *cmGlobalMSYSMakefileGenerator::CreateLocalGenerator()
//----------------------------------------------------------------------------
void cmGlobalMSYSMakefileGenerator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalMSYSMakefileGenerator::GetActualName();
entry.Brief = "Generates MSYS makefiles.";
entry.Full = "The makefiles use /bin/sh as the shell. "
"They require msys to be installed on the machine.";
diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h
index b76a5bf..659de11 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.h
+++ b/Source/cmGlobalMSYSMakefileGenerator.h
@@ -23,8 +23,9 @@ class cmGlobalMSYSMakefileGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
cmGlobalMSYSMakefileGenerator();
- static cmGlobalGenerator* New() {
- return new cmGlobalMSYSMakefileGenerator; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory
+ <cmGlobalMSYSMakefileGenerator>(); }
///! Get the name for the generator.
virtual const char* GetName() const {
@@ -32,7 +33,7 @@ public:
static const char* GetActualName() {return "MSYS Makefiles";}
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx
index d6045c8..1f374d3 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.cxx
+++ b/Source/cmGlobalMinGWMakefileGenerator.cxx
@@ -26,33 +26,7 @@ void cmGlobalMinGWMakefileGenerator
cmMakefile *mf,
bool optional)
{
- this->FindMakeProgram(mf);
- std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
- std::vector<std::string> locations;
- locations.push_back(cmSystemTools::GetProgramPath(makeProgram.c_str()));
- locations.push_back("/mingw/bin");
- locations.push_back("c:/mingw/bin");
- std::string tgcc = cmSystemTools::FindProgram("gcc", locations);
- std::string gcc = "gcc.exe";
- if(tgcc.size())
- {
- gcc = tgcc;
- }
- std::string tgxx = cmSystemTools::FindProgram("g++", locations);
- std::string gxx = "g++.exe";
- if(tgxx.size())
- {
- gxx = tgxx;
- }
- std::string trc = cmSystemTools::FindProgram("windres", locations);
- std::string rc = "windres.exe";
- if(trc.size())
- {
- rc = trc;
- }
- mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str());
- mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str());
- mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str());
+ this->EnableMinGWLanguage(mf);
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
@@ -71,9 +45,9 @@ cmLocalGenerator *cmGlobalMinGWMakefileGenerator::CreateLocalGenerator()
//----------------------------------------------------------------------------
void cmGlobalMinGWMakefileGenerator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalMinGWMakefileGenerator::GetActualName();
entry.Brief = "Generates a make file for use with mingw32-make.";
entry.Full = "The makefiles generated use cmd.exe as the shell. "
"They do not require msys or a unix shell.";
diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h
index 9a6a513..7951e98 100644
--- a/Source/cmGlobalMinGWMakefileGenerator.h
+++ b/Source/cmGlobalMinGWMakefileGenerator.h
@@ -23,15 +23,16 @@ class cmGlobalMinGWMakefileGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
cmGlobalMinGWMakefileGenerator();
- static cmGlobalGenerator* New() {
- return new cmGlobalMinGWMakefileGenerator; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory
+ <cmGlobalMinGWMakefileGenerator>(); }
///! Get the name for the generator.
virtual const char* GetName() const {
return cmGlobalMinGWMakefileGenerator::GetActualName();}
static const char* GetActualName() {return "MinGW Makefiles";}
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index 57a26c8..7af4ee3 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -61,9 +61,9 @@ cmLocalGenerator *cmGlobalNMakeMakefileGenerator::CreateLocalGenerator()
//----------------------------------------------------------------------------
void cmGlobalNMakeMakefileGenerator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName();
entry.Brief = "Generates NMake makefiles.";
entry.Full = "";
}
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index de33b8f..5756fbd 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -23,15 +23,16 @@ class cmGlobalNMakeMakefileGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
cmGlobalNMakeMakefileGenerator();
- static cmGlobalGenerator* New() {
- return new cmGlobalNMakeMakefileGenerator; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory
+ <cmGlobalNMakeMakefileGenerator>(); }
///! Get the name for the generator.
virtual const char* GetName() const {
return cmGlobalNMakeMakefileGenerator::GetActualName();}
static const char* GetActualName() {return "NMake Makefiles";}
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 05f5b4c..fa277b1 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -17,6 +17,8 @@
#include "cmGeneratorTarget.h"
#include "cmVersion.h"
+#include <algorithm>
+
const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja";
const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja";
const char* cmGlobalNinjaGenerator::INDENT = " ";
@@ -83,6 +85,7 @@ std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string &lit)
{
std::string result = lit;
cmSystemTools::ReplaceString(result, "$", "$$");
+ cmSystemTools::ReplaceString(result, "\n", "$\n");
return result;
}
@@ -452,9 +455,9 @@ cmLocalGenerator* cmGlobalNinjaGenerator::CreateLocalGenerator()
}
void cmGlobalNinjaGenerator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalNinjaGenerator::GetActualName();
entry.Brief = "Generates build.ninja files (experimental).";
entry.Full =
"A build.ninja file is generated into the build tree. Recent "
@@ -491,69 +494,20 @@ void cmGlobalNinjaGenerator::Generate()
// Used in:
// Source/cmMakefile.cxx:
void cmGlobalNinjaGenerator
-::EnableLanguage(std::vector<std::string>const& languages,
- cmMakefile *mf,
+::EnableLanguage(std::vector<std::string>const& langs,
+ cmMakefile* makefile,
bool optional)
{
- std::string path;
- for(std::vector<std::string>::const_iterator l = languages.begin();
- l != languages.end(); ++l)
+ if (makefile->IsOn("CMAKE_COMPILER_IS_MINGW"))
{
- std::vector<std::string> language;
- language.push_back(*l);
-
- if(*l == "NONE")
- {
- this->cmGlobalGenerator::EnableLanguage(language, mf, optional);
- continue;
- }
- else if(*l == "Fortran")
- {
- std::string message = "The \"";
- message += this->GetName();
- message += "\" generator does not support the language \"";
- message += *l;
- message += "\" yet.";
- cmSystemTools::Error(message.c_str());
- }
- else if(*l == "RC")
- {
- // check if mingw is used
- if(mf->IsOn("CMAKE_COMPILER_IS_MINGW"))
- {
- UsingMinGW = true;
- if(!mf->GetDefinition("CMAKE_RC_COMPILER"))
- {
- std::string windres = cmSystemTools::FindProgram("windres");
- if(windres.empty())
- {
- std::string compiler_path;
- std::string::size_type prefix = std::string::npos;
- if (mf->GetDefinition("CMAKE_C_COMPILER"))
- {
- compiler_path = mf->GetDefinition("CMAKE_C_COMPILER");
- prefix = compiler_path.rfind("gcc");
- }
- else if (mf->GetDefinition("CMAKE_CXX_COMPILER"))
- {
- compiler_path = mf->GetDefinition("CMAKE_CXX_COMPILER");
- prefix = compiler_path.rfind("++");
- prefix--;
- }
- if (prefix != std::string::npos)
- {
- windres = compiler_path.substr(0, prefix) + "windres";
- windres = cmSystemTools::FindProgram(windres.c_str());
- }
- }
- if(!windres.empty())
- mf->AddDefinition("CMAKE_RC_COMPILER", windres.c_str());
- }
- }
- }
- this->cmGlobalGenerator::EnableLanguage(language, mf, optional);
- this->ResolveLanguageCompiler(*l, mf, optional);
+ UsingMinGW = true;
+ this->EnableMinGWLanguage(makefile);
+ }
+ if (std::find(langs.begin(), langs.end(), "Fortran") != langs.end())
+ {
+ cmSystemTools::Error("The Ninja generator does not support Fortran yet.");
}
+ this->cmGlobalGenerator::EnableLanguage(langs, makefile, optional);
}
bool cmGlobalNinjaGenerator::UsingMinGW = false;
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 24c3916..c3df7d9 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -14,6 +14,7 @@
# define cmGlobalNinjaGenerator_h
# include "cmGlobalGenerator.h"
+# include "cmGlobalGeneratorFactory.h"
# include "cmNinjaTypes.h"
//#define NINJA_GEN_VERBOSE_FILES
@@ -160,8 +161,8 @@ public:
cmGlobalNinjaGenerator();
/// Convenience method for creating an instance of this class.
- static cmGlobalGenerator* New() {
- return new cmGlobalNinjaGenerator; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory<cmGlobalNinjaGenerator>(); }
/// Destructor.
virtual ~cmGlobalNinjaGenerator() { }
@@ -177,7 +178,7 @@ public:
static const char* GetActualName() { return "Ninja"; }
/// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
/// Overloaded methods. @see cmGlobalGenerator::Generate()
virtual void Generate();
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index ebd8219..e26cca9 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -61,9 +61,9 @@ cmLocalGenerator *cmGlobalUnixMakefileGenerator3::CreateLocalGenerator()
//----------------------------------------------------------------------------
void cmGlobalUnixMakefileGenerator3
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalUnixMakefileGenerator3::GetActualName();
entry.Brief = "Generates standard UNIX makefiles.";
entry.Full =
"A hierarchy of UNIX makefiles is generated into the build tree. Any "
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index e6dd09d..385cdc4 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -13,6 +13,7 @@
#define cmGlobalUnixMakefileGenerator3_h
#include "cmGlobalGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
class cmGeneratedFileStream;
class cmMakefileTargetGenerator;
@@ -54,8 +55,9 @@ class cmGlobalUnixMakefileGenerator3 : public cmGlobalGenerator
{
public:
cmGlobalUnixMakefileGenerator3();
- static cmGlobalGenerator* New() {
- return new cmGlobalUnixMakefileGenerator3; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory
+ <cmGlobalUnixMakefileGenerator3>(); }
///! Get the name for the generator.
virtual const char* GetName() const {
@@ -63,7 +65,7 @@ public:
static const char* GetActualName() {return "Unix Makefiles";}
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator3
virtual cmLocalGenerator *CreateLocalGenerator();
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 480c577..ee7c56f 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -16,8 +16,61 @@
#include "cmSourceFile.h"
#include "cmake.h"
+static const char vs10Win32generatorName[] = "Visual Studio 10";
+static const char vs10Win64generatorName[] = "Visual Studio 10 Win64";
+static const char vs10IA64generatorName[] = "Visual Studio 10 IA64";
-cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator()
+class cmGlobalVisualStudio10Generator::Factory
+ : public cmGlobalGeneratorFactory
+{
+public:
+ virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
+ if(!strcmp(name, vs10Win32generatorName))
+ {
+ return new cmGlobalVisualStudio10Generator(
+ vs10Win32generatorName, NULL, NULL);
+ }
+ if(!strcmp(name, vs10Win64generatorName))
+ {
+ return new cmGlobalVisualStudio10Generator(
+ vs10Win64generatorName, "x64", "CMAKE_FORCE_WIN64");
+ }
+ if(!strcmp(name, vs10IA64generatorName))
+ {
+ return new cmGlobalVisualStudio10Generator(
+ vs10IA64generatorName, "Itanium", "CMAKE_FORCE_IA64");
+ }
+ return 0;
+ }
+
+ virtual void GetDocumentation(cmDocumentationEntry& entry) const {
+ entry.Name = "Visual Studio 10";
+ entry.Brief = "Generates Visual Studio 10 (2010) project files.";
+ entry.Full =
+ "It is possible to append a space followed by the platform name "
+ "to create project files for a specific target platform. E.g. "
+ "\"Visual Studio 10 Win64\" will create project files for "
+ "the x64 processor; \"Visual Studio 10 IA64\" for Itanium.";
+ }
+
+ virtual void GetGenerators(std::vector<std::string>& names) const {
+ names.push_back(vs10Win32generatorName);
+ names.push_back(vs10Win64generatorName);
+ names.push_back(vs10IA64generatorName); }
+};
+
+//----------------------------------------------------------------------------
+cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory()
+{
+ return new Factory;
+}
+
+//----------------------------------------------------------------------------
+cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(
+ const char* name, const char* architectureId,
+ const char* additionalPlatformDefinition)
+ : cmGlobalVisualStudio8Generator(name, architectureId,
+ additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS10FindMake.cmake";
std::string vc10Express;
@@ -27,6 +80,14 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator()
}
//----------------------------------------------------------------------------
+bool
+cmGlobalVisualStudio10Generator::SetGeneratorToolset(std::string const& ts)
+{
+ this->PlatformToolset = ts;
+ return true;
+}
+
+//----------------------------------------------------------------------------
void cmGlobalVisualStudio10Generator::AddPlatformDefinitions(cmMakefile* mf)
{
cmGlobalVisualStudio8Generator::AddPlatformDefinitions(mf);
@@ -41,7 +102,14 @@ void cmGlobalVisualStudio10Generator::AddPlatformDefinitions(cmMakefile* mf)
void cmGlobalVisualStudio10Generator::WriteSLNHeader(std::ostream& fout)
{
fout << "Microsoft Visual Studio Solution File, Format Version 11.00\n";
- fout << "# Visual Studio 2010\n";
+ if (this->ExpressEdition)
+ {
+ fout << "# Visual C++ Express 2010\n";
+ }
+ else
+ {
+ fout << "# Visual Studio 2010\n";
+ }
}
///! Create a local generator appropriate to this Global Generator
@@ -88,18 +156,16 @@ void cmGlobalVisualStudio10Generator::Generate()
//----------------------------------------------------------------------------
void cmGlobalVisualStudio10Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
-{
- entry.Name = this->GetName();
- entry.Brief = "Generates Visual Studio 10 project files.";
- entry.Full = "";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio10Generator
::EnableLanguage(std::vector<std::string>const & lang,
cmMakefile *mf, bool optional)
{
+ if(this->ArchitectureId == "Itanium" || this->ArchitectureId == "x64")
+ {
+ if(this->IsExpressEdition() && !this->Find64BitTools(mf))
+ {
+ return;
+ }
+ }
cmGlobalVisualStudio8Generator::EnableLanguage(lang, mf, optional);
}
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 47ce790..5926e0f 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -24,9 +24,11 @@ class cmGlobalVisualStudio10Generator :
public cmGlobalVisualStudio8Generator
{
public:
- cmGlobalVisualStudio10Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio10Generator; }
+ cmGlobalVisualStudio10Generator(const char* name,
+ const char* architectureId, const char* additionalPlatformDefinition);
+ static cmGlobalGeneratorFactory* NewFactory();
+
+ virtual bool SetGeneratorToolset(std::string const& ts);
virtual std::string
GenerateBuildCommand(const char* makeProgram,
@@ -34,15 +36,8 @@ public:
const char* additionalOptions, const char *targetName,
const char* config, bool ignoreErrors, bool);
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio10Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 10";}
virtual void AddPlatformDefinitions(cmMakefile* mf);
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
-
///! create the correct local generator
virtual cmLocalGenerator *CreateLocalGenerator();
@@ -92,6 +87,7 @@ protected:
bool UseFolderProperty();
private:
+ class Factory;
struct LongestSourcePath
{
LongestSourcePath(): Length(0), Target(0), SourceFile(0) {}
diff --git a/Source/cmGlobalVisualStudio10IA64Generator.cxx b/Source/cmGlobalVisualStudio10IA64Generator.cxx
deleted file mode 100644
index 25dd88f..0000000
--- a/Source/cmGlobalVisualStudio10IA64Generator.cxx
+++ /dev/null
@@ -1,50 +0,0 @@
-/*============================================================================
- 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.
-============================================================================*/
-#include "cmGlobalVisualStudio10IA64Generator.h"
-#include "cmMakefile.h"
-#include "cmake.h"
-
-//----------------------------------------------------------------------------
-cmGlobalVisualStudio10IA64Generator::cmGlobalVisualStudio10IA64Generator()
-{
- this->ArchitectureId = "x64";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio10IA64Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
-{
- entry.Name = this->GetName();
- entry.Brief = "Generates Visual Studio 10 Itanium project files.";
- entry.Full = "";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio10IA64Generator
-::AddPlatformDefinitions(cmMakefile* mf)
-{
- this->cmGlobalVisualStudio10Generator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_FORCE_IA64", "TRUE");
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio10IA64Generator
-::EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile* mf, bool optional)
-{
- if(this->IsExpressEdition() && !this->Find64BitTools(mf))
- {
- return;
- }
- this->cmGlobalVisualStudio10Generator
- ::EnableLanguage(languages, mf, optional);
-}
diff --git a/Source/cmGlobalVisualStudio10IA64Generator.h b/Source/cmGlobalVisualStudio10IA64Generator.h
deleted file mode 100644
index a088272..0000000
--- a/Source/cmGlobalVisualStudio10IA64Generator.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*============================================================================
- 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.
-============================================================================*/
-#ifndef cmGlobalVisualStudio10IA64Generator_h
-#define cmGlobalVisualStudio10IA64Generator_h
-
-#include "cmGlobalVisualStudio10Generator.h"
-
-class cmGlobalVisualStudio10IA64Generator :
- public cmGlobalVisualStudio10Generator
-{
-public:
- cmGlobalVisualStudio10IA64Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio10IA64Generator; }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio10IA64Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 10 IA64";}
-
- virtual const char* GetPlatformName() const {return "Itanium";}
-
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
-
- virtual void AddPlatformDefinitions(cmMakefile* mf);
-
- virtual void EnableLanguage(std::vector<std::string>const& languages,
- cmMakefile *, bool optional);
-};
-#endif
diff --git a/Source/cmGlobalVisualStudio10Win64Generator.cxx b/Source/cmGlobalVisualStudio10Win64Generator.cxx
deleted file mode 100644
index d0a0c49..0000000
--- a/Source/cmGlobalVisualStudio10Win64Generator.cxx
+++ /dev/null
@@ -1,50 +0,0 @@
-/*============================================================================
- 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.
-============================================================================*/
-#include "cmGlobalVisualStudio10Win64Generator.h"
-#include "cmMakefile.h"
-#include "cmake.h"
-
-//----------------------------------------------------------------------------
-cmGlobalVisualStudio10Win64Generator::cmGlobalVisualStudio10Win64Generator()
-{
- this->ArchitectureId = "x64";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio10Win64Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
-{
- entry.Name = this->GetName();
- entry.Brief = "Generates Visual Studio 10 Win64 project files.";
- entry.Full = "";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio10Win64Generator
-::AddPlatformDefinitions(cmMakefile* mf)
-{
- this->cmGlobalVisualStudio10Generator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_FORCE_WIN64", "TRUE");
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio10Win64Generator
-::EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile* mf, bool optional)
-{
- if(this->IsExpressEdition() && !this->Find64BitTools(mf))
- {
- return;
- }
- this->cmGlobalVisualStudio10Generator
- ::EnableLanguage(languages, mf, optional);
-}
diff --git a/Source/cmGlobalVisualStudio10Win64Generator.h b/Source/cmGlobalVisualStudio10Win64Generator.h
deleted file mode 100644
index 8a2de4c..0000000
--- a/Source/cmGlobalVisualStudio10Win64Generator.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*============================================================================
- 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.
-============================================================================*/
-#ifndef cmGlobalVisualStudio10Win64Generator_h
-#define cmGlobalVisualStudio10Win64Generator_h
-
-#include "cmGlobalVisualStudio10Generator.h"
-
-class cmGlobalVisualStudio10Win64Generator :
- public cmGlobalVisualStudio10Generator
-{
-public:
- cmGlobalVisualStudio10Win64Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio10Win64Generator; }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio10Win64Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 10 Win64";}
-
- virtual const char* GetPlatformName() const {return "x64";}
-
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
-
- virtual void AddPlatformDefinitions(cmMakefile* mf);
-
- virtual void EnableLanguage(std::vector<std::string>const& languages,
- cmMakefile *, bool optional);
-};
-#endif
diff --git a/Source/cmGlobalVisualStudio11ARMGenerator.cxx b/Source/cmGlobalVisualStudio11ARMGenerator.cxx
deleted file mode 100644
index efd71c6..0000000
--- a/Source/cmGlobalVisualStudio11ARMGenerator.cxx
+++ /dev/null
@@ -1,29 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 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 "cmGlobalVisualStudio11ARMGenerator.h"
-#include "cmMakefile.h"
-#include "cmake.h"
-
-//----------------------------------------------------------------------------
-cmGlobalVisualStudio11ARMGenerator::cmGlobalVisualStudio11ARMGenerator()
-{
- this->ArchitectureId = "ARM";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio11ARMGenerator
-::GetDocumentation(cmDocumentationEntry& entry) const
-{
- entry.Name = this->GetName();
- entry.Brief = "Generates Visual Studio 11 ARM project files.";
- entry.Full = "";
-}
diff --git a/Source/cmGlobalVisualStudio11ARMGenerator.h b/Source/cmGlobalVisualStudio11ARMGenerator.h
deleted file mode 100644
index 71dbf2e..0000000
--- a/Source/cmGlobalVisualStudio11ARMGenerator.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 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 cmGlobalVisualStudio11ARMGenerator_h
-#define cmGlobalVisualStudio11ARMGenerator_h
-
-#include "cmGlobalVisualStudio11Generator.h"
-
-class cmGlobalVisualStudio11ARMGenerator :
- public cmGlobalVisualStudio11Generator
-{
-public:
- cmGlobalVisualStudio11ARMGenerator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio11ARMGenerator; }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio11ARMGenerator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 11 ARM";}
-
- virtual const char* GetPlatformName() const {return "ARM";}
-
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
-};
-#endif
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index 23a1204..624d01d 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -13,8 +13,61 @@
#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";
+
+class cmGlobalVisualStudio11Generator::Factory
+ : public cmGlobalGeneratorFactory
+{
+public:
+ virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
+ if(!strcmp(name, vs11Win32generatorName))
+ {
+ return new cmGlobalVisualStudio11Generator(
+ vs11Win32generatorName, NULL, NULL);
+ }
+ if(!strcmp(name, vs11Win64generatorName))
+ {
+ return new cmGlobalVisualStudio11Generator(
+ vs11Win64generatorName, "x64", "CMAKE_FORCE_WIN64");
+ }
+ if(!strcmp(name, vs11ARMgeneratorName))
+ {
+ return new cmGlobalVisualStudio11Generator(
+ vs11ARMgeneratorName, "ARM", NULL);
+ }
+ return 0;
+ }
+
+ virtual void GetDocumentation(cmDocumentationEntry& entry) const {
+ entry.Name = "Visual Studio 11";
+ entry.Brief = "Generates Visual Studio 11 (2012) project files.";
+ entry.Full =
+ "It is possible to append a space followed by the platform name "
+ "to create project files for a specific target platform. E.g. "
+ "\"Visual Studio 11 Win64\" will create project files for "
+ "the x64 processor; \"Visual Studio 11 ARM\" for ARM.";
+ }
+
+ virtual void GetGenerators(std::vector<std::string>& names) const {
+ names.push_back(vs11Win32generatorName);
+ names.push_back(vs11Win64generatorName);
+ names.push_back(vs11ARMgeneratorName); }
+};
+
+//----------------------------------------------------------------------------
+cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory()
+{
+ return new Factory;
+}
+
//----------------------------------------------------------------------------
-cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator()
+cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator(
+ const char* name, const char* architectureId,
+ const char* additionalPlatformDefinition)
+ : cmGlobalVisualStudio10Generator(name, architectureId,
+ additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS11FindMake.cmake";
std::string vc11Express;
@@ -28,7 +81,14 @@ cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator()
void cmGlobalVisualStudio11Generator::WriteSLNHeader(std::ostream& fout)
{
fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
- fout << "# Visual Studio 11\n";
+ if (this->ExpressEdition)
+ {
+ fout << "# Visual Studio Express 2012 for Windows Desktop\n";
+ }
+ else
+ {
+ fout << "# Visual Studio 2012\n";
+ }
}
//----------------------------------------------------------------------------
@@ -42,10 +102,10 @@ cmLocalGenerator *cmGlobalVisualStudio11Generator::CreateLocalGenerator()
}
//----------------------------------------------------------------------------
-void cmGlobalVisualStudio11Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
+bool cmGlobalVisualStudio11Generator::UseFolderProperty()
{
- entry.Name = this->GetName();
- entry.Brief = "Generates Visual Studio 11 project files.";
- entry.Full = "";
+ // 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 VS11 Express.
+ return cmGlobalVisualStudio8Generator::UseFolderProperty();
}
diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h
index 56337a4..174f1cc 100644
--- a/Source/cmGlobalVisualStudio11Generator.h
+++ b/Source/cmGlobalVisualStudio11Generator.h
@@ -20,20 +20,12 @@ class cmGlobalVisualStudio11Generator:
public cmGlobalVisualStudio10Generator
{
public:
- cmGlobalVisualStudio11Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio11Generator; }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio11Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 11";}
+ cmGlobalVisualStudio11Generator(const char* name,
+ const char* architectureId, const char* additionalPlatformDefinition);
+ static cmGlobalGeneratorFactory* NewFactory();
virtual void WriteSLNHeader(std::ostream& fout);
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
-
///! create the correct local generator
virtual cmLocalGenerator *CreateLocalGenerator();
@@ -41,5 +33,8 @@ public:
virtual std::string GetUserMacrosDirectory() { return ""; }
protected:
virtual const char* GetIDEVersion() { return "11.0"; }
+ bool UseFolderProperty();
+private:
+ class Factory;
};
#endif
diff --git a/Source/cmGlobalVisualStudio11Win64Generator.cxx b/Source/cmGlobalVisualStudio11Win64Generator.cxx
deleted file mode 100644
index 94e07bf..0000000
--- a/Source/cmGlobalVisualStudio11Win64Generator.cxx
+++ /dev/null
@@ -1,37 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 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 "cmGlobalVisualStudio11Win64Generator.h"
-#include "cmMakefile.h"
-#include "cmake.h"
-
-//----------------------------------------------------------------------------
-cmGlobalVisualStudio11Win64Generator::cmGlobalVisualStudio11Win64Generator()
-{
- this->ArchitectureId = "x64";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio11Win64Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
-{
- entry.Name = this->GetName();
- entry.Brief = "Generates Visual Studio 11 Win64 project files.";
- entry.Full = "";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio11Win64Generator
-::AddPlatformDefinitions(cmMakefile* mf)
-{
- this->cmGlobalVisualStudio11Generator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_FORCE_WIN64", "TRUE");
-}
diff --git a/Source/cmGlobalVisualStudio11Win64Generator.h b/Source/cmGlobalVisualStudio11Win64Generator.h
deleted file mode 100644
index 9445d15..0000000
--- a/Source/cmGlobalVisualStudio11Win64Generator.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*============================================================================
- CMake - Cross Platform Makefile Generator
- Copyright 2000-2011 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 cmGlobalVisualStudio11Win64Generator_h
-#define cmGlobalVisualStudio11Win64Generator_h
-
-#include "cmGlobalVisualStudio11Generator.h"
-
-class cmGlobalVisualStudio11Win64Generator :
- public cmGlobalVisualStudio11Generator
-{
-public:
- cmGlobalVisualStudio11Win64Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio11Win64Generator; }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio11Win64Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 11 Win64";}
-
- virtual const char* GetPlatformName() const {return "x64";}
-
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
-
- virtual void AddPlatformDefinitions(cmMakefile* mf);
-};
-#endif
diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
new file mode 100644
index 0000000..d77b84d
--- /dev/null
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -0,0 +1,111 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2011 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 "cmGlobalVisualStudio12Generator.h"
+#include "cmLocalVisualStudio10Generator.h"
+#include "cmMakefile.h"
+
+static const char vs12Win32generatorName[] = "Visual Studio 12";
+static const char vs12Win64generatorName[] = "Visual Studio 12 Win64";
+static const char vs12ARMgeneratorName[] = "Visual Studio 12 ARM";
+
+class cmGlobalVisualStudio12Generator::Factory
+ : public cmGlobalGeneratorFactory
+{
+public:
+ virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
+ if(!strcmp(name, vs12Win32generatorName))
+ {
+ return new cmGlobalVisualStudio12Generator(
+ vs12Win32generatorName, NULL, NULL);
+ }
+ if(!strcmp(name, vs12Win64generatorName))
+ {
+ return new cmGlobalVisualStudio12Generator(
+ vs12Win64generatorName, "x64", "CMAKE_FORCE_WIN64");
+ }
+ if(!strcmp(name, vs12ARMgeneratorName))
+ {
+ return new cmGlobalVisualStudio12Generator(
+ vs12ARMgeneratorName, "ARM", NULL);
+ }
+ return 0;
+ }
+
+ virtual void GetDocumentation(cmDocumentationEntry& entry) const {
+ entry.Name = "Visual Studio 12";
+ entry.Brief = "Generates Visual Studio 12 (2013) project files.";
+ entry.Full =
+ "It is possible to append a space followed by the platform name "
+ "to create project files for a specific target platform. E.g. "
+ "\"Visual Studio 12 Win64\" will create project files for "
+ "the x64 processor; \"Visual Studio 12 ARM\" for ARM.";
+ }
+
+ virtual void GetGenerators(std::vector<std::string>& names) const {
+ names.push_back(vs12Win32generatorName);
+ names.push_back(vs12Win64generatorName);
+ names.push_back(vs12ARMgeneratorName); }
+};
+
+//----------------------------------------------------------------------------
+cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory()
+{
+ return new Factory;
+}
+
+//----------------------------------------------------------------------------
+cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator(
+ const char* name, const char* architectureId,
+ const char* additionalPlatformDefinition)
+ : cmGlobalVisualStudio11Generator(name, architectureId,
+ additionalPlatformDefinition)
+{
+ this->FindMakeProgramFile = "CMakeVS12FindMake.cmake";
+ std::string vc12Express;
+ this->ExpressEdition = cmSystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\12.0\\Setup\\VC;"
+ "ProductDir", vc12Express, cmSystemTools::KeyWOW64_32);
+ this->PlatformToolset = "v120";
+}
+
+//----------------------------------------------------------------------------
+void cmGlobalVisualStudio12Generator::WriteSLNHeader(std::ostream& fout)
+{
+ fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n";
+ if (this->ExpressEdition)
+ {
+ fout << "# Visual Studio Express 2013 for Windows Desktop\n";
+ }
+ else
+ {
+ fout << "# Visual Studio 2013\n";
+ }
+}
+
+//----------------------------------------------------------------------------
+cmLocalGenerator *cmGlobalVisualStudio12Generator::CreateLocalGenerator()
+{
+ cmLocalVisualStudio10Generator* lg =
+ new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS12);
+ lg->SetPlatformName(this->GetPlatformName());
+ 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
new file mode 100644
index 0000000..5844ee0
--- /dev/null
+++ b/Source/cmGlobalVisualStudio12Generator.h
@@ -0,0 +1,40 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2011 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 cmGlobalVisualStudio12Generator_h
+#define cmGlobalVisualStudio12Generator_h
+
+#include "cmGlobalVisualStudio11Generator.h"
+
+
+/** \class cmGlobalVisualStudio12Generator */
+class cmGlobalVisualStudio12Generator:
+ public cmGlobalVisualStudio11Generator
+{
+public:
+ cmGlobalVisualStudio12Generator(const char* name,
+ const char* architectureId, const char* additionalPlatformDefinition);
+ static cmGlobalGeneratorFactory* NewFactory();
+
+ virtual void WriteSLNHeader(std::ostream& fout);
+
+ ///! create the correct local generator
+ virtual cmLocalGenerator *CreateLocalGenerator();
+
+ /** TODO: VS 12 user macro support. */
+ virtual std::string GetUserMacrosDirectory() { return ""; }
+protected:
+ virtual const char* GetIDEVersion() { return "12.0"; }
+ bool UseFolderProperty();
+private:
+ class Factory;
+};
+#endif
diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx
index e8ca788..9f3af71 100644
--- a/Source/cmGlobalVisualStudio6Generator.cxx
+++ b/Source/cmGlobalVisualStudio6Generator.cxx
@@ -41,11 +41,8 @@ void cmGlobalVisualStudio6Generator
bool optional)
{
cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
- mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
- mf->AddDefinition("CMAKE_GENERATOR_Fortran", "ifort");
this->GenerateConfigurations(mf);
this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
}
@@ -200,7 +197,6 @@ void cmGlobalVisualStudio6Generator
tt != orderedProjectTargets.end(); ++tt)
{
cmTarget* target = *tt;
- cmMakefile* mf = target->GetMakefile();
// Write the project into the DSW file
const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
if(expath)
@@ -398,9 +394,9 @@ cmGlobalVisualStudio6Generator::WriteUtilityDepend(cmTarget* target)
//----------------------------------------------------------------------------
void cmGlobalVisualStudio6Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalVisualStudio6Generator::GetActualName();
entry.Brief = "Generates Visual Studio 6 project files.";
entry.Full = "";
}
diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h
index 259aa8d..40149e9 100644
--- a/Source/cmGlobalVisualStudio6Generator.h
+++ b/Source/cmGlobalVisualStudio6Generator.h
@@ -13,6 +13,7 @@
#define cmGlobalVisualStudio6Generator_h
#include "cmGlobalVisualStudioGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
class cmTarget;
@@ -25,8 +26,9 @@ class cmGlobalVisualStudio6Generator : public cmGlobalVisualStudioGenerator
{
public:
cmGlobalVisualStudio6Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio6Generator; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory
+ <cmGlobalVisualStudio6Generator>(); }
///! Get the name for the generator.
virtual const char* GetName() const {
@@ -34,7 +36,7 @@ public:
static const char* GetActualName() {return "Visual Studio 6";}
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index ab2308f..2494f55 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -128,6 +128,9 @@ void cmGlobalVisualStudio71Generator
fout << "\tEndGlobalSection\n";
}
+ // Write out global sections
+ this->WriteSLNGlobalSections(fout, root);
+
// Write the footer for the SLN file
this->WriteSLNFooter(fout);
}
@@ -273,9 +276,10 @@ void cmGlobalVisualStudio71Generator
// Write a dsp file into the SLN file, Note, that dependencies from
// executables to the libraries it uses are also done here
void cmGlobalVisualStudio71Generator
-::WriteProjectConfigurations(std::ostream& fout, const char* name,
- bool partOfDefaultBuild,
- const char* platformMapping)
+::WriteProjectConfigurations(
+ std::ostream& fout, const char* name, cmTarget::TargetType,
+ const std::set<std::string>& configsPartOfDefaultBuild,
+ const char* platformMapping)
{
std::string guid = this->GetGUID(name);
for(std::vector<std::string>::iterator i = this->Configurations.begin();
@@ -284,7 +288,9 @@ void cmGlobalVisualStudio71Generator
fout << "\t\t{" << guid << "}." << *i
<< ".ActiveCfg = " << *i << "|"
<< (platformMapping ? platformMapping : "Win32") << std::endl;
- if(partOfDefaultBuild)
+ std::set<std::string>::const_iterator
+ ci = configsPartOfDefaultBuild.find(*i);
+ if(!(ci == configsPartOfDefaultBuild.end()))
{
fout << "\t\t{" << guid << "}." << *i
<< ".Build.0 = " << *i << "|"
@@ -294,17 +300,6 @@ void cmGlobalVisualStudio71Generator
}
//----------------------------------------------------------------------------
-// Standard end of dsw file
-void cmGlobalVisualStudio71Generator::WriteSLNFooter(std::ostream& fout)
-{
- fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
- << "\tEndGlobalSection\n"
- << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
- << "\tEndGlobalSection\n"
- << "EndGlobal\n";
-}
-
-//----------------------------------------------------------------------------
// ouput standard header for dsw file
void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout)
{
@@ -313,9 +308,9 @@ void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout)
//----------------------------------------------------------------------------
void cmGlobalVisualStudio71Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalVisualStudio71Generator::GetActualName();
entry.Brief = "Generates Visual Studio .NET 2003 project files.";
entry.Full = "";
}
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index a8daad6..6d91f97 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -24,8 +24,9 @@ class cmGlobalVisualStudio71Generator : public cmGlobalVisualStudio7Generator
{
public:
cmGlobalVisualStudio71Generator();
- static cmGlobalGenerator* New()
- { return new cmGlobalVisualStudio71Generator; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory
+ <cmGlobalVisualStudio71Generator>(); }
///! Get the name for the generator.
virtual const char* GetName() const {
@@ -33,7 +34,7 @@ public:
static const char* GetActualName() {return "Visual Studio 7 .NET 2003";}
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
@@ -61,16 +62,15 @@ protected:
const char* name, const char* path, cmTarget &t);
virtual void WriteProjectDepends(std::ostream& fout,
const char* name, const char* path, cmTarget &t);
- virtual void WriteProjectConfigurations(std::ostream& fout,
- const char* name,
- bool partOfDefaultBuild,
- const char* platformMapping = NULL);
+ virtual void WriteProjectConfigurations(
+ std::ostream& fout, const char* name, cmTarget::TargetType type,
+ const std::set<std::string>& configsPartOfDefaultBuild,
+ const char* platformMapping = NULL);
virtual void WriteExternalProject(std::ostream& fout,
const char* name,
const char* path,
const char* typeGuid,
const std::set<cmStdString>& depends);
- virtual void WriteSLNFooter(std::ostream& fout);
virtual void WriteSLNHeader(std::ostream& fout);
std::string ProjectConfigurationSectionName;
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index b6eea5d..63cbdb8 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -10,6 +10,7 @@
See the License for more information.
============================================================================*/
#include "windows.h" // this must be first to define GetCurrentDirectory
+#include <assert.h>
#include "cmGlobalVisualStudio7Generator.h"
#include "cmGeneratedFileStream.h"
#include "cmLocalVisualStudio7Generator.h"
@@ -26,8 +27,6 @@ void cmGlobalVisualStudio7Generator
::EnableLanguage(std::vector<std::string>const & lang,
cmMakefile *mf, bool optional)
{
- mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
- mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
mf->AddDefinition("CMAKE_GENERATOR_FC", "ifort");
@@ -243,20 +242,23 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
if(expath)
{
+ std::set<std::string> allConfigurations(this->Configurations.begin(),
+ this->Configurations.end());
this->WriteProjectConfigurations(
- fout, target->GetName(),
- true, target->GetProperty("VS_PLATFORM_MAPPING"));
+ fout, target->GetName(), target->GetType(),
+ allConfigurations, target->GetProperty("VS_PLATFORM_MAPPING"));
}
else
{
- bool partOfDefaultBuild = this->IsPartOfDefaultBuild(
- root->GetMakefile()->GetProjectName(), target);
+ const std::set<std::string>& configsPartOfDefaultBuild =
+ this->IsPartOfDefaultBuild(root->GetMakefile()->GetProjectName(),
+ target);
const char *vcprojName =
target->GetProperty("GENERATOR_FILE_NAME");
if (vcprojName)
{
- this->WriteProjectConfigurations(fout, vcprojName,
- partOfDefaultBuild);
+ this->WriteProjectConfigurations(fout, vcprojName, target->GetType(),
+ configsPartOfDefaultBuild);
}
}
}
@@ -268,6 +270,8 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
cmLocalGenerator* root,
OrderedTargetDependSet const& projectTargets)
{
+ VisualStudioFolders.clear();
+
for(OrderedTargetDependSet::const_iterator tt =
projectTargets.begin(); tt != projectTargets.end(); ++tt)
{
@@ -429,6 +433,9 @@ void cmGlobalVisualStudio7Generator
this->WriteTargetConfigurations(fout, root, orderedProjectTargets);
fout << "\tEndGlobalSection\n";
+ // Write out global sections
+ this->WriteSLNGlobalSections(fout, root);
+
// Write the footer for the SLN file
this->WriteSLNFooter(fout);
}
@@ -577,9 +584,10 @@ cmGlobalVisualStudio7Generator
// Write a dsp file into the SLN file, Note, that dependencies from
// executables to the libraries it uses are also done here
void cmGlobalVisualStudio7Generator
-::WriteProjectConfigurations(std::ostream& fout, const char* name,
- bool partOfDefaultBuild,
- const char* platformMapping)
+::WriteProjectConfigurations(
+ std::ostream& fout, const char* name, cmTarget::TargetType,
+ const std::set<std::string>& configsPartOfDefaultBuild,
+ const char* platformMapping)
{
std::string guid = this->GetGUID(name);
for(std::vector<std::string>::iterator i = this->Configurations.begin();
@@ -588,7 +596,9 @@ void cmGlobalVisualStudio7Generator
fout << "\t\t{" << guid << "}." << *i
<< ".ActiveCfg = " << *i << "|"
<< (platformMapping ? platformMapping : "Win32") << "\n";
- if(partOfDefaultBuild)
+ std::set<std::string>::const_iterator
+ ci = configsPartOfDefaultBuild.find(*i);
+ if(!(ci == configsPartOfDefaultBuild.end()))
{
fout << "\t\t{" << guid << "}." << *i
<< ".Build.0 = " << *i << "|"
@@ -622,14 +632,73 @@ void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout,
+void cmGlobalVisualStudio7Generator
+::WriteSLNGlobalSections(std::ostream& fout,
+ cmLocalGenerator* root)
+{
+ bool extensibilityGlobalsOverridden = false;
+ bool extensibilityAddInsOverridden = false;
+ const cmPropertyMap& props = root->GetMakefile()->GetProperties();
+ for(cmPropertyMap::const_iterator itProp = props.begin();
+ itProp != props.end(); ++itProp)
+ {
+ if(itProp->first.find("VS_GLOBAL_SECTION_") == 0)
+ {
+ std::string sectionType;
+ std::string name = itProp->first.substr(18);
+ if(name.find("PRE_") == 0)
+ {
+ name = name.substr(4);
+ sectionType = "preSolution";
+ }
+ else if(name.find("POST_") == 0)
+ {
+ name = name.substr(5);
+ sectionType = "postSolution";
+ }
+ else
+ continue;
+ if(!name.empty())
+ {
+ if(name == "ExtensibilityGlobals" && sectionType == "postSolution")
+ extensibilityGlobalsOverridden = true;
+ else if(name == "ExtensibilityAddIns" && sectionType == "postSolution")
+ extensibilityAddInsOverridden = true;
+ fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n";
+ std::vector<std::string> keyValuePairs;
+ cmSystemTools::ExpandListArgument(itProp->second.GetValue(),
+ keyValuePairs);
+ for(std::vector<std::string>::const_iterator itPair =
+ keyValuePairs.begin(); itPair != keyValuePairs.end(); ++itPair)
+ {
+ const std::string::size_type posEqual = itPair->find('=');
+ if(posEqual != std::string::npos)
+ {
+ const std::string key =
+ cmSystemTools::TrimWhitespace(itPair->substr(0, posEqual));
+ const std::string value =
+ cmSystemTools::TrimWhitespace(itPair->substr(posEqual + 1));
+ fout << "\t\t" << key << " = " << value << "\n";
+ }
+ }
+ fout << "\tEndGlobalSection\n";
+ }
+ }
+ }
+ if(!extensibilityGlobalsOverridden)
+ fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
+ << "\tEndGlobalSection\n";
+ if(!extensibilityAddInsOverridden)
+ fout << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
+ << "\tEndGlobalSection\n";
+}
+
+
+
// Standard end of dsw file
void cmGlobalVisualStudio7Generator::WriteSLNFooter(std::ostream& fout)
{
- fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
- << "\tEndGlobalSection\n"
- << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
- << "\tEndGlobalSection\n"
- << "EndGlobal\n";
+ fout << "EndGlobal\n";
}
@@ -738,9 +807,9 @@ std::vector<std::string> *cmGlobalVisualStudio7Generator::GetConfigurations()
//----------------------------------------------------------------------------
void cmGlobalVisualStudio7Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalVisualStudio7Generator::GetActualName();
entry.Brief = "Generates Visual Studio .NET 2002 project files.";
entry.Full = "";
}
@@ -761,26 +830,34 @@ cmGlobalVisualStudio7Generator
}
}
-bool cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(const char* project,
- cmTarget* target)
+std::set<std::string>
+cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(const char* project,
+ cmTarget* target)
{
- if(target->GetPropertyAsBool("EXCLUDE_FROM_DEFAULT_BUILD"))
- {
- return false;
- }
+ std::set<std::string> activeConfigs;
// if it is a utilitiy target then only make it part of the
// default build if another target depends on it
int type = target->GetType();
if (type == cmTarget::GLOBAL_TARGET)
{
- return false;
+ return activeConfigs;
}
- if(type == cmTarget::UTILITY)
+ if(type == cmTarget::UTILITY && !this->IsDependedOn(project, target))
{
- return this->IsDependedOn(project, target);
+ return activeConfigs;
+ }
+ // inspect EXCLUDE_FROM_DEFAULT_BUILD[_<CONFIG>] properties
+ for(std::vector<std::string>::iterator i = this->Configurations.begin();
+ i != this->Configurations.end(); ++i)
+ {
+ const char* propertyValue =
+ target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i->c_str());
+ if(cmSystemTools::IsOff(propertyValue))
+ {
+ activeConfigs.insert(*i);
+ }
}
- // default is to be part of the build
- return true;
+ return activeConfigs;
}
//----------------------------------------------------------------------------
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 1df58f9..6e78620 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -13,6 +13,7 @@
#define cmGlobalVisualStudio7Generator_h
#include "cmGlobalVisualStudioGenerator.h"
+#include "cmGlobalGeneratorFactory.h"
class cmTarget;
struct cmIDEFlagTable;
@@ -26,8 +27,9 @@ class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator
{
public:
cmGlobalVisualStudio7Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio7Generator; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory
+ <cmGlobalVisualStudio7Generator>(); }
///! Get the name for the generator.
virtual const char* GetName() const {
@@ -38,7 +40,7 @@ public:
virtual cmLocalGenerator *CreateLocalGenerator();
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
/**
* Try to determine system infomation such as shared library
@@ -105,10 +107,12 @@ protected:
const char* name, const char* path, cmTarget &t);
virtual void WriteProjectDepends(std::ostream& fout,
const char* name, const char* path, cmTarget &t);
- virtual void WriteProjectConfigurations(std::ostream& fout,
- const char* name,
- bool partOfDefaultBuild,
- const char* platformMapping = NULL);
+ virtual void WriteProjectConfigurations(
+ std::ostream& fout, const char* name, cmTarget::TargetType type,
+ const std::set<std::string>& configsPartOfDefaultBuild,
+ const char* platformMapping = NULL);
+ virtual void WriteSLNGlobalSections(std::ostream& fout,
+ cmLocalGenerator* root);
virtual void WriteSLNFooter(std::ostream& fout);
virtual void WriteSLNHeader(std::ostream& fout);
virtual std::string WriteUtilityDepend(cmTarget* target);
@@ -136,8 +140,8 @@ protected:
std::string ConvertToSolutionPath(const char* path);
- bool IsPartOfDefaultBuild(const char* project,
- cmTarget* target);
+ std::set<std::string> IsPartOfDefaultBuild(const char* project,
+ cmTarget* target);
std::vector<std::string> Configurations;
std::map<cmStdString, cmStdString> GUIDMap;
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index bca1754..864e8db 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -13,14 +13,117 @@
#include "cmGlobalVisualStudio8Generator.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
+#include "cmVisualStudioWCEPlatformParser.h"
#include "cmake.h"
#include "cmGeneratedFileStream.h"
+static const char vs8generatorName[] = "Visual Studio 8 2005";
+
+class cmGlobalVisualStudio8Generator::Factory
+ : public cmGlobalGeneratorFactory
+{
+public:
+ virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
+ if(strstr(name, vs8generatorName) != name)
+ {
+ return 0;
+ }
+
+ const char* p = name + sizeof(vs8generatorName) - 1;
+ if(p[0] == '\0')
+ {
+ return new cmGlobalVisualStudio8Generator(
+ name, NULL, NULL);
+ }
+
+ if(p[0] != ' ')
+ {
+ return 0;
+ }
+
+ ++p;
+
+ if(!strcmp(p, "Win64"))
+ {
+ return new cmGlobalVisualStudio8Generator(
+ name, "x64", "CMAKE_FORCE_WIN64");
+ }
+
+ cmVisualStudioWCEPlatformParser parser(p);
+ parser.ParseVersion("8.0");
+ if (!parser.Found())
+ {
+ return 0;
+ }
+
+ cmGlobalVisualStudio8Generator* ret = new cmGlobalVisualStudio8Generator(
+ name, parser.GetArchitectureFamily(), NULL);
+ ret->PlatformName = p;
+ ret->WindowsCEVersion = parser.GetOSVersion();
+ return ret;
+ }
+
+ virtual void GetDocumentation(cmDocumentationEntry& entry) const {
+ entry.Name = vs8generatorName;
+ entry.Brief = "Generates Visual Studio 8 2005 project files.";
+ entry.Full =
+ "It is possible to append a space followed by the platform name "
+ "to create project files for a specific target platform. E.g. "
+ "\"Visual Studio 8 2005 Win64\" will create project files for "
+ "the x64 processor.";
+ }
+
+ virtual void GetGenerators(std::vector<std::string>& names) const {
+ names.push_back(vs8generatorName);
+ names.push_back(vs8generatorName + std::string(" Win64"));
+ cmVisualStudioWCEPlatformParser parser;
+ parser.ParseVersion("8.0");
+ const std::vector<std::string>& availablePlatforms =
+ parser.GetAvailablePlatforms();
+ for(std::vector<std::string>::const_iterator i =
+ availablePlatforms.begin(); i != availablePlatforms.end(); ++i)
+ {
+ names.push_back("Visual Studio 8 2005 " + *i);
+ }
+ }
+};
+
+//----------------------------------------------------------------------------
+cmGlobalGeneratorFactory* cmGlobalVisualStudio8Generator::NewFactory()
+{
+ return new Factory;
+}
+
//----------------------------------------------------------------------------
-cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator()
+cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(
+ const char* name, const char* architectureId,
+ const char* additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS8FindMake.cmake";
this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms";
+ this->Name = name;
+ if (architectureId)
+ {
+ this->ArchitectureId = architectureId;
+ }
+ if (additionalPlatformDefinition)
+ {
+ this->AdditionalPlatformDefinition = additionalPlatformDefinition;
+ }
+}
+
+//----------------------------------------------------------------------------
+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();
}
//----------------------------------------------------------------------------
@@ -36,6 +139,19 @@ cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator()
}
//----------------------------------------------------------------------------
+void cmGlobalVisualStudio8Generator::AddPlatformDefinitions(cmMakefile* mf)
+{
+ cmGlobalVisualStudio71Generator::AddPlatformDefinitions(mf);
+ mf->AddDefinition("CMAKE_VS_PLATFORM_NAME", this->GetPlatformName());
+
+ if(this->TargetsWindowsCE())
+ {
+ mf->AddDefinition("CMAKE_VS_WINCE_VERSION",
+ this->WindowsCEVersion.c_str());
+ }
+}
+
+//----------------------------------------------------------------------------
// ouput standard header for dsw file
void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout)
{
@@ -45,9 +161,9 @@ void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout)
//----------------------------------------------------------------------------
void cmGlobalVisualStudio8Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalVisualStudio8Generator::GetActualName();
entry.Brief = "Generates Visual Studio 8 2005 project files.";
entry.Full = "";
}
@@ -204,7 +320,6 @@ void cmGlobalVisualStudio8Generator::AddCheckTarget()
// overwritten by the CreateVCProjBuildRule.
// (this could be avoided with per-target source files)
const char* no_main_dependency = 0;
- const char* no_working_directory = 0;
if(cmSourceFile* file =
mf->AddCustomCommandToOutput(
stamps, listFiles,
@@ -258,9 +373,10 @@ cmGlobalVisualStudio8Generator
//----------------------------------------------------------------------------
void
cmGlobalVisualStudio8Generator
-::WriteProjectConfigurations(std::ostream& fout, const char* name,
- bool partOfDefaultBuild,
- const char* platformMapping)
+::WriteProjectConfigurations(
+ std::ostream& fout, const char* name, cmTarget::TargetType type,
+ const std::set<std::string>& configsPartOfDefaultBuild,
+ const char* platformMapping)
{
std::string guid = this->GetGUID(name);
for(std::vector<std::string>::iterator i = this->Configurations.begin();
@@ -270,13 +386,24 @@ cmGlobalVisualStudio8Generator
<< "|" << this->GetPlatformName() << ".ActiveCfg = " << *i << "|"
<< (platformMapping ? platformMapping : this->GetPlatformName())
<< "\n";
- if(partOfDefaultBuild)
+ std::set<std::string>::const_iterator
+ ci = configsPartOfDefaultBuild.find(*i);
+ if(!(ci == configsPartOfDefaultBuild.end()))
{
fout << "\t\t{" << guid << "}." << *i
<< "|" << this->GetPlatformName() << ".Build.0 = " << *i << "|"
<< (platformMapping ? platformMapping : this->GetPlatformName())
<< "\n";
}
+ bool needsDeploy = (type == cmTarget::EXECUTABLE ||
+ type == cmTarget::SHARED_LIBRARY);
+ if(this->TargetsWindowsCE() && needsDeploy)
+ {
+ fout << "\t\t{" << guid << "}." << *i
+ << "|" << this->GetPlatformName() << ".Deploy.0 = " << *i << "|"
+ << (platformMapping ? platformMapping : this->GetPlatformName())
+ << "\n";
+ }
}
}
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index 5009f29..bcbd7a0 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -23,23 +23,23 @@
class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator
{
public:
- cmGlobalVisualStudio8Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio8Generator; }
+ cmGlobalVisualStudio8Generator(const char* name,
+ const char* architectureId, const char* additionalPlatformDefinition);
+ static cmGlobalGeneratorFactory* NewFactory();
///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio8Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 8 2005";}
+ virtual const char* GetName() const {return this->Name.c_str();}
- virtual const char* GetPlatformName() const {return "Win32";}
+ const char* GetPlatformName() const;
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
+ virtual void AddPlatformDefinitions(cmMakefile* mf);
+
/**
* Override Configure and Generate to add the build-system check
* target.
@@ -64,6 +64,10 @@ public:
LinkLibraryDependencies and link to .sln dependencies. */
virtual bool NeedLinkLibraryDependencies(cmTarget& target);
+ /** Return true if building for Windows CE */
+ virtual bool TargetsWindowsCE() const {
+ return !this->WindowsCEVersion.empty(); }
+
protected:
virtual const char* GetIDEVersion() { return "8.0"; }
@@ -74,12 +78,20 @@ protected:
static cmIDEFlagTable const* GetExtraFlagTableVS8();
virtual void WriteSLNHeader(std::ostream& fout);
virtual void WriteSolutionConfigurations(std::ostream& fout);
- virtual void WriteProjectConfigurations(std::ostream& fout,
- const char* name,
- bool partOfDefaultBuild,
- const char* platformMapping = NULL);
+ virtual void WriteProjectConfigurations(
+ std::ostream& fout, const char* name, cmTarget::TargetType type,
+ const std::set<std::string>& configsPartOfDefaultBuild,
+ const char* platformMapping = NULL);
virtual bool ComputeTargetDepends();
virtual void WriteProjectDepends(std::ostream& fout, const char* name,
const char* path, cmTarget &t);
+
+ std::string Name;
+ std::string PlatformName;
+ std::string WindowsCEVersion;
+
+private:
+ class Factory;
+ friend class Factory;
};
#endif
diff --git a/Source/cmGlobalVisualStudio8Win64Generator.cxx b/Source/cmGlobalVisualStudio8Win64Generator.cxx
deleted file mode 100644
index 4cbc275..0000000
--- a/Source/cmGlobalVisualStudio8Win64Generator.cxx
+++ /dev/null
@@ -1,40 +0,0 @@
-/*============================================================================
- 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.
-============================================================================*/
-#include "windows.h" // this must be first to define GetCurrentDirectory
-#include "cmGlobalVisualStudio8Win64Generator.h"
-#include "cmLocalVisualStudio7Generator.h"
-#include "cmMakefile.h"
-#include "cmake.h"
-
-
-
-cmGlobalVisualStudio8Win64Generator::cmGlobalVisualStudio8Win64Generator()
-{
- this->ArchitectureId = "x64";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio8Win64Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
-{
- entry.Name = this->GetName();
- entry.Brief = "Generates Visual Studio 8 2005 Win64 project files.";
- entry.Full = "";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio8Win64Generator
-::AddPlatformDefinitions(cmMakefile* mf)
-{
- this->cmGlobalVisualStudio8Generator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_FORCE_WIN64", "TRUE");
-}
diff --git a/Source/cmGlobalVisualStudio8Win64Generator.h b/Source/cmGlobalVisualStudio8Win64Generator.h
deleted file mode 100644
index 12f8012..0000000
--- a/Source/cmGlobalVisualStudio8Win64Generator.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*============================================================================
- 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.
-============================================================================*/
-#ifndef cmGlobalVisualStudio8Win64Generator_h
-#define cmGlobalVisualStudio8Win64Generator_h
-
-#include "cmGlobalVisualStudio8Generator.h"
-
-
-/** \class cmGlobalVisualStudio8Win64Generator
- * \brief Write a Unix makefiles.
- *
- * cmGlobalVisualStudio8Win64Generator manages UNIX build process for a tree
- */
-class cmGlobalVisualStudio8Win64Generator :
- public cmGlobalVisualStudio8Generator
-{
-public:
- cmGlobalVisualStudio8Win64Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio8Win64Generator; }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio8Win64Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 8 2005 Win64";}
-
- virtual const char* GetPlatformName() const {return "x64";}
-
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
-
- /**
- * Try to determine system infomation such as shared library
- * extension, pthreads, byte order etc.
- */
- virtual void AddPlatformDefinitions(cmMakefile *);
-};
-#endif
diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx
index 70af50d..2082384 100644
--- a/Source/cmGlobalVisualStudio9Generator.cxx
+++ b/Source/cmGlobalVisualStudio9Generator.cxx
@@ -13,11 +13,99 @@
#include "cmGlobalVisualStudio9Generator.h"
#include "cmLocalVisualStudio7Generator.h"
#include "cmMakefile.h"
+#include "cmVisualStudioWCEPlatformParser.h"
#include "cmake.h"
+static const char vs9generatorName[] = "Visual Studio 9 2008";
+class cmGlobalVisualStudio9Generator::Factory
+ : public cmGlobalGeneratorFactory
+{
+public:
+ virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const {
+ if(strstr(name, vs9generatorName) != name)
+ {
+ return 0;
+ }
+
+ const char* p = name + sizeof(vs9generatorName) - 1;
+ if(p[0] == '\0')
+ {
+ return new cmGlobalVisualStudio9Generator(
+ name, NULL, NULL);
+ }
+
+ if(p[0] != ' ')
+ {
+ return 0;
+ }
+
+ ++p;
+
+ if(!strcmp(p, "IA64"))
+ {
+ return new cmGlobalVisualStudio9Generator(
+ name, "Itanium", "CMAKE_FORCE_IA64");
+ }
+
+ if(!strcmp(p, "Win64"))
+ {
+ return new cmGlobalVisualStudio9Generator(
+ name, "x64", "CMAKE_FORCE_WIN64");
+ }
+
+ cmVisualStudioWCEPlatformParser parser(p);
+ parser.ParseVersion("9.0");
+ if (!parser.Found())
+ {
+ return 0;
+ }
+
+ cmGlobalVisualStudio9Generator* ret = new cmGlobalVisualStudio9Generator(
+ name, parser.GetArchitectureFamily(), NULL);
+ ret->PlatformName = p;
+ ret->WindowsCEVersion = parser.GetOSVersion();
+ return ret;
+ }
+
+ virtual void GetDocumentation(cmDocumentationEntry& entry) const {
+ entry.Name = vs9generatorName;
+ entry.Brief = "Generates Visual Studio 9 2008 project files.";
+ entry.Full =
+ "It is possible to append a space followed by the platform name "
+ "to create project files for a specific target platform. E.g. "
+ "\"Visual Studio 9 2008 Win64\" will create project files for "
+ "the x64 processor; \"Visual Studio 9 2008 IA64\" for Itanium.";
+ }
+
+ virtual void GetGenerators(std::vector<std::string>& names) const {
+ names.push_back(vs9generatorName);
+ names.push_back(vs9generatorName + std::string(" Win64"));
+ names.push_back(vs9generatorName + std::string(" IA64"));
+ cmVisualStudioWCEPlatformParser parser;
+ parser.ParseVersion("9.0");
+ const std::vector<std::string>& availablePlatforms =
+ parser.GetAvailablePlatforms();
+ for(std::vector<std::string>::const_iterator i =
+ availablePlatforms.begin(); i != availablePlatforms.end(); ++i)
+ {
+ names.push_back("Visual Studio 9 2008 " + *i);
+ }
+ }
+};
-cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator()
+//----------------------------------------------------------------------------
+cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory()
+{
+ return new Factory;
+}
+
+//----------------------------------------------------------------------------
+cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator(
+ const char* name, const char* architectureId,
+ const char* additionalPlatformDefinition)
+ : cmGlobalVisualStudio8Generator(name, architectureId,
+ additionalPlatformDefinition)
{
this->FindMakeProgramFile = "CMakeVS9FindMake.cmake";
}
@@ -42,15 +130,6 @@ cmLocalGenerator *cmGlobalVisualStudio9Generator::CreateLocalGenerator()
//----------------------------------------------------------------------------
void cmGlobalVisualStudio9Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
-{
- entry.Name = this->GetName();
- entry.Brief = "Generates Visual Studio 9 2008 project files.";
- entry.Full = "";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio9Generator
::EnableLanguage(std::vector<std::string>const & lang,
cmMakefile *mf, bool optional)
{
diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h
index 0b0d143..1310a93 100644
--- a/Source/cmGlobalVisualStudio9Generator.h
+++ b/Source/cmGlobalVisualStudio9Generator.h
@@ -24,17 +24,9 @@ class cmGlobalVisualStudio9Generator :
public cmGlobalVisualStudio8Generator
{
public:
- cmGlobalVisualStudio9Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio9Generator; }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio9Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 9 2008";}
-
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ cmGlobalVisualStudio9Generator(const char* name,
+ const char* architectureId, const char* additionalPlatformDefinition);
+ static cmGlobalGeneratorFactory* NewFactory();
///! create the correct local generator
virtual cmLocalGenerator *CreateLocalGenerator();
@@ -61,5 +53,8 @@ public:
virtual std::string GetUserMacrosRegKeyBase();
protected:
virtual const char* GetIDEVersion() { return "9.0"; }
+private:
+ class Factory;
+ friend class Factory;
};
#endif
diff --git a/Source/cmGlobalVisualStudio9IA64Generator.cxx b/Source/cmGlobalVisualStudio9IA64Generator.cxx
deleted file mode 100644
index 38dbfac..0000000
--- a/Source/cmGlobalVisualStudio9IA64Generator.cxx
+++ /dev/null
@@ -1,37 +0,0 @@
-/*============================================================================
- 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.
-============================================================================*/
-#include "cmGlobalVisualStudio9IA64Generator.h"
-#include "cmLocalVisualStudio7Generator.h"
-#include "cmMakefile.h"
-
-
-cmGlobalVisualStudio9IA64Generator::cmGlobalVisualStudio9IA64Generator()
-{
- this->ArchitectureId = "Itanium";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio9IA64Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
-{
- entry.Name = this->GetName();
- entry.Brief = "Generates Visual Studio 9 2008 Itanium project files.";
- entry.Full = "";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio9IA64Generator
-::AddPlatformDefinitions(cmMakefile* mf)
-{
- cmGlobalVisualStudio9Generator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_FORCE_IA64", "TRUE");
-}
diff --git a/Source/cmGlobalVisualStudio9IA64Generator.h b/Source/cmGlobalVisualStudio9IA64Generator.h
deleted file mode 100644
index 989b0d1..0000000
--- a/Source/cmGlobalVisualStudio9IA64Generator.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*============================================================================
- 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.
-============================================================================*/
-#ifndef cmGlobalVisualStudio9IA64Generator_h
-#define cmGlobalVisualStudio9IA64Generator_h
-
-#include "cmGlobalVisualStudio9Generator.h"
-
-
-/** \class cmGlobalVisualStudio8IA64Generator
- * \brief Write a Unix makefiles.
- *
- * cmGlobalVisualStudio8IA64Generator manages UNIX build process for a tree
- */
-class cmGlobalVisualStudio9IA64Generator :
- public cmGlobalVisualStudio9Generator
-{
-public:
- cmGlobalVisualStudio9IA64Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio9IA64Generator; }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio9IA64Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 9 2008 IA64";}
-
- virtual const char* GetPlatformName() const {return "Itanium";}
-
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
-
- /**
- * Try to determine system infomation such as shared library
- * extension, pthreads, byte order etc.
- */
- virtual void AddPlatformDefinitions(cmMakefile *);
-};
-#endif
diff --git a/Source/cmGlobalVisualStudio9Win64Generator.cxx b/Source/cmGlobalVisualStudio9Win64Generator.cxx
deleted file mode 100644
index 4d8a646..0000000
--- a/Source/cmGlobalVisualStudio9Win64Generator.cxx
+++ /dev/null
@@ -1,37 +0,0 @@
-/*============================================================================
- 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.
-============================================================================*/
-#include "cmGlobalVisualStudio9Win64Generator.h"
-#include "cmLocalVisualStudio7Generator.h"
-#include "cmMakefile.h"
-
-
-cmGlobalVisualStudio9Win64Generator::cmGlobalVisualStudio9Win64Generator()
-{
- this->ArchitectureId = "x64";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio9Win64Generator
-::GetDocumentation(cmDocumentationEntry& entry) const
-{
- entry.Name = this->GetName();
- entry.Brief = "Generates Visual Studio 9 2008 Win64 project files.";
- entry.Full = "";
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalVisualStudio9Win64Generator
-::AddPlatformDefinitions(cmMakefile* mf)
-{
- cmGlobalVisualStudio9Generator::AddPlatformDefinitions(mf);
- mf->AddDefinition("CMAKE_FORCE_WIN64", "TRUE");
-}
diff --git a/Source/cmGlobalVisualStudio9Win64Generator.h b/Source/cmGlobalVisualStudio9Win64Generator.h
deleted file mode 100644
index 7c20cf4..0000000
--- a/Source/cmGlobalVisualStudio9Win64Generator.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*============================================================================
- 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.
-============================================================================*/
-#ifndef cmGlobalVisualStudio9Win64Generator_h
-#define cmGlobalVisualStudio9Win64Generator_h
-
-#include "cmGlobalVisualStudio9Generator.h"
-
-
-/** \class cmGlobalVisualStudio8Win64Generator
- * \brief Write a Unix makefiles.
- *
- * cmGlobalVisualStudio8Win64Generator manages UNIX build process for a tree
- */
-class cmGlobalVisualStudio9Win64Generator :
- public cmGlobalVisualStudio9Generator
-{
-public:
- cmGlobalVisualStudio9Win64Generator();
- static cmGlobalGenerator* New() {
- return new cmGlobalVisualStudio9Win64Generator; }
-
- ///! Get the name for the generator.
- virtual const char* GetName() const {
- return cmGlobalVisualStudio9Win64Generator::GetActualName();}
- static const char* GetActualName() {return "Visual Studio 9 2008 Win64";}
-
- virtual const char* GetPlatformName() const {return "x64";}
-
- /** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
-
- /**
- * Try to determine system infomation such as shared library
- * extension, pthreads, byte order etc.
- */
- virtual void AddPlatformDefinitions(cmMakefile *);
-};
-#endif
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 0968b77..808664d 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -22,6 +22,7 @@
cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator()
{
this->ArchitectureId = "X86";
+ this->AdditionalPlatformDefinition = NULL;
}
//----------------------------------------------------------------------------
@@ -32,9 +33,16 @@ cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator()
//----------------------------------------------------------------------------
std::string cmGlobalVisualStudioGenerator::GetRegistryBase()
{
+ return cmGlobalVisualStudioGenerator::GetRegistryBase(
+ this->GetIDEVersion());
+}
+
+//----------------------------------------------------------------------------
+std::string cmGlobalVisualStudioGenerator::GetRegistryBase(
+ const char* version)
+{
std::string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\";
- key += this->GetIDEVersion();
- return key;
+ return key + version;
}
//----------------------------------------------------------------------------
@@ -75,7 +83,6 @@ void cmGlobalVisualStudioGenerator::Generate()
#endif
// Now make all targets depend on the ALL_BUILD target
- cmTargets targets;
for(std::vector<cmLocalGenerator*>::iterator i = gen.begin();
i != gen.end(); ++i)
{
@@ -492,8 +499,13 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target)
//----------------------------------------------------------------------------
void cmGlobalVisualStudioGenerator::AddPlatformDefinitions(cmMakefile* mf)
{
- mf->AddDefinition("MSVC_C_ARCHITECTURE_ID", this->ArchitectureId);
- mf->AddDefinition("MSVC_CXX_ARCHITECTURE_ID", this->ArchitectureId);
+ 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 cebf7d7..9d81170 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -65,10 +65,16 @@ public:
/** Get the top-level registry key for this VS version. */
std::string GetRegistryBase();
+ /** Get the top-level registry key for the given VS version. */
+ static std::string GetRegistryBase(const char* version);
+
/** Return true if the generated build tree may contain multiple builds.
i.e. "Can I build Debug and Release in the same tree?" */
virtual bool IsMultiConfig() { return true; }
+ /** Return true if building for Windows CE */
+ virtual bool TargetsWindowsCE() const { return false; }
+
class TargetSet: public std::set<cmTarget*> {};
struct TargetCompare
{
@@ -98,7 +104,8 @@ protected:
std::string GetUtilityDepend(cmTarget* target);
typedef std::map<cmTarget*, cmStdString> UtilityDependsMap;
UtilityDependsMap UtilityDepends;
- const char* ArchitectureId;
+ std::string ArchitectureId;
+ const char* AdditionalPlatformDefinition;
private:
void ComputeTargetObjects(cmGeneratorTarget* gt) const;
diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx
index 45b171f..e3cebc4 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.cxx
+++ b/Source/cmGlobalWatcomWMakeGenerator.cxx
@@ -58,9 +58,9 @@ cmLocalGenerator *cmGlobalWatcomWMakeGenerator::CreateLocalGenerator()
//----------------------------------------------------------------------------
void cmGlobalWatcomWMakeGenerator
-::GetDocumentation(cmDocumentationEntry& entry) const
+::GetDocumentation(cmDocumentationEntry& entry)
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalWatcomWMakeGenerator::GetActualName();
entry.Brief = "Generates Watcom WMake makefiles.";
entry.Full = "";
}
diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h
index ee16eae..23e60a1 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.h
+++ b/Source/cmGlobalWatcomWMakeGenerator.h
@@ -23,14 +23,16 @@ class cmGlobalWatcomWMakeGenerator : public cmGlobalUnixMakefileGenerator3
{
public:
cmGlobalWatcomWMakeGenerator();
- static cmGlobalGenerator* New() { return new cmGlobalWatcomWMakeGenerator; }
+ static cmGlobalGeneratorFactory* NewFactory() {
+ return new cmGlobalGeneratorSimpleFactory
+ <cmGlobalWatcomWMakeGenerator>(); }
///! Get the name for the generator.
virtual const char* GetName() const {
return cmGlobalWatcomWMakeGenerator::GetActualName();}
static const char* GetActualName() {return "Watcom WMake";}
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 30d8f18..3092abf 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -20,6 +20,7 @@
#include "cmSourceFile.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalGeneratorFactory.h"
#include <cmsys/auto_ptr.hxx>
@@ -112,6 +113,18 @@ public:
}
};
+class cmGlobalXCodeGenerator::Factory : public cmGlobalGeneratorFactory
+{
+public:
+ virtual cmGlobalGenerator* CreateGlobalGenerator(const char* name) const;
+
+ virtual void GetDocumentation(cmDocumentationEntry& entry) const {
+ cmGlobalXCodeGenerator::GetDocumentation(entry); }
+
+ virtual void GetGenerators(std::vector<std::string>& names) const {
+ names.push_back(cmGlobalXCodeGenerator::GetActualName()); }
+};
+
//----------------------------------------------------------------------------
cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(std::string const& version)
{
@@ -132,8 +145,17 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(std::string const& version)
}
//----------------------------------------------------------------------------
-cmGlobalGenerator* cmGlobalXCodeGenerator::New()
+cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory()
{
+ return new Factory;
+}
+
+//----------------------------------------------------------------------------
+cmGlobalGenerator* cmGlobalXCodeGenerator::Factory
+::CreateGlobalGenerator(const char* name) const
+{
+ if (strcmp(name, GetActualName()))
+ return 0;
#if defined(CMAKE_BUILD_WITH_CMAKE)
cmXcodeVersionParser parser;
std::string versionFile;
@@ -179,6 +201,20 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::New()
}
//----------------------------------------------------------------------------
+bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts)
+{
+ if(this->XcodeVersion >= 30)
+ {
+ this->PlatformToolset = ts;
+ return true;
+ }
+ else
+ {
+ return cmGlobalGenerator::SetGeneratorToolset(ts);
+ }
+}
+
+//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const&
lang,
cmMakefile * mf, bool optional)
@@ -201,9 +237,12 @@ void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const&
cmCacheManager::STRING);
}
}
- mf->AddDefinition("CMAKE_GENERATOR_CC", "gcc");
- mf->AddDefinition("CMAKE_GENERATOR_CXX", "g++");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
+ if(!this->PlatformToolset.empty())
+ {
+ mf->AddDefinition("CMAKE_XCODE_PLATFORM_TOOLSET",
+ this->PlatformToolset.c_str());
+ }
this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
const char* osxArch =
mf->GetDefinition("CMAKE_OSX_ARCHITECTURES");
@@ -495,8 +534,12 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
(this->CurrentReRunCMakeMakefile.c_str());
makefileStream.SetCopyIfDifferent(true);
makefileStream << "# Generated by CMake, DO NOT EDIT\n";
- makefileStream << cmake::GetCMakeFilesDirectoryPostSlash();
- makefileStream << "cmake.check_cache: ";
+ std::string checkCache = mf->GetHomeOutputDirectory();
+ checkCache += "/";
+ checkCache += cmake::GetCMakeFilesDirectoryPostSlash();
+ checkCache += "cmake.check_cache";
+ makefileStream << this->ConvertToRelativeForMake(checkCache.c_str())
+ << ": ";
for(std::vector<std::string>::const_iterator i = lfiles.begin();
i != lfiles.end(); ++i)
{
@@ -911,6 +954,15 @@ void cmGlobalXCodeGenerator::SetCurrentLocalGenerator(cmLocalGenerator* gen)
}
//----------------------------------------------------------------------------
+struct cmSourceFilePathCompare
+{
+ bool operator()(cmSourceFile* l, cmSourceFile* r)
+ {
+ return l->GetFullPath() < r->GetFullPath();
+ }
+};
+
+//----------------------------------------------------------------------------
void
cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
std::vector<cmXCodeObject*>&
@@ -936,7 +988,9 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
}
// organize the sources
- std::vector<cmSourceFile*> const &classes = cmtarget.GetSourceFiles();
+ std::vector<cmSourceFile*> classes = cmtarget.GetSourceFiles();
+ std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
+
std::vector<cmXCodeObject*> externalObjFiles;
std::vector<cmXCodeObject*> headerFiles;
std::vector<cmXCodeObject*> resourceFiles;
@@ -1180,7 +1234,7 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget)
// If the language is compiled as a source trust Xcode to link with it.
cmTarget::LinkImplementation const* impl =
- cmtarget.GetLinkImplementation("NOCONFIG");
+ cmtarget.GetLinkImplementation("NOCONFIG", &cmtarget);
for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
li != impl->Languages.end(); ++li)
{
@@ -1341,16 +1395,18 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
}
//----------------------------------------------------------------------------
-// This function removes each occurence of the flag and returns the last one
+// This function removes each occurrence of the flag and returns the last one
// (i.e., the dominant flag in GCC)
std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
std::string& flags)
{
std::string retFlag;
- std::string::size_type pos = flags.rfind(flag);
+ std::string::size_type lastOccurancePos = flags.rfind(flag);
bool saved = false;
- while(pos != flags.npos)
+ while(lastOccurancePos != flags.npos)
{
+ //increment pos, we use lastOccurancePos to reduce search space on next inc
+ std::string::size_type pos = lastOccurancePos;
if(pos == 0 || flags[pos-1]==' ')
{
while(pos < flags.size() && flags[pos] != ' ')
@@ -1362,9 +1418,12 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
flags[pos] = ' ';
pos++;
}
- }
saved = true;
- pos = flags.rfind(flag);
+ }
+ //decrement lastOccurancePos while making sure we don't loop around
+ //and become a very large positive number since size_type is unsigned
+ lastOccurancePos = lastOccurancePos == 0 ? 0 : lastOccurancePos-1;
+ lastOccurancePos = flags.rfind(flag,lastOccurancePos);
}
return retFlag;
}
@@ -1613,14 +1672,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
if(strcmp(lang, "CXX") == 0)
{
this->CurrentLocalGenerator->AddLanguageFlags(cflags, "C", configName);
- this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target, "C");
+ this->CurrentLocalGenerator->AddCMP0018Flags(cflags, &target,
+ "C", configName);
}
// Add language-specific flags.
this->CurrentLocalGenerator->AddLanguageFlags(flags, lang, configName);
// Add shared-library flags if needed.
- this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target, lang);
+ this->CurrentLocalGenerator->AddCMP0018Flags(flags, &target,
+ lang, configName);
}
else if(binary)
{
@@ -1648,12 +1709,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
this->AppendDefines(ppDefs, exportMacro);
}
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
- this->AppendDefines(ppDefs, gtgt->GetCompileDefinitions().c_str());
- if(configName)
- {
- this->AppendDefines(ppDefs,
- gtgt->GetCompileDefinitions(configName).c_str());
- }
+ this->AppendDefines(ppDefs,
+ target.GetCompileDefinitions(configName).c_str());
buildSettings->AddAttribute
("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());
@@ -1971,15 +2028,16 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
dirs.Add(incpath.c_str());
}
}
- std::vector<std::string>& frameworks = target.GetFrameworks();
- if(frameworks.size())
+ // Add framework search paths needed for linking.
+ if(cmComputeLinkInformation* cli = target.GetLinkInformation(configName))
{
- for(std::vector<std::string>::iterator fmIt = frameworks.begin();
- fmIt != frameworks.end(); ++fmIt)
+ std::vector<std::string> const& fwDirs = cli->GetFrameworkPaths();
+ for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
+ fdi != fwDirs.end(); ++fdi)
{
- if(emitted.insert(*fmIt).second)
+ if(emitted.insert(*fdi).second)
{
- fdirs.Add(this->XCodeEscapePath(fmIt->c_str()).c_str());
+ fdirs.Add(this->XCodeEscapePath(fdi->c_str()).c_str());
}
}
}
@@ -2044,6 +2102,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
debugStr = "NO";
}
+ buildSettings->AddAttribute("COMBINE_HIDPI_IMAGES",
+ this->CreateString("YES"));
buildSettings->AddAttribute("GCC_GENERATE_DEBUGGING_SYMBOLS",
this->CreateString(debugStr));
buildSettings->AddAttribute("GCC_OPTIMIZATION_LEVEL",
@@ -2460,47 +2520,25 @@ std::string cmGlobalXCodeGenerator::GetOrCreateId(const char* name,
void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
cmXCodeObject* dependTarget)
{
- // make sure a target does not depend on itself
- if(target == dependTarget)
- {
- return;
- }
- // now avoid circular references if dependTarget already
- // depends on target then skip it. Circular references crashes
- // xcode
- cmXCodeObject* dependTargetDepends =
- dependTarget->GetObject("dependencies");
- if(dependTargetDepends)
- {
- if(dependTargetDepends->HasObject(target->GetPBXTargetDependency()))
- {
- return;
- }
- }
-
- cmXCodeObject* targetdep = dependTarget->GetPBXTargetDependency();
- if(!targetdep)
- {
- cmXCodeObject* container =
- this->CreateObject(cmXCodeObject::PBXContainerItemProxy);
- container->SetComment("PBXContainerItemProxy");
- container->AddAttribute("containerPortal",
- this->CreateObjectReference(this->RootObject));
- container->AddAttribute("proxyType", this->CreateString("1"));
- container->AddAttribute("remoteGlobalIDString",
- this->CreateObjectReference(dependTarget));
- container->AddAttribute("remoteInfo",
- this->CreateString(
- dependTarget->GetTarget()->GetName()));
- targetdep =
- this->CreateObject(cmXCodeObject::PBXTargetDependency);
- targetdep->SetComment("PBXTargetDependency");
- targetdep->AddAttribute("target",
- this->CreateObjectReference(dependTarget));
- targetdep->AddAttribute("targetProxy",
- this->CreateObjectReference(container));
- dependTarget->SetPBXTargetDependency(targetdep);
- }
+ // This is called once for every edge in the target dependency graph.
+ cmXCodeObject* container =
+ this->CreateObject(cmXCodeObject::PBXContainerItemProxy);
+ container->SetComment("PBXContainerItemProxy");
+ container->AddAttribute("containerPortal",
+ this->CreateObjectReference(this->RootObject));
+ container->AddAttribute("proxyType", this->CreateString("1"));
+ container->AddAttribute("remoteGlobalIDString",
+ this->CreateObjectReference(dependTarget));
+ container->AddAttribute("remoteInfo",
+ this->CreateString(
+ dependTarget->GetTarget()->GetName()));
+ cmXCodeObject* targetdep =
+ this->CreateObject(cmXCodeObject::PBXTargetDependency);
+ targetdep->SetComment("PBXTargetDependency");
+ targetdep->AddAttribute("target",
+ this->CreateObjectReference(dependTarget));
+ targetdep->AddAttribute("targetProxy",
+ this->CreateObjectReference(container));
cmXCodeObject* depends = target->GetObject("dependencies");
if(!depends)
@@ -2623,8 +2661,7 @@ void cmGlobalXCodeGenerator
}
// Compute the link library and directory information.
- cmGeneratorTarget* gtgt = this->GetGeneratorTarget(cmtarget);
- cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName);
+ cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName);
if(!pcli)
{
continue;
@@ -2666,25 +2703,6 @@ void cmGlobalXCodeGenerator
linkDirs.c_str(), configName);
}
- // add the framework search paths
- {
- const char* sep = "";
- std::string fdirs;
- std::vector<std::string> const& fwDirs = cli.GetFrameworkPaths();
- for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
- fdi != fwDirs.end(); ++fdi)
- {
- fdirs += sep;
- sep = " ";
- fdirs += this->XCodeEscapePath(fdi->c_str());
- }
- if(!fdirs.empty())
- {
- this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS",
- fdirs.c_str(), configName);
- }
- }
-
// now add the link libraries
{
std::string linkLibs;
@@ -2877,7 +2895,7 @@ cmXCodeObject* cmGlobalXCodeGenerator
{
std::vector<std::string> folders =
cmSystemTools::tokenize(sg->GetFullName(), "\\");
- cmStdString curr_folder = cmtarget.GetName();
+ cmStdString curr_folder = target;
curr_folder += "/";
for(std::vector<std::string>::size_type i = 0; i < folders.size();i++)
{
@@ -3145,6 +3163,11 @@ void cmGlobalXCodeGenerator
buildSettings->AddAttribute("MACOSX_DEPLOYMENT_TARGET",
this->CreateString(deploymentTarget));
}
+ if(!this->PlatformToolset.empty())
+ {
+ buildSettings->AddAttribute("GCC_VERSION",
+ this->CreateString(this->PlatformToolset.c_str()));
+ }
// Put this last so it can override existing settings
// Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly.
@@ -3470,9 +3493,8 @@ const char* cmGlobalXCodeGenerator::GetCMakeCFGIntDir() const
//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry)
- const
{
- entry.Name = this->GetName();
+ entry.Name = cmGlobalXCodeGenerator::GetActualName();
entry.Brief = "Generate Xcode project files.";
entry.Full = "";
}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index afa1ca2..131a6e6 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -15,6 +15,7 @@
#include "cmGlobalGenerator.h"
#include "cmXCodeObject.h"
#include "cmCustomCommand.h"
+class cmGlobalGeneratorFactory;
class cmTarget;
class cmSourceFile;
class cmSourceGroup;
@@ -29,7 +30,7 @@ class cmGlobalXCodeGenerator : public cmGlobalGenerator
{
public:
cmGlobalXCodeGenerator(std::string const& version);
- static cmGlobalGenerator* New();
+ static cmGlobalGeneratorFactory* NewFactory();
///! Get the name for the generator.
virtual const char* GetName() const {
@@ -37,7 +38,7 @@ public:
static const char* GetActualName() {return "Xcode";}
/** Get the documentation entry for this generator. */
- virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+ static void GetDocumentation(cmDocumentationEntry& entry);
///! Create a local generator appropriate to this Global Generator
virtual cmLocalGenerator *CreateLocalGenerator();
@@ -82,6 +83,7 @@ public:
i.e. "Can I build Debug and Release in the same tree?" */
virtual bool IsMultiConfig();
+ virtual bool SetGeneratorToolset(std::string const& ts);
private:
cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget,
cmSourceGroup* sg);
@@ -186,6 +188,7 @@ private:
const char* varNameSuffix,
const char* default_flags);
+ class Factory;
class BuildObjectListOrString;
friend class BuildObjectListOrString;
@@ -234,6 +237,7 @@ private:
std::map<cmStdString, cmXCodeObject* > TargetGroup;
std::map<cmStdString, cmXCodeObject* > FileRefs;
std::vector<std::string> Architectures;
+ std::string PlatformToolset;
};
#endif
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index 15bad52..4816da9 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -15,8 +15,6 @@
#include "cmGlobalGenerator.h"
#include "cmGeneratedFileStream.h"
-#include <memory>
-
static const char* getShapeForTarget(const cmTarget* target)
@@ -67,7 +65,7 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
cmake cm;
cmGlobalGenerator ggi;
ggi.SetCMakeInstance(&cm);
- std::auto_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator());
+ cmsys::auto_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator());
cmMakefile *mf = lg->GetMakefile();
const char* inFileName = settingsFileName;
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index d9c0e87..76a60cf 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -177,3 +177,14 @@ void cmIDEOptions::RemoveFlag(const char* flag)
{
this->FlagMap.erase(flag);
}
+
+//----------------------------------------------------------------------------
+const char* cmIDEOptions::GetFlag(const char* flag)
+{
+ std::map<cmStdString, cmStdString>::iterator i = this->FlagMap.find(flag);
+ if(i != this->FlagMap.end())
+ {
+ return i->second.c_str();
+ }
+ return 0;
+}
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index a5be8fb..e556bde 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -29,6 +29,7 @@ public:
void AddDefines(const char* defines);
void AddFlag(const char* flag, const char* value);
void RemoveFlag(const char* flag);
+ const char* GetFlag(const char* flag);
protected:
// create a map of xml tags to the values they should have in the output
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index ba81849..30c1743 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -36,6 +36,10 @@ bool cmIncludeDirectoryCommand
++i;
}
+ std::vector<std::string> beforeIncludes;
+ std::vector<std::string> afterIncludes;
+ std::set<cmStdString> systemIncludes;
+
for(; i != args.end(); ++i)
{
if(*i == "SYSTEM")
@@ -49,9 +53,37 @@ bool cmIncludeDirectoryCommand
return false;
}
- this->AddDirectory(i->c_str(),before,system);
+ std::vector<std::string> includes;
+
+ GetIncludes(*i, includes);
+ if (before)
+ {
+ beforeIncludes.insert(beforeIncludes.end(),
+ includes.begin(),
+ includes.end());
+ }
+ else
+ {
+ afterIncludes.insert(afterIncludes.end(),
+ includes.begin(),
+ includes.end());
+ }
+ if (system)
+ {
+ for (std::vector<std::string>::const_iterator li = includes.begin();
+ li != includes.end(); ++li)
+ {
+ systemIncludes.insert(*li);
+ }
+ }
}
+ std::reverse(beforeIncludes.begin(), beforeIncludes.end());
+
+ this->Makefile->AddIncludeDirectories(afterIncludes);
+ this->Makefile->AddIncludeDirectories(beforeIncludes, before);
+ this->Makefile->AddSystemIncludeDirectories(systemIncludes);
+
return true;
}
@@ -72,57 +104,60 @@ static bool StartsWithGeneratorExpression(const std::string &input)
// output from a program and passing it into a command the cleanup doesn't
// always happen
//
-void cmIncludeDirectoryCommand::AddDirectory(const char *i,
- bool before,
- bool system)
+void cmIncludeDirectoryCommand::GetIncludes(const std::string &arg,
+ std::vector<std::string> &incs)
{
// break apart any line feed arguments
- std::string ret = i;
std::string::size_type pos = 0;
- if((pos = ret.find('\n', pos)) != std::string::npos)
+ std::string::size_type lastPos = 0;
+ while((pos = arg.find('\n', lastPos)) != std::string::npos)
{
if (pos)
{
- this->AddDirectory(ret.substr(0,pos).c_str(), before, system);
- }
- if (ret.size()-pos-1)
- {
- this->AddDirectory(ret.substr(pos+1,ret.size()-pos-1).c_str(),
- before, system);
+ std::string inc = arg.substr(lastPos,pos);
+ this->NormalizeInclude(inc);
+ if (!inc.empty())
+ {
+ incs.push_back(inc);
+ }
}
- return;
+ lastPos = pos + 1;
}
+ std::string inc = arg.substr(lastPos);
+ this->NormalizeInclude(inc);
+ if (!inc.empty())
+ {
+ incs.push_back(inc);
+ }
+}
- // remove any leading or trailing spaces and \r
- std::string::size_type b = ret.find_first_not_of(" \r");
- std::string::size_type e = ret.find_last_not_of(" \r");
- if ((b!=ret.npos) && (e!=ret.npos))
+void cmIncludeDirectoryCommand::NormalizeInclude(std::string &inc)
+{
+ std::string::size_type b = inc.find_first_not_of(" \r");
+ std::string::size_type e = inc.find_last_not_of(" \r");
+ if ((b!=inc.npos) && (e!=inc.npos))
{
- ret.assign(ret, b, 1+e-b); // copy the remaining substring
+ inc.assign(inc, b, 1+e-b); // copy the remaining substring
}
else
{
- return; // if we get here, we had only whitespace in the string
+ inc = "";
+ return;
}
- if (!cmSystemTools::IsOff(ret.c_str()))
+ if (!cmSystemTools::IsOff(inc.c_str()))
{
- cmSystemTools::ConvertToUnixSlashes(ret);
- if(!cmSystemTools::FileIsFullPath(ret.c_str()))
+ cmSystemTools::ConvertToUnixSlashes(inc);
+
+ if(!cmSystemTools::FileIsFullPath(inc.c_str()))
{
- if(!StartsWithGeneratorExpression(ret))
+ if(!StartsWithGeneratorExpression(inc))
{
std::string tmp = this->Makefile->GetStartDirectory();
tmp += "/";
- tmp += ret;
- ret = tmp;
+ tmp += inc;
+ inc = tmp;
}
}
}
- this->Makefile->AddIncludeDirectory(ret.c_str(), before);
- if(system)
- {
- this->Makefile->AddSystemIncludeDirectory(ret.c_str());
- }
}
-
diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h
index 6751fc0..77a340a 100644
--- a/Source/cmIncludeDirectoryCommand.h
+++ b/Source/cmIncludeDirectoryCommand.h
@@ -59,8 +59,9 @@ public:
return
" include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)\n"
"Add the given directories to those the compiler uses to search "
- "for include files. "
- "These directories are added to the directory property "
+ "for include files. Relative paths are interpreted as relative to "
+ "the current source directory. \n"
+ "The include directories are added to the directory property "
"INCLUDE_DIRECTORIES for the current CMakeLists file. "
"They are also added to the target property INCLUDE_DIRECTORIES "
"for each target in the current CMakeLists file. "
@@ -72,16 +73,20 @@ public:
"CMAKE_INCLUDE_DIRECTORIES_BEFORE to ON. "
"By using AFTER or BEFORE explicitly, you can select between "
"appending and prepending, independent of the default. "
+ "\n"
"If the SYSTEM option is given, the compiler will be told the "
"directories are meant as system include directories on some "
- "platforms.";
+ "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).";
}
cmTypeMacro(cmIncludeDirectoryCommand, cmCommand);
protected:
// used internally
- void AddDirectory(const char *arg, bool before, bool system);
+ void GetIncludes(const std::string &arg, std::vector<std::string> &incs);
+ void NormalizeInclude(std::string &inc);
};
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index ee92906..7aff731 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -36,6 +36,8 @@ public:
cmExportSet* GetExportSet() {return this->ExportSet;}
+ cmMakefile* GetMakefile() const { return this->Makefile; }
+
const std::string& GetNamespace() const { return this->Namespace; }
protected:
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 347ad3e..5f9b658 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -16,7 +16,6 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmake.h"
-#include "cmGeneratorTarget.h"
#include <assert.h>
@@ -27,8 +26,7 @@ cmInstallTargetGenerator
std::vector<std::string> const& configurations,
const char* component, bool optional):
cmInstallGenerator(dest, configurations, component), Target(&t),
- ImportLibrary(implib), FilePermissions(file_permissions),
- Optional(optional), GeneratorTarget(0)
+ ImportLibrary(implib), FilePermissions(file_permissions), Optional(optional)
{
this->ActionsPerConfig = true;
this->NamelinkMode = NamelinkModeNone;
@@ -486,17 +484,6 @@ void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os,
this->AddStripRule(os, indent, file);
}
-void cmInstallTargetGenerator::CreateGeneratorTarget()
-{
- if (!this->GeneratorTarget)
- {
- this->GeneratorTarget = this->Target->GetMakefile()
- ->GetLocalGenerator()
- ->GetGlobalGenerator()
- ->GetGeneratorTarget(this->Target);
- }
-}
-
//----------------------------------------------------------------------------
void
cmInstallTargetGenerator
@@ -520,13 +507,10 @@ cmInstallTargetGenerator
return;
}
- this->CreateGeneratorTarget();
-
// Build a map of build-tree install_name to install-tree install_name for
// shared libraries linked to this target.
std::map<cmStdString, cmStdString> install_name_remap;
- if(cmComputeLinkInformation* cli =
- this->GeneratorTarget->GetLinkInformation(config))
+ if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config))
{
std::set<cmTarget*> const& sharedLibs = cli->GetSharedLibrariesLinked();
for(std::set<cmTarget*>::const_iterator j = sharedLibs.begin();
@@ -624,12 +608,9 @@ cmInstallTargetGenerator
return;
}
- this->CreateGeneratorTarget();
-
// Get the link information for this target.
// It can provide the RPATH.
- cmComputeLinkInformation* cli =
- this->GeneratorTarget->GetLinkInformation(config);
+ cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
if(!cli)
{
return;
@@ -658,12 +639,9 @@ cmInstallTargetGenerator
return;
}
- this->CreateGeneratorTarget();
-
// Get the link information for this target.
// It can provide the RPATH.
- cmComputeLinkInformation* cli =
- this->GeneratorTarget->GetLinkInformation(config);
+ cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
if(!cli)
{
return;
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index cab3e90..8cf72f9 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -14,8 +14,7 @@
#include "cmInstallGenerator.h"
#include "cmTarget.h"
-
-class cmGeneratorTarget;
+#include "cmGeneratorTarget.h"
/** \class cmInstallTargetGenerator
* \brief Generate target installation rules.
@@ -94,8 +93,6 @@ protected:
void AddRanlibRule(std::ostream& os, Indent const& indent,
const std::string& toDestDirPath);
- void CreateGeneratorTarget();
-
cmTarget* Target;
bool ImportLibrary;
std::string FilePermissions;
diff --git a/Source/cmLinkDirectoriesCommand.h b/Source/cmLinkDirectoriesCommand.h
index 889118c..9218f44 100644
--- a/Source/cmLinkDirectoriesCommand.h
+++ b/Source/cmLinkDirectoriesCommand.h
@@ -62,10 +62,8 @@ public:
" link_directories(directory1 directory2 ...)\n"
"Specify the paths in which the linker should search for libraries. "
"The command will apply only to targets created after it is called. "
- "For historical reasons, relative paths given to this command are "
- "passed to the linker unchanged "
- "(unlike many CMake commands which interpret them relative to the "
- "current source directory).\n"
+ "Relative paths given to this command are interpreted as relative to "
+ "the current source directory, see CMP0015. \n"
"Note that this command is rarely necessary. Library locations "
"returned by find_package() and find_library() are absolute paths. "
"Pass these absolute library file paths directly to the "
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index 7848424..df64695 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -15,13 +15,14 @@
#include <stdlib.h> // required for atoi
#include <ctype.h>
+#include <assert.h>
//----------------------------------------------------------------------------
bool cmListCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
- if(args.size() < 1)
+ if(args.size() < 2)
{
- this->SetError("must be called with at least one argument.");
+ this->SetError("must be called with at least two arguments.");
return false;
}
@@ -243,11 +244,7 @@ bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args)
//----------------------------------------------------------------------------
bool cmListCommand::HandleAppendCommand(std::vector<std::string> const& args)
{
- if(args.size() < 2)
- {
- this->SetError("sub-command APPEND requires at least one argument.");
- return false;
- }
+ assert(args.size() >= 2);
// Skip if nothing to append.
if(args.size() < 3)
@@ -424,12 +421,8 @@ bool cmListCommand
bool cmListCommand
::HandleReverseCommand(std::vector<std::string> const& args)
{
- if(args.size() < 2)
- {
- this->SetError("sub-command REVERSE requires a list as an argument.");
- return false;
- }
- else if(args.size() > 2)
+ assert(args.size() >= 2);
+ if(args.size() > 2)
{
this->SetError(
"sub-command REVERSE only takes one argument.");
@@ -463,13 +456,8 @@ bool cmListCommand
bool cmListCommand
::HandleRemoveDuplicatesCommand(std::vector<std::string> const& args)
{
- if(args.size() < 2)
- {
- this->SetError(
- "sub-command REMOVE_DUPLICATES requires a list as an argument.");
- return false;
- }
- else if(args.size() > 2)
+ assert(args.size() >= 2);
+ if(args.size() > 2)
{
this->SetError(
"sub-command REMOVE_DUPLICATES only takes one argument.");
@@ -513,12 +501,8 @@ bool cmListCommand
bool cmListCommand
::HandleSortCommand(std::vector<std::string> const& args)
{
- if(args.size() < 2)
- {
- this->SetError("sub-command SORT requires a list as an argument.");
- return false;
- }
- else if(args.size() > 2)
+ assert(args.size() >= 2);
+ if(args.size() > 2)
{
this->SetError(
"sub-command SORT only takes one argument.");
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index c057754..fec3d07 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -76,4 +76,13 @@ struct cmListFile
std::vector<cmListFileFunction> Functions;
};
+struct cmValueWithOrigin {
+ cmValueWithOrigin(const std::string &value,
+ const cmListFileBacktrace &bt)
+ : Value(value), Backtrace(bt)
+ {}
+ std::string Value;
+ cmListFileBacktrace Backtrace;
+};
+
#endif
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 4952a8c..ee5b9d8 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1212,7 +1212,8 @@ cmLocalGenerator::ConvertToIncludeReference(std::string const& path)
//----------------------------------------------------------------------------
std::string cmLocalGenerator::GetIncludeFlags(
const std::vector<std::string> &includes,
- const char* lang, bool forResponseFile)
+ const char* lang, bool forResponseFile,
+ const char *config)
{
if(!lang)
{
@@ -1285,7 +1286,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
if(!flagUsed || repeatFlag)
{
if(sysIncludeFlag &&
- this->Makefile->IsSystemIncludeDirectory(i->c_str()))
+ this->Makefile->IsSystemIncludeDirectory(i->c_str(), config))
{
includeFlags << sysIncludeFlag;
}
@@ -1329,7 +1330,9 @@ std::string cmLocalGenerator::GetIncludeFlags(
void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
cmGeneratorTarget* target,
const char* lang,
- const char *config)
+ const char *config,
+ bool stripImplicitInclDirs
+ )
{
// Need to decide whether to automatically include the source and
// binary directories at the beginning of the include path.
@@ -1404,6 +1407,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
return;
}
+ std::vector<std::string> implicitDirs;
// Load implicit include directories for this language.
std::string impDirVar = "CMAKE_";
impDirVar += lang;
@@ -1416,6 +1420,10 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
i != impDirVec.end(); ++i)
{
emitted.insert(*i);
+ if (!stripImplicitInclDirs)
+ {
+ implicitDirs.push_back(*i);
+ }
}
}
@@ -1457,6 +1465,15 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
dirs.push_back(*i);
}
}
+
+ for(std::vector<std::string>::const_iterator i = implicitDirs.begin();
+ i != implicitDirs.end(); ++i)
+ {
+ if(std::find(includes.begin(), includes.end(), *i) != includes.end())
+ {
+ dirs.push_back(*i);
+ }
+ }
}
void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
@@ -1671,7 +1688,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
{
cmOStringStream fout;
const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
- cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config);
+ cmComputeLinkInformation* pcli = tgt.Target->GetLinkInformation(config);
if(!pcli)
{
return;
@@ -1703,7 +1720,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
fdi != fwDirs.end(); ++fdi)
{
- frameworkPath = " -F";
+ frameworkPath += "-F";
frameworkPath += this->Convert(fdi->c_str(), NONE, SHELL, false);
frameworkPath += " ";
}
@@ -1875,6 +1892,14 @@ bool cmLocalGenerator::GetRealDependency(const char* inName,
// modify the name so stripping down to just the file name should
// produce the target name in this case.
std::string name = cmSystemTools::GetFilenameName(inName);
+
+ // If the input name is the empty string, there is no real
+ // dependency. Short-circuit the other checks:
+ if(name == "")
+ {
+ return false;
+ }
+
if(cmSystemTools::GetFilenameLastExtension(name) == ".exe")
{
name = cmSystemTools::GetFilenameWithoutLastExtension(name);
@@ -1971,7 +1996,8 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
//----------------------------------------------------------------------------
void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target,
- std::string const& lang)
+ std::string const& lang,
+ const char *config)
{
int targetType = target->GetType();
@@ -1984,8 +2010,18 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags, cmTarget* target,
}
else
{
- // Add position independendent flags, if needed.
- if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE"))
+ if (target->GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ if (target->GetPropertyAsBool("POSITION_INDEPENDENT_CODE"))
+ {
+ this->AddPositionIndependentFlags(flags, lang, targetType);
+ }
+ return;
+ }
+
+ if (target->GetLinkInterfaceDependentBoolProperty(
+ "POSITION_INDEPENDENT_CODE",
+ config))
{
this->AddPositionIndependentFlags(flags, lang, targetType);
}
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index bd58218..a1c34f0 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -49,29 +49,29 @@ public:
/**
* Calls TraceVSDependencies() on all targets of this generator.
*/
- virtual void TraceDependencies();
+ void TraceDependencies();
virtual void AddHelperCommands() {}
/**
* Perform any final calculations prior to generation
*/
- virtual void ConfigureFinalPass();
+ void ConfigureFinalPass();
/**
* Generate the install rules files in this directory.
*/
- virtual void GenerateInstallRules();
+ void GenerateInstallRules();
/**
* Generate the test files for tests.
*/
- virtual void GenerateTestFiles();
+ void GenerateTestFiles();
/**
* Generate a manifest of target files that will be built.
*/
- virtual void GenerateTargetManifest();
+ void GenerateTargetManifest();
///! Get the makefile for this generator
cmMakefile *GetMakefile() {
@@ -142,14 +142,15 @@ public:
void AddLanguageFlags(std::string& flags, const char* lang,
const char* config);
void AddCMP0018Flags(std::string &flags, cmTarget* target,
- std::string const& lang);
+ std::string const& lang, const char *config);
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);
///! Get the include flags for the current makefile and language
std::string GetIncludeFlags(const std::vector<std::string> &includes,
- const char* lang, bool forResponseFile = false);
+ const char* lang, bool forResponseFile = false,
+ const char *config = 0);
/**
* Encode a list of preprocessor definitions for the compiler
@@ -212,7 +213,8 @@ public:
/** Get the include flags for the current makefile and language. */
void GetIncludeDirectories(std::vector<std::string>& dirs,
cmGeneratorTarget* target,
- const char* lang = "C", const char *config = 0);
+ const char* lang = "C", const char *config = 0,
+ bool stripImplicitInclDirs = true);
/** Compute the language used to compile the given source file. */
const char* GetSourceFileLanguage(const cmSourceFile& source);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index db93529..0f680f6 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -32,7 +32,6 @@
#include <cmsys/auto_ptr.hxx>
-#include <memory> // auto_ptr
#include <queue>
//----------------------------------------------------------------------------
@@ -1939,8 +1938,12 @@ void cmLocalUnixMakefileGenerator3
for(ImplicitDependFileMap::const_iterator pi = implicitPairs.begin();
pi != implicitPairs.end(); ++pi)
{
- cmakefileStream << " \"" << pi->second << "\" ";
- cmakefileStream << "\"" << pi->first << "\"\n";
+ for(cmDepends::DependencyVector::const_iterator di = pi->second.begin();
+ di != pi->second.end(); ++ di)
+ {
+ cmakefileStream << " \"" << *di << "\" ";
+ cmakefileStream << "\"" << pi->first << "\"\n";
+ }
}
cmakefileStream << " )\n";
@@ -1958,34 +1961,16 @@ void cmLocalUnixMakefileGenerator3
}
// Build a list of preprocessor definitions for the target.
- std::vector<std::string> defines;
- {
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName += cmSystemTools::UpperCase(this->ConfigurationName);
- if(const char* ddefs = this->Makefile->GetProperty("COMPILE_DEFINITIONS"))
- {
- cmSystemTools::ExpandListArgument(ddefs, defines);
- }
- if(const char* cdefs = target.GetProperty("COMPILE_DEFINITIONS"))
- {
- cmSystemTools::ExpandListArgument(cdefs, defines);
- }
- if(const char* dcdefs = this->Makefile->GetProperty(defPropName.c_str()))
- {
- cmSystemTools::ExpandListArgument(dcdefs, defines);
- }
- if(const char* ccdefs = target.GetProperty(defPropName.c_str()))
- {
- cmSystemTools::ExpandListArgument(ccdefs, defines);
- }
- }
+ std::set<std::string> defines;
+ this->AppendDefines(defines, target.GetCompileDefinitions(
+ this->ConfigurationName.c_str()));
if(!defines.empty())
{
cmakefileStream
<< "\n"
<< "# Preprocessor definitions for this target.\n"
<< "SET(CMAKE_TARGET_DEFINITIONS\n";
- for(std::vector<std::string>::const_iterator di = defines.begin();
+ for(std::set<std::string>::const_iterator di = defines.begin();
di != defines.end(); ++di)
{
cmakefileStream
@@ -2204,7 +2189,7 @@ cmLocalUnixMakefileGenerator3::AddImplicitDepends(cmTarget const& tgt,
const char* obj,
const char* src)
{
- this->ImplicitDepends[tgt.GetName()][lang][obj] = src;
+ this->ImplicitDepends[tgt.GetName()][lang][obj].push_back(src);
}
//----------------------------------------------------------------------------
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index e374959..703369e 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -209,7 +209,8 @@ public:
// File pairs for implicit dependency scanning. The key of the map
// is the depender and the value is the explicit dependee.
- struct ImplicitDependFileMap: public std::map<cmStdString, cmStdString> {};
+ struct ImplicitDependFileMap:
+ public std::map<cmStdString, cmDepends::DependencyVector> {};
struct ImplicitDependLanguageMap:
public std::map<cmStdString, ImplicitDependFileMap> {};
struct ImplicitDependTargetMap:
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index f15322b..dc94476 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -325,19 +325,22 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
if(!cmSystemTools::FileExists(source.c_str()))
{
cmSystemTools::ReplaceString(source, "$(IntDir)/", "");
+ // Make sure the path exists for the file
+ std::string path = cmSystemTools::GetFilenamePath(source);
+ cmSystemTools::MakeDirectory(path.c_str());
#if defined(_WIN32) || defined(__CYGWIN__)
- std::ofstream fout(source.c_str(),
+ std::ofstream sourceFout(source.c_str(),
std::ios::binary | std::ios::out
| std::ios::trunc);
#else
- std::ofstream fout(source.c_str(),
+ std::ofstream sourceFout(source.c_str(),
std::ios::out | std::ios::trunc);
#endif
- if(fout)
+ if(sourceFout)
{
- fout.write("# generated from CMake",22);
- fout.flush();
- fout.close();
+ sourceFout.write("# generated from CMake",22);
+ sourceFout.flush();
+ sourceFout.close();
}
}
}
@@ -710,6 +713,8 @@ void cmLocalVisualStudio6Generator::SetBuildType(BuildType b,
switch(b)
{
+ case WIN32_EXECUTABLE:
+ break;
case STATIC_LIBRARY:
this->DSPHeaderTemplate = root;
this->DSPHeaderTemplate += "/staticLibHeader.dsptemplate";
@@ -1695,25 +1700,21 @@ void cmLocalVisualStudio6Generator
std::set<std::string> minsizeDefinesSet;
std::set<std::string> debugrelDefinesSet;
-
- cmGeneratorTarget* gt =
- this->GlobalGenerator->GetGeneratorTarget(&target);
-
this->AppendDefines(
definesSet,
- gt->GetCompileDefinitions());
+ target.GetCompileDefinitions(0));
this->AppendDefines(
debugDefinesSet,
- gt->GetCompileDefinitions("DEBUG"));
+ target.GetCompileDefinitions("DEBUG"));
this->AppendDefines(
releaseDefinesSet,
- gt->GetCompileDefinitions("RELEASE"));
+ target.GetCompileDefinitions("RELEASE"));
this->AppendDefines(
minsizeDefinesSet,
- gt->GetCompileDefinitions("MINSIZEREL"));
+ target.GetCompileDefinitions("MINSIZEREL"));
this->AppendDefines(
debugrelDefinesSet,
- gt->GetCompileDefinitions("RELWITHDEBINFO"));
+ target.GetCompileDefinitions("RELWITHDEBINFO"));
std::string defines = " ";
std::string debugDefines = " ";
@@ -1783,10 +1784,8 @@ void cmLocalVisualStudio6Generator
const std::string extraOptions,
std::string& options)
{
- cmGeneratorTarget* gt =
- this->GlobalGenerator->GetGeneratorTarget(&target);
// Compute the link information for this configuration.
- cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName);
+ cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
if(!pcli)
{
return;
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index f9a2d32..7d0bc67 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -229,6 +229,9 @@ void cmLocalVisualStudio7Generator
this->FortranProject =
static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
->TargetIsFortranOnly(target);
+ this->WindowsCEProject =
+ static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
+ ->TargetsWindowsCE();
// Intel Fortran for VS10 uses VS9 format ".vfproj" files.
VSVersion realVersion = this->Version;
@@ -742,8 +745,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
targetOptions.ParseFinish();
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
- targetOptions.AddDefines(gt->GetCompileDefinitions().c_str());
- targetOptions.AddDefines(gt->GetCompileDefinitions(configName).c_str());
+ targetOptions.AddDefines(target.GetCompileDefinitions(configName).c_str());
targetOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -914,12 +916,12 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
// for FAT32 file systems, which can cause an empty manifest
// to be embedded into the resulting executable. See CMake
// bug #2617.
- const char* tool = "VCManifestTool";
+ const char* manifestTool = "VCManifestTool";
if(this->FortranProject)
{
- tool = "VFManifestTool";
+ manifestTool = "VFManifestTool";
}
- fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n"
+ fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << manifestTool << "\"\n"
<< "\t\t\t\tUseFAT32Workaround=\"true\"\n"
<< "\t\t\t/>\n";
}
@@ -1003,6 +1005,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
}
switch(target.GetType())
{
+ case cmTarget::UNKNOWN_LIBRARY:
+ break;
case cmTarget::OBJECT_LIBRARY:
{
std::string libpath = this->GetTargetDirectory(target);
@@ -1074,9 +1078,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
targetNameImport, targetNamePDB, configName);
// Compute the link library and directory information.
- cmGeneratorTarget* gt =
- this->GlobalGenerator->GetGeneratorTarget(&target);
- cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName);
+ cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
if(!pcli)
{
return;
@@ -1131,6 +1133,17 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
{
fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
}
+ if(this->WindowsCEProject)
+ {
+ if(this->GetVersion() < VS9)
+ {
+ fout << "\t\t\t\tSubSystem=\"9\"\n";
+ }
+ else
+ {
+ fout << "\t\t\t\tSubSystem=\"8\"\n";
+ }
+ }
std::string stackVar = "CMAKE_";
stackVar += linkLanguage;
stackVar += "_STACK_SIZE";
@@ -1161,9 +1174,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
targetNameImport, targetNamePDB, configName);
// Compute the link library and directory information.
- cmGeneratorTarget* gt =
- this->GlobalGenerator->GetGeneratorTarget(&target);
- cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName);
+ cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
if(!pcli)
{
return;
@@ -1171,6 +1182,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
cmComputeLinkInformation& cli = *pcli;
const char* linkLanguage = cli.GetLinkLanguage();
+ bool isWin32Executable = target.GetPropertyAsBool("WIN32_EXECUTABLE");
+
// Compute the variable name to lookup standard libraries for this
// language.
std::string standardLibsVar = "CMAKE_";
@@ -1218,15 +1231,31 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
{
fout << "\t\t\t\tGenerateDebugInformation=\"TRUE\"\n";
}
- if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") )
+ if ( this->WindowsCEProject )
+ {
+ if(this->GetVersion() < VS9)
+ {
+ fout << "\t\t\t\tSubSystem=\"9\"\n";
+ }
+ else
+ {
+ fout << "\t\t\t\tSubSystem=\"8\"\n";
+ }
+ fout << "\t\t\t\tEntryPointSymbol=\""
+ << (isWin32Executable ? "WinMainCRTStartup" : "mainACRTStartup")
+ << "\"\n";
+ }
+ else if ( this->FortranProject )
{
fout << "\t\t\t\tSubSystem=\""
- << (this->FortranProject? "subSystemWindows" : "2") << "\"\n";
+ << (isWin32Executable ? "subSystemWindows" : "subSystemConsole")
+ << "\"\n";
}
else
{
fout << "\t\t\t\tSubSystem=\""
- << (this->FortranProject? "subSystemConsole" : "1") << "\"\n";
+ << (isWin32Executable ? "2" : "1")
+ << "\"\n";
}
std::string stackVar = "CMAKE_";
stackVar += linkLanguage;
@@ -1591,17 +1620,30 @@ cmLocalVisualStudio7Generator
return dir_max;
}
-void cmLocalVisualStudio7Generator
+bool cmLocalVisualStudio7Generator
::WriteGroup(const cmSourceGroup *sg, cmTarget& target,
std::ostream &fout, const char *libName,
std::vector<std::string> *configs)
{
const std::vector<const cmSourceFile *> &sourceFiles =
sg->GetSourceFiles();
+ std::vector<cmSourceGroup> const& children = sg->GetGroupChildren();
+
+ // Write the children to temporary output.
+ bool hasChildrenWithSources = false;
+ cmOStringStream tmpOut;
+ for(unsigned int i=0;i<children.size();++i)
+ {
+ if(this->WriteGroup(&children[i], target, tmpOut, libName, configs))
+ {
+ hasChildrenWithSources = true;
+ }
+ }
+
// If the group is empty, don't write it at all.
- if(sourceFiles.empty() && sg->GetGroupChildren().empty())
+ if(sourceFiles.empty() && !hasChildrenWithSources)
{
- return;
+ return false;
}
// If the group has a name, write the header.
@@ -1722,11 +1764,10 @@ void cmLocalVisualStudio7Generator
}
}
- std::vector<cmSourceGroup> const& children = sg->GetGroupChildren();
-
- for(unsigned int i=0;i<children.size();++i)
+ // If the group has children with source files, write the children.
+ if(hasChildrenWithSources)
{
- this->WriteGroup(&children[i], target, fout, libName, configs);
+ fout << tmpOut.str();
}
// If the group has a name, write the footer.
@@ -1734,6 +1775,8 @@ void cmLocalVisualStudio7Generator
{
this->WriteVCProjEndGroup(fout);
}
+
+ return true;
}
void cmLocalVisualStudio7Generator::
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 95db2cc..d9e2ef0 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -109,7 +109,7 @@ private:
FCInfo& fcinfo);
void WriteTargetVersionAttribute(std::ostream& fout, cmTarget& target);
- void WriteGroup(const cmSourceGroup *sg,
+ bool WriteGroup(const cmSourceGroup *sg,
cmTarget& target, std::ostream &fout,
const char *libName, std::vector<std::string> *configs);
@@ -122,6 +122,7 @@ private:
cmVS7FlagTable const* ExtraFlagTable;
std::string ModuleDefinitionFile;
bool FortranProject;
+ bool WindowsCEProject;
std::string PlatformName; // Win32 or x64
cmLocalVisualStudio7GeneratorInternals* Internal;
};
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 4bcf4de..ef2bb1d 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -84,7 +84,6 @@ cmLocalVisualStudioGenerator
const char* newline_text)
{
bool useLocal = this->CustomCommandUseLocal();
- const cmCustomCommandLines& commandLines = cc.GetCommandLines();
const char* workingDirectory = cc.GetWorkingDirectory();
cmCustomCommandGenerator ccg(cc, configName, this->Makefile);
RelativeRoot relativeRoot = workingDirectory? NONE : START_OUTPUT;
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index 9968592..1a3499a 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -38,7 +38,8 @@ public:
VS8 = 80,
VS9 = 90,
VS10 = 100,
- VS11 = 110
+ VS11 = 110,
+ VS12 = 120
};
cmLocalVisualStudioGenerator(VSVersion v);
diff --git a/Source/cmMacroCommand.h b/Source/cmMacroCommand.h
index f8c40c0..aedbb4d 100644
--- a/Source/cmMacroCommand.h
+++ b/Source/cmMacroCommand.h
@@ -92,12 +92,12 @@ public:
"facilitates creating macros with optional arguments. Additionally "
"${ARGV} holds the list of all arguments given to the macro and "
"${ARGN} "
- "holds the list of argument past the last expected argument. "
+ "holds the list of arguments past the last expected argument. "
"Note that the parameters to a macro and values such as ARGN "
"are not variables in the usual CMake sense. They are string "
- "replacements much like the c preprocessor would do with a "
- "macro. If you want true CMake variables you should look at "
- "the function command."
+ "replacements much like the C preprocessor would do with a macro. "
+ "If you want true CMake variables and/or better CMake scope control "
+ "you should look at the function command."
"\n"
"See the cmake_policy() command documentation for the behavior of "
"policies inside macros."
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index f067da4..47a6d2e 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -23,6 +23,7 @@
#include "cmListFileCache.h"
#include "cmCommandArgumentParserHelper.h"
#include "cmDocumentCompileDefinitions.h"
+#include "cmGeneratorExpression.h"
#include "cmTest.h"
#ifdef CMAKE_BUILD_WITH_CMAKE
# include "cmVariableWatch.h"
@@ -99,6 +100,7 @@ cmMakefile::cmMakefile(): Internal(new Internals)
this->AddDefaultDefinitions();
this->Initialize();
this->PreOrder = false;
+ this->GeneratingBuildSystem = false;
}
cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
@@ -814,7 +816,7 @@ bool cmMakefile::NeedBackwardsCompatibility(unsigned int major,
void cmMakefile::FinalPass()
{
// do all the variable expansions here
- this->ExpandVariables();
+ this->ExpandVariablesCMP0019();
// give all the commands a chance to do something
// after the file has been parsed before generation
@@ -1485,9 +1487,12 @@ void cmMakefile::InitializeFromParent()
// Initialize definitions with the closure of the parent scope.
this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure();
- // copy include paths
- this->SetProperty("INCLUDE_DIRECTORIES",
- parent->GetProperty("INCLUDE_DIRECTORIES"));
+ const std::vector<cmValueWithOrigin> parentIncludes =
+ parent->GetIncludeDirectoriesEntries();
+ this->IncludeDirectoriesEntries.insert(this->IncludeDirectoriesEntries.end(),
+ parentIncludes.begin(),
+ parentIncludes.end());
+
this->SystemIncludeDirectories = parent->SystemIncludeDirectories;
// define flags
@@ -1613,74 +1618,72 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath,
}
//----------------------------------------------------------------------------
-void AddStringToProperty(cmProperty *prop, const char* name, const char* s,
- bool before)
+void cmMakefile::AddIncludeDirectories(const std::vector<std::string> &incs,
+ bool before)
{
- if (!prop)
+ if (incs.empty())
{
return;
}
- // Don't worry about duplicates at this point. We eliminate them when
- // we convert the property to a vector in GetIncludeDirectories.
-
- if (before)
- {
- const char *val = prop->GetValue();
- cmOStringStream oss;
-
- if(val && *val)
- {
- oss << s << ";" << val;
- }
- else
- {
- oss << s;
- }
+ std::string incString;
+ std::string sep;
- std::string newVal = oss.str();
- prop->Set(name, newVal.c_str());
- }
- else
+ for(std::vector<std::string>::const_iterator li = incs.begin();
+ li != incs.end(); ++li)
{
- prop->Append(name, s);
+ incString += sep + *li;
+ sep = ";";
}
-}
-//----------------------------------------------------------------------------
-void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
-{
- if (!inc)
- {
- return;
- }
+ std::vector<cmValueWithOrigin>::iterator position =
+ before ? this->IncludeDirectoriesEntries.begin()
+ : this->IncludeDirectoriesEntries.end();
- // Directory property:
- cmProperty *prop =
- this->GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES");
- AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before);
+ cmListFileBacktrace lfbt;
+ this->GetBacktrace(lfbt);
+ cmValueWithOrigin entry(incString, lfbt);
+ this->IncludeDirectoriesEntries.insert(position, entry);
// Property on each target:
for (cmTargets::iterator l = this->Targets.begin();
l != this->Targets.end(); ++l)
{
cmTarget &t = l->second;
- prop = t.GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES");
- AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before);
+ t.InsertInclude(entry, before);
}
}
//----------------------------------------------------------------------------
-void cmMakefile::AddSystemIncludeDirectory(const char* dir)
+void
+cmMakefile::AddSystemIncludeDirectories(const std::set<cmStdString> &incs)
{
- this->SystemIncludeDirectories.insert(dir);
+ for(std::set<cmStdString>::const_iterator li = incs.begin();
+ li != incs.end(); ++li)
+ {
+ this->SystemIncludeDirectories.insert(*li);
+ }
}
//----------------------------------------------------------------------------
-bool cmMakefile::IsSystemIncludeDirectory(const char* dir)
+bool cmMakefile::IsSystemIncludeDirectory(const char* dir, const char *config)
{
- return (this->SystemIncludeDirectories.find(dir) !=
- this->SystemIncludeDirectories.end());
+ for (std::set<cmStdString>::const_iterator
+ it = this->SystemIncludeDirectories.begin();
+ it != this->SystemIncludeDirectories.end(); ++it)
+ {
+ 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;
+ }
+ }
+ return false;
}
void cmMakefile::AddDefinition(const char* name, const char* value)
@@ -2122,21 +2125,33 @@ void cmMakefile::AddExtraDirectory(const char* dir)
this->AuxSourceDirectories.push_back(dir);
}
+static bool mightExpandVariablesCMP0019(const char* s)
+{
+ return s && *s && strstr(s,"${") && strchr(s,'}');
+}
-// expand CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the
-// include and library directories.
-
-void cmMakefile::ExpandVariables()
+void cmMakefile::ExpandVariablesCMP0019()
{
- // Now expand variables in the include and link strings
+ // Drop this ancient compatibility behavior with a policy.
+ cmPolicies::PolicyStatus pol = this->GetPolicyStatus(cmPolicies::CMP0019);
+ if(pol != cmPolicies::OLD && pol != cmPolicies::WARN)
+ {
+ return;
+ }
+ cmOStringStream w;
- // May not be necessary anymore... But may need a policy for strict
- // backwards compatibility
const char *includeDirs = this->GetProperty("INCLUDE_DIRECTORIES");
- if (includeDirs)
+ if(mightExpandVariablesCMP0019(includeDirs))
{
std::string dirs = includeDirs;
this->ExpandVariablesInString(dirs, true, true);
+ if(pol == cmPolicies::WARN && dirs != includeDirs)
+ {
+ w << "Evaluated directory INCLUDE_DIRECTORIES\n"
+ << " " << includeDirs << "\n"
+ << "as\n"
+ << " " << dirs << "\n";
+ }
this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
}
@@ -2146,10 +2161,17 @@ void cmMakefile::ExpandVariables()
{
cmTarget &t = l->second;
includeDirs = t.GetProperty("INCLUDE_DIRECTORIES");
- if (includeDirs)
+ if(mightExpandVariablesCMP0019(includeDirs))
{
std::string dirs = includeDirs;
this->ExpandVariablesInString(dirs, true, true);
+ if(pol == cmPolicies::WARN && dirs != includeDirs)
+ {
+ w << "Evaluated target " << t.GetName() << " INCLUDE_DIRECTORIES\n"
+ << " " << includeDirs << "\n"
+ << "as\n"
+ << " " << dirs << "\n";
+ }
t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
}
}
@@ -2157,13 +2179,45 @@ void cmMakefile::ExpandVariables()
for(std::vector<std::string>::iterator d = this->LinkDirectories.begin();
d != this->LinkDirectories.end(); ++d)
{
- this->ExpandVariablesInString(*d, true, true);
+ if(mightExpandVariablesCMP0019(d->c_str()))
+ {
+ std::string orig = *d;
+ this->ExpandVariablesInString(*d, true, true);
+ if(pol == cmPolicies::WARN && *d != orig)
+ {
+ w << "Evaluated link directory\n"
+ << " " << orig << "\n"
+ << "as\n"
+ << " " << *d << "\n";
+ }
+ }
}
for(cmTarget::LinkLibraryVectorType::iterator l =
this->LinkLibraries.begin();
l != this->LinkLibraries.end(); ++l)
{
- this->ExpandVariablesInString(l->first, true, true);
+ if(mightExpandVariablesCMP0019(l->first.c_str()))
+ {
+ std::string orig = l->first;
+ this->ExpandVariablesInString(l->first, true, true);
+ if(pol == cmPolicies::WARN && l->first != orig)
+ {
+ w << "Evaluated link library\n"
+ << " " << orig << "\n"
+ << "as\n"
+ << " " << l->first << "\n";
+ }
+ }
+ }
+
+ if(!w.str().empty())
+ {
+ cmOStringStream m;
+ m << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0019)
+ << "\n"
+ << "The following variable evaluations were encountered:\n"
+ << w.str();
+ this->IssueMessage(cmake::AUTHOR_WARNING, m.str());
}
}
@@ -2221,7 +2275,7 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName)
{
return true;
}
- // If we are doing an in-source build, than the test will always fail
+ // If we are doing an in-source build, then the test will always fail
if ( cmSystemTools::SameFile(this->GetHomeDirectory(),
this->GetHomeOutputDirectory()) )
{
@@ -2232,8 +2286,8 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName)
return true;
}
- // Check if this is subdirectory of the source tree but not a
- // subdirectory of a build tree
+ // Check if this is a subdirectory of the source tree but not a
+ // subdirectory of the build tree
if ( cmSystemTools::IsSubDirectory(fileName,
this->GetHomeDirectory()) &&
!cmSystemTools::IsSubDirectory(fileName,
@@ -2951,6 +3005,7 @@ int cmMakefile::TryCompile(const char *srcdir, const char *bindir,
cm.SetStartDirectory(srcdir);
cm.SetStartOutputDirectory(bindir);
cm.SetCMakeCommand(cmakeCommand.c_str());
+ cm.SetGeneratorToolset(this->GetCMakeInstance()->GetGeneratorToolset());
cm.LoadCache();
if(!gg->IsMultiConfig())
{
@@ -3400,6 +3455,19 @@ void cmMakefile::SetProperty(const char* prop, const char* value)
this->SetLinkDirectories(varArgsExpanded);
return;
}
+ if (propname == "INCLUDE_DIRECTORIES")
+ {
+ this->IncludeDirectoriesEntries.clear();
+ if (!value)
+ {
+ return;
+ }
+ cmListFileBacktrace lfbt;
+ this->GetBacktrace(lfbt);
+ this->IncludeDirectoriesEntries.push_back(
+ cmValueWithOrigin(value, lfbt));
+ return;
+ }
if ( propname == "INCLUDE_REGULAR_EXPRESSION" )
{
@@ -3431,6 +3499,14 @@ void cmMakefile::AppendProperty(const char* prop, const char* value,
// handle special props
std::string propname = prop;
+ if (propname == "INCLUDE_DIRECTORIES")
+ {
+ cmListFileBacktrace lfbt;
+ this->GetBacktrace(lfbt);
+ this->IncludeDirectoriesEntries.push_back(
+ cmValueWithOrigin(value, lfbt));
+ return;
+ }
if ( propname == "LINK_DIRECTORIES" )
{
std::vector<std::string> varArgsExpanded;
@@ -3542,6 +3618,20 @@ const char *cmMakefile::GetProperty(const char* prop,
output = str.str();
return output.c_str();
}
+ else if (!strcmp("INCLUDE_DIRECTORIES",prop))
+ {
+ std::string sep;
+ for (std::vector<cmValueWithOrigin>::const_iterator
+ it = this->IncludeDirectoriesEntries.begin(),
+ end = this->IncludeDirectoriesEntries.end();
+ it != end; ++it)
+ {
+ output += sep;
+ output += it->Value;
+ sep = ";";
+ }
+ return output.c_str();
+ }
bool chain = false;
const char *retVal =
@@ -3937,6 +4027,46 @@ void cmMakefile::DefineProperties(cmake *cm)
"See the global property of the same name for details. "
"This overrides the global property for a directory.",
true);
+
+ cm->DefineProperty
+ ("VS_GLOBAL_SECTION_PRE_<section>", cmProperty::DIRECTORY,
+ "Specify a preSolution global section in Visual Studio.",
+ "Setting a property like this generates an entry of the following form "
+ "in the solution file:\n"
+ " GlobalSection(<section>) = preSolution\n"
+ " <contents based on property value>\n"
+ " EndGlobalSection\n"
+ "The property must be set to a semicolon-separated list of key=value "
+ "pairs. Each such pair will be transformed into an entry in the solution "
+ "global section. Whitespace around key and value is ignored. List "
+ "elements which do not contain an equal sign are skipped."
+ "\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.");
+ cm->DefineProperty
+ ("VS_GLOBAL_SECTION_POST_<section>", cmProperty::DIRECTORY,
+ "Specify a postSolution global section in Visual Studio.",
+ "Setting a property like this generates an entry of the following form "
+ "in the solution file:\n"
+ " GlobalSection(<section>) = postSolution\n"
+ " <contents based on property value>\n"
+ " EndGlobalSection\n"
+ "The property must be set to a semicolon-separated list of key=value "
+ "pairs. Each such pair will be transformed into an entry in the solution "
+ "global section. Whitespace around key and value is ignored. List "
+ "elements which do not contain an equal sign are skipped."
+ "\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."
+ "\n"
+ "Note that CMake generates postSolution sections ExtensibilityGlobals "
+ "and ExtensibilityAddIns by default. If you set the corresponding "
+ "property, it will override the default section. For example, setting "
+ "VS_GLOBAL_SECTION_POST_ExtensibilityGlobals will override the default "
+ "contents of the ExtensibilityGlobals section, while keeping "
+ "ExtensibilityAddIns on its default.");
}
//----------------------------------------------------------------------------
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 70cfe54..74a731d 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -286,7 +286,8 @@ public:
/**
* Add an include directory to the build.
*/
- void AddIncludeDirectory(const char*, bool before = false);
+ void AddIncludeDirectories(const std::vector<std::string> &incs,
+ bool before = false);
/**
* Add a variable definition to the build. This variable
@@ -544,8 +545,8 @@ public:
/**
* Mark include directories as system directories.
*/
- void AddSystemIncludeDirectory(const char* dir);
- bool IsSystemIncludeDirectory(const char* dir);
+ void AddSystemIncludeDirectories(const std::set<cmStdString> &incs);
+ bool IsSystemIncludeDirectory(const char* dir, const char *config);
/** Expand out any arguements in the vector that have ; separated
* strings into multiple arguements. A new vector is created
@@ -693,7 +694,7 @@ public:
/**
* Expand variables in the makefiles ivars such as link directories etc
*/
- void ExpandVariables();
+ void ExpandVariablesCMP0019();
/**
* Replace variables and #cmakedefine lines in the given string.
@@ -861,6 +862,14 @@ public:
/** Set whether or not to report a CMP0000 violation. */
void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; }
+ std::vector<cmValueWithOrigin> GetIncludeDirectoriesEntries() const
+ {
+ return this->IncludeDirectoriesEntries;
+ }
+
+ bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; }
+ void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; }
+
protected:
// add link libraries and directories to the target
void AddGlobalLinkInformation(const char* name, cmTarget& target);
@@ -909,6 +918,8 @@ protected:
std::vector<std::string> HeaderFileExtensions;
std::string DefineFlags;
+ std::vector<cmValueWithOrigin> IncludeDirectoriesEntries;
+
// Track the value of the computed DEFINITIONS property.
void AddDefineFlag(const char*, std::string&);
void RemoveDefineFlag(const char*, std::string::size_type, std::string&);
@@ -1008,6 +1019,9 @@ private:
// Enforce rules about CMakeLists.txt files.
void EnforceDirectoryLevelRules();
+
+ bool GeneratingBuildSystem;
+
};
//----------------------------------------------------------------------------
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index e7004d6..5b4e4d7 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -19,8 +19,6 @@
#include "cmTarget.h"
#include "cmake.h"
-#include <memory> // auto_ptr
-
//----------------------------------------------------------------------------
cmMakefileLibraryTargetGenerator
::cmMakefileLibraryTargetGenerator(cmTarget* target):
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 3d02d6a..4220ae1 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -268,7 +268,8 @@ std::string cmMakefileTargetGenerator::GetFlags(const std::string &l)
this->AddFortranFlags(flags);
}
- this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang);
+ this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
+ lang, this->ConfigName);
// Add include directory flags.
this->AddIncludeFlags(flags, lang);
@@ -302,10 +303,7 @@ std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
// Add preprocessor definitions for this target and configuration.
this->LocalGenerator->AppendDefines
- (defines, this->GeneratorTarget->GetCompileDefinitions());
-
- this->LocalGenerator->AppendDefines
- (defines, this->GeneratorTarget->GetCompileDefinitions(
+ (defines, this->Target->GetCompileDefinitions(
this->LocalGenerator->ConfigurationName.c_str()));
std::string definesString;
@@ -639,18 +637,25 @@ cmMakefileTargetGenerator
(commands, buildEcho.c_str(), cmLocalUnixMakefileGenerator3::EchoBuild);
}
+ std::string targetOutPathReal;
std::string targetOutPathPDB;
{
+ std::string targetFullPathReal;
std::string targetFullPathPDB;
if(this->Target->GetType() == cmTarget::EXECUTABLE ||
this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
this->Target->GetType() == cmTarget::MODULE_LIBRARY)
{
+ targetFullPathReal =
+ this->Target->GetFullPath(this->ConfigName, false, true);
targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName);
targetFullPathPDB += "/";
targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
}
+ targetOutPathReal = this->Convert(targetFullPathReal.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::SHELL);
targetOutPathPDB =
this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
cmLocalGenerator::SHELL);
@@ -659,6 +664,7 @@ cmMakefileTargetGenerator
vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
vars.CMTarget = this->Target;
vars.Language = lang;
+ vars.Target = targetOutPathReal.c_str();
vars.TargetPDB = targetOutPathPDB.c_str();
vars.Source = sourceFile.c_str();
std::string shellObj =
@@ -1017,8 +1023,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
std::set<cmTarget const*> emitted;
const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
- if(cmComputeLinkInformation* cli =
- this->GeneratorTarget->GetLinkInformation(cfg))
+ if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
{
cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
for(cmComputeLinkInformation::ItemVector::const_iterator
@@ -1551,10 +1556,10 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags()
this->LocalGenerator->GetIncludeDirectories(includes,
this->GeneratorTarget,
"C", config);
- std::vector<std::string>::iterator i;
// check all include directories for frameworks as this
// will already have added a -F for the framework
- for(i = includes.begin(); i != includes.end(); ++i)
+ for(std::vector<std::string>::iterator i = includes.begin();
+ i != includes.end(); ++i)
{
if(this->Target->NameResolvesToFramework(i->c_str()))
{
@@ -1566,17 +1571,21 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags()
}
std::string flags;
- std::vector<std::string>& frameworks = this->Target->GetFrameworks();
- for(i = frameworks.begin();
- i != frameworks.end(); ++i)
+ const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
+ if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
{
- if(emitted.insert(*i).second)
+ std::vector<std::string> const& frameworks = cli->GetFrameworkPaths();
+ for(std::vector<std::string>::const_iterator i = frameworks.begin();
+ i != frameworks.end(); ++i)
{
- flags += "-F";
- flags += this->Convert(i->c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::SHELL, true);
- flags += " ";
+ if(emitted.insert(*i).second)
+ {
+ flags += "-F";
+ flags += this->Convert(i->c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::SHELL, true);
+ flags += " ";
+ }
}
}
return flags;
@@ -1594,8 +1603,7 @@ void cmMakefileTargetGenerator
// Loop over all library dependencies.
const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
- if(cmComputeLinkInformation* cli =
- this->GeneratorTarget->GetLinkInformation(cfg))
+ if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
{
std::vector<std::string> const& libDeps = cli->GetDepends();
for(std::vector<std::string>::const_iterator j = libDeps.begin();
diff --git a/Source/cmMathCommand.h b/Source/cmMathCommand.h
index 27c5b6a..dc0ceb3 100644
--- a/Source/cmMathCommand.h
+++ b/Source/cmMathCommand.h
@@ -58,11 +58,11 @@ public:
{
return
" math(EXPR <output variable> <math expression>)\n"
- "EXPR evaluates mathematical expression and return result in the "
+ "EXPR evaluates mathematical expression and returns result in the "
"output variable. Example mathematical expression is "
"'5 * ( 10 + 13 )'. Supported operators are "
"+ - * / % | & ^ ~ << >> * / %. They have the same meaning "
- " as they do in c code.";
+ " as they do in C code.";
}
cmTypeMacro(cmMathCommand, cmCommand);
diff --git a/Source/cmMessageCommand.h b/Source/cmMessageCommand.h
index 9f01eaf..fc61810 100644
--- a/Source/cmMessageCommand.h
+++ b/Source/cmMessageCommand.h
@@ -67,8 +67,9 @@ public:
" STATUS = Incidental information\n"
" WARNING = CMake Warning, continue processing\n"
" AUTHOR_WARNING = CMake Warning (dev), continue processing\n"
- " SEND_ERROR = CMake Error, continue but skip generation\n"
- " FATAL_ERROR = CMake Error, stop all processing\n"
+ " SEND_ERROR = CMake Error, continue processing,\n"
+ " but skip generation\n"
+ " FATAL_ERROR = CMake Error, stop processing and generation\n"
"The CMake command-line tool displays STATUS messages on stdout "
"and all other message types on stderr. "
"The CMake GUI displays all messages in its log area. "
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 6c54ced..7e48cd7 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -190,7 +190,7 @@ cmNinjaNormalTargetGenerator
linkOptionVar += cmTarget::GetTargetTypeName(targetType);
const std::string linkOption =
GetMakefile()->GetSafeDefinition(linkOptionVar.c_str());
- rspcontent = "$in " + linkOption + " $LINK_PATH $LINK_LIBRARIES";
+ rspcontent = "$in_newline "+linkOption+" $LINK_PATH $LINK_LIBRARIES";
vars.Objects = responseFlag.c_str();
vars.LinkLibraries = "";
}
@@ -439,6 +439,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
this->GetGeneratorTarget());
this->AddModuleDefinitionFlag(vars["LINK_FLAGS"]);
+ vars["LINK_FLAGS"] = cmGlobalNinjaGenerator
+ ::EncodeLiteral(vars["LINK_FLAGS"]);
+
vars["LINK_PATH"] = frameworkPath + linkPath;
// Compute architecture specific link flags. Yes, these go into a different
@@ -564,6 +567,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
// for instance ARG_MAX is 2096152 on Ubuntu or 262144 on Mac
commandLineLengthLimit = ((int)sysconf(_SC_ARG_MAX))-linkRuleLength-1000;
#else
+ (void)linkRuleLength;
commandLineLengthLimit = -1;
#endif
}
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 0f10152..3fb823c 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -147,7 +147,8 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
// Add shared-library flags if needed.
this->LocalGenerator->AddCMP0018Flags(flags, this->Target,
- language.c_str());
+ language.c_str(),
+ this->GetConfigName());
// Add include directory flags.
{
@@ -227,7 +228,7 @@ ComputeDefines(cmSourceFile *source, const std::string& language)
// Add preprocessor definitions for this target and configuration.
this->LocalGenerator->AppendDefines
(defines,
- this->GeneratorTarget->GetCompileDefinitions());
+ this->Target->GetCompileDefinitions(this->GetConfigName()));
this->LocalGenerator->AppendDefines
(defines,
source->GetProperty("COMPILE_DEFINITIONS"));
@@ -236,9 +237,6 @@ ComputeDefines(cmSourceFile *source, const std::string& language)
defPropName += cmSystemTools::UpperCase(this->GetConfigName());
this->LocalGenerator->AppendDefines
(defines,
- this->GeneratorTarget->GetCompileDefinitions(this->GetConfigName()));
- this->LocalGenerator->AppendDefines
- (defines,
source->GetProperty(defPropName.c_str()));
}
@@ -257,7 +255,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
return cmNinjaDeps();
cmComputeLinkInformation* cli =
- this->GeneratorTarget->GetLinkInformation(this->GetConfigName());
+ this->Target->GetLinkInformation(this->GetConfigName());
if(!cli)
return cmNinjaDeps();
@@ -423,17 +421,19 @@ cmNinjaTargetGenerator
std::vector<std::string> compileCmds;
cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+ if(useClDeps)
+ {
+ std::string cmdPrefix = clDepsBinary + lang + " $in \"$DEP_FILE\" $out " +
+ clShowPrefix + clBinary;
+ compileCmds.front().insert(0, cmdPrefix);
+ }
+
for (std::vector<std::string>::iterator i = compileCmds.begin();
i != compileCmds.end(); ++i)
this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
- std::string cmdLine;
- if(useClDeps)
- {
- cmdLine = clDepsBinary + lang + " $in \"$DEP_FILE\" $out " +
- clShowPrefix + clBinary;
- }
- cmdLine += this->GetLocalGenerator()->BuildCommandLine(compileCmds);
+ std::string cmdLine =
+ this->GetLocalGenerator()->BuildCommandLine(compileCmds);
// Write the rule for compiling file of the given language.
@@ -549,7 +549,7 @@ cmNinjaTargetGenerator
cmCustomCommand const* cc = (*si)->GetCustomCommand();
const std::vector<std::string>& ccoutputs = cc->GetOutputs();
std::transform(ccoutputs.begin(), ccoutputs.end(),
- std::back_inserter(implicitDeps), MapToNinjaPath());
+ std::back_inserter(orderOnlyDeps), MapToNinjaPath());
}
// If the source file is GENERATED and does not have a custom command
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 79af4d7..831e92e 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -457,7 +457,7 @@ cmPolicies::cmPolicies()
"This makes sure that the modules belonging to "
"CMake always get those files included which they expect, and against "
"which they were developed and tested. "
- "In call other cases, the files found in "
+ "In all other cases, the files found in "
"CMAKE_MODULE_PATH still take precedence over the ones in "
"the CMake module directory. "
"The OLD behaviour is to always prefer files from CMAKE_MODULE_PATH over "
@@ -491,6 +491,44 @@ cmPolicies::cmPolicies()
"CMAKE_SHARED_LIBRARY_<Lang>_FLAGS whether it is modified or not and "
"honor the POSITION_INDEPENDENT_CODE target property.",
2,8,9,0, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0019, "CMP0019",
+ "Do not re-expand variables in include and link information.",
+ "CMake 2.8.10 and lower re-evaluated values given to the "
+ "include_directories, link_directories, and link_libraries "
+ "commands to expand any leftover variable references at the "
+ "end of the configuration step. "
+ "This was for strict compatibility with VERY early CMake versions "
+ "because all variable references are now normally evaluated during "
+ "CMake language processing. "
+ "CMake 2.8.11 and higher prefer to skip the extra evaluation."
+ "\n"
+ "The OLD behavior for this policy is to re-evaluate the values "
+ "for strict compatibility. "
+ "The NEW behavior for this policy is to leave the values untouched.",
+ 2,8,11,0, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0020, "CMP0020",
+ "Automatically link Qt executables to qtmain target on Windows.",
+ "CMake 2.8.10 and lower required users of Qt to always specify a link "
+ "dependency to the qtmain.lib static library manually on Windows. CMake "
+ "2.8.11 gained the ability to evaluate generator expressions while "
+ "determining the link dependencies from IMPORTED targets. This allows "
+ "CMake itself to automatically link executables which link to Qt to the "
+ "qtmain.lib library when using IMPORTED Qt targets. For applications "
+ "already linking to qtmain.lib, this should have little impact. For "
+ "applications which supply their own alternative WinMain implementation "
+ "and for applications which use the QAxServer library, this automatic "
+ "linking will need to be disabled as per the documentation."
+ "\n"
+ "The OLD behavior for this policy is not to link executables to "
+ "qtmain.lib automatically when they link to the QtCore IMPORTED"
+ "target. "
+ "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);
}
cmPolicies::~cmPolicies()
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 6932565..c11af07 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -68,6 +68,8 @@ public:
CMP0018, ///< Ignore language flags for shared libs, and adhere to
/// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
/// instead.
+ CMP0019, ///< No variable re-expansion in include and link info
+ CMP0020, ///< Automatically link Qt executables to qtmain target
/** \brief Always the last entry.
*
diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx
index 25614b8..a1fa31f 100644
--- a/Source/cmQtAutomoc.cxx
+++ b/Source/cmQtAutomoc.cxx
@@ -17,6 +17,10 @@
#include "cmSourceFile.h"
#include "cmSystemTools.h"
+#if defined(_WIN32) && !defined(__CYGWIN__)
+# include "cmLocalVisualStudioGenerator.h"
+#endif
+
#include <cmsys/Terminal.h>
#include <cmsys/ios/sstream>
@@ -44,14 +48,14 @@ static bool containsQ_OBJECT(const std::string& text)
static std::string findMatchingHeader(const std::string& absPath,
const std::string& mocSubDir,
const std::string& basename,
- const std::list<std::string>& headerExtensions)
+ const std::vector<std::string>& headerExtensions)
{
std::string header;
- for(std::list<std::string>::const_iterator ext = headerExtensions.begin();
+ for(std::vector<std::string>::const_iterator ext = headerExtensions.begin();
ext != headerExtensions.end();
++ext)
{
- std::string sourceFilePath = absPath + basename + (*ext);
+ std::string sourceFilePath = absPath + basename + "." + (*ext);
if (cmsys::SystemTools::FileExists(sourceFilePath.c_str()))
{
header = sourceFilePath;
@@ -59,7 +63,7 @@ static std::string findMatchingHeader(const std::string& absPath,
}
if (!mocSubDir.empty())
{
- sourceFilePath = mocSubDir + basename + (*ext);
+ sourceFilePath = mocSubDir + basename + "." + (*ext);
if (cmsys::SystemTools::FileExists(sourceFilePath.c_str()))
{
header = sourceFilePath;
@@ -85,6 +89,18 @@ static std::string extractSubDir(const std::string& absPath,
}
+static void copyTargetProperty(cmTarget* destinationTarget,
+ cmTarget* sourceTarget,
+ const char* propertyName)
+{
+ const char* propertyValue = sourceTarget->GetProperty(propertyName);
+ if (propertyValue)
+ {
+ destinationTarget->SetProperty(propertyName, propertyValue);
+ }
+}
+
+
cmQtAutomoc::cmQtAutomoc()
:Verbose(cmsys::SystemTools::GetEnv("VERBOSE") != 0)
,ColorOutput(true)
@@ -107,12 +123,9 @@ cmQtAutomoc::cmQtAutomoc()
}
}
-
-void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
+bool cmQtAutomoc::InitializeMocSourceFile(cmTarget* target)
{
cmMakefile* makefile = target->GetMakefile();
- cmLocalGenerator* localGen = makefile->GetLocalGenerator();
- const char* targetName = target->GetName();
// don't do anything if there is no Qt4 or Qt5Core (which contains moc):
std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
if (qtMajorVersion == "")
@@ -121,9 +134,30 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
}
if (qtMajorVersion != "4" && qtMajorVersion != "5")
{
- return;
+ return false;
}
+ std::string automocTargetName = target->GetName();
+ automocTargetName += "_automoc";
+ std::string mocCppFile = makefile->GetCurrentOutputDirectory();
+ mocCppFile += "/";
+ mocCppFile += automocTargetName;
+ mocCppFile += ".cpp";
+ cmSourceFile* mocCppSource = makefile->GetOrCreateSource(mocCppFile.c_str(),
+ true);
+ makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
+ mocCppFile.c_str(), false);
+
+ target->AddSourceFile(mocCppSource);
+ return true;
+}
+
+void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
+{
+ cmMakefile* makefile = target->GetMakefile();
+ cmLocalGenerator* localGen = makefile->GetLocalGenerator();
+ const char* targetName = target->GetName();
+
bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE");
// create a custom target for running automoc at buildtime:
@@ -152,10 +186,44 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
std::string automocComment = "Automoc for target ";
automocComment += targetName;
- makefile->AddUtilityCommand(automocTargetName.c_str(), true,
- workingDirectory.c_str(), depends,
- commandLines, false, automocComment.c_str());
- target->AddUtility(automocTargetName.c_str());
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ bool usePRE_BUILD = false;
+ cmGlobalGenerator* gg = localGen->GetGlobalGenerator();
+ if(strstr(gg->GetName(), "Visual Studio"))
+ {
+ cmLocalVisualStudioGenerator* vslg =
+ static_cast<cmLocalVisualStudioGenerator*>(localGen);
+ // Under VS >= 7 use a PRE_BUILD event instead of a separate target to
+ // reduce the number of targets loaded into the IDE.
+ // This also works around a VS 11 bug that may skip updating the target:
+ // https://connect.microsoft.com/VisualStudio/feedback/details/769495
+ usePRE_BUILD = vslg->GetVersion() >= cmLocalVisualStudioGenerator::VS7;
+ }
+ if(usePRE_BUILD)
+ {
+ // Add the pre-build command directly to bypass the OBJECT_LIBRARY
+ // rejection in cmMakefile::AddCustomCommandToTarget because we know
+ // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
+ std::vector<std::string> no_output;
+ cmCustomCommand cc(makefile, no_output, depends,
+ commandLines, automocComment.c_str(),
+ workingDirectory.c_str());
+ cc.SetEscapeOldStyle(false);
+ cc.SetEscapeAllowMakeVars(true);
+ target->GetPreBuildCommands().push_back(cc);
+ }
+ else
+#endif
+ {
+ cmTarget* automocTarget = makefile->AddUtilityCommand(
+ automocTargetName.c_str(), true,
+ workingDirectory.c_str(), depends,
+ commandLines, false, automocComment.c_str());
+ // inherit FOLDER property from target (#13688)
+ copyTargetProperty(automocTarget, target, "FOLDER");
+
+ target->AddUtility(automocTargetName.c_str());
+ }
// configure a file to get all information to automoc at buildtime:
std::string _moc_files;
@@ -196,36 +264,11 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
}
- const char* qtIncDir = 0;
- const char* qtCoreIncDir = 0;
-
- // check whether ${QT_INCLUDE_DIR} is part of the implicit include dirs,
- // see http://public.kitware.com/Bug/view.php?id=13667
- bool qtIncludeDirMayHaveBeenRemoved = false;
- if (makefile->IsSet("QT_INCLUDE_DIR"))
- {
- qtIncDir = makefile->GetDefinition("QT_INCLUDE_DIR");
- std::string s =
- makefile->GetSafeDefinition("CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES");
- std::vector<std::string> implIncDirs;
- cmSystemTools::ExpandListArgument(s, implIncDirs);
- if (std::find(implIncDirs.begin(), implIncDirs.end(),std::string(qtIncDir))
- != implIncDirs.end())
- {
- qtIncludeDirMayHaveBeenRemoved = true;
- if (makefile->IsSet("QT_QTCORE_INCLUDE_DIR"))
- {
- qtCoreIncDir = makefile->GetDefinition("QT_QTCORE_INCLUDE_DIR");
- }
- }
- }
-
- bool haveQtCoreIncDir = false;
- bool haveQtIncDir = false;
-
std::vector<std::string> includeDirs;
cmGeneratorTarget gtgt(target);
- localGen->GetIncludeDirectories(includeDirs, &gtgt, "CXX");
+ // 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();
@@ -235,41 +278,14 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
_moc_incs += sep;
sep = ";";
_moc_incs += *incDirIt;
-
- if (qtIncludeDirMayHaveBeenRemoved && qtCoreIncDir && qtIncDir) // #13667
- {
- if (*incDirIt == qtIncDir)
- {
- haveQtIncDir = true;
- qtIncludeDirMayHaveBeenRemoved = false; // it's here, i.e. not removed
- }
- if (*incDirIt == qtCoreIncDir)
- {
- haveQtCoreIncDir = true;
- }
- }
}
- // Some projects (kdelibs, phonon) query the compiler for its default
- // include search dirs, and add those to
- // CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES.
- // These may include e.g./usr/lib/qt/include . This is typically also part
- // of ${QT_INCLUDES}. If this directory is then contained in the implicit
- // include dirs, it is removed from the include dirs returned from the
- // target above. So we add ${QT_INCLUDE_DIR} manually for moc if we detected
- // that ${QT_QTCORE_INCLUDE_DIR} is among the include dirs (there shouldn't
- // be a way to use Qt4 without using ${QT_QTCORE_INCLUDE_DIR} I think.
- // See #13646 and #13667.
- if (qtIncludeDirMayHaveBeenRemoved && qtCoreIncDir && qtIncDir
- && (haveQtCoreIncDir == true) && (haveQtIncDir == false))
+ const char* tmp = target->GetProperty("COMPILE_DEFINITIONS");
+ std::string _moc_compile_defs;
+ if (tmp)
{
- _moc_incs += sep;
- sep = ";";
- _moc_incs += qtIncDir;
+ _moc_compile_defs = target->GetCompileDefinitions(0);
}
-
- const char* tmp = target->GetProperty("COMPILE_DEFINITIONS");
- std::string _moc_compile_defs = (tmp!=0 ? tmp : "");
tmp = makefile->GetProperty("COMPILE_DEFINITIONS");
if (tmp)
{
@@ -304,17 +320,6 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
outputFile += "/AutomocInfo.cmake";
makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(),
false, true, false);
-
- std::string mocCppFile = makefile->GetCurrentOutputDirectory();
- mocCppFile += "/";
- mocCppFile += automocTargetName;
- mocCppFile += ".cpp";
- cmSourceFile* mocCppSource = makefile->GetOrCreateSource(mocCppFile.c_str(),
- true);
- target->AddSourceFile(mocCppSource);
-
- makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
- mocCppFile.c_str(), false);
}
@@ -332,7 +337,7 @@ bool cmQtAutomoc::Run(const char* targetDirectory)
if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5")
{
- success = this->RunAutomoc();
+ success = this->RunAutomoc(makefile);
}
this->WriteOldMocDefinitionsFile(targetDirectory);
@@ -540,7 +545,7 @@ void cmQtAutomoc::Init()
}
-bool cmQtAutomoc::RunAutomoc()
+bool cmQtAutomoc::RunAutomoc(cmMakefile* makefile)
{
if (!cmsys::SystemTools::FileExists(this->OutMocCppFilename.c_str())
|| (this->OldCompileSettingsStr != this->CurrentCompileSettingsStr))
@@ -564,22 +569,8 @@ bool cmQtAutomoc::RunAutomoc()
std::vector<std::string> sourceFiles;
cmSystemTools::ExpandListArgument(this->Sources, sourceFiles);
- std::list<std::string> headerExtensions;
- headerExtensions.push_back(".h");
- headerExtensions.push_back(".hpp");
- headerExtensions.push_back(".hxx");
-#if defined(_WIN32)
- // not case sensitive, don't add ".H"
-#elif defined(__APPLE__)
- // detect case-sensitive filesystem
- long caseSensitive = pathconf(this->Srcdir.c_str(), _PC_CASE_SENSITIVE);
- if (caseSensitive == 1)
- {
- headerExtensions.push_back(".H");
- }
-#else
- headerExtensions.push_back(".H");
-#endif
+ const std::vector<std::string>& headerExtensions =
+ makefile->GetHeaderExtensions();
for (std::vector<std::string>::const_iterator it = sourceFiles.begin();
it != sourceFiles.end();
@@ -679,7 +670,7 @@ bool cmQtAutomoc::RunAutomoc()
void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
- const std::list<std::string>& headerExtensions,
+ const std::vector<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs)
{
cmsys::RegularExpression mocIncludeRegExp(
@@ -857,7 +848,7 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
void cmQtAutomoc::StrictParseCppFile(const std::string& absFilename,
- const std::list<std::string>& headerExtensions,
+ const std::vector<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs)
{
cmsys::RegularExpression mocIncludeRegExp(
@@ -968,8 +959,8 @@ void cmQtAutomoc::StrictParseCppFile(const std::string& absFilename,
void cmQtAutomoc::SearchHeadersForCppFile(const std::string& absFilename,
- const std::list<std::string>& headerExtensions,
- std::set<std::string>& absHeaders)
+ const std::vector<std::string>& headerExtensions,
+ std::set<std::string>& absHeaders)
{
// search for header files and private header files we may need to moc:
const std::string basename =
@@ -977,22 +968,22 @@ void cmQtAutomoc::SearchHeadersForCppFile(const std::string& absFilename,
const std::string absPath = cmsys::SystemTools::GetFilenamePath(
cmsys::SystemTools::GetRealPath(absFilename.c_str())) + '/';
- for(std::list<std::string>::const_iterator ext = headerExtensions.begin();
+ for(std::vector<std::string>::const_iterator ext = headerExtensions.begin();
ext != headerExtensions.end();
++ext)
{
- const std::string headerName = absPath + basename + (*ext);
+ const std::string headerName = absPath + basename + "." + (*ext);
if (cmsys::SystemTools::FileExists(headerName.c_str()))
{
absHeaders.insert(headerName);
break;
}
}
- for(std::list<std::string>::const_iterator ext = headerExtensions.begin();
+ for(std::vector<std::string>::const_iterator ext = headerExtensions.begin();
ext != headerExtensions.end();
++ext)
{
- const std::string privateHeaderName = absPath+basename+"_p"+(*ext);
+ const std::string privateHeaderName = absPath+basename+"_p."+(*ext);
if (cmsys::SystemTools::FileExists(privateHeaderName.c_str()))
{
absHeaders.insert(privateHeaderName);
@@ -1113,7 +1104,8 @@ bool cmQtAutomoc::GenerateMoc(const std::string& sourceFile,
}
-std::string cmQtAutomoc::Join(const std::list<std::string>& lst,char separator)
+std::string cmQtAutomoc::Join(const std::vector<std::string>& lst,
+ char separator)
{
if (lst.empty())
{
@@ -1121,11 +1113,11 @@ std::string cmQtAutomoc::Join(const std::list<std::string>& lst,char separator)
}
std::string result;
- for (std::list<std::string>::const_iterator it = lst.begin();
+ for (std::vector<std::string>::const_iterator it = lst.begin();
it != lst.end();
++it)
{
- result += (*it) + separator;
+ result += "." + (*it) + separator;
}
result.erase(result.end() - 1);
return result;
diff --git a/Source/cmQtAutomoc.h b/Source/cmQtAutomoc.h
index a737477..01b68fc 100644
--- a/Source/cmQtAutomoc.h
+++ b/Source/cmQtAutomoc.h
@@ -23,6 +23,7 @@ public:
cmQtAutomoc();
bool Run(const char* targetDirectory);
+ bool InitializeMocSourceFile(cmTarget* target);
void SetupAutomocTarget(cmTarget* target);
private:
@@ -37,18 +38,18 @@ private:
std::string MakeCompileSettingsString(cmMakefile* makefile);
- bool RunAutomoc();
+ bool RunAutomoc(cmMakefile* makefile);
bool GenerateMoc(const std::string& sourceFile,
const std::string& mocFileName);
void ParseCppFile(const std::string& absFilename,
- const std::list<std::string>& headerExtensions,
+ const std::vector<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs);
void StrictParseCppFile(const std::string& absFilename,
- const std::list<std::string>& headerExtensions,
+ const std::vector<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs);
void SearchHeadersForCppFile(const std::string& absFilename,
- const std::list<std::string>& headerExtensions,
- std::set<std::string>& absHeaders);
+ const std::vector<std::string>& headerExtensions,
+ std::set<std::string>& absHeaders);
void ParseHeaders(const std::set<std::string>& absHeaders,
const std::map<std::string, std::string>& includedMocs,
@@ -56,7 +57,7 @@ private:
void Init();
- std::string Join(const std::list<std::string>& lst, char separator);
+ std::string Join(const std::vector<std::string>& lst, char separator);
bool EndsWith(const std::string& str, const std::string& with);
bool StartsWith(const std::string& str, const std::string& with);
std::string ReadAll(const std::string& filename);
diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h
index 65c89fa..9dd7848 100644
--- a/Source/cmSetTargetPropertiesCommand.h
+++ b/Source/cmSetTargetPropertiesCommand.h
@@ -156,7 +156,9 @@ public:
"\n"
"The EXCLUDE_FROM_DEFAULT_BUILD property is used by the visual "
"studio generators. If it is set to 1 the target will not be "
- "part of the default build when you select \"Build Solution\"."
+ "part of the default build when you select \"Build Solution\". "
+ "This can also be set on a per-configuration basis using "
+ "EXCLUDE_FROM_DEFAULT_BUILD_<CONFIG>."
;
}
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index cc3b6d6..1d4b0c8 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -458,7 +458,7 @@ void cmSourceFile::DefineProperties(cmake *cm)
"A property on a source file that indicates if the source file "
"is a header file with no associated implementation. This is "
"set automatically based on the file extension and is used by "
- "CMake to determine is certain dependency information should be "
+ "CMake to determine if certain dependency information should be "
"computed.");
cm->DefineProperty
diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx
index 4fd9851..f09976f 100644
--- a/Source/cmSourceGroup.cxx
+++ b/Source/cmSourceGroup.cxx
@@ -182,10 +182,6 @@ cmSourceGroup *cmSourceGroup::MatchChildrenRegex(const char *name)
std::vector<cmSourceGroup>::iterator end =
this->Internal->GroupChildren.end();
- if(this->MatchesRegex(name))
- {
- return this;
- }
for(;iter!=end; ++iter)
{
cmSourceGroup *result = iter->MatchChildrenRegex(name);
@@ -194,6 +190,11 @@ cmSourceGroup *cmSourceGroup::MatchChildrenRegex(const char *name)
return result;
}
}
+ if(this->MatchesRegex(name))
+ {
+ return this;
+ }
+
return 0;
}
diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h
index 6c87b71..9f6b7e4 100644
--- a/Source/cmSourceGroupCommand.h
+++ b/Source/cmSourceGroupCommand.h
@@ -68,7 +68,7 @@ public:
"expression matches the file will be favored.\n"
"The name of the group may contain backslashes to specify subgroups:\n"
" source_group(outer\\\\inner ...)\n"
- "For backwards compatibility, this command is also supports the "
+ "For backwards compatibility, this command also supports the "
"format:\n"
" source_group(name regex)";
}
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 0193dc9..e49edd8 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -19,6 +19,8 @@
#include <ctype.h>
#include <time.h>
+#include <cmTimestamp.h>
+
//----------------------------------------------------------------------------
bool cmStringCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
@@ -87,6 +89,10 @@ bool cmStringCommand
{
return this->HandleFindCommand(args);
}
+ else if(subCommand == "TIMESTAMP")
+ {
+ return this->HandleTimestampCommand(args);
+ }
std::string e = "does not recognize sub-command "+subCommand;
this->SetError(e.c_str());
@@ -879,3 +885,51 @@ bool cmStringCommand
this->Makefile->AddDefinition(variableName.c_str(), &*result.begin());
return true;
}
+
+//----------------------------------------------------------------------------
+bool cmStringCommand
+::HandleTimestampCommand(std::vector<std::string> const& args)
+{
+ if(args.size() < 2)
+ {
+ this->SetError("sub-command TIMESTAMP requires at least one argument.");
+ return false;
+ }
+ else if(args.size() > 4)
+ {
+ this->SetError("sub-command TIMESTAMP takes at most three arguments.");
+ return false;
+ }
+
+ unsigned int argsIndex = 1;
+
+ const std::string &outputVariable = args[argsIndex++];
+
+ std::string formatString;
+ if(args.size() > argsIndex && args[argsIndex] != "UTC")
+ {
+ formatString = args[argsIndex++];
+ }
+
+ bool utcFlag = false;
+ if(args.size() > argsIndex)
+ {
+ if(args[argsIndex] == "UTC")
+ {
+ utcFlag = true;
+ }
+ else
+ {
+ std::string e = " TIMESTAMP sub-command does not recognize option " +
+ args[argsIndex] + ".";
+ this->SetError(e.c_str());
+ return false;
+ }
+ }
+
+ cmTimestamp timestamp;
+ std::string result = timestamp.CurrentTime(formatString, utcFlag);
+ this->Makefile->AddDefinition(outputVariable.c_str(), result.c_str());
+
+ return true;
+}
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index 728b1bc..802e0b8 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -93,6 +93,7 @@ public:
" string(RANDOM [LENGTH <length>] [ALPHABET <alphabet>]\n"
" [RANDOM_SEED <seed>] <output variable>)\n"
" string(FIND <string> <substring> <output variable> [REVERSE])\n"
+ " string(TIMESTAMP <output variable> [<format string>] [UTC])\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 "
@@ -128,13 +129,16 @@ public:
"will search for the position of the last occurrence of the "
"specified substring.\n"
"The following characters have special meaning in regular expressions:\n"
- " ^ Matches at beginning of a line\n"
- " $ Matches at end of a line\n"
+ " ^ Matches at beginning of input\n"
+ " $ Matches at end of input\n"
" . Matches any single character\n"
" [ ] Matches any character(s) inside the brackets\n"
" [^ ] Matches any character(s) not inside the brackets\n"
" - Inside brackets, specifies an inclusive range between\n"
" characters on either side e.g. [a-f] is [abcdef]\n"
+ " To match a literal - using brackets, make it the first\n"
+ " or the last character e.g. [+*/-] matches basic\n"
+ " mathematical operators.\n"
" * Matches preceding pattern zero or more times\n"
" + Matches preceding pattern one or more times\n"
" ? Matches preceding pattern zero or once only\n"
@@ -142,7 +146,37 @@ public:
" () Saves a matched subexpression, which can be referenced \n"
" in the REGEX REPLACE operation. Additionally it is saved\n"
" by all regular expression-related commands, including \n"
- " e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).";
+ " e.g. if( MATCHES ), in the variables CMAKE_MATCH_(0..9).\n"
+ "*, + and ? have higher precedence than concatenation. | has lower "
+ "precedence than concatenation. This means that the regular expression "
+ "\"^ab+d$\" matches \"abbd\" but not \"ababd\", and the regular "
+ "expression \"^(ab|cd)$\" matches \"ab\" but not \"abd\".\n"
+ "TIMESTAMP will write a string representation of "
+ "the current date and/or time to the output variable.\n"
+ "Should the command be unable to obtain a timestamp "
+ "the output variable will be set to the empty string \"\".\n"
+ "The optional UTC flag requests the current date/time "
+ "representation to be in Coordinated Universal Time (UTC) "
+ "rather than local time.\n"
+ "The optional <format string> may contain the following "
+ "format specifiers: \n"
+ " %d The day of the current month (01-31).\n"
+ " %H The hour on a 24-hour clock (00-23).\n"
+ " %I The hour on a 12-hour clock (01-12).\n"
+ " %j The day of the current year (001-366).\n"
+ " %m The month of the current year (01-12).\n"
+ " %M The minute of the current hour (00-59).\n"
+ " %S The second of the current minute.\n"
+ " 60 represents a leap second. (00-60)\n"
+ " %U The week number of the current year (00-53).\n"
+ " %w The day of the current week. 0 is Sunday. (0-6)\n"
+ " %y The last two digits of the current year (00-99)\n"
+ " %Y The current year. \n"
+ "Unknown format specifiers will be ignored "
+ "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.";
}
cmTypeMacro(cmStringCommand, cmCommand);
@@ -165,6 +199,7 @@ protected:
bool HandleStripCommand(std::vector<std::string> const& args);
bool HandleRandomCommand(std::vector<std::string> const& args);
bool HandleFindCommand(std::vector<std::string> const& args);
+ bool HandleTimestampCommand(std::vector<std::string> const& args);
class RegexReplacement
{
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 544f7e4..67f3023 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -52,7 +52,6 @@
#endif
#if defined(CMAKE_BUILD_WITH_CMAKE)
-# include <memory> // auto_ptr
# include <fcntl.h>
# include "cmCryptoHash.h"
#endif
@@ -204,13 +203,13 @@ std::string cmSystemTools::EscapeQuotes(const char* str)
std::string cmSystemTools::TrimWhitespace(const std::string& s)
{
std::string::const_iterator start = s.begin();
- while(start != s.end() && *start == ' ')
+ while(start != s.end() && *start <= ' ')
++start;
if (start == s.end())
return "";
std::string::const_iterator stop = s.end()-1;
- while(*stop == ' ')
+ while(*stop <= ' ')
--stop;
return std::string(start, stop+1);
}
@@ -1181,46 +1180,35 @@ bool cmSystemTools::CopyFileIfDifferent(const char* source,
bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
{
#ifdef _WIN32
- /* On Windows the move functions will not replace existing files.
- Check if the destination exists. */
- struct stat newFile;
- if(stat(newname, &newFile) == 0)
+# ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+# endif
+ /* Windows MoveFileEx may not replace read-only or in-use files. If it
+ fails then remove the read-only attribute from any existing destination.
+ Try multiple times since we may be racing against another process
+ creating/opening the destination file just before our MoveFileEx. */
+ int tries = 5;
+ while(!MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) && --tries)
{
- /* The destination exists. We have to replace it carefully. The
- MoveFileEx function does what we need but is not available on
- Win9x. */
- OSVERSIONINFO osv;
- DWORD attrs;
-
- /* Make sure the destination is not read only. */
- attrs = GetFileAttributes(newname);
- if(attrs & FILE_ATTRIBUTE_READONLY)
+ // Try again only if failure was due to access permissions.
+ if(GetLastError() != ERROR_ACCESS_DENIED)
{
- SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY);
+ return false;
}
-
- /* Check the windows version number. */
- osv.dwOSVersionInfoSize = sizeof(osv);
- GetVersionEx(&osv);
- if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+ DWORD attrs = GetFileAttributes(newname);
+ if((attrs != INVALID_FILE_ATTRIBUTES) &&
+ (attrs & FILE_ATTRIBUTE_READONLY))
{
- /* This is Win9x. There is no MoveFileEx implementation. We
- cannot quite rename the file atomically. Just delete the
- destination and then move the file. */
- DeleteFile(newname);
- return MoveFile(oldname, newname) != 0;
+ // Remove the read-only attribute from the destination file.
+ SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY);
}
else
{
- /* This is not Win9x. Use the MoveFileEx implementation. */
- return MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) != 0;
+ // The file may be temporarily in use so wait a bit.
+ cmSystemTools::Delay(100);
}
}
- else
- {
- /* The destination does not exist. Just move the file. */
- return MoveFile(oldname, newname) != 0;
- }
+ return tries > 0;
#else
/* On UNIX we have an OS-provided call to do this atomically. */
return rename(oldname, newname) == 0;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index f3eb52b..d14bfca 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -15,11 +15,13 @@
#include "cmSourceFile.h"
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
+#include "cmComputeLinkInformation.h"
#include "cmDocumentCompileDefinitions.h"
#include "cmDocumentGeneratorExpressions.h"
#include "cmDocumentLocationUndefined.h"
#include "cmListFileCache.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
#include <cmsys/RegularExpression.hxx>
#include <map>
#include <set>
@@ -70,6 +72,11 @@ struct cmTarget::ImportInfo
cmTarget::LinkInterface LinkInterface;
};
+struct TargetConfigPair : public std::pair<cmTarget*, std::string> {
+ TargetConfigPair(cmTarget* tgt, const std::string &config)
+ : std::pair<cmTarget*, std::string>(tgt, config) {}
+};
+
//----------------------------------------------------------------------------
class cmTargetInternals
{
@@ -85,6 +92,7 @@ public:
// Others not copied here are result caches.
this->SourceEntries = r.SourceEntries;
}
+ ~cmTargetInternals();
typedef cmTarget::SourceFileFlags SourceFileFlags;
std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
bool SourceFileFlagsConstructed;
@@ -98,39 +106,98 @@ public:
OptionalLinkInterface(): Exists(false) {}
bool Exists;
};
- typedef std::map<cmStdString, OptionalLinkInterface> LinkInterfaceMapType;
+ typedef std::map<TargetConfigPair, OptionalLinkInterface>
+ LinkInterfaceMapType;
LinkInterfaceMapType LinkInterfaceMap;
typedef std::map<cmStdString, cmTarget::OutputInfo> OutputInfoMapType;
OutputInfoMapType OutputInfoMap;
- typedef std::map<cmStdString, cmTarget::ImportInfo> ImportInfoMapType;
+ typedef std::map<TargetConfigPair, cmTarget::ImportInfo>
+ ImportInfoMapType;
ImportInfoMapType ImportInfoMap;
// Cache link implementation computation from each configuration.
- typedef std::map<cmStdString, cmTarget::LinkImplementation> LinkImplMapType;
+ typedef std::map<TargetConfigPair,
+ cmTarget::LinkImplementation> LinkImplMapType;
LinkImplMapType LinkImplMap;
- typedef std::map<cmStdString, cmTarget::LinkClosure> LinkClosureMapType;
+ typedef std::map<TargetConfigPair, cmTarget::LinkClosure>
+ LinkClosureMapType;
LinkClosureMapType LinkClosureMap;
struct SourceEntry { std::vector<cmSourceFile*> Depends; };
typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
SourceEntriesType SourceEntries;
+
+ struct IncludeDirectoriesEntry {
+ IncludeDirectoriesEntry(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;
+ const std::string TargetName;
+ };
+ std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
+ std::vector<cmValueWithOrigin> LinkInterfaceIncludeDirectoriesEntries;
+
+ std::map<std::string, std::vector<IncludeDirectoriesEntry*> >
+ CachedLinkInterfaceIncludeDirectoriesEntries;
+ std::map<std::string, std::string> CachedLinkInterfaceCompileDefinitions;
+
+ std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
+ std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
};
//----------------------------------------------------------------------------
+void deleteAndClear(
+ std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries)
+{
+ for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+ it = entries.begin(),
+ end = entries.end();
+ it != end; ++it)
+ {
+ delete *it;
+ }
+ entries.clear();
+}
+
+//----------------------------------------------------------------------------
+void deleteAndClear(
+ std::map<std::string,
+ std::vector<cmTargetInternals::IncludeDirectoriesEntry*> > &entries)
+{
+ for (std::map<std::string,
+ std::vector<cmTargetInternals::IncludeDirectoriesEntry*> >::iterator
+ it = entries.begin(), end = entries.end(); it != end; ++it)
+ {
+ deleteAndClear(it->second);
+ }
+}
+
+//----------------------------------------------------------------------------
+cmTargetInternals::~cmTargetInternals()
+{
+ deleteAndClear(CachedLinkInterfaceIncludeDirectoriesEntries);
+}
+
+//----------------------------------------------------------------------------
cmTarget::cmTarget()
{
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;
this->IsApple = false;
this->IsImportedTarget = false;
+ this->BuildInterfaceIncludesAppended = false;
+ this->DebugIncludesDone = false;
}
//----------------------------------------------------------------------------
@@ -141,7 +208,8 @@ void cmTarget::DefineProperties(cmake *cm)
"Should the target be processed with automoc (for Qt projects).",
"AUTOMOC is a boolean specifying whether CMake will handle "
"the Qt moc preprocessor automatically, i.e. without having to use "
- "the QT4_WRAP_CPP() macro. Currently Qt4 is supported. "
+ "the QT4_WRAP_CPP() or QT5_WRAP_CPP() macro. Currently Qt4 and Qt5 are "
+ "supported. "
"When this property is set to TRUE, CMake will scan the source files "
"at build time and invoke moc accordingly. "
"If an #include statement like #include \"moc_foo.cpp\" is found, "
@@ -266,6 +334,21 @@ void cmTarget::DefineProperties(cmake *cm)
"bundle.");
cm->DefineProperty
+ ("EXCLUDE_FROM_DEFAULT_BUILD", cmProperty::TARGET,
+ "Exclude target from \"Build Solution\".",
+ "This property is only used by Visual Studio generators 7 and above. "
+ "When set to TRUE, the target will not be built when you press "
+ "\"Build Solution\".");
+
+ cm->DefineProperty
+ ("EXCLUDE_FROM_DEFAULT_BUILD_<CONFIG>", cmProperty::TARGET,
+ "Per-configuration version of target exclusion from \"Build Solution\". ",
+ "This is the configuration-specific version of "
+ "EXCLUDE_FROM_DEFAULT_BUILD. If the generic EXCLUDE_FROM_DEFAULT_BUILD "
+ "is also set on a target, EXCLUDE_FROM_DEFAULT_BUILD_<CONFIG> takes "
+ "precedence in configurations for which it has a value.");
+
+ cm->DefineProperty
("FRAMEWORK", cmProperty::TARGET,
"This target is a framework on the Mac.",
"If a shared library target has this property set to true it will "
@@ -486,6 +569,22 @@ void cmTarget::DefineProperties(cmake *cm)
"undefined behavior.");
cm->DefineProperty
+ ("LINK_LIBRARIES", cmProperty::TARGET,
+ "List of direct link dependencies.",
+ "This property specifies the list of libraries or targets which will be "
+ "used for linking. "
+ "In addition to accepting values from the target_link_libraries "
+ "command, values may be set directly on any target using the "
+ "set_property command. "
+ "\n"
+ "The target property values are used by the generators to set "
+ "the link libraries for the compiler. "
+ "See also the target_link_libraries command.\n"
+ "Contents of LINK_LIBRARIES may use \"generator expressions\" with "
+ "the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+
+ cm->DefineProperty
("INCLUDE_DIRECTORIES", cmProperty::TARGET,
"List of preprocessor include file search directories.",
"This property specifies the list of directories given "
@@ -651,6 +750,22 @@ void cmTarget::DefineProperties(cmake *cm)
"custom Makefile link rules.");
cm->DefineProperty
+ ("LINK_DEPENDS_NO_SHARED", cmProperty::TARGET,
+ "Do not depend on linked shared library files.",
+ "Set this property to true to tell CMake generators not to add "
+ "file-level dependencies on the shared library files linked by "
+ "this target. "
+ "Modification to the shared libraries will not be sufficient to "
+ "re-link this target. "
+ "Logical target-level dependencies will not be affected so the "
+ "linked shared libraries will still be brought up to date before "
+ "this target is built."
+ "\n"
+ "This property is initialized by the value of the variable "
+ "CMAKE_LINK_DEPENDS_NO_SHARED if it is set when a target is "
+ "created.");
+
+ cm->DefineProperty
("LINK_INTERFACE_LIBRARIES", cmProperty::TARGET,
"List public interface libraries for a shared library or executable.",
"By default linking to a shared library target transitively "
@@ -679,6 +794,28 @@ void cmTarget::DefineProperties(cmake *cm)
"for the named configuration.");
cm->DefineProperty
+ ("INTERFACE_INCLUDE_DIRECTORIES", cmProperty::TARGET,
+ "List of public include directories for a library.",
+ "Targets may populate this property to publish the include directories "
+ "required to compile against the headers for the target. Consuming "
+ "targets can add entries to their own INCLUDE_DIRECTORIES property such "
+ "as $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> to use the "
+ "include directories specified in the interface of 'foo'."
+ "\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 "
+ "required to compile against the headers for the target. Consuming "
+ "targets can add entries to their own COMPILE_DEFINITIONS property such "
+ "as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_DEFINITIONS> to use the "
+ "compile definitions specified in the interface of 'foo'."
+ "\n"
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+
+ cm->DefineProperty
("LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET,
"Repetition count for STATIC libraries with cyclic dependencies.",
"When linking to a STATIC library target with cyclic dependencies the "
@@ -790,6 +927,50 @@ void cmTarget::DefineProperties(cmake *cm)
"created.");
cm->DefineProperty
+ ("INTERFACE_POSITION_INDEPENDENT_CODE", cmProperty::TARGET,
+ "Whether consumers need to create a position-independent target",
+ "The INTERFACE_POSITION_INDEPENDENT_CODE property informs consumers of "
+ "this target whether they must set their POSITION_INDEPENDENT_CODE "
+ "property to ON. If this property is set to ON, then the "
+ "POSITION_INDEPENDENT_CODE property on all consumers will be set to "
+ "ON. Similarly, if this property is set to OFF, then the "
+ "POSITION_INDEPENDENT_CODE property on all consumers will be set to "
+ "OFF. If this property is undefined, then consumers will determine "
+ "their POSITION_INDEPENDENT_CODE property by other means. Consumers "
+ "must ensure that the targets that they link to have a consistent "
+ "requirement for their INTERFACE_POSITION_INDEPENDENT_CODE property.");
+
+ cm->DefineProperty
+ ("COMPATIBLE_INTERFACE_BOOL", cmProperty::TARGET,
+ "Properties which must be compatible with their link interface",
+ "The COMPATIBLE_INTERFACE_BOOL property may contain a list of properties"
+ "for this target which must be consistent when evaluated as a boolean "
+ "in the INTERFACE of all linked dependees. For example, if a "
+ "property \"FOO\" appears in the list, then for each dependee, the "
+ "\"INTERFACE_FOO\" property content in all of its dependencies must be "
+ "consistent with each other, and with the \"FOO\" property in the "
+ "dependee. Consistency in this sense has the meaning that if the "
+ "property is set, then it must have the same boolean value as all "
+ "others, and if the property is not set, then it is ignored. Note that "
+ "for each dependee, the set of properties from this property must not "
+ "intersect with the set of properties from the "
+ "COMPATIBLE_INTERFACE_STRING property.");
+
+ cm->DefineProperty
+ ("COMPATIBLE_INTERFACE_STRING", cmProperty::TARGET,
+ "Properties which must be string-compatible with their link interface",
+ "The COMPATIBLE_INTERFACE_STRING property may contain a list of "
+ "properties for this target which must be the same when evaluated as "
+ "a string in the INTERFACE of all linked dependees. For example, "
+ "if a property \"FOO\" appears in the list, then for each dependee, the "
+ "\"INTERFACE_FOO\" property content in all of its dependencies must be "
+ "equal with each other, and with the \"FOO\" property in the dependee. "
+ "If the property is not set, then it is ignored. Note that for each "
+ "dependee, the set of properties from this property must not intersect "
+ "with the set of properties from the COMPATIBLE_INTERFACE_BOOL "
+ "property.");
+
+ cm->DefineProperty
("POST_INSTALL_SCRIPT", cmProperty::TARGET,
"Deprecated install support.",
"The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the "
@@ -1067,7 +1248,9 @@ void cmTarget::DefineProperties(cmake *cm)
("GENERATOR_FILE_NAME", cmProperty::TARGET,
"Generator's file for this target.",
"An internal property used by some generators to record the name of "
- "project or dsp file associated with this target.");
+ "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().");
cm->DefineProperty
("SOURCES", cmProperty::TARGET,
@@ -1314,6 +1497,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->SetPropertyDefault("OSX_ARCHITECTURES", 0);
this->SetPropertyDefault("AUTOMOC", 0);
this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", 0);
+ this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", 0);
this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0);
this->SetPropertyDefault("WIN32_EXECUTABLE", 0);
this->SetPropertyDefault("MACOSX_BUNDLE", 0);
@@ -1359,8 +1543,14 @@ void cmTarget::SetMakefile(cmMakefile* mf)
// Initialize the INCLUDE_DIRECTORIES property based on the current value
// of the same directory property:
- this->SetProperty("INCLUDE_DIRECTORIES",
- this->Makefile->GetProperty("INCLUDE_DIRECTORIES"));
+ const std::vector<cmValueWithOrigin> parentIncludes =
+ this->Makefile->GetIncludeDirectoriesEntries();
+
+ for (std::vector<cmValueWithOrigin>::const_iterator it
+ = parentIncludes.begin(); it != parentIncludes.end(); ++it)
+ {
+ this->InsertInclude(*it);
+ }
if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY
|| this->TargetTypeValue == cmTarget::MODULE_LIBRARY)
@@ -1376,6 +1566,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->Makefile->GetPolicyStatus(cmPolicies::CMP0004);
this->PolicyStatusCMP0008 =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0008);
+ this->PolicyStatusCMP0020 =
+ this->Makefile->GetPolicyStatus(cmPolicies::CMP0020);
}
//----------------------------------------------------------------------------
@@ -1397,6 +1589,13 @@ void cmTarget::ClearLinkMaps()
this->Internal->LinkImplMap.clear();
this->Internal->LinkInterfaceMap.clear();
this->Internal->LinkClosureMap.clear();
+ for (cmTargetLinkInformationMap::const_iterator it
+ = this->LinkInformation.begin();
+ it != this->LinkInformation.end(); ++it)
+ {
+ delete it->second;
+ }
+ this->LinkInformation.clear();
}
//----------------------------------------------------------------------------
@@ -1695,9 +1894,10 @@ cmTargetTraceDependencies
for(cmCustomCommandLine::const_iterator cli = cit->begin();
cli != cit->end(); ++cli)
{
- const cmCompiledGeneratorExpression &cge = ge.Parse(*cli);
- cge.Evaluate(this->Makefile, 0, true);
- std::set<cmTarget*> geTargets = cge.GetTargets();
+ const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge
+ = ge.Parse(*cli);
+ cge->Evaluate(this->Makefile, 0, true);
+ std::set<cmTarget*> geTargets = cge->GetTargets();
for(std::set<cmTarget*>::const_iterator it = geTargets.begin();
it != geTargets.end(); ++it)
{
@@ -2060,23 +2260,74 @@ bool cmTarget::NameResolvesToFramework(const std::string& libname)
}
//----------------------------------------------------------------------------
-bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType)
+void cmTarget::GetDirectLinkLibraries(const char *config,
+ std::vector<std::string> &libs, cmTarget *head)
{
- if(this->NameResolvesToFramework(libname.c_str()))
+ const char *prop = this->GetProperty("LINK_LIBRARIES");
+ if (prop)
+ {
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+ const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "LINK_LIBRARIES", 0, 0);
+ cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
+ config,
+ false,
+ head,
+ &dagChecker),
+ libs);
+
+ std::set<cmStdString> seenProps = cge->GetSeenTargetProperties();
+ for (std::set<cmStdString>::const_iterator it = seenProps.begin();
+ it != seenProps.end(); ++it)
+ {
+ if (!this->GetProperty(it->c_str()))
+ {
+ this->LinkImplicitNullProperties.insert(*it);
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value,
+ cmTarget::LinkLibraryType llt)
+{
+ if (llt == GENERAL)
+ {
+ return value;
+ }
+
+ // Get the list of configurations considered to be DEBUG.
+ std::vector<std::stri