summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2013-08-13 07:48:01 -0400
committerAnas Nashif <anas.nashif@intel.com>2013-08-13 07:48:01 -0400
commit297c63fa65327491a2b50e521b661c5835a19fe4 (patch)
treecf30d58014e240eb5e4417727d8f137cdbe75828 /Source
parentef8aa19c33e83ff019595fd7f8fdc29c35c336a3 (diff)
downloadcmake-297c63fa65327491a2b50e521b661c5835a19fe4.tar.gz
cmake-297c63fa65327491a2b50e521b661c5835a19fe4.tar.bz2
cmake-297c63fa65327491a2b50e521b661c5835a19fe4.zip
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 8bf6c4084..f0519fe7c 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 c59c618e2..a8b890775 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 000000000..e8b0ea971
--- /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 000000000..0e95d70f6
--- /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 000000000..774c22c76
--- /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 000000000..10b67c39f
--- /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 000000000..af7ba807f
--- /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 000000000..1dafc1ff2
--- /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 48d935cbe..abae3724e 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 4bd5d5c2f..4494e8a18 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 78cb1b61c..d973c0134 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 e96469600..7cc152269 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 37ff46041..b36c2a2f8 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 b2e57a2b8..62bfa91d4 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 82248546f..e46fbdab7 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 edbe8380d..c617a3e32 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 101813fa4..ba3d968f6 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 13aa6d8f9..66a419405 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 b6035854e..b18891858 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 554efb5bb..4fa3c53b9 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 90296001a..ca50c6452 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 7a99ddfa0..d6d39a98f 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 4d1e249e6..20aded2b5 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 2c1a0afd9..5b3449181 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 0da8aae52..453e32ce2 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 ebef1ed9c..76ddeea01 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 b796b8373..e7491bba3 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 5c7414f13..bd1ff71c6 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 29daffde8..1684fb229 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 1d21d421d..6006758c7 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 c5252b794..1cc1e3a75 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 a77140d61..04a304e39 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 c14456535..e5f27cb51 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 9efeda48f..5b1c9c668 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 9097a7482..e3a2ad4e5 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 3722ab635..91d55a5a2 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 a6d04b70d..322a6a26f 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 f2638feda..587a6db51 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 423124340..3d5b24b84 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 696a6a8c3..c5146c5d7 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 49ed96795..227b22678 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 055aab032..dec2b54d1 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 80a04541f..1d5d1b920 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 cd3ef59a9..896b50aa5 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 f60f8d325..1a76922a5 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 ab77c6bc9..8fd95b9cd 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 67bce72d9..d6131cf1c 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 347174a9e..0393ecfa9 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 1ae70350b..85e49a928 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 a1505bd65..a4f6ac4b4 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 07df7d5e0..f2f77eea0 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 166a58461..74a0ccb21 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 f7dc8811e..d787eddc6 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 44841a900..43b7b8a60 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 bd9a4b7b4..16dfad7bc 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 3e660587d..e41e5ea86 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 cdfde6ea9..cb40796c8 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 ba0e8fbe6..949d46515 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 bf7e234dc..22af53f8d 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 445fd0e12..6cc3f25ae 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 8db0e8f53..61f9f5a25 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 e4bb2517a..ee963f920 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 fb3f39fe6..7147f86be 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 726537bfc..5e1be1648 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 8dffae43a..27ec56beb 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 70bc65de5..9f958a234 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 784173172..ad12b5a13 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 e719eccd5..20dd57ad1 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 000000000..75f2651ba
--- /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 000000000..ed393abf4
--- /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 25b13e52e..f6f4ceff3 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 96b8a0920..97ab0863c 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 37ce65e75..31ad68da9 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 000000000..e4802d59e
--- /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 000000000..790259372
--- /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 a4aa75a7d..b08c335ac 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 8de24b358..018ce7ecd 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 b4aa903a0..5973fa732 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 a54bf7c4a..7ce003216 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 eac1885f3..84b03300c 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 0080e55aa..4af7e11bf 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 455348aaf..cd0fce8ad 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 470cecabe..aa3a73d26 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 952492463..6a432984d 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 730a7a760..0a029dc5f 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 7d8df3733..ab8bd137e 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 29d3f444f..86b6f25df 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 bfb0ddf92..5cb50b9b8 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 ffc84f8fd..62a5cdf38 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 2e123a4d9..a01a0f890 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 04a2acdc6..ce7ad69bb 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 7a8fc510d..a619cecd0 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 19b55c62c..335ba0f25 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 a29a9f904..cbcd8a579 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 c46101625..f294daa0d 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 8c6787a2c..2a7d61d6a 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 c0cb8a6d1..bd3db3eae 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 6c95ea805..df1433105 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 0aab2d63e..11616e0d0 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 000000000..fd1d65fb5
--- /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 ef42bd4d6..4af06076f 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 691ebdb8f..28893bf27 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 80526aad8..d49639bef 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 b76a5bf9b..659de1186 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 d6045c8de..1f374d3b8 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 9a6a5139f..7951e9886 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 57a26c8ae..7af4ee3a8 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 de33b8f94..5756fbd0d 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 05f5b4c86..fa277b1d1 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 24c391610..c3df7d935 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 ebd82194c..e26cca940 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 e6dd09d6d..385cdc4a1 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 480c577f2..ee7c56fc6 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 47ce790f8..5926e0f21 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 25dd88f2a..000000000
--- 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 a088272ef..000000000
--- 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 d0a0c49a1..000000000
--- 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 8a2de4c0a..000000000
--- 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 efd71c65d..000000000
--- 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 71dbf2e3b..000000000
--- 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 23a1204bd..624d01d69 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 56337a4db..174f1ccb0 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 94e07bf38..000000000
--- 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 9445d156c..000000000
--- 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 000000000..d77b84d2c
--- /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 000000000..5844ee01e
--- /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 e8ca78873..9f3af71bb 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 259aa8d03..40149e911 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 ab2308f50..2494f559c 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 a8daad6a2..6d91f97fc 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 b6eea5d0b..63cbdb890 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 1df58f97b..6e786201b 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 bca1754c6..864e8db02 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 5009f2960..bcbd7a0bd 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 4cbc2750d..000000000
--- 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 12f80125a..000000000
--- 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 70af50d7b..2082384e6 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 0b0d1437f..1310a93ac 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 38dbfacc4..000000000
--- 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 989b0d1af..000000000
--- 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 4d8a6463b..000000000
--- 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 7c20cf4e2..000000000
--- 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 0968b771d..808664d44 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 cebf7d741..9d811706b 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 45b171ff2..e3cebc4ac 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 ee16eaebc..23e60a1fc 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 30d8f18bb..3092abf95 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 afa1ca22e..131a6e6d5 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 15bad5265..4816da9ea 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 d9c0e87e9..76a60cfcd 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 a5be8fbd5..e556bdeca 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 ba8184989..30c174375 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 6751fc02f..77a340a64 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 ee92906fe..7aff7314c 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 347ad3ec5..5f9b6585e 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 cab3e9065..8cf72f975 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 889118cbc..9218f448d 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 7848424c6..df64695aa 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 c057754a3..fec3d07d8 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 4952a8ce9..ee5b9d812 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 bd582181c..a1c34f076 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 db93529dd..0f680f6a1 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 e3749590b..703369e1c 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 f15322be6..dc94476c8 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 f9a2d3200..7d0bc67ed 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 95db2cc8c..d9e2ef0dd 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 4bcf4defd..ef2bb1d99 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 9968592d1..1a3499a96 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 f8c40c002..aedbb4ddc 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 f067da491..47a6d2e66 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 70cfe5421..74a731d5b 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 e7004d668..5b4e4d774 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 3d02d6a04..4220ae148 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 27c5b6a3b..dc0ceb340 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 9f01eaf24..fc61810c3 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 6c54ced9a..7e48cd716 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 0f1015208..3fb823cb0 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 79af4d700..831e92e92 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 6932565ab..c11af0714 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 25614b862..a1fa31f2a 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 a73747781..01b68fc54 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 65c89fad4..9dd7848d3 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 cc3b6d603..1d4b0c8b4 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 4fd98518b..f09976f44 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 6c87b7101..9f6b7e4f9 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 0193dc9e7..e49edd878 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 728b1bc5f..802e0b850 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 544f7e43e..67f302391 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 f3eb52b76..d14bfcaf6 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::string> const& debugConfigs =
+ this->Makefile->GetCMakeInstance()->GetDebugConfigs();
+
+ std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";
+
+ if (debugConfigs.size() > 1)
{
- std::string frameworkDir = libname;
- frameworkDir += "/../";
- frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
- std::vector<std::string>::iterator i =
- std::find(this->Frameworks.begin(),
- this->Frameworks.end(), frameworkDir);
- if(i == this->Frameworks.end())
+ for(std::vector<std::string>::const_iterator
+ li = debugConfigs.begin() + 1; li != debugConfigs.end(); ++li)
{
- this->Frameworks.push_back(frameworkDir);
+ configString += ",$<CONFIG:" + *li + ">";
}
- return true;
+ configString = "$<OR:" + configString + ">";
}
- return false;
+
+ if (llt == OPTIMIZED)
+ {
+ configString = "$<NOT:" + configString + ">";
+ }
+ return "$<" + configString + ":" + value + ">";
+}
+
+//----------------------------------------------------------------------------
+static std::string targetNameGenex(const char *lib)
+{
+ return std::string("$<TARGET_NAME:") + lib + ">";
}
//----------------------------------------------------------------------------
@@ -2089,7 +2340,24 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
{
return;
}
- this->AddFramework(lib, llt);
+
+ {
+ cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
+ const bool isNonImportedTarget = tgt && !tgt->IsImported();
+
+ const std::string libName = (isNonImportedTarget && llt != GENERAL)
+ ? targetNameGenex(lib)
+ : std::string(lib);
+ this->AppendProperty("LINK_LIBRARIES",
+ this->GetDebugGeneratorExpressions(libName,
+ llt).c_str());
+ }
+
+ if (cmGeneratorExpression::Find(lib) != std::string::npos)
+ {
+ return;
+ }
+
cmTarget::LibraryID tmp;
tmp.first = lib;
tmp.second = llt;
@@ -2440,6 +2708,30 @@ void cmTarget::SetProperty(const char* prop, const char* value)
return;
}
+ if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
+ {
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmGeneratorExpression ge(lfbt);
+ deleteAndClear(this->Internal->IncludeDirectoriesEntries);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+ this->Internal->IncludeDirectoriesEntries.push_back(
+ new cmTargetInternals::IncludeDirectoriesEntry(cge));
+ return;
+ }
+ if (strcmp(prop, "LINK_LIBRARIES") == 0)
+ {
+ this->Internal->LinkInterfaceIncludeDirectoriesEntries.clear();
+ if (cmGeneratorExpression::IsValidTargetName(value)
+ || cmGeneratorExpression::Find(value) != std::string::npos)
+ {
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmValueWithOrigin entry(value, lfbt);
+ this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry);
+ }
+ // Fall through
+ }
this->Properties.SetProperty(prop, value, cmProperty::TARGET);
this->MaybeInvalidatePropertyCache(prop);
}
@@ -2452,11 +2744,368 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
{
return;
}
+ if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
+ {
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmGeneratorExpression ge(lfbt);
+ this->Internal->IncludeDirectoriesEntries.push_back(
+ new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value)));
+ return;
+ }
+ if (strcmp(prop, "LINK_LIBRARIES") == 0)
+ {
+ if (cmGeneratorExpression::IsValidTargetName(value)
+ || cmGeneratorExpression::Find(value) != std::string::npos)
+ {
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmValueWithOrigin entry(value, lfbt);
+ this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry);
+ }
+ // Fall through
+ }
this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString);
this->MaybeInvalidatePropertyCache(prop);
}
//----------------------------------------------------------------------------
+void cmTarget::AppendBuildInterfaceIncludes()
+{
+ if(this->GetType() != cmTarget::SHARED_LIBRARY &&
+ this->GetType() != cmTarget::STATIC_LIBRARY &&
+ this->GetType() != cmTarget::MODULE_LIBRARY &&
+ !this->IsExecutableWithExports())
+ {
+ return;
+ }
+ if (this->BuildInterfaceIncludesAppended)
+ {
+ return;
+ }
+ this->BuildInterfaceIncludesAppended = true;
+
+ if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE"))
+ {
+ const char *binDir = this->Makefile->GetStartOutputDirectory();
+ const char *srcDir = this->Makefile->GetStartDirectory();
+ const std::string dirs = std::string(binDir ? binDir : "")
+ + std::string(binDir ? ";" : "")
+ + std::string(srcDir ? srcDir : "");
+ if (!dirs.empty())
+ {
+ this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
+ ("$<BUILD_INTERFACE:" + dirs + ">").c_str());
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::InsertInclude(const cmValueWithOrigin &entry,
+ bool before)
+{
+ cmGeneratorExpression ge(entry.Backtrace);
+
+ std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::iterator position
+ = before ? this->Internal->IncludeDirectoriesEntries.begin()
+ : this->Internal->IncludeDirectoriesEntries.end();
+
+ this->Internal->IncludeDirectoriesEntries.insert(position,
+ new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value)));
+}
+
+//----------------------------------------------------------------------------
+static void processIncludeDirectories(cmTarget *tgt,
+ const std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries,
+ std::vector<std::string> &includes,
+ std::set<std::string> &uniqueIncludes,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ const char *config, bool debugIncludes)
+{
+ cmMakefile *mf = tgt->GetMakefile();
+
+ for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+ it = entries.begin(), end = entries.end(); it != end; ++it)
+ {
+ bool testIsOff = true;
+ bool cacheIncludes = false;
+ std::vector<std::string> entryIncludes = (*it)->CachedIncludes;
+ if(!entryIncludes.empty())
+ {
+ testIsOff = false;
+ }
+ else
+ {
+ cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
+ config,
+ false,
+ tgt,
+ dagChecker),
+ entryIncludes);
+ if (mf->IsGeneratingBuildSystem()
+ && !(*it)->ge->GetHadContextSensitiveCondition())
+ {
+ cacheIncludes = true;
+ }
+ }
+ std::string usedIncludes;
+ for(std::vector<std::string>::iterator
+ li = entryIncludes.begin(); li != entryIncludes.end(); ++li)
+ {
+ cmTarget *dependentTarget =
+ mf->FindTargetToUse((*it)->TargetName.c_str());
+
+ const bool fromImported = dependentTarget
+ && dependentTarget->IsImported();
+
+ if (fromImported && !cmSystemTools::FileExists(li->c_str()))
+ {
+ cmOStringStream e;
+ e << "Imported target \"" << (*it)->TargetName << "\" includes "
+ "non-existent path\n \"" << *li << "\"\nin its "
+ "INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:\n"
+ "* The path was deleted, renamed, or moved to another "
+ "location.\n"
+ "* An install or uninstall procedure did not complete "
+ "successfully.\n"
+ "* The installation package was faulty and references files it "
+ "does not provide.\n";
+ tgt->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
+ return;
+ }
+
+ if (!cmSystemTools::FileIsFullPath(li->c_str()))
+ {
+ if (!(*it)->TargetName.empty())
+ {
+ cmOStringStream e;
+ e << "Target \"" << (*it)->TargetName << "\" contains relative "
+ "path in its INTERFACE_INCLUDE_DIRECTORIES:\n"
+ " \"" << *li << "\" ";
+ tgt->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
+ e.str().c_str());
+ return;
+ }
+ }
+
+ if (testIsOff && !cmSystemTools::IsOff(li->c_str()))
+ {
+ cmSystemTools::ConvertToUnixSlashes(*li);
+ }
+ std::string inc = *li;
+
+ if(uniqueIncludes.insert(inc).second)
+ {
+ includes.push_back(inc);
+ if (debugIncludes)
+ {
+ usedIncludes += " * " + inc + "\n";
+ }
+ }
+ }
+ if (cacheIncludes)
+ {
+ (*it)->CachedIncludes = entryIncludes;
+ }
+ if (!usedIncludes.empty())
+ {
+ mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
+ std::string("Used includes for target ")
+ + tgt->GetName() + ":\n"
+ + usedIncludes, (*it)->ge->GetBacktrace());
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
+{
+ std::vector<std::string> includes;
+ std::set<std::string> uniqueIncludes;
+ cmListFileBacktrace lfbt;
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "INCLUDE_DIRECTORIES", 0, 0);
+
+ this->AppendBuildInterfaceIncludes();
+
+ std::vector<std::string> debugProperties;
+ const char *debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp)
+ {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugIncludes = !this->DebugIncludesDone
+ && std::find(debugProperties.begin(),
+ debugProperties.end(),
+ "INCLUDE_DIRECTORIES")
+ != debugProperties.end();
+
+ if (this->Makefile->IsGeneratingBuildSystem())
+ {
+ this->DebugIncludesDone = true;
+ }
+
+ processIncludeDirectories(this,
+ this->Internal->IncludeDirectoriesEntries,
+ includes,
+ uniqueIncludes,
+ &dagChecker,
+ config,
+ debugIncludes);
+
+ std::string configString = config ? config : "";
+ if (!this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString])
+ {
+ for (std::vector<cmValueWithOrigin>::const_iterator
+ it = this->Internal->LinkInterfaceIncludeDirectoriesEntries.begin(),
+ end = this->Internal->LinkInterfaceIncludeDirectoriesEntries.end();
+ it != end; ++it)
+ {
+ {
+ cmGeneratorExpression ge(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(it->Value);
+ std::string result = cge->Evaluate(this->Makefile, config,
+ false, this, 0, 0);
+ if (!this->Makefile->FindTargetToUse(result.c_str()))
+ {
+ continue;
+ }
+ }
+ std::string includeGenex = "$<TARGET_PROPERTY:" +
+ it->Value + ",INTERFACE_INCLUDE_DIRECTORIES>";
+ if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
+ {
+ // Because it->Value is a generator expression, ensure that it
+ // evaluates to the non-empty string before being used in the
+ // TARGET_PROPERTY expression.
+ includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
+ }
+ cmGeneratorExpression ge(it->Backtrace);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
+ includeGenex);
+
+ this->Internal
+ ->CachedLinkInterfaceIncludeDirectoriesEntries[configString].push_back(
+ new cmTargetInternals::IncludeDirectoriesEntry(cge,
+ it->Value));
+ }
+ }
+
+ processIncludeDirectories(this,
+ this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries[configString],
+ includes,
+ uniqueIncludes,
+ &dagChecker,
+ config,
+ debugIncludes);
+
+ if (!this->Makefile->IsGeneratingBuildSystem())
+ {
+ deleteAndClear(
+ this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries);
+ }
+ else
+ {
+ this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString]
+ = true;
+ }
+
+ return includes;
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::GetCompileDefinitions(const char *config)
+{
+ const char *configProp = 0;
+ if (config)
+ {
+ std::string configPropName;
+ configPropName = "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
+ configProp = this->GetProperty(configPropName.c_str());
+ }
+
+ const char *noconfigProp = this->GetProperty("COMPILE_DEFINITIONS");
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "COMPILE_DEFINITIONS", 0, 0);
+
+ std::string defsString = (noconfigProp ? noconfigProp : "");
+ if (configProp && noconfigProp)
+ {
+ defsString += ";";
+ }
+ defsString += (configProp ? configProp : "");
+
+ cmGeneratorExpression ge(lfbt);
+ std::string result = ge.Parse(defsString.c_str())->Evaluate(this->Makefile,
+ config,
+ false,
+ this,
+ &dagChecker);
+
+ std::vector<std::string> libs;
+ this->GetDirectLinkLibraries(config, libs, this);
+
+ if (libs.empty())
+ {
+ return result;
+ }
+
+ std::string sep;
+ std::string depString;
+ for (std::vector<std::string>::const_iterator it = libs.begin();
+ it != libs.end(); ++it)
+ {
+ if ((cmGeneratorExpression::IsValidTargetName(it->c_str())
+ || cmGeneratorExpression::Find(it->c_str()) != std::string::npos)
+ && this->Makefile->FindTargetToUse(it->c_str()))
+ {
+ depString += sep + "$<TARGET_PROPERTY:"
+ + *it + ",INTERFACE_COMPILE_DEFINITIONS>";
+ sep = ";";
+ }
+ }
+
+ std::string configString = config ? config : "";
+ if (!this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString])
+ {
+ cmGeneratorExpression ge2(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge2 =
+ ge2.Parse(depString);
+ this->Internal->CachedLinkInterfaceCompileDefinitions[configString] =
+ cge2->Evaluate(this->Makefile,
+ config,
+ false,
+ this,
+ &dagChecker);
+ }
+ if (!this->Internal->CachedLinkInterfaceCompileDefinitions[configString]
+ .empty())
+ {
+ result += (result.empty() ? "" : ";")
+ + this->Internal->CachedLinkInterfaceCompileDefinitions[configString];
+ }
+
+ if (!this->Makefile->IsGeneratingBuildSystem())
+ {
+ this->Internal->CachedLinkInterfaceCompileDefinitions[configString] = "";
+ }
+ else
+ {
+ this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString]
+ = true;
+ }
+
+ return result;
+}
+
+//----------------------------------------------------------------------------
void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
{
// Wipe out maps caching information affected by this property.
@@ -2783,6 +3432,24 @@ const char *cmTarget::GetProperty(const char* prop,
}
}
}
+ if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
+ {
+ static std::string output;
+ output = "";
+ std::string sep;
+ typedef cmTargetInternals::IncludeDirectoriesEntry
+ IncludeDirectoriesEntry;
+ for (std::vector<IncludeDirectoriesEntry*>::const_iterator
+ it = this->Internal->IncludeDirectoriesEntries.begin(),
+ end = this->Internal->IncludeDirectoriesEntries.end();
+ it != end; ++it)
+ {
+ output += sep;
+ output += (*it)->ge->GetInput();
+ sep = ";";
+ }
+ return output.c_str();
+ }
if (strcmp(prop,"IMPORTED") == 0)
{
@@ -2842,8 +3509,11 @@ class cmTargetCollectLinkLanguages
{
public:
cmTargetCollectLinkLanguages(cmTarget* target, const char* config,
- std::set<cmStdString>& languages):
- Config(config), Languages(languages) { this->Visited.insert(target); }
+ std::set<cmStdString>& languages,
+ cmTarget* head):
+ Config(config), Languages(languages), HeadTarget(head)
+ { this->Visited.insert(target); }
+
void Visit(cmTarget* target)
{
if(!target || !this->Visited.insert(target).second)
@@ -2852,7 +3522,7 @@ public:
}
cmTarget::LinkInterface const* iface =
- target->GetLinkInterface(this->Config);
+ target->GetLinkInterface(this->Config, this->HeadTarget);
if(!iface) { return; }
for(std::vector<std::string>::const_iterator
@@ -2871,26 +3541,30 @@ public:
private:
const char* Config;
std::set<cmStdString>& Languages;
+ cmTarget* HeadTarget;
std::set<cmTarget*> Visited;
};
//----------------------------------------------------------------------------
-const char* cmTarget::GetLinkerLanguage(const char* config)
+const char* cmTarget::GetLinkerLanguage(const char* config, cmTarget *head)
{
- const char* lang = this->GetLinkClosure(config)->LinkerLanguage.c_str();
+ cmTarget *headTarget = head ? head : this;
+ const char* lang = this->GetLinkClosure(config, headTarget)
+ ->LinkerLanguage.c_str();
return *lang? lang : 0;
}
//----------------------------------------------------------------------------
-cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config)
+cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config,
+ cmTarget *head)
{
- std::string key = cmSystemTools::UpperCase(config? config : "");
+ TargetConfigPair key(head, cmSystemTools::UpperCase(config ? config : ""));
cmTargetInternals::LinkClosureMapType::iterator
i = this->Internal->LinkClosureMap.find(key);
if(i == this->Internal->LinkClosureMap.end())
{
LinkClosure lc;
- this->ComputeLinkClosure(config, lc);
+ this->ComputeLinkClosure(config, lc, head);
cmTargetInternals::LinkClosureMapType::value_type entry(key, lc);
i = this->Internal->LinkClosureMap.insert(entry).first;
}
@@ -2951,11 +3625,12 @@ public:
};
//----------------------------------------------------------------------------
-void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
+void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc,
+ cmTarget *head)
{
// Get languages built in this target.
std::set<cmStdString> languages;
- LinkImplementation const* impl = this->GetLinkImplementation(config);
+ LinkImplementation const* impl = this->GetLinkImplementation(config, head);
for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
li != impl->Languages.end(); ++li)
{
@@ -2963,7 +3638,7 @@ void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc)
}
// Add interface languages from linked targets.
- cmTargetCollectLinkLanguages cll(this, config, languages);
+ cmTargetCollectLinkLanguages cll(this, config, languages, head);
for(std::vector<std::string>::const_iterator li = impl->Libraries.begin();
li != impl->Libraries.end(); ++li)
{
@@ -3102,7 +3777,8 @@ bool cmTarget::HasSOName(const char* config)
return ((this->GetType() == cmTarget::SHARED_LIBRARY ||
this->GetType() == cmTarget::MODULE_LIBRARY) &&
!this->GetPropertyAsBool("NO_SONAME") &&
- this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config)));
+ this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config,
+ this)));
}
//----------------------------------------------------------------------------
@@ -3111,7 +3787,7 @@ std::string cmTarget::GetSOName(const char* config)
if(this->IsImported())
{
// Lookup the imported soname.
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+ if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
{
if(info->NoSOName)
{
@@ -3148,7 +3824,7 @@ bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config)
{
if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY)
{
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+ if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
{
return info->NoSOName;
}
@@ -3262,7 +3938,7 @@ std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
std::string cmTarget::ImportedGetFullPath(const char* config, bool implib)
{
std::string result;
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+ if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
{
result = implib? info->ImportLibrary : info->Location;
}
@@ -3347,7 +4023,7 @@ void cmTarget::GetFullNameInternal(const char* config,
const char* suffixVar = this->GetSuffixVariableInternal(implib);
// Check for language-specific default prefix and suffix.
- if(const char* ll = this->GetLinkerLanguage(config))
+ if(const char* ll = this->GetLinkerLanguage(config, this))
{
if(!targetSuffix && suffixVar && *suffixVar)
{
@@ -3666,10 +4342,15 @@ void cmTarget::SetPropertyDefault(const char* property,
}
//----------------------------------------------------------------------------
-bool cmTarget::HaveBuildTreeRPATH()
+bool cmTarget::HaveBuildTreeRPATH(const char *config)
{
- return (!this->GetPropertyAsBool("SKIP_BUILD_RPATH") &&
- !this->LinkLibraries.empty());
+ if (this->GetPropertyAsBool("SKIP_BUILD_RPATH"))
+ {
+ return false;
+ }
+ std::vector<std::string> libs;
+ this->GetDirectLinkLibraries(config, libs, this);
+ return !libs.empty();
}
//----------------------------------------------------------------------------
@@ -3718,7 +4399,7 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config)
}
// Check for rpath support on this platform.
- if(const char* ll = this->GetLinkerLanguage(config))
+ if(const char* ll = this->GetLinkerLanguage(config, this))
{
std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
flagVar += ll;
@@ -3740,7 +4421,7 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config)
// If either a build or install tree rpath is set then the rpath
// will likely change between the build tree and install tree and
// this target must be relinked.
- return this->HaveBuildTreeRPATH() || this->HaveInstallTreeRPATH();
+ return this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH();
}
//----------------------------------------------------------------------------
@@ -4089,6 +4770,280 @@ const char* cmTarget::GetExportMacro()
}
//----------------------------------------------------------------------------
+bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p)
+{
+ return this->LinkImplicitNullProperties.find(p)
+ != this->LinkImplicitNullProperties.end();
+}
+
+//----------------------------------------------------------------------------
+template<typename PropertyType>
+PropertyType getTypedProperty(cmTarget *tgt, const char *prop,
+ PropertyType *);
+
+//----------------------------------------------------------------------------
+template<>
+bool getTypedProperty<bool>(cmTarget *tgt, const char *prop, bool *)
+{
+ return tgt->GetPropertyAsBool(prop);
+}
+
+//----------------------------------------------------------------------------
+template<>
+const char *getTypedProperty<const char *>(cmTarget *tgt, const char *prop,
+ const char **)
+{
+ return tgt->GetProperty(prop);
+}
+
+//----------------------------------------------------------------------------
+template<typename PropertyType>
+bool consistentProperty(PropertyType lhs, PropertyType rhs);
+
+//----------------------------------------------------------------------------
+template<>
+bool consistentProperty(bool lhs, bool rhs)
+{
+ return lhs == rhs;
+}
+
+//----------------------------------------------------------------------------
+template<>
+bool consistentProperty(const char *lhs, const char *rhs)
+{
+ if (!lhs && !rhs)
+ return true;
+ if (!lhs || !rhs)
+ return false;
+ return strcmp(lhs, rhs) == 0;
+}
+
+//----------------------------------------------------------------------------
+template<typename PropertyType>
+PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt,
+ const std::string &p,
+ const char *config,
+ const char *defaultValue,
+ PropertyType *)
+{
+ PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(),
+ 0);
+ const bool explicitlySet = tgt->GetProperties()
+ .find(p.c_str())
+ != tgt->GetProperties().end();
+ const bool impliedByUse =
+ tgt->IsNullImpliedByLinkLibraries(p);
+ assert((impliedByUse ^ explicitlySet)
+ || (!impliedByUse && !explicitlySet));
+
+ cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
+ if(!info)
+ {
+ return propContent;
+ }
+ const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
+ bool propInitialized = explicitlySet;
+
+ for(cmComputeLinkInformation::ItemVector::const_iterator li =
+ deps.begin();
+ li != deps.end(); ++li)
+ {
+ // An error should be reported if one dependency
+ // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other
+ // has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the
+ // target itself has a POSITION_INDEPENDENT_CODE which disagrees
+ // with a dependency.
+
+ if (!li->Target)
+ {
+ continue;
+ }
+
+ const bool ifaceIsSet = li->Target->GetProperties()
+ .find("INTERFACE_" + p)
+ != li->Target->GetProperties().end();
+ PropertyType ifacePropContent =
+ getTypedProperty<PropertyType>(li->Target,
+ ("INTERFACE_" + p).c_str(), 0);
+ if (explicitlySet)
+ {
+ if (ifaceIsSet)
+ {
+ if (!consistentProperty(propContent, ifacePropContent))
+ {
+ cmOStringStream e;
+ e << "Property " << p << " on target \""
+ << tgt->GetName() << "\" does\nnot match the "
+ "INTERFACE_" << p << " property requirement\nof "
+ "dependency \"" << li->Target->GetName() << "\".\n";
+ cmSystemTools::Error(e.str().c_str());
+ break;
+ }
+ else
+ {
+ // Agree
+ continue;
+ }
+ }
+ else
+ {
+ // Explicitly set on target and not set in iface. Can't disagree.
+ continue;
+ }
+ }
+ else if (impliedByUse)
+ {
+ if (ifaceIsSet)
+ {
+ if (!consistentProperty(propContent, ifacePropContent))
+ {
+ cmOStringStream e;
+ e << "Property " << p << " on target \""
+ << tgt->GetName() << "\" is\nimplied to be " << defaultValue
+ << " because it was used to determine the link libraries\n"
+ "already. The INTERFACE_" << p << " property on\ndependency \""
+ << li->Target->GetName() << "\" is in conflict.\n";
+ cmSystemTools::Error(e.str().c_str());
+ break;
+ }
+ else
+ {
+ // Agree
+ continue;
+ }
+ }
+ else
+ {
+ // Implicitly set on target and not set in iface. Can't disagree.
+ continue;
+ }
+ }
+ else
+ {
+ if (ifaceIsSet)
+ {
+ if (propInitialized)
+ {
+ if (!consistentProperty(propContent, ifacePropContent))
+ {
+ cmOStringStream e;
+ e << "The INTERFACE_" << p << " property of \""
+ << li->Target->GetName() << "\" does\nnot agree with the value "
+ "of " << p << " already determined\nfor \""
+ << tgt->GetName() << "\".\n";
+ cmSystemTools::Error(e.str().c_str());
+ break;
+ }
+ else
+ {
+ // Agree.
+ continue;
+ }
+ }
+ else
+ {
+ propContent = ifacePropContent;
+ propInitialized = true;
+ }
+ }
+ else
+ {
+ // Not set. Nothing to agree on.
+ continue;
+ }
+ }
+ }
+ return propContent;
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
+ const char *config)
+{
+ return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
+ 0);
+}
+
+//----------------------------------------------------------------------------
+const char * cmTarget::GetLinkInterfaceDependentStringProperty(
+ const std::string &p,
+ const char *config)
+{
+ return checkInterfacePropertyCompatibility<const char *>(this,
+ p,
+ config,
+ "empty", 0);
+}
+
+//----------------------------------------------------------------------------
+bool isLinkDependentProperty(cmTarget *tgt, const std::string &p,
+ const char *interfaceProperty,
+ const char *config)
+{
+ cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
+ if(!info)
+ {
+ return false;
+ }
+
+ const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
+
+ for(cmComputeLinkInformation::ItemVector::const_iterator li =
+ deps.begin();
+ li != deps.end(); ++li)
+ {
+ if (!li->Target)
+ {
+ continue;
+ }
+ const char *prop = li->Target->GetProperty(interfaceProperty);
+ if (!prop)
+ {
+ continue;
+ }
+
+ std::vector<std::string> props;
+ cmSystemTools::ExpandListArgument(prop, props);
+
+ for(std::vector<std::string>::iterator pi = props.begin();
+ pi != props.end(); ++pi)
+ {
+ if (*pi == p)
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p,
+ const char *config)
+{
+ if (this->TargetTypeValue == OBJECT_LIBRARY)
+ {
+ return false;
+ }
+ return (p == "POSITION_INDEPENDENT_CODE") ||
+ isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_BOOL",
+ config);
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p,
+ const char *config)
+{
+ if (this->TargetTypeValue == OBJECT_LIBRARY)
+ {
+ return false;
+ }
+ return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING",
+ config);
+}
+
+//----------------------------------------------------------------------------
void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
{
for(std::vector<cmSourceFile*>::const_iterator
@@ -4140,7 +5095,7 @@ bool cmTarget::IsChrpathUsed(const char* config)
// Enable if the rpath flag uses a separator and the target uses ELF
// binaries.
- if(const char* ll = this->GetLinkerLanguage(config))
+ if(const char* ll = this->GetLinkerLanguage(config, this))
{
std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
sepVar += ll;
@@ -4164,7 +5119,7 @@ bool cmTarget::IsChrpathUsed(const char* config)
//----------------------------------------------------------------------------
cmTarget::ImportInfo const*
-cmTarget::GetImportInfo(const char* config)
+cmTarget::GetImportInfo(const char* config, cmTarget *headTarget)
{
// There is no imported information for non-imported targets.
if(!this->IsImported())
@@ -4183,14 +5138,16 @@ cmTarget::GetImportInfo(const char* config)
{
config_upper = "NOCONFIG";
}
+ TargetConfigPair key(headTarget, config_upper);
typedef cmTargetInternals::ImportInfoMapType ImportInfoMapType;
+
ImportInfoMapType::const_iterator i =
- this->Internal->ImportInfoMap.find(config_upper);
+ this->Internal->ImportInfoMap.find(key);
if(i == this->Internal->ImportInfoMap.end())
{
ImportInfo info;
- this->ComputeImportInfo(config_upper, info);
- ImportInfoMapType::value_type entry(config_upper, info);
+ this->ComputeImportInfo(config_upper, info, headTarget);
+ ImportInfoMapType::value_type entry(key, info);
i = this->Internal->ImportInfoMap.insert(entry).first;
}
@@ -4205,27 +5162,15 @@ cmTarget::GetImportInfo(const char* config)
return &i->second;
}
-//----------------------------------------------------------------------------
-void cmTarget::ComputeImportInfo(std::string const& desired_config,
- ImportInfo& info)
+bool cmTarget::GetMappedConfig(std::string const& desired_config,
+ const char** loc,
+ const char** imp,
+ std::string& suffix)
{
- // This method finds information about an imported target from its
- // properties. The "IMPORTED_" namespace is reserved for properties
- // defined by the project exporting the target.
-
- // Initialize members.
- info.NoSOName = false;
-
// Track the configuration-specific property suffix.
- std::string suffix = "_";
+ suffix = "_";
suffix += desired_config;
- // On a DLL platform there may be only IMPORTED_IMPLIB for a shared
- // library or an executable with exports.
- bool allowImp = this->HasImportLibrary();
-
- // Look for a mapping from the current project's configuration to
- // the imported project's configuration.
std::vector<std::string> mappedConfigs;
{
std::string mapProp = "MAP_IMPORTED_CONFIG_";
@@ -4236,26 +5181,29 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
}
}
+ // If we needed to find one of the mapped configurations but did not
+ // On a DLL platform there may be only IMPORTED_IMPLIB for a shared
+ // library or an executable with exports.
+ bool allowImp = this->HasImportLibrary();
+
// If a mapping was found, check its configurations.
- const char* loc = 0;
- const char* imp = 0;
for(std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
- !loc && !imp && mci != mappedConfigs.end(); ++mci)
+ !*loc && !*imp && mci != mappedConfigs.end(); ++mci)
{
// Look for this configuration.
std::string mcUpper = cmSystemTools::UpperCase(mci->c_str());
std::string locProp = "IMPORTED_LOCATION_";
locProp += mcUpper;
- loc = this->GetProperty(locProp.c_str());
+ *loc = this->GetProperty(locProp.c_str());
if(allowImp)
{
std::string impProp = "IMPORTED_IMPLIB_";
impProp += mcUpper;
- imp = this->GetProperty(impProp.c_str());
+ *imp = this->GetProperty(impProp.c_str());
}
// If it was found, use it for all properties below.
- if(loc || imp)
+ if(*loc || *imp)
{
suffix = "_";
suffix += mcUpper;
@@ -4265,45 +5213,45 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
// If we needed to find one of the mapped configurations but did not
// then the target is not found. The project does not want any
// other configuration.
- if(!mappedConfigs.empty() && !loc && !imp)
+ if(!mappedConfigs.empty() && !*loc && !*imp)
{
- return;
+ return false;
}
// If we have not yet found it then there are no mapped
// configurations. Look for an exact-match.
- if(!loc && !imp)
+ if(!*loc && !*imp)
{
std::string locProp = "IMPORTED_LOCATION";
locProp += suffix;
- loc = this->GetProperty(locProp.c_str());
+ *loc = this->GetProperty(locProp.c_str());
if(allowImp)
{
std::string impProp = "IMPORTED_IMPLIB";
impProp += suffix;
- imp = this->GetProperty(impProp.c_str());
+ *imp = this->GetProperty(impProp.c_str());
}
}
// If we have not yet found it then there are no mapped
// configurations and no exact match.
- if(!loc && !imp)
+ if(!*loc && !*imp)
{
// The suffix computed above is not useful.
suffix = "";
// Look for a configuration-less location. This may be set by
// manually-written code.
- loc = this->GetProperty("IMPORTED_LOCATION");
+ *loc = this->GetProperty("IMPORTED_LOCATION");
if(allowImp)
{
- imp = this->GetProperty("IMPORTED_IMPLIB");
+ *imp = this->GetProperty("IMPORTED_IMPLIB");
}
}
// If we have not yet found it then the project is willing to try
// any available configuration.
- if(!loc && !imp)
+ if(!*loc && !*imp)
{
std::vector<std::string> availableConfigs;
if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS"))
@@ -4312,24 +5260,47 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
}
for(std::vector<std::string>::const_iterator
aci = availableConfigs.begin();
- !loc && !imp && aci != availableConfigs.end(); ++aci)
+ !*loc && !*imp && aci != availableConfigs.end(); ++aci)
{
suffix = "_";
suffix += cmSystemTools::UpperCase(*aci);
std::string locProp = "IMPORTED_LOCATION";
locProp += suffix;
- loc = this->GetProperty(locProp.c_str());
+ *loc = this->GetProperty(locProp.c_str());
if(allowImp)
{
std::string impProp = "IMPORTED_IMPLIB";
impProp += suffix;
- imp = this->GetProperty(impProp.c_str());
+ *imp = this->GetProperty(impProp.c_str());
}
}
}
-
// If we have not yet found it then the target is not available.
- if(!loc && !imp)
+ if(!*loc && !*imp)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::ComputeImportInfo(std::string const& desired_config,
+ ImportInfo& info,
+ cmTarget *headTarget)
+{
+ (void)headTarget;
+ // This method finds information about an imported target from its
+ // properties. The "IMPORTED_" namespace is reserved for properties
+ // defined by the project exporting the target.
+
+ // Initialize members.
+ info.NoSOName = false;
+
+ const char* loc = 0;
+ const char* imp = 0;
+ std::string suffix;
+ if (!this->GetMappedConfig(desired_config, &loc, &imp, suffix))
{
return;
}
@@ -4410,16 +5381,30 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
{
std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
linkProp += suffix;
- if(const char* config_libs = this->GetProperty(linkProp.c_str()))
+
+ const char *propertyLibs = this->GetProperty(linkProp.c_str());
+
+ if(!propertyLibs)
{
- cmSystemTools::ExpandListArgument(config_libs,
- info.LinkInterface.Libraries);
+ linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
+ propertyLibs = this->GetProperty(linkProp.c_str());
}
- else if(const char* libs =
- this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES"))
+ if(propertyLibs)
{
- cmSystemTools::ExpandListArgument(libs,
- info.LinkInterface.Libraries);
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ linkProp, 0, 0);
+ cmSystemTools::ExpandListArgument(ge.Parse(propertyLibs)
+ ->Evaluate(this->Makefile,
+ desired_config.c_str(),
+ false,
+ headTarget,
+ this,
+ &dagChecker),
+ info.LinkInterface.Libraries);
}
}
@@ -4475,12 +5460,13 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
}
//----------------------------------------------------------------------------
-cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config)
+cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config,
+ cmTarget *head)
{
// Imported targets have their own link interface.
if(this->IsImported())
{
- if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
+ if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head))
{
return &info->LinkInterface;
}
@@ -4496,14 +5482,15 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config)
}
// Lookup any existing link interface for this configuration.
- std::string key = cmSystemTools::UpperCase(config? config : "");
+ TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : ""));
+
cmTargetInternals::LinkInterfaceMapType::iterator
i = this->Internal->LinkInterfaceMap.find(key);
if(i == this->Internal->LinkInterfaceMap.end())
{
// Compute the link interface for this configuration.
cmTargetInternals::OptionalLinkInterface iface;
- iface.Exists = this->ComputeLinkInterface(config, iface);
+ iface.Exists = this->ComputeLinkInterface(config, iface, head);
// Store the information for this configuration.
cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface);
@@ -4514,7 +5501,8 @@ cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config)
}
//----------------------------------------------------------------------------
-bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
+bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
+ cmTarget *headTarget)
{
// Construct the property name suffix for this configuration.
std::string suffix = "_";
@@ -4530,18 +5518,20 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
// An explicit list of interface libraries may be set for shared
// libraries and executables that export symbols.
const char* explicitLibraries = 0;
+ std::string linkIfaceProp;
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
this->IsExecutableWithExports())
{
// Lookup the per-configuration property.
- std::string propName = "LINK_INTERFACE_LIBRARIES";
- propName += suffix;
- explicitLibraries = this->GetProperty(propName.c_str());
+ linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
+ linkIfaceProp += suffix;
+ explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
// If not set, try the generic property.
if(!explicitLibraries)
{
- explicitLibraries = this->GetProperty("LINK_INTERFACE_LIBRARIES");
+ linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
+ explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
}
}
@@ -4559,7 +5549,16 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
if(explicitLibraries)
{
// The interface libraries have been explicitly set.
- cmSystemTools::ExpandListArgument(explicitLibraries, iface.Libraries);
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
+ linkIfaceProp, 0, 0);
+ cmSystemTools::ExpandListArgument(ge.Parse(explicitLibraries)->Evaluate(
+ this->Makefile,
+ config,
+ false,
+ headTarget,
+ this, &dagChecker), iface.Libraries);
if(this->GetType() == cmTarget::SHARED_LIBRARY)
{
@@ -4571,7 +5570,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
{
emitted.insert(*li);
}
- LinkImplementation const* impl = this->GetLinkImplementation(config);
+ LinkImplementation const* impl = this->GetLinkImplementation(config,
+ headTarget);
for(std::vector<std::string>::const_iterator
li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li)
{
@@ -4599,7 +5599,9 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
else
{
// The link implementation is the default link interface.
- LinkImplementation const* impl = this->GetLinkImplementation(config);
+ LinkImplementation const* impl = this->GetLinkImplementation(config,
+ headTarget);
+ iface.ImplementationIsInterface = true;
iface.Libraries = impl->Libraries;
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
if(this->GetType() == cmTarget::STATIC_LIBRARY)
@@ -4631,7 +5633,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
//----------------------------------------------------------------------------
cmTarget::LinkImplementation const*
-cmTarget::GetLinkImplementation(const char* config)
+cmTarget::GetLinkImplementation(const char* config, cmTarget *head)
{
// There is no link implementation for imported targets.
if(this->IsImported())
@@ -4640,14 +5642,15 @@ cmTarget::GetLinkImplementation(const char* config)
}
// Lookup any existing link implementation for this configuration.
- std::string key = cmSystemTools::UpperCase(config? config : "");
+ TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : ""));
+
cmTargetInternals::LinkImplMapType::iterator
i = this->Internal->LinkImplMap.find(key);
if(i == this->Internal->LinkImplMap.end())
{
// Compute the link implementation for this configuration.
LinkImplementation impl;
- this->ComputeLinkImplementation(config, impl);
+ this->ComputeLinkImplementation(config, impl, head);
// Store the information for this configuration.
cmTargetInternals::LinkImplMapType::value_type entry(key, impl);
@@ -4659,30 +5662,39 @@ cmTarget::GetLinkImplementation(const char* config)
//----------------------------------------------------------------------------
void cmTarget::ComputeLinkImplementation(const char* config,
- LinkImplementation& impl)
+ LinkImplementation& impl,
+ cmTarget *head)
{
// Compute which library configuration to link.
cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
// Collect libraries directly linked in this configuration.
- LinkLibraryVectorType const& llibs = this->GetOriginalLinkLibraries();
- for(cmTarget::LinkLibraryVectorType::const_iterator li = llibs.begin();
+ std::vector<std::string> llibs;
+ this->GetDirectLinkLibraries(config, llibs, head);
+ for(std::vector<std::string>::const_iterator li = llibs.begin();
li != llibs.end(); ++li)
{
// Skip entries that resolve to the target itself or are empty.
- std::string item = this->CheckCMP0004(li->first);
+ std::string item = this->CheckCMP0004(*li);
if(item == this->GetName() || item.empty())
{
continue;
}
+ // The entry is meant for this configuration.
+ impl.Libraries.push_back(item);
+ }
- if(li->second == cmTarget::GENERAL || li->second == linkType)
- {
- // The entry is meant for this configuration.
- impl.Libraries.push_back(item);
- }
- else
+ LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries();
+ for(cmTarget::LinkLibraryVectorType::const_iterator li = oldllibs.begin();
+ li != oldllibs.end(); ++li)
+ {
+ if(li->second != cmTarget::GENERAL && li->second != linkType)
{
+ std::string item = this->CheckCMP0004(li->first);
+ if(item == this->GetName() || item.empty())
+ {
+ continue;
+ }
// Support OLD behavior for CMP0003.
impl.WrongConfigLibraries.push_back(item);
}
@@ -4771,6 +5783,158 @@ std::string cmTarget::CheckCMP0004(std::string const& item)
return lib;
}
+template<typename PropertyType>
+PropertyType getLinkInterfaceDependentProperty(cmTarget *tgt,
+ const std::string prop,
+ const char *config,
+ PropertyType *);
+
+template<>
+bool getLinkInterfaceDependentProperty(cmTarget *tgt,
+ const std::string prop,
+ const char *config, bool *)
+{
+ return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
+}
+
+template<>
+const char * getLinkInterfaceDependentProperty(cmTarget *tgt,
+ const std::string prop,
+ const char *config,
+ const char **)
+{
+ return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
+}
+
+//----------------------------------------------------------------------------
+template<typename PropertyType>
+void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee,
+ const char *propName,
+ std::set<cmStdString> &emitted,
+ const char *config,
+ PropertyType *)
+{
+ const char *prop = dependee->GetProperty(propName);
+ if (!prop)
+ {
+ return;
+ }
+
+ std::vector<std::string> props;
+ cmSystemTools::ExpandListArgument(prop, props);
+
+ for(std::vector<std::string>::iterator pi = props.begin();
+ pi != props.end(); ++pi)
+ {
+ if (depender->GetMakefile()->GetCMakeInstance()
+ ->GetIsPropertyDefined(pi->c_str(),
+ cmProperty::TARGET))
+ {
+ cmOStringStream e;
+ e << "Target \"" << dependee->GetName() << "\" has property \""
+ << *pi << "\" listed in its " << propName << " property. "
+ "This is not allowed. Only user-defined properties may appear "
+ "listed in the " << propName << " property.";
+ depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ }
+ if(emitted.insert(*pi).second)
+ {
+ getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config,
+ 0);
+ if (cmSystemTools::GetErrorOccuredFlag())
+ {
+ return;
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
+ const char* config)
+{
+ const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
+
+ std::set<cmStdString> emittedBools;
+ std::set<cmStdString> emittedStrings;
+
+ for(cmComputeLinkInformation::ItemVector::const_iterator li =
+ deps.begin();
+ li != deps.end(); ++li)
+ {
+ if (!li->Target)
+ {
+ continue;
+ }
+
+ checkPropertyConsistency<bool>(this, li->Target,
+ "COMPATIBLE_INTERFACE_BOOL",
+ emittedBools, config, 0);
+ if (cmSystemTools::GetErrorOccuredFlag())
+ {
+ return;
+ }
+ checkPropertyConsistency<const char *>(this, li->Target,
+ "COMPATIBLE_INTERFACE_STRING",
+ emittedStrings, config, 0);
+ if (cmSystemTools::GetErrorOccuredFlag())
+ {
+ return;
+ }
+ }
+
+ for(std::set<cmStdString>::const_iterator li = emittedBools.begin();
+ li != emittedBools.end(); ++li)
+ {
+ const std::set<cmStdString>::const_iterator si = emittedStrings.find(*li);
+ if (si != emittedStrings.end())
+ {
+ cmOStringStream e;
+ e << "Property \"" << *li << "\" appears in both the "
+ "COMPATIBLE_INTERFACE_BOOL and the COMPATIBLE_INTERFACE_STRING "
+ "property in the dependencies of target \"" << this->GetName() <<
+ "\". This is not allowed. A property may only require compatibility "
+ "in a boolean interpretation or a string interpretation, but not both.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ break;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+cmComputeLinkInformation*
+cmTarget::GetLinkInformation(const char* config, cmTarget *head)
+{
+ cmTarget *headTarget = head ? head : this;
+ // Lookup any existing information for this configuration.
+ TargetConfigPair key(headTarget,
+ cmSystemTools::UpperCase(config?config:""));
+ cmTargetLinkInformationMap::iterator
+ i = this->LinkInformation.find(key);
+ if(i == this->LinkInformation.end())
+ {
+ // Compute information for this configuration.
+ cmComputeLinkInformation* info =
+ new cmComputeLinkInformation(this, config, headTarget);
+ if(!info || !info->Compute())
+ {
+ delete info;
+ info = 0;
+ }
+
+ // Store the information for this configuration.
+ cmTargetLinkInformationMap::value_type entry(key, info);
+ i = this->LinkInformation.insert(entry).first;
+
+ if (info)
+ {
+ this->CheckPropertyCompatibility(info, config);
+ }
+ }
+ return i->second;
+}
+
//----------------------------------------------------------------------------
std::string cmTarget::GetFrameworkDirectory(const char* config)
{
@@ -4829,6 +5993,29 @@ std::string cmTarget::GetMacContentDirectory(const char* config,
}
//----------------------------------------------------------------------------
+cmTargetLinkInformationMap
+::cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r): derived()
+{
+ // Ideally cmTarget instances should never be copied. However until
+ // we can make a sweep to remove that, this copy constructor avoids
+ // allowing the resources (LinkInformation) from getting copied. In
+ // the worst case this will lead to extra cmComputeLinkInformation
+ // instances. We also enforce in debug mode that the map be emptied
+ // when copied.
+ static_cast<void>(r);
+ assert(r.empty());
+}
+
+//----------------------------------------------------------------------------
+cmTargetLinkInformationMap::~cmTargetLinkInformationMap()
+{
+ for(derived::iterator i = this->begin(); i != this->end(); ++i)
+ {
+ delete i->second;
+ }
+}
+
+//----------------------------------------------------------------------------
cmTargetInternalPointer::cmTargetInternalPointer()
{
this->Pointer = new cmTargetInternals;
@@ -4847,6 +6034,7 @@ cmTargetInternalPointer
//----------------------------------------------------------------------------
cmTargetInternalPointer::~cmTargetInternalPointer()
{
+ deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
delete this->Pointer;
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index e442d259a..9d467961b 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -15,6 +15,7 @@
#include "cmCustomCommand.h"
#include "cmPropertyMap.h"
#include "cmPolicies.h"
+#include "cmListFileCache.h"
#include <cmsys/auto_ptr.hxx>
@@ -22,7 +23,19 @@ class cmake;
class cmMakefile;
class cmSourceFile;
class cmGlobalGenerator;
+class cmComputeLinkInformation;
class cmListFileBacktrace;
+class cmTarget;
+
+struct cmTargetLinkInformationMap:
+ public std::map<std::pair<cmTarget*, std::string>, cmComputeLinkInformation*>
+{
+ typedef std::map<std::pair<cmTarget*, std::string>,
+ cmComputeLinkInformation*> derived;
+ cmTargetLinkInformationMap() {}
+ cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r);
+ ~cmTargetLinkInformationMap();
+};
class cmTargetInternals;
class cmTargetInternalPointer
@@ -89,6 +102,10 @@ public:
cmPolicies::PolicyStatus GetPolicyStatusCMP0008() const
{ return this->PolicyStatusCMP0008; }
+ /** Get the status of policy CMP0020 when the target was created. */
+ cmPolicies::PolicyStatus GetPolicyStatusCMP0020() const
+ { return this->PolicyStatusCMP0020; }
+
/**
* Get the list of the custom commands for this target
*/
@@ -99,9 +116,6 @@ public:
std::vector<cmCustomCommand> &GetPostBuildCommands()
{return this->PostBuildCommands;}
- ///! Return the list of frameworks being linked to this target
- std::vector<std::string> &GetFrameworks() {return this->Frameworks;}
-
/**
* Get the list of the source files used by this target
*/
@@ -158,6 +172,9 @@ public:
return this->LinkLibraries;}
const LinkLibraryVectorType &GetOriginalLinkLibraries() const
{return this->OriginalLinkLibraries;}
+ void GetDirectLinkLibraries(const char *config,
+ std::vector<std::string> &,
+ cmTarget *head);
/** Compute the link type to use for the given configuration. */
LinkLibraryType ComputeLinkType(const char* config);
@@ -169,7 +186,6 @@ public:
// Check to see if a library is a framework and treat it different on Mac
bool NameResolvesToFramework(const std::string& libname);
- bool AddFramework(const std::string& lib, LinkLibraryType llt);
void AddLinkLibrary(cmMakefile& mf,
const char *target, const char* lib,
LinkLibraryType llt);
@@ -246,12 +262,15 @@ public:
// Needed only for OLD behavior of CMP0003.
std::vector<std::string> WrongConfigLibraries;
- LinkInterface(): Multiplicity(0) {}
+ bool ImplementationIsInterface;
+
+ LinkInterface(): Multiplicity(0), ImplementationIsInterface(false) {}
};
/** Get the link interface for the given configuration. Returns 0
if the target cannot be linked. */
- LinkInterface const* GetLinkInterface(const char* config);
+ LinkInterface const* GetLinkInterface(const char* config,
+ cmTarget *headTarget);
/** The link implementation specifies the direct library
dependencies needed by the object files of the target. */
@@ -267,7 +286,8 @@ public:
// Needed only for OLD behavior of CMP0003.
std::vector<std::string> WrongConfigLibraries;
};
- LinkImplementation const* GetLinkImplementation(const char* config);
+ LinkImplementation const* GetLinkImplementation(const char* config,
+ cmTarget *head);
/** Link information from the transitive closure of the link
implementation and the interfaces of its dependencies. */
@@ -279,7 +299,7 @@ public:
// Languages whose runtime libraries must be linked.
std::vector<std::string> Languages;
};
- LinkClosure const* GetLinkClosure(const char* config);
+ LinkClosure const* GetLinkClosure(const char* config, cmTarget *head);
/** Strip off leading and trailing whitespace from an item named in
the link dependencies of this target. */
@@ -324,7 +344,7 @@ public:
bool FindSourceFiles();
///! Return the preferred linker language for this target
- const char* GetLinkerLanguage(const char* config = 0);
+ const char* GetLinkerLanguage(const char* config = 0, cmTarget *head = 0);
/** Get the full name of the target according to the settings in its
makefile. */
@@ -381,7 +401,7 @@ public:
*/
bool NeedRelinkBeforeInstall(const char* config);
- bool HaveBuildTreeRPATH();
+ bool HaveBuildTreeRPATH(const char *config);
bool HaveInstallTreeRPATH();
/** Return true if builtin chrpath will work for this target */
@@ -392,9 +412,17 @@ public:
std::string GetInstallNameDirForInstallTree(const char* config,
bool for_xcode = false);
+ cmComputeLinkInformation* GetLinkInformation(const char* config,
+ cmTarget *head = 0);
+
// Get the properties
cmPropertyMap &GetProperties() { return this->Properties; };
+ bool GetMappedConfig(std::string const& desired_config,
+ const char** loc,
+ const char** imp,
+ std::string& suffix);
+
// Define the properties
static void DefineProperties(cmake *cm);
@@ -402,6 +430,8 @@ public:
If no macro should be defined null is returned. */
const char* GetExportMacro();
+ std::string GetCompileDefinitions(const char *config);
+
// Compute the set of languages compiled by the target. This is
// computed every time it is called because the languages can change
// when source file properties are changed and we do not have enough
@@ -462,6 +492,26 @@ public:
/** @return the Mac framework directory without the base. */
std::string GetFrameworkDirectory(const char* config = 0);
+ std::vector<std::string> GetIncludeDirectories(const char *config);
+ void InsertInclude(const cmValueWithOrigin &entry,
+ bool before = false);
+
+ void AppendBuildInterfaceIncludes();
+
+ bool IsNullImpliedByLinkLibraries(const std::string &p);
+ bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
+ const char *config);
+ bool IsLinkInterfaceDependentStringProperty(const std::string &p,
+ const char *config);
+
+ bool GetLinkInterfaceDependentBoolProperty(const std::string &p,
+ const char *config);
+
+ const char *GetLinkInterfaceDependentStringProperty(const std::string &p,
+ const char *config);
+
+ std::string GetDebugGeneratorExpressions(const std::string &value,
+ cmTarget::LinkLibraryType llt);
private:
/**
* A list of direct dependencies. Use in conjunction with DependencyMap.
@@ -557,7 +607,6 @@ private:
LinkLibraryVectorType LinkLibraries;
LinkLibraryVectorType PrevLinkedLibraries;
bool LinkLibrariesAnalyzed;
- std::vector<std::string> Frameworks;
std::vector<std::string> LinkDirectories;
std::set<cmStdString> LinkDirectoriesEmmitted;
bool HaveInstallRule;
@@ -572,6 +621,9 @@ private:
bool DLLPlatform;
bool IsApple;
bool IsImportedTarget;
+ bool DebugIncludesDone;
+ mutable std::set<std::string> LinkImplicitNullProperties;
+ bool BuildInterfaceIncludesAppended;
// Cache target output paths for each configuration.
struct OutputInfo;
@@ -581,14 +633,21 @@ private:
// Cache import information from properties for each configuration.
struct ImportInfo;
- ImportInfo const* GetImportInfo(const char* config);
- void ComputeImportInfo(std::string const& desired_config, ImportInfo& info);
+ ImportInfo const* GetImportInfo(const char* config,
+ cmTarget *workingTarget);
+ void ComputeImportInfo(std::string const& desired_config, ImportInfo& info,
+ cmTarget *head);
+
+ cmTargetLinkInformationMap LinkInformation;
+ void CheckPropertyCompatibility(cmComputeLinkInformation *info,
+ const char* config);
- bool ComputeLinkInterface(const char* config, LinkInterface& iface);
+ bool ComputeLinkInterface(const char* config, LinkInterface& iface,
+ cmTarget *head);
void ComputeLinkImplementation(const char* config,
- LinkImplementation& impl);
- void ComputeLinkClosure(const char* config, LinkClosure& lc);
+ LinkImplementation& impl, cmTarget *head);
+ void ComputeLinkClosure(const char* config, LinkClosure& lc, cmTarget *head);
void ClearLinkMaps();
@@ -604,6 +663,7 @@ private:
cmPolicies::PolicyStatus PolicyStatusCMP0003;
cmPolicies::PolicyStatus PolicyStatusCMP0004;
cmPolicies::PolicyStatus PolicyStatusCMP0008;
+ cmPolicies::PolicyStatus PolicyStatusCMP0020;
// Internal representation details.
friend class cmTargetInternals;
diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
new file mode 100644
index 000000000..ba0ad5986
--- /dev/null
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -0,0 +1,66 @@
+/*============================================================================
+ 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 "cmTargetCompileDefinitionsCommand.h"
+
+bool cmTargetCompileDefinitionsCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+ return this->HandleArguments(args, "COMPILE_DEFINITIONS");
+}
+
+void cmTargetCompileDefinitionsCommand
+::HandleImportedTarget(const std::string &tgt)
+{
+ cmOStringStream e;
+ e << "Cannot specify compile definitions for imported target \""
+ << tgt << "\".";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+void cmTargetCompileDefinitionsCommand
+::HandleMissingTarget(const std::string &name)
+{
+ cmOStringStream e;
+ e << "Cannot specify compile definitions for target \"" << name << "\" "
+ "which is not built by this project.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
+std::string cmTargetCompileDefinitionsCommand
+::Join(const std::vector<std::string> &content)
+{
+ std::string defs;
+ std::string sep;
+ for(std::vector<std::string>::const_iterator it = content.begin();
+ it != content.end(); ++it)
+ {
+ if (strncmp(it->c_str(), "-D", 2) == 0)
+ {
+ defs += sep + it->substr(2);
+ }
+ else
+ {
+ defs += sep + *it;
+ }
+ sep = ";";
+ }
+ return defs;
+}
+
+//----------------------------------------------------------------------------
+void cmTargetCompileDefinitionsCommand
+::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
+ bool)
+{
+ tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
+}
diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h
new file mode 100644
index 000000000..ec9b071db
--- /dev/null
+++ b/Source/cmTargetCompileDefinitionsCommand.h
@@ -0,0 +1,88 @@
+/*============================================================================
+ 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 cmTargetCompileDefinitionsCommand_h
+#define cmTargetCompileDefinitionsCommand_h
+
+#include "cmTargetPropCommandBase.h"
+
+class cmTargetCompileDefinitionsCommand : public cmTargetPropCommandBase
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ virtual cmCommand* Clone()
+ {
+ return new cmTargetCompileDefinitionsCommand;
+ }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ virtual bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus &status);
+
+ /**
+ * The name of the command as specified in CMakeList.txt.
+ */
+ virtual const char* GetName() const { return "target_compile_definitions";}
+
+ /**
+ * Succinct documentation.
+ */
+ virtual const char* GetTerseDocumentation() const
+ {
+ return
+ "Add compile definitions to a target.";
+ }
+
+ /**
+ * More documentation.
+ */
+ virtual const char* GetFullDocumentation() const
+ {
+ return
+ " target_compile_definitions(<target> "
+ "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
+ " [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
+ "Specify compile definitions to use when compiling a given target. "
+ "The named <target> must have been created by a command such as "
+ "add_executable or add_library and must not be an IMPORTED target. "
+ "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
+ "the scope of the following arguments. PRIVATE and PUBLIC items will "
+ "populate the COMPILE_DEFINITIONS property of <target>. PUBLIC and "
+ "INTERFACE items will populate the INTERFACE_COMPILE_DEFINITIONS "
+ "property of <target>. "
+ "The following arguments specify compile definitions. "
+ "Repeated calls for the same <target> append items in the order called."
+ "\n"
+ "Arguments to target_compile_definitions may use \"generator "
+ "expressions\" with the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ ;
+ }
+
+ cmTypeMacro(cmTargetCompileDefinitionsCommand, cmTargetPropCommandBase);
+
+private:
+ virtual void HandleImportedTarget(const std::string &tgt);
+ virtual void HandleMissingTarget(const std::string &name);
+
+ virtual void HandleDirectContent(cmTarget *tgt,
+ const std::vector<std::string> &content,
+ bool prepend);
+ virtual std::string Join(const std::vector<std::string> &content);
+};
+
+#endif
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
new file mode 100644
index 000000000..12d0a515f
--- /dev/null
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -0,0 +1,74 @@
+/*============================================================================
+ 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 "cmTargetIncludeDirectoriesCommand.h"
+
+//----------------------------------------------------------------------------
+bool cmTargetIncludeDirectoriesCommand
+::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
+{
+ return this->HandleArguments(args, "INCLUDE_DIRECTORIES", PROCESS_BEFORE);
+}
+
+//----------------------------------------------------------------------------
+void cmTargetIncludeDirectoriesCommand
+::HandleImportedTarget(const std::string &tgt)
+{
+ cmOStringStream e;
+ e << "Cannot specify include directories for imported target \""
+ << tgt << "\".";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
+void cmTargetIncludeDirectoriesCommand
+::HandleMissingTarget(const std::string &name)
+{
+ cmOStringStream e;
+ e << "Cannot specify include directories for target \"" << name << "\" "
+ "which is not built by this project.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+}
+
+//----------------------------------------------------------------------------
+std::string cmTargetIncludeDirectoriesCommand
+::Join(const std::vector<std::string> &content)
+{
+ std::string dirs;
+ std::string sep;
+ std::string prefix = this->Makefile->GetStartDirectory() + std::string("/");
+ for(std::vector<std::string>::const_iterator it = content.begin();
+ it != content.end(); ++it)
+ {
+ if (cmSystemTools::FileIsFullPath(it->c_str())
+ || cmGeneratorExpression::Find(*it) != std::string::npos)
+ {
+ dirs += sep + *it;
+ }
+ else
+ {
+ dirs += sep + prefix + *it;
+ }
+ sep = ";";
+ }
+ return dirs;
+}
+
+//----------------------------------------------------------------------------
+void cmTargetIncludeDirectoriesCommand
+::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
+ bool prepend)
+{
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmValueWithOrigin entry(this->Join(content), lfbt);
+ tgt->InsertInclude(entry, prepend);
+}
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
new file mode 100644
index 000000000..e4bc9cf67
--- /dev/null
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -0,0 +1,93 @@
+/*============================================================================
+ 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 cmTargetIncludeDirectoriesCommand_h
+#define cmTargetIncludeDirectoriesCommand_h
+
+#include "cmTargetPropCommandBase.h"
+
+//----------------------------------------------------------------------------
+class cmTargetIncludeDirectoriesCommand : public cmTargetPropCommandBase
+{
+public:
+ /**
+ * This is a virtual constructor for the command.
+ */
+ virtual cmCommand* Clone()
+ {
+ return new cmTargetIncludeDirectoriesCommand;
+ }
+
+ /**
+ * This is called when the command is first encountered in
+ * the CMakeLists.txt file.
+ */
+ virtual bool InitialPass(std::vector<std::string> const& args,
+ cmExecutionStatus &status);
+
+ /**
+ * The name of the command as specified in CMakeList.txt.
+ */
+ virtual const char* GetName() const { return "target_include_directories";}
+
+ /**
+ * Succinct documentation.
+ */
+ virtual const char* GetTerseDocumentation() const
+ {
+ return
+ "Add include directories to a target.";
+ }
+
+ /**
+ * More documentation.
+ */
+ virtual const char* GetFullDocumentation() const
+ {
+ return
+ " target_include_directories(<target> [BEFORE] "
+ "<INTERFACE|PUBLIC|PRIVATE> [items1...]\n"
+ " [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])\n"
+ "Specify include directories or targets to use when compiling a given "
+ "target. "
+ "The named <target> must have been created by a command such as "
+ "add_executable or add_library and must not be an IMPORTED target.\n"
+ "If BEFORE is specified, the content will be prepended to the property "
+ "instead of being appended.\n"
+ "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
+ "the scope of the following arguments. PRIVATE and PUBLIC items will "
+ "populate the INCLUDE_DIRECTORIES property of <target>. PUBLIC and "
+ "INTERFACE items will populate the INTERFACE_INCLUDE_DIRECTORIES "
+ "property of <target>. "
+ "The following arguments specify include directories. Specified "
+ "include directories may be absolute paths or relative paths. "
+ "Repeated calls for the same <target> append items in the order called."
+ "\n"
+ "Arguments to target_include_directories may use \"generator "
+ "expressions\" with the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ ;
+ }
+
+ cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmTargetPropCommandBase);
+
+private:
+ virtual void HandleImportedTarget(const std::string &tgt);
+ virtual void HandleMissingTarget(const std::string &name);
+
+ virtual void HandleDirectContent(cmTarget *tgt,
+ const std::vector<std::string> &content,
+ bool prepend);
+ virtual std::string Join(const std::vector<std::string> &content);
+};
+
+#endif
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index f42b0f687..b7b7691c8 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -11,6 +11,8 @@
============================================================================*/
#include "cmTargetLinkLibrariesCommand.h"
+#include "cmGeneratorExpression.h"
+
const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] =
{
"general",
diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h
index 63114d209..c683016dd 100644
--- a/Source/cmTargetLinkLibrariesCommand.h
+++ b/Source/cmTargetLinkLibrariesCommand.h
@@ -13,6 +13,7 @@
#define cmTargetLinkLibrariesCommand_h
#include "cmCommand.h"
+#include "cmDocumentGeneratorExpressions.h"
/** \class cmTargetLinkLibrariesCommand
* \brief Specify a list of libraries to link into executables.
@@ -92,7 +93,21 @@ public:
"linked to this target will appear on the link line for the other "
"target too. "
"See the LINK_INTERFACE_LIBRARIES target property to override the "
- "set of transitive link dependencies for a target."
+ "set of transitive link dependencies for a target. "
+ "Calls to other signatures of this command may set the property "
+ "making any libraries linked exclusively by this signature private."
+ "\n"
+ "CMake will also propagate \"usage requirements\" from linked library "
+ "targets. "
+ "Usage requirements affect compilation of sources in the <target>. "
+ "They are specified by properties defined on linked targets. "
+ "During generation of the build system, CMake integrates "
+ "usage requirement property values with the corresponding "
+ "build properties for <target>:\n"
+ " INTERFACE_COMPILE_DEFINITONS: Appends to COMPILE_DEFINITONS\n"
+ " INTERFACE_INCLUDE_DIRECTORIES: Appends to INCLUDE_DIRECTORIES\n"
+ " INTERFACE_POSITION_INDEPENDENT_CODE: Sets POSITION_INDEPENDENT_CODE\n"
+ " or checked for consistency with existing value\n"
"\n"
" target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n"
" [[debug|optimized|general] <lib>] ...)\n"
@@ -100,11 +115,11 @@ public:
"to the LINK_INTERFACE_LIBRARIES and its per-configuration equivalent "
"target properties instead of using them for linking. "
"Libraries specified as \"debug\" are appended to the "
- "the LINK_INTERFACE_LIBRARIES_DEBUG property (or to the properties "
+ "LINK_INTERFACE_LIBRARIES_DEBUG property (or to the properties "
"corresponding to configurations listed in the DEBUG_CONFIGURATIONS "
"global property if it is set). "
"Libraries specified as \"optimized\" are appended to the "
- "the LINK_INTERFACE_LIBRARIES property. "
+ "LINK_INTERFACE_LIBRARIES property. "
"Libraries specified as \"general\" (or without any keyword) are "
"treated as if specified for both \"debug\" and \"optimized\"."
"\n"
@@ -141,6 +156,12 @@ public:
"However, if two archives are really so interdependent they should "
"probably be combined into a single archive."
")"
+ "\n"
+ "Arguments to target_link_libraries may use \"generator expressions\" "
+ "with the syntax \"$<...>\". Note however, that generator expressions "
+ "will not be used in OLD handling of CMP0003 or CMP0004."
+ "\n"
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
;
}
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
new file mode 100644
index 000000000..771097ca2
--- /dev/null
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -0,0 +1,144 @@
+/*============================================================================
+ 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 "cmTargetPropCommandBase.h"
+
+#include "cmGlobalGenerator.h"
+
+//----------------------------------------------------------------------------
+bool cmTargetPropCommandBase
+::HandleArguments(std::vector<std::string> const& args, const char *prop,
+ ArgumentFlags flags)
+{
+ if(args.size() < 3)
+ {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+
+ // Lookup the target for which libraries are specified.
+ this->Target =
+ this->Makefile->GetCMakeInstance()
+ ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
+ if(!this->Target)
+ {
+ this->Target = this->Makefile->FindTargetToUse(args[0].c_str());
+ }
+ if(!this->Target)
+ {
+ this->HandleMissingTarget(args[0]);
+ return false;
+ }
+ if ((this->Target->GetType() != cmTarget::SHARED_LIBRARY)
+ && (this->Target->GetType() != cmTarget::STATIC_LIBRARY)
+ && (this->Target->GetType() != cmTarget::OBJECT_LIBRARY)
+ && (this->Target->GetType() != cmTarget::MODULE_LIBRARY)
+ && (this->Target->GetType() != cmTarget::EXECUTABLE))
+ {
+ this->SetError("called with non-compilable target type");
+ return false;
+ }
+
+ unsigned int argIndex = 1;
+
+ bool prepend = false;
+ if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE")
+ {
+ if (args.size() < 4)
+ {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+ prepend = true;
+ ++argIndex;
+ }
+
+ this->Property = prop;
+
+ while (argIndex < args.size())
+ {
+ if (!this->ProcessContentArgs(args, argIndex, prepend))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+bool cmTargetPropCommandBase
+::ProcessContentArgs(std::vector<std::string> const& args,
+ unsigned int &argIndex, bool prepend)
+{
+ const std::string scope = args[argIndex];
+
+ if(scope != "PUBLIC"
+ && scope != "PRIVATE"
+ && scope != "INTERFACE" )
+ {
+ this->SetError("called with invalid arguments");
+ return false;
+ }
+
+ if(this->Target->IsImported())
+ {
+ this->HandleImportedTarget(args[0]);
+ return false;
+ }
+
+ ++argIndex;
+
+ std::vector<std::string> content;
+
+ for(unsigned int i=argIndex; i < args.size(); ++i, ++argIndex)
+ {
+ if(args[i] == "PUBLIC"
+ || args[i] == "PRIVATE"
+ || args[i] == "INTERFACE" )
+ {
+ this->PopulateTargetProperies(scope, content, prepend);
+ return true;
+ }
+ content.push_back(args[i]);
+ }
+ this->PopulateTargetProperies(scope, content, prepend);
+ return true;
+}
+
+//----------------------------------------------------------------------------
+void cmTargetPropCommandBase
+::PopulateTargetProperies(const std::string &scope,
+ const std::vector<std::string> &content,
+ bool prepend)
+{
+ if (scope == "PRIVATE" || scope == "PUBLIC")
+ {
+ this->HandleDirectContent(this->Target, content, prepend);
+ }
+ if (scope == "INTERFACE" || scope == "PUBLIC")
+ {
+ if (prepend)
+ {
+ const std::string propName = std::string("INTERFACE_") + this->Property;
+ const char *propValue = this->Target->GetProperty(propName.c_str());
+ const std::string totalContent = this->Join(content) + (propValue
+ ? std::string(";") + propValue
+ : std::string());
+ this->Target->SetProperty(propName.c_str(), totalContent.c_str());
+ }
+ else
+ {
+ this->Target->AppendProperty(("INTERFACE_" + this->Property).c_str(),
+ this->Join(content).c_str());
+ }
+ }
+}
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
new file mode 100644
index 000000000..8047a48aa
--- /dev/null
+++ b/Source/cmTargetPropCommandBase.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 cmTargetPropCommandBase_h
+#define cmTargetPropCommandBase_h
+
+#include "cmCommand.h"
+#include "cmDocumentGeneratorExpressions.h"
+
+class cmTarget;
+
+//----------------------------------------------------------------------------
+class cmTargetPropCommandBase : public cmCommand
+{
+public:
+
+ enum ArgumentFlags {
+ NO_FLAGS = 0,
+ PROCESS_BEFORE = 1
+ };
+
+ bool HandleArguments(std::vector<std::string> const& args,
+ const char *prop, ArgumentFlags flags = NO_FLAGS);
+
+ cmTypeMacro(cmTargetPropCommandBase, cmCommand);
+protected:
+ std::string Property;
+ cmTarget *Target;
+
+private:
+ virtual void HandleImportedTarget(const std::string &tgt) = 0;
+ virtual void HandleMissingTarget(const std::string &name) = 0;
+
+ virtual void HandleDirectContent(cmTarget *tgt,
+ const std::vector<std::string> &content,
+ bool prepend) = 0;
+ virtual std::string Join(const std::vector<std::string> &content) = 0;
+
+ bool ProcessContentArgs(std::vector<std::string> const& args,
+ unsigned int &argIndex, bool prepend);
+ void PopulateTargetProperies(const std::string &scope,
+ const std::vector<std::string> &content,
+ bool prepend);
+};
+
+#endif
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 2f650e72e..42f511ea3 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -112,7 +112,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
else
{
// Use the command name given.
- exe = ge.Parse(exe.c_str()).Evaluate(mf, config);
+ exe = ge.Parse(exe.c_str())->Evaluate(mf, config);
cmSystemTools::ConvertToUnixSlashes(exe);
}
@@ -122,7 +122,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
for(std::vector<std::string>::const_iterator ci = command.begin()+1;
ci != command.end(); ++ci)
{
- os << " " << lg->EscapeForCMake(ge.Parse(*ci).Evaluate(mf, config));
+ os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config));
}
// Finish the test command.
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
new file mode 100644
index 000000000..ac26503c6
--- /dev/null
+++ b/Source/cmTimestamp.cxx
@@ -0,0 +1,134 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 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 "cmTimestamp.h"
+
+#include <cstring>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+//----------------------------------------------------------------------------
+std::string cmTimestamp::CurrentTime(
+ const std::string& formatString, bool utcFlag)
+{
+ time_t currentTimeT = time(0);
+ if(currentTimeT == time_t(-1))
+ {
+ return std::string();
+ }
+
+ return CreateTimestampFromTimeT(currentTimeT, formatString, utcFlag);
+}
+
+//----------------------------------------------------------------------------
+std::string cmTimestamp::FileModificationTime(const char* path,
+ const std::string& formatString, bool utcFlag)
+{
+ struct stat info;
+ memset(&info, 0, sizeof(info));
+
+ if(stat(path, &info) != 0)
+ {
+ return std::string();
+ }
+
+ return CreateTimestampFromTimeT(info.st_mtime, formatString, utcFlag);
+}
+
+//----------------------------------------------------------------------------
+std::string cmTimestamp::CreateTimestampFromTimeT(time_t timeT,
+ std::string formatString, bool utcFlag)
+{
+ if(formatString.empty())
+ {
+ formatString = "%Y-%m-%dT%H:%M:%S";
+ if(utcFlag)
+ {
+ formatString += "Z";
+ }
+ }
+
+ struct tm timeStruct;
+ memset(&timeStruct, 0, sizeof(timeStruct));
+
+ struct tm* ptr = (struct tm*) 0;
+ if(utcFlag)
+ {
+ ptr = gmtime(&timeT);
+ }
+ else
+ {
+ ptr = localtime(&timeT);
+ }
+
+ if(ptr == 0)
+ {
+ return std::string();
+ }
+
+ timeStruct = *ptr;
+
+ std::string result;
+ for(std::string::size_type i = 0; i < formatString.size(); ++i)
+ {
+ char c1 = formatString[i];
+ char c2 = (i+1 < formatString.size()) ?
+ formatString[i+1] : static_cast<char>(0);
+
+ if(c1 == '%' && c2 != 0)
+ {
+ result += AddTimestampComponent(c2, timeStruct);
+ ++i;
+ }
+ else
+ {
+ result += c1;
+ }
+ }
+
+ return result;
+}
+
+//----------------------------------------------------------------------------
+std::string cmTimestamp::AddTimestampComponent(
+ char flag, struct tm& timeStruct)
+{
+ std::string formatString = "%";
+ formatString += flag;
+
+ switch(flag)
+ {
+ case 'd':
+ case 'H':
+ case 'I':
+ case 'j':
+ case 'm':
+ case 'M':
+ case 'S':
+ case 'U':
+ case 'w':
+ case 'y':
+ case 'Y':
+ break;
+ default:
+ {
+ return formatString;
+ }
+ }
+
+ char buffer[16];
+
+ size_t size = strftime(buffer, sizeof(buffer),
+ formatString.c_str(), &timeStruct);
+
+ return std::string(buffer, size);
+}
diff --git a/Source/cmTimestamp.h b/Source/cmTimestamp.h
new file mode 100644
index 000000000..24c186983
--- /dev/null
+++ b/Source/cmTimestamp.h
@@ -0,0 +1,40 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 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 cmTimestamp_h
+#define cmTimestamp_h
+
+#include <string>
+#include <time.h>
+
+/** \class cmTimestamp
+ * \brief Utility class to generate sting representation of a timestamp
+ *
+ */
+class cmTimestamp
+{
+public:
+ cmTimestamp() {}
+
+ std::string CurrentTime(const std::string& formatString, bool utcFlag);
+
+ std::string FileModificationTime(const char* path,
+ const std::string& formatString, bool utcFlag);
+
+private:
+ std::string CreateTimestampFromTimeT(time_t timeT,
+ std::string formatString, bool utcFlag);
+
+ std::string AddTimestampComponent(char flag, struct tm& timeStruct);
+};
+
+
+#endif
diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h
index 68ec666ec..6caa130ce 100644
--- a/Source/cmTryCompileCommand.h
+++ b/Source/cmTryCompileCommand.h
@@ -67,6 +67,7 @@ public:
" try_compile(RESULT_VAR <bindir> <srcfile>\n"
" [CMAKE_FLAGS flags...]\n"
" [COMPILE_DEFINITIONS flags...]\n"
+ " [LINK_LIBRARIES libs...]\n"
" [OUTPUT_VARIABLE <var>]\n"
" [COPY_FILE <fileName>])\n"
"Try building a source file into an executable. "
@@ -90,7 +91,12 @@ public:
"Some extra flags that can be included are, "
"INCLUDE_DIRECTORIES, LINK_DIRECTORIES, and LINK_LIBRARIES. "
"COMPILE_DEFINITIONS are -Ddefinition that will be passed to the "
- "compile line. "
+ "compile line.\n"
+ "The srcfile signature also accepts a LINK_LIBRARIES argument which "
+ "may contain a list of libraries or IMPORTED targets which will be "
+ "linked to in the generated project. If LINK_LIBRARIES is specified "
+ "as a parameter to try_compile, then any LINK_LIBRARIES passed as "
+ "CMAKE_FLAGS will be ignored.\n"
"try_compile creates a CMakeList.txt "
"file on the fly that looks like this:\n"
" add_definitions( <expanded COMPILE_DEFINITIONS from calling "
diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h
index 7878729d9..13b997307 100644
--- a/Source/cmTryRunCommand.h
+++ b/Source/cmTryRunCommand.h
@@ -81,7 +81,7 @@ public:
"the executable, but it will not try to run the executable. Instead it "
"will create cache variables which must be filled by the user or by "
"presetting them in some CMake script file to the values the "
- "executable would have produced if it would have been run on its actual "
+ "executable would have produced if it had been run on its actual "
"target platform. These variables are RUN_RESULT_VAR (explanation see "
"above) and if RUN_OUTPUT_VARIABLE (or OUTPUT_VARIABLE) was used, an "
"additional cache variable "
diff --git a/Source/cmVS10LinkFlagTable.h b/Source/cmVS10LinkFlagTable.h
index c60e8eb20..64febbb52 100644
--- a/Source/cmVS10LinkFlagTable.h
+++ b/Source/cmVS10LinkFlagTable.h
@@ -182,8 +182,8 @@ static cmVS7FlagTable cmVS10LinkFlagTable[] =
{"SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0},
{"SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0},
{"Profile", "PROFILE", "", "true", 0},
- {"DelaySign", "DELAYSIGN:NO", "", "false", 0},
- {"DelaySign", "DELAYSIGN", "", "true", 0},
+ {"LinkDelaySign", "DELAYSIGN:NO", "", "false", 0},
+ {"LinkDelaySign", "DELAYSIGN", "", "true", 0},
{"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0},
{"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0},
{"ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0},
@@ -294,7 +294,7 @@ static cmVS7FlagTable cmVS10LinkFlagTable[] =
{"MergeSections", "MERGE:",
"Merge Sections",
"", cmVS7FlagTable::UserValue},
- {"KeyFile", "KEYFILE:",
+ {"LinkKeyFile", "KEYFILE:",
"Key File",
"", cmVS7FlagTable::UserValue},
{"KeyContainer", "KEYCONTAINER:",
diff --git a/Source/cmVS12CLFlagTable.h b/Source/cmVS12CLFlagTable.h
new file mode 100644
index 000000000..8f5131989
--- /dev/null
+++ b/Source/cmVS12CLFlagTable.h
@@ -0,0 +1,297 @@
+static cmVS7FlagTable cmVS12CLFlagTable[] =
+{
+
+ //Enum Properties
+ {"DebugInformationFormat", "",
+ "None", "None", 0},
+ {"DebugInformationFormat", "Z7",
+ "C7 compatible", "OldStyle", 0},
+ {"DebugInformationFormat", "Zi",
+ "Program Database", "ProgramDatabase", 0},
+ {"DebugInformationFormat", "ZI",
+ "Program Database for Edit And Continue", "EditAndContinue", 0},
+
+ {"WarningLevel", "W0",
+ "Turn Off All Warnings", "TurnOffAllWarnings", 0},
+ {"WarningLevel", "W1",
+ "Level1", "Level1", 0},
+ {"WarningLevel", "W2",
+ "Level2", "Level2", 0},
+ {"WarningLevel", "W3",
+ "Level3", "Level3", 0},
+ {"WarningLevel", "W4",
+ "Level4", "Level4", 0},
+ {"WarningLevel", "Wall",
+ "EnableAllWarnings", "EnableAllWarnings", 0},
+
+ {"Optimization", "",
+ "Custom", "Custom", 0},
+ {"Optimization", "Od",
+ "Disabled", "Disabled", 0},
+ {"Optimization", "O1",
+ "Minimize Size", "MinSpace", 0},
+ {"Optimization", "O2",
+ "Maximize Speed", "MaxSpeed", 0},
+ {"Optimization", "Ox",
+ "Full Optimization", "Full", 0},
+
+ {"InlineFunctionExpansion", "",
+ "Default", "Default", 0},
+ {"InlineFunctionExpansion", "Ob0",
+ "Disabled", "Disabled", 0},
+ {"InlineFunctionExpansion", "Ob1",
+ "Only __inline", "OnlyExplicitInline", 0},
+ {"InlineFunctionExpansion", "Ob2",
+ "Any Suitable", "AnySuitable", 0},
+
+ {"FavorSizeOrSpeed", "Os",
+ "Favor small code", "Size", 0},
+ {"FavorSizeOrSpeed", "Ot",
+ "Favor fast code", "Speed", 0},
+ {"FavorSizeOrSpeed", "",
+ "Neither", "Neither", 0},
+
+ {"ExceptionHandling", "EHa",
+ "Yes with SEH Exceptions", "Async", 0},
+ {"ExceptionHandling", "EHsc",
+ "Yes", "Sync", 0},
+ {"ExceptionHandling", "EHs",
+ "Yes with Extern C functions", "SyncCThrow", 0},
+ {"ExceptionHandling", "",
+ "No", "false", 0},
+
+ {"BasicRuntimeChecks", "RTCs",
+ "Stack Frames", "StackFrameRuntimeCheck", 0},
+ {"BasicRuntimeChecks", "RTCu",
+ "Uninitialized variables", "UninitializedLocalUsageCheck", 0},
+ {"BasicRuntimeChecks", "RTC1",
+ "Both (/RTC1, equiv. to /RTCsu)", "EnableFastChecks", 0},
+ {"BasicRuntimeChecks", "",
+ "Default", "Default", 0},
+
+ {"RuntimeLibrary", "MT",
+ "Multi-threaded", "MultiThreaded", 0},
+ {"RuntimeLibrary", "MTd",
+ "Multi-threaded Debug", "MultiThreadedDebug", 0},
+ {"RuntimeLibrary", "MD",
+ "Multi-threaded DLL", "MultiThreadedDLL", 0},
+ {"RuntimeLibrary", "MDd",
+ "Multi-threaded Debug DLL", "MultiThreadedDebugDLL", 0},
+
+ {"StructMemberAlignment", "Zp1",
+ "1 Byte", "1Byte", 0},
+ {"StructMemberAlignment", "Zp2",
+ "2 Bytes", "2Bytes", 0},
+ {"StructMemberAlignment", "Zp4",
+ "4 Byte", "4Bytes", 0},
+ {"StructMemberAlignment", "Zp8",
+ "8 Bytes", "8Bytes", 0},
+ {"StructMemberAlignment", "Zp16",
+ "16 Bytes", "16Bytes", 0},
+ {"StructMemberAlignment", "",
+ "Default", "Default", 0},
+
+ {"BufferSecurityCheck", "GS-",
+ "Disable Security Check", "false", 0},
+ {"BufferSecurityCheck", "GS",
+ "Enable Security Check", "true", 0},
+
+ {"EnableEnhancedInstructionSet", "arch:SSE",
+ "Streaming SIMD Extensions", "StreamingSIMDExtensions", 0},
+ {"EnableEnhancedInstructionSet", "arch:SSE2",
+ "Streaming SIMD Extensions 2", "StreamingSIMDExtensions2", 0},
+ {"EnableEnhancedInstructionSet", "arch:AVX",
+ "Advanced Vector Extensions", "AdvancedVectorExtensions", 0},
+ {"EnableEnhancedInstructionSet", "arch:IA32",
+ "No Enhanced Instructions", "NoExtensions", 0},
+ {"EnableEnhancedInstructionSet", "",
+ "Not Set", "NotSet", 0},
+
+ {"FloatingPointModel", "fp:precise",
+ "Precise", "Precise", 0},
+ {"FloatingPointModel", "fp:strict",
+ "Strict", "Strict", 0},
+ {"FloatingPointModel", "fp:fast",
+ "Fast", "Fast", 0},
+
+ {"PrecompiledHeader", "Yc",
+ "Create", "Create",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
+ {"PrecompiledHeader", "Yu",
+ "Use", "Use",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
+ {"PrecompiledHeader", "",
+ "Not Using Precompiled Headers", "NotUsing", 0},
+
+ {"AssemblerOutput", "",
+ "No Listing", "NoListing", 0},
+ {"AssemblerOutput", "FA",
+ "Assembly-Only Listing", "AssemblyCode", 0},
+ {"AssemblerOutput", "FAc",
+ "Assembly With Machine Code", "AssemblyAndMachineCode", 0},
+ {"AssemblerOutput", "FAs",
+ "Assembly With Source Code", "AssemblyAndSourceCode", 0},
+ {"AssemblerOutput", "FAcs",
+ "Assembly, Machine Code and Source", "All", 0},
+
+ {"CallingConvention", "Gd",
+ "__cdecl", "Cdecl", 0},
+ {"CallingConvention", "Gr",
+ "__fastcall", "FastCall", 0},
+ {"CallingConvention", "Gz",
+ "__stdcall", "StdCall", 0},
+ {"CallingConvention", "Gv",
+ "__vectorcall", "VectorCall", 0},
+
+ {"CompileAs", "",
+ "Default", "Default", 0},
+ {"CompileAs", "TC",
+ "Compile as C Code", "CompileAsC", 0},
+ {"CompileAs", "TP",
+ "Compile as C++ Code", "CompileAsCpp", 0},
+
+ {"ErrorReporting", "errorReport:none",
+ "Do Not Send Report", "None", 0},
+ {"ErrorReporting", "errorReport:prompt",
+ "Prompt Immediately", "Prompt", 0},
+ {"ErrorReporting", "errorReport:queue",
+ "Queue For Next Login", "Queue", 0},
+ {"ErrorReporting", "errorReport:send",
+ "Send Automatically", "Send", 0},
+
+ {"CompileAsManaged", "",
+ "No Common Language RunTime Support", "false", 0},
+ {"CompileAsManaged", "clr",
+ "Common Language RunTime Support", "true", 0},
+ {"CompileAsManaged", "clr:pure",
+ "Pure MSIL Common Language RunTime Support", "Pure", 0},
+ {"CompileAsManaged", "clr:safe",
+ "Safe MSIL Common Language RunTime Support", "Safe", 0},
+ {"CompileAsManaged", "clr:oldSyntax",
+ "Common Language RunTime Support, Old Syntax", "OldSyntax", 0},
+
+
+ //Bool Properties
+ {"CompileAsWinRT", "ZW", "", "true", 0},
+ {"WinRTNoStdLib", "ZW:nostdlib", "", "true", 0},
+ {"SuppressStartupBanner", "nologo", "", "true", 0},
+ {"TreatWarningAsError", "WX-", "", "false", 0},
+ {"TreatWarningAsError", "WX", "", "true", 0},
+ {"SDLCheck", "sdl-", "", "false", 0},
+ {"SDLCheck", "sdl", "", "true", 0},
+ {"IntrinsicFunctions", "Oi", "", "true", 0},
+ {"OmitFramePointers", "Oy-", "", "false", 0},
+ {"OmitFramePointers", "Oy", "", "true", 0},
+ {"EnableFiberSafeOptimizations", "GT", "", "true", 0},
+ {"WholeProgramOptimization", "GL", "", "true", 0},
+ {"UndefineAllPreprocessorDefinitions", "u", "", "true", 0},
+ {"IgnoreStandardIncludePath", "X", "", "true", 0},
+ {"PreprocessToFile", "P", "", "true", 0},
+ {"PreprocessSuppressLineNumbers", "EP", "", "true", 0},
+ {"PreprocessKeepComments", "C", "", "true", 0},
+ {"StringPooling", "GF-", "", "false", 0},
+ {"StringPooling", "GF", "", "true", 0},
+ {"MinimalRebuild", "Gm-", "", "false", 0},
+ {"MinimalRebuild", "Gm", "", "true", 0},
+ {"SmallerTypeCheck", "RTCc", "", "true", 0},
+ {"FunctionLevelLinking", "Gy-", "", "false", 0},
+ {"FunctionLevelLinking", "Gy", "", "true", 0},
+ {"EnableParallelCodeGeneration", "Qpar-", "", "false", 0},
+ {"EnableParallelCodeGeneration", "Qpar", "", "true", 0},
+ {"FloatingPointExceptions", "fp:except-", "", "false", 0},
+ {"FloatingPointExceptions", "fp:except", "", "true", 0},
+ {"CreateHotpatchableImage", "hotpatch", "", "true", 0},
+ {"DisableLanguageExtensions", "Za", "", "true", 0},
+ {"TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0},
+ {"TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0},
+ {"ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0},
+ {"ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0},
+ {"RuntimeTypeInfo", "GR-", "", "false", 0},
+ {"RuntimeTypeInfo", "GR", "", "true", 0},
+ {"OpenMPSupport", "openmp-", "", "false", 0},
+ {"OpenMPSupport", "openmp", "", "true", 0},
+ {"ExpandAttributedSource", "Fx", "", "true", 0},
+ {"UseUnicodeForAssemblerListing", "FAu", "", "true", 0},
+ {"ShowIncludes", "showIncludes", "", "true", 0},
+ {"EnablePREfast", "analyze-", "", "false", 0},
+ {"EnablePREfast", "analyze", "", "true", 0},
+ {"UseFullPaths", "FC", "", "true", 0},
+ {"OmitDefaultLibName", "Zl", "", "true", 0},
+
+ //Bool Properties With Argument
+ {"MultiProcessorCompilation", "MP", "", "true",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
+ {"ProcessorNumber", "MP", "Multi-processor Compilation", "",
+ cmVS7FlagTable::UserValueRequired},
+ {"GenerateXMLDocumentationFiles", "doc", "", "true",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
+ {"XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "",
+ cmVS7FlagTable::UserValueRequired},
+ {"BrowseInformation", "FR", "", "true",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
+ {"BrowseInformationFile", "FR", "Enable Browse Information", "",
+ cmVS7FlagTable::UserValueRequired},
+
+ //String List Properties
+ {"AdditionalIncludeDirectories", "I",
+ "Additional Include Directories",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"AdditionalUsingDirectories", "AI",
+ "Additional #using Directories",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"PreprocessorDefinitions", "D ",
+ "Preprocessor Definitions",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"UndefinePreprocessorDefinitions", "U",
+ "Undefine Preprocessor Definitions",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"DisableSpecificWarnings", "wd",
+ "Disable Specific Warnings",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"ForcedIncludeFiles", "FI",
+ "Forced Include File",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"ForcedUsingFiles", "FU",
+ "Forced #using File",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"PREfastAdditionalOptions", "analyze:",
+ "Additional Code Analysis Native options",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"PREfastAdditionalPlugins", "analyze:plugin",
+ "Additional Code Analysis Native plugins",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"TreatSpecificWarningsAsErrors", "we",
+ "Treat Specific Warnings As Errors",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+
+ //String Properties
+ // Skip [TrackerLogDirectory] - no command line Switch.
+ {"PreprocessOutputPath", "Fi",
+ "Preprocess Output Path",
+ "", cmVS7FlagTable::UserValue},
+ {"PrecompiledHeaderFile", "Yc",
+ "Precompiled Header Name",
+ "", cmVS7FlagTable::UserValueRequired},
+ {"PrecompiledHeaderFile", "Yu",
+ "Precompiled Header Name",
+ "", cmVS7FlagTable::UserValueRequired},
+ {"PrecompiledHeaderOutputFile", "Fp",
+ "Precompiled Header Output File",
+ "", cmVS7FlagTable::UserValue},
+ {"AssemblerListingLocation", "Fa",
+ "ASM List Location",
+ "", cmVS7FlagTable::UserValue},
+ {"ObjectFileName", "Fo",
+ "Object File Name",
+ "", cmVS7FlagTable::UserValue},
+ {"ProgramDataBaseFileName", "Fd",
+ "Program Database File Name",
+ "", cmVS7FlagTable::UserValue},
+ // Skip [XMLDocumentationFileName] - no command line Switch.
+ // Skip [BrowseInformationFile] - no command line Switch.
+ {"PREfastLog", "analyze:log ",
+ "Code Analysis Log",
+ "", cmVS7FlagTable::UserValue},
+ // Skip [AdditionalOptions] - no command line Switch.
+ {0,0,0,0,0}
+};
diff --git a/Source/cmVS12LibFlagTable.h b/Source/cmVS12LibFlagTable.h
new file mode 100644
index 000000000..10bb8057f
--- /dev/null
+++ b/Source/cmVS12LibFlagTable.h
@@ -0,0 +1,102 @@
+static cmVS7FlagTable cmVS12LibFlagTable[] =
+{
+
+ //Enum Properties
+ {"ErrorReporting", "ERRORREPORT:PROMPT",
+ "PromptImmediately", "PromptImmediately", 0},
+ {"ErrorReporting", "ERRORREPORT:QUEUE",
+ "Queue For Next Login", "QueueForNextLogin", 0},
+ {"ErrorReporting", "ERRORREPORT:SEND",
+ "Send Error Report", "SendErrorReport", 0},
+ {"ErrorReporting", "ERRORREPORT:NONE",
+ "No Error Report", "NoErrorReport", 0},
+
+ {"TargetMachine", "MACHINE:ARM",
+ "MachineARM", "MachineARM", 0},
+ {"TargetMachine", "MACHINE:EBC",
+ "MachineEBC", "MachineEBC", 0},
+ {"TargetMachine", "MACHINE:IA64",
+ "MachineIA64", "MachineIA64", 0},
+ {"TargetMachine", "MACHINE:MIPS",
+ "MachineMIPS", "MachineMIPS", 0},
+ {"TargetMachine", "MACHINE:MIPS16",
+ "MachineMIPS16", "MachineMIPS16", 0},
+ {"TargetMachine", "MACHINE:MIPSFPU",
+ "MachineMIPSFPU", "MachineMIPSFPU", 0},
+ {"TargetMachine", "MACHINE:MIPSFPU16",
+ "MachineMIPSFPU16", "MachineMIPSFPU16", 0},
+ {"TargetMachine", "MACHINE:SH4",
+ "MachineSH4", "MachineSH4", 0},
+ {"TargetMachine", "MACHINE:THUMB",
+ "MachineTHUMB", "MachineTHUMB", 0},
+ {"TargetMachine", "MACHINE:X64",
+ "MachineX64", "MachineX64", 0},
+ {"TargetMachine", "MACHINE:X86",
+ "MachineX86", "MachineX86", 0},
+
+ {"SubSystem", "SUBSYSTEM:CONSOLE",
+ "Console", "Console", 0},
+ {"SubSystem", "SUBSYSTEM:WINDOWS",
+ "Windows", "Windows", 0},
+ {"SubSystem", "SUBSYSTEM:NATIVE",
+ "Native", "Native", 0},
+ {"SubSystem", "SUBSYSTEM:EFI_APPLICATION",
+ "EFI Application", "EFI Application", 0},
+ {"SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
+ "EFI Boot Service Driver", "EFI Boot Service Driver", 0},
+ {"SubSystem", "SUBSYSTEM:EFI_ROM",
+ "EFI ROM", "EFI ROM", 0},
+ {"SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER",
+ "EFI Runtime", "EFI Runtime", 0},
+ {"SubSystem", "SUBSYSTEM:WINDOWSCE",
+ "WindowsCE", "WindowsCE", 0},
+ {"SubSystem", "SUBSYSTEM:POSIX",
+ "POSIX", "POSIX", 0},
+
+
+ //Bool Properties
+ {"SuppressStartupBanner", "NOLOGO", "", "true", 0},
+ {"IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0},
+ {"TreatLibWarningAsErrors", "WX:NO", "", "false", 0},
+ {"TreatLibWarningAsErrors", "WX", "", "true", 0},
+ {"Verbose", "VERBOSE", "", "true", 0},
+ {"LinkTimeCodeGeneration", "LTCG", "", "true", 0},
+
+ //Bool Properties With Argument
+
+ //String List Properties
+ // Skip [AdditionalDependencies] - no command line Switch.
+ {"AdditionalLibraryDirectories", "LIBPATH:",
+ "Additional Library Directories",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
+ "Ignore Specific Default Libraries",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"ExportNamedFunctions", "EXPORT:",
+ "Export Named Functions",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"RemoveObjects", "REMOVE:",
+ "Remove Objects",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+
+ //String Properties
+ {"OutputFile", "OUT:",
+ "Output File",
+ "", cmVS7FlagTable::UserValue},
+ {"ModuleDefinitionFile", "DEF:",
+ "Module Definition File Name",
+ "", cmVS7FlagTable::UserValue},
+ {"ForceSymbolReferences", "INCLUDE:",
+ "Force Symbol References",
+ "", cmVS7FlagTable::UserValue},
+ {"DisplayLibrary", "LIST:",
+ "Display Library to standard output",
+ "", cmVS7FlagTable::UserValue},
+ // Skip [MinimumRequiredVersion] - no command line Switch.
+ {"Name", "NAME:",
+ "Name",
+ "", cmVS7FlagTable::UserValue},
+ // Skip [AdditionalOptions] - no command line Switch.
+ // Skip [TrackerLogDirectory] - no command line Switch.
+ {0,0,0,0,0}
+};
diff --git a/Source/cmVS12LinkFlagTable.h b/Source/cmVS12LinkFlagTable.h
new file mode 100644
index 000000000..ce32e3815
--- /dev/null
+++ b/Source/cmVS12LinkFlagTable.h
@@ -0,0 +1,343 @@
+static cmVS7FlagTable cmVS12LinkFlagTable[] =
+{
+
+ //Enum Properties
+ {"ShowProgress", "",
+ "Not Set", "NotSet", 0},
+ {"ShowProgress", "VERBOSE",
+ "Display all progress messages", "LinkVerbose", 0},
+ {"ShowProgress", "VERBOSE:Lib",
+ "For Libraries Searched", "LinkVerboseLib", 0},
+ {"ShowProgress", "VERBOSE:ICF",
+ "About COMDAT folding during optimized linking", "LinkVerboseICF", 0},
+ {"ShowProgress", "VERBOSE:REF",
+ "About data removed during optimized linking", "LinkVerboseREF", 0},
+ {"ShowProgress", "VERBOSE:SAFESEH",
+ "About Modules incompatible with SEH", "LinkVerboseSAFESEH", 0},
+ {"ShowProgress", "VERBOSE:CLR",
+ "About linker activity related to managed code", "LinkVerboseCLR", 0},
+
+ {"ForceFileOutput", "FORCE",
+ "Enabled", "Enabled", 0},
+ {"ForceFileOutput", "FORCE:MULTIPLE",
+ "Multiply Defined Symbol Only", "MultiplyDefinedSymbolOnly", 0},
+ {"ForceFileOutput", "FORCE:UNRESOLVED",
+ "Undefined Symbol Only", "UndefinedSymbolOnly", 0},
+
+ {"CreateHotPatchableImage", "FUNCTIONPADMIN",
+ "Enabled", "Enabled", 0},
+ {"CreateHotPatchableImage", "FUNCTIONPADMIN:5",
+ "X86 Image Only", "X86Image", 0},
+ {"CreateHotPatchableImage", "FUNCTIONPADMIN:6",
+ "X64 Image Only", "X64Image", 0},
+ {"CreateHotPatchableImage", "FUNCTIONPADMIN:16",
+ "Itanium Image Only", "ItaniumImage", 0},
+
+ {"UACExecutionLevel", "level='asInvoker'",
+ "asInvoker", "AsInvoker", 0},
+ {"UACExecutionLevel", "level='highestAvailable'",
+ "highestAvailable", "HighestAvailable", 0},
+ {"UACExecutionLevel", "level='requireAdministrator'",
+ "requireAdministrator", "RequireAdministrator", 0},
+
+ {"SubSystem", "",
+ "Not Set", "NotSet", 0},
+ {"SubSystem", "SUBSYSTEM:CONSOLE",
+ "Console", "Console", 0},
+ {"SubSystem", "SUBSYSTEM:WINDOWS",
+ "Windows", "Windows", 0},
+ {"SubSystem", "SUBSYSTEM:NATIVE",
+ "Native", "Native", 0},
+ {"SubSystem", "SUBSYSTEM:EFI_APPLICATION",
+ "EFI Application", "EFI Application", 0},
+ {"SubSystem", "SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER",
+ "EFI Boot Service Driver", "EFI Boot Service Driver", 0},
+ {"SubSystem", "SUBSYSTEM:EFI_ROM",
+ "EFI ROM", "EFI ROM", 0},
+ {"SubSystem", "SUBSYSTEM:EFI_RUNTIME_DRIVER",
+ "EFI Runtime", "EFI Runtime", 0},
+ {"SubSystem", "SUBSYSTEM:POSIX",
+ "POSIX", "POSIX", 0},
+
+ {"Driver", "",
+ "Not Set", "NotSet", 0},
+ {"Driver", "Driver",
+ "Driver", "Driver", 0},
+ {"Driver", "DRIVER:UPONLY",
+ "UP Only", "UpOnly", 0},
+ {"Driver", "DRIVER:WDM",
+ "WDM", "WDM", 0},
+
+ {"LinkTimeCodeGeneration", "",
+ "Default", "Default", 0},
+ {"LinkTimeCodeGeneration", "LTCG",
+ "Use Link Time Code Generation", "UseLinkTimeCodeGeneration", 0},
+ {"LinkTimeCodeGeneration", "LTCG:PGInstrument",
+ "Profile Guided Optimization - Instrument", "PGInstrument", 0},
+ {"LinkTimeCodeGeneration", "LTCG:PGOptimize",
+ "Profile Guided Optimization - Optimization", "PGOptimization", 0},
+ {"LinkTimeCodeGeneration", "LTCG:PGUpdate",
+ "Profile Guided Optimization - Update", "PGUpdate", 0},
+
+ {"GenerateWindowsMetadata", "WINMD",
+ "Yes", "true", 0},
+ {"GenerateWindowsMetadata", "WINMD:NO",
+ "No", "false", 0},
+
+ {"WindowsMetadataSignHash", "WINMDSIGNHASH:SHA1",
+ "SHA1", "SHA1", 0},
+ {"WindowsMetadataSignHash", "WINMDSIGNHASH:SHA256",
+ "SHA256", "SHA256", 0},
+ {"WindowsMetadataSignHash", "WINMDSIGNHASH:SHA384",
+ "SHA384", "SHA384", 0},
+ {"WindowsMetadataSignHash", "WINMDSIGNHASH:SHA512",
+ "SHA512", "SHA512", 0},
+
+ {"TargetMachine", "",
+ "Not Set", "NotSet", 0},
+ {"TargetMachine", "MACHINE:ARM",
+ "MachineARM", "MachineARM", 0},
+ {"TargetMachine", "MACHINE:EBC",
+ "MachineEBC", "MachineEBC", 0},
+ {"TargetMachine", "MACHINE:IA64",
+ "MachineIA64", "MachineIA64", 0},
+ {"TargetMachine", "MACHINE:MIPS",
+ "MachineMIPS", "MachineMIPS", 0},
+ {"TargetMachine", "MACHINE:MIPS16",
+ "MachineMIPS16", "MachineMIPS16", 0},
+ {"TargetMachine", "MACHINE:MIPSFPU",
+ "MachineMIPSFPU", "MachineMIPSFPU", 0},
+ {"TargetMachine", "MACHINE:MIPSFPU16",
+ "MachineMIPSFPU16", "MachineMIPSFPU16", 0},
+ {"TargetMachine", "MACHINE:SH4",
+ "MachineSH4", "MachineSH4", 0},
+ {"TargetMachine", "MACHINE:THUMB",
+ "MachineTHUMB", "MachineTHUMB", 0},
+ {"TargetMachine", "MACHINE:X64",
+ "MachineX64", "MachineX64", 0},
+ {"TargetMachine", "MACHINE:X86",
+ "MachineX86", "MachineX86", 0},
+
+ {"CLRThreadAttribute", "CLRTHREADATTRIBUTE:MTA",
+ "MTA threading attribute", "MTAThreadingAttribute", 0},
+ {"CLRThreadAttribute", "CLRTHREADATTRIBUTE:STA",
+ "STA threading attribute", "STAThreadingAttribute", 0},
+ {"CLRThreadAttribute", "CLRTHREADATTRIBUTE:NONE",
+ "Default threading attribute", "DefaultThreadingAttribute", 0},
+
+ {"CLRImageType", "CLRIMAGETYPE:IJW",
+ "Force IJW image", "ForceIJWImage", 0},
+ {"CLRImageType", "CLRIMAGETYPE:PURE",
+ "Force Pure IL Image", "ForcePureILImage", 0},
+ {"CLRImageType", "CLRIMAGETYPE:SAFE",
+ "Force Safe IL Image", "ForceSafeILImage", 0},
+ {"CLRImageType", "",
+ "Default image type", "Default", 0},
+
+ {"SignHash", "CLRSIGNHASH:SHA1",
+ "SHA1", "SHA1", 0},
+ {"SignHash", "CLRSIGNHASH:SHA256",
+ "SHA256", "SHA256", 0},
+ {"SignHash", "CLRSIGNHASH:SHA384",
+ "SHA384", "SHA384", 0},
+ {"SignHash", "CLRSIGNHASH:SHA512",
+ "SHA512", "SHA512", 0},
+
+ {"LinkErrorReporting", "ERRORREPORT:PROMPT",
+ "PromptImmediately", "PromptImmediately", 0},
+ {"LinkErrorReporting", "ERRORREPORT:QUEUE",
+ "Queue For Next Login", "QueueForNextLogin", 0},
+ {"LinkErrorReporting", "ERRORREPORT:SEND",
+ "Send Error Report", "SendErrorReport", 0},
+ {"LinkErrorReporting", "ERRORREPORT:NONE",
+ "No Error Report", "NoErrorReport", 0},
+
+ {"CLRSupportLastError", "CLRSupportLastError",
+ "Enabled", "Enabled", 0},
+ {"CLRSupportLastError", "CLRSupportLastError:NO",
+ "Disabled", "Disabled", 0},
+ {"CLRSupportLastError", "CLRSupportLastError:SYSTEMDLL",
+ "System Dlls Only", "SystemDlls", 0},
+
+
+ //Bool Properties
+ {"LinkIncremental", "INCREMENTAL:NO", "", "false", 0},
+ {"LinkIncremental", "INCREMENTAL", "", "true", 0},
+ {"SuppressStartupBanner", "NOLOGO", "", "true", 0},
+ {"LinkStatus", "LTCG:NOSTATUS", "", "false", 0},
+ {"LinkStatus", "LTCG:STATUS", "", "true", 0},
+ {"PreventDllBinding", "ALLOWBIND:NO", "", "false", 0},
+ {"PreventDllBinding", "ALLOWBIND", "", "true", 0},
+ {"TreatLinkerWarningAsErrors", "WX:NO", "", "false", 0},
+ {"TreatLinkerWarningAsErrors", "WX", "", "true", 0},
+ {"IgnoreAllDefaultLibraries", "NODEFAULTLIB", "", "true", 0},
+ {"GenerateManifest", "MANIFEST:NO", "", "false", 0},
+ {"GenerateManifest", "MANIFEST", "", "true", 0},
+ {"AllowIsolation", "ALLOWISOLATION:NO", "", "false", 0},
+ {"UACUIAccess", "uiAccess='false'", "", "false", 0},
+ {"UACUIAccess", "uiAccess='true'", "", "true", 0},
+ {"ManifestEmbed", "manifest:embed", "", "true", 0},
+ {"GenerateDebugInformation", "DEBUG", "", "true", 0},
+ {"MapExports", "MAPINFO:EXPORTS", "", "true", 0},
+ {"AssemblyDebug", "ASSEMBLYDEBUG:DISABLE", "", "false", 0},
+ {"AssemblyDebug", "ASSEMBLYDEBUG", "", "true", 0},
+ {"LargeAddressAware", "LARGEADDRESSAWARE:NO", "", "false", 0},
+ {"LargeAddressAware", "LARGEADDRESSAWARE", "", "true", 0},
+ {"TerminalServerAware", "TSAWARE:NO", "", "false", 0},
+ {"TerminalServerAware", "TSAWARE", "", "true", 0},
+ {"SwapRunFromCD", "SWAPRUN:CD", "", "true", 0},
+ {"SwapRunFromNET", "SWAPRUN:NET", "", "true", 0},
+ {"OptimizeReferences", "OPT:NOREF", "", "false", 0},
+ {"OptimizeReferences", "OPT:REF", "", "true", 0},
+ {"EnableCOMDATFolding", "OPT:NOICF", "", "false", 0},
+ {"EnableCOMDATFolding", "OPT:ICF", "", "true", 0},
+ {"IgnoreEmbeddedIDL", "IGNOREIDL", "", "true", 0},
+ {"AppContainer", "APPCONTAINER", "", "true", 0},
+ {"WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN:NO", "", "false", 0},
+ {"WindowsMetadataLinkDelaySign", "WINMDDELAYSIGN", "", "true", 0},
+ {"NoEntryPoint", "NOENTRY", "", "true", 0},
+ {"SetChecksum", "RELEASE", "", "true", 0},
+ {"RandomizedBaseAddress", "DYNAMICBASE:NO", "", "false", 0},
+ {"RandomizedBaseAddress", "DYNAMICBASE", "", "true", 0},
+ {"FixedBaseAddress", "FIXED:NO", "", "false", 0},
+ {"FixedBaseAddress", "FIXED", "", "true", 0},
+ {"DataExecutionPrevention", "NXCOMPAT:NO", "", "false", 0},
+ {"DataExecutionPrevention", "NXCOMPAT", "", "true", 0},
+ {"TurnOffAssemblyGeneration", "NOASSEMBLY", "", "true", 0},
+ {"SupportUnloadOfDelayLoadedDLL", "DELAY:UNLOAD", "", "true", 0},
+ {"SupportNobindOfDelayLoadedDLL", "DELAY:NOBIND", "", "true", 0},
+ {"Profile", "PROFILE", "", "true", 0},
+ {"LinkDelaySign", "DELAYSIGN:NO", "", "false", 0},
+ {"LinkDelaySign", "DELAYSIGN", "", "true", 0},
+ {"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK:NO", "", "false", 0},
+ {"CLRUnmanagedCodeCheck", "CLRUNMANAGEDCODECHECK", "", "true", 0},
+ {"DetectOneDefinitionRule", "ODR", "", "true", 0},
+ {"ImageHasSafeExceptionHandlers", "SAFESEH:NO", "", "false", 0},
+ {"ImageHasSafeExceptionHandlers", "SAFESEH", "", "true", 0},
+ {"LinkDLL", "DLL", "", "true", 0},
+
+ //Bool Properties With Argument
+ {"EnableUAC", "MANIFESTUAC:NO", "", "false",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
+ {"EnableUAC", "MANIFESTUAC:NO", "Enable User Account Control (UAC)", "",
+ cmVS7FlagTable::UserValueRequired},
+ {"EnableUAC", "MANIFESTUAC:", "", "true",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
+ {"UACUIAccess", "MANIFESTUAC:", "Enable User Account Control (UAC)", "",
+ cmVS7FlagTable::UserValueRequired},
+ {"GenerateMapFile", "MAP", "", "true",
+ cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue},
+ {"MapFileName", "MAP", "Generate Map File", "",
+ cmVS7FlagTable::UserValueRequired},
+
+ //String List Properties
+ {"AdditionalLibraryDirectories", "LIBPATH:",
+ "Additional Library Directories",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ // Skip [AdditionalDependencies] - no command line Switch.
+ {"IgnoreSpecificDefaultLibraries", "NODEFAULTLIB:",
+ "Ignore Specific Default Libraries",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"AddModuleNamesToAssembly", "ASSEMBLYMODULE:",
+ "Add Module to Assembly",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"EmbedManagedResourceFile", "ASSEMBLYRESOURCE:",
+ "Embed Managed Resource File",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"ForceSymbolReferences", "INCLUDE:",
+ "Force Symbol References",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"DelayLoadDLLs", "DELAYLOAD:",
+ "Delay Loaded Dlls",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"AssemblyLinkResource", "ASSEMBLYLINKRESOURCE:",
+ "Assembly Link Resource",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"AdditionalManifestDependencies", "MANIFESTDEPENDENCY:",
+ "Additional Manifest Dependencies",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+ {"ManifestInput", "manifestinput:",
+ "Manifest Input",
+ "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable},
+
+ //String Properties
+ {"OutputFile", "OUT:",
+ "Output File",
+ "", cmVS7FlagTable::UserValue},
+ {"Version", "VERSION:",
+ "Version",
+ "", cmVS7FlagTable::UserValue},
+ {"SpecifySectionAttributes", "SECTION:",
+ "Specify Section Attributes",
+ "", cmVS7FlagTable::UserValue},
+ {"MSDOSStubFileName", "STUB:",
+ "MS-DOS Stub File Name",
+ "", cmVS7FlagTable::UserValue},
+ // Skip [TrackerLogDirectory] - no command line Switch.
+ {"ModuleDefinitionFile", "DEF:",
+ "Module Definition File",
+ "", cmVS7FlagTable::UserValue},
+ {"ManifestFile", "ManifestFile:",
+ "Manifest File",
+ "", cmVS7FlagTable::UserValue},
+ {"ProgramDatabaseFile", "PDB:",
+ "Generate Program Database File",
+ "", cmVS7FlagTable::UserValue},
+ {"StripPrivateSymbols", "PDBSTRIPPED:",
+ "Strip Private Symbols",
+ "", cmVS7FlagTable::UserValue},
+ // Skip [MapFileName] - no command line Switch.
+ // Skip [MinimumRequiredVersion] - no command line Switch.
+ {"HeapReserveSize", "HEAP:",
+ "Heap Reserve Size",
+ "", cmVS7FlagTable::UserValue},
+ // Skip [HeapCommitSize] - no command line Switch.
+ {"StackReserveSize", "STACK:",
+ "Stack Reserve Size",
+ "", cmVS7FlagTable::UserValue},
+ // Skip [StackCommitSize] - no command line Switch.
+ {"FunctionOrder", "ORDER:@",
+ "Function Order",
+ "", cmVS7FlagTable::UserValue},
+ {"ProfileGuidedDatabase", "PGD:",
+ "Profile Guided Database",
+ "", cmVS7FlagTable::UserValue},
+ {"MidlCommandFile", "MIDL:@",
+ "MIDL Commands",
+ "", cmVS7FlagTable::UserValue},
+ {"MergedIDLBaseFileName", "IDLOUT:",
+ "Merged IDL Base File Name",
+ "", cmVS7FlagTable::UserValue},
+ {"TypeLibraryFile", "TLBOUT:",
+ "Type Library",
+ "", cmVS7FlagTable::UserValue},
+ {"WindowsMetadataFile", "WINMDFILE:",
+ "Windows Metadata File",
+ "", cmVS7FlagTable::UserValue},
+ {"WindowsMetadataLinkKeyFile", "WINMDKEYFILE:",
+ "Windows Metadata Key File",
+ "", cmVS7FlagTable::UserValue},
+ {"WindowsMetadataKeyContainer", "WINMDKEYCONTAINER:",
+ "Windows Metadata Key Container",
+ "", cmVS7FlagTable::UserValue},
+ {"EntryPointSymbol", "ENTRY:",
+ "Entry Point",
+ "", cmVS7FlagTable::UserValue},
+ {"BaseAddress", "BASE:",
+ "Base Address",
+ "", cmVS7FlagTable::UserValue},
+ {"ImportLibrary", "IMPLIB:",
+ "Import Library",
+ "", cmVS7FlagTable::UserValue},
+ {"MergeSections", "MERGE:",
+ "Merge Sections",
+ "", cmVS7FlagTable::UserValue},
+ {"LinkKeyFile", "KEYFILE:",
+ "Key File",
+ "", cmVS7FlagTable::UserValue},
+ {"KeyContainer", "KEYCONTAINER:",
+ "Key Container",
+ "", cmVS7FlagTable::UserValue},
+ // Skip [AdditionalOptions] - no command line Switch.
+ {0,0,0,0,0}
+};
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 1e37ca532..9cfb3703e 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -25,31 +25,43 @@
#include "cmVS11CLFlagTable.h"
#include "cmVS11LinkFlagTable.h"
#include "cmVS11LibFlagTable.h"
+#include "cmVS12CLFlagTable.h"
+#include "cmVS12LinkFlagTable.h"
+#include "cmVS12LibFlagTable.h"
#include <cmsys/auto_ptr.hxx>
static cmVS7FlagTable const*
cmVSGetCLFlagTable(cmLocalVisualStudioGenerator* lg)
{
- if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS11)
+ if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS12)
+ { return cmVS12CLFlagTable; }
+ else if(lg->GetVersion() == cmLocalVisualStudioGenerator::VS11)
{ return cmVS11CLFlagTable; }
- return cmVS10CLFlagTable;
+ else
+ { return cmVS10CLFlagTable; }
}
static cmVS7FlagTable const*
cmVSGetLibFlagTable(cmLocalVisualStudioGenerator* lg)
{
- if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS11)
+ if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS12)
+ { return cmVS12LibFlagTable; }
+ else if(lg->GetVersion() == cmLocalVisualStudioGenerator::VS11)
{ return cmVS11LibFlagTable; }
- return cmVS10LibFlagTable;
+ else
+ { return cmVS10LibFlagTable; }
}
static cmVS7FlagTable const*
cmVSGetLinkFlagTable(cmLocalVisualStudioGenerator* lg)
{
- if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS11)
+ if(lg->GetVersion() >= cmLocalVisualStudioGenerator::VS12)
+ { return cmVS12LinkFlagTable; }
+ else if(lg->GetVersion() == cmLocalVisualStudioGenerator::VS11)
{ return cmVS11LinkFlagTable; }
- return cmVS10LinkFlagTable;
+ else
+ { return cmVS10LinkFlagTable; }
}
static std::string cmVS10EscapeXML(std::string arg)
@@ -109,6 +121,11 @@ cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
{
delete i->second;
}
+ for(OptionsMap::iterator i = this->LinkOptions.begin();
+ i != this->LinkOptions.end(); ++i)
+ {
+ delete i->second;
+ }
if(!this->BuildFileStream)
{
return;
@@ -181,6 +198,10 @@ void cmVisualStudio10TargetGenerator::Generate()
{
return;
}
+ if(!this->ComputeLinkOptions())
+ {
+ return;
+ }
}
cmMakefile* mf = this->Target->GetMakefile();
std::string path = mf->GetStartOutputDirectory();
@@ -395,6 +416,9 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
case cmTarget::UTILITY:
configType += "Utility";
break;
+ case cmTarget::GLOBAL_TARGET:
+ case cmTarget::UNKNOWN_LIBRARY:
+ break;
}
configType += "</ConfigurationType>\n";
this->WriteString(configType.c_str(), 2);
@@ -416,8 +440,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
mfcLine += useOfMfcValue + "</UseOfMfc>\n";
this->WriteString(mfcLine.c_str(), 2);
- if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY &&
- this->ClOptions[*i]->UsingUnicode() ||
+ if((this->Target->GetType() <= cmTarget::OBJECT_LIBRARY &&
+ this->ClOptions[*i]->UsingUnicode()) ||
this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS"))
{
this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2);
@@ -560,6 +584,12 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
sep = ";";
}
(*this->BuildFileStream ) << "</Outputs>\n";
+ if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10)
+ {
+ // VS >= 11 let us turn off linking of custom command outputs.
+ this->WritePlatformConfigTag("LinkObjects", i->c_str(), 3);
+ (*this->BuildFileStream ) << "false</LinkObjects>\n";
+ }
}
this->WriteString("</CustomBuild>\n", 2);
}
@@ -867,14 +897,23 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
}
}
- for(std::vector<cmSourceFile*>::const_iterator
- si = this->GeneratorTarget->ExternalObjects.begin();
- si != this->GeneratorTarget->ExternalObjects.end(); ++si)
+ if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10)
+ {
+ // For VS >= 11 we use LinkObjects to avoid linking custom command
+ // outputs. Use Object for all external objects, generated or not.
+ this->WriteSources("Object", this->GeneratorTarget->ExternalObjects);
+ }
+ else
{
// If an object file is generated in this target, then vs10 will use
// it in the build, and we have to list it as None instead of Object.
- std::vector<cmSourceFile*> const* d = this->Target->GetSourceDepends(*si);
- this->WriteSource((d && !d->empty())? "None":"Object", *si);
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ExternalObjects.begin();
+ si != this->GeneratorTarget->ExternalObjects.end(); ++si)
+ {
+ std::vector<cmSourceFile*> const* d=this->Target->GetSourceDepends(*si);
+ this->WriteSource((d && !d->empty())? "None":"Object", *si);
+ }
}
this->WriteSources("None", this->GeneratorTarget->ExtraSources);
@@ -898,7 +937,6 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
cmSourceFile* source)
{
cmSourceFile& sf = *source;
- cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
std::string objectName;
if(this->GeneratorTarget->ExplicitObjectName.find(&sf)
@@ -1077,7 +1115,6 @@ void
cmVisualStudio10TargetGenerator::
OutputLinkIncremental(std::string const& configName)
{
- std::string CONFIG = cmSystemTools::UpperCase(configName);
// static libraries and things greater than modules do not need
// to set this option
if(this->Target->GetType() == cmTarget::STATIC_LIBRARY
@@ -1085,72 +1122,36 @@ OutputLinkIncremental(std::string const& configName)
{
return;
}
- const char* linkType = "SHARED";
- if(this->Target->GetType() == cmTarget::EXECUTABLE)
- {
- linkType = "EXE";
- }
+ Options& linkOptions = *(this->LinkOptions[configName]);
- // assume incremental linking
- const char* incremental = "true";
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(configName.c_str());
- if(!linkLanguage)
- {
- cmSystemTools::Error
- ("CMake can not determine linker language for target:",
- this->Name.c_str());
- return;
- }
- std::string linkFlagVarBase = "CMAKE_";
- linkFlagVarBase += linkType;
- linkFlagVarBase += "_LINKER_FLAGS";
- std::string flags = this->
- Target->GetMakefile()->GetRequiredDefinition(linkFlagVarBase.c_str());
- std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
- flags += this->
- Target->GetMakefile()->GetRequiredDefinition(linkFlagVar.c_str());
- if(strcmp(linkLanguage, "C") == 0 || strcmp(linkLanguage, "CXX") == 0
- || strcmp(linkLanguage, "Fortran") == 0)
- {
- std::string baseFlagVar = "CMAKE_";
- baseFlagVar += linkLanguage;
- baseFlagVar += "_FLAGS";
- flags += this->
- Target->GetMakefile()->GetRequiredDefinition(baseFlagVar.c_str());
- std::string flagVar = baseFlagVar + std::string("_") + CONFIG;
- flags +=
- Target->GetMakefile()->GetRequiredDefinition(flagVar.c_str());
- }
- const char* targetLinkFlags = this->Target->GetProperty("LINK_FLAGS");
- if(targetLinkFlags)
- {
- flags += " ";
- flags += targetLinkFlags;
- }
- std::string flagsProp = "LINK_FLAGS_";
- flagsProp += CONFIG;
- if(const char* flagsConfig = this->Target->GetProperty(flagsProp.c_str()))
- {
- flags += " ";
- flags += flagsConfig;
- }
- if(flags.find("INCREMENTAL:NO") != flags.npos)
- {
- incremental = "false";
- }
+ const char* incremental = linkOptions.GetFlag("LinkIncremental");
this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 3);
- *this->BuildFileStream << incremental
+ *this->BuildFileStream << (incremental?incremental:"true")
<< "</LinkIncremental>\n";
+ linkOptions.RemoveFlag("LinkIncremental");
- const char* manifest = "true";
- if(flags.find("MANIFEST:NO") != flags.npos)
- {
- manifest = "false";
- }
+ const char* manifest = linkOptions.GetFlag("GenerateManifest");
this->WritePlatformConfigTag("GenerateManifest", configName.c_str(), 3);
- *this->BuildFileStream << manifest
+ *this->BuildFileStream << (manifest?manifest:"true")
<< "</GenerateManifest>\n";
+ linkOptions.RemoveFlag("GenerateManifest");
+
+ // Some link options belong here. Use them now and remove them so that
+ // WriteLinkOptions does not use them.
+ const char* flags[] = {
+ "LinkDelaySign",
+ "LinkKeyFile",
+ 0};
+ for(const char** f = flags; *f; ++f)
+ {
+ const char* flag = *f;
+ if(const char* value = linkOptions.GetFlag(flag))
+ {
+ this->WritePlatformConfigTag(flag, configName.c_str(), 3);
+ *this->BuildFileStream << value << "</" << flag << ">\n";
+ linkOptions.RemoveFlag(flag);
+ }
+ }
}
//----------------------------------------------------------------------------
@@ -1231,9 +1232,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
clOptions.AddFlag("PrecompiledHeader", "NotUsing");
clOptions.Parse(flags.c_str());
clOptions.Parse(defineFlags.c_str());
- clOptions.AddDefines(
- this->GeneratorTarget->GetCompileDefinitions().c_str());
- clOptions.AddDefines(this->GeneratorTarget->GetCompileDefinitions(
+ clOptions.AddDefines(this->Target->GetCompileDefinitions(
configName.c_str()).c_str());
clOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -1343,18 +1342,36 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config)
}
}
+//----------------------------------------------------------------------------
+bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
+{
+ if(this->Target->GetType() == cmTarget::EXECUTABLE ||
+ this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
+ this->Target->GetType() == cmTarget::MODULE_LIBRARY)
+ {
+ std::vector<std::string> const* configs =
+ this->GlobalGenerator->GetConfigurations();
+ for(std::vector<std::string>::const_iterator i = configs->begin();
+ i != configs->end(); ++i)
+ {
+ if(!this->ComputeLinkOptions(*i))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
-void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
- config)
+//----------------------------------------------------------------------------
+bool
+cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
{
+ cmsys::auto_ptr<Options> pOptions(
+ new Options(this->LocalGenerator, Options::Linker,
+ cmVSGetLinkFlagTable(this->LocalGenerator), 0, this));
+ Options& linkOptions = *pOptions;
- // static libraries and things greater than modules do not need
- // to set this option
- if(this->Target->GetType() == cmTarget::STATIC_LIBRARY
- || this->Target->GetType() > cmTarget::MODULE_LIBRARY)
- {
- return;
- }
const char* linkLanguage =
this->Target->GetLinkerLanguage(config.c_str());
if(!linkLanguage)
@@ -1362,10 +1379,9 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
cmSystemTools::Error
("CMake can not determine linker language for target:",
this->Name.c_str());
- return;
+ return false;
}
- this->WriteString("<Link>\n", 2);
std::string CONFIG = cmSystemTools::UpperCase(config);
const char* linkType = "SHARED";
@@ -1384,10 +1400,9 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
std::string flags;
if(stackVal)
{
- flags += " ";
+ flags += " /STACK:";
flags += stackVal;
}
- // assume incremental linking
std::string linkFlagVarBase = "CMAKE_";
linkFlagVarBase += linkType;
linkFlagVarBase += "_LINKER_FLAGS";
@@ -1411,10 +1426,6 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
flags += " ";
flags += flagsConfig;
}
- cmVisualStudioGeneratorOptions
- linkOptions(this->LocalGenerator,
- cmVisualStudioGeneratorOptions::Linker,
- cmVSGetLinkFlagTable(this->LocalGenerator), 0, this);
if ( this->Target->GetPropertyAsBool("WIN32_EXECUTABLE") )
{
flags += " /SUBSYSTEM:WINDOWS";
@@ -1423,8 +1434,6 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
{
flags += " /SUBSYSTEM:CONSOLE";
}
- cmSystemTools::ReplaceString(flags, "/INCREMENTAL:YES", "");
- cmSystemTools::ReplaceString(flags, "/INCREMENTAL:NO", "");
std::string standardLibsVar = "CMAKE_";
standardLibsVar += linkLanguage;
standardLibsVar += "_STANDARD_LIBRARIES";
@@ -1446,13 +1455,13 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
// Replace spaces in libs with ;
cmSystemTools::ReplaceString(libs, " ", ";");
cmComputeLinkInformation* pcli =
- this->GeneratorTarget->GetLinkInformation(config.c_str());
+ this->Target->GetLinkInformation(config.c_str());
if(!pcli)
{
cmSystemTools::Error
("CMake can not compute cmComputeLinkInformation for target:",
this->Name.c_str());
- return;
+ return false;
}
// add the libraries for the target to libs string
cmComputeLinkInformation& cli = *pcli;
@@ -1521,7 +1530,22 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
this->GeneratorTarget->ModuleDefinitionFile.c_str());
}
- linkOptions.RemoveFlag("GenerateManifest");
+ this->LinkOptions[config] = pOptions.release();
+ return true;
+}
+
+//----------------------------------------------------------------------------
+void
+cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& config)
+{
+ if(this->Target->GetType() == cmTarget::STATIC_LIBRARY
+ || this->Target->GetType() > cmTarget::MODULE_LIBRARY)
+ {
+ return;
+ }
+ Options& linkOptions = *(this->LinkOptions[config]);
+ this->WriteString("<Link>\n", 2);
+
linkOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", "");
linkOptions.OutputFlagMap(*this->BuildFileStream, " ");
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 308b9bd94..55a850a1b 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -68,6 +68,8 @@ private:
std::vector<std::string> const & includes);
void WriteRCOptions(std::string const& config,
std::vector<std::string> const & includes);
+ bool ComputeLinkOptions();
+ bool ComputeLinkOptions(std::string const& config);
void WriteLinkOptions(std::string const& config);
void WriteMidlOptions(std::string const& config,
std::vector<std::string> const & includes);
@@ -95,6 +97,7 @@ private:
typedef cmVisualStudioGeneratorOptions Options;
typedef std::map<cmStdString, Options*> OptionsMap;
OptionsMap ClOptions;
+ OptionsMap LinkOptions;
std::string PathToVcxproj;
cmTarget* Target;
cmGeneratorTarget* GeneratorTarget;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 1df0d9ed1..01950e16d 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -66,6 +66,7 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault()
break;
case cmLocalVisualStudioGenerator::VS10:
case cmLocalVisualStudioGenerator::VS11:
+ case cmLocalVisualStudioGenerator::VS12:
// by default VS puts <ExceptionHandling></ExceptionHandling> empty
// for a project, to make our projects look the same put a new line
// and space over for the closing </ExceptionHandling> as the default
diff --git a/Source/cmVisualStudioWCEPlatformParser.cxx b/Source/cmVisualStudioWCEPlatformParser.cxx
new file mode 100644
index 000000000..b302246ea
--- /dev/null
+++ b/Source/cmVisualStudioWCEPlatformParser.cxx
@@ -0,0 +1,175 @@
+/*============================================================================
+ 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 "cmVisualStudioWCEPlatformParser.h"
+#include "cmGlobalVisualStudioGenerator.h"
+#include "cmXMLParser.h"
+
+int cmVisualStudioWCEPlatformParser::ParseVersion(const char* version)
+{
+ const std::string registryBase =
+ cmGlobalVisualStudioGenerator::GetRegistryBase(version);
+ const std::string vckey = registryBase + "\\Setup\\VC;ProductDir";
+ const std::string vskey = registryBase + "\\Setup\\VS;ProductDir";
+
+ if(!cmSystemTools::ReadRegistryValue(vckey.c_str(), this->VcInstallDir) ||
+ !cmSystemTools::ReadRegistryValue(vskey.c_str(), this->VsInstallDir))
+ {
+ return 0;
+ }
+ cmSystemTools::ConvertToUnixSlashes(this->VcInstallDir);
+ cmSystemTools::ConvertToUnixSlashes(this->VsInstallDir);
+ this->VcInstallDir.append("/");
+ this->VsInstallDir.append("/");
+
+ const std::string configFilename =
+ this->VcInstallDir + "vcpackages/WCE.VCPlatform.config";
+
+ return this->ParseFile(configFilename.c_str());
+}
+
+std::string cmVisualStudioWCEPlatformParser::GetOSVersion() const
+{
+ if (this->OSMinorVersion.empty())
+ {
+ return OSMajorVersion;
+ }
+
+ return OSMajorVersion + "." + OSMinorVersion;
+}
+
+const char* cmVisualStudioWCEPlatformParser::GetArchitectureFamily() const
+{
+ std::map<std::string, std::string>::const_iterator it =
+ this->Macros.find("ARCHFAM");
+ if (it != this->Macros.end())
+ {
+ return it->second.c_str();
+ }
+
+ return 0;
+}
+
+void cmVisualStudioWCEPlatformParser::StartElement(const char* name,
+ const char** attributes)
+{
+ if(this->FoundRequiredName)
+ {
+ return;
+ }
+
+ this->CharacterData = "";
+
+ if(strcmp(name, "PlatformData") == 0)
+ {
+ this->PlatformName = "";
+ this->OSMajorVersion = "";
+ this->OSMinorVersion = "";
+ this->Macros.clear();
+ }
+
+ if(strcmp(name, "Macro") == 0)
+ {
+ std::string macroName;
+ std::string macroValue;
+
+ for(const char** attr = attributes; *attr; attr += 2)
+ {
+ if(strcmp(attr[0], "Name") == 0)
+ {
+ macroName = attr[1];
+ }
+ else if(strcmp(attr[0], "Value") == 0)
+ {
+ macroValue = attr[1];
+ }
+ }
+
+ if(!macroName.empty())
+ {
+ this->Macros[macroName] = macroValue;
+ }
+ }
+ else if(strcmp(name, "Directories") == 0)
+ {
+ for(const char** attr = attributes; *attr; attr += 2)
+ {
+ if(strcmp(attr[0], "Include") == 0)
+ {
+ this->Include = attr[1];
+ }
+ else if(strcmp(attr[0], "Library") == 0)
+ {
+ this->Library = attr[1];
+ }
+ else if(strcmp(attr[0], "Path") == 0)
+ {
+ this->Path = attr[1];
+ }
+ }
+ }
+}
+
+void cmVisualStudioWCEPlatformParser::EndElement(const char* name)
+{
+ if(!this->RequiredName)
+ {
+ if(strcmp(name, "PlatformName") == 0)
+ {
+ this->AvailablePlatforms.push_back(this->CharacterData);
+ }
+ return;
+ }
+
+ if(this->FoundRequiredName)
+ {
+ return;
+ }
+
+ if(strcmp(name, "PlatformName") == 0)
+ {
+ this->PlatformName = this->CharacterData;
+ }
+ else if(strcmp(name, "OSMajorVersion") == 0)
+ {
+ this->OSMajorVersion = this->CharacterData;
+ }
+ else if(strcmp(name, "OSMinorVersion") == 0)
+ {
+ this->OSMinorVersion = this->CharacterData;
+ }
+ else if(strcmp(name, "Platform") == 0)
+ {
+ if(this->PlatformName == this->RequiredName)
+ {
+ this->FoundRequiredName = true;
+ }
+ }
+}
+
+void cmVisualStudioWCEPlatformParser::CharacterDataHandler(const char* data,
+ int length)
+{
+ this->CharacterData.append(data, length);
+}
+
+std::string cmVisualStudioWCEPlatformParser::FixPaths(
+ const std::string& paths) const
+{
+ std::string ret = paths;
+ cmSystemTools::ReplaceString(ret, "$(PATH)", "%PATH%");
+ cmSystemTools::ReplaceString(ret, "$(VCInstallDir)", VcInstallDir.c_str());
+ cmSystemTools::ReplaceString(ret, "$(VSInstallDir)", VsInstallDir.c_str());
+ cmSystemTools::ReplaceString(ret, "\\", "/");
+ cmSystemTools::ReplaceString(ret, "//", "/");
+ cmSystemTools::ReplaceString(ret, "/", "\\");
+ return ret;
+}
diff --git a/Source/cmVisualStudioWCEPlatformParser.h b/Source/cmVisualStudioWCEPlatformParser.h
new file mode 100644
index 000000000..466e1dd43
--- /dev/null
+++ b/Source/cmVisualStudioWCEPlatformParser.h
@@ -0,0 +1,68 @@
+/*============================================================================
+ 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 cmVisualStudioWCEPlatformParser_h
+#define cmVisualStudioWCEPlatformParser_h
+#include "cmStandardIncludes.h"
+
+#include "cmXMLParser.h"
+
+// This class is used to parse XML with configuration
+// of installed SDKs in system
+class cmVisualStudioWCEPlatformParser : public cmXMLParser
+{
+public:
+ cmVisualStudioWCEPlatformParser(const char* name = NULL)
+ : RequiredName(name)
+ , FoundRequiredName(false)
+ {
+ }
+
+ int ParseVersion(const char* version);
+
+ bool Found() const {return this->FoundRequiredName;}
+ const char* GetArchitectureFamily() const;
+ std::string GetOSVersion() const;
+ std::string GetIncludeDirectories() const {
+ return this->FixPaths(this->Include); }
+ std::string GetLibraryDirectories() const {
+ return this->FixPaths(this->Library); }
+ std::string GetPathDirectories() const {
+ return this->FixPaths(this->Path); }
+ const std::vector<std::string>& GetAvailablePlatforms() const {
+ return this->AvailablePlatforms; }
+
+protected:
+ virtual void StartElement(const char* name, const char** attributes);
+ void EndElement(const char* name);
+ void CharacterDataHandler(const char* data, int length);
+
+private:
+ std::string FixPaths(const std::string& paths) const;
+
+ std::string CharacterData;
+
+ std::string Include;
+ std::string Library;
+ std::string Path;
+ std::string PlatformName;
+ std::string OSMajorVersion;
+ std::string OSMinorVersion;
+ std::map<std::string, std::string> Macros;
+ std::vector<std::string> AvailablePlatforms;
+
+ const char* RequiredName;
+ bool FoundRequiredName;
+ std::string VcInstallDir;
+ std::string VsInstallDir;
+};
+
+#endif
diff --git a/Source/cmWin32ProcessExecution.cxx b/Source/cmWin32ProcessExecution.cxx
index 9a536c159..5752ab61c 100644
--- a/Source/cmWin32ProcessExecution.cxx
+++ b/Source/cmWin32ProcessExecution.cxx
@@ -271,13 +271,6 @@ bool cmWin32ProcessExecution::Wait(int timeout)
return this->PrivateClose(timeout);
}
-/*
- * Internal dictionary mapping popen* file pointers to process handles,
- * for use when retrieving the process exit code. See _PyPclose() below
- * for more information on this dictionary's use.
- */
-static void *_PyPopenProcs = NULL;
-
static BOOL RealPopenCreateProcess(const char *cmdstring,
const char *path,
const char *szConsoleSpawn,
@@ -679,18 +672,6 @@ bool cmWin32ProcessExecution::PrivateOpen(const char *cmdstring,
}
}
- /*
- * Insert the files we've created into the process dictionary
- * all referencing the list with the process handle and the
- * initial number of files (see description below in _PyPclose).
- * Since if _PyPclose later tried to wait on a process when all
- * handles weren't closed, it could create a deadlock with the
- * child, we spend some energy here to try to ensure that we
- * either insert all file handles into the dictionary or none
- * at all. It's a little clumsy with the various popen modes
- * and variable number of files involved.
- */
-
/* Child is launched. Close the parents copy of those pipe
* handles that only the child should have open. You need to
* make sure that no handles to the write end of the output pipe
@@ -761,43 +742,6 @@ cmWin32ProcessExecution::~cmWin32ProcessExecution()
this->CloseHandles();
}
-/*
- * Wrapper for fclose() to use for popen* files, so we can retrieve the
- * exit code for the child process and return as a result of the close.
- *
- * This function uses the _PyPopenProcs dictionary in order to map the
- * input file pointer to information about the process that was
- * originally created by the popen* call that created the file pointer.
- * The dictionary uses the file pointer as a key (with one entry
- * inserted for each file returned by the original popen* call) and a
- * single list object as the value for all files from a single call.
- * The list object contains the Win32 process handle at [0], and a file
- * count at [1], which is initialized to the total number of file
- * handles using that list.
- *
- * This function closes whichever handle it is passed, and decrements
- * the file count in the dictionary for the process handle pointed to
- * by this file. On the last close (when the file count reaches zero),
- * this function will wait for the child process and then return its
- * exit code as the result of the close() operation. This permits the
- * files to be closed in any order - it is always the close() of the
- * final handle that will return the exit code.
- */
-
- /* RED_FLAG 31-Aug-2000 Tim
- * This is always called (today!) between a pair of
- * Py_BEGIN_ALLOW_THREADS/ Py_END_ALLOW_THREADS
- * macros. So the thread running this has no valid thread state, as
- * far as Python is concerned. However, this calls some Python API
- * functions that cannot be called safely without a valid thread
- * state, in particular PyDict_GetItem.
- * As a temporary hack (although it may last for years ...), we
- * *rely* on not having a valid thread state in this function, in
- * order to create our own "from scratch".
- * This will deadlock if _PyPclose is ever called by a thread
- * holding the global lock.
- */
-
bool cmWin32ProcessExecution::PrivateClose(int /* timeout */)
{
HANDLE hProcess = this->ProcessHandle;
diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx
index de150ee0f..6abf6bf00 100644
--- a/Source/cmXCodeObject.cxx
+++ b/Source/cmXCodeObject.cxx
@@ -38,7 +38,6 @@ cmXCodeObject::~cmXCodeObject()
cmXCodeObject::cmXCodeObject(PBXType ptype, Type type)
{
this->Version = 15;
- this->PBXTargetDependencyValue = 0;
this->Target = 0;
this->Object =0;
diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h
index bb2d5b225..b89f78cf3 100644
--- a/Source/cmXCodeObject.h
+++ b/Source/cmXCodeObject.h
@@ -120,14 +120,6 @@ public:
return 0;
}
- cmXCodeObject* GetPBXTargetDependency()
- {
- return this->PBXTargetDependencyValue;
- }
- void SetPBXTargetDependency(cmXCodeObject* d)
- {
- this->PBXTargetDependencyValue = d;
- }
void CopyAttributes(cmXCodeObject* );
void AddDependLibrary(const char* configName,
@@ -170,7 +162,6 @@ protected:
cmStdString Comment;
cmStdString String;
cmXCodeObject* Object;
- cmXCodeObject* PBXTargetDependencyValue;
std::vector<cmXCodeObject*> List;
std::map<cmStdString, StringVec> DependLibraries;
std::map<cmStdString, StringVec> DependTargets;
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 012342715..376758e48 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -63,15 +63,9 @@
# include "cmGlobalVisualStudio71Generator.h"
# include "cmGlobalVisualStudio8Generator.h"
# include "cmGlobalVisualStudio9Generator.h"
-# include "cmGlobalVisualStudio9IA64Generator.h"
-# include "cmGlobalVisualStudio9Win64Generator.h"
# include "cmGlobalVisualStudio10Generator.h"
-# include "cmGlobalVisualStudio10IA64Generator.h"
-# include "cmGlobalVisualStudio10Win64Generator.h"
# include "cmGlobalVisualStudio11Generator.h"
-# include "cmGlobalVisualStudio11Win64Generator.h"
-# include "cmGlobalVisualStudio11ARMGenerator.h"
-# include "cmGlobalVisualStudio8Win64Generator.h"
+# include "cmGlobalVisualStudio12Generator.h"
# include "cmGlobalBorlandMakefileGenerator.h"
# include "cmGlobalNMakeMakefileGenerator.h"
# include "cmGlobalJOMMakefileGenerator.h"
@@ -89,11 +83,13 @@
#if defined(CMAKE_HAVE_VS_GENERATORS)
#include "cmCallVisualStudioMacro.h"
+#include "cmVisualStudioWCEPlatformParser.h"
#endif
#if !defined(CMAKE_BOOT_MINGW)
# include "cmExtraCodeBlocksGenerator.h"
#endif
+#include "cmExtraSublimeTextGenerator.h"
#ifdef CMAKE_USE_KDEVELOP
# include "cmGlobalKdevelopGenerator.h"
@@ -117,8 +113,6 @@
#include <sys/stat.h> // struct stat
-#include <memory> // auto_ptr
-
static bool cmakeCheckStampFile(const char* stampName);
static bool cmakeCheckStampList(const char* stampName);
@@ -222,6 +216,11 @@ cmake::~cmake()
{
delete (*j).second;
}
+ for(RegisteredGeneratorsVector::iterator j = this->Generators.begin();
+ j != this->Generators.end(); ++j)
+ {
+ delete *j;
+ }
#ifdef CMAKE_BUILD_WITH_CMAKE
delete this->VariableWatch;
#endif
@@ -521,7 +520,7 @@ void cmake::ReadListFile(const std::vector<std::string>& args,
// read in the list file to fill the cache
if(path)
{
- std::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
+ cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
lg->GetMakefile()->SetHomeOutputDirectory
(cmSystemTools::GetCurrentWorkingDirectory().c_str());
lg->GetMakefile()->SetStartOutputDirectory
@@ -560,7 +559,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
this->SetGlobalGenerator(gg);
// read in the list file to fill the cache
- std::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
+ cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator());
cmMakefile* mf = lg->GetMakefile();
mf->SetHomeOutputDirectory
(cmSystemTools::GetCurrentWorkingDirectory().c_str());
@@ -662,6 +661,7 @@ void cmake::SetArgs(const std::vector<std::string>& args,
bool directoriesSetBefore)
{
bool directoriesSet = directoriesSetBefore;
+ bool haveToolset = false;
for(unsigned int i=1; i < args.size(); ++i)
{
std::string arg = args[i];
@@ -790,6 +790,27 @@ void cmake::SetArgs(const std::vector<std::string>& args,
"uninitialized variables.\n";
this->SetCheckSystemVars(true);
}
+ else if(arg.find("-T",0) == 0)
+ {
+ std::string value = arg.substr(2);
+ if(value.size() == 0)
+ {
+ ++i;
+ if(i >= args.size())
+ {
+ cmSystemTools::Error("No toolset specified for -T");
+ return;
+ }
+ value = args[i];
+ }
+ if(haveToolset)
+ {
+ cmSystemTools::Error("Multiple -T options not allowed");
+ return;
+ }
+ this->GeneratorToolset = value;
+ haveToolset = true;
+ }
else if(arg.find("-G",0) == 0)
{
std::string value = arg.substr(2);
@@ -956,7 +977,7 @@ int cmake::AddCMakePaths()
cMakeSelf = cmSystemTools::GetRealPath(cMakeSelf.c_str());
cMakeSelf += "/cmake";
cMakeSelf += cmSystemTools::GetExecutableExtension();
-#if __APPLE__
+#ifdef __APPLE__
// on the apple this might be the gui bundle
if(!cmSystemTools::FileExists(cMakeSelf.c_str()))
{
@@ -1147,6 +1168,10 @@ void CMakeCommandUsage(const char* program)
<< "Available on Windows only:\n"
<< " comspec - on windows 9x use this for RunCommand\n"
<< " delete_regv key - delete registry value\n"
+ << " env_vs8_wince sdkname - displays a batch file which sets the "
+ "environment for the provided Windows CE SDK installed in VS2005\n"
+ << " env_vs9_wince sdkname - displays a batch file which sets the "
+ "environment for the provided Windows CE SDK installed in VS2008\n"
<< " write_regv key value - write registry value\n"
#else
<< "Available on UNIX only:\n"
@@ -1656,7 +1681,7 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen.c_str()))
{
cm.SetGlobalGenerator(ggd);
- std::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
+ cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
lgd->GetMakefile()->SetStartDirectory(startDir.c_str());
lgd->GetMakefile()->SetStartOutputDirectory(startOutDir.c_str());
lgd->GetMakefile()->MakeStartDirectoriesCurrent();
@@ -1812,6 +1837,14 @@ int cmake::ExecuteCMakeCommand(std::vector<std::string>& args)
}
return cmWin32ProcessExecution::Windows9xHack(command.c_str());
}
+ else if (args[1] == "env_vs8_wince" && args.size() == 3)
+ {
+ return cmake::WindowsCEEnvironment("8.0", args[2]);
+ }
+ else if (args[1] == "env_vs9_wince" && args.size() == 3)
+ {
+ return cmake::WindowsCEEnvironment("9.0", args[2]);
+ }
#endif
}
@@ -1847,6 +1880,8 @@ void cmake::AddDefaultExtraGenerators()
this->AddExtraGenerator(cmExtraCodeBlocksGenerator::GetActualName(),
&cmExtraCodeBlocksGenerator::New);
+ this->AddExtraGenerator(cmExtraSublimeTextGenerator::GetActualName(),
+ &cmExtraSublimeTextGenerator::New);
#ifdef CMAKE_USE_ECLIPSE
this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(),
@@ -1869,10 +1904,10 @@ void cmake::AddDefaultExtraGenerators()
//----------------------------------------------------------------------------
void cmake::GetRegisteredGenerators(std::vector<std::string>& names)
{
- for(RegisteredGeneratorsMap::const_iterator i = this->Generators.begin();
+ for(RegisteredGeneratorsVector::const_iterator i = this->Generators.begin();
i != this->Generators.end(); ++i)
{
- names.push_back(i->first);
+ (*i)->GetGenerators(names);
}
for(RegisteredExtraGeneratorsMap::const_iterator
i = this->ExtraGenerators.begin();
@@ -1884,29 +1919,36 @@ void cmake::GetRegisteredGenerators(std::vector<std::string>& names)
cmGlobalGenerator* cmake::CreateGlobalGenerator(const char* name)
{
- cmGlobalGenerator* generator = 0;
cmExternalMakefileProjectGenerator* extraGenerator = 0;
- RegisteredGeneratorsMap::const_iterator genIt = this->Generators.find(name);
- if(genIt == this->Generators.end())
+ RegisteredExtraGeneratorsMap::const_iterator extraGenIt =
+ this->ExtraGenerators.find(name);
+ if (extraGenIt != this->ExtraGenerators.end())
{
- RegisteredExtraGeneratorsMap::const_iterator extraGenIt =
- this->ExtraGenerators.find(name);
- if (extraGenIt == this->ExtraGenerators.end())
- {
- return 0;
- }
extraGenerator = (extraGenIt->second)();
- genIt=this->Generators.find(extraGenerator->GetGlobalGeneratorName(name));
- if(genIt == this->Generators.end())
+ name = extraGenerator->GetGlobalGeneratorName(name);
+ }
+
+ cmGlobalGenerator* generator = 0;
+ for (RegisteredGeneratorsVector::const_iterator i =
+ this->Generators.begin(); i != this->Generators.end(); ++i)
+ {
+ generator = (*i)->CreateGlobalGenerator(name);
+ if (generator)
{
- delete extraGenerator;
- return 0;
+ break;
}
- }
+ }
+
+ if (generator)
+ {
+ generator->SetCMakeInstance(this);
+ generator->SetExternalMakefileProjectGenerator(extraGenerator);
+ }
+ else
+ {
+ delete extraGenerator;
+ }
- generator = (genIt->second)();
- generator->SetCMakeInstance(this);
- generator->SetExternalMakefileProjectGenerator(extraGenerator);
return generator;
}
@@ -2046,7 +2088,7 @@ struct SaveCacheEntry
int cmake::HandleDeleteCacheVariables(const char* var)
{
std::vector<std::string> argsSplit;
- cmSystemTools::ExpandListArgument(std::string(var), argsSplit);
+ cmSystemTools::ExpandListArgument(std::string(var), argsSplit, true);
// erase the property to avoid infinite recursion
this->SetProperty("__CMAKE_DELETE_CACHE_CHANGE_VARS_", "");
if(this->GetIsInTryCompile())
@@ -2203,6 +2245,7 @@ int cmake::ActualConfigure()
{"9.0", "Visual Studio 9 2008"},
{"10.0", "Visual Studio 10"},
{"11.0", "Visual Studio 11"},
+ {"12.0", "Visual Studio 12"},
{0, 0}};
for(int i=0; version[i].MSVersion != 0; i++)
{
@@ -2266,6 +2309,39 @@ int cmake::ActualConfigure()
cmCacheManager::INTERNAL);
}
+ if(const char* tsName =
+ this->CacheManager->GetCacheValue("CMAKE_GENERATOR_TOOLSET"))
+ {
+ if(this->GeneratorToolset.empty())
+ {
+ this->GeneratorToolset = tsName;
+ }
+ else if(this->GeneratorToolset != tsName)
+ {
+ std::string message = "Error: generator toolset: ";
+ message += this->GeneratorToolset;
+ message += "\nDoes not match the toolset used previously: ";
+ message += tsName;
+ message +=
+ "\nEither remove the CMakeCache.txt file or choose a different"
+ " binary directory.";
+ cmSystemTools::Error(message.c_str());
+ return -2;
+ }
+ }
+ else
+ {
+ this->CacheManager->AddCacheEntry("CMAKE_GENERATOR_TOOLSET",
+ this->GeneratorToolset.c_str(),
+ "Name of generator toolset.",
+ cmCacheManager::INTERNAL);
+ }
+ if(!this->GeneratorToolset.empty() &&
+ !this->GlobalGenerator->SetGeneratorToolset(this->GeneratorToolset))
+ {
+ return -2;
+ }
+
// reset any system configuration information, except for when we are
// InTryCompile. With TryCompile the system info is taken from the parent's
// info to save time
@@ -2570,55 +2646,43 @@ void cmake::AddDefaultGenerators()
{
#if defined(_WIN32) && !defined(__CYGWIN__)
# if !defined(CMAKE_BOOT_MINGW)
- this->Generators[cmGlobalVisualStudio6Generator::GetActualName()] =
- &cmGlobalVisualStudio6Generator::New;
- this->Generators[cmGlobalVisualStudio7Generator::GetActualName()] =
- &cmGlobalVisualStudio7Generator::New;
- this->Generators[cmGlobalVisualStudio10Generator::GetActualName()] =
- &cmGlobalVisualStudio10Generator::New;
- this->Generators[cmGlobalVisualStudio10IA64Generator::GetActualName()] =
- &cmGlobalVisualStudio10IA64Generator::New;
- this->Generators[cmGlobalVisualStudio10Win64Generator::GetActualName()] =
- &cmGlobalVisualStudio10Win64Generator::New;
- this->Generators[cmGlobalVisualStudio11Generator::GetActualName()] =
- &cmGlobalVisualStudio11Generator::New;
- this->Generators[cmGlobalVisualStudio11Win64Generator::GetActualName()] =
- &cmGlobalVisualStudio11Win64Generator::New;
- this->Generators[cmGlobalVisualStudio11ARMGenerator::GetActualName()] =
- &cmGlobalVisualStudio11ARMGenerator::New;
- this->Generators[cmGlobalVisualStudio71Generator::GetActualName()] =
- &cmGlobalVisualStudio71Generator::New;
- this->Generators[cmGlobalVisualStudio8Generator::GetActualName()] =
- &cmGlobalVisualStudio8Generator::New;
- this->Generators[cmGlobalVisualStudio9Generator::GetActualName()] =
- &cmGlobalVisualStudio9Generator::New;
- this->Generators[cmGlobalVisualStudio9IA64Generator::GetActualName()] =
- &cmGlobalVisualStudio9IA64Generator::New;
- this->Generators[cmGlobalVisualStudio9Win64Generator::GetActualName()] =
- &cmGlobalVisualStudio9Win64Generator::New;
- this->Generators[cmGlobalVisualStudio8Win64Generator::GetActualName()] =
- &cmGlobalVisualStudio8Win64Generator::New;
- this->Generators[cmGlobalBorlandMakefileGenerator::GetActualName()] =
- &cmGlobalBorlandMakefileGenerator::New;
- this->Generators[cmGlobalNMakeMakefileGenerator::GetActualName()] =
- &cmGlobalNMakeMakefileGenerator::New;
- this->Generators[cmGlobalJOMMakefileGenerator::GetActualName()] =
- &cmGlobalJOMMakefileGenerator::New;
- this->Generators[cmGlobalWatcomWMakeGenerator::GetActualName()] =
- &cmGlobalWatcomWMakeGenerator::New;
+ this->Generators.push_back(
+ cmGlobalVisualStudio6Generator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalVisualStudio7Generator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalVisualStudio10Generator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalVisualStudio11Generator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalVisualStudio12Generator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalVisualStudio71Generator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalVisualStudio8Generator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalVisualStudio9Generator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalBorlandMakefileGenerator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalNMakeMakefileGenerator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalJOMMakefileGenerator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalWatcomWMakeGenerator::NewFactory());
# endif
- this->Generators[cmGlobalMSYSMakefileGenerator::GetActualName()] =
- &cmGlobalMSYSMakefileGenerator::New;
- this->Generators[cmGlobalMinGWMakefileGenerator::GetActualName()] =
- &cmGlobalMinGWMakefileGenerator::New;
+ this->Generators.push_back(
+ cmGlobalMSYSMakefileGenerator::NewFactory());
+ this->Generators.push_back(
+ cmGlobalMinGWMakefileGenerator::NewFactory());
#endif
- this->Generators[cmGlobalUnixMakefileGenerator3::GetActualName()] =
- &cmGlobalUnixMakefileGenerator3::New;
- this->Generators[cmGlobalNinjaGenerator::GetActualName()] =
- &cmGlobalNinjaGenerator::New;
+ this->Generators.push_back(
+ cmGlobalUnixMakefileGenerator3::NewFactory());
+ this->Generators.push_back(
+ cmGlobalNinjaGenerator::NewFactory());
#ifdef CMAKE_USE_XCODE
- this->Generators[cmGlobalXCodeGenerator::GetActualName()] =
- &cmGlobalXCodeGenerator::New;
+ this->Generators.push_back(
+ cmGlobalXCodeGenerator::NewFactory());
#endif
}
@@ -2712,17 +2776,15 @@ void cmake::GetPropertiesDocumentation(std::map<std::string,
void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v)
{
- for(RegisteredGeneratorsMap::const_iterator i = this->Generators.begin();
- i != this->Generators.end(); ++i)
+ for(RegisteredGeneratorsVector::const_iterator i =
+ this->Generators.begin(); i != this->Generators.end(); ++i)
{
cmDocumentationEntry e;
- cmGlobalGenerator* generator = (i->second)();
- generator->GetDocumentation(e);
- delete generator;
+ (*i)->GetDocumentation(e);
v.push_back(e);
}
- for(RegisteredExtraGeneratorsMap::const_iterator
- i = this->ExtraGenerators.begin(); i != this->ExtraGenerators.end(); ++i)
+ for(RegisteredExtraGeneratorsMap::const_iterator i =
+ this->ExtraGenerators.begin(); i != this->ExtraGenerators.end(); ++i)
{
cmDocumentationEntry e;
cmExternalMakefileProjectGenerator* generator = (i->second)();
@@ -2805,7 +2867,7 @@ int cmake::CheckBuildSystem()
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();
if(!mf->ReadListFile(0, this->CheckBuildSystemArgument.c_str()) ||
cmSystemTools::GetErrorOccuredFlag())
@@ -2831,11 +2893,11 @@ int cmake::CheckBuildSystem()
}
// Create the generator and use it to clear the dependencies.
- std::auto_ptr<cmGlobalGenerator>
+ cmsys::auto_ptr<cmGlobalGenerator>
ggd(this->CreateGlobalGenerator(genName));
if(ggd.get())
{
- std::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
+ cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
lgd->ClearDependencies(mf, verbose);
}
}
@@ -3078,7 +3140,7 @@ void cmake::MarkCliAsUsed(const std::string& variable)
void cmake::GenerateGraphViz(const char* fileName) const
{
#ifdef CMAKE_BUILD_WITH_CMAKE
- std::auto_ptr<cmGraphVizWriter> gvWriter(
+ cmsys::auto_ptr<cmGraphVizWriter> gvWriter(
new cmGraphVizWriter(this->GetGlobalGenerator()->GetLocalGenerators()));
std::string settingsFile = this->GetHomeOutputDirectory();
@@ -3299,6 +3361,12 @@ int cmake::ExecuteLinkScript(std::vector<std::string>& args)
int result = 0;
while(result == 0 && cmSystemTools::GetLineFromStream(fin, command))
{
+ // Skip empty command lines.
+ if(command.find_first_not_of(" \t") == command.npos)
+ {
+ continue;
+ }
+
// Setup this command line.
const char* cmd[2] = {command.c_str(), 0};
cmsysProcess_SetCommand(cp, cmd);
@@ -3552,6 +3620,13 @@ void cmake::DefineProperty(const char *name, cmProperty::ScopeType scope,
chained);
}
+bool cmake::GetIsPropertyDefined(const char *name,
+ cmProperty::ScopeType scope)
+{
+ return this->PropertyDefinitions[scope].find(name) !=
+ this->PropertyDefinitions[scope].end();
+}
+
cmPropertyDefinition *cmake
::GetPropertyDefinition(const char *name,
cmProperty::ScopeType scope)
@@ -3965,10 +4040,18 @@ static bool cmakeCheckStampFile(const char* stampName)
}
// The build system is up to date. The stamp file has been removed
- // by the VS IDE due to a "rebuild" request. Just restore it.
- std::ofstream stamp(stampName);
+ // by the VS IDE due to a "rebuild" request. Restore it atomically.
+ cmOStringStream stampTempStream;
+ stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed();
+ std::string stampTempString = stampTempStream.str();
+ const char* stampTemp = stampTempString.c_str();
+ {
+ // TODO: Teach cmGeneratedFileStream to use a random temp file (with
+ // multiple tries in unlikely case of conflict) and use that here.
+ std::ofstream stamp(stampTemp);
stamp << "# CMake generation timestamp file this directory.\n";
- if(stamp)
+ }
+ if(cmSystemTools::RenameFile(stampTemp, stampName))
{
// Notify the user why CMake is not re-running. It is safe to
// just print to stdout here because this code is only reachable
@@ -3979,6 +4062,7 @@ static bool cmakeCheckStampFile(const char* stampName)
}
else
{
+ cmSystemTools::RemoveFile(stampTemp);
cmSystemTools::Error("Cannot restore timestamp ", stampName);
return false;
}
@@ -4014,6 +4098,29 @@ static bool cmakeCheckStampList(const char* stampList)
return true;
}
+//----------------------------------------------------------------------------
+int cmake::WindowsCEEnvironment(const char* version, const std::string& name)
+{
+#if defined(CMAKE_HAVE_VS_GENERATORS)
+ cmVisualStudioWCEPlatformParser parser(name.c_str());
+ parser.ParseVersion(version);
+ if (parser.Found())
+ {
+ std::cout << "@echo off" << std::endl;
+ std::cout << "echo Environment Selection: " << name << std::endl;
+ std::cout << "set PATH=" << parser.GetPathDirectories() << std::endl;
+ std::cout << "set INCLUDE=" << parser.GetIncludeDirectories() <<std::endl;
+ std::cout << "set LIB=" << parser.GetLibraryDirectories() <<std::endl;
+ return 0;
+ }
+#else
+ (void)version;
+#endif
+
+ std::cerr << "Could not find " << name;
+ return -1;
+}
+
// For visual studio 2005 and newer manifest files need to be embeded into
// exe and dll's. This code does that in such a way that incremental linking
// still works.
@@ -4358,6 +4465,10 @@ void cmake::IssueMessage(cmake::MessageType t, std::string const& text,
isError = true;
msg << "CMake Internal Error (please report a bug)";
}
+ else if(t == cmake::LOG)
+ {
+ msg << "CMake Debug Log";
+ }
else
{
msg << "CMake Warning";
@@ -4477,7 +4588,7 @@ int cmake::Build(const std::string& dir,
std::cerr << "Error: could find generator in Cache\n";
return 1;
}
- std::auto_ptr<cmGlobalGenerator> gen(
+ cmsys::auto_ptr<cmGlobalGenerator> gen(
this->CreateGlobalGenerator(it.GetValue()));
std::string output;
std::string projName;
diff --git a/Source/cmake.h b/Source/cmake.h
index 94c6f128f..63065a17c 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -17,6 +17,7 @@
#include "cmPropertyDefinitionMap.h"
#include "cmPropertyMap.h"
+class cmGlobalGeneratorFactory;
class cmGlobalGenerator;
class cmLocalGenerator;
class cmCacheManager;
@@ -186,6 +187,14 @@ class cmake
///! Get the names of the current registered generators
void GetRegisteredGenerators(std::vector<std::string>& names);
+ ///! Set the name of the selected generator-specific toolset.
+ void SetGeneratorToolset(std::string const& ts)
+ { this->GeneratorToolset = ts; }
+
+ ///! Get the name of the selected generator-specific toolset.
+ std::string const& GetGeneratorToolset() const
+ { return this->GeneratorToolset; }
+
///! get the cmCachemManager used by this invocation of cmake
cmCacheManager *GetCacheManager() { return this->CacheManager; }
@@ -340,6 +349,8 @@ class cmake
bool chain = false,
const char *variableGroup = 0);
+ bool GetIsPropertyDefined(const char *name, cmProperty::ScopeType scope);
+
// get property definition
cmPropertyDefinition *GetPropertyDefinition
(const char *name, cmProperty::ScopeType scope);
@@ -396,12 +407,9 @@ protected:
cmExternalMakefileProjectGenerator* (*CreateExtraGeneratorFunctionType)();
typedef std::map<cmStdString,
CreateExtraGeneratorFunctionType> RegisteredExtraGeneratorsMap;
-
- typedef cmGlobalGenerator* (*CreateGeneratorFunctionType)();
- typedef std::map<cmStdString,
- CreateGeneratorFunctionType> RegisteredGeneratorsMap;
+ typedef std::vector<cmGlobalGeneratorFactory*> RegisteredGeneratorsVector;
RegisteredCommandsMap Commands;
- RegisteredGeneratorsMap Generators;
+ RegisteredGeneratorsVector Generators;
RegisteredExtraGeneratorsMap ExtraGenerators;
void AddDefaultCommands();
void AddDefaultGenerators();
@@ -418,6 +426,7 @@ protected:
std::string StartOutputDirectory;
bool SuppressDevWarnings;
bool DoSuppressDevWarnings;
+ std::string GeneratorToolset;
///! read in a cmake list file to initialize the cache
void ReadListFile(const std::vector<std::string>& args, const char *path);
@@ -447,6 +456,8 @@ protected:
std::string const& link);
static int ExecuteEchoColor(std::vector<std::string>& args);
static int ExecuteLinkScript(std::vector<std::string>& args);
+ static int WindowsCEEnvironment(const char* version,
+ const std::string& name);
static int VisualStudioLink(std::vector<std::string>& args, int type);
static int VisualStudioLinkIncremental(std::vector<std::string>& args,
int type,
@@ -526,6 +537,13 @@ private:
"A makefile generator is responsible for generating a particular build " \
"system. Possible generator names are specified in the Generators " \
"section."},\
+ {"-T <toolset-name>", "Specify toolset name if supported by generator.", \
+ "Some CMake generators support a toolset name to be given to the " \
+ "native build system to choose a compiler. " \
+ "This is supported only on specific generators:\n" \
+ " Visual Studio >= 10\n" \
+ " Xcode >= 3.0\n" \
+ "See native build system documentation for allowed toolset names."}, \
{"-Wno-dev", "Suppress developer warnings.",\
"Suppress warnings that are meant for the author"\
" of the CMakeLists.txt files."},\
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 11a426753..42678419e 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -344,19 +344,17 @@ int main(int ac, char** av)
int do_cmake(int ac, char** av)
{
- int nocwd = 0;
-
if ( cmSystemTools::GetCurrentWorkingDirectory().size() == 0 )
{
std::cerr << "Current working directory cannot be established."
<< std::endl;
- nocwd = 1;
+ return 1;
}
#ifdef CMAKE_BUILD_WITH_CMAKE
cmDocumentation doc;
doc.addCMakeStandardDocSections();
- if(doc.CheckOptions(ac, av, "-E") || nocwd)
+ if(doc.CheckOptions(ac, av, "-E"))
{
// Construct and print requested documentation.
cmake hcm;
@@ -424,7 +422,7 @@ int do_cmake(int ac, char** av)
return result;
}
#else
- if ( nocwd || ac == 1 )
+ if ( ac == 1 )
{
std::cout <<
"Bootstrap CMake should not be used outside CMake build process."
diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx
index 34350bf7a..04dab59d0 100644
--- a/Source/cmcldeps.cxx
+++ b/Source/cmcldeps.cxx
@@ -237,12 +237,14 @@ int main() {
// needed to suppress filename output of msvc tools
std::string srcfilename;
+ {
std::string::size_type pos = srcfile.rfind("\\");
if (pos == std::string::npos) {
srcfilename = srcfile;
} else {
srcfilename = srcfile.substr(pos + 1);
}
+ }
std::string nol = " /nologo ";
std::string show = " /showIncludes ";
@@ -266,10 +268,12 @@ int main() {
// call cl in object dir so the .i is generated there
std::string objdir;
+ {
std::string::size_type pos = objfile.rfind("\\");
if (pos != std::string::npos) {
objdir = objfile.substr(0, pos);
}
+ }
// extract dependencies with cl.exe
int exit_code = process(srcfilename, dfile, objfile,
diff --git a/Source/cmparseMSBuildXML.py b/Source/cmparseMSBuildXML.py
index 35b55ca25..d1b61ef6a 100755
--- a/Source/cmparseMSBuildXML.py
+++ b/Source/cmparseMSBuildXML.py
@@ -9,6 +9,9 @@
# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/cl.xml"
# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/lib.xml"
# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/V110/1033/link.xml"
+# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/cl.xml"
+# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/lib.xml"
+# "${PROGRAMFILES}/MSBuild/Microsoft.Cpp/v4.0/v120/1033/link.xml"
#
# BoolProperty <Name>true|false</Name>
# simple example:
diff --git a/Source/cmw9xcom.cxx b/Source/cmw9xcom.cxx
index e6014b325..ab238d539 100644
--- a/Source/cmw9xcom.cxx
+++ b/Source/cmw9xcom.cxx
@@ -31,14 +31,14 @@ int main (int argc, char *argv[])
int cc;
for ( cc = 2; cc < argc; cc ++ )
{
- std::string arg = argv[cc];
- if ( (arg.find_first_of(" ") != arg.npos) &&
- (arg.find_first_of("\"") == arg.npos) )
+ std::string nextArg = argv[cc];
+ if ( (nextArg.find_first_of(" ") != nextArg.npos) &&
+ (nextArg.find_first_of("\"") == nextArg.npos) )
{
- arg = "\"" + arg + "\"";
+ nextArg = "\"" + nextArg + "\"";
}
command += " ";
- command += arg;
+ command += nextArg;
}
return cmWin32ProcessExecution::Windows9xHack(command.c_str());
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index d65077748..3e63183eb 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -187,6 +187,7 @@ static const char * cmDocumentationOptions[][3] =
{"--build-two-config", "Run CMake twice", "" },
{"--build-exe-dir", "Specify the directory for the executable.", "" },
{"--build-generator", "Specify the generator to use.", "" },
+ {"--build-generator-toolset", "Specify the generator-specific toolset.",""},
{"--build-project", "Specify the name of the project to build.", "" },
{"--build-makeprogram", "Specify the make program to use.", "" },
{"--build-noclean", "Skip the make clean step.", "" },
@@ -273,14 +274,13 @@ int main (int argc, char *argv[])
return cmCTestLaunch::Main(argc, argv);
}
- int nocwd = 0;
cmCTest inst;
if ( cmSystemTools::GetCurrentWorkingDirectory().size() == 0 )
{
cmCTestLog(&inst, ERROR_MESSAGE,
"Current working directory cannot be established." << std::endl);
- nocwd = 1;
+ return 1;
}
// If there is a testing input file, check for documentation options
@@ -298,7 +298,7 @@ int main (int argc, char *argv[])
}
cmDocumentation doc;
doc.addCTestStandardDocSections();
- if(doc.CheckOptions(argc, argv) || nocwd)
+ if(doc.CheckOptions(argc, argv))
{
// Construct and print requested documentation.
std::vector<cmDocumentationEntry> commands;
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index a132357f3..124b8aca0 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -116,7 +116,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET(KWSYS_USE_MD5 1)
SET(KWSYS_USE_Process 1)
SET(KWSYS_USE_RegularExpression 1)
- SET(KWSYS_USE_Registry 1)
SET(KWSYS_USE_System 1)
SET(KWSYS_USE_SystemTools 1)
SET(KWSYS_USE_CommandLineArguments 1)
@@ -509,19 +508,28 @@ ENDIF(KWSYS_USE_FundamentalType)
IF(KWSYS_USE_IOStream)
# Determine whether iostreams support long long.
+ SET(KWSYS_PLATFORM_CXX_TEST_DEFINES
+ -DKWSYS_IOS_USE_ANSI=${KWSYS_IOS_USE_ANSI}
+ -DKWSYS_IOS_HAVE_STD=${KWSYS_IOS_HAVE_STD})
IF(KWSYS_CXX_HAS_LONG_LONG)
- SET(KWSYS_PLATFORM_CXX_TEST_DEFINES
- -DKWSYS_IOS_USE_ANSI=${KWSYS_IOS_USE_ANSI}
- -DKWSYS_IOS_HAVE_STD=${KWSYS_IOS_HAVE_STD})
KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_ISTREAM_LONG_LONG
"Checking if istream supports long long" DIRECT)
KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_OSTREAM_LONG_LONG
"Checking if ostream supports long long" DIRECT)
- SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
ELSE()
SET(KWSYS_IOS_HAS_ISTREAM_LONG_LONG 0)
SET(KWSYS_IOS_HAS_OSTREAM_LONG_LONG 0)
ENDIF()
+ IF(KWSYS_CXX_HAS___INT64)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_ISTREAM___INT64
+ "Checking if istream supports __int64" DIRECT)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_IOS_HAS_OSTREAM___INT64
+ "Checking if ostream supports __int64" DIRECT)
+ ELSE()
+ SET(KWSYS_IOS_HAS_ISTREAM___INT64 0)
+ SET(KWSYS_IOS_HAS_OSTREAM___INT64 0)
+ ENDIF()
+ SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
ENDIF(KWSYS_USE_IOStream)
IF(KWSYS_NAMESPACE MATCHES "^kwsys$")
@@ -566,9 +574,106 @@ IF(KWSYS_USE_SystemTools)
ENDIF()
IF(KWSYS_USE_SystemInformation)
- SET_PROPERTY(SOURCE SystemInformation.cxx PROPERTY
- COMPILE_DEFINITIONS KWSYS_USE_LONG_LONG=${KWSYS_USE_LONG_LONG}
- KWSYS_USE___INT64=${KWSYS_USE___INT64})
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P})
+ IF(NOT CYGWIN)
+ INCLUDE(CheckIncludeFiles)
+ CHECK_INCLUDE_FILES("sys/types.h;ifaddrs.h" KWSYS_SYS_HAS_IFADDRS_H)
+ IF(KWSYS_SYS_HAS_IFADDRS_H)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_SYS_HAS_IFADDRS_H=1)
+ ENDIF()
+ ENDIF()
+ IF(WIN32)
+ INCLUDE(CheckSymbolExists)
+ SET(CMAKE_REQUIRED_LIBRARIES Psapi)
+ CHECK_SYMBOL_EXISTS(GetProcessMemoryInfo "windows.h;psapi.h" KWSYS_SYS_HAS_PSAPI)
+ UNSET(CMAKE_REQUIRED_LIBRARIES)
+ IF(KWSYS_SYS_HAS_PSAPI)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_SYS_HAS_PSAPI=1)
+ IF(MSVC70 OR MSVC71)
+ # Suppress LNK4089: all references to 'PSAPI.DLL' discarded by /OPT:REF
+ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /IGNORE:4089")
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ IF(CMAKE_SYSTEM MATCHES "HP-UX")
+ CHECK_INCLUDE_FILES("sys/mpctl.h" KWSYS_SYS_HAS_MPCTL_H)
+ IF(KWSYS_SYS_HAS_MPCTL_H)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_SYS_HAS_MPCTL_H=1)
+ ENDIF()
+ ENDIF()
+ IF(CMAKE_SYSTEM MATCHES "BSD")
+ CHECK_INCLUDE_FILES("machine/cpu.h" KWSYS_SYS_HAS_MACHINE_CPU_H)
+ IF(KWSYS_SYS_HAS_MACHINE_CPU_H)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_SYS_HAS_MACHINE_CPU_H=1)
+ ENDIF()
+ ENDIF()
+ IF(KWSYS_LFS_AVAILABLE AND NOT KWSYS_LFS_DISABLE)
+ SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1)
+ ENDIF()
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_RLIMIT64
+ "Checking whether CXX compiler has rlimit64" DIRECT)
+ SET(KWSYS_PLATFORM_CXX_TEST_DEFINES)
+ IF(KWSYS_CXX_HAS_RLIMIT64)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_CXX_HAS_RLIMIT64=1)
+ ENDIF()
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ATOL
+ "Checking whether CXX compiler has atol" DIRECT)
+ IF(KWSYS_CXX_HAS_ATOL)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_CXX_HAS_ATOL=1)
+ ENDIF()
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ATOLL
+ "Checking whether CXX compiler has atoll" DIRECT)
+ IF(KWSYS_CXX_HAS_ATOLL)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_CXX_HAS_ATOLL=1)
+ ENDIF()
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS__ATOI64
+ "Checking whether CXX compiler has _atoi64" DIRECT)
+ IF(KWSYS_CXX_HAS__ATOI64)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1)
+ ENDIF()
+ IF(BORLAND)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM
+ "Checking whether Borland CXX compiler supports assembler instructions" DIRECT)
+ IF(KWSYS_CXX_HAS_BORLAND_ASM)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM=1)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM_CPUID
+ "Checking whether Borland CXX compiler supports CPUID assembler instruction" DIRECT)
+ IF(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM_CPUID=1)
+ ENDIF()
+ ENDIF()
+ ENDIF()
+ IF(KWSYS_USE___INT64)
+ SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_USE___INT64=1)
+ ENDIF()
+ IF(KWSYS_USE_LONG_LONG)
+ SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_USE_LONG_LONG=1)
+ ENDIF()
+ IF(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
+ SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_IOS_HAS_OSTREAM_LONG_LONG=1)
+ ENDIF()
+ IF(KWSYS_IOS_HAS_OSTREAM___INT64)
+ SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_IOS_HAS_OSTREAM___INT64=1)
+ ENDIF()
+ IF(KWSYS_BUILD_SHARED)
+ SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
+ COMPILE_DEFINITIONS KWSYS_BUILD_SHARED=1)
+ ENDIF()
ENDIF()
#-----------------------------------------------------------------------------
@@ -686,7 +791,7 @@ SET(KWSYS_HXX_FILES Configure String
# Add selected C++ classes.
SET(cppclasses
Directory DynamicLoader Glob RegularExpression SystemTools
- CommandLineArguments Registry IOStream SystemInformation
+ CommandLineArguments IOStream SystemInformation
)
FOREACH(cpp ${cppclasses})
IF(KWSYS_USE_${cpp})
@@ -724,12 +829,8 @@ SET(KWSYS_CXX_SRCS)
# Add the proper sources for this platform's Process implementation.
IF(KWSYS_USE_Process)
IF(NOT UNIX)
- # Use the Windows implementation. We need the encoded forwarding executable.
- SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c
- ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c)
- SET_SOURCE_FILES_PROPERTIES(
- ${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
- PROPERTIES GENERATED 1)
+ # Use the Windows implementation.
+ SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c)
ELSE(NOT UNIX)
# Use the UNIX implementation.
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c)
@@ -802,9 +903,12 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS})
ENDIF(UNIX)
ENDIF(KWSYS_USE_DynamicLoader)
-
+
IF(KWSYS_USE_SystemInformation AND WIN32)
TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32)
+ IF(KWSYS_SYS_HAS_PSAPI)
+ TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi)
+ ENDIF()
ENDIF(KWSYS_USE_SystemInformation AND WIN32)
# Apply user-defined target properties to the library.
@@ -842,6 +946,16 @@ ENDIF(KWSYS_ENABLE_C AND KWSYS_C_SRCS)
# line to configure the namespace in the C and C++ source files.
ADD_DEFINITIONS("-DKWSYS_NAMESPACE=${KWSYS_NAMESPACE}")
+# Disable deprecation warnings for standard C functions.
+IF(MSVC OR (WIN32 AND "${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$"))
+ ADD_DEFINITIONS(
+ -D_CRT_NONSTDC_NO_DEPRECATE
+ -D_CRT_SECURE_NO_DEPRECATE
+ -D_CRT_SECURE_NO_WARNINGS
+ -D_SCL_SECURE_NO_DEPRECATE
+ )
+ENDIF()
+
IF(KWSYS_USE_String)
# Activate code in "String.c". See the comment in the source.
SET_SOURCE_FILES_PROPERTIES(String.c PROPERTIES
@@ -849,43 +963,6 @@ IF(KWSYS_USE_String)
ENDIF(KWSYS_USE_String)
#-----------------------------------------------------------------------------
-# Process execution on windows needs to build a forwarding executable
-# that works around a Win9x bug. We encode the executable into a C
-# file and build it into the library. Win9x platforms reproduce the
-# executable into a temporary directory when it is needed.
-IF(KWSYS_USE_Process)
- IF(NOT UNIX)
- # Build the forwarding executable itself and a program that will
- # encode it into a C file.
- ADD_EXECUTABLE(${KWSYS_NAMESPACE}ProcessFwd9x ProcessFwd9x.c)
- ADD_EXECUTABLE(${KWSYS_NAMESPACE}EncodeExecutable EncodeExecutable.c)
- SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
- SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
- SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY LABELS ${KWSYS_LABELS_EXE})
- SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY LABELS ${KWSYS_LABELS_EXE})
-
- SET(CFG_INTDIR "/${CMAKE_CFG_INTDIR}")
- IF(CMAKE_BUILD_TOOL MATCHES "make")
- SET(CFG_INTDIR "")
- ENDIF(CMAKE_BUILD_TOOL MATCHES "make")
-
- # Take advantage of a better custom command syntax if possible.
- SET(CMD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}EncodeExecutable.exe)
- SET(FWD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}ProcessFwd9x.exe)
- ADD_CUSTOM_COMMAND(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
- COMMAND ${CMD}
- ARGS ${FWD} ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
- ${KWSYS_NAMESPACE} ProcessFwd9x
- DEPENDS ${CMD} ${FWD})
-
- # Make sure build occurs in proper order.
- ADD_DEPENDENCIES(${KWSYS_NAMESPACE} ${KWSYS_NAMESPACE}ProcessFwd9x
- ${KWSYS_NAMESPACE}EncodeExecutable)
- ENDIF(NOT UNIX)
-ENDIF(KWSYS_USE_Process)
-
-#-----------------------------------------------------------------------------
# Setup testing if not being built as part of another project.
IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
IF(BUILD_TESTING)
@@ -923,7 +1000,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
)
ENDIF(NOT WATCOM)
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
- testRegistry
testIOS
testSystemTools
testCommandLineArguments
@@ -1027,8 +1103,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
# We expect test to fail
SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES WILL_FAIL ON)
GET_TEST_PROPERTY(kwsys.testFail WILL_FAIL wfv)
- SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES FAIL_REGULAR_EXPRESSION "ERROR_NOT_VALGRIND;FAIL;Test failed")
- SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES PASS_REGULAR_EXPRESSION "Test passed")
SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES MEASUREMENT "Some Key=Some Value")
MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}")
ENDIF()
diff --git a/Source/kwsys/CPU.h.in b/Source/kwsys/CPU.h.in
index ecd29d133..2e1a584b1 100644
--- a/Source/kwsys/CPU.h.in
+++ b/Source/kwsys/CPU.h.in
@@ -98,6 +98,14 @@
#elif defined(__SYSC_ZARCH__)
# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
+/* Aarch64 */
+#elif defined(__aarch64__)
+# if !defined(__AARCH64EB__)
+# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE
+# else
+# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG
+# endif
+
/* Unknown CPU */
#else
# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID 0
diff --git a/Source/kwsys/CTestConfig.cmake b/Source/kwsys/CTestConfig.cmake
index 9ab6ed86c..d977b472a 100644
--- a/Source/kwsys/CTestConfig.cmake
+++ b/Source/kwsys/CTestConfig.cmake
@@ -1,6 +1,6 @@
#=============================================================================
# KWSys - Kitware System Library
-# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+# Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
@@ -9,10 +9,9 @@
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
-set (CTEST_PROJECT_NAME "kwsys")
-set (CTEST_NIGHTLY_START_TIME "21:00:00 EDT")
-set (CTEST_DART_SERVER_VERSION "2")
+set(CTEST_PROJECT_NAME "KWSys")
+set(CTEST_NIGHTLY_START_TIME "21:00:00 EDT")
set(CTEST_DROP_METHOD "http")
-set(CTEST_DROP_SITE "www.cdash.org")
-set(CTEST_DROP_LOCATION "/CDash/submit.php?project=PublicDashboard")
+set(CTEST_DROP_SITE "open.cdash.org")
+set(CTEST_DROP_LOCATION "/submit.php?project=PublicDashboard")
set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/Source/kwsys/Configure.h.in b/Source/kwsys/Configure.h.in
index 15986cfea..70cf8442b 100644
--- a/Source/kwsys/Configure.h.in
+++ b/Source/kwsys/Configure.h.in
@@ -37,20 +37,6 @@
/* Whether kwsys namespace is "kwsys". */
#define @KWSYS_NAMESPACE@_NAME_IS_KWSYS @KWSYS_NAME_IS_KWSYS@
-/* If we are building a kwsys .c or .cxx file, suppress the Microsoft
- deprecation warnings. */
-#if defined(KWSYS_NAMESPACE)
-# ifndef _CRT_NONSTDC_NO_DEPRECATE
-# define _CRT_NONSTDC_NO_DEPRECATE
-# endif
-# ifndef _CRT_SECURE_NO_DEPRECATE
-# define _CRT_SECURE_NO_DEPRECATE
-# endif
-# ifndef _SCL_SECURE_NO_DEPRECATE
-# define _SCL_SECURE_NO_DEPRECATE
-# endif
-#endif
-
/* Whether Large File Support is requested. */
#define @KWSYS_NAMESPACE@_LFS_REQUESTED @KWSYS_LFS_REQUESTED@
diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx
index c4ee09551..fd83752c0 100644
--- a/Source/kwsys/DynamicLoader.cxx
+++ b/Source/kwsys/DynamicLoader.cxx
@@ -428,6 +428,58 @@ const char* DynamicLoader::LastError()
} // namespace KWSYS_NAMESPACE
#endif
+#ifdef __MINT__
+#define DYNAMICLOADER_DEFINED 1
+#define _GNU_SOURCE /* for program_invocation_name */
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+#include <dld.h>
+
+namespace KWSYS_NAMESPACE
+{
+
+//----------------------------------------------------------------------------
+DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const char* libname )
+{
+ char *name = (char *)calloc(1, strlen(libname) + 1);
+ dld_init(program_invocation_name);
+ strncpy(name, libname, strlen(libname));
+ dld_link(libname);
+ return (void *)name;
+}
+
+//----------------------------------------------------------------------------
+int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib)
+{
+ dld_unlink_by_file((char *)lib, 0);
+ free(lib);
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
+ DynamicLoader::LibraryHandle lib, const char* sym)
+{
+ // Hack to cast pointer-to-data to pointer-to-function.
+ union
+ {
+ void* pvoid;
+ DynamicLoader::SymbolPointer psym;
+ } result;
+ result.pvoid = dld_get_symbol(sym);
+ return result.psym;
+}
+
+//----------------------------------------------------------------------------
+const char* DynamicLoader::LastError()
+{
+ return dld_strerror(dld_errno);
+}
+
+} // namespace KWSYS_NAMESPACE
+#endif
+
// ---------------------------------------------------------------
// 6. Implementation for default UNIX machines.
// if nothing has been defined then use this
diff --git a/Source/kwsys/EncodeExecutable.c b/Source/kwsys/EncodeExecutable.c
deleted file mode 100644
index bc30568ff..000000000
--- a/Source/kwsys/EncodeExecutable.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- 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 <stdio.h>
-#ifdef __WATCOMC__
-#define _unlink unlink
-#endif
-int main(int argc, char* argv[])
-{
- FILE* ifp;
- FILE* ofp;
- int i;
- int n;
- int count = 0;
- unsigned char buffer[1024];
-
- /* Check arguments. */
- if(argc != 5)
- {
- fprintf(stderr, "Usage: %s <input> <output> <kwsys-name> <array>\n",
- argv[0]);
- return 1;
- }
-
- /* Open the input file. */
- ifp = fopen(argv[1], "rb");
- if(!ifp)
- {
- fprintf(stderr, "Cannot open input file: \"%s\"\n", argv[1]);
- return 2;
- }
- ofp = fopen(argv[2], "w");
- if(!ofp)
- {
- fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]);
- fclose(ifp);
- return 2;
- }
-
- /* Prepend header comment. */
- fprintf(ofp, "/*\n * DO NOT EDIT\n * This file is generated by:\n");
- fprintf(ofp, " * %s\n */\n\n", argv[0]);
- fprintf(ofp, "#include \"kwsysPrivate.h\"\n");
- fprintf(ofp, "#include KWSYS_HEADER(Configure.h)\n\n");
- fprintf(ofp, "#include <stdio.h>\n\n");
- fprintf(ofp, "#if defined(_WIN32)\n");
- fprintf(ofp, "# include <io.h>\n");
- fprintf(ofp, "#else\n");
- fprintf(ofp, "# include <unistd.h>\n");
- fprintf(ofp, "#endif\n");
- fprintf(ofp, "\n");
- fprintf(ofp, "static void kwsys_unlink(const char* fname)\n");
- fprintf(ofp, "{\n");
- fprintf(ofp, "#if defined(__WATCOMC__)\n");
- fprintf(ofp, " unlink(fname);\n");
- fprintf(ofp, "#else\n");
- fprintf(ofp, " _unlink(fname);\n");
- fprintf(ofp, "#endif\n");
- fprintf(ofp, "}\n");
- fprintf(ofp, "\n");
-
- /* Split file up in 1024-byte chunks. */
- while((n = (int)fread(buffer, 1, 1024, ifp)) > 0)
- {
- fprintf(ofp, "static unsigned char kwsysEncodedArray%s_%d[%d] = {\n",
- argv[4], count++, n);
- for(i=0; i < n-1; ++i)
- {
- fprintf(ofp, "0x%02X", buffer[i]);
- if(i%10 == 9)
- {
- fprintf(ofp, ",\n");
- }
- else
- {
- fprintf(ofp, ", ");
- }
- }
- fprintf(ofp, "0x%02X};\n\n", buffer[n-1]);
- }
- fclose(ifp);
-
- /* Provide a function to write the data to a file. */
- fprintf(ofp, "extern %s_EXPORT int %sEncodedWriteArray%s(const char* fname)\n",
- argv[3], argv[3], argv[4]);
- fprintf(ofp, "{\n");
- fprintf(ofp, " FILE* ofp = fopen(fname, \"wb\");\n");
- fprintf(ofp, " if(!ofp) { return 0; }\n");
- for(i=0; i < count; ++i)
- {
- fprintf(ofp, " if(fwrite(kwsysEncodedArray%s_%d, 1,\n"
- " sizeof(kwsysEncodedArray%s_%d), ofp) !=\n"
- " sizeof(kwsysEncodedArray%s_%d))\n",
- argv[4], i, argv[4], i, argv[4], i);
- fprintf(ofp, " {\n");
- fprintf(ofp, " fclose(ofp);\n");
- fprintf(ofp, " kwsys_unlink(fname);\n");
- fprintf(ofp, " return 0;\n");
- fprintf(ofp, " }\n");
- }
- fprintf(ofp, " fclose(ofp);\n");
- fprintf(ofp, " return 1;\n");
- fprintf(ofp, "}\n");
- fclose(ofp);
- return 0;
-}
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index 513eb6408..46a7e4f44 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -399,7 +399,7 @@ bool Glob::FindFiles(const kwsys_stl::string& inexpr)
if ( last_slash > 0 )
{
//kwsys_ios::cout << "I can skip: " << fexpr.substr(0, last_slash)
- //<< kwsys_ios::endl;
+ // << kwsys_ios::endl;
skip = last_slash;
}
if ( skip == 0 )
diff --git a/Source/kwsys/IOStream.cxx b/Source/kwsys/IOStream.cxx
index 57b696eb3..a31f8c846 100644
--- a/Source/kwsys/IOStream.cxx
+++ b/Source/kwsys/IOStream.cxx
@@ -272,6 +272,7 @@ namespace KWSYS_NAMESPACE
// Create one public symbol in this object file to avoid warnings from
// archivers.
+void IOStreamSymbolToAvoidWarning();
void IOStreamSymbolToAvoidWarning()
{
}
diff --git a/Source/kwsys/IOStream.hxx.in b/Source/kwsys/IOStream.hxx.in
index 9eb99e058..2eeedf2ff 100644
--- a/Source/kwsys/IOStream.hxx.in
+++ b/Source/kwsys/IOStream.hxx.in
@@ -26,12 +26,9 @@
/* Whether ostream supports long long. */
#define @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_IOS_HAS_OSTREAM_LONG_LONG@
-/* Size of type long long and 0 if not available. */
-#define @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG @KWSYS_SIZEOF_LONG_LONG@
-
/* Determine whether we need to define the streaming operators for
long long or __int64. */
-#if @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG
+#if @KWSYS_USE_LONG_LONG@
# if !@KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG || \
!@KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
# define @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL 1
@@ -136,7 +133,6 @@ operator<<(kwsys_ios::ostream& os, @KWSYS_NAMESPACE@::IOStreamULL value)
/* If building a C++ file in kwsys itself, give the source file
access to the macros without a configured namespace. */
#if defined(KWSYS_NAMESPACE)
-# define KWSYS_IOS_SIZEOF_LONG_LONG @KWSYS_NAMESPACE@_IOS_SIZEOF_LONG_LONG
# define KWSYS_IOS_HAS_ISTREAM_LONG_LONG @KWSYS_NAMESPACE@_IOS_HAS_ISTREAM_LONG_LONG
# define KWSYS_IOS_HAS_OSTREAM_LONG_LONG @KWSYS_NAMESPACE@_IOS_HAS_OSTREAM_LONG_LONG
# define KWSYS_IOS_NEED_OPERATORS_LL @KWSYS_NAMESPACE@_IOS_NEED_OPERATORS_LL
diff --git a/Source/kwsys/ProcessFwd9x.c b/Source/kwsys/ProcessFwd9x.c
deleted file mode 100644
index 536c54b67..000000000
--- a/Source/kwsys/ProcessFwd9x.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- 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.
-============================================================================*/
-
-/*
- On Windows9x platforms, this executable is spawned between a parent
- process and the child it is invoking to work around a bug. See the
- Win32 implementation file for details.
-
- Future Work: This executable must be linked statically against the C
- runtime library before being encoded into the library. Building it
- in this way may be hard because CMake has limited abilities to build
- different targets with different configurations in the same
- directory. We may just have to create and encode the executable
- once instead of generating it during the build. This would be an
- acceptable solution because the forwarding executable should not
- change very often and is pretty simple.
-*/
-
-#ifdef _MSC_VER
-#pragma warning (push, 1)
-#endif
-#include <windows.h>
-#include <stdio.h>
-
-void ReportLastError(HANDLE errorPipe);
-
-int main()
-{
- /* Process startup information for the real child. */
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
-
- /* The result of waiting for the child to exit. */
- DWORD waitResult;
-
- /* The child's process return code. */
- DWORD retVal;
-
- /* The command line used to invoke this process. */
- LPSTR commandLine = GetCommandLine();
-
- /* Pointer that will be advanced to the beginning of the command
- line of the real child process. */
- LPSTR cmdLine = commandLine;
-
- /* Handle to the error reporting pipe provided by the parent. This
- is parsed off the command line. */
- HANDLE errorPipe = 0;
- HANDLE errorPipeOrig = 0;
-
- /* Handle to the event the parent uses to tell us to resume the child.
- This is parsed off the command line. */
- HANDLE resumeEvent = 0;
-
- /* Handle to the event the parent uses to tell us to kill the child.
- This is parsed off the command line. */
- HANDLE killEvent = 0;
-
- /* Flag for whether to hide window of child process. */
- int hideWindow = 0;
-
- /* An array of the handles on which we wait when the child is
- running. */
- HANDLE waitHandles[2] = {0, 0};
-
- /* Move the pointer past the name of this executable. */
- if(*cmdLine == '"')
- {
- ++cmdLine;
- while(*cmdLine && *cmdLine != '"') { ++cmdLine; }
- if(*cmdLine) { ++cmdLine; }
- }
- else
- {
- while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
- }
-
- /* Parse the error pipe handle. */
- while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
- sscanf(cmdLine, "%p", &errorPipeOrig);
-
- /* Parse the resume event handle. */
- while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
- while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
- sscanf(cmdLine, "%p", &resumeEvent);
-
- /* Parse the kill event handle. */
- while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
- while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
- sscanf(cmdLine, "%p", &killEvent);
-
- /* Parse the hide window flag. */
- while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
- while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
- sscanf(cmdLine, "%d", &hideWindow);
-
- /* Skip to the beginning of the command line of the real child. */
- while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
- while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
-
- /* Create a non-inherited copy of the error pipe. We do not want
- the child to get it. */
- if(DuplicateHandle(GetCurrentProcess(), errorPipeOrig,
- GetCurrentProcess(), &errorPipe,
- 0, FALSE, DUPLICATE_SAME_ACCESS))
- {
- /* Have a non-inherited duplicate. Close the inherited one. */
- CloseHandle(errorPipeOrig);
- }
- else
- {
- /* Could not duplicate handle. Report the error. */
- ReportLastError(errorPipeOrig);
- return 1;
- }
-
- /* Create the subprocess. */
- ZeroMemory(&si, sizeof(si));
- ZeroMemory(&pi, sizeof(pi));
- si.cb = sizeof(si);
- si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
- si.wShowWindow = hideWindow?SW_HIDE:SW_SHOWDEFAULT;
- si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- if(CreateProcess(0, cmdLine, 0, 0, TRUE, CREATE_SUSPENDED, 0, 0, &si, &pi))
- {
- /* Process created successfully. Close the error reporting pipe
- to notify the parent of success. */
- CloseHandle(errorPipe);
- }
- else
- {
- /* Error creating the process. Report the error to the parent
- process through the special error reporting pipe. */
- ReportLastError(errorPipe);
- return 1;
- }
-
- /* Wait for resume or kill event from parent. */
- waitHandles[0] = killEvent;
- waitHandles[1] = resumeEvent;
- waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
-
- /* Check what happened. */
- if(waitResult == WAIT_OBJECT_0)
- {
- /* We were asked to kill the child. */
- TerminateProcess(pi.hProcess, 255);
- WaitForSingleObject(pi.hProcess, INFINITE);
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return 1;
- }
- else
- {
- /* We were asked to resume the child. */
- ResumeThread(pi.hThread);
- CloseHandle(pi.hThread);
- }
-
- /* Wait for subprocess to exit or for kill event from parent. */
- waitHandles[0] = killEvent;
- waitHandles[1] = pi.hProcess;
- waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
-
- /* Check what happened. */
- if(waitResult == WAIT_OBJECT_0)
- {
- /* We were asked to kill the child. */
- TerminateProcess(pi.hProcess, 255);
- WaitForSingleObject(pi.hProcess, INFINITE);
- CloseHandle(pi.hProcess);
- return 1;
- }
- else
- {
- /* The child exited. Get the return code. */
- GetExitCodeProcess(pi.hProcess, &retVal);
- CloseHandle(pi.hProcess);
- return retVal;
- }
-}
-
-void ReportLastError(HANDLE errorPipe)
-{
- LPVOID lpMsgBuf;
- DWORD n;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPTSTR) &lpMsgBuf,
- 0,
- NULL
- );
- WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0);
- LocalFree( lpMsgBuf );
-}
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index 9c66a4486..b9af2f1f5 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -47,6 +47,12 @@ do.
*/
+#if defined(__CYGWIN__)
+/* Increase the file descriptor limit for select() before including
+ related system headers. (Default: 64) */
+# define FD_SETSIZE 16384
+#endif
+
#include <stddef.h> /* ptrdiff_t */
#include <stdio.h> /* snprintf */
#include <stdlib.h> /* malloc, free */
@@ -63,10 +69,6 @@ do.
#include <dirent.h> /* DIR, dirent */
#include <ctype.h> /* isspace */
-#ifdef __HAIKU__
-#undef __BEOS__
-#endif
-
#if defined(__VMS)
# define KWSYSPE_VMS_NONBLOCK , O_NONBLOCK
#else
@@ -106,7 +108,7 @@ static inline void kwsysProcess_usleep(unsigned int msec)
* pipes' file handles to be non-blocking and just poll them directly
* without select().
*/
-#if !defined(__BEOS__) && !defined(__VMS)
+#if !defined(__BEOS__) && !defined(__VMS) && !defined(__MINT__)
# define KWSYSPE_USE_SELECT 1
#endif
@@ -422,9 +424,10 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
parse it. */
newCommands[cp->NumberOfCommands] =
kwsysSystem_Parse_CommandForUnix(*command, 0);
- if(!newCommands[cp->NumberOfCommands])
+ if(!newCommands[cp->NumberOfCommands] ||
+ !newCommands[cp->NumberOfCommands][0])
{
- /* Out of memory. */
+ /* Out of memory or no command parsed. */
free(newCommands);
return 0;
}
@@ -2732,6 +2735,7 @@ static void kwsysProcessesSignalHandler(int signum
kwsysProcess* cp = kwsysProcesses.Processes[i];
kwsysProcess_ssize_t status=
read(cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL], &buf, 1);
+ (void)status;
status=write(cp->SignalPipe, &buf, 1);
(void)status;
}
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 5aa4d8bf6..c836f9b08 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -28,14 +28,6 @@ On windows, a thread is created to wait for data on each pipe. The
threads are synchronized with the main thread to simulate the use of
a UNIX-style select system call.
-On Windows9x platforms, a small WIN32 console application is spawned
-in-between the calling process and the actual child to be executed.
-This is to work-around a problem with connecting pipes from WIN16
-console applications to WIN32 applications.
-
-For more information, please check Microsoft Knowledge Base Articles
-Q190351 and Q150956.
-
*/
#ifdef _MSC_VER
@@ -91,18 +83,12 @@ Q190351 and Q150956.
# define KWSYSPE_DEBUG(x) (void)1
#endif
-#define kwsysEncodedWriteArrayProcessFwd9x kwsys_ns(EncodedWriteArrayProcessFwd9x)
-
typedef LARGE_INTEGER kwsysProcessTime;
typedef struct kwsysProcessCreateInformation_s
{
/* Windows child startup control data. */
STARTUPINFO StartupInfo;
-
- /* Special error reporting pipe for Win9x forwarding executable. */
- HANDLE ErrorPipeRead;
- HANDLE ErrorPipeWrite;
} kwsysProcessCreateInformation;
/*--------------------------------------------------------------------------*/
@@ -146,7 +132,6 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc
static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
static void kwsysProcessKillTree(int pid);
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
-extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
/*--------------------------------------------------------------------------*/
/* A structure containing synchronization data for each thread. */
@@ -233,15 +218,6 @@ struct kwsysProcess_s
/* Whether to treat command lines as verbatim. */
int Verbatim;
- /* On Win9x platforms, the path to the forwarding executable. */
- char* Win9x;
-
- /* On Win9x platforms, the resume event for the forwarding executable. */
- HANDLE Win9xResumeEvent;
-
- /* On Win9x platforms, the kill event for the forwarding executable. */
- HANDLE Win9xKillEvent;
-
/* Mutex to protect the shared index used by threads to report data. */
HANDLE SharedIndexMutex;
@@ -269,9 +245,6 @@ struct kwsysProcess_s
HANDLE PipeNativeSTDOUT[2];
HANDLE PipeNativeSTDERR[2];
- /* Handle to automatically delete the Win9x forwarding executable. */
- HANDLE Win9xHandle;
-
/* ------------- Data managed per call to Execute ------------- */
/* The exceptional behavior that terminated the process, if any. */
@@ -311,7 +284,7 @@ struct kwsysProcess_s
for pipes to close after process termination. */
int PipesLeft;
- /* Buffer for error messages (possibly from Win9x child). */
+ /* Buffer for error messages. */
char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
/* Description for the ExitException. */
@@ -337,9 +310,6 @@ kwsysProcess* kwsysProcess_New(void)
/* Process control structure. */
kwsysProcess* cp;
- /* Path to Win9x forwarding executable. */
- char* win9x = 0;
-
/* Windows version number data. */
OSVERSIONINFO osv;
@@ -365,73 +335,11 @@ kwsysProcess* kwsysProcess_New(void)
GetVersionEx(&osv);
if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
- /* This is Win9x. We need the console forwarding executable to
- work-around a Windows 9x bug. */
- char fwdName[_MAX_FNAME+1] = "";
- char tempDir[_MAX_PATH+1] = "";
-
- /* We will try putting the executable in the system temp
- directory. Note that the returned path already has a trailing
- slash. */
- DWORD length = GetTempPath(_MAX_PATH+1, tempDir);
-
- /* Construct the executable name from the process id and kwsysProcess
- instance. This should be unique. */
- sprintf(fwdName, KWSYS_NAMESPACE_STRING "pew9xfwd_%ld_%p.exe",
- GetCurrentProcessId(), cp);
-
- /* If we have a temp directory, use it. */
- if(length > 0 && length <= _MAX_PATH)
- {
- /* Allocate a buffer to hold the forwarding executable path. */
- size_t tdlen = strlen(tempDir);
- win9x = (char*)malloc(tdlen + strlen(fwdName) + 2);
- if(!win9x)
- {
- kwsysProcess_Delete(cp);
- return 0;
- }
-
- /* Construct the full path to the forwarding executable. */
- sprintf(win9x, "%s%s", tempDir, fwdName);
- }
-
- /* If we found a place to put the forwarding executable, try to
- write it. */
- if(win9x)
- {
- if(!kwsysEncodedWriteArrayProcessFwd9x(win9x))
- {
- /* Failed to create forwarding executable. Give up. */
- free(win9x);
- kwsysProcess_Delete(cp);
- return 0;
- }
-
- /* Get a handle to the file that will delete it when closed. */
- cp->Win9xHandle = CreateFile(win9x, GENERIC_READ, FILE_SHARE_READ, 0,
- OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
- if(cp->Win9xHandle == INVALID_HANDLE_VALUE)
- {
- /* We were not able to get a read handle for the forwarding
- executable. It will not be deleted properly. Give up. */
- _unlink(win9x);
- free(win9x);
- kwsysProcess_Delete(cp);
- return 0;
- }
- }
- else
- {
- /* Failed to find a place to put forwarding executable. */
- kwsysProcess_Delete(cp);
- return 0;
- }
+ /* Win9x no longer supported. */
+ kwsysProcess_Delete(cp);
+ return 0;
}
- /* Save the path to the forwarding executable. */
- cp->Win9x = win9x;
-
/* Initially no thread owns the mutex. Initialize semaphore to 1. */
if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0)))
{
@@ -446,30 +354,6 @@ kwsysProcess* kwsysProcess_New(void)
return 0;
}
- if(cp->Win9x)
- {
- SECURITY_ATTRIBUTES sa;
- ZeroMemory(&sa, sizeof(sa));
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
-
- /* Create an event to tell the forwarding executable to resume the
- child. */
- if(!(cp->Win9xResumeEvent = CreateEvent(&sa, TRUE, 0, 0)))
- {
- kwsysProcess_Delete(cp);
- return 0;
- }
-
- /* Create an event to tell the forwarding executable to kill the
- child. */
- if(!(cp->Win9xKillEvent = CreateEvent(&sa, TRUE, 0, 0)))
- {
- kwsysProcess_Delete(cp);
- return 0;
- }
- }
-
/* Create the thread to read each pipe. */
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
{
@@ -620,13 +504,6 @@ void kwsysProcess_Delete(kwsysProcess* cp)
kwsysProcessCleanupHandle(&cp->SharedIndexMutex);
kwsysProcessCleanupHandle(&cp->Full);
- /* Close the Win9x resume and kill event handles. */
- if(cp->Win9x)
- {
- kwsysProcessCleanupHandle(&cp->Win9xResumeEvent);
- kwsysProcessCleanupHandle(&cp->Win9xKillEvent);
- }
-
/* Free memory. */
kwsysProcess_SetCommand(cp, 0);
kwsysProcess_SetWorkingDirectory(cp, 0);
@@ -637,12 +514,6 @@ void kwsysProcess_Delete(kwsysProcess* cp)
{
free(cp->CommandExitCodes);
}
- if(cp->Win9x)
- {
- /* Close our handle to the forwarding executable file. This will
- cause it to be deleted. */
- kwsysProcessCleanupHandle(&cp->Win9xHandle);
- }
free(cp);
}
@@ -1017,21 +888,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
SetCurrentDirectory(cp->WorkingDirectory);
}
- /* Reset the Win9x resume and kill events. */
- if(cp->Win9x)
- {
- if(!ResetEvent(cp->Win9xResumeEvent))
- {
- kwsysProcessCleanup(cp, 1);
- return;
- }
- if(!ResetEvent(cp->Win9xKillEvent))
- {
- kwsysProcessCleanup(cp, 1);
- return;
- }
- }
-
/* Initialize startup info data. */
ZeroMemory(&si, sizeof(si));
si.StartupInfo.cb = sizeof(si.StartupInfo);
@@ -1130,8 +986,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
STD_OUTPUT_HANDLE);
kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
STD_ERROR_HANDLE);
- kwsysProcessCleanupHandle(&si.ErrorPipeRead);
- kwsysProcessCleanupHandle(&si.ErrorPipeWrite);
return;
}
}
@@ -1160,16 +1014,9 @@ void kwsysProcess_Execute(kwsysProcess* cp)
/* All processes in the pipeline have been started in suspended
mode. Resume them all now. */
- if(cp->Win9x)
- {
- SetEvent(cp->Win9xResumeEvent);
- }
- else
+ for(i=0; i < cp->NumberOfCommands; ++i)
{
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
- ResumeThread(cp->ProcessInformation[i].hThread);
- }
+ ResumeThread(cp->ProcessInformation[i].hThread);
}
/* ---- It is no longer safe to call kwsysProcessCleanup. ----- */
@@ -1480,21 +1327,12 @@ void kwsysProcess_Kill(kwsysProcess* cp)
/* Kill the children. */
cp->Killed = 1;
- if(cp->Win9x)
- {
- /* Windows 9x. Tell the forwarding executable to kill the child. */
- SetEvent(cp->Win9xKillEvent);
- }
- else
+ for(i=0; i < cp->NumberOfCommands; ++i)
{
- /* Not Windows 9x. Just terminate the children. */
- for(i=0; i < cp->NumberOfCommands; ++i)
- {
- kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
- // close the handle if we kill it
- kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
- kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
- }
+ kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
+ // close the handle if we kill it
+ kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
+ kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
}
/* We are killing the children and ignoring all data. Do not wait
@@ -1815,97 +1653,13 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
}
}
- /* Create the child process. */
- {
- BOOL r;
- char* realCommand;
- if(cp->Win9x)
- {
- /* Create an error reporting pipe for the forwarding executable.
- Neither end is directly inherited. */
- if(!CreatePipe(&si->ErrorPipeRead, &si->ErrorPipeWrite, 0, 0))
- {
- return 0;
- }
-
- /* Create an inherited duplicate of the write end. This also closes
- the non-inherited version. */
- if(!DuplicateHandle(GetCurrentProcess(), si->ErrorPipeWrite,
- GetCurrentProcess(), &si->ErrorPipeWrite,
- 0, TRUE, (DUPLICATE_CLOSE_SOURCE |
- DUPLICATE_SAME_ACCESS)))
- {
- return 0;
- }
-
- /* The forwarding executable is given a handle to the error pipe
- and resume and kill events. */
- realCommand = (char*)malloc(strlen(cp->Win9x)+strlen(cp->Commands[index])+100);
- if(!realCommand)
- {
- return 0;
- }
- sprintf(realCommand, "%s %p %p %p %d %s", cp->Win9x,
- si->ErrorPipeWrite, cp->Win9xResumeEvent, cp->Win9xKillEvent,
- cp->HideWindow, cp->Commands[index]);
- }
- else
- {
- realCommand = cp->Commands[index];
- }
-
/* Create the child in a suspended state so we can wait until all
children have been created before running any one. */
- r = CreateProcess(0, realCommand, 0, 0, TRUE,
- cp->Win9x? 0 : CREATE_SUSPENDED, 0, 0,
- &si->StartupInfo, &cp->ProcessInformation[index]);
- if(cp->Win9x)
- {
- /* Free memory. */
- free(realCommand);
-
- /* Close the error pipe write end so we can detect when the
- forwarding executable closes it. */
- kwsysProcessCleanupHandle(&si->ErrorPipeWrite);
- if(r)
- {
- /* Wait for the forwarding executable to report an error or
- close the error pipe to report success. */
- DWORD total = 0;
- DWORD n = 1;
- while(total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0)
- {
- if(ReadFile(si->ErrorPipeRead, cp->ErrorMessage+total,
- KWSYSPE_PIPE_BUFFER_SIZE-total, &n, 0))
- {
- total += n;
- }
- else
- {
- n = 0;
- }
- }
- if(total > 0 || GetLastError() != ERROR_BROKEN_PIPE)
- {
- /* The forwarding executable could not run the process, or
- there was an error reading from its error pipe. Preserve
- the last error while cleaning up the forwarding executable
- so the cleanup our caller does reports the proper error. */
- DWORD error = GetLastError();
- kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread);
- kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess);
- SetLastError(error);
- return 0;
- }
- }
- kwsysProcessCleanupHandle(&si->ErrorPipeRead);
- }
-
- if(!r)
+ if(!CreateProcess(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0,
+ 0, &si->StartupInfo, &cp->ProcessInformation[index]))
{
return 0;
}
- }
/* Successfully created this child process. Close the current
process's copies of the inherited stdout and stdin handles. The
@@ -2152,19 +1906,12 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
/* Cleanup any processes already started in a suspended state. */
if(cp->ProcessInformation)
{
- if(cp->Win9x)
- {
- SetEvent(cp->Win9xKillEvent);
- }
- else
+ for(i=0; i < cp->NumberOfCommands; ++i)
{
- for(i=0; i < cp->NumberOfCommands; ++i)
+ if(cp->ProcessInformation[i].hProcess)
{
- if(cp->ProcessInformation[i].hProcess)
- {
- TerminateProcess(cp->ProcessInformation[i].hProcess, 255);
- WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
- }
+ TerminateProcess(cp->ProcessInformation[i].hProcess, 255);
+ WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
}
}
for(i=0; i < cp->NumberOfCommands; ++i)
diff --git a/Source/kwsys/Registry.cxx b/Source/kwsys/Registry.cxx
deleted file mode 100644
index cd521c966..000000000
--- a/Source/kwsys/Registry.cxx
+++ /dev/null
@@ -1,818 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- 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 "kwsysPrivate.h"
-#include KWSYS_HEADER(Registry.hxx)
-
-#include KWSYS_HEADER(Configure.hxx)
-#include KWSYS_HEADER(ios/iostream)
-#include KWSYS_HEADER(stl/string)
-#include KWSYS_HEADER(stl/map)
-#include KWSYS_HEADER(ios/iostream)
-#include KWSYS_HEADER(ios/fstream)
-#include KWSYS_HEADER(ios/sstream)
-// Work-around CMake dependency scanning limitation. This must
-// duplicate the above list of headers.
-#if 0
-# include "Registry.hxx.in"
-# include "Configure.hxx.in"
-# include "kwsys_stl.hxx.in"
-# include "kwsys_stl_string.hxx.in"
-# include "kwsys_stl_map.hxx.in"
-# include "kwsys_ios_iostream.h.in"
-# include "kwsys_ios_fstream.h.in"
-# include "kwsys_ios_sstream.h.in"
-#endif
-
-#include <ctype.h> // for isspace
-#include <stdio.h>
-#include <string.h> /* strlen, strncpy */
-#include <stdlib.h> /* getenv */
-
-#ifdef _WIN32
-# include <windows.h>
-#endif
-
-
-namespace KWSYS_NAMESPACE
-{
-class RegistryHelper {
-public:
- RegistryHelper(Registry::RegistryType registryType);
- virtual ~RegistryHelper();
-
- // Read a value from the registry.
- virtual bool ReadValue(const char *key, const char **value);
-
- // Delete a key from the registry.
- virtual bool DeleteKey(const char *key);
-
- // Delete a value from a given key.
- virtual bool DeleteValue(const char *key);
-
- // Set value in a given key.
- virtual bool SetValue(const char *key, const char *value);
-
- // Open the registry at toplevel/subkey.
- virtual bool Open(const char *toplevel, const char *subkey,
- int readonly);
-
- // Close the registry.
- virtual bool Close();
-
- // Set the value of changed
- void SetChanged(bool b) { m_Changed = b; }
- void SetTopLevel(const char* tl);
- const char* GetTopLevel() { return m_TopLevel.c_str(); }
-
- //! Read from local or global scope. On Windows this mean from local machine
- // or local user. On unix this will read from $HOME/.Projectrc or
- // /etc/Project
- void SetGlobalScope(bool b);
- bool GetGlobalScope();
-
- kwsys_stl::string EncodeKey(const char* str);
- kwsys_stl::string EncodeValue(const char* str);
- kwsys_stl::string DecodeValue(const char* str);
-
-protected:
- bool m_Changed;
- kwsys_stl::string m_TopLevel;
- bool m_GlobalScope;
-
-#ifdef _WIN32
- HKEY HKey;
-#endif
- // Strip trailing and ending spaces.
- char *Strip(char *str);
- void SetSubKey(const char* sk);
- kwsys_stl::string CreateKey(const char *key);
-
- typedef kwsys_stl::map<kwsys_stl::string, kwsys_stl::string> StringToStringMap;
- StringToStringMap EntriesMap;
- kwsys_stl::string m_SubKey;
- bool m_Empty;
- bool m_SubKeySpecified;
- kwsys_stl::string m_HomeDirectory;
-
- Registry::RegistryType m_RegistryType;
-};
-
-//----------------------------------------------------------------------------
-#define Registry_BUFFER_SIZE 8192
-
-//----------------------------------------------------------------------------
-Registry::Registry(Registry::RegistryType registryType)
-{
- m_Opened = false;
- m_Locked = false;
- this->Helper = 0;
- this->Helper = new RegistryHelper(registryType);
-}
-
-//----------------------------------------------------------------------------
-Registry::~Registry()
-{
- if ( m_Opened )
- {
- kwsys_ios::cerr << "Registry::Close should be "
- "called here. The registry is not closed."
- << kwsys_ios::endl;
- }
- delete this->Helper;
-}
-
-//----------------------------------------------------------------------------
-void Registry::SetGlobalScope(bool b)
-{
- this->Helper->SetGlobalScope(b);
-}
-
-//----------------------------------------------------------------------------
-bool Registry::GetGlobalScope()
-{
- return this->Helper->GetGlobalScope();
-}
-
-//----------------------------------------------------------------------------
-bool Registry::Open(const char *toplevel,
- const char *subkey, int readonly)
-{
- bool res = false;
- if ( m_Locked )
- {
- return res;
- }
- if ( m_Opened )
- {
- if ( !this->Close() )
- {
- return res;
- }
- }
- if ( !toplevel || !*toplevel )
- {
- kwsys_ios::cerr << "Registry::Opened() Toplevel not defined"
- << kwsys_ios::endl;
- return res;
- }
-
- if ( isspace(toplevel[0]) ||
- isspace(toplevel[strlen(toplevel)-1]) )
- {
- kwsys_ios::cerr << "Toplevel has to start with letter or number and end"
- " with one" << kwsys_ios::endl;
- return res;
- }
-
- res = this->Helper->Open(toplevel, subkey, readonly);
- if ( readonly != Registry::READONLY )
- {
- m_Locked = true;
- }
-
- if ( res )
- {
- m_Opened = true;
- this->Helper->SetTopLevel(toplevel);
- }
- return res;
-}
-
-//----------------------------------------------------------------------------
-bool Registry::Close()
-{
- bool res = false;
- if ( m_Opened )
- {
- res = this->Helper->Close();
- }
-
- if ( res )
- {
- m_Opened = false;
- m_Locked = false;
- this->Helper->SetChanged(false);
- }
- return res;
-}
-
-//----------------------------------------------------------------------------
-bool Registry::ReadValue(const char *subkey,
- const char *key,
- const char **value)
-{
- bool res = false;
- bool open = false;
- if ( ! value )
- {
- return res;
- }
- *value = 0;
- if ( !m_Opened )
- {
- if ( !this->Open(this->GetTopLevel(), subkey,
- Registry::READONLY) )
- {
- return res;
- }
- open = true;
- }
- res = this->Helper->ReadValue(key, value);
-
- if ( open )
- {
- if ( !this->Close() )
- {
- res = false;
- }
- }
- return res;
-}
-
-//----------------------------------------------------------------------------
-bool Registry::DeleteKey(const char *subkey, const char *key)
-{
- bool res = false;
- bool open = false;
- if ( !m_Opened )
- {
- if ( !this->Open(this->GetTopLevel(), subkey,
- Registry::READWRITE) )
- {
- return res;
- }
- open = true;
- }
-
- res = this->Helper->DeleteKey(key);
- if ( res )
- {
- this->Helper->SetChanged(true);
- }
-
- if ( open )
- {
- if ( !this->Close() )
- {
- res = false;
- }
- }
- return res;
-}
-
-//----------------------------------------------------------------------------
-bool Registry::DeleteValue(const char *subkey, const char *key)
-{
- bool res = false;
- bool open = false;
- if ( !m_Opened )
- {
- if ( !this->Open(this->GetTopLevel(), subkey,
- Registry::READWRITE) )
- {
- return res;
- }
- open = true;
- }
-
- res = this->Helper->DeleteValue(key);
- if ( res )
- {
- this->Helper->SetChanged(true);
- }
-
- if ( open )
- {
- if ( !this->Close() )
- {
- res = false;
- }
- }
- return res;
-}
-
-//----------------------------------------------------------------------------
-bool Registry::SetValue(const char *subkey, const char *key,
- const char *value)
-{
- bool res = false;
- bool open = false;
- if ( !m_Opened )
- {
- if ( !this->Open(this->GetTopLevel(), subkey,
- Registry::READWRITE) )
- {
- return res;
- }
- open = true;
- }
-
- res = this->Helper->SetValue( key, value );
- if ( res )
- {
- this->Helper->SetChanged(true);
- }
-
- if ( open )
- {
- if ( !this->Close() )
- {
- res = false;
- }
- }
- return res;
-}
-
-//----------------------------------------------------------------------------
-const char* Registry::GetTopLevel()
-{
- return this->Helper->GetTopLevel();
-}
-
-//----------------------------------------------------------------------------
-void Registry::SetTopLevel(const char* tl)
-{
- this->Helper->SetTopLevel(tl);
-}
-
-//----------------------------------------------------------------------------
-void RegistryHelper::SetTopLevel(const char* tl)
-{
- if ( tl )
- {
- m_TopLevel = tl;
- }
- else
- {
- m_TopLevel = "";
- }
-}
-
-//----------------------------------------------------------------------------
-RegistryHelper::RegistryHelper(Registry::RegistryType registryType)
-{
- m_Changed = false;
- m_TopLevel = "";
- m_SubKey = "";
- m_SubKeySpecified = false;
- m_Empty = true;
- m_GlobalScope = false;
- m_RegistryType = registryType;
-}
-
-//----------------------------------------------------------------------------
-RegistryHelper::~RegistryHelper()
-{
-}
-
-
-//----------------------------------------------------------------------------
-bool RegistryHelper::Open(const char *toplevel, const char *subkey,
- int readonly)
-{
- this->EntriesMap.clear();
- m_Empty = 1;
-
-#ifdef _WIN32
- if ( m_RegistryType == Registry::WIN32_REGISTRY)
- {
- HKEY scope = HKEY_CURRENT_USER;
- if ( this->GetGlobalScope() )
- {
- scope = HKEY_LOCAL_MACHINE;
- }
- int res = 0;
- kwsys_ios::ostringstream str;
- DWORD dwDummy;
- str << "Software\\Kitware\\" << toplevel << "\\" << subkey;
- if ( readonly == Registry::READONLY )
- {
- res = ( RegOpenKeyEx(scope, str.str().c_str(),
- 0, KEY_READ, &this->HKey) == ERROR_SUCCESS );
- }
- else
- {
- char lpClass[] = "";
- res = ( RegCreateKeyEx(scope, str.str().c_str(),
- 0, lpClass, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE,
- NULL, &this->HKey, &dwDummy) == ERROR_SUCCESS );
- }
- if ( res != 0 )
- {
- this->SetSubKey( subkey );
- }
- return (res != 0);
- }
-#endif
- if ( m_RegistryType == Registry::FILE_REGISTRY )
- {
- bool res = false;
- int cc;
- kwsys_ios::ostringstream str;
- const char* homeDirectory;
- if ( (homeDirectory = getenv("HOME")) == 0 )
- {
- if ( (homeDirectory = getenv("USERPROFILE")) == 0 )
- {
- return false;
- }
- }
- m_HomeDirectory = homeDirectory;
- str << m_HomeDirectory.c_str() << "/." << toplevel << "rc";
- if ( readonly == Registry::READWRITE )
- {
- kwsys_ios::ofstream ofs( str.str().c_str(), kwsys_ios::ios::out|kwsys_ios::ios::app );
- if ( ofs.fail() )
- {
- return false;
- }
- ofs.close();
- }
-
- kwsys_ios::ifstream *ifs = new kwsys_ios::ifstream(str.str().c_str(), kwsys_ios::ios::in
-#ifndef KWSYS_IOS_USE_ANSI
- | kwsys_ios::ios::nocreate
-#endif
- );
- if ( !ifs )
- {
- return false;
- }
- if ( ifs->fail())
- {
- delete ifs;
- return false;
- }
-
- res = true;
- char buffer[Registry_BUFFER_SIZE];
- while( !ifs->fail() )
- {
- ifs->getline(buffer, Registry_BUFFER_SIZE);
- if ( ifs->fail() || ifs->eof() )
- {
- break;
- }
- char *line = this->Strip(buffer);
- if ( *line == '#' || *line == 0 )
- {
- // Comment
- continue;
- }
- int linelen = static_cast<int>(strlen(line));
- for ( cc = 0; cc < linelen; cc++ )
- {
- if ( line[cc] == '=' )
- {
- char *key = new char[ cc+1 ];
- strncpy( key, line, cc );
- key[cc] = 0;
- char *value = line + cc + 1;
- char *nkey = this->Strip(key);
- char *nvalue = this->Strip(value);
- this->EntriesMap[nkey] = this->DecodeValue(nvalue);
- m_Empty = 0;
- delete [] key;
- break;
- }
- }
- }
- ifs->close();
- this->SetSubKey( subkey );
- delete ifs;
- return res;
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-bool RegistryHelper::Close()
-{
-#ifdef _WIN32
- if ( m_RegistryType == Registry::WIN32_REGISTRY)
- {
- int res;
- res = ( RegCloseKey(this->HKey) == ERROR_SUCCESS );
- return (res != 0);
- }
-#endif
- if ( m_RegistryType == Registry::FILE_REGISTRY )
- {
- if ( !m_Changed )
- {
- this->SetSubKey(0);
- return true;
- }
-
- kwsys_ios::ostringstream str;
- str << m_HomeDirectory.c_str() << "/." << this->GetTopLevel() << "rc";
- kwsys_ios::ofstream *ofs = new kwsys_ios::ofstream(str.str().c_str(), kwsys_ios::ios::out);
- if ( !ofs )
- {
- return false;
- }
- if ( ofs->fail())
- {
- delete ofs;
- return false;
- }
- *ofs << "# This file is automatically generated by the application" << kwsys_ios::endl
- << "# If you change any lines or add new lines, note that all" << kwsys_ios::endl
- << "# comments and empty lines will be deleted. Every line has" << kwsys_ios::endl
- << "# to be in format: " << kwsys_ios::endl
- << "# key = value" << kwsys_ios::endl
- << "#" << kwsys_ios::endl;
-
- if ( !this->EntriesMap.empty() )
- {
- RegistryHelper::StringToStringMap::iterator it;
- for ( it = this->EntriesMap.begin();
- it != this->EntriesMap.end();
- ++ it )
- {
- *ofs << it->first.c_str() << " = " << this->EncodeValue(it->second.c_str()).c_str() << kwsys_ios::endl;
- }
- }
- this->EntriesMap.clear();
- ofs->close();
- delete ofs;
- this->SetSubKey(0);
- m_Empty = 1;
- return true;
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-bool RegistryHelper::ReadValue(const char *skey, const char **value)
-
-{
-#ifdef _WIN32
- if ( m_RegistryType == Registry::WIN32_REGISTRY)
- {
- kwsys_stl::string key = this->CreateKey( skey );
- if ( key.empty() )
- {
- return false;
- }
- DWORD dwType, dwSize;
- dwType = REG_SZ;
- char buffer[1024]; // Replace with RegQueryInfoKey
- dwSize = sizeof(buffer);
- int res = ( RegQueryValueEx(this->HKey, skey, NULL, &dwType,
- (BYTE *)buffer, &dwSize) == ERROR_SUCCESS );
- if ( !res )
- {
- return false;
- }
- this->EntriesMap[key] = buffer;
- RegistryHelper::StringToStringMap::iterator it
- = this->EntriesMap.find(key);
- *value = it->second.c_str();
- return true;
- }
-#endif
- if ( m_RegistryType == Registry::FILE_REGISTRY )
- {
- bool res = false;
- kwsys_stl::string key = this->CreateKey( skey );
- if ( key.empty() )
- {
- return false;
- }
-
- RegistryHelper::StringToStringMap::iterator it
- = this->EntriesMap.find(key);
- if ( it != this->EntriesMap.end() )
- {
- *value = it->second.c_str();
- res = true;
- }
- return res;
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-bool RegistryHelper::DeleteKey(const char* skey)
-{
-#ifdef _WIN32
- if ( m_RegistryType == Registry::WIN32_REGISTRY)
- {
- int res = ( RegDeleteKey( this->HKey, skey ) == ERROR_SUCCESS );
- return (res != 0);
- }
-#endif
- if ( m_RegistryType == Registry::FILE_REGISTRY )
- {
- kwsys_stl::string key = this->CreateKey( skey );
- if ( key.empty() )
- {
- return false;
- }
- this->EntriesMap.erase(key);
- return true;
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-bool RegistryHelper::DeleteValue(const char *skey)
-{
-#ifdef _WIN32
- if ( m_RegistryType == Registry::WIN32_REGISTRY)
- {
- int res = ( RegDeleteValue( this->HKey, skey ) == ERROR_SUCCESS );
- return (res != 0);
- }
-#endif
- if ( m_RegistryType == Registry::FILE_REGISTRY )
- {
- kwsys_stl::string key = this->CreateKey( skey );
- if ( key.empty() )
- {
- return false;
- }
- this->EntriesMap.erase(key);
- return true;
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-bool RegistryHelper::SetValue(const char *skey, const char *value)
-{
-#ifdef _WIN32
- if ( m_RegistryType == Registry::WIN32_REGISTRY)
- {
- DWORD len = (DWORD)(value ? strlen(value) : 0);
- int res = ( RegSetValueEx(this->HKey, skey, 0, REG_SZ,
- (CONST BYTE *)(const char *)value,
- len+1) == ERROR_SUCCESS );
- return (res != 0);
- }
-#endif
- if ( m_RegistryType == Registry::FILE_REGISTRY )
- {
- kwsys_stl::string key = this->CreateKey( skey );
- if ( key.empty() )
- {
- return 0;
- }
- this->EntriesMap[key] = value;
- return 1;
- }
- return false;
-}
-
-//----------------------------------------------------------------------------
-kwsys_stl::string RegistryHelper::CreateKey( const char *key )
-{
- if ( !m_SubKeySpecified || m_SubKey.empty() || !key )
- {
- return "";
- }
- kwsys_ios::ostringstream ostr;
- ostr << this->EncodeKey(this->m_SubKey.c_str()).c_str()
- << "\\" << this->EncodeKey(key).c_str();
- return ostr.str();
-}
-
-//----------------------------------------------------------------------------
-void RegistryHelper::SetSubKey(const char* sk)
-{
- if ( !sk )
- {
- m_SubKey = "";
- m_SubKeySpecified = false;
- }
- else
- {
- m_SubKey = sk;
- m_SubKeySpecified = true;
- }
-}
-
-//----------------------------------------------------------------------------
-char *RegistryHelper::Strip(char *str)
-{
- int cc;
- size_t len;
- char *nstr;
- if ( !str )
- {
- return NULL;
- }
- len = strlen(str);
- nstr = str;
- for( cc=0; cc < static_cast<int>(len); cc++ )
- {
- if ( !isspace( *nstr ) )
- {
- break;
- }
- nstr ++;
- }
- for( cc= static_cast<int>(strlen(nstr))-1; cc>=0; cc-- )
- {
- if ( !isspace( nstr[cc] ) )
- {
- nstr[cc+1] = 0;
- break;
- }
- }
- return nstr;
-}
-
-//----------------------------------------------------------------------------
-void RegistryHelper::SetGlobalScope(bool b)
-{
- m_GlobalScope = b;
-}
-
-//----------------------------------------------------------------------------
-bool RegistryHelper::GetGlobalScope()
-{
- return m_GlobalScope;
-}
-
-//----------------------------------------------------------------------------
-kwsys_stl::string RegistryHelper::EncodeKey(const char* str)
-{
- kwsys_ios::ostringstream ostr;
- while ( *str )
- {
- switch ( *str )
- {
- case '%': case '=': case '\n': case '\r': case '\t':
- char buffer[4];
- sprintf(buffer, "%%%02X", *str);
- ostr << buffer;
- break;
- default:
- ostr << *str;
- }
- str ++;
- }
- return ostr.str();
-}
-
-//----------------------------------------------------------------------------
-kwsys_stl::string RegistryHelper::EncodeValue(const char* str)
-{
- kwsys_ios::ostringstream ostr;
- while ( *str )
- {
- switch ( *str )
- {
- case '%': case '=': case '\n': case '\r': case '\t':
- char buffer[4];
- sprintf(buffer, "%%%02X", *str);
- ostr << buffer;
- break;
- default:
- ostr << *str;
- }
- str ++;
- }
- return ostr.str();
-}
-
-//----------------------------------------------------------------------------
-kwsys_stl::string RegistryHelper::DecodeValue(const char* str)
-{
- kwsys_ios::ostringstream ostr;
- while ( *str )
- {
- unsigned int val;
- switch ( *str )
- {
- case '%':
- if ( *(str+1) && *(str+2) && sscanf(str+1, "%x", &val) == 1 )
- {
- ostr << static_cast<char>(val);
- str += 2;
- }
- else
- {
- ostr << *str;
- }
- break;
- default:
- ostr << *str;
- }
- str ++;
- }
- return ostr.str();
-}
-
-} // namespace KWSYS_NAMESPACE
diff --git a/Source/kwsys/Registry.hxx.in b/Source/kwsys/Registry.hxx.in
deleted file mode 100644
index ed9b01072..000000000
--- a/Source/kwsys/Registry.hxx.in
+++ /dev/null
@@ -1,107 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- 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 @KWSYS_NAMESPACE@_Registry_hxx
-#define @KWSYS_NAMESPACE@_Registry_hxx
-
-#include <@KWSYS_NAMESPACE@/Configure.h>
-
-#include <@KWSYS_NAMESPACE@/stl/string>
-
-namespace @KWSYS_NAMESPACE@
-{
-
-class RegistryHelper;
-
-/** \class Registry
- * \brief Portable registry class
- *
- * This class abstracts the storing of data that can be restored
- * when the program executes again. On Win32 platform it is
- * implemented using the registry and on unix as a file in
- * the user's home directory.
- */
-class @KWSYS_NAMESPACE@_EXPORT Registry
-{
-public:
- enum RegistryType
- {
-#ifdef _WIN32
- WIN32_REGISTRY,
-#endif
- FILE_REGISTRY
- };
-
-#ifdef _WIN32
- Registry(RegistryType registryType = WIN32_REGISTRY);
-#else
- Registry(RegistryType registryType = FILE_REGISTRY);
-#endif
-
- virtual ~Registry();
-
- //! Read a value from the registry.
- bool ReadValue(const char *subkey, const char *key, const char **value);
-
- //! Delete a key from the registry.
- bool DeleteKey(const char *subkey, const char *key);
-
- //! Delete a value from a given key.
- bool DeleteValue(const char *subkey, const char *key);
-
- //! Set value in a given key.
- bool SetValue(const char *subkey, const char *key,
- const char *value);
-
- //! Open the registry at toplevel/subkey.
- bool Open(const char *toplevel, const char *subkey,
- int readonly);
-
- //! Close the registry.
- bool Close();
-
- //! Read from local or global scope. On Windows this mean from local machine
- // or local user. On unix this will read from $HOME/.Projectrc or
- // /etc/Project
- void GlobalScopeOn() { this->SetGlobalScope(1); }
- void GlobalScopeOff() { this->SetGlobalScope(0); }
- void SetGlobalScope(bool b);
- bool GetGlobalScope();
-
- // Set or get the toplevel registry key.
- void SetTopLevel(const char* tl);
- const char* GetTopLevel();
-
- // Return true if registry opened
- bool GetOpened() { return m_Opened; }
-
- // Should the registry be locked?
- bool GetLocked() { return m_Locked; }
-
- enum {
- READONLY,
- READWRITE
- };
-
- // Return true if the character is space.
- int IsSpace(char c);
-
-private:
- RegistryHelper* Helper;
-
- bool m_Opened;
-
- bool m_Locked;
-}; // End Class: Registry
-
-} // namespace @KWSYS_NAMESPACE@
-
-#endif
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index e1ee873b4..9e2a93d7c 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -9,7 +9,12 @@
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
-#ifdef _WIN32
+
+#if defined(_WIN32)
+# define NOMINMAX // use our min,max
+# if !defined(_WIN32_WINNT) && !(defined(_MSC_VER) && _MSC_VER < 1300)
+# define _WIN32_WINNT 0x0501
+# endif
# include <winsock.h> // WSADATA, include before sys/types.h
#endif
@@ -33,6 +38,7 @@
#include KWSYS_HEADER(Process.h)
#include KWSYS_HEADER(ios/iostream)
#include KWSYS_HEADER(ios/sstream)
+#include KWSYS_HEADER(ios/fstream)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
@@ -45,66 +51,257 @@
# include "kwsys_stl_iosfwd.in"
# include "kwsys_ios_sstream.h.in"
# include "kwsys_ios_iostream.h.in"
+# include "kwsys_ios_fstream.h.in"
#endif
-#ifndef WIN32
+#if defined(_WIN32)
+# include <windows.h>
+# include <errno.h>
+# if defined(KWSYS_SYS_HAS_PSAPI)
+# include <psapi.h>
+# endif
+# if !defined(siginfo_t)
+typedef int siginfo_t;
+# endif
+#else
+# include <sys/types.h>
+# include <sys/time.h>
# include <sys/utsname.h> // int uname(struct utsname *buf);
+# include <sys/resource.h> // getrlimit
+# include <unistd.h>
+# include <signal.h>
+# include <fcntl.h>
+# include <errno.h> // extern int errno;
#endif
-#ifdef _WIN32
-# include <windows.h>
+#ifdef __FreeBSD__
+# include <sys/sysctl.h>
+# include <fenv.h>
+# include <sys/socket.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# if defined(KWSYS_SYS_HAS_IFADDRS_H)
+# include <ifaddrs.h>
+# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
+# endif
+#endif
+
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+# include <sys/param.h>
+# include <sys/sysctl.h>
+#endif
+
+#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H)
+# include <machine/cpu.h>
+#endif
+
+#if defined(__DragonFly__)
+# include <sys/sysctl.h>
#endif
#ifdef __APPLE__
-#include <sys/sysctl.h>
-#include <mach/vm_statistics.h>
-#include <mach/host_info.h>
-#include <mach/mach.h>
-#include <mach/mach_types.h>
+# include <sys/sysctl.h>
+# include <mach/vm_statistics.h>
+# include <mach/host_info.h>
+# include <mach/mach.h>
+# include <mach/mach_types.h>
+# include <fenv.h>
+# include <sys/socket.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# if defined(KWSYS_SYS_HAS_IFADDRS_H)
+# include <ifaddrs.h>
+# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
+# endif
+# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 >= 1050
+# include <execinfo.h>
+# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE
+# endif
#endif
#ifdef __linux
-# include <sys/types.h>
-# include <unistd.h>
-# include <fcntl.h>
-# include <ctype.h> // int isdigit(int c);
-# include <errno.h> // extern int errno;
-# include <sys/time.h>
+# include <fenv.h>
+# include <sys/socket.h>
+# include <netdb.h>
+# include <netinet/in.h>
+# if defined(KWSYS_SYS_HAS_IFADDRS_H)
+# include <ifaddrs.h>
+# if !defined(__LSB_VERSION__) /* LSB has no getifaddrs */
+# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
+# endif
+# endif
+# if defined(__GNUC__)
+# include <execinfo.h>
+# if !(defined(__LSB_VERSION__) && __LSB_VERSION__ < 41)
+# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE
+# endif
+# endif
+# if defined(KWSYS_CXX_HAS_RLIMIT64)
+typedef struct rlimit64 ResourceLimitType;
+# define GetResourceLimit getrlimit64
+# else
+typedef struct rlimit ResourceLimitType;
+# define GetResourceLimit getrlimit
+# endif
#elif defined( __hpux )
# include <sys/param.h>
# include <sys/pstat.h>
+# if defined(KWSYS_SYS_HAS_MPCTL_H)
+# include <sys/mpctl.h>
+# endif
#endif
#ifdef __HAIKU__
-#include <OS.h>
+# include <OS.h>
#endif
#include <memory.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <ctype.h> // int isdigit(int c);
+
+#if defined(KWSYS_USE_LONG_LONG)
+# if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)x)
+# endif
+#elif defined(KWSYS_USE___INT64)
+# if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)x)
+# endif
+#else
+# error "No Long Long"
+#endif
+#if defined(KWSYS_CXX_HAS_ATOLL)
+# define atoLongLong atoll
+#else
+# if defined(KWSYS_CXX_HAS__ATOI64)
+# define atoLongLong _atoi64
+# elif defined(KWSYS_CXX_HAS_ATOL)
+# define atoLongLong atol
+# else
+# define atoLongLong atoi
+# endif
+#endif
-namespace KWSYS_NAMESPACE
-{
+#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64)
+#define USE_ASM_INSTRUCTIONS 1
+#else
+#define USE_ASM_INSTRUCTIONS 0
+#endif
-// Create longlong
-#if KWSYS_USE_LONG_LONG
- typedef long long LongLong;
-#elif KWSYS_USE___INT64
- typedef __int64 LongLong;
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#include <intrin.h>
+#define USE_CPUID_INTRINSICS 1
#else
-# error "No Long Long"
+#define USE_CPUID_INTRINSICS 0
#endif
+#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS || defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
+# define USE_CPUID 1
+#else
+# define USE_CPUID 0
+#endif
+
+#if USE_CPUID
+
+#define CPUID_AWARE_COMPILER
+
+/**
+ * call CPUID instruction
+ *
+ * Will return false if the instruction failed.
+ */
+static bool call_cpuid(int select, int result[4])
+{
+#if USE_CPUID_INTRINSICS
+ __cpuid(result, select);
+ return true;
+#else
+ int tmp[4];
+#if defined(_MSC_VER)
+ // Use SEH to determine CPUID presence
+ __try {
+ _asm {
+#ifdef CPUID_AWARE_COMPILER
+ ; we must push/pop the registers <<CPUID>> writes to, as the
+ ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
+ ; these registers to change.
+ push eax
+ push ebx
+ push ecx
+ push edx
+#endif
+ ; <<CPUID>>
+ mov eax, select
+#ifdef CPUID_AWARE_COMPILER
+ cpuid
+#else
+ _asm _emit 0x0f
+ _asm _emit 0xa2
+#endif
+ mov tmp[0 * TYPE int], eax
+ mov tmp[1 * TYPE int], ebx
+ mov tmp[2 * TYPE int], ecx
+ mov tmp[3 * TYPE int], edx
+
+#ifdef CPUID_AWARE_COMPILER
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+#endif
+ }
+ }
+ __except(1)
+ {
+ return false;
+ }
+
+ memcpy(result, tmp, sizeof(tmp));
+#elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
+ unsigned int a, b, c, d;
+ __asm {
+ mov EAX, select;
+ cpuid
+ mov a, EAX;
+ mov b, EBX;
+ mov c, ECX;
+ mov d, EDX;
+ }
+
+ result[0] = a;
+ result[1] = b;
+ result[2] = c;
+ result[3] = d;
+#endif
+
+ // The cpuid instruction succeeded.
+ return true;
+#endif
+}
+#endif
+
+
+namespace KWSYS_NAMESPACE
+{
+template<typename T>
+T min(T a, T b){ return a<b ? a : b; }
+
+extern "C" { typedef void (*SigAction)(int,siginfo_t*,void*); }
// Define SystemInformationImplementation class
typedef void (*DELAY_FUNC)(unsigned int uiMS);
-
class SystemInformationImplementation
{
public:
+ typedef SystemInformation::LongLong LongLong;
SystemInformationImplementation ();
~SystemInformationImplementation ();
@@ -113,6 +310,7 @@ public:
kwsys_stl::string GetTypeID();
kwsys_stl::string GetFamilyID();
kwsys_stl::string GetModelID();
+ kwsys_stl::string GetModelName();
kwsys_stl::string GetSteppingCode();
const char * GetExtendedProcessorName();
const char * GetProcessorSerialNumber();
@@ -122,9 +320,10 @@ public:
int GetProcessorAPICID();
int GetProcessorCacheXSize(long int);
bool DoesCPUSupportFeature(long int);
-
+
const char * GetOSName();
const char * GetHostname();
+ int GetFullyQualifiedDomainName(kwsys_stl::string &fqdn);
const char * GetOSRelease();
const char * GetOSVersion();
const char * GetOSPlatform();
@@ -140,7 +339,23 @@ public:
size_t GetTotalVirtualMemory();
size_t GetAvailableVirtualMemory();
size_t GetTotalPhysicalMemory();
- size_t GetAvailablePhysicalMemory();
+ size_t GetAvailablePhysicalMemory();
+
+ LongLong GetProcessId();
+
+ // Retrieve memory information in kib
+ LongLong GetHostMemoryTotal();
+ LongLong GetHostMemoryAvailable(const char *envVarName);
+ LongLong GetHostMemoryUsed();
+
+ LongLong GetProcMemoryAvailable(
+ const char *hostLimitEnvVarName,
+ const char *procLimitEnvVarName);
+ LongLong GetProcMemoryUsed();
+
+ // enable/disable stack trace signal handler.
+ static
+ void SetStackTraceOnError(int enable);
/** Run the different checks */
void RunCPUCheck();
@@ -159,6 +374,7 @@ public:
kwsys_stl::string ProcessorName;
kwsys_stl::string Vendor;
kwsys_stl::string SerialNumber;
+ kwsys_stl::string ModelName;
} ID;
typedef struct tagCPUPowerManagement
@@ -206,7 +422,7 @@ public:
enum Manufacturer
{
AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta, Sun, IBM,
- Motorola, UnknownManufacturer
+ Motorola, HP, UnknownManufacturer
};
protected:
@@ -234,28 +450,32 @@ protected:
int CPUCount();
unsigned char LogicalCPUPerPhysicalCPU();
unsigned char GetAPICId();
- unsigned int IsHyperThreadingSupported();
- LongLong GetCyclesDifference(DELAY_FUNC, unsigned int);
+ bool IsHyperThreadingSupported();
+ static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int);
// For Linux and Cygwin, /proc/cpuinfo formats are slightly different
- int RetreiveInformationFromCpuInfoFile();
+ bool RetreiveInformationFromCpuInfoFile();
kwsys_stl::string ExtractValueFromCpuInfoFile(kwsys_stl::string buffer,
const char* word, size_t init=0);
+ bool QueryLinuxMemory();
+ bool QueryCygwinMemory();
+
static void Delay (unsigned int);
static void DelayOverhead (unsigned int);
- void FindManufacturer();
+ void FindManufacturer(const kwsys_stl::string &family = "");
// For Mac
bool ParseSysCtl();
- void CallSwVers();
+ int CallSwVers(const char *arg, kwsys_stl::string &ver);
void TrimNewline(kwsys_stl::string&);
kwsys_stl::string ExtractValueFromSysCtl(const char* word);
kwsys_stl::string SysCtlBuffer;
// For Solaris
- bool QuerySolarisInfo();
+ bool QuerySolarisMemory();
+ bool QuerySolarisProcessor();
kwsys_stl::string ParseValueFromKStat(const char* arguments);
kwsys_stl::string RunProcess(kwsys_stl::vector<const char*> args);
@@ -266,8 +486,26 @@ protected:
bool QueryQNXMemory();
bool QueryQNXProcessor();
+ //For OpenBSD, FreeBSD, NetBSD, DragonFly
+ bool QueryBSDMemory();
+ bool QueryBSDProcessor();
+
+ //For HP-UX
+ bool QueryHPUXMemory();
+ bool QueryHPUXProcessor();
+
+ //For Microsoft Windows
+ bool QueryWindowsMemory();
+
+ //For AIX
+ bool QueryAIXMemory();
+
+ bool QueryProcessorBySysconf();
+ bool QueryProcessor();
+
// Evaluate the memory information.
- int QueryMemory();
+ bool QueryMemoryBySysconf();
+ bool QueryMemory();
size_t TotalVirtualMemory;
size_t AvailableVirtualMemory;
size_t TotalPhysicalMemory;
@@ -281,7 +519,7 @@ protected:
kwsys_stl::string Hostname;
kwsys_stl::string OSRelease;
kwsys_stl::string OSVersion;
- kwsys_stl::string OSPlatform;
+ kwsys_stl::string OSPlatform;
};
@@ -320,6 +558,11 @@ kwsys_stl::string SystemInformation::GetModelID()
return this->Implementation->GetModelID();
}
+kwsys_stl::string SystemInformation::GetModelName()
+{
+ return this->Implementation->GetModelName();
+}
+
kwsys_stl::string SystemInformation::GetSteppingCode()
{
return this->Implementation->GetSteppingCode();
@@ -365,6 +608,37 @@ bool SystemInformation::DoesCPUSupportFeature(long int i)
return this->Implementation->DoesCPUSupportFeature(i);
}
+kwsys_stl::string SystemInformation::GetCPUDescription()
+{
+ kwsys_ios::ostringstream oss;
+ oss
+ << this->GetNumberOfPhysicalCPU()
+ << " core ";
+ if (this->GetModelName().empty())
+ {
+ oss
+ << this->GetProcessorClockFrequency()
+ << " MHz "
+ << this->GetVendorString()
+ << " "
+ << this->GetExtendedProcessorName();
+ }
+ else
+ {
+ oss << this->GetModelName();
+ }
+
+ // remove extra spaces
+ kwsys_stl::string tmp=oss.str();
+ size_t pos;
+ while( (pos=tmp.find(" "))!=kwsys_stl::string::npos)
+ {
+ tmp.replace(pos,2," ");
+ }
+
+ return tmp;
+}
+
const char * SystemInformation::GetOSName()
{
return this->Implementation->GetOSName();
@@ -375,6 +649,13 @@ const char * SystemInformation::GetHostname()
return this->Implementation->GetHostname();
}
+kwsys_stl::string SystemInformation::GetFullyQualifiedDomainName()
+{
+ kwsys_stl::string fqdn;
+ this->Implementation->GetFullyQualifiedDomainName(fqdn);
+ return fqdn;
+}
+
const char * SystemInformation::GetOSRelease()
{
return this->Implementation->GetOSRelease();
@@ -390,6 +671,46 @@ const char * SystemInformation::GetOSPlatform()
return this->Implementation->GetOSPlatform();
}
+int SystemInformation::GetOSIsWindows()
+{
+#if defined(_WIN32)
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+int SystemInformation::GetOSIsLinux()
+{
+#if defined(__linux)
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+int SystemInformation::GetOSIsApple()
+{
+#if defined(__APPLE__)
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+kwsys_stl::string SystemInformation::GetOSDescription()
+{
+ kwsys_ios::ostringstream oss;
+ oss
+ << this->GetOSName()
+ << " "
+ << this->GetOSRelease()
+ << " "
+ << this->GetOSVersion();
+
+ return oss.str();
+}
+
bool SystemInformation::Is64Bits()
{
return this->Implementation->Is64Bits();
@@ -431,6 +752,66 @@ size_t SystemInformation::GetAvailablePhysicalMemory()
return this->Implementation->GetAvailablePhysicalMemory();
}
+kwsys_stl::string SystemInformation::GetMemoryDescription(
+ const char *hostLimitEnvVarName,
+ const char *procLimitEnvVarName)
+{
+ kwsys_ios::ostringstream oss;
+ oss
+ << "Host Total: "
+ << iostreamLongLong(this->GetHostMemoryTotal())
+ << " KiB, Host Available: "
+ << iostreamLongLong(this->GetHostMemoryAvailable(hostLimitEnvVarName))
+ << " KiB, Process Available: "
+ << iostreamLongLong(
+ this->GetProcMemoryAvailable(hostLimitEnvVarName,procLimitEnvVarName))
+ << " KiB";
+ return oss.str();
+}
+
+// host memory info in units of KiB.
+SystemInformation::LongLong SystemInformation::GetHostMemoryTotal()
+{
+ return this->Implementation->GetHostMemoryTotal();
+}
+
+SystemInformation::LongLong
+SystemInformation::GetHostMemoryAvailable(const char *hostLimitEnvVarName)
+{
+ return this->Implementation->GetHostMemoryAvailable(hostLimitEnvVarName);
+}
+
+SystemInformation::LongLong SystemInformation::GetHostMemoryUsed()
+{
+ return this->Implementation->GetHostMemoryUsed();
+}
+
+// process memory info in units of KiB.
+SystemInformation::LongLong
+SystemInformation::GetProcMemoryAvailable(
+ const char *hostLimitEnvVarName,
+ const char *procLimitEnvVarName)
+{
+ return this->Implementation->GetProcMemoryAvailable(
+ hostLimitEnvVarName,
+ procLimitEnvVarName);
+}
+
+SystemInformation::LongLong SystemInformation::GetProcMemoryUsed()
+{
+ return this->Implementation->GetProcMemoryUsed();
+}
+
+SystemInformation::LongLong SystemInformation::GetProcessId()
+{
+ return this->Implementation->GetProcessId();
+}
+
+void SystemInformation::SetStackTraceOnError(int enable)
+{
+ SystemInformationImplementation::SetStackTraceOnError(enable);
+}
+
/** Run the different checks */
void SystemInformation::RunCPUCheck()
{
@@ -451,24 +832,11 @@ void SystemInformation::RunMemoryCheck()
// --------------------------------------------------------------
// SystemInformationImplementation starts here
-#if defined(_MSC_VER) && (_MSC_VER >= 1300) && !defined(_WIN64)
-#define USE_ASM_INSTRUCTIONS 1
-#else
-#define USE_ASM_INSTRUCTIONS 0
-#endif
-
#define STORE_TLBCACHE_INFO(x,y) x = (x < y) ? y : x
#define TLBCACHE_INFO_UNITS (15)
#define CLASSICAL_CPU_FREQ_LOOP 10000000
#define RDTSC_INSTRUCTION _asm _emit 0x0f _asm _emit 0x31
-#define CPUID_AWARE_COMPILER
-#ifdef CPUID_AWARE_COMPILER
- #define CPUID_INSTRUCTION cpuid
-#else
- #define CPUID_INSTRUCTION _asm _emit 0x0f _asm _emit 0xa2
-#endif
-
#define MMX_FEATURE 0x00000001
#define MMX_PLUS_FEATURE 0x00000002
#define SSE_FEATURE 0x00000004
@@ -501,22 +869,365 @@ void SystemInformation::RunMemoryCheck()
#define HT_CANNOT_DETECT 4
// EDX[28] Bit 28 is set if HT is supported
-#define HT_BIT 0x10000000
+#define HT_BIT 0x10000000
// EAX[11:8] Bit 8-11 contains family processor ID.
#define FAMILY_ID 0x0F00
-#define PENTIUM4_ID 0x0F00
+#define PENTIUM4_ID 0x0F00
// EAX[23:20] Bit 20-23 contains extended family processor ID
-#define EXT_FAMILY_ID 0x0F00000
+#define EXT_FAMILY_ID 0x0F00000
// EBX[23:16] Bit 16-23 in ebx contains the number of logical
-#define NUM_LOGICAL_BITS 0x00FF0000
-// processors per physical processor when execute cpuid with
+#define NUM_LOGICAL_BITS 0x00FF0000
+// processors per physical processor when execute cpuid with
// eax set to 1
-// EBX[31:24] Bits 24-31 (8 bits) return the 8-bit unique
-#define INITIAL_APIC_ID_BITS 0xFF000000
+// EBX[31:24] Bits 24-31 (8 bits) return the 8-bit unique
+#define INITIAL_APIC_ID_BITS 0xFF000000
// initial APIC ID for the processor this code is running on.
// Default value = 0xff if HT is not supported
+// Hide implementation details in an anonymous namespace.
+namespace {
+// *****************************************************************************
+#if defined(__linux) || defined(__APPLE__)
+int LoadLines(
+ FILE *file,
+ kwsys_stl::vector<kwsys_stl::string> &lines)
+{
+ // Load each line in the given file into a the vector.
+ int nRead=0;
+ const int bufSize=1024;
+ char buf[bufSize]={'\0'};
+ while (!feof(file) && !ferror(file))
+ {
+ errno=0;
+ if (fgets(buf,bufSize,file) == 0)
+ {
+ if (ferror(file) && (errno==EINTR))
+ {
+ clearerr(file);
+ }
+ continue;
+ }
+ lines.push_back(buf);
+ ++nRead;
+ }
+ if (ferror(file))
+ {
+ return 0;
+ }
+ return nRead;
+}
+
+# if defined(__linux)
+// *****************************************************************************
+int LoadLines(
+ const char *fileName,
+ kwsys_stl::vector<kwsys_stl::string> &lines)
+{
+ FILE *file=fopen(fileName,"r");
+ if (file==0)
+ {
+ return 0;
+ }
+ int nRead=LoadLines(file,lines);
+ fclose(file);
+ return nRead;
+}
+# endif
+
+// ****************************************************************************
+template<typename T>
+int NameValue(
+ kwsys_stl::vector<kwsys_stl::string> &lines,
+ kwsys_stl::string name, T &value)
+{
+ size_t nLines=lines.size();
+ for (size_t i=0; i<nLines; ++i)
+ {
+ size_t at=lines[i].find(name);
+ if (at==kwsys_stl::string::npos)
+ {
+ continue;
+ }
+ kwsys_ios::istringstream is(lines[i].substr(at+name.size()));
+ is >> value;
+ return 0;
+ }
+ return -1;
+}
+#endif
+
+#if defined(__linux)
+// ****************************************************************************
+template<typename T>
+int GetFieldsFromFile(
+ const char *fileName,
+ const char **fieldNames,
+ T *values)
+{
+ kwsys_stl::vector<kwsys_stl::string> fields;
+ if (!LoadLines(fileName,fields))
+ {
+ return -1;
+ }
+ int i=0;
+ while (fieldNames[i]!=NULL)
+ {
+ int ierr=NameValue(fields,fieldNames[i],values[i]);
+ if (ierr)
+ {
+ return -(i+2);
+ }
+ i+=1;
+ }
+ return 0;
+}
+
+// ****************************************************************************
+template<typename T>
+int GetFieldFromFile(
+ const char *fileName,
+ const char *fieldName,
+ T &value)
+{
+ const char *fieldNames[2]={fieldName,NULL};
+ T values[1]={T(0)};
+ int ierr=GetFieldsFromFile(fileName,fieldNames,values);
+ if (ierr)
+ {
+ return ierr;
+ }
+ value=values[0];
+ return 0;
+}
+#endif
+
+// ****************************************************************************
+#if defined(__APPLE__)
+template<typename T>
+int GetFieldsFromCommand(
+ const char *command,
+ const char **fieldNames,
+ T *values)
+{
+ FILE *file=popen(command,"r");
+ if (file==0)
+ {
+ return -1;
+ }
+ kwsys_stl::vector<kwsys_stl::string> fields;
+ int nl=LoadLines(file,fields);
+ pclose(file);
+ if (nl==0)
+ {
+ return -1;
+ }
+ int i=0;
+ while (fieldNames[i]!=NULL)
+ {
+ int ierr=NameValue(fields,fieldNames[i],values[i]);
+ if (ierr)
+ {
+ return -(i+2);
+ }
+ i+=1;
+ }
+ return 0;
+}
+#endif
+
+// ****************************************************************************
+#if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+void StacktraceSignalHandler(
+ int sigNo,
+ siginfo_t *sigInfo,
+ void * /*sigContext*/)
+{
+#if defined(__linux) || defined(__APPLE__)
+ kwsys_ios::ostringstream oss;
+ oss
+ << "=========================================================" << kwsys_ios::endl
+ << "Process id " << getpid() << " ";
+ switch (sigNo)
+ {
+ case SIGFPE:
+ oss << "Caught SIGFPE ";
+ switch (sigInfo->si_code)
+ {
+# if defined(FPE_INTDIV)
+ case FPE_INTDIV:
+ oss << "integer division by zero";
+ break;
+# endif
+
+# if defined(FPE_INTOVF)
+ case FPE_INTOVF:
+ oss << "integer overflow";
+ break;
+# endif
+
+ case FPE_FLTDIV:
+ oss << "floating point divide by zero";
+ break;
+
+ case FPE_FLTOVF:
+ oss << "floating point overflow";
+ break;
+
+ case FPE_FLTUND:
+ oss << "floating point underflow";
+ break;
+
+ case FPE_FLTRES:
+ oss << "floating point inexact result";
+ break;
+
+ case FPE_FLTINV:
+ oss << "floating point invalid operation";
+ break;
+
+#if defined(FPE_FLTSUB)
+ case FPE_FLTSUB:
+ oss << "floating point subscript out of range";
+ break;
+#endif
+
+ default:
+ oss << "code " << sigInfo->si_code;
+ break;
+ }
+ break;
+
+ case SIGSEGV:
+ oss << "Caught SIGSEGV ";
+ switch (sigInfo->si_code)
+ {
+ case SEGV_MAPERR:
+ oss << "address not mapped to object";
+ break;
+
+ case SEGV_ACCERR:
+ oss << "invalid permission for mapped object";
+ break;
+
+ default:
+ oss << "code " << sigInfo->si_code;
+ break;
+ }
+ break;
+
+ case SIGINT:
+ oss << "Caught SIGTERM";
+ break;
+
+ case SIGTERM:
+ oss << "Caught SIGTERM";
+ break;
+
+ case SIGBUS:
+ oss << "Caught SIGBUS type ";
+ switch (sigInfo->si_code)
+ {
+ case BUS_ADRALN:
+ oss << "invalid address alignment";
+ break;
+
+# if defined(BUS_ADRERR)
+ case BUS_ADRERR:
+ oss << "non-exestent physical address";
+ break;
+# endif
+
+# if defined(BUS_OBJERR)
+ case BUS_OBJERR:
+ oss << "object specific hardware error";
+ break;
+# endif
+
+ default:
+ oss << "code " << sigInfo->si_code;
+ break;
+ }
+ break;
+
+ case SIGILL:
+ oss << "Caught SIGILL ";
+ switch (sigInfo->si_code)
+ {
+ case ILL_ILLOPC:
+ oss << "illegal opcode";
+ break;
+
+# if defined(ILL_ILLOPN)
+ case ILL_ILLOPN:
+ oss << "illegal operand";
+ break;
+# endif
+
+# if defined(ILL_ILLADR)
+ case ILL_ILLADR:
+ oss << "illegal addressing mode.";
+ break;
+# endif
+
+ case ILL_ILLTRP:
+ oss << "illegal trap";
+
+ case ILL_PRVOPC:
+ oss << "privileged opcode";
+ break;
+
+# if defined(ILL_PRVREG)
+ case ILL_PRVREG:
+ oss << "privileged register";
+ break;
+# endif
+
+# if defined(ILL_COPROC)
+ case ILL_COPROC:
+ oss << "co-processor error";
+ break;
+# endif
+
+# if defined(ILL_BADSTK)
+ case ILL_BADSTK:
+ oss << "internal stack error";
+ break;
+# endif
+
+ default:
+ oss << "code " << sigInfo->si_code;
+ break;
+ }
+ break;
+
+ default:
+ oss << "Caught " << sigNo << " code " << sigInfo->si_code;
+ break;
+ }
+ oss << kwsys_ios::endl;
+#if defined(KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE)
+ oss << "Program Stack:" << kwsys_ios::endl;
+ void *stackSymbols[128];
+ int n=backtrace(stackSymbols,128);
+ char **stackText=backtrace_symbols(stackSymbols,n);
+ for (int i=0; i<n; ++i)
+ {
+ oss << " " << stackText[i] << kwsys_ios::endl;
+ }
+#endif
+ oss
+ << "=========================================================" << kwsys_ios::endl;
+ kwsys_ios::cerr << oss.str() << kwsys_ios::endl;
+ abort();
+#else
+ // avoid warning C4100
+ (void)sigNo;
+ (void)sigInfo;
+#endif
+}
+#endif
+} // anonymous namespace
SystemInformationImplementation::SystemInformationImplementation()
{
@@ -557,6 +1268,7 @@ void SystemInformationImplementation::RunCPUCheck()
{
// Retrieve the CPU details.
RetrieveCPUIdentity();
+ this->FindManufacturer();
RetrieveCPUFeatures();
}
@@ -573,13 +1285,13 @@ void SystemInformationImplementation::RunCPUCheck()
if (supportsCPUID)
{
// Retrieve cache information.
- if (!RetrieveCPUCacheDetails())
+ if (!RetrieveCPUCacheDetails())
{
RetrieveClassicalCPUCacheDetails();
}
// Retrieve the extended CPU details.
- if (!RetrieveExtendedCPUIdentity())
+ if (!RetrieveExtendedCPUIdentity())
{
RetrieveClassicalCPUIdentity();
}
@@ -596,13 +1308,19 @@ void SystemInformationImplementation::RunCPUCheck()
#elif defined(__APPLE__)
this->ParseSysCtl();
#elif defined (__SVR4) && defined (__sun)
- this->QuerySolarisInfo();
+ this->QuerySolarisProcessor();
#elif defined(__HAIKU__)
this->QueryHaikuInfo();
#elif defined(__QNX__)
this->QueryQNXProcessor();
-#else
+#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+ this->QueryBSDProcessor();
+#elif defined(__hpux)
+ this->QueryHPUXProcessor();
+#elif defined(__linux) || defined(__CYGWIN__)
this->RetreiveInformationFromCpuInfoFile();
+#else
+ this->QueryProcessor();
#endif
}
@@ -616,11 +1334,23 @@ void SystemInformationImplementation::RunMemoryCheck()
#if defined(__APPLE__)
this->ParseSysCtl();
#elif defined (__SVR4) && defined (__sun)
- this->QuerySolarisInfo();
+ this->QuerySolarisMemory();
#elif defined(__HAIKU__)
this->QueryHaikuInfo();
#elif defined(__QNX__)
this->QueryQNXMemory();
+#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+ this->QueryBSDMemory();
+#elif defined(__CYGWIN__)
+ this->QueryCygwinMemory();
+#elif defined(_WIN32)
+ this->QueryWindowsMemory();
+#elif defined(__hpux)
+ this->QueryHPUXMemory();
+#elif defined(__linux)
+ this->QueryLinuxMemory();
+#elif defined(_AIX)
+ this->QueryAIXMemory();
#else
this->QueryMemory();
#endif
@@ -641,9 +1371,145 @@ const char * SystemInformationImplementation::GetOSName()
/** Get the hostname */
const char* SystemInformationImplementation::GetHostname()
{
+ if (this->Hostname.empty())
+ {
+ this->Hostname="localhost";
+#if defined(_WIN32)
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ char name[255];
+ wVersionRequested = MAKEWORD(2,0);
+ if ( WSAStartup( wVersionRequested, &wsaData ) == 0 )
+ {
+ gethostname(name,sizeof(name));
+ WSACleanup( );
+ }
+ this->Hostname = name;
+#else
+ struct utsname unameInfo;
+ int errorFlag = uname(&unameInfo);
+ if(errorFlag == 0)
+ {
+ this->Hostname = unameInfo.nodename;
+ }
+#endif
+ }
return this->Hostname.c_str();
}
+/** Get the FQDN */
+int SystemInformationImplementation::GetFullyQualifiedDomainName(
+ kwsys_stl::string &fqdn)
+{
+ // in the event of absolute failure return localhost.
+ fqdn="localhost";
+
+#if defined(_WIN32)
+ int ierr;
+ // TODO - a more robust implementation for windows, see comments
+ // in unix implementation.
+ WSADATA wsaData;
+ WORD ver=MAKEWORD(2,0);
+ ierr=WSAStartup(ver,&wsaData);
+ if (ierr)
+ {
+ return -1;
+ }
+
+ char base[256]={'\0'};
+ ierr=gethostname(base,256);
+ if (ierr)
+ {
+ WSACleanup();
+ return -2;
+ }
+ fqdn=base;
+
+ HOSTENT *hent=gethostbyname(base);
+ if (hent)
+ {
+ fqdn=hent->h_name;
+ }
+
+ WSACleanup();
+ return 0;
+
+#elif defined(KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN)
+ // gethostname typical returns an alias for loopback interface
+ // we want the fully qualified domain name. Because there are
+ // any number of interfaces on this system we look for the
+ // first of these that contains the name returned by gethostname
+ // and is longer. failing that we return gethostname and indicate
+ // with a failure code. Return of a failure code is not necessarilly
+ // an indication of an error. for instance gethostname may return
+ // the fully qualified domain name, or there may not be one if the
+ // system lives on a private network such as in the case of a cluster
+ // node.
+
+ int ierr=0;
+ char base[NI_MAXHOST];
+ ierr=gethostname(base,NI_MAXHOST);
+ if (ierr)
+ {
+ return -1;
+ }
+ size_t baseSize=strlen(base);
+ fqdn=base;
+
+ struct ifaddrs *ifas;
+ struct ifaddrs *ifa;
+ ierr=getifaddrs(&ifas);
+ if (ierr)
+ {
+ return -2;
+ }
+
+ for (ifa=ifas; ifa!=NULL; ifa=ifa->ifa_next)
+ {
+ int fam = ifa->ifa_addr? ifa->ifa_addr->sa_family : -1;
+ if ((fam==AF_INET) || (fam==AF_INET6))
+ {
+ char host[NI_MAXHOST]={'\0'};
+
+ int addrlen
+ = (fam==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6));
+
+ ierr=getnameinfo(
+ ifa->ifa_addr,
+ addrlen,
+ host,
+ NI_MAXHOST,
+ NULL,
+ 0,
+ NI_NAMEREQD);
+ if (ierr)
+ {
+ // don't report the failure now since we may succeed on another
+ // interface. If all attempts fail then return the failure code.
+ ierr=-3;
+ continue;
+ }
+
+ kwsys_stl::string candidate=host;
+ if ((candidate.find(base)!=kwsys_stl::string::npos) && baseSize<candidate.size())
+ {
+ // success, stop now.
+ ierr=0;
+ fqdn=candidate;
+ break;
+ }
+ }
+ }
+ freeifaddrs(ifas);
+
+ return ierr;
+#else
+ /* TODO: Implement on more platforms. */
+ fqdn=this->GetHostname();
+ return -1;
+#endif
+}
+
/** Get the OS release */
const char* SystemInformationImplementation::GetOSRelease()
{
@@ -692,6 +1558,8 @@ const char * SystemInformationImplementation::GetVendorID()
return "IBM";
case Motorola:
return "Motorola";
+ case HP:
+ return "Hewlett-Packard";
default:
return "Unknown Manufacturer";
}
@@ -721,9 +1589,15 @@ kwsys_stl::string SystemInformationImplementation::GetModelID()
return str.str();
}
+// Return the model name of CPU present */
+kwsys_stl::string SystemInformationImplementation::GetModelName()
+{
+ return this->ChipID.ModelName;
+}
+
/** Return the stepping code of the CPU present. */
kwsys_stl::string SystemInformationImplementation::GetSteppingCode()
-{
+{
kwsys_ios::ostringstream str;
str << this->ChipID.Revision;
return str.str();
@@ -734,8 +1608,8 @@ const char * SystemInformationImplementation::GetExtendedProcessorName()
{
return this->ChipID.ProcessorName.c_str();
}
-
-/** Return the serial number of the processor
+
+/** Return the serial number of the processor
* in hexadecimal: xxxx-xxxx-xxxx-xxxx-xxxx-xxxx. */
const char * SystemInformationImplementation::GetProcessorSerialNumber()
{
@@ -870,7 +1744,7 @@ void SystemInformationImplementation::Delay(unsigned int uiMS)
QueryPerformanceCounter (&StartCounter);
do {
- // Get the ending position of the counter.
+ // Get the ending position of the counter.
QueryPerformanceCounter (&EndCounter);
} while (EndCounter.QuadPart - StartCounter.QuadPart < x);
#endif
@@ -880,40 +1754,15 @@ void SystemInformationImplementation::Delay(unsigned int uiMS)
bool SystemInformationImplementation::DoesCPUSupportCPUID()
{
-#if USE_ASM_INSTRUCTIONS
- // Use SEH to determine CPUID presence
- __try {
- _asm {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- mov eax, 0
- CPUID_INSTRUCTION
+#if USE_CPUID
+ int dummy[4] = { 0, 0, 0, 0 };
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
+#if USE_ASM_INSTRUCTIONS
+ return call_cpuid(0, dummy);
+#else
+ call_cpuid(0, dummy);
+ return dummy[0] || dummy[1] || dummy[2] || dummy[3];
#endif
- }
- }
- __except(1)
- {
- // Stop the class from trying to use CPUID again!
- return false;
- }
-
- // The cpuid instruction succeeded.
- return true;
-
#else
// Assume no cpuid instruction.
return false;
@@ -923,97 +1772,71 @@ bool SystemInformationImplementation::DoesCPUSupportCPUID()
bool SystemInformationImplementation::RetrieveCPUFeatures()
{
-#if USE_ASM_INSTRUCTIONS
- int localCPUFeatures = 0;
- int localCPUAdvanced = 0;
+#if USE_CPUID
+ int cpuinfo[4] = { 0, 0, 0, 0 };
- // Use assembly to detect CPUID information...
- __try {
- _asm {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
- ; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
- ; edx: CPU feature flags
- mov eax,1
- CPUID_INSTRUCTION
- mov localCPUFeatures, edx
- mov localCPUAdvanced, ebx
-
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
-#endif
- }
- }
- __except(1)
+ if (!call_cpuid(1, cpuinfo))
{
return false;
}
// Retrieve the features of CPU present.
- this->Features.HasFPU = ((localCPUFeatures & 0x00000001) != 0); // FPU Present --> Bit 0
- this->Features.HasTSC = ((localCPUFeatures & 0x00000010) != 0); // TSC Present --> Bit 4
- this->Features.HasAPIC = ((localCPUFeatures & 0x00000200) != 0); // APIC Present --> Bit 9
- this->Features.HasMTRR = ((localCPUFeatures & 0x00001000) != 0); // MTRR Present --> Bit 12
- this->Features.HasCMOV = ((localCPUFeatures & 0x00008000) != 0); // CMOV Present --> Bit 15
- this->Features.HasSerial = ((localCPUFeatures & 0x00040000) != 0); // Serial Present --> Bit 18
- this->Features.HasACPI = ((localCPUFeatures & 0x00400000) != 0); // ACPI Capable --> Bit 22
- this->Features.HasMMX = ((localCPUFeatures & 0x00800000) != 0); // MMX Present --> Bit 23
- this->Features.HasSSE = ((localCPUFeatures & 0x02000000) != 0); // SSE Present --> Bit 25
- this->Features.HasSSE2 = ((localCPUFeatures & 0x04000000) != 0); // SSE2 Present --> Bit 26
- this->Features.HasThermal = ((localCPUFeatures & 0x20000000) != 0); // Thermal Monitor Present --> Bit 29
- this->Features.HasIA64 = ((localCPUFeatures & 0x40000000) != 0); // IA64 Present --> Bit 30
+ this->Features.HasFPU = ((cpuinfo[3] & 0x00000001) != 0); // FPU Present --> Bit 0
+ this->Features.HasTSC = ((cpuinfo[3] & 0x00000010) != 0); // TSC Present --> Bit 4
+ this->Features.HasAPIC = ((cpuinfo[3] & 0x00000200) != 0); // APIC Present --> Bit 9
+ this->Features.HasMTRR = ((cpuinfo[3] & 0x00001000) != 0); // MTRR Present --> Bit 12
+ this->Features.HasCMOV = ((cpuinfo[3] & 0x00008000) != 0); // CMOV Present --> Bit 15
+ this->Features.HasSerial = ((cpuinfo[3] & 0x00040000) != 0); // Serial Present --> Bit 18
+ this->Features.HasACPI = ((cpuinfo[3] & 0x00400000) != 0); // ACPI Capable --> Bit 22
+ this->Features.HasMMX = ((cpuinfo[3] & 0x00800000) != 0); // MMX Present --> Bit 23
+ this->Features.HasSSE = ((cpuinfo[3] & 0x02000000) != 0); // SSE Present --> Bit 25
+ this->Features.HasSSE2 = ((cpuinfo[3] & 0x04000000) != 0); // SSE2 Present --> Bit 26
+ this->Features.HasThermal = ((cpuinfo[3] & 0x20000000) != 0); // Thermal Monitor Present --> Bit 29
+ this->Features.HasIA64 = ((cpuinfo[3] & 0x40000000) != 0); // IA64 Present --> Bit 30
+#if USE_ASM_INSTRUCTIONS
// Retrieve extended SSE capabilities if SSE is available.
if (this->Features.HasSSE) {
-
+
// Attempt to __try some SSE FP instructions.
- __try
+ __try
{
// Perform: orps xmm0, xmm0
- _asm
+ _asm
{
_emit 0x0f
_emit 0x56
- _emit 0xc0
+ _emit 0xc0
}
// SSE FP capable processor.
this->Features.HasSSEFP = true;
- }
- __except(1)
+ }
+ __except(1)
{
// bad instruction - processor or OS cannot handle SSE FP.
this->Features.HasSSEFP = false;
}
- }
- else
+ }
+ else
{
// Set the advanced SSE capabilities to not available.
this->Features.HasSSEFP = false;
}
+#else
+ this->Features.HasSSEFP = false;
+#endif
// Retrieve Intel specific extended features.
- if (this->ChipManufacturer == Intel)
+ if (this->ChipManufacturer == Intel)
{
- this->Features.ExtendedFeatures.SupportsHyperthreading = ((localCPUFeatures & 0x10000000) != 0); // Intel specific: Hyperthreading --> Bit 28
- this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = (this->Features.ExtendedFeatures.SupportsHyperthreading) ? ((localCPUAdvanced & 0x00FF0000) >> 16) : 1;
-
+ this->Features.ExtendedFeatures.SupportsHyperthreading = ((cpuinfo[3] & 0x10000000) != 0); // Intel specific: Hyperthreading --> Bit 28
+ this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = (this->Features.ExtendedFeatures.SupportsHyperthreading) ? ((cpuinfo[1] & 0x00FF0000) >> 16) : 1;
+
if ((this->Features.ExtendedFeatures.SupportsHyperthreading) && (this->Features.HasAPIC))
{
// Retrieve APIC information if there is one present.
- this->Features.ExtendedFeatures.APIC_ID = ((localCPUAdvanced & 0xFF000000) >> 24);
+ this->Features.ExtendedFeatures.APIC_ID = ((cpuinfo[1] & 0xFF000000) >> 24);
}
}
@@ -1026,7 +1849,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
/** Find the manufacturer given the vendor id */
-void SystemInformationImplementation::FindManufacturer()
+void SystemInformationImplementation::FindManufacturer(const kwsys_stl::string& family)
{
if (this->ChipID.Vendor == "GenuineIntel") this->ChipManufacturer = Intel; // Intel Corp.
else if (this->ChipID.Vendor == "UMC UMC UMC ") this->ChipManufacturer = UMC; // United Microelectronics Corp.
@@ -1041,7 +1864,9 @@ void SystemInformationImplementation::FindManufacturer()
else if (this->ChipID.Vendor == "Geode By NSC") this->ChipManufacturer = NSC; // National Semiconductor
else if (this->ChipID.Vendor == "Sun") this->ChipManufacturer = Sun; // Sun Microelectronics
else if (this->ChipID.Vendor == "IBM") this->ChipManufacturer = IBM; // IBM Microelectronics
+ else if (this->ChipID.Vendor == "Hewlett-Packard") this->ChipManufacturer = HP; // Hewlett-Packard
else if (this->ChipID.Vendor == "Motorola") this->ChipManufacturer = Motorola; // Motorola Microelectronics
+ else if (family.substr(0, 7) == "PA-RISC") this->ChipManufacturer = HP; // Hewlett-Packard
else this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer
}
@@ -1049,73 +1874,41 @@ void SystemInformationImplementation::FindManufacturer()
/** */
bool SystemInformationImplementation::RetrieveCPUIdentity()
{
-#if USE_ASM_INSTRUCTIONS
- int localCPUVendor[3];
- int localCPUSignature;
+#if USE_CPUID
+ int localCPUVendor[4];
+ int localCPUSignature[4];
- // Use assembly to detect CPUID information...
- __try
+ if (!call_cpuid(0, localCPUVendor))
{
- _asm
- {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- ; eax = 0 --> eax: maximum value of CPUID instruction.
- ; ebx: part 1 of 3; CPU signature.
- ; edx: part 2 of 3; CPU signature.
- ; ecx: part 3 of 3; CPU signature.
- mov eax, 0
- CPUID_INSTRUCTION
- mov localCPUVendor[0 * TYPE int], ebx
- mov localCPUVendor[1 * TYPE int], edx
- mov localCPUVendor[2 * TYPE int], ecx
-
- ; <<CPUID>>
- ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
- ; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
- ; edx: CPU feature flags
- mov eax,1
- CPUID_INSTRUCTION
- mov localCPUSignature, eax
-
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
-#endif
+ return false;
}
- }
- __except(1)
+ if (!call_cpuid(1, localCPUSignature))
{
return false;
}
// Process the returned information.
+ // ; eax = 0 --> eax: maximum value of CPUID instruction.
+ // ; ebx: part 1 of 3; CPU signature.
+ // ; edx: part 2 of 3; CPU signature.
+ // ; ecx: part 3 of 3; CPU signature.
char vbuf[13];
- memcpy (&(vbuf[0]), &(localCPUVendor[0]), sizeof (int));
- memcpy (&(vbuf[4]), &(localCPUVendor[1]), sizeof (int));
+ memcpy (&(vbuf[0]), &(localCPUVendor[1]), sizeof (int));
+ memcpy (&(vbuf[4]), &(localCPUVendor[3]), sizeof (int));
memcpy (&(vbuf[8]), &(localCPUVendor[2]), sizeof (int));
vbuf[12] = '\0';
this->ChipID.Vendor = vbuf;
- this->FindManufacturer();
-
// Retrieve the family of CPU present.
- this->ChipID.ExtendedFamily = ((localCPUSignature & 0x0FF00000) >> 20); // Bits 27..20 Used
- this->ChipID.ExtendedModel = ((localCPUSignature & 0x000F0000) >> 16); // Bits 19..16 Used
- this->ChipID.Type = ((localCPUSignature & 0x0000F000) >> 12); // Bits 15..12 Used
- this->ChipID.Family = ((localCPUSignature & 0x00000F00) >> 8); // Bits 11..8 Used
- this->ChipID.Model = ((localCPUSignature & 0x000000F0) >> 4); // Bits 7..4 Used
- this->ChipID.Revision = ((localCPUSignature & 0x0000000F) >> 0); // Bits 3..0 Used
+ // ; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
+ // ; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
+ // ; edx: CPU feature flags
+ this->ChipID.ExtendedFamily = ((localCPUSignature[0] & 0x0FF00000) >> 20); // Bits 27..20 Used
+ this->ChipID.ExtendedModel = ((localCPUSignature[0] & 0x000F0000) >> 16); // Bits 19..16 Used
+ this->ChipID.Type = ((localCPUSignature[0] & 0x0000F000) >> 12); // Bits 15..12 Used
+ this->ChipID.Family = ((localCPUSignature[0] & 0x00000F00) >> 8); // Bits 11..8 Used
+ this->ChipID.Model = ((localCPUSignature[0] & 0x000000F0) >> 4); // Bits 7..4 Used
+ this->ChipID.Revision = ((localCPUSignature[0] & 0x0000000F) >> 0); // Bits 3..0 Used
return true;
@@ -1128,111 +1921,43 @@ bool SystemInformationImplementation::RetrieveCPUIdentity()
/** */
bool SystemInformationImplementation::RetrieveCPUCacheDetails()
{
-#if USE_ASM_INSTRUCTIONS
+#if USE_CPUID
int L1Cache[4] = { 0, 0, 0, 0 };
int L2Cache[4] = { 0, 0, 0, 0 };
// Check to see if what we are about to do is supported...
- if (RetrieveCPUExtendedLevelSupport (0x80000005))
+ if (RetrieveCPUExtendedLevelSupport (0x80000005))
{
- // Use assembly to retrieve the L1 cache information ...
- __try
- {
- _asm
- {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- ; eax = 0x80000005 --> eax: L1 cache information - Part 1 of 4.
- ; ebx: L1 cache information - Part 2 of 4.
- ; edx: L1 cache information - Part 3 of 4.
- ; ecx: L1 cache information - Part 4 of 4.
- mov eax, 0x80000005
- CPUID_INSTRUCTION
- mov L1Cache[0 * TYPE int], eax
- mov L1Cache[1 * TYPE int], ebx
- mov L1Cache[2 * TYPE int], ecx
- mov L1Cache[3 * TYPE int], edx
-
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
-#endif
- }
- }
- __except(1)
+ if (!call_cpuid(0x80000005, L1Cache))
{
return false;
}
// Save the L1 data cache size (in KB) from ecx: bits 31..24 as well as data cache size from edx: bits 31..24.
this->Features.L1CacheSize = ((L1Cache[2] & 0xFF000000) >> 24);
this->Features.L1CacheSize += ((L1Cache[3] & 0xFF000000) >> 24);
- }
- else
+ }
+ else
{
// Store -1 to indicate the cache could not be queried.
this->Features.L1CacheSize = -1;
}
// Check to see if what we are about to do is supported...
- if (RetrieveCPUExtendedLevelSupport (0x80000006))
+ if (RetrieveCPUExtendedLevelSupport (0x80000006))
{
- // Use assembly to retrieve the L2 cache information ...
- __try
- {
- _asm
- {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- ; eax = 0x80000006 --> eax: L2 cache information - Part 1 of 4.
- ; ebx: L2 cache information - Part 2 of 4.
- ; edx: L2 cache information - Part 3 of 4.
- ; ecx: L2 cache information - Part 4 of 4.
- mov eax, 0x80000006
- CPUID_INSTRUCTION
- mov L2Cache[0 * TYPE int], eax
- mov L2Cache[1 * TYPE int], ebx
- mov L2Cache[2 * TYPE int], ecx
- mov L2Cache[3 * TYPE int], edx
-
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
-#endif
- }
- }
- __except(1)
+ if (!call_cpuid(0x80000006, L2Cache))
{
return false;
}
// Save the L2 unified cache size (in KB) from ecx: bits 31..16.
this->Features.L2CacheSize = ((L2Cache[2] & 0xFFFF0000) >> 16);
- }
+ }
else
{
// Store -1 to indicate the cache could not be queried.
this->Features.L2CacheSize = -1;
}
-
+
// Define L3 as being not present as we cannot test for it.
this->Features.L3CacheSize = -1;
@@ -1246,7 +1971,7 @@ bool SystemInformationImplementation::RetrieveCPUCacheDetails()
/** */
bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails()
{
-#if USE_ASM_INSTRUCTIONS
+#if USE_CPUID
int TLBCode = -1, TLBData = -1, L1Code = -1, L1Data = -1, L1Trace = -1, L2Unified = -1, L3Unified = -1;
int TLBCacheData[4] = { 0, 0, 0, 0 };
int TLBPassCounter = 0;
@@ -1254,39 +1979,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails()
do {
- // Use assembly to retrieve the L2 cache information ...
- __try {
- _asm {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- ; eax = 2 --> eax: TLB and cache information - Part 1 of 4.
- ; ebx: TLB and cache information - Part 2 of 4.
- ; ecx: TLB and cache information - Part 3 of 4.
- ; edx: TLB and cache information - Part 4 of 4.
- mov eax, 2
- CPUID_INSTRUCTION
- mov TLBCacheData[0 * TYPE int], eax
- mov TLBCacheData[1 * TYPE int], ebx
- mov TLBCacheData[2 * TYPE int], ecx
- mov TLBCacheData[3 * TYPE int], edx
-
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
-#endif
- }
- }
- __except(1)
+ if (!call_cpuid(2, TLBCacheData))
{
return false;
}
@@ -1294,10 +1987,10 @@ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails()
int bob = ((TLBCacheData[0] & 0x00FF0000) >> 16);
(void)bob;
// Process the returned TLB and cache information.
- for (int nCounter = 0; nCounter < TLBCACHE_INFO_UNITS; nCounter ++)
+ for (int nCounter = 0; nCounter < TLBCACHE_INFO_UNITS; nCounter ++)
{
// First of all - decide which unit we are dealing with.
- switch (nCounter)
+ switch (nCounter)
{
// eax: bits 8..15 : bits 16..23 : bits 24..31
case 0: TLBCacheUnit = ((TLBCacheData[0] & 0x0000FF00) >> 8); break;
@@ -1327,7 +2020,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails()
}
// Now process the resulting unit to see what it means....
- switch (TLBCacheUnit)
+ switch (TLBCacheUnit)
{
case 0x00: break;
case 0x01: STORE_TLBCACHE_INFO (TLBCode, 4); break;
@@ -1383,7 +2076,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails()
case 0x90: STORE_TLBCACHE_INFO (TLBCode, 262144); break; // <-- FIXME: IA-64 Only
case 0x96: STORE_TLBCACHE_INFO (TLBCode, 262144); break; // <-- FIXME: IA-64 Only
case 0x9b: STORE_TLBCACHE_INFO (TLBCode, 262144); break; // <-- FIXME: IA-64 Only
-
+
// Default case - an error has occured.
default: return false;
}
@@ -1394,47 +2087,47 @@ bool SystemInformationImplementation::RetrieveClassicalCPUCacheDetails()
} while ((TLBCacheData[0] & 0x000000FF) > TLBPassCounter);
// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
- if ((L1Code == -1) && (L1Data == -1) && (L1Trace == -1))
+ if ((L1Code == -1) && (L1Data == -1) && (L1Trace == -1))
{
this->Features.L1CacheSize = -1;
}
- else if ((L1Code == -1) && (L1Data == -1) && (L1Trace != -1))
+ else if ((L1Code == -1) && (L1Data == -1) && (L1Trace != -1))
{
this->Features.L1CacheSize = L1Trace;
}
- else if ((L1Code != -1) && (L1Data == -1))
+ else if ((L1Code != -1) && (L1Data == -1))
{
this->Features.L1CacheSize = L1Code;
}
- else if ((L1Code == -1) && (L1Data != -1))
+ else if ((L1Code == -1) && (L1Data != -1))
{
this->Features.L1CacheSize = L1Data;
}
- else if ((L1Code != -1) && (L1Data != -1))
+ else if ((L1Code != -1) && (L1Data != -1))
{
this->Features.L1CacheSize = L1Code + L1Data;
}
- else
+ else
{
this->Features.L1CacheSize = -1;
}
// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
- if (L2Unified == -1)
+ if (L2Unified == -1)
{
this->Features.L2CacheSize = -1;
}
- else
+ else
{
this->Features.L2CacheSize = L2Unified;
}
// Ok - we now have the maximum TLB, L1, L2, and L3 sizes...
- if (L3Unified == -1)
+ if (L3Unified == -1)
{
this->Features.L3CacheSize = -1;
}
- else
+ else
{
this->Features.L3CacheSize = L3Unified;
}
@@ -1453,11 +2146,40 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed()
bool retrieved = false;
#if defined(_WIN32)
- // First of all we check to see if the RDTSC (0x0F, 0x31) instruction is
- // supported. If not, we fallback to trying to read this value from the
- // registry:
- //
- if (!this->Features.HasTSC)
+ unsigned int uiRepetitions = 1;
+ unsigned int uiMSecPerRepetition = 50;
+ __int64 i64Total = 0;
+ __int64 i64Overhead = 0;
+
+ // Check if the TSC implementation works at all
+ if (this->Features.HasTSC &&
+ GetCyclesDifference(SystemInformationImplementation::Delay,
+ uiMSecPerRepetition) > 0)
+ {
+ for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++)
+ {
+ i64Total += GetCyclesDifference (SystemInformationImplementation::Delay,
+ uiMSecPerRepetition);
+ i64Overhead +=
+ GetCyclesDifference (SystemInformationImplementation::DelayOverhead,
+ uiMSecPerRepetition);
+ }
+
+ // Calculate the MHz speed.
+ i64Total -= i64Overhead;
+ i64Total /= uiRepetitions;
+ i64Total /= uiMSecPerRepetition;
+ i64Total /= 1000;
+
+ // Save the CPU speed.
+ this->CPUSpeedInMHz = (float) i64Total;
+
+ retrieved = true;
+ }
+
+ // If RDTSC is not supported, we fallback to trying to read this value
+ // from the registry:
+ if (!retrieved)
{
HKEY hKey = NULL;
LONG err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
@@ -1482,34 +2204,7 @@ bool SystemInformationImplementation::RetrieveCPUClockSpeed()
RegCloseKey(hKey);
hKey = NULL;
}
-
- return retrieved;
- }
-
- unsigned int uiRepetitions = 1;
- unsigned int uiMSecPerRepetition = 50;
- __int64 i64Total = 0;
- __int64 i64Overhead = 0;
-
- for (unsigned int nCounter = 0; nCounter < uiRepetitions; nCounter ++)
- {
- i64Total += GetCyclesDifference (SystemInformationImplementation::Delay,
- uiMSecPerRepetition);
- i64Overhead +=
- GetCyclesDifference (SystemInformationImplementation::DelayOverhead,
- uiMSecPerRepetition);
}
-
- // Calculate the MHz speed.
- i64Total -= i64Overhead;
- i64Total /= uiRepetitions;
- i64Total /= uiMSecPerRepetition;
- i64Total /= 1000;
-
- // Save the CPU speed.
- this->CPUSpeedInMHz = (float) i64Total;
-
- retrieved = true;
#endif
return retrieved;
@@ -1526,19 +2221,19 @@ bool SystemInformationImplementation::RetrieveClassicalCPUClockSpeed()
// Attempt to get a starting tick count.
QueryPerformanceCounter (&liStart);
- __try
+ __try
{
- _asm
+ _asm
{
mov eax, 0x80000000
mov ebx, CLASSICAL_CPU_FREQ_LOOP
- Timer_Loop:
+ Timer_Loop:
bsf ecx,eax
dec ebx
jnz Timer_Loop
- }
+ }
}
- __except(1)
+ __except(1)
{
return false;
}
@@ -1551,22 +2246,22 @@ bool SystemInformationImplementation::RetrieveClassicalCPUClockSpeed()
dDifference = (((double) liEnd.QuadPart - (double) liStart.QuadPart) / (double) liCountsPerSecond.QuadPart);
// Calculate the clock speed.
- if (this->ChipID.Family == 3)
+ if (this->ChipID.Family == 3)
{
// 80386 processors.... Loop time is 115 cycles!
dFrequency = (((CLASSICAL_CPU_FREQ_LOOP * 115) / dDifference) / 1000000);
- }
- else if (this->ChipID.Family == 4)
+ }
+ else if (this->ChipID.Family == 4)
{
// 80486 processors.... Loop time is 47 cycles!
dFrequency = (((CLASSICAL_CPU_FREQ_LOOP * 47) / dDifference) / 1000000);
- }
- else if (this->ChipID.Family == 5)
+ }
+ else if (this->ChipID.Family == 5)
{
// Pentium processors.... Loop time is 43 cycles!
dFrequency = (((CLASSICAL_CPU_FREQ_LOOP * 43) / dDifference) / 1000000);
}
-
+
// Save the clock speed.
this->Features.CPUSpeed = (int) dFrequency;
@@ -1581,9 +2276,9 @@ bool SystemInformationImplementation::RetrieveClassicalCPUClockSpeed()
/** */
bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULevelToCheck)
{
- int MaxCPUExtendedLevel = 0;
+ int cpuinfo[4] = { 0, 0, 0, 0 };
- // The extended CPUID is supported by various vendors starting with the following CPU models:
+ // The extended CPUID is supported by various vendors starting with the following CPU models:
//
// Manufacturer & Chip Name | Family Model Revision
//
@@ -1596,27 +2291,27 @@ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULev
//
// We check to see if a supported processor is present...
- if (this->ChipManufacturer == AMD)
+ if (this->ChipManufacturer == AMD)
{
if (this->ChipID.Family < 5) return false;
if ((this->ChipID.Family == 5) && (this->ChipID.Model < 6)) return false;
- }
- else if (this->ChipManufacturer == Cyrix)
+ }
+ else if (this->ChipManufacturer == Cyrix)
{
if (this->ChipID.Family < 5) return false;
if ((this->ChipID.Family == 5) && (this->ChipID.Model < 4)) return false;
if ((this->ChipID.Family == 6) && (this->ChipID.Model < 5)) return false;
- }
- else if (this->ChipManufacturer == IDT)
+ }
+ else if (this->ChipManufacturer == IDT)
{
if (this->ChipID.Family < 5) return false;
if ((this->ChipID.Family == 5) && (this->ChipID.Model < 8)) return false;
- }
- else if (this->ChipManufacturer == Transmeta)
+ }
+ else if (this->ChipManufacturer == Transmeta)
{
if (this->ChipID.Family < 5) return false;
- }
- else if (this->ChipManufacturer == Intel)
+ }
+ else if (this->ChipManufacturer == Intel)
{
if (this->ChipID.Family < 0xf)
{
@@ -1624,35 +2319,8 @@ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULev
}
}
-#if USE_ASM_INSTRUCTIONS
-
- // Use assembly to detect CPUID information...
- __try {
- _asm {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- ; eax = 0x80000000 --> eax: maximum supported extended level
- mov eax,0x80000000
- CPUID_INSTRUCTION
- mov MaxCPUExtendedLevel, eax
-
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
-#endif
- }
- }
- __except(1)
+#if USE_CPUID
+ if (!call_cpuid(0x80000000, cpuinfo))
{
return false;
}
@@ -1660,7 +2328,7 @@ bool SystemInformationImplementation::RetrieveCPUExtendedLevelSupport(int CPULev
// Now we have to check the level wanted vs level returned...
int nLevelWanted = (CPULevelToCheck & 0x7FFFFFFF);
- int nLevelReturn = (MaxCPUExtendedLevel & 0x7FFFFFFF);
+ int nLevelReturn = (cpuinfo[0] & 0x7FFFFFFF);
// Check to see if the level provided is supported...
if (nLevelWanted > nLevelReturn)
@@ -1677,7 +2345,7 @@ bool SystemInformationImplementation::RetrieveExtendedCPUFeatures()
{
// Check that we are not using an Intel processor as it does not support this.
- if (this->ChipManufacturer == Intel)
+ if (this->ChipManufacturer == Intel)
{
return false;
}
@@ -1688,60 +2356,30 @@ bool SystemInformationImplementation::RetrieveExtendedCPUFeatures()
return false;
}
-#if USE_ASM_INSTRUCTIONS
- int localCPUExtendedFeatures = 0;
-
- // Use assembly to detect CPUID information...
- __try
- {
- _asm
- {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- ; eax = 0x80000001 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
- ; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
- ; edx: CPU feature flags
- mov eax,0x80000001
- CPUID_INSTRUCTION
- mov localCPUExtendedFeatures, edx
+#if USE_CPUID
+ int localCPUExtendedFeatures[4] = { 0, 0, 0, 0 };
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
-#endif
- }
- }
- __except(1)
+ if (!call_cpuid(0x80000001, localCPUExtendedFeatures))
{
return false;
}
// Retrieve the extended features of CPU present.
- this->Features.ExtendedFeatures.Has3DNow = ((localCPUExtendedFeatures & 0x80000000) != 0); // 3DNow Present --> Bit 31.
- this->Features.ExtendedFeatures.Has3DNowPlus = ((localCPUExtendedFeatures & 0x40000000) != 0); // 3DNow+ Present -- > Bit 30.
- this->Features.ExtendedFeatures.HasSSEMMX = ((localCPUExtendedFeatures & 0x00400000) != 0); // SSE MMX Present --> Bit 22.
- this->Features.ExtendedFeatures.SupportsMP = ((localCPUExtendedFeatures & 0x00080000) != 0); // MP Capable -- > Bit 19.
-
+ this->Features.ExtendedFeatures.Has3DNow = ((localCPUExtendedFeatures[3] & 0x80000000) != 0); // 3DNow Present --> Bit 31.
+ this->Features.ExtendedFeatures.Has3DNowPlus = ((localCPUExtendedFeatures[3] & 0x40000000) != 0); // 3DNow+ Present -- > Bit 30.
+ this->Features.ExtendedFeatures.HasSSEMMX = ((localCPUExtendedFeatures[3] & 0x00400000) != 0); // SSE MMX Present --> Bit 22.
+ this->Features.ExtendedFeatures.SupportsMP = ((localCPUExtendedFeatures[3] & 0x00080000) != 0); // MP Capable -- > Bit 19.
+
// Retrieve AMD specific extended features.
- if (this->ChipManufacturer == AMD)
+ if (this->ChipManufacturer == AMD)
{
- this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures & 0x00400000) != 0); // AMD specific: MMX-SSE --> Bit 22
+ this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures[3] & 0x00400000) != 0); // AMD specific: MMX-SSE --> Bit 22
}
// Retrieve Cyrix specific extended features.
- if (this->ChipManufacturer == Cyrix)
+ if (this->ChipManufacturer == Cyrix)
{
- this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures & 0x01000000) != 0); // Cyrix specific: Extended MMX --> Bit 24
+ this->Features.ExtendedFeatures.HasMMXPlus = ((localCPUExtendedFeatures[3] & 0x01000000) != 0); // Cyrix specific: Extended MMX --> Bit 24
}
return true;
@@ -1761,51 +2399,20 @@ bool SystemInformationImplementation::RetrieveProcessorSerialNumber()
return false;
}
-#if USE_ASM_INSTRUCTIONS
- int SerialNumber[3];
+#if USE_CPUID
+ int SerialNumber[4];
- // Use assembly to detect CPUID information...
- __try {
- _asm {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- ; eax = 3 --> ebx: top 32 bits are the processor signature bits --> NB: Transmeta only ?!?
- ; ecx: middle 32 bits are the processor signature bits
- ; edx: bottom 32 bits are the processor signature bits
- mov eax, 3
- CPUID_INSTRUCTION
- mov SerialNumber[0 * TYPE int], ebx
- mov SerialNumber[1 * TYPE int], ecx
- mov SerialNumber[2 * TYPE int], edx
-
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
-#endif
- }
- }
- __except(1)
+ if (!call_cpuid(3, SerialNumber))
{
return false;
}
// Process the returned information.
+ // ; eax = 3 --> ebx: top 32 bits are the processor signature bits --> NB: Transmeta only ?!?
+ // ; ecx: middle 32 bits are the processor signature bits
+ // ; edx: bottom 32 bits are the processor signature bits
char sn[128];
sprintf (sn, "%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x",
- ((SerialNumber[0] & 0xff000000) >> 24),
- ((SerialNumber[0] & 0x00ff0000) >> 16),
- ((SerialNumber[0] & 0x0000ff00) >> 8),
- ((SerialNumber[0] & 0x000000ff) >> 0),
((SerialNumber[1] & 0xff000000) >> 24),
((SerialNumber[1] & 0x00ff0000) >> 16),
((SerialNumber[1] & 0x0000ff00) >> 8),
@@ -1813,7 +2420,11 @@ bool SystemInformationImplementation::RetrieveProcessorSerialNumber()
((SerialNumber[2] & 0xff000000) >> 24),
((SerialNumber[2] & 0x00ff0000) >> 16),
((SerialNumber[2] & 0x0000ff00) >> 8),
- ((SerialNumber[2] & 0x000000ff) >> 0));
+ ((SerialNumber[2] & 0x000000ff) >> 0),
+ ((SerialNumber[3] & 0xff000000) >> 24),
+ ((SerialNumber[3] & 0x00ff0000) >> 16),
+ ((SerialNumber[3] & 0x0000ff00) >> 8),
+ ((SerialNumber[3] & 0x000000ff) >> 0));
this->ChipID.SerialNumber = sn;
return true;
@@ -1835,45 +2446,18 @@ bool SystemInformationImplementation::RetrieveCPUPowerManagement()
return false;
}
-#if USE_ASM_INSTRUCTIONS
- int localCPUPowerManagement = 0;
-
+#if USE_CPUID
+ int localCPUPowerManagement[4] = { 0, 0, 0, 0 };
- // Use assembly to detect CPUID information...
- __try {
- _asm {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- ; eax = 0x80000007 --> edx: get processor power management
- mov eax,0x80000007
- CPUID_INSTRUCTION
- mov localCPUPowerManagement, edx
-
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
-#endif
- }
- }
- __except(1)
+ if (!call_cpuid(0x80000007, localCPUPowerManagement))
{
return false;
}
// Check for the power management capabilities of the CPU.
- this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = ((localCPUPowerManagement & 0x00000001) != 0);
- this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID = ((localCPUPowerManagement & 0x00000002) != 0);
- this->Features.ExtendedFeatures.PowerManagement.HasVoltageID = ((localCPUPowerManagement & 0x00000004) != 0);
+ this->Features.ExtendedFeatures.PowerManagement.HasTempSenseDiode = ((localCPUPowerManagement[3] & 0x00000001) != 0);
+ this->Features.ExtendedFeatures.PowerManagement.HasFrequencyID = ((localCPUPowerManagement[3] & 0x00000002) != 0);
+ this->Features.ExtendedFeatures.PowerManagement.HasVoltageID = ((localCPUPowerManagement[3] & 0x00000004) != 0);
return true;
@@ -1882,7 +2466,9 @@ bool SystemInformationImplementation::RetrieveCPUPowerManagement()
#endif
}
-void SystemInformationStripLeadingSpace(kwsys_stl::string& str)
+#if USE_CPUID
+// Used only in USE_CPUID implementation below.
+static void SystemInformationStripLeadingSpace(kwsys_stl::string& str)
{
// Because some manufacturers have leading white space - we have to post-process the name.
kwsys_stl::string::size_type pos = str.find_first_not_of(" ");
@@ -1891,6 +2477,7 @@ void SystemInformationStripLeadingSpace(kwsys_stl::string& str)
str = str.substr(pos);
}
}
+#endif
/** */
bool SystemInformationImplementation::RetrieveExtendedCPUIdentity()
@@ -1903,57 +2490,18 @@ bool SystemInformationImplementation::RetrieveExtendedCPUIdentity()
if (!RetrieveCPUExtendedLevelSupport(static_cast<int>(0x80000004)))
return false;
-#if USE_ASM_INSTRUCTIONS
+#if USE_CPUID
int CPUExtendedIdentity[12];
- // Use assembly to detect CPUID information...
- __try {
- _asm {
-#ifdef CPUID_AWARE_COMPILER
- ; we must push/pop the registers <<CPUID>> writes to, as the
- ; optimiser doesn't know about <<CPUID>>, and so doesn't expect
- ; these registers to change.
- push eax
- push ebx
- push ecx
- push edx
-#endif
- ; <<CPUID>>
- ; eax = 0x80000002 --> eax, ebx, ecx, edx: get processor name string (part 1)
- mov eax,0x80000002
- CPUID_INSTRUCTION
- mov CPUExtendedIdentity[0 * TYPE int], eax
- mov CPUExtendedIdentity[1 * TYPE int], ebx
- mov CPUExtendedIdentity[2 * TYPE int], ecx
- mov CPUExtendedIdentity[3 * TYPE int], edx
-
- ; <<CPUID>>
- ; eax = 0x80000003 --> eax, ebx, ecx, edx: get processor name string (part 2)
- mov eax,0x80000003
- CPUID_INSTRUCTION
- mov CPUExtendedIdentity[4 * TYPE int], eax
- mov CPUExtendedIdentity[5 * TYPE int], ebx
- mov CPUExtendedIdentity[6 * TYPE int], ecx
- mov CPUExtendedIdentity[7 * TYPE int], edx
-
- ; <<CPUID>>
- ; eax = 0x80000004 --> eax, ebx, ecx, edx: get processor name string (part 3)
- mov eax,0x80000004
- CPUID_INSTRUCTION
- mov CPUExtendedIdentity[8 * TYPE int], eax
- mov CPUExtendedIdentity[9 * TYPE int], ebx
- mov CPUExtendedIdentity[10 * TYPE int], ecx
- mov CPUExtendedIdentity[11 * TYPE int], edx
-
-#ifdef CPUID_AWARE_COMPILER
- pop edx
- pop ecx
- pop ebx
- pop eax
-#endif
+ if (!call_cpuid(0x80000002, CPUExtendedIdentity))
+ {
+ return false;
}
- }
- __except(1)
+ if (!call_cpuid(0x80000003, CPUExtendedIdentity + 4))
+ {
+ return false;
+ }
+ if (!call_cpuid(0x80000004, CPUExtendedIdentity + 8))
{
return false;
}
@@ -1974,6 +2522,7 @@ bool SystemInformationImplementation::RetrieveExtendedCPUIdentity()
memcpy (&(nbuf[44]), &(CPUExtendedIdentity[11]), sizeof (int));
nbuf[48] = '\0';
this->ChipID.ProcessorName = nbuf;
+ this->ChipID.ModelName = nbuf;
// Because some manufacturers have leading white space - we have to post-process the name.
SystemInformationStripLeadingSpace(this->ChipID.ProcessorName);
@@ -1988,13 +2537,13 @@ bool SystemInformationImplementation::RetrieveExtendedCPUIdentity()
bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
{
// Start by decided which manufacturer we are using....
- switch (this->ChipManufacturer)
+ switch (this->ChipManufacturer)
{
case Intel:
// Check the family / model / revision to determine the CPU ID.
switch (this->ChipID.Family) {
case 3:
- this->ChipID.ProcessorName = "Newer i80386 family";
+ this->ChipID.ProcessorName = "Newer i80386 family";
break;
case 4:
switch (this->ChipID.Model) {
@@ -2011,7 +2560,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
}
break;
case 5:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 0: this->ChipID.ProcessorName = "P5 A-Step"; break;
case 1: this->ChipID.ProcessorName = "P5"; break;
@@ -2024,7 +2573,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
}
break;
case 6:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 0: this->ChipID.ProcessorName = "P6 A-Step"; break;
case 1: this->ChipID.ProcessorName = "P6"; break;
@@ -2044,10 +2593,10 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
break;
case 0xf:
// Check the extended family bits...
- switch (this->ChipID.ExtendedFamily)
+ switch (this->ChipID.ExtendedFamily)
{
case 0:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 0: this->ChipID.ProcessorName = "Pentium IV (0.18 micron)"; break;
case 1: this->ChipID.ProcessorName = "Pentium IV (0.18 micron)"; break;
@@ -2070,10 +2619,10 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
case AMD:
// Check the family / model / revision to determine the CPU ID.
- switch (this->ChipID.Family)
+ switch (this->ChipID.Family)
{
case 4:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 3: this->ChipID.ProcessorName = "80486DX2"; break;
case 7: this->ChipID.ProcessorName = "80486DX2 WriteBack"; break;
@@ -2085,7 +2634,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
}
break;
case 5:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 0: this->ChipID.ProcessorName = "SSA5 (PR75, PR90 = PR100)"; break;
case 1: this->ChipID.ProcessorName = "5k86 (PR120 = PR133)"; break;
@@ -2100,7 +2649,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
}
break;
case 6:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 1: this->ChipID.ProcessorName = "Athlon- (0.25 micron)"; break;
case 2: this->ChipID.ProcessorName = "Athlon- (0.18 micron)"; break;
@@ -2108,9 +2657,9 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
case 4: this->ChipID.ProcessorName = "Athlon- (Thunderbird core)"; break;
case 6: this->ChipID.ProcessorName = "Athlon- (Palomino core)"; break;
case 7: this->ChipID.ProcessorName = "Duron- (Morgan core)"; break;
- case 8:
+ case 8:
if (this->Features.ExtendedFeatures.SupportsMP)
- this->ChipID.ProcessorName = "Athlon - MP (Thoroughbred core)";
+ this->ChipID.ProcessorName = "Athlon - MP (Thoroughbred core)";
else this->ChipID.ProcessorName = "Athlon - XP (Thoroughbred core)";
break;
default: this->ChipID.ProcessorName = "Unknown K7 family"; return false;
@@ -2123,10 +2672,10 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
break;
case Transmeta:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family)
+ {
case 5:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 4: this->ChipID.ProcessorName = "Crusoe TM3x00 and TM5x00"; break;
default: this->ChipID.ProcessorName = "Unknown Crusoe family"; return false;
@@ -2139,10 +2688,10 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
break;
case Rise:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family)
+ {
case 5:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 0: this->ChipID.ProcessorName = "mP6 (0.25 micron)"; break;
case 2: this->ChipID.ProcessorName = "mP6 (0.18 micron)"; break;
@@ -2156,10 +2705,10 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
break;
case UMC:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family)
+ {
case 4:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 1: this->ChipID.ProcessorName = "U5D"; break;
case 2: this->ChipID.ProcessorName = "U5S"; break;
@@ -2173,10 +2722,10 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
break;
case IDT:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family)
+ {
case 5:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 4: this->ChipID.ProcessorName = "C6"; break;
case 8: this->ChipID.ProcessorName = "C2"; break;
@@ -2185,7 +2734,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
}
break;
case 6:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 6: this->ChipID.ProcessorName = "VIA Cyrix III - Samuel"; break;
default: this->ChipID.ProcessorName = "Unknown IDT\\Centaur family"; return false;
@@ -2198,10 +2747,10 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
break;
case Cyrix:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family)
+ {
case 4:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 4: this->ChipID.ProcessorName = "MediaGX GX = GXm"; break;
case 9: this->ChipID.ProcessorName = "5x86"; break;
@@ -2209,7 +2758,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
}
break;
case 5:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 2: this->ChipID.ProcessorName = "Cx6x86"; break;
case 4: this->ChipID.ProcessorName = "MediaGX GXm"; break;
@@ -2217,7 +2766,7 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
}
break;
case 6:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 0: this->ChipID.ProcessorName = "6x86MX"; break;
case 5: this->ChipID.ProcessorName = "Cyrix M2 Core"; break;
@@ -2234,10 +2783,10 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
break;
case NexGen:
- switch (this->ChipID.Family)
- {
+ switch (this->ChipID.Family)
+ {
case 5:
- switch (this->ChipID.Model)
+ switch (this->ChipID.Model)
{
case 0: this->ChipID.ProcessorName = "Nx586 or Nx586FPU"; break;
default: this->ChipID.ProcessorName = "Unknown NexGen family"; return false;
@@ -2272,6 +2821,16 @@ kwsys_stl::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(k
size_t pos2 = buffer.find("\n",pos);
if(pos!=buffer.npos && pos2!=buffer.npos)
{
+ // It may happen that the beginning matches, but this is still not the requested key.
+ // An example is looking for "cpu" when "cpu family" comes first. So we check that
+ // we have only spaces from here to pos, otherwise we search again.
+ for(size_t i=this->CurrentPositionInFile+strlen(word); i < pos; ++i)
+ {
+ if(buffer[i] != ' ' && buffer[i] != '\t')
+ {
+ return this->ExtractValueFromCpuInfoFile(buffer, word, pos2);
+ }
+ }
return buffer.substr(pos+2,pos2-pos-2);
}
}
@@ -2280,19 +2839,19 @@ kwsys_stl::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(k
}
/** Query for the cpu status */
-int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
+bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
{
this->NumberOfLogicalCPU = 0;
this->NumberOfPhysicalCPU = 0;
kwsys_stl::string buffer;
FILE *fd = fopen("/proc/cpuinfo", "r" );
- if ( !fd )
+ if ( !fd )
{
kwsys_ios::cout << "Problem opening /proc/cpuinfo" << kwsys_ios::endl;
- return 0;
+ return false;
}
-
+
size_t fileSize = 0;
while(!feof(fd))
{
@@ -2336,14 +2895,14 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
#else // __CYGWIN__
// does not have "physical id" entries, neither "cpu cores"
- // this has to be fixed for hyper-threading.
+ // this has to be fixed for hyper-threading.
kwsys_stl::string cpucount =
this->ExtractValueFromCpuInfoFile(buffer,"cpu count");
this->NumberOfPhysicalCPU=
this->NumberOfLogicalCPU = atoi(cpucount.c_str());
#endif
- // gotta have one, and if this is 0 then we get a / by 0n
- // beter to have a bad answer than a crash
+ // gotta have one, and if this is 0 then we get a / by 0n
+ // better to have a bad answer than a crash
if(this->NumberOfPhysicalCPU <= 0)
{
this->NumberOfPhysicalCPU = 1;
@@ -2352,49 +2911,500 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical=
this->NumberOfLogicalCPU/this->NumberOfPhysicalCPU;
- // CPU speed (checking only the first proc
+ // CPU speed (checking only the first processor)
kwsys_stl::string CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer,"cpu MHz");
this->CPUSpeedInMHz = static_cast<float>(atof(CPUSpeed.c_str()));
// Chip family
- this->ChipID.Family = atoi(this->ExtractValueFromCpuInfoFile(buffer,"cpu family").c_str());
-
+ kwsys_stl::string familyStr =
+ this->ExtractValueFromCpuInfoFile(buffer,"cpu family");
+ if(familyStr.empty())
+ {
+ familyStr = this->ExtractValueFromCpuInfoFile(buffer,"CPU architecture");
+ }
+ this->ChipID.Family = atoi(familyStr.c_str());
+
// Chip Vendor
this->ChipID.Vendor = this->ExtractValueFromCpuInfoFile(buffer,"vendor_id");
- this->FindManufacturer();
-
+ this->FindManufacturer(familyStr);
+
+ // second try for setting family
+ if (this->ChipID.Family == 0 && this->ChipManufacturer == HP)
+ {
+ if (familyStr == "PA-RISC 1.1a")
+ this->ChipID.Family = 0x11a;
+ else if (familyStr == "PA-RISC 2.0")
+ this->ChipID.Family = 0x200;
+ // If you really get CMake to work on a machine not belonging to
+ // any of those families I owe you a dinner if you get it to
+ // contribute nightly builds regularly.
+ }
+
// Chip Model
this->ChipID.Model = atoi(this->ExtractValueFromCpuInfoFile(buffer,"model").c_str());
- this->RetrieveClassicalCPUIdentity();
+ if(!this->RetrieveClassicalCPUIdentity())
+ {
+ // Some platforms (e.g. PA-RISC) tell us their CPU name here.
+ // Note: x86 does not.
+ kwsys_stl::string cpuname = this->ExtractValueFromCpuInfoFile(buffer,"cpu");
+ if(!cpuname.empty())
+ {
+ this->ChipID.ProcessorName = cpuname;
+ }
+ }
+
+ // Chip revision
+ kwsys_stl::string cpurev = this->ExtractValueFromCpuInfoFile(buffer,"stepping");
+ if(cpurev.empty())
+ {
+ cpurev = this->ExtractValueFromCpuInfoFile(buffer,"CPU revision");
+ }
+ this->ChipID.Revision = atoi(cpurev.c_str());
+
+ // Chip Model Name
+ this->ChipID.ModelName = this->ExtractValueFromCpuInfoFile(buffer,"model name").c_str();
// L1 Cache size
- kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,"cache size");
- pos = cacheSize.find(" KB");
- if(pos!=cacheSize.npos)
+ // Different architectures may show different names for the caches.
+ // Sum up everything we find.
+ kwsys_stl::vector<const char*> cachename;
+ cachename.clear();
+
+ cachename.push_back("cache size"); // e.g. x86
+ cachename.push_back("I-cache"); // e.g. PA-RISC
+ cachename.push_back("D-cache"); // e.g. PA-RISC
+
+ this->Features.L1CacheSize = 0;
+ for (size_t index = 0; index < cachename.size(); index ++)
{
- cacheSize = cacheSize.substr(0,pos);
+ kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,cachename[index]);
+ if (!cacheSize.empty())
+ {
+ pos = cacheSize.find(" KB");
+ if(pos!=cacheSize.npos)
+ {
+ cacheSize = cacheSize.substr(0,pos);
+ }
+ this->Features.L1CacheSize += atoi(cacheSize.c_str());
+ }
}
- this->Features.L1CacheSize = atoi(cacheSize.c_str());
- return 1;
+
+ // processor feature flags (probably x86 specific)
+ kwsys_stl::string cpuflags = this->ExtractValueFromCpuInfoFile(buffer,"flags");
+ if(!cpurev.empty())
+ {
+ // now we can match every flags as space + flag + space
+ cpuflags = " " + cpuflags + " ";
+ if ((cpuflags.find(" fpu ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasFPU = true;
+ }
+ if ((cpuflags.find(" tsc ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasTSC = true;
+ }
+ if ((cpuflags.find(" mmx ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasMMX = true;
+ }
+ if ((cpuflags.find(" sse ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasSSE = true;
+ }
+ if ((cpuflags.find(" sse2 ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasSSE2 = true;
+ }
+ if ((cpuflags.find(" apic ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasAPIC = true;
+ }
+ if ((cpuflags.find(" cmov ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasCMOV = true;
+ }
+ if ((cpuflags.find(" mtrr ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasMTRR = true;
+ }
+ if ((cpuflags.find(" acpi ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasACPI = true;
+ }
+ if ((cpuflags.find(" 3dnow ")!=kwsys_stl::string::npos))
+ {
+ this->Features.ExtendedFeatures.Has3DNow = true;
+ }
+ }
+
+ return true;
}
-/** Query for the memory status */
-int SystemInformationImplementation::QueryMemory()
+bool SystemInformationImplementation::QueryProcessorBySysconf()
{
- this->TotalVirtualMemory = 0;
- this->TotalPhysicalMemory = 0;
- this->AvailableVirtualMemory = 0;
- this->AvailablePhysicalMemory = 0;
-#ifdef __CYGWIN__
+#if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN)
+// IRIX names this slightly different
+# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
+#endif
+
+#ifdef _SC_NPROCESSORS_ONLN
+ long c = sysconf(_SC_NPROCESSORS_ONLN);
+ if (c <= 0)
+ {
+ return false;
+ }
+
+ this->NumberOfPhysicalCPU = static_cast<unsigned int>(c);
+ this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool SystemInformationImplementation::QueryProcessor()
+{
+ return this->QueryProcessorBySysconf();
+}
+
+/**
+Get total system RAM in units of KiB.
+*/
+SystemInformation::LongLong
+SystemInformationImplementation::GetHostMemoryTotal()
+{
+#if defined(_WIN32)
+# if defined(_MSC_VER) && _MSC_VER < 1300
+ MEMORYSTATUS stat;
+ stat.dwLength = sizeof(stat);
+ GlobalMemoryStatus(&stat);
+ return stat.dwTotalPhys/1024;
+# else
+ MEMORYSTATUSEX statex;
+ statex.dwLength=sizeof(statex);
+ GlobalMemoryStatusEx(&statex);
+ return statex.ullTotalPhys/1024;
+# endif
+#elif defined(__linux)
+ SystemInformation::LongLong memTotal=0;
+ int ierr=GetFieldFromFile("/proc/meminfo","MemTotal:",memTotal);
+ if (ierr)
+ {
+ return -1;
+ }
+ return memTotal;
+#elif defined(__APPLE__)
+ uint64_t mem;
+ size_t len = sizeof(mem);
+ int ierr=sysctlbyname("hw.memsize", &mem, &len, NULL, 0);
+ if (ierr)
+ {
+ return -1;
+ }
+ return mem/1024;
+#else
return 0;
-#elif defined(_WIN32)
-#if _MSC_VER < 1300
+#endif
+}
+
+/**
+Get total system RAM in units of KiB. This may differ from the
+host total if a host-wide resource limit is applied.
+*/
+SystemInformation::LongLong
+SystemInformationImplementation::GetHostMemoryAvailable(const char *hostLimitEnvVarName)
+{
+ SystemInformation::LongLong memTotal=this->GetHostMemoryTotal();
+
+ // the following mechanism is provided for systems that
+ // apply resource limits across groups of processes.
+ // this is of use on certain SMP systems (eg. SGI UV)
+ // where the host has a large amount of ram but a given user's
+ // access to it is severly restricted. The system will
+ // apply a limit across a set of processes. Units are in KiB.
+ if (hostLimitEnvVarName)
+ {
+ const char *hostLimitEnvVarValue=getenv(hostLimitEnvVarName);
+ if (hostLimitEnvVarValue)
+ {
+ SystemInformation::LongLong hostLimit=atoLongLong(hostLimitEnvVarValue);
+ if (hostLimit>0)
+ {
+ memTotal=min(hostLimit,memTotal);
+ }
+ }
+ }
+
+ return memTotal;
+}
+
+/**
+Get total system RAM in units of KiB. This may differ from the
+host total if a per-process resource limit is applied.
+*/
+SystemInformation::LongLong
+SystemInformationImplementation::GetProcMemoryAvailable(
+ const char *hostLimitEnvVarName,
+ const char *procLimitEnvVarName)
+{
+ SystemInformation::LongLong memAvail
+ = this->GetHostMemoryAvailable(hostLimitEnvVarName);
+
+ // the following mechanism is provide for systems where rlimits
+ // are not employed. Units are in KiB.
+ if (procLimitEnvVarName)
+ {
+ const char *procLimitEnvVarValue=getenv(procLimitEnvVarName);
+ if (procLimitEnvVarValue)
+ {
+ SystemInformation::LongLong procLimit=atoLongLong(procLimitEnvVarValue);
+ if (procLimit>0)
+ {
+ memAvail=min(procLimit,memAvail);
+ }
+ }
+ }
+
+#if defined(__linux)
+ int ierr;
+ ResourceLimitType rlim;
+ ierr=GetResourceLimit(RLIMIT_DATA,&rlim);
+ if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
+ {
+ memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
+ }
+
+ ierr=GetResourceLimit(RLIMIT_AS,&rlim);
+ if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
+ {
+ memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
+ }
+#elif defined(__APPLE__)
+ struct rlimit rlim;
+ int ierr;
+ ierr=getrlimit(RLIMIT_DATA,&rlim);
+ if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
+ {
+ memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
+ }
+
+ ierr=getrlimit(RLIMIT_RSS,&rlim);
+ if ((ierr==0) && (rlim.rlim_cur != RLIM_INFINITY))
+ {
+ memAvail=min((SystemInformation::LongLong)rlim.rlim_cur/1024,memAvail);
+ }
+#endif
+
+ return memAvail;
+}
+
+/**
+Get RAM used by all processes in the host, in units of KiB.
+*/
+SystemInformation::LongLong
+SystemInformationImplementation::GetHostMemoryUsed()
+{
+#if defined(_WIN32)
+# if defined(_MSC_VER) && _MSC_VER < 1300
+ MEMORYSTATUS stat;
+ stat.dwLength = sizeof(stat);
+ GlobalMemoryStatus(&stat);
+ return (stat.dwTotalPhys - stat.dwAvailPhys)/1024;
+# else
+ MEMORYSTATUSEX statex;
+ statex.dwLength=sizeof(statex);
+ GlobalMemoryStatusEx(&statex);
+ return (statex.ullTotalPhys - statex.ullAvailPhys)/1024;
+# endif
+#elif defined(__linux)
+ const char *names[3]={"MemTotal:","MemFree:",NULL};
+ SystemInformation::LongLong values[2]={SystemInformation::LongLong(0)};
+ int ierr=GetFieldsFromFile("/proc/meminfo",names,values);
+ if (ierr)
+ {
+ return ierr;
+ }
+ SystemInformation::LongLong &memTotal=values[0];
+ SystemInformation::LongLong &memFree=values[1];
+ return memTotal - memFree;
+#elif defined(__APPLE__)
+ SystemInformation::LongLong psz=getpagesize();
+ if (psz<1)
+ {
+ return -1;
+ }
+ const char *names[4]={"Pages active:","Pages inactive:","Pages wired down:",NULL};
+ SystemInformation::LongLong values[3]={SystemInformation::LongLong(0)};
+ int ierr=GetFieldsFromCommand("vm_stat", names, values);
+ if (ierr)
+ {
+ return -1;
+ }
+ SystemInformation::LongLong &vmActive=values[0];
+ SystemInformation::LongLong &vmInactive=values[1];
+ SystemInformation::LongLong &vmWired=values[2];
+ return ((vmActive+vmInactive+vmWired)*psz)/1024;
+#else
+ return 0;
+#endif
+}
+
+/**
+Get system RAM used by the process associated with the given
+process id in units of KiB.
+*/
+SystemInformation::LongLong
+SystemInformationImplementation::GetProcMemoryUsed()
+{
+#if defined(_WIN32) && defined(KWSYS_SYS_HAS_PSAPI)
+ long pid=GetCurrentProcessId();
+ HANDLE hProc;
+ hProc=OpenProcess(
+ PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,
+ false,
+ pid);
+ if (hProc==0)
+ {
+ return -1;
+ }
+ PROCESS_MEMORY_COUNTERS pmc;
+ int ok=GetProcessMemoryInfo(hProc,&pmc,sizeof(pmc));
+ CloseHandle(hProc);
+ if (!ok)
+ {
+ return -2;
+ }
+ return pmc.WorkingSetSize/1024;
+#elif defined(__linux)
+ SystemInformation::LongLong memUsed=0;
+ int ierr=GetFieldFromFile("/proc/self/status","VmRSS:",memUsed);
+ if (ierr)
+ {
+ return -1;
+ }
+ return memUsed;
+#elif defined(__APPLE__)
+ SystemInformation::LongLong memUsed=0;
+ pid_t pid=getpid();
+ kwsys_ios::ostringstream oss;
+ oss << "ps -o rss= -p " << pid;
+ FILE *file=popen(oss.str().c_str(),"r");
+ if (file==0)
+ {
+ return -1;
+ }
+ oss.str("");
+ while (!feof(file) && !ferror(file))
+ {
+ char buf[256]={'\0'};
+ errno=0;
+ size_t nRead=fread(buf,1,256,file);
+ if (ferror(file) && (errno==EINTR))
+ {
+ clearerr(file);
+ }
+ if (nRead) oss << buf;
+ }
+ int ierr=ferror(file);
+ pclose(file);
+ if (ierr)
+ {
+ return -2;
+ }
+ kwsys_ios::istringstream iss(oss.str());
+ iss >> memUsed;
+ return memUsed;
+#else
+ return 0;
+#endif
+}
+
+/**
+Get the process id of the running process.
+*/
+SystemInformation::LongLong
+SystemInformationImplementation::GetProcessId()
+{
+#if defined(_WIN32)
+ return GetCurrentProcessId();
+#elif defined(__linux) || defined(__APPLE__)
+ return getpid();
+#else
+ return -1;
+#endif
+}
+
+/**
+when set print stack trace in response to common signals.
+*/
+void SystemInformationImplementation::SetStackTraceOnError(int enable)
+{
+#if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+ static int saOrigValid=0;
+ static struct sigaction saSEGVOrig;
+ static struct sigaction saTERMOrig;
+ static struct sigaction saINTOrig;
+ static struct sigaction saILLOrig;
+ static struct sigaction saBUSOrig;
+ static struct sigaction saFPEOrig;
+
+ if (enable && !saOrigValid)
+ {
+ // save the current actions
+ sigaction(SIGSEGV,0,&saSEGVOrig);
+ sigaction(SIGTERM,0,&saTERMOrig);
+ sigaction(SIGINT,0,&saINTOrig);
+ sigaction(SIGILL,0,&saILLOrig);
+ sigaction(SIGBUS,0,&saBUSOrig);
+ sigaction(SIGFPE,0,&saFPEOrig);
+
+ // enable read, disable write
+ saOrigValid=1;
+
+ // install ours
+ struct sigaction sa;
+ sa.sa_sigaction=(SigAction)StacktraceSignalHandler;
+ sa.sa_flags=SA_SIGINFO|SA_RESTART;
+ sigemptyset(&sa.sa_mask);
+
+ sigaction(SIGSEGV,&sa,0);
+ sigaction(SIGTERM,&sa,0);
+ sigaction(SIGINT,&sa,0);
+ sigaction(SIGILL,&sa,0);
+ sigaction(SIGBUS,&sa,0);
+ sigaction(SIGFPE,&sa,0);
+ }
+ else
+ if (!enable && saOrigValid)
+ {
+ // restore previous actions
+ sigaction(SIGSEGV,&saSEGVOrig,0);
+ sigaction(SIGTERM,&saTERMOrig,0);
+ sigaction(SIGINT,&saINTOrig,0);
+ sigaction(SIGILL,&saILLOrig,0);
+ sigaction(SIGBUS,&saBUSOrig,0);
+ sigaction(SIGFPE,&saFPEOrig,0);
+
+ // enable write, disable read
+ saOrigValid=0;
+ }
+#else
+ // avoid warning C4100
+ (void)enable;
+#endif
+}
+
+bool SystemInformationImplementation::QueryWindowsMemory()
+{
+#if defined(_WIN32)
+# if defined(_MSC_VER) && _MSC_VER < 1300
MEMORYSTATUS ms;
unsigned long tv, tp, av, ap;
ms.dwLength = sizeof(ms);
GlobalMemoryStatus(&ms);
- #define MEM_VAL(value) dw##value
-#else
+# define MEM_VAL(value) dw##value
+# else
MEMORYSTATUSEX ms;
DWORDLONG tv, tp, av, ap;
ms.dwLength = sizeof(ms);
@@ -2402,8 +3412,8 @@ int SystemInformationImplementation::QueryMemory()
{
return 0;
}
-#define MEM_VAL(value) ull##value
-#endif
+# define MEM_VAL(value) ull##value
+# endif
tv = ms.MEM_VAL(TotalVirtual);
tp = ms.MEM_VAL(TotalPhys);
av = ms.MEM_VAL(AvailVirtual);
@@ -2412,51 +3422,58 @@ int SystemInformationImplementation::QueryMemory()
this->TotalPhysicalMemory = tp>>10>>10;
this->AvailableVirtualMemory = av>>10>>10;
this->AvailablePhysicalMemory = ap>>10>>10;
- return 1;
-#elif defined(__linux)
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool SystemInformationImplementation::QueryLinuxMemory()
+{
+#if defined(__linux)
unsigned long tv=0;
unsigned long tp=0;
unsigned long av=0;
unsigned long ap=0;
-
+
char buffer[1024]; // for reading lines
-
+
int linuxMajor = 0;
int linuxMinor = 0;
-
+
// Find the Linux kernel version first
struct utsname unameInfo;
int errorFlag = uname(&unameInfo);
if( errorFlag!=0 )
{
kwsys_ios::cout << "Problem calling uname(): " << strerror(errno) << kwsys_ios::endl;
- return 0;
+ return false;
}
-
+
if( unameInfo.release!=0 && strlen(unameInfo.release)>=3 )
{
// release looks like "2.6.3-15mdk-i686-up-4GB"
char majorChar=unameInfo.release[0];
char minorChar=unameInfo.release[2];
-
+
if( isdigit(majorChar) )
{
linuxMajor=majorChar-'0';
}
-
+
if( isdigit(minorChar) )
{
linuxMinor=minorChar-'0';
}
}
-
+
FILE *fd = fopen("/proc/meminfo", "r" );
- if ( !fd )
+ if ( !fd )
{
kwsys_ios::cout << "Problem opening /proc/meminfo" << kwsys_ios::endl;
- return 0;
+ return false;
}
-
+
if( linuxMajor>=3 || ( (linuxMajor>=2) && (linuxMinor>=6) ) )
{
// new /proc/meminfo format since kernel 2.6.x
@@ -2493,13 +3510,13 @@ int SystemInformationImplementation::QueryMemory()
{
kwsys_ios::cout << "Problem parsing /proc/meminfo" << kwsys_ios::endl;
fclose(fd);
- return 0;
+ return false;
}
}
else
{
// /proc/meminfo format for kernel older than 2.6.x
-
+
unsigned long temp;
unsigned long cachedMem;
unsigned long buffersMem;
@@ -2525,72 +3542,132 @@ int SystemInformationImplementation::QueryMemory()
{
kwsys_ios::cout << "Problem parsing /proc/meminfo" << kwsys_ios::endl;
fclose(fd);
- return 0;
+ return false;
}
}
fclose( fd );
- return 1;
-#elif defined(__hpux)
- unsigned long tv=0;
- unsigned long tp=0;
- unsigned long av=0;
- unsigned long ap=0;
- struct pst_static pst;
- struct pst_dynamic pdy;
-
- unsigned long ps = 0;
- if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) != -1)
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool SystemInformationImplementation::QueryCygwinMemory()
+{
+#ifdef __CYGWIN__
+ // _SC_PAGE_SIZE does return the mmap() granularity on Cygwin,
+ // see http://cygwin.com/ml/cygwin/2006-06/msg00350.html
+ // Therefore just use 4096 as the page size of Windows.
+ long m = sysconf(_SC_PHYS_PAGES);
+ if (m < 0)
{
- ps = pst.page_size;
- tp = pst.physical_memory *ps;
- tv = (pst.physical_memory + pst.pst_maxmem) * ps;
- if (pstat_getdynamic(&pdy, sizeof(pdy), (size_t) 1, 0) != -1)
- {
- ap = tp - pdy.psd_rm * ps;
- av = tv - pdy.psd_vm;
- this->TotalVirtualMemory = tv>>10>>10;
- this->TotalPhysicalMemory = tp>>10>>10;
- this->AvailableVirtualMemory = av>>10>>10;
- this->AvailablePhysicalMemory = ap>>10>>10;
- return 1;
- }
+ return false;
}
- return 0;
+ this->TotalPhysicalMemory = m >> 8;
+ return true;
#else
- return 0;
+ return false;
+#endif
+}
+
+bool SystemInformationImplementation::QueryAIXMemory()
+{
+#if defined(_AIX)
+ long c = sysconf(_SC_AIX_REALMEM);
+ if (c <= 0)
+ {
+ return false;
+ }
+
+ this->TotalPhysicalMemory = c / 1024;
+
+ return true;
+#else
+ return false;
#endif
+}
+bool SystemInformationImplementation::QueryMemoryBySysconf()
+{
+#if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
+ // Assume the mmap() granularity as returned by _SC_PAGESIZE is also
+ // the system page size. The only known system where this isn't true
+ // is Cygwin.
+ long p = sysconf(_SC_PHYS_PAGES);
+ long m = sysconf(_SC_PAGESIZE);
+
+ if (p < 0 || m < 0)
+ {
+ return false;
+ }
+
+ // assume pagesize is a power of 2 and smaller 1 MiB
+ size_t pagediv = (1024 * 1024 / m);
+ this->TotalPhysicalMemory = p;
+ this->TotalPhysicalMemory /= pagediv;
+
+#if defined(_SC_AVPHYS_PAGES)
+ p = sysconf(_SC_AVPHYS_PAGES);
+ if (p < 0)
+ {
+ return false;
+ }
+
+ this->AvailablePhysicalMemory = p;
+ this->AvailablePhysicalMemory /= pagediv;
+#endif
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+/** Query for the memory status */
+bool SystemInformationImplementation::QueryMemory()
+{
+ return this->QueryMemoryBySysconf();
}
/** */
-size_t SystemInformationImplementation::GetTotalVirtualMemory()
-{
- return this->TotalVirtualMemory;
+size_t SystemInformationImplementation::GetTotalVirtualMemory()
+{
+ return this->TotalVirtualMemory;
}
/** */
-size_t SystemInformationImplementation::GetAvailableVirtualMemory()
-{
- return this->AvailableVirtualMemory;
+size_t SystemInformationImplementation::GetAvailableVirtualMemory()
+{
+ return this->AvailableVirtualMemory;
}
-size_t SystemInformationImplementation::GetTotalPhysicalMemory()
-{
- return this->TotalPhysicalMemory;
+size_t SystemInformationImplementation::GetTotalPhysicalMemory()
+{
+ return this->TotalPhysicalMemory;
}
/** */
-size_t SystemInformationImplementation::GetAvailablePhysicalMemory()
-{
- return this->AvailablePhysicalMemory;
+size_t SystemInformationImplementation::GetAvailablePhysicalMemory()
+{
+ return this->AvailablePhysicalMemory;
}
/** Get Cycle differences */
-LongLong SystemInformationImplementation::GetCyclesDifference (DELAY_FUNC DelayFunction,
+SystemInformation::LongLong
+SystemInformationImplementation::GetCyclesDifference (DELAY_FUNC DelayFunction,
unsigned int uiParameter)
{
-#if USE_ASM_INSTRUCTIONS
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+ unsigned __int64 stamp1, stamp2;
+
+ stamp1 = __rdtsc();
+ DelayFunction(uiParameter);
+ stamp2 = __rdtsc();
+
+ return stamp2 - stamp1;
+#elif USE_ASM_INSTRUCTIONS
unsigned int edx1, eax1;
unsigned int edx2, eax2;
@@ -2619,7 +3696,7 @@ LongLong SystemInformationImplementation::GetCyclesDifference (DELAY_FUNC DelayF
mov eax1, esi ; eax2 = esi
}
}
- __except(1)
+ __except(1)
{
return -1;
}
@@ -2642,7 +3719,7 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS)
__int64 x;
// Get the frequency of the high performance counter.
- if(!QueryPerformanceFrequency (&Frequency))
+ if(!QueryPerformanceFrequency (&Frequency))
{
return;
}
@@ -2650,9 +3727,9 @@ void SystemInformationImplementation::DelayOverhead(unsigned int uiMS)
// Get the starting position of the counter.
QueryPerformanceCounter (&StartCounter);
-
+
do {
- // Get the ending position of the counter.
+ // Get the ending position of the counter.
QueryPerformanceCounter (&EndCounter);
} while (EndCounter.QuadPart - StartCounter.QuadPart == x);
#endif
@@ -2672,61 +3749,53 @@ unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void)
}
return static_cast<unsigned char>(cores_per_package);
#else
- unsigned int Regebx = 0;
-#if USE_ASM_INSTRUCTIONS
+ int Regs[4] = { 0, 0, 0, 0 };
+#if USE_CPUID
if (!this->IsHyperThreadingSupported())
{
return static_cast<unsigned char>(1); // HT not supported
}
- __asm
- {
- mov eax, 1
- cpuid
- mov Regebx, ebx
- }
+ call_cpuid(1, Regs);
#endif
- return static_cast<unsigned char> ((Regebx & NUM_LOGICAL_BITS) >> 16);
+ return static_cast<unsigned char> ((Regs[1] & NUM_LOGICAL_BITS) >> 16);
#endif
}
/** Works only for windows */
-unsigned int SystemInformationImplementation::IsHyperThreadingSupported()
+bool SystemInformationImplementation::IsHyperThreadingSupported()
{
-#if USE_ASM_INSTRUCTIONS
- unsigned int Regedx = 0,
- Regeax = 0,
- VendorId[3] = {0, 0, 0};
- __try // Verify cpuid instruction is supported
+ if (this->Features.ExtendedFeatures.SupportsHyperthreading)
{
- __asm
- {
- xor eax, eax // call cpuid with eax = 0
- cpuid // Get vendor id string
- mov VendorId, ebx
- mov VendorId + 4, edx
- mov VendorId + 8, ecx
-
- mov eax, 1 // call cpuid with eax = 1
- cpuid
- mov Regeax, eax // eax contains family processor type
- mov Regedx, edx // edx has info about the availability of hyper-Threading
- }
+ return true;
}
- __except (EXCEPTION_EXECUTE_HANDLER)
+
+#if USE_CPUID
+ int Regs[4] = { 0, 0, 0, 0 },
+ VendorId[4] = { 0, 0, 0, 0 };
+ // Get vendor id string
+ if (!call_cpuid(0, VendorId))
{
- return(0); // cpuid is unavailable
+ return false;
+ }
+ // eax contains family processor type
+ // edx has info about the availability of hyper-Threading
+ if (!call_cpuid(1, Regs))
+ {
+ return false;
}
- if (((Regeax & FAMILY_ID) == PENTIUM4_ID) || (Regeax & EXT_FAMILY_ID))
+ if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID))
{
- if (VendorId[0] == 'uneG')
+ if (VendorId[1] == 0x756e6547) // 'uneG'
{
- if (VendorId[1] == 'Ieni')
+ if (VendorId[3] == 0x49656e69) // 'Ieni'
{
- if (VendorId[2] == 'letn')
+ if (VendorId[2] == 0x6c65746e) // 'letn'
{
- return(Regedx & HT_BIT); // Genuine Intel with hyper-Threading technology
+ // Genuine Intel with hyper-Threading technology
+ this->Features.ExtendedFeatures.SupportsHyperthreading = ((Regs[3] & HT_BIT) != 0);
+ return this->Features.ExtendedFeatures.SupportsHyperthreading;
}
}
}
@@ -2740,22 +3809,17 @@ unsigned int SystemInformationImplementation::IsHyperThreadingSupported()
/** Return the APIC Id. Works only for windows. */
unsigned char SystemInformationImplementation::GetAPICId()
{
- unsigned int Regebx = 0;
+ int Regs[4] = { 0, 0, 0, 0 };
-#if USE_ASM_INSTRUCTIONS
- if (!this->IsHyperThreadingSupported())
+#if USE_CPUID
+ if (!this->IsHyperThreadingSupported())
{
return static_cast<unsigned char>(-1); // HT not supported
} // Logical processor = 1
- __asm
- {
- mov eax, 1
- cpuid
- mov Regebx, ebx
- }
+ call_cpuid(1, Regs);
#endif
- return static_cast<unsigned char>((Regebx & INITIAL_APIC_ID_BITS) >> 24);
+ return static_cast<unsigned char>((Regs[1] & INITIAL_APIC_ID_BITS) >> 24);
}
@@ -2773,7 +3837,7 @@ int SystemInformationImplementation::CPUCount()
// Number of physical processors in a non-Intel system
// or in a 32-bit Intel system with Hyper-Threading technology disabled
- this->NumberOfPhysicalCPU = (unsigned char) info.dwNumberOfProcessors;
+ this->NumberOfPhysicalCPU = (unsigned char) info.dwNumberOfProcessors;
if (this->IsHyperThreadingSupported())
{
@@ -2789,7 +3853,7 @@ int SystemInformationImplementation::CPUCount()
DWORD_PTR dwSystemAffinity;
DWORD dwAffinityMask;
- // Calculate the appropriate shifts and mask based on the
+ // Calculate the appropriate shifts and mask based on the
// number of logical processors.
unsigned int i = 1;
unsigned char PHY_ID_MASK = 0xFF;
@@ -2801,7 +3865,7 @@ int SystemInformationImplementation::CPUCount()
PHY_ID_MASK <<= 1;
// PHY_ID_SHIFT++;
}
-
+
hCurrentProcessHandle = GetCurrentProcess();
GetProcessAffinityMask(hCurrentProcessHandle, &dwProcessAffinity,
&dwSystemAffinity);
@@ -2829,8 +3893,8 @@ int SystemInformationImplementation::CPUCount()
APIC_ID = GetAPICId();
LOG_ID = APIC_ID & ~PHY_ID_MASK;
-
- if (LOG_ID != 0)
+
+ if (LOG_ID != 0)
{
HT_Enabled = 1;
}
@@ -2840,7 +3904,7 @@ int SystemInformationImplementation::CPUCount()
}
// Reset the processor affinity
SetProcessAffinityMask(hCurrentProcessHandle, dwProcessAffinity);
-
+
if (this->NumberOfLogicalCPU == 1) // Normal P4 : HT is disabled in hardware
{
StatusFlag = HT_DISABLED;
@@ -2853,7 +3917,7 @@ int SystemInformationImplementation::CPUCount()
this->NumberOfPhysicalCPU /= (this->NumberOfLogicalCPU);
StatusFlag = HT_ENABLED;
}
- else
+ else
{
StatusFlag = HT_SUPPORTED_NOT_ENABLED;
}
@@ -2891,6 +3955,7 @@ unsigned int SystemInformationImplementation::GetNumberOfPhysicalCPU()
bool SystemInformationImplementation::ParseSysCtl()
{
#if defined(__APPLE__)
+ char retBuf[128];
int err = 0;
uint64_t value = 0;
size_t len = sizeof(value);
@@ -2901,9 +3966,10 @@ bool SystemInformationImplementation::ParseSysCtl()
this->AvailablePhysicalMemory = 0;
vm_statistics_data_t vmstat;
mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
- if ( host_statistics(mach_host_self(), HOST_VM_INFO,
+ if ( host_statistics(mach_host_self(), HOST_VM_INFO,
(host_info_t) &vmstat, &count) == KERN_SUCCESS )
{
+ len = sizeof(value);
err = sysctlbyname("hw.pagesize", &value, &len, NULL, 0);
int64_t available_memory = vmstat.free_count * value;
this->AvailablePhysicalMemory = static_cast< size_t >( available_memory / 1048576 );
@@ -2914,7 +3980,7 @@ bool SystemInformationImplementation::ParseSysCtl()
int mib[2] = { CTL_VM, VM_SWAPUSAGE };
size_t miblen = sizeof(mib) / sizeof(mib[0]);
struct xsw_usage swap;
- len = sizeof(struct xsw_usage);
+ len = sizeof(swap);
err = sysctl(mib, miblen, &swap, &len, NULL, 0);
if (err == 0)
{
@@ -2929,8 +3995,9 @@ bool SystemInformationImplementation::ParseSysCtl()
// CPU Info
len = sizeof(this->NumberOfPhysicalCPU);
sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0);
+ len = sizeof(this->NumberOfLogicalCPU);
sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0);
- this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
+ this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
this->LogicalCPUPerPhysicalCPU();
len = sizeof(value);
@@ -2947,16 +4014,16 @@ bool SystemInformationImplementation::ParseSysCtl()
if (err != 0) // Go back to names we know but are less descriptive
{
this->ChipID.Family = 0;
- char retBuf[32];
- ::memset(retBuf, 0, 32);
+ ::memset(retBuf, 0, 128);
len = 32;
- err = sysctlbyname("hw.machine", &retBuf, &len, NULL, 0);
+ err = sysctlbyname("hw.machine", &retBuf, &len, NULL, 0);
kwsys_stl::string machineBuf(retBuf);
if (machineBuf.find_first_of("Power") != kwsys_stl::string::npos)
{
this->ChipID.Vendor = "IBM";
- len = 4;
+ len = sizeof(this->ChipID.Family);
err = sysctlbyname("hw.cputype", &this->ChipID.Family, &len, NULL, 0);
+ len = sizeof(this->ChipID.Model);
err = sysctlbyname("hw.cpusubtype", &this->ChipID.Model, &len, NULL, 0);
this->FindManufacturer();
}
@@ -2964,35 +4031,115 @@ bool SystemInformationImplementation::ParseSysCtl()
else // Should be an Intel Chip.
{
len = sizeof(this->ChipID.Family);
- err =
+ err =
sysctlbyname("machdep.cpu.family", &this->ChipID.Family, &len, NULL, 0);
-
- char retBuf[128];
+
::memset(retBuf, 0, 128);
len = 128;
err = sysctlbyname("machdep.cpu.vendor", retBuf, &len, NULL, 0);
// Chip Vendor
this->ChipID.Vendor = retBuf;
this->FindManufacturer();
-
- ::memset(retBuf, 0, 128);
- err =
- sysctlbyname("machdep.cpu.brand_string",
- retBuf, &len, NULL, 0);
- this->ChipID.ProcessorName = retBuf;
// Chip Model
len = sizeof(value);
err = sysctlbyname("machdep.cpu.model", &value, &len, NULL, 0);
this->ChipID.Model = static_cast< int >( value );
+
+ // Chip Stepping
+ len = sizeof(value);
+ value = 0;
+ err = sysctlbyname("machdep.cpu.stepping", &value, &len, NULL, 0);
+ if (!err)
+ {
+ this->ChipID.Revision = static_cast< int >( value );
+ }
+
+ // feature string
+ char *buf = 0;
+ size_t allocSize = 128;
+
+ err = 0;
+ len = 0;
+
+ // sysctlbyname() will return with err==0 && len==0 if the buffer is too small
+ while (err == 0 && len == 0)
+ {
+ delete[] buf;
+ allocSize *= 2;
+ buf = new char[allocSize];
+ if (!buf)
+ {
+ break;
+ }
+ buf[0] = ' ';
+ len = allocSize - 2; // keep space for leading and trailing space
+ err = sysctlbyname("machdep.cpu.features", buf + 1, &len, NULL, 0);
+ }
+ if (!err && buf && len)
+ {
+ // now we can match every flags as space + flag + space
+ buf[len + 1] = ' ';
+ kwsys_stl::string cpuflags(buf, len + 2);
+
+ if ((cpuflags.find(" FPU ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasFPU = true;
+ }
+ if ((cpuflags.find(" TSC ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasTSC = true;
+ }
+ if ((cpuflags.find(" MMX ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasMMX = true;
+ }
+ if ((cpuflags.find(" SSE ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasSSE = true;
+ }
+ if ((cpuflags.find(" SSE2 ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasSSE2 = true;
+ }
+ if ((cpuflags.find(" APIC ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasAPIC = true;
+ }
+ if ((cpuflags.find(" CMOV ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasCMOV = true;
+ }
+ if ((cpuflags.find(" MTRR ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasMTRR = true;
+ }
+ if ((cpuflags.find(" ACPI ")!=kwsys_stl::string::npos))
+ {
+ this->Features.HasACPI = true;
+ }
+ }
+ delete[] buf;
}
+
+ // brand string
+ ::memset(retBuf, 0, sizeof(retBuf));
+ len = sizeof(retBuf);
+ err = sysctlbyname("machdep.cpu.brand_string", retBuf, &len, NULL, 0);
+ if (!err)
+ {
+ this->ChipID.ProcessorName = retBuf;
+ this->ChipID.ModelName = retBuf;
+ }
+
// Cache size
len = sizeof(value);
err = sysctlbyname("hw.l1icachesize", &value, &len, NULL, 0);
this->Features.L1CacheSize = static_cast< int >( value );
+ len = sizeof(value);
err = sysctlbyname("hw.l2cachesize", &value, &len, NULL, 0);
this->Features.L2CacheSize = static_cast< int >( value );
-
+
return true;
#else
return false;
@@ -3019,7 +4166,7 @@ kwsys_stl::string SystemInformationImplementation::ExtractValueFromSysCtl(const
/** Run a given process */
kwsys_stl::string SystemInformationImplementation::RunProcess(kwsys_stl::vector<const char*> args)
-{
+{
kwsys_stl::string buffer = "";
// Run the application
@@ -3032,13 +4179,12 @@ kwsys_stl::string SystemInformationImplementation::RunProcess(kwsys_stl::vector<
char* data = NULL;
int length;
double timeout = 255;
+ int pipe; // pipe id as returned by kwsysProcess_WaitForData()
- while(kwsysProcess_WaitForData(gp,&data,&length,&timeout)) // wait for 1s
+ while( ( pipe = kwsysProcess_WaitForData(gp,&data,&length,&timeout),
+ (pipe == kwsysProcess_Pipe_STDOUT || pipe == kwsysProcess_Pipe_STDERR) ) ) // wait for 1s
{
- for(int i=0;i<length;i++)
- {
- buffer += data[i];
- }
+ buffer.append(data, length);
}
kwsysProcess_WaitForExit(gp, 0);
@@ -3085,7 +4231,7 @@ kwsys_stl::string SystemInformationImplementation::ParseValueFromKStat(const cha
args.clear();
args.push_back("kstat");
args.push_back("-p");
-
+
kwsys_stl::string command = arguments;
size_t start = command.npos;
size_t pos = command.find(' ',0);
@@ -3105,7 +4251,7 @@ kwsys_stl::string SystemInformationImplementation::ParseValueFromKStat(const cha
b0 = command.find('"',b1+1);
b1 = command.find('"',b0+1);
}
-
+
if(!inQuotes)
{
kwsys_stl::string arg = command.substr(start+1,pos-start-1);
@@ -3117,7 +4263,7 @@ kwsys_stl::string SystemInformationImplementation::ParseValueFromKStat(const cha
arg.erase(quotes,1);
quotes = arg.find('"');
}
- args.push_back(arg.c_str());
+ args.push_back(arg.c_str());
start = pos;
}
pos = command.find(' ',pos+1);
@@ -3146,48 +4292,55 @@ kwsys_stl::string SystemInformationImplementation::ParseValueFromKStat(const cha
return value;
}
-
/** Querying for system information from Solaris */
-bool SystemInformationImplementation::QuerySolarisInfo()
+bool SystemInformationImplementation::QuerySolarisMemory()
{
- // Parse values
- this->NumberOfPhysicalCPU = static_cast<unsigned int>(
- atoi(this->ParseValueFromKStat("-n syste_misc -s ncpus").c_str()));
- this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
-
- if(this->NumberOfPhysicalCPU!=0)
+#if defined (__SVR4) && defined (__sun)
+ // Solaris allows querying this value by sysconf, but if this is
+ // a 32 bit process on a 64 bit host the returned memory will be
+ // limited to 4GiB. So if this is a 32 bit process or if the sysconf
+ // method fails use the kstat interface.
+#if SIZEOF_VOID_P == 8
+ if (this->QueryMemoryBySysconf())
{
- this->NumberOfLogicalCPU /= this->NumberOfPhysicalCPU;
+ return true;
}
+#endif
+
+ char* tail;
+ unsigned long totalMemory =
+ strtoul(this->ParseValueFromKStat("-s physmem").c_str(),&tail,0);
+ this->TotalPhysicalMemory = totalMemory/128;
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool SystemInformationImplementation::QuerySolarisProcessor()
+{
+ if (!this->QueryProcessorBySysconf())
+ {
+ return false;
+ }
+
+ // Parse values
this->CPUSpeedInMHz = static_cast<float>(atoi(this->ParseValueFromKStat("-s clock_MHz").c_str()));
// Chip family
- this->ChipID.Family = 0;
-
- // Chip Vendor
- this->ChipID.Vendor = "Sun";
- this->FindManufacturer();
-
+ this->ChipID.Family = 0;
+
// Chip Model
this->ChipID.ProcessorName = this->ParseValueFromKStat("-s cpu_type");
this->ChipID.Model = 0;
- // Cache size
- this->Features.L1CacheSize = 0;
- this->Features.L2CacheSize = 0;
-
- char* tail;
- unsigned long totalMemory =
- strtoul(this->ParseValueFromKStat("-s physmem").c_str(),&tail,0);
- this->TotalPhysicalMemory = totalMemory/1024;
- this->TotalPhysicalMemory *= 8192;
- this->TotalPhysicalMemory /= 1024;
-
- // Undefined values (for now at least)
- this->TotalVirtualMemory = 0;
- this->AvailablePhysicalMemory = 0;
- this->AvailableVirtualMemory = 0;
+ // Chip Vendor
+ if (this->ChipID.ProcessorName != "i386")
+ {
+ this->ChipID.Vendor = "Sun";
+ this->FindManufacturer();
+ }
return true;
}
@@ -3200,16 +4353,16 @@ bool SystemInformationImplementation::QueryHaikuInfo()
system_info info;
get_system_info(&info);
-
+
this->NumberOfPhysicalCPU = info.cpu_count;
this->CPUSpeedInMHz = info.cpu_clock_speed / 1000000.0F;
// Physical Memory
this->TotalPhysicalMemory = (info.max_pages * B_PAGE_SIZE) / (1024 * 1024) ;
- this->AvailablePhysicalMemory = this->TotalPhysicalMemory -
+ this->AvailablePhysicalMemory = this->TotalPhysicalMemory -
((info.used_pages * B_PAGE_SIZE) / (1024 * 1024));
-
+
// NOTE: get_system_info_etc is currently a private call so just set to 0
// until it becomes public
this->TotalVirtualMemory = 0;
@@ -3237,8 +4390,8 @@ bool SystemInformationImplementation::QueryHaikuInfo()
this->ChipID.Type = cpu_info.eax_1.type;
// Chip family
- this->ChipID.Family = cpu_info.eax_1.family;
-
+ this->ChipID.Family = cpu_info.eax_1.family;
+
// Chip Model
this->ChipID.Model = cpu_info.eax_1.model;
@@ -3296,6 +4449,31 @@ bool SystemInformationImplementation::QueryQNXMemory()
return false;
}
+bool SystemInformationImplementation::QueryBSDMemory()
+{
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+ int ctrl[2] = { CTL_HW, HW_PHYSMEM };
+#if defined(HW_PHYSMEM64)
+ int64_t k;
+ ctrl[1] = HW_PHYSMEM64;
+#else
+ int k;
+#endif
+ size_t sz = sizeof(k);
+
+ if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0)
+ {
+ return false;
+ }
+
+ this->TotalPhysicalMemory = k>>10>>10;
+
+ return true;
+#else
+ return false;
+#endif
+}
+
bool SystemInformationImplementation::QueryQNXProcessor()
{
#if defined(__QNX__)
@@ -3349,6 +4527,163 @@ bool SystemInformationImplementation::QueryQNXProcessor()
#endif
}
+bool SystemInformationImplementation::QueryBSDProcessor()
+{
+#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
+ int k;
+ size_t sz = sizeof(k);
+ int ctrl[2] = { CTL_HW, HW_NCPU };
+
+ if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0)
+ {
+ return false;
+ }
+
+ this->NumberOfPhysicalCPU = k;
+ this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
+
+#if defined(HW_CPUSPEED)
+ ctrl[1] = HW_CPUSPEED;
+
+ if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0)
+ {
+ return false;
+ }
+
+ this->CPUSpeedInMHz = (float) k;
+#endif
+
+#if defined(CPU_SSE)
+ ctrl[0] = CTL_MACHDEP;
+ ctrl[1] = CPU_SSE;
+
+ if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0)
+ {
+ return false;
+ }
+
+ this->Features.HasSSE = (k > 0);
+#endif
+
+#if defined(CPU_SSE2)
+ ctrl[0] = CTL_MACHDEP;
+ ctrl[1] = CPU_SSE2;
+
+ if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0)
+ {
+ return false;
+ }
+
+ this->Features.HasSSE2 = (k > 0);
+#endif
+
+#if defined(CPU_CPUVENDOR)
+ ctrl[0] = CTL_MACHDEP;
+ ctrl[1] = CPU_CPUVENDOR;
+ char vbuf[25];
+ ::memset(vbuf, 0, sizeof(vbuf));
+ sz = sizeof(vbuf) - 1;
+ if (sysctl(ctrl, 2, vbuf, &sz, NULL, 0) != 0)
+ {
+ return false;
+ }
+
+ this->ChipID.Vendor = vbuf;
+ this->FindManufacturer();
+#endif
+
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool SystemInformationImplementation::QueryHPUXMemory()
+{
+#if defined(__hpux)
+ unsigned long tv=0;
+ unsigned long tp=0;
+ unsigned long av=0;
+ unsigned long ap=0;
+ struct pst_static pst;
+ struct pst_dynamic pdy;
+
+ unsigned long ps = 0;
+ if (pstat_getstatic(&pst, sizeof(pst), (size_t) 1, 0) == -1)
+ {
+ return false;
+ }
+
+ ps = pst.page_size;
+ tp = pst.physical_memory *ps;
+ tv = (pst.physical_memory + pst.pst_maxmem) * ps;
+ if (pstat_getdynamic(&pdy, sizeof(pdy), (size_t) 1, 0) == -1)
+ {
+ return false;
+ }
+
+ ap = tp - pdy.psd_rm * ps;
+ av = tv - pdy.psd_vm;
+ this->TotalVirtualMemory = tv>>10>>10;
+ this->TotalPhysicalMemory = tp>>10>>10;
+ this->AvailableVirtualMemory = av>>10>>10;
+ this->AvailablePhysicalMemory = ap>>10>>10;
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool SystemInformationImplementation::QueryHPUXProcessor()
+{
+#if defined(__hpux)
+# if defined(KWSYS_SYS_HAS_MPCTL_H)
+ int c = mpctl(MPC_GETNUMSPUS_SYS, 0, 0);
+ if (c <= 0)
+ {
+ return false;
+ }
+
+ this->NumberOfPhysicalCPU = c;
+ this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
+
+ long t = sysconf(_SC_CPU_VERSION);
+
+ if (t == -1)
+ {
+ return false;
+ }
+
+ switch (t)
+ {
+ case CPU_PA_RISC1_0:
+ this->ChipID.Vendor = "Hewlett-Packard";
+ this->ChipID.Family = 0x100;
+ case CPU_PA_RISC1_1:
+ this->ChipID.Vendor = "Hewlett-Packard";
+ this->ChipID.Family = 0x110;
+ case CPU_PA_RISC2_0:
+ this->ChipID.Vendor = "Hewlett-Packard";
+ this->ChipID.Family = 0x200;
+ case CPU_IA64_ARCHREV_0:
+ this->ChipID.Vendor = "GenuineIntel";
+ this->Features.HasIA64 = true;
+ break;
+ default:
+ return false;
+ }
+
+ this->FindManufacturer();
+
+ return true;
+# else
+ return false;
+# endif
+#else
+ return false;
+#endif
+}
+
/** Query the operating system information */
bool SystemInformationImplementation::QueryOSInformation()
{
@@ -3365,16 +4700,16 @@ bool SystemInformationImplementation::QueryOSInformation()
ZeroMemory (&osvi, sizeof (OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi);
- if (!bOsVersionInfoEx)
+ if (!bOsVersionInfoEx)
{
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
- if (!GetVersionEx ((OSVERSIONINFO *) &osvi))
+ if (!GetVersionEx ((OSVERSIONINFO *) &osvi))
{
return false;
}
}
- switch (osvi.dwPlatformId)
+ switch (osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
// Test for the product.
@@ -3417,40 +4752,40 @@ bool SystemInformationImplementation::QueryOSInformation()
{
this->OSRelease += " Personal";
}
- else
+ else
{
this->OSRelease += " Professional";
}
}
#endif
- }
+ }
else if (osvi.wProductType == VER_NT_SERVER)
{
// Check for .NET Server instead of Windows XP.
- if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
{
this->OSRelease = ".NET";
}
// Continue with the type detection.
- if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
{
this->OSRelease += " DataCenter Server";
}
- else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
{
this->OSRelease += " Advanced Server";
}
- else
+ else
{
this->OSRelease += " Server";
}
}
sprintf (operatingSystem, "%s (Build %ld)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
- this->OSVersion = operatingSystem;
+ this->OSVersion = operatingSystem;
}
- else
+ else
#endif // VER_NT_WORKSTATION
{
HKEY hKey;
@@ -3473,7 +4808,7 @@ bool SystemInformationImplementation::QueryOSInformation()
{
this->OSRelease += " Standard Server";
}
- else
+ else
{
this->OSRelease += " Server";
}
@@ -3485,7 +4820,7 @@ bool SystemInformationImplementation::QueryOSInformation()
{
this->OSRelease += " Enterprise Server";
}
- else
+ else
{
this->OSRelease += " Advanced Server";
}
@@ -3493,7 +4828,7 @@ bool SystemInformationImplementation::QueryOSInformation()
}
// Display version, service pack (if any), and build number.
- if (osvi.dwMajorVersion <= 4)
+ if (osvi.dwMajorVersion <= 4)
{
// NB: NT 4.0 and earlier.
sprintf (operatingSystem, "version %ld.%ld %s (Build %ld)",
@@ -3502,30 +4837,30 @@ bool SystemInformationImplementation::QueryOSInformation()
osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF);
this->OSVersion = operatingSystem;
- }
- else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
+ }
+ else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
{
// Windows XP and .NET server.
typedef BOOL (CALLBACK* LPFNPROC) (HANDLE, BOOL *);
- HINSTANCE hKernelDLL;
+ HINSTANCE hKernelDLL;
LPFNPROC DLLProc;
-
+
// Load the Kernel32 DLL.
hKernelDLL = LoadLibrary ("kernel32");
- if (hKernelDLL != NULL) {
+ if (hKernelDLL != NULL) {
// Only XP and .NET Server support IsWOW64Process so... Load dynamically!
- DLLProc = (LPFNPROC) GetProcAddress (hKernelDLL, "IsWow64Process");
-
+ DLLProc = (LPFNPROC) GetProcAddress (hKernelDLL, "IsWow64Process");
+
// If the function address is valid, call the function.
if (DLLProc != NULL) (DLLProc) (GetCurrentProcess (), &bIsWindows64Bit);
else bIsWindows64Bit = false;
-
+
// Free the DLL module.
- FreeLibrary (hKernelDLL);
- }
- }
- else
- {
+ FreeLibrary (hKernelDLL);
+ }
+ }
+ else
+ {
// Windows 2000 and everything else.
sprintf (operatingSystem,"%s (Build %ld)", osvi.szCSDVersion, osvi.dwBuildNumber & 0xFFFF);
this->OSVersion = operatingSystem;
@@ -3534,32 +4869,32 @@ bool SystemInformationImplementation::QueryOSInformation()
case VER_PLATFORM_WIN32_WINDOWS:
// Test for the product.
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
{
this->OSRelease = "95";
- if(osvi.szCSDVersion[1] == 'C')
+ if(osvi.szCSDVersion[1] == 'C')
{
this->OSRelease += "OSR 2.5";
}
- else if(osvi.szCSDVersion[1] == 'B')
+ else if(osvi.szCSDVersion[1] == 'B')
{
this->OSRelease += "OSR 2";
}
- }
+ }
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
{
this->OSRelease = "98";
- if (osvi.szCSDVersion[1] == 'A' )
+ if (osvi.szCSDVersion[1] == 'A' )
{
this->OSRelease += "SE";
}
- }
+ }
- if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
+ if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
{
this->OSRelease = "Me";
- }
+ }
break;
case VER_PLATFORM_WIN32s:
@@ -3583,7 +4918,7 @@ bool SystemInformationImplementation::QueryOSInformation()
WSACleanup( );
}
this->Hostname = name;
-
+
const char* arch = getenv("PROCESSOR_ARCHITECTURE");
if(arch)
{
@@ -3604,51 +4939,41 @@ bool SystemInformationImplementation::QueryOSInformation()
}
#ifdef __APPLE__
- this->CallSwVers();
+ this->OSName="Unknown Apple OS";
+ this->OSRelease="Unknown product version";
+ this->OSVersion="Unknown build version";
+
+ this->CallSwVers("-productName",this->OSName);
+ this->CallSwVers("-productVersion",this->OSRelease);
+ this->CallSwVers("-buildVersion",this->OSVersion);
#endif
#endif
return true;
-
}
-
-void SystemInformationImplementation::CallSwVers()
+int SystemInformationImplementation::CallSwVers(
+ const char *arg,
+ kwsys_stl::string &ver)
{
#ifdef __APPLE__
- kwsys_stl::string output;
kwsys_stl::vector<const char*> args;
- args.clear();
-
- args.push_back("sw_vers");
- args.push_back("-productName");
- args.push_back(0);
- output = this->RunProcess(args);
- this->TrimNewline(output);
- this->OSName = output;
- args.clear();
-
- args.push_back("sw_vers");
- args.push_back("-productVersion");
- args.push_back(0);
- output = this->RunProcess(args);
- this->TrimNewline(output);
- this->OSRelease = output;
- args.clear();
-
args.push_back("sw_vers");
- args.push_back("-buildVersion");
+ args.push_back(arg);
args.push_back(0);
- output = this->RunProcess(args);
- this->TrimNewline(output);
- this->OSVersion = output;
+ ver = this->RunProcess(args);
+ this->TrimNewline(ver);
+#else
+ // avoid C4100
+ (void)arg;
+ (void)ver;
#endif
+ return 0;
}
-
void SystemInformationImplementation::TrimNewline(kwsys_stl::string& output)
-{
+{
// remove \r
kwsys_stl::string::size_type pos=0;
while((pos = output.find("\r", pos)) != kwsys_stl::string::npos)
diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in
index b6ebe6aee..8f4cb4e5a 100644
--- a/Source/kwsys/SystemInformation.hxx.in
+++ b/Source/kwsys/SystemInformation.hxx.in
@@ -24,14 +24,22 @@
namespace @KWSYS_NAMESPACE@
{
-
-// forward declare the implementation class
+// forward declare the implementation class
class SystemInformationImplementation;
-
-class @KWSYS_NAMESPACE@_EXPORT SystemInformation
-{
+class @KWSYS_NAMESPACE@_EXPORT SystemInformation
+{
+#if @KWSYS_USE_LONG_LONG@
+ typedef long long LongLong;
+#elif @KWSYS_USE___INT64@
+ typedef __int64 LongLong;
+#else
+# error "No Long Long"
+#endif
+ friend class SystemInformationImplementation;
+ SystemInformationImplementation* Implementation;
public:
+
SystemInformation ();
~SystemInformation ();
@@ -40,6 +48,7 @@ public:
kwsys_stl::string GetTypeID();
kwsys_stl::string GetFamilyID();
kwsys_stl::string GetModelID();
+ kwsys_stl::string GetModelName();
kwsys_stl::string GetSteppingCode();
const char * GetExtendedProcessorName();
const char * GetProcessorSerialNumber();
@@ -49,13 +58,27 @@ public:
int GetProcessorAPICID();
int GetProcessorCacheXSize(long int);
bool DoesCPUSupportFeature(long int);
-
- const char * GetOSName();
+
+ // returns an informative general description of the cpu
+ // on this system.
+ kwsys_stl::string GetCPUDescription();
+
const char * GetHostname();
+ kwsys_stl::string GetFullyQualifiedDomainName();
+
+ const char * GetOSName();
const char * GetOSRelease();
const char * GetOSVersion();
const char * GetOSPlatform();
+ int GetOSIsWindows();
+ int GetOSIsLinux();
+ int GetOSIsApple();
+
+ // returns an informative general description of the os
+ // on this system.
+ kwsys_stl::string GetOSDescription();
+
bool Is64Bits();
unsigned int GetNumberOfLogicalCPU(); // per physical cpu
@@ -63,20 +86,62 @@ public:
bool DoesCPUSupportCPUID();
+ // Retrieve id of the current running process
+ LongLong GetProcessId();
+
// Retrieve memory information in megabyte.
size_t GetTotalVirtualMemory();
size_t GetAvailableVirtualMemory();
size_t GetTotalPhysicalMemory();
- size_t GetAvailablePhysicalMemory();
+ size_t GetAvailablePhysicalMemory();
+
+ // returns an informative general description if the installed and
+ // available ram on this system. See the GetHostMmeoryTotal, and
+ // Get{Host,Proc}MemoryAvailable methods for more information.
+ kwsys_stl::string GetMemoryDescription(
+ const char *hostLimitEnvVarName=NULL,
+ const char *procLimitEnvVarName=NULL);
+
+ // Retrieve amount of physical memory installed on the system in KiB
+ // units.
+ LongLong GetHostMemoryTotal();
+
+ // Get total system RAM in units of KiB available colectivley to all
+ // processes in a process group. An example of a process group
+ // are the processes comprising an mpi program which is running in
+ // parallel. The amount of memory reported may differ from the host
+ // total if a host wide resource limit is applied. Such reource limits
+ // are reported to us via an applicaiton specified environment variable.
+ LongLong GetHostMemoryAvailable(const char *hostLimitEnvVarName=NULL);
+
+ // Get total system RAM in units of KiB available to this process.
+ // This may differ from the host available if a per-process resource
+ // limit is applied. per-process memory limits are applied on unix
+ // system via rlimit api. Resource limits that are not imposed via
+ // rlimit api may be reported to us via an application specified
+ // environment variable.
+ LongLong GetProcMemoryAvailable(
+ const char *hostLimitEnvVarName=NULL,
+ const char *procLimitEnvVarName=NULL);
+
+ // Get the system RAM used by all processes on the host, in units of KiB.
+ LongLong GetHostMemoryUsed();
+
+ // Get system RAM used by this process id in units of KiB.
+ LongLong GetProcMemoryUsed();
+
+ // enable/disable stack trace signal handler. In order to
+ // produce an informative stack trace the application should
+ // be dynamically linked and compiled with debug symbols.
+ static
+ void SetStackTraceOnError(int enable);
/** Run the different checks */
void RunCPUCheck();
void RunOSCheck();
void RunMemoryCheck();
-private:
- SystemInformationImplementation* Implementation;
-
};
+
} // namespace @KWSYS_NAMESPACE@
/* Undefine temporary macros. */
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 66850e9ac..8b25d608d 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -157,7 +157,7 @@ public:
#include <os/storage/Path.h>
#endif
-#if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__)
+#if defined(__BEOS__) && !defined(__ZETA__)
#include <be/kernel/OS.h>
#include <be/storage/Path.h>
@@ -196,18 +196,16 @@ inline int Rmdir(const char* dir)
}
inline const char* Getcwd(char* buf, unsigned int len)
{
- const char* ret = _getcwd(buf, len);
- if(!ret)
+ if(const char* ret = _getcwd(buf, len))
{
- fprintf(stderr, "No current working directory.\n");
- abort();
- }
- // make sure the drive letter is capital
- if(strlen(buf) > 1 && buf[1] == ':')
- {
- buf[0] = toupper(buf[0]);
+ // make sure the drive letter is capital
+ if(strlen(buf) > 1 && buf[1] == ':')
+ {
+ buf[0] = toupper(buf[0]);
+ }
+ return ret;
}
- return ret;
+ return 0;
}
inline int Chdir(const char* dir)
{
@@ -245,13 +243,7 @@ inline int Rmdir(const char* dir)
}
inline const char* Getcwd(char* buf, unsigned int len)
{
- const char* ret = getcwd(buf, len);
- if(!ret)
- {
- fprintf(stderr, "No current working directory\n");
- abort();
- }
- return ret;
+ return getcwd(buf, len);
}
inline int Chdir(const char* dir)
@@ -622,11 +614,7 @@ bool SystemTools::MakeDirectory(const char* path)
}
SystemTools::ConvertToUnixSlashes(dir);
- kwsys_stl::string::size_type pos = dir.find(':');
- if(pos == kwsys_stl::string::npos)
- {
- pos = 0;
- }
+ kwsys_stl::string::size_type pos = 0;
kwsys_stl::string topdir;
while((pos = dir.find('/', pos)) != kwsys_stl::string::npos)
{
@@ -634,14 +622,7 @@ bool SystemTools::MakeDirectory(const char* path)
Mkdir(topdir.c_str());
pos++;
}
- if(dir[dir.size()-1] == '/')
- {
- topdir = dir.substr(0, dir.size());
- }
- else
- {
- topdir = dir;
- }
+ topdir = dir;
if(Mkdir(topdir.c_str()) != 0)
{
// There is a bug in the Borland Run time library which makes MKDIR
@@ -1665,7 +1646,7 @@ kwsys_stl::string SystemTools::EscapeChars(
kwsys_stl::string n;
if (str)
{
- if (!chars_to_escape | !*chars_to_escape)
+ if (!chars_to_escape || !*chars_to_escape)
{
n.append(str);
}
@@ -2754,15 +2735,30 @@ kwsys_stl::string SystemTools::GetRealPath(const char* path)
bool SystemTools::FileIsDirectory(const char* name)
{
+ size_t length = strlen(name);
+ if (length == 0)
+ {
+ return false;
+ }
+
// Remove any trailing slash from the name.
- char buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
- size_t last = strlen(name)-1;
+ char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
+ std::string string_buffer;
+ size_t last = length-1;
if(last > 0 && (name[last] == '/' || name[last] == '\\')
&& strcmp(name, "/") !=0)
{
- memcpy(buffer, name, last);
- buffer[last] = 0;
- name = buffer;
+ if(last < sizeof(local_buffer))
+ {
+ memcpy(local_buffer, name, last);
+ local_buffer[last] = 0;
+ name = local_buffer;
+ }
+ else
+ {
+ string_buffer.append(name, last);
+ name = string_buffer.c_str();
+ }
}
// Now check the file node type.
@@ -3042,7 +3038,7 @@ void SystemTools::CheckTranslationPath(kwsys_stl::string & path)
path.erase(path.end()-1, path.end());
}
-void
+static void
SystemToolsAppendComponents(
kwsys_stl::vector<kwsys_stl::string>& out_components,
kwsys_stl::vector<kwsys_stl::string>::const_iterator first,
@@ -3094,7 +3090,7 @@ kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
}
else
{
- // ??
+ base_components.push_back("");
}
}
@@ -4048,7 +4044,7 @@ kwsys_stl::string SystemTools::GetCurrentDateTime(const char* format)
return kwsys_stl::string(buf);
}
-kwsys_stl::string SystemTools::MakeCindentifier(const char* s)
+kwsys_stl::string SystemTools::MakeCidentifier(const char* s)
{
kwsys_stl::string str(s);
if (str.find_first_of("0123456789") == 0)
@@ -4709,7 +4705,7 @@ bool SystemTools::ParseURL( const kwsys_stl::string& URL,
// ----------------------------------------------------------------------
// These must NOT be initialized. Default initialization to zero is
// necessary.
-unsigned int SystemToolsManagerCount;
+static unsigned int SystemToolsManagerCount;
SystemToolsTranslationMap *SystemTools::TranslationMap;
SystemToolsTranslationMap *SystemTools::LongPathMap;
#ifdef __CYGWIN__
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 5171125ce..9c56e96b0 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -91,8 +91,13 @@ public:
* then an underscore is prepended. Note that this can produce
* identifiers that the standard reserves (_[A-Z].* and __.*).
*/
- static kwsys_stl::string MakeCindentifier(const char* s);
-
+ static kwsys_stl::string MakeCidentifier(const char* s);
+
+ static kwsys_stl::string MakeCindentifier(const char* s)
+ {
+ return MakeCidentifier(s);
+ }
+
/**
* Replace replace all occurences of the string in the source string.
*/
diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx
index 7b73d06df..48976c442 100644
--- a/Source/kwsys/kwsysPlatformTestsCXX.cxx
+++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx
@@ -358,6 +358,30 @@ int main()
}
#endif
+#ifdef TEST_KWSYS_IOS_HAS_ISTREAM___INT64
+int test_istream(kwsys_ios::istream& is, __int64& x)
+{
+ return (is >> x)? 1:0;
+}
+int main()
+{
+ __int64 x = 0;
+ return test_istream(kwsys_ios::cin, x);
+}
+#endif
+
+#ifdef TEST_KWSYS_IOS_HAS_OSTREAM___INT64
+int test_ostream(kwsys_ios::ostream& os, __int64 x)
+{
+ return (os << x)? 1:0;
+}
+int main()
+{
+ __int64 x = 0;
+ return test_ostream(kwsys_ios::cout, x);
+}
+#endif
+
#ifdef TEST_KWSYS_CHAR_IS_SIGNED
/* Return 0 for char signed and 1 for char unsigned. */
int main()
@@ -428,6 +452,48 @@ int main()
}
#endif
+#ifdef TEST_KWSYS_CXX_HAS_RLIMIT64
+# if defined(KWSYS_HAS_LFS)
+# define _LARGEFILE_SOURCE
+# define _LARGEFILE64_SOURCE
+# define _LARGE_FILES
+# define _FILE_OFFSET_BITS 64
+# endif
+# include <sys/resource.h>
+int main()
+{
+ struct rlimit64 rlim;
+ return getrlimit64(0,&rlim);
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_ATOLL
+#include <stdlib.h>
+int main()
+{
+ const char *str="1024";
+ return static_cast<int>(atoll(str));
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_ATOL
+#include <stdlib.h>
+int main()
+{
+ const char *str="1024";
+ return static_cast<int>(atol(str));
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS__ATOI64
+#include <stdlib.h>
+int main()
+{
+ const char *str="1024";
+ return static_cast<int>(_atoi64(str));
+}
+#endif
+
#ifdef TEST_KWSYS_CXX_TYPE_INFO
/* Collect fundamental type information and save it to a CMake script. */
@@ -514,3 +580,30 @@ int main()
}
}
#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_BORLAND_ASM
+int main()
+{
+ int a = 1;
+ __asm {
+ xor EBX, EBX;
+ mov a, EBX;
+ }
+
+ return a;
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_BORLAND_ASM_CPUID
+int main()
+{
+ int a = 0;
+ __asm {
+ xor EAX, EAX;
+ cpuid;
+ mov a, EAX;
+ }
+
+ return a;
+}
+#endif
diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx
index e75a87e86..72e65447b 100644
--- a/Source/kwsys/testCommandLineArguments.cxx
+++ b/Source/kwsys/testCommandLineArguments.cxx
@@ -24,9 +24,9 @@
#include <stddef.h> /* size_t */
#include <string.h> /* strcmp */
-void* random_ptr = reinterpret_cast<void*>(0x123);
+static void* random_ptr = reinterpret_cast<void*>(0x123);
-int argument(const char* arg, const char* value, void* call_data)
+static int argument(const char* arg, const char* value, void* call_data)
{
kwsys_ios::cout << "Got argument: \"" << arg << "\" value: \"" << (value?value:"(null)") << "\"" << kwsys_ios::endl;
if ( call_data != random_ptr )
@@ -37,7 +37,7 @@ int argument(const char* arg, const char* value, void* call_data)
return 1;
}
-int unknown_argument(const char* argument, void* call_data)
+static int unknown_argument(const char* argument, void* call_data)
{
kwsys_ios::cout << "Got unknown argument: \"" << argument << "\"" << kwsys_ios::endl;
if ( call_data != random_ptr )
@@ -48,12 +48,12 @@ int unknown_argument(const char* argument, void* call_data)
return 1;
}
-bool CompareTwoItemsOnList(bool i1, bool i2) { return i1 == i2; }
-bool CompareTwoItemsOnList(int i1, int i2) { return i1 == i2; }
-bool CompareTwoItemsOnList(double i1, double i2) { return i1 == i2; }
-bool CompareTwoItemsOnList(const char* i1,
+static bool CompareTwoItemsOnList(bool i1, bool i2) { return i1 == i2; }
+static bool CompareTwoItemsOnList(int i1, int i2) { return i1 == i2; }
+static bool CompareTwoItemsOnList(double i1, double i2) { return i1 == i2; }
+static bool CompareTwoItemsOnList(const char* i1,
const char* i2) { return strcmp(i1, i2) == 0; }
-bool CompareTwoItemsOnList(const kwsys_stl::string& i1,
+static bool CompareTwoItemsOnList(const kwsys_stl::string& i1,
const kwsys_stl::string& i2) { return i1 == i2; }
int testCommandLineArguments(int argc, char* argv[])
diff --git a/Source/kwsys/testDynamicLoader.cxx b/Source/kwsys/testDynamicLoader.cxx
index a7adbcad9..61c157291 100644
--- a/Source/kwsys/testDynamicLoader.cxx
+++ b/Source/kwsys/testDynamicLoader.cxx
@@ -15,7 +15,7 @@
#include KWSYS_HEADER(ios/iostream)
#include KWSYS_HEADER(stl/string)
-#if defined(__BEOS__) && !defined(__HAIKU__)
+#if defined(__BEOS__)
#include <be/kernel/OS.h> /* disable_debugger() API. */
#endif
@@ -35,7 +35,7 @@
// left on disk.
#include <testSystemTools.h>
-kwsys_stl::string GetLibName(const char* lname)
+static kwsys_stl::string GetLibName(const char* lname)
{
// Construct proper name of lib
kwsys_stl::string slname;
diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c
index 877002a14..6d5eb71fd 100644
--- a/Source/kwsys/testProcess.c
+++ b/Source/kwsys/testProcess.c
@@ -32,7 +32,7 @@
# pragma warn -8060 /* possibly incorrect assignment */
#endif
-#if defined(__BEOS__) && !defined(__ZETA__) && !defined(__HAIKU__)
+#if defined(__BEOS__) && !defined(__ZETA__)
/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
# include <be/kernel/OS.h>
static inline void testProcess_usleep(unsigned int msec)
@@ -47,7 +47,7 @@ int runChild(const char* cmd[], int state, int exception, int value,
int share, int output, int delay, double timeout, int poll,
int repeat, int disown);
-int test1(int argc, const char* argv[])
+static int test1(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output on stdout from test returning 0.\n");
@@ -55,7 +55,7 @@ int test1(int argc, const char* argv[])
return 0;
}
-int test2(int argc, const char* argv[])
+static int test2(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output on stdout from test returning 123.\n");
@@ -63,7 +63,7 @@ int test2(int argc, const char* argv[])
return 123;
}
-int test3(int argc, const char* argv[])
+static int test3(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output before sleep on stdout from timeout test.\n");
@@ -80,8 +80,16 @@ int test3(int argc, const char* argv[])
return 0;
}
-int test4(int argc, const char* argv[])
+static int test4(int argc, const char* argv[])
{
+ /* Prepare a pointer to an invalid address. Don't use null, because
+ dereferencing null is undefined behaviour and compilers are free to
+ do whatever they want. ex: Clang will warn at compile time, or even
+ optimize away the write. We hope to 'outsmart' them by using
+ 'volatile' and a slightly larger address, based on a runtime value. */
+ volatile int* invalidAddress = 0;
+ invalidAddress += argc?1:2;
+
#if defined(_WIN32)
/* Avoid error diagnostic popups since we are crashing on purpose. */
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
@@ -94,17 +102,14 @@ int test4(int argc, const char* argv[])
fprintf(stderr, "Output before crash on stderr from crash test.\n");
fflush(stdout);
fflush(stderr);
-#if defined(__clang__)
- *(int*)1 = 0; /* Clang warns about 0-ptr; undefined behavior. */
-#else
- *(int*)0 = 0;
-#endif
+ /* Provoke deliberate crash by writing to the invalid address. */
+ *invalidAddress = 0;
fprintf(stdout, "Output after crash on stdout from crash test.\n");
fprintf(stderr, "Output after crash on stderr from crash test.\n");
return 0;
}
-int test5(int argc, const char* argv[])
+static int test5(int argc, const char* argv[])
{
int r;
const char* cmd[4];
@@ -127,7 +132,7 @@ int test5(int argc, const char* argv[])
}
#define TEST6_SIZE (4096*2)
-void test6(int argc, const char* argv[])
+static void test6(int argc, const char* argv[])
{
int i;
char runaway[TEST6_SIZE+1];
@@ -151,7 +156,7 @@ void test6(int argc, const char* argv[])
delaying 1/10th of a second should ever have to poll. */
#define MINPOLL 5
#define MAXPOLL 20
-int test7(int argc, const char* argv[])
+static int test7(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output on stdout before sleep.\n");
@@ -171,7 +176,7 @@ int test7(int argc, const char* argv[])
return 0;
}
-int test8(int argc, const char* argv[])
+static int test8(int argc, const char* argv[])
{
/* Create a disowned grandchild to test handling of processes
that exit before their children. */
@@ -195,7 +200,7 @@ int test8(int argc, const char* argv[])
return r;
}
-int test8_grandchild(int argc, const char* argv[])
+static int test8_grandchild(int argc, const char* argv[])
{
(void)argc; (void)argv;
fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
@@ -216,7 +221,7 @@ int test8_grandchild(int argc, const char* argv[])
return 0;
}
-int runChild2(kwsysProcess* kp,
+static int runChild2(kwsysProcess* kp,
const char* cmd[], int state, int exception, int value,
int share, int output, int delay, double timeout,
int poll, int disown)
@@ -500,7 +505,7 @@ int main(int argc, const char* argv[])
fprintf(stderr, "Output on stderr after test %d.\n", n);
fflush(stdout);
fflush(stderr);
-#if _WIN32
+#if defined(_WIN32)
if(argv0) { free(argv0); }
#endif
return r;
diff --git a/Source/kwsys/testRegistry.cxx b/Source/kwsys/testRegistry.cxx
deleted file mode 100644
index 7e9b0d49b..000000000
--- a/Source/kwsys/testRegistry.cxx
+++ /dev/null
@@ -1,109 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- 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 "kwsysPrivate.h"
-
-#include KWSYS_HEADER(Registry.hxx)
-#include KWSYS_HEADER(ios/iostream)
-#include <string.h>
-
-// Work-around CMake dependency scanning limitation. This must
-// duplicate the above list of headers.
-#if 0
-# include "Registry.hxx.in"
-# include "kwsys_ios_iostream.h.in"
-#endif
-
-#define IFT(x,res) if ( !x ) \
- { \
- res = 1; \
- kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \
- }
-#define IFNT(x,res) if ( x ) \
- { \
- res = 1; \
- kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \
- }
-
-#define CHE(x,y,res) if ( x && strcmp(x,y) ) \
- { \
- res = 1; \
- kwsys_ios::cout << "Error, " << x << " != " << y << kwsys_ios::endl; \
- }
-
-int testRegistry(int, char*[])
-{
- int res = 0;
-
- kwsys::Registry reg;
- reg.SetTopLevel("TestRegistry");
-
- IFT(reg.SetValue("TestSubkey", "TestKey1", "Test Value 1"), res);
- IFT(reg.SetValue("TestSubkey1", "TestKey2", "Test Value 2"), res);
- IFT(reg.SetValue("TestSubkey", "TestKey3", "Test Value 3"), res);
- IFT(reg.SetValue("TestSubkey2", "TestKey4", "Test Value 4"), res);
-
- const char *buffer;
- IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res);
- CHE(buffer, "Test Value 1", res);
- IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res);
- CHE(buffer, "Test Value 2", res);
- IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res);
- CHE(buffer, "Test Value 3", res);
- IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res);
- CHE(buffer, "Test Value 4", res);
-
- IFT(reg.SetValue("TestSubkey", "TestKey1", "New Test Value 1"), res);
- IFT(reg.SetValue("TestSubkey1", "TestKey2", "New Test Value 2"), res);
- IFT(reg.SetValue("TestSubkey", "TestKey3", "New Test Value 3"), res);
- IFT(reg.SetValue("TestSubkey2", "TestKey4", "New Test Value 4"), res);
-
- IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res);
- CHE(buffer, "New Test Value 1", res);
- IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res);
- CHE(buffer, "New Test Value 2", res);
- IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res);
- CHE(buffer, "New Test Value 3", res);
- IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res);
- CHE(buffer, "New Test Value 4", res);
-
- IFT( reg.DeleteValue("TestSubkey", "TestKey1"), res);
- IFNT(reg.ReadValue( "TestSubkey", "TestKey1", &buffer), res);
- IFT( reg.DeleteValue("TestSubkey1", "TestKey2"), res);
- IFNT(reg.ReadValue( "TestSubkey1", "TestKey2", &buffer), res);
- IFT( reg.DeleteValue("TestSubkey", "TestKey3"), res);
- IFNT(reg.ReadValue( "TestSubkey", "TestKey3", &buffer), res);
- IFT( reg.DeleteValue("TestSubkey2", "TestKey4"), res);
- IFNT(reg.ReadValue( "TestSubkey2", "TestKey5", &buffer), res);
-
- const char* longStringWithNewLines = "Value with embedded CR and LF characters CR='\015' LF='\012' CRLF='\015\012'";
- IFT(reg.SetValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", longStringWithNewLines), res);
- IFT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res);
- CHE(buffer, longStringWithNewLines, res);
- IFT(reg.DeleteValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1"), res);
- IFNT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res);
-
- IFT(reg.SetValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", "Some value"), res);
- IFT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res);
- CHE(buffer, "Some value", res);
- IFT(reg.DeleteValue("TestSubkeyWith = EqualSignChar", "TestKey = 1"), res);
- IFNT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res);
-
- if ( res )
- {
- kwsys_ios::cout << "Test failed" << kwsys_ios::endl;
- }
- else
- {
- kwsys_ios::cout << "Test passed" << kwsys_ios::endl;
- }
- return res;
-}
diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx
index b3afc9de9..49a686c17 100644
--- a/Source/kwsys/testSystemInformation.cxx
+++ b/Source/kwsys/testSystemInformation.cxx
@@ -13,8 +13,6 @@
#include KWSYS_HEADER(SystemInformation.hxx)
#include KWSYS_HEADER(ios/iostream)
-
-
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
@@ -22,20 +20,45 @@
# include "kwsys_ios_iostream.h.in"
#endif
-#define printMethod(inof, m) kwsys_ios::cout << #m << ": " \
+#if defined(KWSYS_USE_LONG_LONG)
+# if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)x)
+# endif
+#elif defined(KWSYS_USE___INT64)
+# if defined(KWSYS_IOS_HAS_OSTREAM___INT64)
+# define iostreamLongLong(x) (x)
+# else
+# define iostreamLongLong(x) ((long)x)
+# endif
+#else
+# error "No Long Long"
+#endif
+
+#define printMethod(info, m) kwsys_ios::cout << #m << ": " \
<< info.m() << "\n"
-#define printMethod2(inof, m, unit) kwsys_ios::cout << #m << ": " \
+#define printMethod2(info, m, unit) kwsys_ios::cout << #m << ": " \
<< info.m() << " " << unit << "\n"
+#define printMethod3(info, m, unit) kwsys_ios::cout << #m << ": " \
+<< iostreamLongLong(info.m) << " " << unit << "\n"
+
int testSystemInformation(int, char*[])
{
+ kwsys_ios::cout << "CTEST_FULL_OUTPUT\n"; // avoid truncation
+
kwsys::SystemInformation info;
info.RunCPUCheck();
info.RunOSCheck();
info.RunMemoryCheck();
printMethod(info, GetOSName);
+ printMethod(info, GetOSIsLinux);
+ printMethod(info, GetOSIsApple);
+ printMethod(info, GetOSIsWindows);
printMethod(info, GetHostname);
+ printMethod(info, GetFullyQualifiedDomainName);
printMethod(info, GetOSRelease);
printMethod(info, GetOSVersion);
printMethod(info, GetOSPlatform);
@@ -45,6 +68,7 @@ int testSystemInformation(int, char*[])
printMethod(info, GetFamilyID);
printMethod(info, GetModelID);
printMethod(info, GetExtendedProcessorName);
+ printMethod(info, GetSteppingCode);
printMethod(info, GetProcessorSerialNumber);
printMethod2(info, GetProcessorCacheSize, "KB");
printMethod(info, GetLogicalProcessorsPerPhysical);
@@ -58,7 +82,19 @@ int testSystemInformation(int, char*[])
printMethod2(info, GetAvailableVirtualMemory, "MB");
printMethod2(info, GetTotalPhysicalMemory, "MB");
printMethod2(info, GetAvailablePhysicalMemory, "MB");
+ printMethod3(info, GetHostMemoryTotal(), "KiB");
+ printMethod3(info, GetHostMemoryAvailable("KWSHL"), "KiB");
+ printMethod3(info, GetProcMemoryAvailable("KWSHL","KWSPL"), "KiB");
+ printMethod3(info, GetHostMemoryUsed(), "KiB");
+ printMethod3(info, GetProcMemoryUsed(), "KiB");
+ for (int i = 0; i <= 31; i++)
+ {
+ if (info.DoesCPUSupportFeature(1 << i))
+ {
+ kwsys_ios::cout << "CPU feature " << i << "\n";
+ }
+ }
//int GetProcessorCacheXSize(long int);
// bool DoesCPUSupportFeature(long int);
return 0;
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index 3ac0cb399..1690fd51a 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -32,7 +32,7 @@
#include <string.h> /* strcmp */
//----------------------------------------------------------------------------
-const char* toUnixPaths[][2] =
+static const char* toUnixPaths[][2] =
{
{ "/usr/local/bin/passwd", "/usr/local/bin/passwd" },
{ "/usr/lo cal/bin/pa sswd", "/usr/lo cal/bin/pa sswd" },
@@ -52,8 +52,8 @@ const char* toUnixPaths[][2] =
{0, 0}
};
-bool CheckConvertToUnixSlashes(kwsys_stl::string input,
- kwsys_stl::string output)
+static bool CheckConvertToUnixSlashes(kwsys_stl::string input,
+ kwsys_stl::string output)
{
kwsys_stl::string result = input;
kwsys::SystemTools::ConvertToUnixSlashes(result);
@@ -69,17 +69,17 @@ bool CheckConvertToUnixSlashes(kwsys_stl::string input,
}
//----------------------------------------------------------------------------
-const char* checkEscapeChars[][4] =
+static const char* checkEscapeChars[][4] =
{
{ "1 foo 2 bar 2", "12", "\\", "\\1 foo \\2 bar \\2"},
{ " {} ", "{}", "#", " #{#} "},
{0, 0, 0, 0}
};
-bool CheckEscapeChars(kwsys_stl::string input,
- const char *chars_to_escape,
- char escape_char,
- kwsys_stl::string output)
+static bool CheckEscapeChars(kwsys_stl::string input,
+ const char *chars_to_escape,
+ char escape_char,
+ kwsys_stl::string output)
{
kwsys_stl::string result = kwsys::SystemTools::EscapeChars(
input.c_str(), chars_to_escape, escape_char);
@@ -95,7 +95,7 @@ bool CheckEscapeChars(kwsys_stl::string input,
}
//----------------------------------------------------------------------------
-bool CheckFileOperations()
+static bool CheckFileOperations()
{
bool res = true;
@@ -129,7 +129,7 @@ bool CheckFileOperations()
}
//----------------------------------------------------------------------------
-bool CheckStringOperations()
+static bool CheckStringOperations()
{
bool res = true;
@@ -329,7 +329,7 @@ bool CheckStringOperations()
//----------------------------------------------------------------------------
-bool CheckPutEnv(const char* env, const char* name, const char* value)
+static bool CheckPutEnv(const char* env, const char* name, const char* value)
{
if(!kwsys::SystemTools::PutEnv(env))
{
@@ -348,7 +348,7 @@ bool CheckPutEnv(const char* env, const char* name, const char* value)
return true;
}
-bool CheckUnPutEnv(const char* env, const char* name)
+static bool CheckUnPutEnv(const char* env, const char* name)
{
if(!kwsys::SystemTools::UnPutEnv(env))
{
@@ -365,7 +365,7 @@ bool CheckUnPutEnv(const char* env, const char* name)
return true;
}
-bool CheckEnvironmentOperations()
+static bool CheckEnvironmentOperations()
{
bool res = true;
res &= CheckPutEnv("A=B", "A", "B");