summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt19
-rw-r--r--CTestCustom.cmake.in3
-rw-r--r--ChangeLog.manual592
-rw-r--r--Modules/AutomocInfo.cmake.in14
-rw-r--r--Modules/BasicConfigVersion-ExactVersion.cmake.in42
-rw-r--r--Modules/CMakeFindEclipseCDT4.cmake4
-rw-r--r--Modules/CMakeGenericSystem.cmake3
-rw-r--r--Modules/CMakeNinjaFindMake.cmake17
-rw-r--r--Modules/CMakePackageConfigHelpers.cmake227
-rw-r--r--Modules/CPack.cmake14
-rw-r--r--Modules/CPackNSIS.cmake26
-rw-r--r--Modules/CPackRPM.cmake1
-rw-r--r--Modules/CTestTargets.cmake4
-rw-r--r--Modules/CheckIncludeFiles.cmake18
-rw-r--r--Modules/Compiler/GNU.cmake12
-rw-r--r--Modules/DeployQt4.cmake78
-rw-r--r--Modules/ExternalProject.cmake19
-rw-r--r--Modules/FindBoost.cmake5
-rw-r--r--Modules/FindCxxTest.cmake6
-rw-r--r--Modules/FindMPI.cmake14
-rw-r--r--Modules/FindPackageHandleStandardArgs.cmake42
-rw-r--r--Modules/FindQt3.cmake91
-rw-r--r--Modules/Platform/Darwin.cmake53
-rw-r--r--Modules/Platform/Windows-cl.cmake4
-rw-r--r--Modules/Platform/eCos.cmake9
-rw-r--r--Modules/WriteBasicConfigVersionFile.cmake27
-rw-r--r--Modules/readme.txt30
-rw-r--r--Source/CMakeLists.txt32
-rwxr-xr-xSource/CMakeVersion.bash7
-rw-r--r--Source/CMakeVersion.cmake6
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx2
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx2
-rw-r--r--Source/CPack/cmCPackDocumentVariables.cxx8
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx10
-rw-r--r--Source/CPack/cmCPackGenerator.cxx6
-rw-r--r--Source/CPack/cmCPackGenerator.h14
-rw-r--r--Source/CPack/cmCPackOSXX11Generator.cxx8
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.cxx93
-rw-r--r--Source/CPack/cmCPackRPMGenerator.cxx2
-rw-r--r--Source/CPack/cmCPackSTGZGenerator.cxx25
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx1
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx2
-rw-r--r--Source/cmAddLibraryCommand.cxx14
-rw-r--r--Source/cmAddLibraryCommand.h20
-rw-r--r--Source/cmCacheManager.cxx11
-rw-r--r--Source/cmCommandArgumentParserHelper.h1
-rw-r--r--Source/cmComputeLinkDepends.cxx13
-rw-r--r--Source/cmComputeLinkInformation.cxx1
-rw-r--r--Source/cmDepends.cxx19
-rw-r--r--Source/cmDocumentVariables.cxx34
-rw-r--r--Source/cmExportCommand.cxx8
-rw-r--r--Source/cmExprParserHelper.cxx6
-rw-r--r--Source/cmExprParserHelper.h3
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx11
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx12
-rw-r--r--Source/cmFileCommand.h3
-rw-r--r--Source/cmFindLibraryCommand.cxx8
-rw-r--r--Source/cmFindPackageCommand.cxx101
-rw-r--r--Source/cmGeneratorTarget.cxx184
-rw-r--r--Source/cmGeneratorTarget.h64
-rw-r--r--Source/cmGlobalGenerator.cxx96
-rw-r--r--Source/cmGlobalGenerator.h13
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx822
-rw-r--r--Source/cmGlobalNinjaGenerator.h338
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx38
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h2
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio6Generator.h2
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h2
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx80
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h2
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx388
-rw-r--r--Source/cmGlobalXCodeGenerator.h18
-rw-r--r--Source/cmIncludeDirectoryCommand.h22
-rw-r--r--Source/cmInstallCommand.cxx11
-rw-r--r--Source/cmInstallTargetGenerator.cxx1
-rw-r--r--Source/cmLocalGenerator.cxx79
-rw-r--r--Source/cmLocalGenerator.h16
-rw-r--r--Source/cmLocalNinjaGenerator.cxx393
-rw-r--r--Source/cmLocalNinjaGenerator.h133
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx87
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h52
-rw-r--r--Source/cmLocalVisualStudio10Generator.cxx18
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx288
-rw-r--r--Source/cmLocalVisualStudio6Generator.h9
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx185
-rw-r--r--Source/cmLocalVisualStudio7Generator.h10
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx90
-rw-r--r--Source/cmLocalVisualStudioGenerator.h14
-rw-r--r--Source/cmLocalXCodeGenerator.cxx13
-rw-r--r--Source/cmLocalXCodeGenerator.h3
-rw-r--r--Source/cmMakeDepend.cxx35
-rw-r--r--Source/cmMakefile.cxx185
-rw-r--r--Source/cmMakefile.h28
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx26
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.h1
-rw-r--r--Source/cmMakefileTargetGenerator.cxx184
-rw-r--r--Source/cmMakefileTargetGenerator.h8
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx500
-rw-r--r--Source/cmNinjaNormalTargetGenerator.h48
-rw-r--r--Source/cmNinjaTargetGenerator.cxx536
-rw-r--r--Source/cmNinjaTargetGenerator.h126
-rw-r--r--Source/cmNinjaTypes.h19
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx116
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.h30
-rw-r--r--Source/cmQtAutomoc.cxx29
-rw-r--r--Source/cmSourceFile.h3
-rw-r--r--Source/cmSourceGroup.cxx6
-rw-r--r--Source/cmSourceGroup.h1
-rw-r--r--Source/cmSystemTools.cxx14
-rw-r--r--Source/cmSystemTools.h5
-rw-r--r--Source/cmTarget.cxx180
-rw-r--r--Source/cmTarget.h16
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx10
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx265
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h9
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx14
-rw-r--r--Source/cmVisualStudioGeneratorOptions.h1
-rw-r--r--Source/cmake.cxx18
-rw-r--r--Source/cmake.h10
-rw-r--r--Source/kwsys/kwsysDateStamp.cmake4
-rw-r--r--Tests/BuildDepends/CMakeLists.txt2
-rw-r--r--Tests/CMakeCommands/CMakeLists.txt11
-rw-r--r--Tests/CMakeCommands/build_command/test.cmake86
-rw-r--r--Tests/CMakeCommands/find_package/CMakeLists.txt3
-rw-r--r--Tests/CMakeCommands/find_package/MissingConfig.cmake1
-rw-r--r--Tests/CMakeCommands/find_package/MissingConfigRequired.cmake1
-rw-r--r--Tests/CMakeCommands/find_package/MissingModule.cmake1
-rw-r--r--Tests/CMakeCommands/find_package/MissingModuleRequired.cmake1
-rw-r--r--Tests/CMakeCommands/find_package/MissingNormal.cmake1
-rw-r--r--Tests/CMakeCommands/find_package/MissingNormalRequired.cmake1
-rw-r--r--Tests/CMakeLists.txt113
-rw-r--r--Tests/CMakeOnly/AllFindModules/CMakeLists.txt18
-rw-r--r--Tests/CMakeTests/CMakeLists.txt6
-rw-r--r--Tests/CMakeTests/CheckSourceTreeTest.cmake.in87
-rw-r--r--Tests/CMakeTests/GetProperty-Bad-Argument.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-Bad-Directory.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-Bad-Scope.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-Bad-Target.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-Bad-Test.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-Doc-Properties.cmake10
-rw-r--r--Tests/CMakeTests/GetProperty-Global-Name.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-Missing-Argument.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-No-Cache.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-No-Property.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-No-Source.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-No-Target.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-No-Test.cmake1
-rw-r--r--Tests/CMakeTests/GetProperty-Variable-Name.cmake1
-rw-r--r--Tests/CMakeTests/GetPropertyTest.cmake.in98
-rw-r--r--Tests/CTestUpdateCVS.cmake.in13
-rw-r--r--Tests/CTestUpdateHG.cmake.in5
-rw-r--r--Tests/ExternalOBJ/CMakeLists.txt2
-rw-r--r--Tests/ExternalOBJ/Sub/CMakeLists.txt3
-rw-r--r--Tests/ExternalProject/CMakeLists.txt12
-rw-r--r--Tests/FindPackageTest/CMakeLists.txt135
-rw-r--r--Tests/FindPackageTest/FindLotsOfComponents.cmake10
-rw-r--r--Tests/FindPackageTest/RelocatableConfig.cmake.in11
-rw-r--r--Tests/FindPackageTest/cmake/SetFoundFALSEConfig.cmake1
-rw-r--r--Tests/FindPackageTest/cmake/SetFoundTRUEConfig.cmake1
-rw-r--r--Tests/IncludeDirectories/CMakeLists.txt2
-rw-r--r--Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt26
-rw-r--r--Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp10
-rw-r--r--Tests/ModuleDefinition/CMakeLists.txt10
-rw-r--r--Tests/ModuleDefinition/example_dll_gen.c1
-rw-r--r--Tests/ModuleDefinition/example_dll_gen.def.in2
-rw-r--r--Tests/ModuleDefinition/example_exe.c2
-rw-r--r--Tests/ObjectLibrary/A/CMakeLists.txt17
-rw-r--r--Tests/ObjectLibrary/A/a.h6
-rw-r--r--Tests/ObjectLibrary/A/a1.c.in2
-rw-r--r--Tests/ObjectLibrary/A/a2.c2
-rw-r--r--Tests/ObjectLibrary/AB.def5
-rw-r--r--Tests/ObjectLibrary/B/CMakeLists.txt15
-rw-r--r--Tests/ObjectLibrary/B/b.h11
-rw-r--r--Tests/ObjectLibrary/B/b1.c2
-rw-r--r--Tests/ObjectLibrary/B/b1_vs6.c1
-rw-r--r--Tests/ObjectLibrary/B/b2.c2
-rw-r--r--Tests/ObjectLibrary/B/b2_vs6.c1
-rw-r--r--Tests/ObjectLibrary/CMakeLists.txt52
-rw-r--r--Tests/ObjectLibrary/c.c19
-rw-r--r--Tests/ObjectLibrary/dummy.c1
-rw-r--r--Tests/ObjectLibrary/dummy.objbin0 -> 498 bytes
-rw-r--r--Tests/ObjectLibrary/main.c16
-rw-r--r--Tests/ObjectLibrary/mainAB.c22
-rw-r--r--Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt6
-rw-r--r--Tests/PrecompiledHeader/CMakeLists.txt3
-rw-r--r--Tests/Qt4Deploy/CMakeLists.txt70
-rw-r--r--Tests/Qt4Deploy/testdeploy.cpp29
-rw-r--r--Tests/QtAutomoc/CMakeLists.txt2
-rw-r--r--Tests/README13
-rw-r--r--Tests/RunCMake/CMakeLists.txt46
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource1-result.txt (renamed from Tests/CMakeCommands/find_package/MixedModeOptions-result.txt)0
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource1-stderr.txt8
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource1.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt (renamed from Tests/CMakeCommands/find_package/MissingNormalRequired-result.txt)0
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt8
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource2.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression1-result.txt (renamed from Tests/CMakeCommands/find_package/MissingModuleRequired-result.txt)0
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt6
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression1.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression2-result.txt (renamed from Tests/CMakeCommands/find_package/MissingConfigRequired-result.txt)0
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression2.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression3-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadSourceExpression3.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/ObjectLibrary/Export-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/Export-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/Export.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/ExportLanguages.cmake15
-rw-r--r--Tests/RunCMake/ObjectLibrary/Import-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/Import-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/Import.cmake1
-rw-r--r--Tests/RunCMake/ObjectLibrary/Install-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/Install-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/Install.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt6
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake3
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt6
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake3
-rw-r--r--Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/ObjWithObj.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/PostBuild-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/PostBuild-stderr.txt5
-rw-r--r--Tests/RunCMake/ObjectLibrary/PostBuild.cmake4
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreBuild-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreBuild-stderr.txt5
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreBuild.cmake4
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreLink-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreLink-stderr.txt5
-rw-r--r--Tests/RunCMake/ObjectLibrary/PreLink.cmake4
-rw-r--r--Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake18
-rw-r--r--Tests/RunCMake/ObjectLibrary/a.c1
-rw-r--r--Tests/RunCMake/ObjectLibrary/a.cxx1
-rw-r--r--Tests/RunCMake/ObjectLibrary/bad.def0
-rw-r--r--Tests/RunCMake/ObjectLibrary/bad.obj0
-rw-r--r--Tests/RunCMake/RunCMake.cmake (renamed from Tests/CMakeCommands/find_package/test.cmake)39
-rw-r--r--Tests/RunCMake/build_command/CMakeLists.txt (renamed from Tests/CMakeCommands/build_command/CMakeLists.txt)7
-rw-r--r--Tests/RunCMake/build_command/ErrorsOFF-stderr.txt1
-rw-r--r--Tests/RunCMake/build_command/ErrorsOFF-stdout.txt1
-rw-r--r--Tests/RunCMake/build_command/ErrorsOFF.cmake1
-rw-r--r--Tests/RunCMake/build_command/ErrorsON-result.txt1
-rw-r--r--Tests/RunCMake/build_command/ErrorsON-stderr.txt12
-rw-r--r--Tests/RunCMake/build_command/ErrorsON-stdout.txt1
-rw-r--r--Tests/RunCMake/build_command/ErrorsON.cmake1
-rw-r--r--Tests/RunCMake/build_command/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/find_package/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/find_package/ComponentRequiredAndOptional-result.txt1
-rw-r--r--Tests/RunCMake/find_package/ComponentRequiredAndOptional-stderr.txt8
-rw-r--r--Tests/RunCMake/find_package/ComponentRequiredAndOptional.cmake1
-rw-r--r--Tests/RunCMake/find_package/MissingConfig-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingConfig-stderr.txt)6
-rw-r--r--Tests/RunCMake/find_package/MissingConfig.cmake2
-rw-r--r--Tests/RunCMake/find_package/MissingConfigOneName-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingConfigOneName-stderr.txt)0
-rw-r--r--Tests/RunCMake/find_package/MissingConfigOneName.cmake (renamed from Tests/CMakeCommands/find_package/MissingConfigOneName.cmake)0
-rw-r--r--Tests/RunCMake/find_package/MissingConfigRequired-result.txt1
-rw-r--r--Tests/RunCMake/find_package/MissingConfigRequired-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingConfigRequired-stderr.txt)2
-rw-r--r--Tests/RunCMake/find_package/MissingConfigRequired.cmake2
-rw-r--r--Tests/RunCMake/find_package/MissingConfigVersion-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingConfigVersion-stderr.txt)0
-rw-r--r--Tests/RunCMake/find_package/MissingConfigVersion.cmake (renamed from Tests/CMakeCommands/find_package/MissingConfigVersion.cmake)0
-rw-r--r--Tests/RunCMake/find_package/MissingModule-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingModule-stderr.txt)5
-rw-r--r--Tests/RunCMake/find_package/MissingModule.cmake2
-rw-r--r--Tests/RunCMake/find_package/MissingModuleRequired-result.txt1
-rw-r--r--Tests/RunCMake/find_package/MissingModuleRequired-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingModuleRequired-stderr.txt)2
-rw-r--r--Tests/RunCMake/find_package/MissingModuleRequired.cmake2
-rw-r--r--Tests/RunCMake/find_package/MissingNormal-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingNormal-stderr.txt)6
-rw-r--r--Tests/RunCMake/find_package/MissingNormal.cmake2
-rw-r--r--Tests/RunCMake/find_package/MissingNormalRequired-result.txt1
-rw-r--r--Tests/RunCMake/find_package/MissingNormalRequired-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingNormalRequired-stderr.txt)2
-rw-r--r--Tests/RunCMake/find_package/MissingNormalRequired.cmake2
-rw-r--r--Tests/RunCMake/find_package/MissingNormalVersion-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingNormalVersion-stderr.txt)0
-rw-r--r--Tests/RunCMake/find_package/MissingNormalVersion.cmake (renamed from Tests/CMakeCommands/find_package/MissingNormalVersion.cmake)0
-rw-r--r--Tests/RunCMake/find_package/MissingNormalWarnNoModuleNew-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleNew-stderr.txt)0
-rw-r--r--Tests/RunCMake/find_package/MissingNormalWarnNoModuleNew.cmake (renamed from Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleNew.cmake)0
-rw-r--r--Tests/RunCMake/find_package/MissingNormalWarnNoModuleOld-stderr.txt (renamed from Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleOld-stderr.txt)0
-rw-r--r--Tests/RunCMake/find_package/MissingNormalWarnNoModuleOld.cmake (renamed from Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleOld.cmake)0
-rw-r--r--Tests/RunCMake/find_package/MixedModeOptions-result.txt1
-rw-r--r--Tests/RunCMake/find_package/MixedModeOptions-stderr.txt (renamed from Tests/CMakeCommands/find_package/MixedModeOptions-stderr.txt)0
-rw-r--r--Tests/RunCMake/find_package/MixedModeOptions.cmake (renamed from Tests/CMakeCommands/find_package/MixedModeOptions.cmake)0
-rw-r--r--Tests/RunCMake/find_package/RunCMakeTest.cmake16
-rw-r--r--Tests/RunCMake/find_package/SetFoundFALSE-stderr.txt9
-rw-r--r--Tests/RunCMake/find_package/SetFoundFALSE.cmake2
-rw-r--r--Tests/RunCMake/find_package/SetFoundFALSEConfig.cmake1
-rw-r--r--Tests/SBCS/CMakeLists.txt6
-rw-r--r--Tests/SBCS/SBCS.cxx22
-rw-r--r--Utilities/.gitattributes2
-rw-r--r--Utilities/GitSetup/.gitattributes7
-rw-r--r--Utilities/GitSetup/LICENSE202
-rw-r--r--Utilities/GitSetup/NOTICE5
-rw-r--r--Utilities/GitSetup/README80
-rw-r--r--Utilities/GitSetup/config9
-rw-r--r--Utilities/GitSetup/config.sample22
-rwxr-xr-xUtilities/GitSetup/setup-gerrit142
-rwxr-xr-xUtilities/GitSetup/setup-hooks63
-rwxr-xr-xUtilities/GitSetup/setup-ssh111
-rwxr-xr-xUtilities/GitSetup/setup-stage53
-rwxr-xr-xUtilities/GitSetup/setup-user39
-rwxr-xr-xUtilities/GitSetup/tips55
-rw-r--r--Utilities/KWIML/test/test_INT_format.h.in58
-rw-r--r--Utilities/Release/Cygwin/cygwin-setup.hint.in8
-rwxr-xr-xUtilities/SetupForDevelopment.sh13
-rw-r--r--Utilities/cmcurl/CMakeLists.txt4
-rwxr-xr-xbootstrap13
309 files changed, 8374 insertions, 1648 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c9ff2fc..b1d5930 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -422,26 +422,13 @@ ENDIF()
# The main section of the CMakeLists file
#
#-----------------------------------------------------------------------
-# The CMake version number.
-SET(CMake_VERSION_MAJOR 2)
-SET(CMake_VERSION_MINOR 8)
-SET(CMake_VERSION_PATCH 7)
-#SET(CMake_VERSION_TWEAK 0)
-#SET(CMake_VERSION_RC 1)
-
-# Releases define a tweak level.
-IF(DEFINED CMake_VERSION_TWEAK)
+INCLUDE(Source/CMakeVersion.cmake)
+# Releases define a small tweak level.
+IF("${CMake_VERSION_TWEAK}" VERSION_LESS 20000000)
SET(CMake_VERSION_IS_RELEASE 1)
SET(CMake_VERSION_SOURCE "")
ELSE()
SET(CMake_VERSION_IS_RELEASE 0)
-
- # Use the date as the tweak level.
- INCLUDE(${CMake_SOURCE_DIR}/Source/kwsys/kwsysDateStamp.cmake)
- SET(CMake_VERSION_TWEAK
- "${KWSYS_DATE_STAMP_YEAR}${KWSYS_DATE_STAMP_MONTH}${KWSYS_DATE_STAMP_DAY}"
- )
-
INCLUDE(${CMake_SOURCE_DIR}/Source/CMakeVersionSource.cmake)
ENDIF()
diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in
index 9eee655..9829191 100644
--- a/CTestCustom.cmake.in
+++ b/CTestCustom.cmake.in
@@ -40,8 +40,9 @@ SET(CTEST_CUSTOM_WARNING_EXCEPTION
"warning.*directory name.*CMake-Xcode.*/bin/.*does not exist.*"
"stl_deque.h:1051"
"(Lexer|Parser).*warning.*conversion.*may (alter its value|change the sign)"
+ "(Lexer|Parser).*warning.*statement is unreachable"
+ "PGC-W-0095-Type cast required for this conversion.*ProcessUNIX.c"
"[Qq]t([Cc]ore|[Gg]ui).*warning.*conversion.*may alter its value"
- "Parser.cxx.*warning.*2111-D.*statement is unreachable"
"warning:.*is.*very unsafe.*consider using.*"
"warning:.*is.*misused, please use.*"
"CMakeSetupManifest.xml.*manifest authoring warning.*Unrecognized Element"
diff --git a/ChangeLog.manual b/ChangeLog.manual
index f672b80..691ff94 100644
--- a/ChangeLog.manual
+++ b/ChangeLog.manual
@@ -1,3 +1,595 @@
+Changes in CMake 2.8.8 (since 2.8.8-rc2)
+----------------------------------------
+Brad King (1):
+ CheckIncludeFiles: Shorten check description message
+
+David Cole (3):
+ CPackNSIS: Rewrite variable documentation to make it more readable.
+ OS X: Use correct extra path when searching for applicaton bundles (#13066)
+ OS X: Mark find_program results as advanced
+
+Eric NOULARD (1):
+ Fix some doc typo and add an undocumented var.
+
+Kashif Rasul (1):
+ OS X: Use OSX_DEVELOPER_ROOT for app search path (#13066)
+
+Rolf Eike Beer (1):
+ FindBoost: add support for 1.49 and 1.50
+
+Changes in CMake 2.8.8-rc2 (since 2.8.8-rc1)
+--------------------------------------------
+Alex Neundorf (4):
+ make cmLocalGenerator::EscapeForCMake() static
+ automoc: fix #13018, proper cmake escaping to avoid false rebuilds
+ automoc: add define to test which caused bug #13018
+ fix #13054: support OBJECT libraries in Eclipse
+
+Ben Boeckel (1):
+ Create granular targets for Ninja generators too
+
+Brad King (6):
+ CTest.UpdateHG: Fix repo URL for leading slash
+ Always compile sources with known language
+ Classify known header file extensions as headers
+ VS: Add CMakeLists.txt re-run rules at start of generation
+ Test generated module .def files
+ Ninja: Fix module .def file path conversion
+
+David Cole (2):
+ CMake: Clarify SUFFIX target property documentation.
+ Xcode: Pay attention to custom configuration types (#13082)
+
+Peter Collingbourne (1):
+ Ninja: Substitute <OBJECT> and <CMAKE_C_COMPILER> in depfile flags
+
+Rolf Eike Beer (2):
+ FILE: mention that TO_CMAKE_PATH also handles list delimiters
+ FIND_LIBRARY: document FIND_LIBRARY_USE_LIB64_PATHS
+
+Sean McBride (1):
+ automoc: include <unistd.h> on Apple to get pathconf
+
+Tom Hughes (1):
+ Override topdir from rpm command line seems necessary on Amazon linux.
+
+Changes in CMake 2.8.8-rc1 (since 2.8.7)
+----------------------------------------
+Aaron C. Meadows (1):
+ Visual Studio: Allow setting Single Byte Character Set (#12189)
+
+Alex Neundorf (34):
+ GNUInstallDirs: add support for Debian multiarch
+ FindRuby: fix usage of RUBY_VERSION_MAJOR (#12172)
+ FindRuby: add more possible library names (for ubuntu, #12172)
+ FindRuby.cmake: add more debug output
+ fix FeatureSummary for REQUIRED packages, they were reported as OPTIONAL
+ FindGetText: fix multiple targets with the same name problem (CMP0002)
+ fix #6976: FindX11 also searches for X11_Xxf86vm_LIB
+ GenerateExportHeader: use double quotes around _gcc_version
+ -remove trailing whitespace
+ -don't pull in CheckTypeSize.cmake from the cmake which is being built
+ bootstrap: move while() and endwhile() into the bootstrap build
+ Check*.cmake: Expand imported targets in CMAKE_REQUIRED_LIBRARIES
+ find_package: print error if an invalid CONFIGS name is used
+ find_package: rename NoModule to UseFindModules
+ find_package: improve error message when no Find module is present
+ find_package: add MODULE mode to use only Find-modules
+ find_package: add CONFIG mode keyword alias for NO_MODULE
+ find_package: mention requested version number in error message
+ add CMakePackageConfigHelpers: configure_package_config_file()
+ wrap write_basic_config_version_file as write_basic_package_version_file()
+ find_package: error out if REQUIRED Config has not been found
+ write_basic_package_version_file(): improve documentation
+ write_basic_package_version_file: add ExactVersion mode
+ WriteBasicConfigVersionFile: add test for ExactVersion mode
+ find_package: allow <pkg>Config.cmake to set <pkg>_FOUND to FALSE
+ find_package: add test for setting Foo_FOUND to FALSE in a Config file
+ find_package: additional test for checking the error message
+ find_package: add OPTIONAL_COMPONENTS keyword
+ FPHSA(): add missing "]" to documentation
+ find_package: add documentation for OPTIONAL_COMPONENTS
+ FPHSA(): add HANDLE_COMPONENTS option
+ add macro check_required_components() to configure_package_config_file()
+ Eclipse: fix #13036, make version detection work with symlinks
+ guard eCos.cmake against multiple inclusion (#12987)
+
+Alexandru Ciobanu (2):
+ CTest: Detect Xcode error "Command ... failed with exit code"
+ CTest: Match valgrind errors with "points to" (#12922)
+
+Alexey Ozeritsky (1):
+ FindBLAS/FindLAPACK: Work with MKL version 10.3 (#12924, #12925)
+
+Artur Kedzierski (1):
+ Add CURL_CA_BUNDLE option for SSL support (#12946)
+
+Bill Hoffman (12):
+ Add CMakeAddFortranSubdirectory to use MinGW gfortran in VS
+ VSGNUFortran: Add special case for SunPro Fortran runtime library
+ VSGNUFortran: Disable test in special cases
+ CMakeAddFortranSubdirectory: Make IMPORTED targets GLOBAL
+ Use upgraded qt on linux build machine.
+ Teach CTest what a ninja error looks like.
+ Allow two cmake_add_fortran_subdirectory calls in the same project.
+ Add ability to include a file in a project via a cache variable.
+ Fix typo in error message, and remove redundent test.
+ Ninja: Add a cache option CMAKE_ENABLE_NINJA to enable the ninja generator.
+ Ninja: Fix for PDB files with spaces in the path.
+ Fix FindMPI for the intel compiler on linux by looking in implict directories.
+
+Bjoern Ricks (1):
+ Fix crash if app bundle executeable couldn't be found
+
+Brad King (138):
+ CheckCCompilerFlag: Generalize "but not for C" case (#12633)
+ complex: Remove ancient unused ComplexRelativePaths test
+ complex: Sync Tests/ComplexOneConfig with Tests/Complex
+ complex: Remove dynamic loader tests
+ complex: Move GeneratedFileStream test to CMakeLibTests
+ complex: Simplify test for single-character exe name
+ complex: Move cmSystemTools::UpperCase test to CMakeLibTests
+ complex: Remove test dependence on cmSystemTools
+ complex: Remove unused option to test CMakeLib
+ Intel: Fix Windows per-config Fortran flags (#12642)
+ libarchive: Remove our copy to make room for new import
+ libarchive: Add .gitattributes for indentation with tab
+ libarchive: Add README-CMake.txt
+ libarchive: Do not build subdirectories not in reduced snapshot
+ libarchive: Remove -Wall -Werror from build with GNU
+ libarchive: Build one static cmlibarchive for CMake
+ libarchive: Include cm_zlib.h to get zlib used by CMake
+ Handle libarchive API change in archive_read_data_block
+ Configure libarchive build within CMake
+ libarchive: Install COPYING with CMake documentation
+ libarchive: Port to OSF operating system
+ libarchive: Fix typo in CheckFileOffsetBits
+ libarchive: Implement custom lseek for Borland
+ libarchive: Declare mbstate_t and wcrtomb for Borland
+ libarchive: Cast constants to int64_t instead of using LL suffix
+ libarchive: Workaround case-insensitive symbols on Borland
+ libarchive: Clean up configuration within CMake build
+ libarchive: Cast mode constants to mode_t in case it is signed
+ libarchive: Fix Windows NT API usage in VS 6
+ libarchive: Suppress compiler warnings
+ libarchive: Fix var decl after statement in archive_string.c
+ libarchive: Do not use ST_NOATIME if not defined
+ libarchive: Check for 'struct statvfs' member 'f_iosize'
+ libarchive: Do not use MNT_NOATIME if not defined
+ libarchive: Use Apple copyfile.h API only if available
+ libarchive: Remove hard-coded build configuration
+ libarchive: Cleanup after ZLIB_WINAPI check
+ libarchive: Define _XOPEN_SOURCE=500 on HP-UX
+ libarchive: Include linux/types.h before linux/fiemap.h
+ libarchive: Rename isoent_rr_move_dir parameter isoent => curent
+ libarchive: Suppress PathScale compiler warnings
+ libarchive: Avoid bogus conversion warning from PGI compiler
+ libarchive: Set .gitattributes to allow trailing whitespace
+ libarchive: Update README-CMake.txt for new snapshot
+ libarchive: Restore CMake 2.6.3 as minimum version
+ bootstrap: Update copyright year in version report
+ bootstrap: Re-implement command line option processing
+ bootstrap: Forward options after '--' to cmake
+ VS10: Fix /pdb option vcxproj element name (#12328)
+ Add framework to detect compiler version with its id (#12408)
+ Detect GNU compiler version with its id (#6251)
+ Detect MSVC compiler version with its id
+ Detect Intel compiler version with its id (#11937)
+ Detect Borland compiler version with its id
+ Detect IBM XL compiler version with its id
+ Detect PGI compiler version with its id
+ Detect Clang compiler version with its id
+ Detect Watcom compiler version with its id
+ Detect SunPro compiler version with its id
+ Detect HP compiler version with its id
+ Document compiler version macro formats used for detection
+ Detect SGI MIPSpro compiler version with its id
+ ExternalProject: Fix git.cmd version detection
+ ExternalProject: Update copyright year
+ Include bzlib.h consistently across CMake build (#10950)
+ FindMPI: Append MPI C++ library correctly in non-compiler case (#12874)
+ Add infrastructure for CMake-only tests
+ Tolerate cycles in shared library link interfaces (#12647)
+ cmInstallCommand: Fix line length for style
+ cmake-mode.el: Indent after multiline argument (#12908)
+ Clarify IMPORTED_ target property documentation
+ Optionally allow IMPORTED targets to be globally visible
+ Add test covering imported target scope rules
+ VS: Simplify ;-separated attribute value parsing
+ Fix CXX/Fortran MODULE flags when enabled before C (#12929)
+ Remove unused test code
+ Allow directory names containing '=' and warn if necessary (#12934)
+ Add CheckLanguage module
+ CMakeAddFortranSubdirectory: Allow full paths to directories
+ CMakeAddFortranSubdirectory: Fix documentation format and typos
+ CMakeAddFortranSubdirectory: Find gfortran in PATH
+ CMakeAddFortranSubdirectory: Validate gfortran architecture
+ CMakeAddFortranSubdirectory: Always parse arguments
+ CMakeAddFortranSubdirectory: Add NO_EXTERNAL_INSTALL option
+ libarchive: Workaround mbsnrtowcs assertion failure on old glibc
+ Recognize OpenBSD versioned .so names (#12954)
+ try_compile: Use random executable file name (#12957)
+ Rename Modules/Platform/Windows-{Borland => Embarcadero}.cmake
+ Recognize Embarcadero compiler (#12604)
+ Factor cmInstallType out of cmTarget::TargetType
+ Add infrastructure for CMakeCommands tests
+ find_package: Reject mixed use of MODULE- and CONFIG-only options
+ find_package: Optionally warn when implicitly using Config mode
+ find_package: Test error and warning messages in failure cases
+ bootstrap: Convert MSYS paths to Windows format (#13001)
+ CTest.UpdateHG: Fix repo URL for local filesystem (#13001)
+ cmcurl: Do not hard-coded Windows check results for MinGW (#13001)
+ CheckSourceTree: Remove CVS checkout support (#13001)
+ Fix MSYS CVS local test repo path format (#13001)
+ find_package: Test that REQUIRED aborts processing correctly
+ Remove unused partial OBJECT_FILES property implementation
+ VS: Simplify object name computation
+ Hide Makefile local object info inside local generator
+ KWIML: Make test_INT robust to #define-d int#_t and INT#_C
+ Add stronger infrastructure for CMake-only tests
+ Use generalized RunCMake test infrastrucure for find_package test
+ Use generalized RunCMake test infrastrucure for build_command test
+ Document Fortran_MODULE_DIRECTORY as OUTPUT only (#13034)
+ Ninja: Constify use of cmCustomCommand
+ Ninja: Avoid using 'this' in member initializers
+ Write CMakeCache.txt atomically (#13040)
+ Add cmGeneratorTarget to represent a target during generation
+ Create a cmGeneratorTarget for each cmTarget during generation
+ Simplify cmMakefileTargetGenerator using cmGeneratorTarget
+ Simplify cmVisualStudio10TargetGenerator using cmGeneratorTarget
+ Pre-compute object file names before Makefile generation
+ Pre-compute object file names before VS project generation
+ Remove unused cmSourceGroup method
+ Rename/constify build-time config placeholder lookup
+ Pre-compute and store target object directory in cmGeneratorTarget
+ Add OBJECT_LIBRARY target type
+ Build object library targets in Makefiles
+ Build object library targets in VS
+ Add $<TARGET_OBJECTS:...> expression to use an object library
+ Test OBJECT library success cases
+ Test OBJECT library failure cases
+ Test OBJECT library language propagation
+ Test OBJECT library use without other sources
+ Document OBJECT library type in add_library command
+ Simplify cmNinjaTargetGenerator using cmGeneratorTarget
+ Pre-compute object file names before Ninja generation
+ Build object library targets in Ninja
+ Ninja: Honor $<TARGET_OBJECTS:...> source expressions
+ find_package: Test rejection of required+optional components
+ Simplify cmVisualStudio10TargetGenerator source classification
+ VS10: Fix external objects generated outside target (#13047)
+ Fix ObjectLibrary test on Watcom
+ KWIML: Avoid conflict with C++11 user-defined literals
+
+Christian Andersson (1):
+ FindPythonLibs: Search for single-user installs on Windows
+
+Christopher Sean Morrison (1):
+ cmake-mode.el: Make indentation case-insensitive (#12995)
+
+Clinton Stimpson (14):
+ GetPrerequisites: Add support for @rpath on Mac OS X.
+ GetPrerequisites: Add support for @rpath on Mac OS X.
+ GetPrerequisites: Add test for @rpath support.
+ Fix new BundleUtilities test failure on Mac 10.4.x
+ Fix BundleUtilities test failure with space in build path.
+ cmake-gui: Improve interrupt granularity to fix bug 12649.
+ FindQt4: clarify warning message about incorrect Qt installation.
+ FindQt4: Add include directories for lupdate.
+ Fix paths/hints for finding qtmain.
+ DragNDrop: Fix problem with relocated files in Xcode 4.3
+ Add test for DeployQt4.cmake
+ Fix for Qt4Deploy on some test machines.
+ Remove QtGui dependency in Qt4Deploy test and verify QtSql existance.
+ DeployQt4: Add path to Qt dlls on Windows.
+
+Daniel Nelson (1):
+ CPack Add top level directory in component install for Archive Generators
+
+David Cole (33):
+ Begin post-2.8.7 development
+ Release: Increase timeout for slow-testing cygwin build
+ Update dashmacmini2 release script to use Qt 4.6.3
+ Update dashmacmini2 release script to use Qt 4.8.0
+ Tests: Update drop site value for the Trilinos contract test
+ Update version of Qt for dashmacmini5 produced release binaries
+ CTestCustom: Suppress clang warning on the dashboard
+ CMake: Eliminate cmMakefile::IncludeDirectories
+ Remove cmMakefile::GetIncludeDirectories
+ Make search paths ordered and unique
+ Call ExpandVariablesInString for each target's INCLUDE_DIRECTORIES
+ Update the documentation regarding INCLUDE_DIRECTORIES.
+ Fix compiler error reported on older Borland dashboard.
+ Fix compiler warning reported on older Borland dashboard.
+ Fix shadowed variable warning on dashboard results
+ Remove trailing white space
+ Use correct "requires" line in cygwin setup hint file
+ VS6: Avoid _MBCS define when _SBCS is defined (#12189)
+ VS6: Avoid SBCS test on VS6 (#12189)
+ Suppress warnings occurring on the dashboards using the PGI compiler.
+ CPack: Fix retry logic when calls to hdiutil fail
+ Ninja: CMake: Adapt Ninja generator for per-target include dirs
+ Ninja: Add friend struct so it can access the private ConvertToNinjaPath.
+ Xcode: Detect new default locations of Xcode 4.3 bits and pieces (#12621)
+ CPack: Use real path to PackageMaker to find its version file (#12621)
+ Xcode: Re-factor code into GetObjectsNormalDirectory method
+ Xcode: Re-factor some existing methods into "FromPath" variants
+ Add a default source group for object files.
+ Allow txt files as ExtraSources in object library targets
+ Pre-compute object file names before Xcode generation
+ Build object library targets in Xcode
+ Xcode: Honor $<TARGET_OBJECTS:...> source expressions
+ Tests: Relax restrictions on version variable contents
+
+Deborah Pickett (1):
+ CPackRPM flag direcories with %dir in the generated spec file
+
+Droscy (1):
+ FindCxxTest: Add support for CxxTest 4 (#13022)
+
+Eric NOULARD (41):
+ Document undocumented (but existing) cpack options (fix #0010134)
+ Enhance bash completion file for cmake and ctest
+ Do not add the content of a file if it's a symlink.
+ CPackArchive restore default behavior and provide new variable.
+ CPackNSIS fix #0012935 switch from LOG_WARNING to avoid final error.
+ CPack begin the implementation of --help-command* and --help-variables*
+ Implement simple CMake script comment markup language.
+ CPack Documentation extraction from CMake script begins to work
+ Update bash completion file in order to handle new CPack doc options.
+ Suppress unused var, beautify code, avoid 1 extra newline.
+ Fix potential bad memory access, thanks to Eike
+ Calm down compiler warning about unused var
+ Really avoid compiler warning about unused vars
+ Fix another compiler warning due to a typo
+ Make the load of script documentation more efficient and dynamic.
+ Example of builtin variable documentation (i.e. only used in C++ source code).
+ Add missing section markup for CPackComponent
+ Create getDocumentedModulesListInDir which may be used in other context.
+ Fix non existent std::string::clear on VS6
+ Avoid discovering system infos for documentation. Adding some path is enough.
+ Dynamically add documentation section specified in documented script.
+ Add structured documentation for NSIS
+ Add structure documentation for CPack Bundle generator
+ Suppress unecessary (now empty) doc sections
+ Correct copy/paste section name mistake
+ Put CPack DMG and PackageMaker doc in separate files
+ More documentation concerning CPack Components
+ Fix typo in end markup
+ Try to fix compile error on Win32-vs70
+ Do not build RPM if path of the build tree contains space
+ Fix layout of the CPack Bundle documentation
+ Fix CPack Drag and Drop generator documentation layout.
+ Review and update CPack variable documentation.
+ Update CPackConfig template.
+ Provide template for CPack Cygwin generator specific variables.
+ Update CPack PackageMaker variable doc layout
+ Typo: Add missing ##end for ##module
+ Fix some typos in CPACK_SET_DESTDIR doc
+ Add some missing CPACK_NSIS_xxx doc and move some to common CPack section.
+ CPack STGZ put execute permission on all packages files (component case)
+ Handle CPACK_MONOLITHIC_INSTALL in some rare use cases.
+
+Eugene Golushkov (1):
+ VS: Add support for WinRT project properties (#12930)
+
+James Bigler (1):
+ Added support for curand, cusparse, npp, nvcuenc and nvcuvid libraries.
+
+Jason Erb (1):
+ FindwxWidgets: Add webview library (#12636)
+
+LibArchive Upstream (2):
+ libarchive 3.0.1-r3950 (reduced)
+ libarchive 3.0.2-r4051 (reduced)
+
+Matthias Kretz (1):
+ Improve checks for Open64 and g++ incompatible flags (#12119)
+
+Mattias Helsing (1):
+ CPack: Fix NSIS handling of privileged users (#12923)
+
+Michael Wild (1):
+ GenerateExportHeader: Fix wrong use of IS_ABSOLUTE (#12645)
+
+Mike McQuaid (5):
+ Don't use QT_LIBRARIES_PLUGINS by default.
+ Fix mismatched arguments.
+ Fix bad plugin paths.
+ Ensure libs are passed to BundleUtilities.
+ Fix plugin installation issues.
+
+Modestas Vainius (3):
+ various typo and formatting fixes in manual pages (#12975)
+ KWIML: Teach ABI.h that MIPS is biendian
+ Tests: Escape metachars before embedding paths into the regex (#12999)
+
+Nicolas Despres (5):
+ ccmake: Factor clear line.
+ ccmake: Extend clear line.
+ java: Factor jar output path.
+ java: Add CMAKE_JAVA_TARGET_OUTPUT_DIR optional variable.
+ java: Add CMAKE_JAVA_JAR_ENTRY_POINT optional variable.
+
+Peter Collingbourne (19):
+ Add cmSystemTools::TrimWhitespace function
+ Add executable with exports flag support to cmLocalGenerator::GetTargetFlags
+ Provide dependency file flags to generator
+ Ninja: Add the Ninja generator
+ Ninja: Fix a 79-col violation
+ Ninja: Remove some default arguments
+ Ninja: Appease various compilers
+ Ninja: Partially revert "win fixes: escape back slash/colon, use cd. as cmd.exe nop"
+ Ninja: Identifier encoding rules for ' ' and ':'
+ Ninja: Backslash rules for Windows
+ Ninja: Shell encode paths used in "cd" commands
+ Ninja: Shell encode various CMake invocations
+ Ninja: Shell encode the command used in custom commands
+ Ninja: Import library support for Windows
+ Ninja: Add a missed license header
+ Ninja: Use cmSystemTools::ExpandListArgument to split compile/link commands
+ Ninja: Remove an unnecessary variable
+ Ninja: add support for OBJECT_OUTPUTS, fix PrecompiledHeader test case
+ Ninja: shell escape $(CMAKE_SOURCE_DIR) and $(CMAKE_BINARY_DIR)
+
+Peter Kuemmel (12):
+ Find VC Express during default generator selection (#12917)
+ Ninja: win fixes: escape back slash/colon, use cd. as cmd.exe nop
+ Ninja: don't define MSVC_IDE when using the ninja generator
+ Ninja: also build ninja support on Windows
+ Ninja: add some hacks for Windows
+ Ninja: disable unfinished Windows ninja support
+ Ninja: mark the Windows specific hacks with a comment only
+ Ninja: windows msvc: create for each target a .pdb file
+ Ninja: ensure the output dir exists at compile time
+ Ninja: add .def file support
+ Ninja: add /DEF: flag to linker call
+ Ninja: Fix <OBJECT_DIR> substitution
+
+Philip Lowman (5):
+ FindProtobuf: Merge patch that allows extra import dirs
+ FindProtobuf: Update documentation comment for 2.8.8
+ Findosg: New modules for osgQt and osgPresentation
+ FindALSA: Fix incorrect include path detection
+ FindALSA: Fix version detection after last commit
+
+Rolf Eike Beer (95):
+ remove reference to CVS directory when installing files
+ CheckSymbolExists: force the compiler to keep the referenced symbol
+ add a test for Check{,CXX}SymbolExists
+ FindOpenSSL: improve version number handling
+ FindOpenSSL: only try to parse opensslv.h if it exists
+ FindOpenSSL: also parse version number define with uppercase letters
+ GenerateExportHeader test: add newlines before end of file
+ add a test that loops through most Find* modules
+ AllFindModules test: keep complete output
+ AllFindModules test: also check Qt3 modules if Qt4 is not found
+ FindPythonInterp: make version selectable
+ FindPythonInterp: fix version parsing
+ LoadCommand test: cleanup
+ FindThreads: Try pthreads with no special option first (#11333)
+ fix uninitialized var in if(NOT foo bar STREQUAL "foo bar")
+ use pkg_check_modules() quiet in other modules
+ FindLibXml2: support version selection
+ FindGnuTLS: partly support version selection
+ FindGit: support version number
+ FindCups: major overhaul
+ FindEXPAT: support version number
+ FindCURL: support version selection
+ FindFLEX: fix version parsing for old flex versions
+ FindFLEX: fix version parsing when the executable is quoted
+ FindJasper: find debug libraries
+ FindJasper: support version number
+ FindBZip2: add support for version checking
+ FindBZip2: add support for debug libraries (#12867)
+ FindImageMagick: make use of more FPHSA features
+ FindPNG: support version selection
+ FindRuby: do not blindly set version to 1.8.0
+ FindTclsh: support version selection
+ SelectLibraryConfigurations: do not output identical configurations
+ FindLua51: add version support
+ FindTIFF: support version selection
+ FindCURL: detect version number also for older versions
+ FindLibXml2: detect version when PkgConfig is not used
+ FindPostgreSQL: support version selection
+ FindOpenSSL: properly parse the hex version components
+ FindBISON: add a version expression for GNU Bison 1.x
+ FindPythonInterp: try harder to get a version number
+ FindJasper: fix library name
+ FindGnuplot: add version selection
+ FindALSA: support version selection
+ FindGettext: support version selection
+ CheckCXXCompilerFlag test: make it a CMakeOnly test
+ CMakeOnly.AllFindModules: clean up the Qt3/Qt4 code
+ CMakeOnly.AllFindModules: always check FindQt
+ CMakeOnly.AllFindModules: suppress two modules from testing
+ CMakeOnly.AllFindModules: require version for some modules
+ CheckIncludeFiles: fix status output
+ FindPerl{,Libs}: move version detection into FindPerl
+ FindLibArchive: support version selection
+ FindX11: also search for Xmu (#12447)
+ detect "pgfortran" as PGI Fortran compiler (#12425)
+ FindSDL*: use FPHSA (#12467)
+ AllFindModules test: do not enforce GNUPLOT version
+ FindPerlLibs: properly detect libperl on Windows (#12224)
+ CTest: mark all gcov covered files as covered
+ FindGLUT: honor REQUIRED (#12466)
+ FindRuby: clean up querying variables from Ruby
+ FindLibXslt: support version selection
+ Tests: document where to put tests
+ FindPkgConfig: support version selection of pkg-config itself
+ fix the same typos as found by Debian in other places, too
+ Find_library(): allow searching for versioned shared objects
+ FindFreetype: support version selection
+ AllFindModules test: expect more modules to have a version number available
+ FindOpenMP: do not fail if only C or CXX is enabled (#11910)
+ FindOpenMP: try the most likely flags first
+ FindOpenMP: simplify check for enabled languages
+ UseSWIG: clean up string compares
+ FindPython{Interp,Libs}: document Python_ADDITIONAL_VERSIONS as input
+ FindPythonLibs: make the version selection work as for PythonInterp
+ FindPythonLibs: get the exact version of the found library (#3080)
+ FindPythonLibs: put debug libraries into PYTHON_LIBRARIES
+ FindPythonLibs: stop scanning when libraries are found
+ Check{C,CXX}CompilerFlag: detect ICC error messages
+ GenerateExportHeader: remove unneeded code
+ GenerateExportHeader: improve compiler identification
+ FindOpenSceneGraph: give every message() with an explicit level
+ FindHSPELL: set HSPELL_VERSION_STRING
+ FindImageMagick: fix fail if no components were given
+ FindPythonInterp: rework the version detection
+ document when version detection will not work
+ AllFindModules test: once again expand version checking
+ improve error message on a stray "endwhile()"
+ add testcases for while()/endwhile() errors
+ reflect that the QtAutomoc depends on QtGui
+ FindQt3: fix warning when Qt3 is not found
+ FindQt3: fix version extraction for versions with letters
+ FindQt3: let FPHSA handle the version selection
+ FindQt3: fix detection of Qt3 include directory
+ AllFindModules test: do not require TCLSH version
+ add test for get_property() errors
+
+Stephen Kelly (13):
+ Fix typos arguement -> argument.
+ Exit the loop when we have determined the language.
+ Add whitespace after '.' in CMAKE_SKIP_RPATH docs.
+ Fix documented function signature to match reality.
+ Add default initializers for WIN32_EXECUTABLE and MACOSX_BUNDLE
+ Add an option to skip RPATH during installation.
+ Refactor GetIncludeFlags to take includes instead of fetching them
+ Make it safe to call this method without creating duplicates.
+ Remove include flags memoization.
+ Add API to get the ordered includes for a target.
+ Keep the INCLUDE_DIRECTORIES target property up to date.
+ Extract and use the INCLUDE_DIRECTORIES target properties.
+ Fix some typos in the docs comments.
+
+Yury G. Kudryashov (23):
+ FindDoxygen: add DOXYGEN_VERSION variable
+ cmInstallCommand: Fix indentation error
+ cmInstallCommand: Remove duplicated sentence from docs
+ FindPkgConfig: respect REQUIRED (#12620)
+ FindPackageHandleStandardArgs: fix documentation
+ Remove unused file cmake.1
+ Fix typo in documentation
+ Drop if(...) check because condition is always true
+ CMakeFindPackageMode: fix 32/64bit detection if 'file' is a symlink
+ Run vim spellcheck on some files
+ cmPropertyDefinition::IsChained is const
+ Add 'const' qualifier to some cmCommand members
+ doxygen: cmPropertyDefinition
+ doxygen: Improve API docs of GetRealDependency
+ doxygen: Use proper syntax to document enum
+ doxygen: Small fixes in cmake.h apidocs
+ doxygen: fix some comments in cmPolicies.h
+ doxygen: remove a few comments
+ doxygen: review cmake.h
+ doxygen: MathCommand is not about string operators
+ Rename UsedCommands to FinalPassCommands
+ Remove UnionsAvailable member from 2 classes
+ Remove cmExprParserHelper::SetLineFile()
+
Changes in CMake 2.8.7 (since 2.8.7-rc2)
--------------------------------------------
None
diff --git a/Modules/AutomocInfo.cmake.in b/Modules/AutomocInfo.cmake.in
index 29dab97..13f2161 100644
--- a/Modules/AutomocInfo.cmake.in
+++ b/Modules/AutomocInfo.cmake.in
@@ -1,9 +1,9 @@
-set(AM_SOURCES "@_moc_files@" )
-set(AM_HEADERS "@_moc_headers@" )
-set(AM_MOC_COMPILE_DEFINITIONS "@_moc_compile_defs@")
-set(AM_MOC_DEFINITIONS "@_moc_defs@")
-set(AM_MOC_INCLUDES "@_moc_incs@")
-set(AM_MOC_OPTIONS "@_moc_options@")
+set(AM_SOURCES @_moc_files@ )
+set(AM_HEADERS @_moc_headers@ )
+set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@)
+set(AM_MOC_DEFINITIONS @_moc_defs@)
+set(AM_MOC_INCLUDES @_moc_incs@)
+set(AM_MOC_OPTIONS @_moc_options@)
set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@")
set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/")
set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/")
@@ -12,5 +12,5 @@ set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
set(AM_QT_VERSION_MAJOR "@QT_VERSION_MAJOR@" )
set(AM_Qt5Core_VERSION_MAJOR "@Qt5Core_VERSION_MAJOR@" )
-set(AM_TARGET_NAME "@_moc_target_name@")
+set(AM_TARGET_NAME @_moc_target_name@)
set(AM_RELAXED_MODE "@_moc_relaxed_mode@")
diff --git a/Modules/BasicConfigVersion-ExactVersion.cmake.in b/Modules/BasicConfigVersion-ExactVersion.cmake.in
new file mode 100644
index 0000000..c610baa
--- /dev/null
+++ b/Modules/BasicConfigVersion-ExactVersion.cmake.in
@@ -0,0 +1,42 @@
+# This is a basic version file for the Config-mode of find_package().
+# It is used by write_basic_package_version_file() as input file for configure_file()
+# to create a version-file which can be installed along a config.cmake file.
+#
+# The created file sets PACKAGE_VERSION_EXACT if the current version string and
+# the requested version string are exactly the same and it sets
+# PACKAGE_VERSION_COMPATIBLE if the current version is equal to the requested version.
+# The tweak version component is ignored.
+# The variable CVF_VERSION must be set before calling configure_file().
+
+
+set(PACKAGE_VERSION "@CVF_VERSION@")
+
+if("@CVF_VERSION@" MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)\\..*") # strip the tweak version
+ set(CVF_VERSION_NO_TWEAK "${CMAKE_MATCH_1}")
+else()
+ set(CVF_VERSION_NO_TWEAK "@CVF_VERSION@")
+endif()
+
+if("${PACKAGE_FIND_VERSION}" MATCHES "^([0-9]+\\.[0-9]+\\.[0-9]+)\\..*") # strip the tweak version
+ set(REQUESTED_VERSION_NO_TWEAK "${CMAKE_MATCH_1}")
+else()
+ set(REQUESTED_VERSION_NO_TWEAK "${PACKAGE_FIND_VERSION}")
+endif()
+
+if("${REQUESTED_VERSION_NO_TWEAK}" STREQUAL "${CVF_VERSION_NO_TWEAK}")
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+else()
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+endif()
+
+if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
+ set(PACKAGE_VERSION_EXACT TRUE)
+endif()
+
+
+# check that the installed version has the same 32/64bit-ness as the one which is currently searching:
+if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "@CMAKE_SIZEOF_VOID_P@")
+ math(EXPR installedBits "@CMAKE_SIZEOF_VOID_P@ * 8")
+ set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)")
+ set(PACKAGE_VERSION_UNSUITABLE TRUE)
+endif()
diff --git a/Modules/CMakeFindEclipseCDT4.cmake b/Modules/CMakeFindEclipseCDT4.cmake
index dd06128..a4264e7 100644
--- a/Modules/CMakeFindEclipseCDT4.cmake
+++ b/Modules/CMakeFindEclipseCDT4.cmake
@@ -20,7 +20,9 @@ FIND_PROGRAM(CMAKE_ECLIPSE_EXECUTABLE NAMES eclipse DOC "The Eclipse executable"
FUNCTION(_FIND_ECLIPSE_VERSION)
# This code is in a function so the variables used here have only local scope
IF(CMAKE_ECLIPSE_EXECUTABLE)
- GET_FILENAME_COMPONENT(_ECLIPSE_DIR "${CMAKE_ECLIPSE_EXECUTABLE}" PATH)
+ # use REALPATH to resolve symlinks (http://public.kitware.com/Bug/view.php?id=13036)
+ GET_FILENAME_COMPONENT(_REALPATH_CMAKE_ECLIPSE_EXECUTABLE "${CMAKE_ECLIPSE_EXECUTABLE}" REALPATH)
+ GET_FILENAME_COMPONENT(_ECLIPSE_DIR "${_REALPATH_CMAKE_ECLIPSE_EXECUTABLE}" PATH)
FILE(GLOB _ECLIPSE_FEATURE_DIR "${_ECLIPSE_DIR}/features/org.eclipse.platform*")
IF("${_ECLIPSE_FEATURE_DIR}" MATCHES ".+org.eclipse.platform_([0-9]+\\.[0-9]+).+")
SET(_ECLIPSE_VERSION ${CMAKE_MATCH_1})
diff --git a/Modules/CMakeGenericSystem.cmake b/Modules/CMakeGenericSystem.cmake
index 6cd8fe6..ee8040e 100644
--- a/Modules/CMakeGenericSystem.cmake
+++ b/Modules/CMakeGenericSystem.cmake
@@ -39,6 +39,8 @@ SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
SET (CMAKE_SKIP_RPATH "NO" CACHE BOOL
"If set, runtime paths are not added when using shared libraries.")
+SET (CMAKE_SKIP_INSTALL_RPATH "NO" CACHE BOOL
+ "If set, runtime paths are not added when installing shared libraries, but are added when building.")
SET(CMAKE_VERBOSE_MAKEFILE FALSE CACHE BOOL "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo.")
@@ -168,5 +170,6 @@ ENDIF(CMAKE_HOST_UNIX)
MARK_AS_ADVANCED(
CMAKE_SKIP_RPATH
+ CMAKE_SKIP_INSTALL_RPATH
CMAKE_VERBOSE_MAKEFILE
)
diff --git a/Modules/CMakeNinjaFindMake.cmake b/Modules/CMakeNinjaFindMake.cmake
new file mode 100644
index 0000000..f15c3e0
--- /dev/null
+++ b/Modules/CMakeNinjaFindMake.cmake
@@ -0,0 +1,17 @@
+
+#=============================================================================
+# Copyright 2011 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.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+FIND_PROGRAM(CMAKE_MAKE_PROGRAM ninja
+ DOC "Program used to build from build.ninja files.")
+MARK_AS_ADVANCED(CMAKE_MAKE_PROGRAM)
diff --git a/Modules/CMakePackageConfigHelpers.cmake b/Modules/CMakePackageConfigHelpers.cmake
new file mode 100644
index 0000000..48039e5
--- /dev/null
+++ b/Modules/CMakePackageConfigHelpers.cmake
@@ -0,0 +1,227 @@
+# - CONFIGURE_PACKAGE_CONFIG_FILE(), WRITE_BASIC_PACKAGE_VERSION_FILE()
+#
+# CONFIGURE_PACKAGE_CONFIG_FILE(<input> <output> INSTALL_DESTINATION <path>
+# [PATH_VARS <var1> <var2> ... <varN>]
+# [NO_SET_AND_CHECK_MACRO]
+# [NO_CHECK_REQUIRED_COMPONENTS_MACRO])
+#
+# CONFIGURE_PACKAGE_CONFIG_FILE() should be used instead of the plain
+# CONFIGURE_FILE() command when creating the <Name>Config.cmake or <Name>-config.cmake
+# file for installing a project or library. It helps making the resulting package
+# relocatable by avoiding hardcoded paths in the installed Config.cmake file.
+#
+# In a FooConfig.cmake file there may be code like this to make the
+# install destinations know to the using project:
+# set(FOO_INCLUDE_DIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@" )
+# set(FOO_DATA_DIR "@CMAKE_INSTALL_PREFIX@/@RELATIVE_DATA_INSTALL_DIR@" )
+# set(FOO_ICONS_DIR "@CMAKE_INSTALL_PREFIX@/share/icons" )
+# ...logic to determine installedPrefix from the own location...
+# set(FOO_CONFIG_DIR "${installedPrefix}/@CONFIG_INSTALL_DIR@" )
+# All 4 options shown above are not sufficient, since the first 3 hardcode
+# the absolute directory locations, and the 4th case works only if the logic
+# to determine the installedPrefix is correct, and if CONFIG_INSTALL_DIR contains
+# a relative path, which in general cannot be guaranteed.
+# This has the effect that the resulting FooConfig.cmake file would work poorly
+# under Windows and OSX, where users are used to choose the install location
+# of a binary package at install time, independent from how CMAKE_INSTALL_PREFIX
+# was set at build/cmake time.
+#
+# Using CONFIGURE_PACKAGE_CONFIG_FILE() helps. If used correctly, it makes the
+# resulting FooConfig.cmake file relocatable.
+# Usage:
+# 1. write a FooConfig.cmake.in file as you are used to
+# 2. insert a line containing only the string "@PACKAGE_INIT@"
+# 3. instead of SET(FOO_DIR "@SOME_INSTALL_DIR@"), use SET(FOO_DIR "@PACKAGE_SOME_INSTALL_DIR@")
+# (this must be after the @PACKAGE_INIT@ line)
+# 4. instead of using the normal CONFIGURE_FILE(), use CONFIGURE_PACKAGE_CONFIG_FILE()
+#
+# The <input> and <output> arguments are the input and output file, the same way
+# as in CONFIGURE_FILE().
+#
+# The <path> given to INSTALL_DESTINATION must be the destination where the FooConfig.cmake
+# file will be installed to. This can either be a relative or absolute path, both work.
+#
+# The variables <var1> to <varN> given as PATH_VARS are the variables which contain
+# install destinations. For each of them the macro will create a helper variable
+# PACKAGE_<var...>. These helper variables must be used
+# in the FooConfig.cmake.in file for setting the installed location. They are calculated
+# by CONFIGURE_PACKAGE_CONFIG_FILE() so that they are always relative to the
+# installed location of the package. This works both for relative and also for absolute locations.
+# For absolute locations it works only if the absolute location is a subdirectory
+# of CMAKE_INSTALL_PREFIX.
+#
+# By default configure_package_config_file() also generates two helper macros,
+# set_and_check() and check_required_components() into the FooConfig.cmake file.
+#
+# set_and_check() should be used instead of the normal set()
+# command for setting directories and file locations. Additionally to setting the
+# variable it also checks that the referenced file or directory actually exists
+# and fails with a FATAL_ERROR otherwise. This makes sure that the created
+# FooConfig.cmake file does not contain wrong references.
+# When using the NO_SET_AND_CHECK_MACRO, this macro is not generated into the
+# FooConfig.cmake file.
+#
+# check_required_components(<package_name>) should be called at the end of the
+# FooConfig.cmake file if the package supports components.
+# This macro checks whether all requested, non-optional components have been found,
+# and if this is not the case, sets the Foo_FOUND variable to FALSE, so that the package
+# is considered to be not found.
+# It does that by testing the Foo_<Component>_FOUND variables for all requested
+# required components.
+# When using the NO_CHECK_REQUIRED_COMPONENTS option, this macro is not generated
+# into the FooConfig.cmake file.
+#
+# For an example see below the documentation for WRITE_BASIC_PACKAGE_VERSION_FILE().
+#
+#
+# WRITE_BASIC_PACKAGE_VERSION_FILE( filename VERSION major.minor.patch COMPATIBILITY (AnyNewerVersion|SameMajorVersion|ExactVersion) )
+#
+# Writes a file for use as <package>ConfigVersion.cmake file to <filename>.
+# See the documentation of FIND_PACKAGE() for details on this.
+# filename is the output filename, it should be in the build tree.
+# major.minor.patch is the version number of the project to be installed
+# The COMPATIBILITY mode AnyNewerVersion means that the installed package version
+# will be considered compatible if it is newer or exactly the same as the requested version.
+# This mode should be used for packages which are fully backward compatible,
+# also across major versions.
+# If SameMajorVersion is used instead, then the behaviour differs from AnyNewerVersion
+# in that the major version number must be the same as requested, e.g. version 2.0 will
+# not be considered compatible if 1.0 is requested.
+# This mode should be used for packages which guarantee backward compatibility within the
+# same major version.
+# If ExactVersion is used, then the package is only considered compatible if the requested
+# version matches exactly its own version number (not considering the tweak version).
+# For example, version 1.2.3 of a package is only considered compatible to requested version 1.2.3.
+# This mode is for packages without compatibility guarantees.
+# If your project has more elaborated version matching rules, you will need to write your
+# own custom ConfigVersion.cmake file instead of using this macro.
+#
+# Internally, this macro executes configure_file() to create the resulting
+# version file. Depending on the COMPATIBLITY, either the file
+# BasicConfigVersion-SameMajorVersion.cmake.in or BasicConfigVersion-AnyNewerVersion.cmake.in
+# is used. Please note that these two files are internal to CMake and you should
+# not call configure_file() on them yourself, but they can be used as starting
+# point to create more sophisticted custom ConfigVersion.cmake files.
+#
+#
+# Example using both configure_package_config_file() and write_basic_package_version_file():
+# CMakeLists.txt:
+# set(INCLUDE_INSTALL_DIR include/ ... CACHE )
+# set(LIB_INSTALL_DIR lib/ ... CACHE )
+# set(SYSCONFIG_INSTALL_DIR etc/foo/ ... CACHE )
+# ...
+# include(CMakePackageConfigHelpers)
+# configure_package_config_file(FooConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
+# INSTALL_DESTINATION ${LIB_INSTALL_DIR}/Foo/cmake
+# PATH_VARS INCLUDE_INSTALL_DIR SYSCONFIG_INSTALL_DIR)
+# write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
+# VERSION 1.2.3
+# COMPATIBILITY SameMajorVersion )
+# install(FILES ${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
+# DESTINATION ${LIB_INSTALL_DIR}/Foo/cmake )
+#
+# With a FooConfig.cmake.in:
+# set(FOO_VERSION x.y.z)
+# ...
+# @PACKAGE_INIT@
+# ...
+# set_and_check(FOO_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
+# set_and_check(FOO_SYSCONFIG_DIR "@PACKAGE_SYSCONFIG_INSTALL_DIR@")
+#
+# check_required_components(Foo)
+
+
+#=============================================================================
+# Copyright 2012 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.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+# License text for the above reference.)
+
+include(CMakeParseArguments)
+
+include(WriteBasicConfigVersionFile)
+
+macro(WRITE_BASIC_PACKAGE_VERSION_FILE)
+ write_basic_config_version_file(${ARGN})
+endmacro()
+
+
+function(CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile)
+ set(options NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO)
+ set(oneValueArgs INSTALL_DESTINATION )
+ set(multiValueArgs PATH_VARS )
+
+ cmake_parse_arguments(CCF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(CCF_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown keywords given to CONFIGURE_PACKAGE_CONFIG_FILE(): \"${CCF_UNPARSED_ARGUMENTS}\"")
+ endif()
+
+ if(NOT CCF_INSTALL_DESTINATION)
+ message(FATAL_ERROR "No INSTALL_DESTINATION given to CONFIGURE_PACKAGE_CONFIG_FILE()")
+ endif()
+
+ if(IS_ABSOLUTE "${CCF_INSTALL_DESTINATION}")
+ set(absInstallDir "${CCF_INSTALL_DESTINATION}")
+ else()
+ set(absInstallDir "${CMAKE_INSTALL_PREFIX}/${CCF_INSTALL_DESTINATION}")
+ endif()
+ file(RELATIVE_PATH PACKAGE_RELATIVE_PATH "${absInstallDir}" "${CMAKE_INSTALL_PREFIX}" )
+
+ foreach(var ${CCF_PATH_VARS})
+ if(NOT DEFINED ${var})
+ message(FATAL_ERROR "Variable ${var} does not exist")
+ else()
+ if(IS_ABSOLUTE "${${var}}")
+ string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${PACKAGE_PREFIX_DIR}"
+ PACKAGE_${var} "${${var}}")
+ else()
+ set(PACKAGE_${var} "\${PACKAGE_PREFIX_DIR}/${${var}}")
+ endif()
+ endif()
+ endforeach()
+
+ set(PACKAGE_INIT "
+####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() #######
+get_filename_component(PACKAGE_PREFIX_DIR \"\${CMAKE_CURRENT_LIST_DIR}/${PACKAGE_RELATIVE_PATH}\" ABSOLUTE)
+")
+
+ if(NOT CCF_NO_SET_AND_CHECK_MACRO)
+ set(PACKAGE_INIT "${PACKAGE_INIT}
+macro(set_and_check _var _file)
+ set(\${_var} \"\${_file}\")
+ if(NOT EXISTS \"\${_file}\")
+ message(FATAL_ERROR \"File or directory \${_file} referenced by variable \${_var} does not exist !\")
+ endif()
+endmacro()
+")
+ endif()
+
+
+ if(NOT CCF_NO_CHECK_REQUIRED_COMPONENTS_MACRO)
+ set(PACKAGE_INIT "${PACKAGE_INIT}
+macro(check_required_components _NAME)
+ foreach(comp \${\${_NAME}_FIND_COMPONENTS})
+ if(NOT \${_NAME}_\${comp}_FOUND)
+ if(\${_NAME}_FIND_REQUIRED_\${comp})
+ set(\${_NAME}_FOUND FALSE)
+ endif()
+ endif()
+ endforeach(comp)
+endmacro()
+")
+ endif()
+
+ set(PACKAGE_INIT "${PACKAGE_INIT}
+####################################################################################")
+
+ configure_file("${_inputFile}" "${_outputFile}" @ONLY)
+
+endfunction()
diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake
index b506711..571770e 100644
--- a/Modules/CPack.cmake
+++ b/Modules/CPack.cmake
@@ -101,6 +101,11 @@
##end
#
##variable
+# CPACK_PACKAGE_ICON - A branding image that will be displayed inside
+# the installer (used by GUI installers).
+##end
+#
+##variable
# CPACK_PROJECT_CONFIG_FILE - CPack-time project CPack configuration
# file. This file included at cpack time, once per
# generator after CPack has set CPACK_GENERATOR to the actual generator
@@ -247,6 +252,15 @@
# CPACK_INSTALLED_DIRECTORIES - Extra directories to install.
##end
#
+##variable
+# CPACK_PACKAGE_INSTALL_REGISTRY_KEY - Registry key used when
+# installing this project. This is only used
+# by installer for Windows.
+##end
+##variable
+# CPACK_CREATE_DESKTOP_LINKS - List of desktop links to create.
+##end
+#
#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
diff --git a/Modules/CPackNSIS.cmake b/Modules/CPackNSIS.cmake
index 97179d7..5e2ba17 100644
--- a/Modules/CPackNSIS.cmake
+++ b/Modules/CPackNSIS.cmake
@@ -8,11 +8,6 @@
##end
#
##variable
-# CPACK_PACKAGE_INSTALL_REGISTRY_KEY - Registry key used when
-# installing this project.
-##end
-#
-##variable
# CPACK_NSIS_INSTALL_ROOT - The default installation directory presented
# to the end user by the NSIS installer is under this root dir. The full
# directory presented to the end user is:
@@ -20,18 +15,19 @@
##end
#
##variable
-# CPACK_NSIS_MUI_ICON - The icon file (.ico) for the generated
+# CPACK_NSIS_MUI_ICON - An icon filename.
+# The name of a *.ico file used as the main icon for the generated
# install program.
##end
#
##variable
-# CPACK_NSIS_MUI_UNIICON - The icon file (.ico) for the generated
+# CPACK_NSIS_MUI_UNIICON - An icon filename.
+# The name of a *.ico file used as the main icon for the generated
# uninstall program.
##end
#
##variable
-# CPACK_PACKAGE_ICON - A branding image that will be displayed inside
-# the installer.
+# CPACK_NSIS_INSTALLER_MUI_ICON_CODE - undocumented.
##end
#
##variable
@@ -50,7 +46,8 @@
##end
#
##variable
-# CPACK_NSIS_MODIFY_PATH - If this is set to "ON", then an extra page
+# CPACK_NSIS_MODIFY_PATH - Modify PATH toggle.
+# If this is set to "ON", then an extra page
# will appear in the installer that will allow the user to choose
# whether the program directory should be added to the system PATH
# variable.
@@ -107,6 +104,15 @@
# CPACK_NSIS_MUI_FINISHPAGE_RUN - Specify an executable to add an option
# to run on the finish page of the NSIS installer.
##end
+##variable
+# CPACK_NSIS_MENU_LINKS - Specify links in [application] menu.
+# This should contain a list of pair "link" "link name". The link
+# may be an URL or a path relative to installation prefix.
+# Like:
+# set(CPACK_NSIS_MENU_LINKS
+# "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake.html" "CMake Help"
+# "http://www.cmake.org" "CMake Web Site")
+##end
#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake
index 442d7c4..cba746f 100644
--- a/Modules/CPackRPM.cmake
+++ b/Modules/CPackRPM.cmake
@@ -899,6 +899,7 @@ IF(RPMBUILD_EXECUTABLE)
# Now call rpmbuild using the SPECFILE
EXECUTE_PROCESS(
COMMAND "${RPMBUILD_EXECUTABLE}" -bb
+ --define "_topdir ${CPACK_RPM_DIRECTORY}"
--buildroot "${CPACK_RPM_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}"
"${CPACK_RPM_BINARY_SPECFILE}"
WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}${CPACK_RPM_PACKAGE_COMPONENT_PART_PATH}"
diff --git a/Modules/CTestTargets.cmake b/Modules/CTestTargets.cmake
index d66874d..bc4d964 100644
--- a/Modules/CTestTargets.cmake
+++ b/Modules/CTestTargets.cmake
@@ -69,7 +69,7 @@ IF(NOT _CTEST_TARGETS_ADDED)
ENDFOREACH(mode)
# For Makefile generators add more granular targets.
- IF("${CMAKE_GENERATOR}" MATCHES Make)
+ IF("${CMAKE_GENERATOR}" MATCHES "(Ninja|Make)")
# Make targets for Experimental builds
FOREACH(mode Nightly Experimental Continuous)
FOREACH(testtype
@@ -83,7 +83,7 @@ IF(NOT _CTEST_TARGETS_ADDED)
SET_PROPERTY(TARGET ${mode}${testtype} PROPERTY FOLDER "CTestDashboardTargets")
ENDFOREACH(testtype)
ENDFOREACH(mode)
- ENDIF("${CMAKE_GENERATOR}" MATCHES Make)
+ ENDIF("${CMAKE_GENERATOR}" MATCHES "(Ninja|Make)")
# If requested, add an alias that is the equivalent of the built-in "test"
# or "RUN_TESTS" target:
diff --git a/Modules/CheckIncludeFiles.cmake b/Modules/CheckIncludeFiles.cmake
index 642d962..a94644e 100644
--- a/Modules/CheckIncludeFiles.cmake
+++ b/Modules/CheckIncludeFiles.cmake
@@ -13,7 +13,7 @@
# CMAKE_REQUIRED_INCLUDES = list of include directories
#=============================================================================
-# Copyright 2003-2009 Kitware, Inc.
+# Copyright 2003-2012 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
@@ -44,7 +44,17 @@ MACRO(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
CONFIGURE_FILE("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
"${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFiles.c" @ONLY IMMEDIATE)
- MESSAGE(STATUS "Looking for include files ${INCLUDE}")
+ SET(_INCLUDE ${INCLUDE}) # remove empty elements
+ IF("${_INCLUDE}" MATCHES "^([^;]+);.+;([^;]+)$")
+ LIST(LENGTH _INCLUDE _INCLUDE_LEN)
+ SET(_description "${_INCLUDE_LEN} include files ${CMAKE_MATCH_1}, ..., ${CMAKE_MATCH_2}")
+ ELSEIF("${_INCLUDE}" MATCHES "^([^;]+);([^;]+)$")
+ SET(_description "include files ${CMAKE_MATCH_1}, ${CMAKE_MATCH_2}")
+ ELSE()
+ SET(_description "include file ${_INCLUDE}")
+ ENDIF()
+
+ MESSAGE(STATUS "Looking for ${_description}")
TRY_COMPILE(${VARIABLE}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFiles.c
@@ -54,14 +64,14 @@ MACRO(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
"${CHECK_INCLUDE_FILES_INCLUDE_DIRS}"
OUTPUT_VARIABLE OUTPUT)
IF(${VARIABLE})
- MESSAGE(STATUS "Looking for include files ${INCLUDE} - found")
+ MESSAGE(STATUS "Looking for ${_description} - found")
SET(${VARIABLE} 1 CACHE INTERNAL "Have include ${INCLUDE}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Determining if files ${INCLUDE} "
"exist passed with the following output:\n"
"${OUTPUT}\n\n")
ELSE(${VARIABLE})
- MESSAGE(STATUS "Looking for include files ${INCLUDE} - not found.")
+ MESSAGE(STATUS "Looking for ${_description} - not found.")
SET(${VARIABLE} "" CACHE INTERNAL "Have includes ${INCLUDE}")
FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if files ${INCLUDE} "
diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake
index 8d6f5df..c74c179 100644
--- a/Modules/Compiler/GNU.cmake
+++ b/Modules/Compiler/GNU.cmake
@@ -24,6 +24,18 @@ macro(__compiler_gnu lang)
set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
+ # Older versions of gcc (< 4.5) contain a bug causing them to report a missing
+ # header file as a warning if depfiles are enabled, causing check_header_file
+ # tests to always succeed. Work around this by disabling dependency tracking
+ # in try_compile mode.
+ GET_PROPERTY(_IN_TC GLOBAL PROPERTY IN_TRY_COMPILE)
+ if(NOT _IN_TC OR CMAKE_FORCE_DEPFILES)
+ # distcc does not transform -o to -MT when invoking the preprocessor
+ # internally, as it ought to. Work around this bug by setting -MT here
+ # even though it isn't strictly necessary.
+ set(CMAKE_DEPFILE_FLAGS_${lang} "-MMD -MT <OBJECT> -MF <DEPFILE>")
+ endif()
+
# Initial configuration flags.
set(CMAKE_${lang}_FLAGS_INIT "")
set(CMAKE_${lang}_FLAGS_DEBUG_INIT "-g")
diff --git a/Modules/DeployQt4.cmake b/Modules/DeployQt4.cmake
index 83f322c..b37695d 100644
--- a/Modules/DeployQt4.cmake
+++ b/Modules/DeployQt4.cmake
@@ -82,6 +82,7 @@
include(BundleUtilities)
set(DeployQt4_cmake_dir "${CMAKE_CURRENT_LIST_DIR}")
+set(DeployQt4_apple_plugins_dir "PlugIns")
function(write_qt4_conf qt_conf_dir qt_conf_contents)
set(qt_conf_path "${qt_conf_dir}/qt.conf")
@@ -125,11 +126,17 @@ function(fixup_qt4_executable executable)
if(QT_LIBRARY_DIR)
list(APPEND dirs "${QT_LIBRARY_DIR}")
endif()
+ if(QT_BINARY_DIR)
+ list(APPEND dirs "${QT_BINARY_DIR}")
+ endif()
if(APPLE)
set(qt_conf_dir "${executable}/Contents/Resources")
set(executable_path "${executable}")
set(write_qt_conf TRUE)
+ if(NOT plugins_dir)
+ set(plugins_dir "${DeployQt4_apple_plugins_dir}")
+ endif()
else()
get_filename_component(executable_path "${executable}" PATH)
if(NOT executable_path)
@@ -141,7 +148,7 @@ function(fixup_qt4_executable executable)
foreach(plugin ${qtplugins})
set(installed_plugin_path "")
- install_qt4_plugin("${plugin}" "${plugins_dir}" "${executable}" 1 installed_plugin_path)
+ install_qt4_plugin("${plugin}" "${executable}" 1 installed_plugin_path)
list(APPEND libs ${installed_plugin_path})
endforeach()
@@ -166,23 +173,19 @@ function(install_qt4_plugin_path plugin executable copy installed_plugin_path_va
set(component ${ARGV5})
set(configurations ${ARGV6})
if(EXISTS "${plugin}")
- if(plugins_dir)
- set(plugins_dir "${plugins_dir}")
- else()
- if(APPLE)
- set(plugins_dir "PlugIns")
- else()
- set(plugins_dir "plugins")
- endif()
- endif()
if(APPLE)
+ if(NOT plugins_dir)
+ set(plugins_dir "${DeployQt4_apple_plugins_dir}")
+ endif()
set(plugins_path "${executable}/Contents/${plugins_dir}")
else()
- get_filename_component(executable_path "${executable}" PATH)
- if(NOT executable_path)
- set(executable_path ".")
+ get_filename_component(plugins_path "${executable}" PATH)
+ if(NOT plugins_path)
+ set(plugins_path ".")
+ endif()
+ if(plugins_dir)
+ set(plugins_path "${plugins_path}/${plugins_dir}")
endif()
- set(plugins_path "${executable_path}/${plugins_dir}")
endif()
set(plugin_group "")
@@ -210,7 +213,7 @@ function(install_qt4_plugin_path plugin executable copy installed_plugin_path_va
endif()
install(FILES "${plugin}" DESTINATION "${plugins_path}" ${configurations} ${component})
endif()
- set(${installed_plugin_path_var} ${${installed_path_var}} "${plugins_path}/${plugin_name}" PARENT_SCOPE)
+ set(${installed_plugin_path_var} "${plugins_path}/${plugin_name}" PARENT_SCOPE)
endif()
endfunction()
@@ -220,11 +223,7 @@ function(install_qt4_plugin plugin executable copy installed_plugin_path_var)
if(EXISTS "${plugin}")
install_qt4_plugin_path("${plugin}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}")
else()
- if(QT_IS_STATIC)
- string(TOUPPER "QT_${plugin}_LIBRARY" plugin_var)
- else()
- string(TOUPPER "QT_${plugin}_PLUGIN" plugin_var)
- endif()
+ string(TOUPPER "QT_${plugin}_PLUGIN" plugin_var)
set(plugin_release_var "${plugin_var}_RELEASE")
set(plugin_debug_var "${plugin_var}_DEBUG")
set(plugin_release "${${plugin_release_var}}")
@@ -232,10 +231,24 @@ function(install_qt4_plugin plugin executable copy installed_plugin_path_var)
if(DEFINED "${plugin_release_var}" AND DEFINED "${plugin_debug_var}" AND NOT EXISTS "${plugin_release}" AND NOT EXISTS "${plugin_debug}")
message(WARNING "Qt plugin \"${plugin}\" not recognized or found.")
endif()
- install_qt4_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}" "Release|RelWithDebInfo|MinSizeRel")
- install_qt4_plugin_path("${plugin_debug}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}" "Debug")
+ if(NOT EXISTS "${${plugin_debug_var}}")
+ set(plugin_debug "${plugin_release}")
+ endif()
+
+ if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
+ install_qt4_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}_release" "${plugins_dir}" "${component}" "Release|RelWithDebInfo|MinSizeRel")
+ install_qt4_plugin_path("${plugin_debug}" "${executable}" "${copy}" "${installed_plugin_path_var}_debug" "${plugins_dir}" "${component}" "Debug")
+
+ if(CMAKE_BUILD_TYPE MATCHES "^Debug$")
+ set(${installed_plugin_path_var} ${${installed_plugin_path_var}_debug})
+ else()
+ set(${installed_plugin_path_var} ${${installed_plugin_path_var}_release})
+ endif()
+ else()
+ install_qt4_plugin_path("${plugin_release}" "${executable}" "${copy}" "${installed_plugin_path_var}" "${plugins_dir}" "${component}")
+ endif()
endif()
- set(installed_plugin_path_var "${installed_plugin_path_var}" PARENT_SCOPE)
+ set(${installed_plugin_path_var} ${${installed_plugin_path_var}} PARENT_SCOPE)
endfunction()
function(install_qt4_executable executable)
@@ -248,6 +261,9 @@ function(install_qt4_executable executable)
if(QT_LIBRARY_DIR)
list(APPEND dirs "${QT_LIBRARY_DIR}")
endif()
+ if(QT_BINARY_DIR)
+ list(APPEND dirs "${QT_BINARY_DIR}")
+ endif()
if(component)
set(component COMPONENT ${component})
else()
@@ -264,16 +280,16 @@ function(install_qt4_executable executable)
set(qt_plugins_dir "")
endif()
- if(NOT qtplugins AND QT_LIBRARIES_PLUGINS)
- set(qtplugins "${QT_LIBRARIES_PLUGINS}")
+ if(QT_IS_STATIC)
+ message(WARNING "Qt built statically: not installing plugins.")
+ else()
+ foreach(plugin ${qtplugins})
+ set(installed_plugin_paths "")
+ install_qt4_plugin("${plugin}" "${executable}" 0 installed_plugin_paths "${plugins_dir}" "${component}")
+ list(APPEND libs ${installed_plugin_paths})
+ endforeach()
endif()
- foreach(plugin ${qtplugins})
- set(installed_plugin_paths "")
- install_qt4_plugin("${plugin}" "${executable}" 0 installed_plugin_paths "${plugins_dir}" "${component}")
- list(APPEND libs ${installed_plugin_paths})
- endforeach()
-
resolve_qt4_paths(libs)
install(CODE
diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake
index fb55d3b..b6fe190 100644
--- a/Modules/ExternalProject.cmake
+++ b/Modules/ExternalProject.cmake
@@ -833,6 +833,12 @@ function(ExternalProject_Add_StepTargets name)
foreach(step ${steps})
add_custom_target(${name}-${step}
DEPENDS ${stamp_dir}${cfgdir}/${name}-${step})
+
+ # Depend on other external projects (target-level).
+ get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
+ foreach(arg IN LISTS deps)
+ add_dependencies(${name}-${step} ${arg})
+ endforeach()
endforeach()
endfunction(ExternalProject_Add_StepTargets)
@@ -1451,9 +1457,18 @@ function(ExternalProject_Add name)
# depends on the 'done' mark so that it rebuilds when this project
# rebuilds. It is important that 'done' is not the output of any
# custom command so that CMake does not propagate build rules to
- # other external project targets.
+ # other external project targets, which may cause problems during
+ # parallel builds. However, the Ninja generator needs to see the entire
+ # dependency graph, and can cope with custom commands belonging to
+ # multiple targets, so we add the 'done' mark as an output for Ninja only.
+ set(complete_outputs ${cmf_dir}${cfgdir}/${name}-complete)
+ if(${CMAKE_GENERATOR} MATCHES "Ninja")
+ set(complete_outputs
+ ${complete_outputs} ${stamp_dir}${cfgdir}/${name}-done)
+ endif()
+
add_custom_command(
- OUTPUT ${cmf_dir}${cfgdir}/${name}-complete
+ OUTPUT ${complete_outputs}
COMMENT "Completed '${name}'"
COMMAND ${CMAKE_COMMAND} -E make_directory ${cmf_dir}${cfgdir}
COMMAND ${CMAKE_COMMAND} -E touch ${cmf_dir}${cfgdir}/${name}-complete
diff --git a/Modules/FindBoost.cmake b/Modules/FindBoost.cmake
index 9c03b3d..7504ea4 100644
--- a/Modules/FindBoost.cmake
+++ b/Modules/FindBoost.cmake
@@ -65,7 +65,8 @@
# 1.33, 1.33.0, 1.33.1, 1.34, 1.34.0, 1.34.1, 1.35, 1.35.0, 1.35.1,
# 1.36, 1.36.0, 1.36.1, 1.37, 1.37.0, 1.38, 1.38.0, 1.39, 1.39.0,
# 1.40, 1.40.0, 1.41, 1.41.0, 1.42, 1.42.0, 1.43, 1.43.0, 1.44, 1.44.0,
-# 1.45, 1.45.0, 1.46, 1.46.0, 1.46.1, 1.47, 1.47.0, 1.48, 1.48.0
+# 1.45, 1.45.0, 1.46, 1.46.0, 1.46.1, 1.47, 1.47.0, 1.48, 1.48.0,
+# 1.49, 1.49.0, 1.50, 1.50.0
#
# NOTE: If you add a new major 1.x version in Boost_ADDITIONAL_VERSIONS you should
# add both 1.x and 1.x.0 as shown above. Official Boost include directories
@@ -449,7 +450,7 @@ else(Boost_FIND_VERSION_EXACT)
# The user has not requested an exact version. Among known
# versions, find those that are acceptable to the user request.
set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS}
- "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1"
+ "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1"
"1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42"
"1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37"
"1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0"
diff --git a/Modules/FindCxxTest.cmake b/Modules/FindCxxTest.cmake
index 4ff310c..a4d1504 100644
--- a/Modules/FindCxxTest.cmake
+++ b/Modules/FindCxxTest.cmake
@@ -9,6 +9,7 @@
# Only used in the case both Python & Perl
# are detected on the system to control
# which CxxTest code generator is used.
+# Valid only for CxxTest version 3.
#
# NOTE: In older versions of this Find Module,
# this variable controlled if the Python test
@@ -159,7 +160,8 @@ find_package(PythonInterp QUIET)
find_package(Perl QUIET)
find_path(CXXTEST_INCLUDE_DIR cxxtest/TestSuite.h)
-find_program(CXXTEST_PYTHON_TESTGEN_EXECUTABLE cxxtestgen.py
+find_program(CXXTEST_PYTHON_TESTGEN_EXECUTABLE
+ NAMES cxxtestgen cxxtestgen.py
PATHS ${CXXTEST_INCLUDE_DIR})
find_program(CXXTEST_PERL_TESTGEN_EXECUTABLE cxxtestgen.pl
PATHS ${CXXTEST_INCLUDE_DIR})
@@ -167,7 +169,7 @@ find_program(CXXTEST_PERL_TESTGEN_EXECUTABLE cxxtestgen.pl
if(PYTHONINTERP_FOUND OR PERL_FOUND)
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
- if(PYTHONINTERP_FOUND AND (CXXTEST_USE_PYTHON OR NOT PERL_FOUND))
+ if(PYTHONINTERP_FOUND AND (CXXTEST_USE_PYTHON OR NOT PERL_FOUND OR NOT DEFINED CXXTEST_USE_PYTHON))
set(CXXTEST_TESTGEN_EXECUTABLE ${CXXTEST_PYTHON_TESTGEN_EXECUTABLE})
set(CXXTEST_TESTGEN_INTERPRETER ${PYTHON_EXECUTABLE})
FIND_PACKAGE_HANDLE_STANDARD_ARGS(CxxTest DEFAULT_MSG
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index 1be4ccf..ae50ca7 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -354,6 +354,20 @@ function (interrogate_mpi_compiler lang try_libs)
# Extract the set of libraries to link against from the link command
# line
string(REGEX MATCHALL "(^| )-l([^\" ]+|\"[^\"]+\")" MPI_LIBNAMES "${MPI_LINK_CMDLINE}")
+ # add the compiler implicit directories because some compilers
+ # such as the intel compiler have libraries that show up
+ # in the showme list that can only be found in the implicit
+ # link directories of the compiler. Do this for C++ and C
+ # compilers if the implicit link directories are defined.
+ if (DEFINED CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES)
+ set(MPI_LINK_PATH
+ "${MPI_LINK_PATH};${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}")
+ endif ()
+
+ if (DEFINED CMAKE_C_IMPLICIT_LINK_DIRECTORIES)
+ set(MPI_LINK_PATH
+ "${MPI_LINK_PATH};${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}")
+ endif ()
# Determine full path names for all of the libraries that one needs
# to link against in an MPI program
diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake
index b503357..cdcf9ca 100644
--- a/Modules/FindPackageHandleStandardArgs.cmake
+++ b/Modules/FindPackageHandleStandardArgs.cmake
@@ -19,7 +19,8 @@
#
# The second mode is more powerful and also supports version checking:
# FIND_PACKAGE_HANDLE_STANDARD_ARGS(NAME [REQUIRED_VARS <var1>...<varN>]
-# [VERSION_VAR <versionvar>
+# [VERSION_VAR <versionvar>]
+# [HANDLE_COMPONENTS]
# [CONFIG_MODE]
# [FAIL_MESSAGE "Custom failure message"] )
#
@@ -32,6 +33,11 @@
# in the find_package() call. The EXACT keyword is also handled. The default
# messages include information about the required version and the version
# which has been actually found, both if the version is ok or not.
+# If the package supports components, use the HANDLE_COMPONENTS option to enable
+# handling them. In this case, find_package_handle_standard_args() will report
+# which components have been found and which are missing, and the <NAME>_FOUND
+# variable will be set to FALSE if any of the required components (i.e. not the
+# ones listed after OPTIONAL_COMPONENTS) are missing.
# Use the option CONFIG_MODE if your FindXXX.cmake module is a wrapper for
# a find_package(... NO_MODULE) call. In this case VERSION_VAR will be set
# to <NAME>_VERSION and the macro will automatically check whether the
@@ -128,7 +134,7 @@ FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
# set up the arguments for CMAKE_PARSE_ARGUMENTS and check whether we are in
# new extended or in the "old" mode:
- SET(options CONFIG_MODE)
+ SET(options CONFIG_MODE HANDLE_COMPONENTS)
SET(oneValueArgs FAIL_MESSAGE VERSION_VAR)
SET(multiValueArgs REQUIRED_VARS)
SET(_KEYWORDS_FOR_EXTENDED_MODE ${options} ${oneValueArgs} ${multiValueArgs} )
@@ -189,6 +195,36 @@ FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
ENDIF(NOT ${_CURRENT_VAR})
ENDFOREACH(_CURRENT_VAR)
+ # component handling
+ UNSET(FOUND_COMPONENTS_MSG)
+ UNSET(MISSING_COMPONENTS_MSG)
+
+ IF(FPHSA_HANDLE_COMPONENTS)
+ FOREACH(comp ${${_NAME}_FIND_COMPONENTS})
+ IF(${_NAME}_${comp}_FOUND)
+
+ IF(NOT DEFINED FOUND_COMPONENTS_MSG)
+ SET(FOUND_COMPONENTS_MSG "found components: ")
+ ENDIF()
+ SET(FOUND_COMPONENTS_MSG "${FOUND_COMPONENTS_MSG} ${comp}")
+
+ ELSE()
+
+ IF(NOT DEFINED MISSING_COMPONENTS_MSG)
+ SET(MISSING_COMPONENTS_MSG "missing components: ")
+ ENDIF()
+ SET(MISSING_COMPONENTS_MSG "${MISSING_COMPONENTS_MSG} ${comp}")
+
+ IF(${_NAME}_FIND_REQUIRED_${comp})
+ SET(${_NAME_UPPER}_FOUND FALSE)
+ SET(MISSING_VARS "${MISSING_VARS} ${comp}")
+ ENDIF()
+
+ ENDIF()
+ ENDFOREACH(comp)
+ SET(COMPONENT_MSG "${FOUND_COMPONENTS_MSG} ${MISSING_COMPONENTS_MSG}")
+ SET(DETAILS "${DETAILS}[c${COMPONENT_MSG}]")
+ ENDIF(FPHSA_HANDLE_COMPONENTS)
# version handling:
SET(VERSION_MSG "")
@@ -240,7 +276,7 @@ FUNCTION(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
# print the result:
IF (${_NAME_UPPER}_FOUND)
- FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG}" "${DETAILS}")
+ FIND_PACKAGE_MESSAGE(${_NAME} "Found ${_NAME}: ${${_FIRST_REQUIRED_VAR}} ${VERSION_MSG} ${COMPONENT_MSG}" "${DETAILS}")
ELSE (${_NAME_UPPER}_FOUND)
IF(FPHSA_CONFIG_MODE)
diff --git a/Modules/FindQt3.cmake b/Modules/FindQt3.cmake
index 86236cc..2d8dbde 100644
--- a/Modules/FindQt3.cmake
+++ b/Modules/FindQt3.cmake
@@ -1,10 +1,11 @@
# - Locate Qt include paths and libraries
# This module defines:
-# QT_INCLUDE_DIR - where to find qt.h, etc.
-# QT_LIBRARIES - the libraries to link against to use Qt.
-# QT_DEFINITIONS - definitions to use when
-# compiling code that uses Qt.
-# QT_FOUND - If false, don't try to use Qt.
+# QT_INCLUDE_DIR - where to find qt.h, etc.
+# QT_LIBRARIES - the libraries to link against to use Qt.
+# QT_DEFINITIONS - definitions to use when
+# compiling code that uses Qt.
+# QT_FOUND - If false, don't try to use Qt.
+# QT_VERSION_STRING - the version of Qt found
#
# If you need the multithreaded version of Qt, set QT_MT_REQUIRED to TRUE
#
@@ -46,13 +47,16 @@ IF(QT4_FOUND)
ENDIF(QT4_FOUND)
-FILE(GLOB GLOB_PATHS_BIN /usr/lib/qt-3*/bin/)
+FILE(GLOB GLOB_PATHS /usr/lib/qt-3*)
+FOREACH(GLOB_PATH ${GLOB_PATHS})
+ LIST(APPEND GLOB_PATHS_BIN "${GLOB_PATH}/bin")
+ENDFOREACH(GLOB_PATH)
FIND_PATH(QT_INCLUDE_DIR qt.h
"[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.2.1;InstallDir]/include/Qt"
"[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.2.0;InstallDir]/include/Qt"
"[HKEY_CURRENT_USER\\Software\\Trolltech\\Qt3Versions\\3.1.0;InstallDir]/include/Qt"
$ENV{QTDIR}/include
- ${GLOB_PATHS_BIN}
+ ${GLOB_PATHS}
/usr/local/qt/include
/usr/lib/qt/include
/usr/lib/qt3/include
@@ -71,12 +75,13 @@ ENDIF(NOT EXISTS ${QT_INCLUDE_DIR}/qglobal.h)
IF(QT_INCLUDE_DIR)
#extract the version string from qglobal.h
FILE(READ ${QT_INCLUDE_DIR}/qglobal.h QGLOBAL_H)
- STRING(REGEX MATCH "#define[\t ]+QT_VERSION_STR[\t ]+\"([0-9]+.[0-9]+.[0-9]+)\"" QGLOBAL_H "${QGLOBAL_H}")
- STRING(REGEX REPLACE ".*\"([0-9]+.[0-9]+.[0-9]+)\".*" "\\1" qt_version_str "${QGLOBAL_H}")
+ STRING(REGEX MATCH "#define[\t ]+QT_VERSION_STR[\t ]+\"[0-9]+.[0-9]+.[0-9]+[a-z]*\"" QGLOBAL_H "${QGLOBAL_H}")
+ STRING(REGEX REPLACE ".*\"([0-9]+.[0-9]+.[0-9]+[a-z]*)\".*" "\\1" qt_version_str "${QGLOBAL_H}")
# Under windows the qt library (MSVC) has the format qt-mtXYZ where XYZ is the
# version X.Y.Z, so we need to remove the dots from version
STRING(REGEX REPLACE "\\." "" qt_version_str_lib "${qt_version_str}")
+ SET(QT_VERSION_STRING "${qt_version_str}")
ENDIF(QT_INCLUDE_DIR)
FILE(GLOB GLOB_PATHS_LIB /usr/lib/qt-3*/lib/)
@@ -195,58 +200,16 @@ IF (WIN32)
)
ENDIF (WIN32)
-
-IF (QT_MIN_VERSION)
-
- STRING(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" qt_major_vers "${qt_version_str}")
- STRING(REGEX REPLACE "[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" qt_minor_vers "${qt_version_str}")
- STRING(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" qt_patch_vers "${qt_version_str}")
-
- #now parse the parts of the user given version string into variables
- STRING(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+$" req_qt_major_vers "${QT_MIN_VERSION}")
- IF (NOT req_qt_major_vers)
- error_message( "Invalid Qt version string given: \"${QT_MIN_VERSION}\", expected e.g. \"3.1.5\"")
- ENDIF (NOT req_qt_major_vers)
-
- STRING(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" req_qt_major_vers "${QT_MIN_VERSION}")
- STRING(REGEX REPLACE "[0-9]+\\.([0-9])+\\.[0-9]+" "\\1" req_qt_minor_vers "${QT_MIN_VERSION}")
- STRING(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" req_qt_patch_vers "${QT_MIN_VERSION}")
-
- # req = "6.5.4", qt = "3.2.1"
- MACRO(error_message msg)
- IF(QT3_REQUIRED)
- MESSAGE( FATAL_ERROR ${msg})
- ELSE(QT3_REQUIRED)
- MESSAGE( STATUS ${msg})
- ENDIF(QT3_REQUIRED)
- ENDMACRO(error_message)
-
- IF (req_qt_major_vers GREATER qt_major_vers) # (6 > 3) ?
- ERROR_MESSAGE( "Qt major version not matched (required: ${QT_MIN_VERSION}, found: ${qt_version_str})") # yes
- ELSE (req_qt_major_vers GREATER qt_major_vers) # no
- IF (req_qt_major_vers LESS qt_major_vers) # (6 < 3) ?
- SET( QT_VERSION_BIG_ENOUGH "YES" ) # yes
- ELSE (req_qt_major_vers LESS qt_major_vers) # ( 6==3) ?
- IF (req_qt_minor_vers GREATER qt_minor_vers) # (5>2) ?
- ERROR_MESSAGE( "Qt minor version not matched (required: ${QT_MIN_VERSION}, found: ${qt_version_str})") # yes
- ELSE (req_qt_minor_vers GREATER qt_minor_vers) # no
- IF (req_qt_minor_vers LESS qt_minor_vers) # (5<2) ?
- SET( QT_VERSION_BIG_ENOUGH "YES" ) # yes
- ELSE (req_qt_minor_vers LESS qt_minor_vers) # (5==2)
- IF (req_qt_patch_vers GREATER qt_patch_vers) # (4>1) ?
- ERROR_MESSAGE( "Qt patch level not matched (required: ${QT_MIN_VERSION}, found: ${qt_version_str})") # yes
- ELSE (req_qt_patch_vers GREATER qt_patch_vers) # (4>1) ?
- SET( QT_VERSION_BIG_ENOUGH "YES" ) # yes
- ENDIF (req_qt_patch_vers GREATER qt_patch_vers) # (4>1) ?
- ENDIF (req_qt_minor_vers LESS qt_minor_vers)
- ENDIF (req_qt_minor_vers GREATER qt_minor_vers)
- ENDIF (req_qt_major_vers LESS qt_major_vers)
- ENDIF (req_qt_major_vers GREATER qt_major_vers)
-ENDIF (QT_MIN_VERSION)
+#support old QT_MIN_VERSION if set, but not if version is supplied by find_package()
+IF(NOT Qt3_FIND_VERSION AND QT_MIN_VERSION)
+ SET(Qt3_FIND_VERSION ${QT_MIN_VERSION})
+ENDIF(NOT Qt3_FIND_VERSION AND QT_MIN_VERSION)
# if the include a library are found then we have it
INCLUDE(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(Qt3 DEFAULT_MSG QT_QT_LIBRARY QT_INCLUDE_DIR QT_MOC_EXECUTABLE)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Qt3
+ REQUIRED_VARS QT_QT_LIBRARY QT_INCLUDE_DIR QT_MOC_EXECUTABLE
+ VERSION_VAR QT_VERSION_STRING)
SET(QT_FOUND ${QT3_FOUND} )
IF(QT_FOUND)
@@ -296,8 +259,16 @@ IF(QT_FOUND)
ENDIF(QT_QT_LIBRARY MATCHES "qt-mt")
ENDIF(QT_FOUND)
-EXEC_PROGRAM(${QT_MOC_EXECUTABLE} ARGS "-v" OUTPUT_VARIABLE QTVERSION_MOC)
-EXEC_PROGRAM(${QT_UIC_EXECUTABLE} ARGS "-version" OUTPUT_VARIABLE QTVERSION_UIC)
+IF(QT_MOC_EXECUTABLE)
+ EXECUTE_PROCESS(COMMAND ${QT_MOC_EXECUTABLE} "-v"
+ OUTPUT_VARIABLE QTVERSION_MOC
+ ERROR_QUIET)
+ENDIF(QT_MOC_EXECUTABLE)
+IF(QT_UIC_EXECUTABLE)
+ EXECUTE_PROCESS(COMMAND ${QT_UIC_EXECUTABLE} "-version"
+ OUTPUT_VARIABLE QTVERSION_UIC
+ ERROR_QUIET)
+ENDIF(QT_UIC_EXECUTABLE)
SET(_QT_UIC_VERSION_3 FALSE)
IF("${QTVERSION_UIC}" MATCHES ".* 3..*")
diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake
index 867c788..f9d37c3 100644
--- a/Modules/Platform/Darwin.cmake
+++ b/Modules/Platform/Darwin.cmake
@@ -6,6 +6,8 @@ SET(APPLE 1)
# 8.x == Mac OSX 10.4 (Tiger)
# 9.x == Mac OSX 10.5 (Leopard)
# 10.x == Mac OSX 10.6 (Snow Leopard)
+# 11.x == Mac OSX 10.7 (Lion)
+# 12.x == Mac OSX 10.8 (Mountain Lion)
STRING(REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_SYSTEM_VERSION}")
STRING(REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\2" DARWIN_MINOR_VERSION "${CMAKE_SYSTEM_VERSION}")
@@ -54,24 +56,31 @@ SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a")
# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex
IF(NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
FIND_PROGRAM(CMAKE_INSTALL_NAME_TOOL install_name_tool)
+ MARK_AS_ADVANCED(CMAKE_INSTALL_NAME_TOOL)
ENDIF(NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
# Set the assumed (Pre 10.5 or Default) location of the developer tools
SET(OSX_DEVELOPER_ROOT "/Developer")
+# Use the xcode-select tool if it's available (Xcode >= 3.0 installations)
+FIND_PROGRAM(CMAKE_XCODE_SELECT xcode-select)
+MARK_AS_ADVANCED(CMAKE_XCODE_SELECT)
+IF(CMAKE_XCODE_SELECT)
+ EXECUTE_PROCESS(COMMAND ${CMAKE_XCODE_SELECT} "-print-path"
+ OUTPUT_VARIABLE OSX_DEVELOPER_ROOT
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ENDIF(CMAKE_XCODE_SELECT)
+
# Find installed SDKs
-FILE(GLOB _CMAKE_OSX_SDKS "${OSX_DEVELOPER_ROOT}/SDKs/*")
+# Start with Xcode-4.3+ default SDKs directory
+SET(_CMAKE_OSX_SDKS_DIR
+ "${OSX_DEVELOPER_ROOT}/Platforms/MacOSX.platform/Developer/SDKs")
+FILE(GLOB _CMAKE_OSX_SDKS "${_CMAKE_OSX_SDKS_DIR}/*")
-# If nothing is found there, then try locating the dev tools based on the xcode-select tool
-# (available in Xcode >= 3.0 installations)
+# If not present, try pre-4.3 SDKs directory
IF(NOT _CMAKE_OSX_SDKS)
- FIND_PROGRAM(CMAKE_XCODE_SELECT xcode-select)
- IF(CMAKE_XCODE_SELECT)
- EXECUTE_PROCESS(COMMAND ${CMAKE_XCODE_SELECT} "-print-path"
- OUTPUT_VARIABLE OSX_DEVELOPER_ROOT
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- FILE(GLOB _CMAKE_OSX_SDKS "${OSX_DEVELOPER_ROOT}/SDKs/*")
- ENDIF(CMAKE_XCODE_SELECT)
+SET(_CMAKE_OSX_SDKS_DIR "${OSX_DEVELOPER_ROOT}/SDKs")
+ FILE(GLOB _CMAKE_OSX_SDKS "${_CMAKE_OSX_SDKS_DIR}/*")
ENDIF(NOT _CMAKE_OSX_SDKS)
EXECUTE_PROCESS(COMMAND sw_vers -productVersion
@@ -103,16 +112,16 @@ SET(ENV_SDKROOT "$ENV{SDKROOT}")
# Set CMAKE_OSX_SYSROOT_DEFAULT based on _CURRENT_OSX_VERSION,
# accounting for the known specially named SDKs.
SET(CMAKE_OSX_SYSROOT_DEFAULT
- "${OSX_DEVELOPER_ROOT}/SDKs/MacOSX${_CURRENT_OSX_VERSION}.sdk")
+ "${_CMAKE_OSX_SDKS_DIR}/MacOSX${_CURRENT_OSX_VERSION}.sdk")
IF(_CURRENT_OSX_VERSION STREQUAL "10.4")
SET(CMAKE_OSX_SYSROOT_DEFAULT
- "${OSX_DEVELOPER_ROOT}/SDKs/MacOSX10.4u.sdk")
+ "${_CMAKE_OSX_SDKS_DIR}/MacOSX10.4u.sdk")
ENDIF(_CURRENT_OSX_VERSION STREQUAL "10.4")
IF(_CURRENT_OSX_VERSION STREQUAL "10.3")
SET(CMAKE_OSX_SYSROOT_DEFAULT
- "${OSX_DEVELOPER_ROOT}/SDKs/MacOSX10.3.9.sdk")
+ "${_CMAKE_OSX_SDKS_DIR}/MacOSX10.3.9.sdk")
ENDIF(_CURRENT_OSX_VERSION STREQUAL "10.3")
# Use environment or default as initial cache value:
@@ -232,10 +241,22 @@ SET(CMAKE_SYSTEM_FRAMEWORK_PATH
# default to searching for application bundles first
SET(CMAKE_FIND_APPBUNDLE FIRST)
# set up the default search directories for application bundles
+SET(_apps_paths)
+FOREACH(_path
+ "~/Applications"
+ "/Applications"
+ "${OSX_DEVELOPER_ROOT}/../Applications" # Xcode 4.3+
+ "${OSX_DEVELOPER_ROOT}/Applications" # pre-4.3
+ )
+ GET_FILENAME_COMPONENT(_apps "${_path}" ABSOLUTE)
+ IF(EXISTS "${_apps}")
+ LIST(APPEND _apps_paths "${_apps}")
+ ENDIF()
+ENDFOREACH()
+LIST(REMOVE_DUPLICATES _apps_paths)
SET(CMAKE_SYSTEM_APPBUNDLE_PATH
- ~/Applications
- /Applications
- /Developer/Applications)
+ ${_apps_paths})
+UNSET(_apps_paths)
INCLUDE(Platform/UnixPaths)
LIST(APPEND CMAKE_SYSTEM_PREFIX_PATH
diff --git a/Modules/Platform/Windows-cl.cmake b/Modules/Platform/Windows-cl.cmake
index ccccbc9..be6abb6 100644
--- a/Modules/Platform/Windows-cl.cmake
+++ b/Modules/Platform/Windows-cl.cmake
@@ -37,7 +37,7 @@ SET(CMAKE_COMPILE_RESOURCE "rc <FLAGS> /fo<OBJECT> <SOURCE>")
# that is automatically copied into try_compile directories
# by the global generator.
SET(MSVC_IDE 1)
-IF(CMAKE_GENERATOR MATCHES "Makefiles")
+IF(CMAKE_GENERATOR MATCHES "Makefiles" OR CMAKE_GENERATOR MATCHES "Ninja")
SET(MSVC_IDE 0)
IF(NOT CMAKE_VC_COMPILER_TESTS_RUN)
SET(CMAKE_VC_COMPILER_TESTS 1)
@@ -125,7 +125,7 @@ IF(CMAKE_GENERATOR MATCHES "Makefiles")
ENDIF(CMAKE_COMPILER_RETURN)
MAKE_DIRECTORY("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp3")
ENDIF(NOT CMAKE_VC_COMPILER_TESTS_RUN)
-ENDIF(CMAKE_GENERATOR MATCHES "Makefiles")
+ENDIF(CMAKE_GENERATOR MATCHES "Makefiles" OR CMAKE_GENERATOR MATCHES "Ninja")
IF(MSVC_C_ARCHITECTURE_ID MATCHES 64)
SET(CMAKE_CL_64 1)
diff --git a/Modules/Platform/eCos.cmake b/Modules/Platform/eCos.cmake
index f0881c0..b437c1a 100644
--- a/Modules/Platform/eCos.cmake
+++ b/Modules/Platform/eCos.cmake
@@ -1,5 +1,12 @@
# support for eCos http://ecos.sourceware.org
-SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic
+
+# Guard against multiple inclusion, which e.g. leads to multiple calls to add_definition() #12987
+IF(__ECOS_CMAKE_INCLUDED)
+ RETURN()
+ENDIF()
+SET(__ECOS_CMAKE_INCLUDED TRUE)
+
+SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") # +s, flag for exe link to use shared lib
SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "") # -rpath
diff --git a/Modules/WriteBasicConfigVersionFile.cmake b/Modules/WriteBasicConfigVersionFile.cmake
index 0b6519d..038cb57 100644
--- a/Modules/WriteBasicConfigVersionFile.cmake
+++ b/Modules/WriteBasicConfigVersionFile.cmake
@@ -1,31 +1,6 @@
# WRITE_BASIC_CONFIG_VERSION_FILE( filename VERSION major.minor.patch COMPATIBILITY (AnyNewerVersion|SameMajorVersion) )
#
-# Writes a file for use as <package>ConfigVersion.cmake file to <filename>.
-# See the documentation of FIND_PACKAGE() for details on this.
-# filename is the output filename, it should be in the build tree.
-# major.minor.patch is the version number of the project to be installed
-# The COMPATIBILITY mode AnyNewerVersion means that the installed package version
-# will be considered compatible if it is newer or exactly the same as the requested version.
-# If SameMajorVersion is used instead, then the behaviour differs from AnyNewerVersion
-# in that the major version number must be the same as requested, e.g. version 2.0 will
-# not be considered compatible if 1.0 is requested.
-# If your project has more elaborated version matching rules, you will need to write your
-# own custom ConfigVersion.cmake file instead of using this macro.
-#
-# Example:
-# write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
-# VERSION 1.2.3
-# COMPATIBILITY SameMajorVersion )
-# install(FILES ${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
-# ${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
-# DESTINATION lib/cmake/Foo )
-#
-# Internally, this macro executes configure_file() to create the resulting
-# version file. Depending on the COMPATIBLITY, either the file
-# BasicConfigVersion-SameMajorVersion.cmake.in or BasicConfigVersion-AnyNewerVersion.cmake.in
-# is used. Please note that these two files are internal to CMake and you should
-# not call configure_file() on them yourself, but they can be used as starting
-# point to create more sophisticted custom ConfigVersion.cmake files.
+# Deprecated, see WRITE_BASIC_PACKAGE_VERSION_FILE(), it is identical.
#=============================================================================
# Copyright 2008-2011 Alexander Neundorf, <neundorf@kde.org>
diff --git a/Modules/readme.txt b/Modules/readme.txt
index e2d7f06..7d61d8d 100644
--- a/Modules/readme.txt
+++ b/Modules/readme.txt
@@ -57,7 +57,7 @@ For example:
# - This is a cool module
# This module does really cool stuff.
# It can do even more than you think.
-#
+#
# It even needs to paragraphs to tell you about it.
# And it defines the following variables:
# VAR_COOL - this is great isn't it?
@@ -119,17 +119,31 @@ able to find the package. If the
REQUIRED option is given to the command it will set the variable
XXX_FIND_REQUIRED to true before loading the FindXXX.cmake module. If
this variable is set the module should issue a FATAL_ERROR if the
-package cannot be found. For each package-specific component, say
-YYY, listed after the REQUIRED option a variable XXX_FIND_REQUIRED_YYY
-to true. The set of components listed after either the REQUIRED
-option or the COMPONENTS option will be specified in a
-XXX_FIND_COMPONENTS variable. This can be used by the FindXXX.cmake
-module to determine which sub-components of the package must be found.
+package cannot be found.
If neither the QUIET nor REQUIRED options are given then the
FindXXX.cmake module should look for the package and complain without
error if the module is not found.
-To get this behaviour you can use the FIND_PACKAGE_HANDLE_STANDARD_ARGS()
+A package can be provide sub-components.
+Those components can be listed after the COMPONENTS (or REQUIRED)
+or OPTIONAL_COMPONENTS keywords. The set of all listed components will be
+specified in a XXX_FIND_COMPONENTS variable.
+For each package-specific component, say Yyy, a variable XXX_FIND_REQUIRED_Yyy
+will be set to true if it listed after COMPONENTS and it will be set to false
+if it was listed after OPTIONAL_COMPONENTS.
+Using those variables a FindXXX.cmake module and also a XXXConfig.cmake package
+configuration file can determine whether and which components have been requested,
+and whether they were requested as required or as optional.
+For each of the requested components a XXX_Yyy_FOUND variable should be set
+accordingly.
+The per-package XXX_FOUND variable should be only set to true if all requested
+required components have been found. A missing optional component should not
+keep the XXX_FOUND variable from being set to true.
+If the package provides XXX_INCLUDE_DIRS and XXX_LIBRARIES variables, the include
+dirs and libraries for all components which were requested and which have been
+found should be added to those two variables.
+
+To get this behaviour you can use the FIND_PACKAGE_HANDLE_STANDARD_ARGS()
macro, as an example see FindJPEG.cmake.
For internal implementation, it's a generally accepted convention that variables starting with
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 0c420b9..f9d1c03 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -185,6 +185,8 @@ SET(SRCS
cmGeneratedFileStream.cxx
cmGeneratorExpression.cxx
cmGeneratorExpression.h
+ cmGeneratorTarget.cxx
+ cmGeneratorTarget.h
cmGlobalGenerator.cxx
cmGlobalGenerator.h
cmGlobalUnixMakefileGenerator3.cxx
@@ -353,6 +355,36 @@ IF (WIN32)
ENDIF(NOT UNIX)
ENDIF (WIN32)
+# turn on Ninja by default
+set(_CMAKE_DEFAULT_NINJA_VALUE TRUE)
+# turn it off for platforms where it does not pass all the
+# tests
+if(WIN32 OR APPLE)
+ SET(_CMAKE_DEFAULT_NINJA_VALUE FALSE)
+endif()
+SET(CMAKE_ENABLE_NINJA ${_CMAKE_DEFAULT_NINJA_VALUE} CACHE BOOL
+ "Enable the ninja generator for CMake. currently not fully working for Windows or OSX")
+MARK_AS_ADVANCED(CMAKE_ENABLE_NINJA)
+IF(CMAKE_ENABLE_NINJA)
+ MESSAGE(STATUS "Enable ninja generator.")
+ SET(SRCS ${SRCS}
+ cmGlobalNinjaGenerator.cxx
+ cmGlobalNinjaGenerator.h
+ cmNinjaTypes.h
+ cmLocalNinjaGenerator.cxx
+ cmLocalNinjaGenerator.h
+ cmNinjaTargetGenerator.cxx
+ cmNinjaTargetGenerator.h
+ cmNinjaNormalTargetGenerator.cxx
+ cmNinjaNormalTargetGenerator.h
+ cmNinjaUtilityTargetGenerator.cxx
+ cmNinjaUtilityTargetGenerator.h
+ )
+ ADD_DEFINITIONS(-DCMAKE_USE_NINJA)
+ELSE()
+ MESSAGE(STATUS "Disable ninja generator.")
+ENDIF()
+
# create a library used by the command line and the GUI
ADD_LIBRARY(CMakeLib ${SRCS})
TARGET_LINK_LIBRARIES(CMakeLib cmsys
diff --git a/Source/CMakeVersion.bash b/Source/CMakeVersion.bash
new file mode 100755
index 0000000..126adba
--- /dev/null
+++ b/Source/CMakeVersion.bash
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+# Update the version component if it looks like a date or -f is given.
+if test "x$1" = "x-f"; then shift ; n='*' ; else n='\{8\}' ; fi
+if test "$#" -gt 0; then echo 1>&2 "usage: CMakeVersion.bash [-f]"; exit 1; fi
+sed -i -e '
+s/\(^SET(CMake_VERSION_TWEAK\) [0-9]'"$n"'\(.*\)/\1 '"$(date +%Y%m%d)"'\2/
+' "${BASH_SOURCE%/*}/CMakeVersion.cmake"
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
new file mode 100644
index 0000000..33b8f04
--- /dev/null
+++ b/Source/CMakeVersion.cmake
@@ -0,0 +1,6 @@
+# CMake version number components.
+SET(CMake_VERSION_MAJOR 2)
+SET(CMake_VERSION_MINOR 8)
+SET(CMake_VERSION_PATCH 8)
+SET(CMake_VERSION_TWEAK 20120425)
+#SET(CMake_VERSION_RC 1)
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 0ff9050..6e7b8d7 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -247,7 +247,7 @@ int cmCPackArchiveGenerator::PackageFiles()
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Toplevel: "
<< toplevel << std::endl);
- if (SupportsComponentInstallation()) {
+ if (WantsComponentInstallation()) {
// CASE 1 : COMPONENT ALL-IN-ONE package
// If ALL COMPONENTS in ONE package has been requested
// then the package file is unique and should be open here.
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index b707e96..178a18d 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -236,7 +236,7 @@ int cmCPackDebGenerator::PackageFiles()
int retval = -1;
/* Are we in the component packaging case */
- if (SupportsComponentInstallation()) {
+ if (WantsComponentInstallation()) {
// CASE 1 : COMPONENT ALL-IN-ONE package
// If ALL GROUPS or ALL COMPONENTS in ONE package has been requested
// then the package file is unique and should be open here.
diff --git a/Source/CPack/cmCPackDocumentVariables.cxx b/Source/CPack/cmCPackDocumentVariables.cxx
index 23e99f8..d2e3802 100644
--- a/Source/CPack/cmCPackDocumentVariables.cxx
+++ b/Source/CPack/cmCPackDocumentVariables.cxx
@@ -44,14 +44,14 @@ void cmCPackDocumentVariables::DefineVariables(cmake* cm)
"Boolean toggle to make CPack use DESTDIR mechanism when"
" packaging.", "DESTDIR means DESTination DIRectory."
" It is commonly used by makefile "
- "users in order to install software at non-default location. It a"
- "basic relocation mechanism. "
+ "users in order to install software at non-default location. It "
+ "is a basic relocation mechanism. "
"It is usually invoked like this:\n"
" make DESTDIR=/home/john install\n"
"which will install the concerned software using the"
" installation prefix, e.g. \"/usr/local\" prepended with "
"the DESTDIR value which finally gives \"/home/john/usr/local\"."
- " When preparing a package CPack first installs the items to be "
+ " When preparing a package, CPack first installs the items to be "
"packaged in a local (to the build tree) directory by using the "
"same DESTDIR mechanism. Nevertheless, if "
"CPACK_SET_DESTDIR is set then CPack will set DESTDIR before"
@@ -63,7 +63,7 @@ void cmCPackDocumentVariables::DefineVariables(cmake* cm)
"Manually setting CPACK_SET_DESTDIR may help (or simply be"
" necessary) if some install rules uses absolute "
"DESTINATION (see CMake INSTALL command)."
- "However, starting with"
+ " However, starting with"
" CPack/CMake 2.8.3 RPM and DEB installers tries to handle DESTDIR"
" automatically so that it is seldom necessary for the user to set"
" it.", false,
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 3b6135e..6aee401 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -63,6 +63,12 @@ cmCPackDragNDropGenerator::~cmCPackDragNDropGenerator()
//----------------------------------------------------------------------
int cmCPackDragNDropGenerator::InitializeInternal()
{
+ // Starting with Xcode 4.3, look in "/Applications/Xcode.app" first:
+ //
+ std::vector<std::string> paths;
+ paths.push_back("/Applications/Xcode.app/Contents/Developer/Tools");
+ paths.push_back("/Developer/Tools");
+
const std::string hdiutil_path = cmSystemTools::FindProgram("hdiutil",
std::vector<std::string>(), false);
if(hdiutil_path.empty())
@@ -75,7 +81,7 @@ int cmCPackDragNDropGenerator::InitializeInternal()
this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path.c_str());
const std::string setfile_path = cmSystemTools::FindProgram("SetFile",
- std::vector<std::string>(1, "/Developer/Tools"), false);
+ paths, false);
if(setfile_path.empty())
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -86,7 +92,7 @@ int cmCPackDragNDropGenerator::InitializeInternal()
this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path.c_str());
const std::string rez_path = cmSystemTools::FindProgram("Rez",
- std::vector<std::string>(1, "/Developer/Tools"), false);
+ paths, false);
if(rez_path.empty())
{
cmCPackLogger(cmCPackLog::LOG_ERROR,
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index f7d8a4d..0f832b3 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -1437,6 +1437,12 @@ bool cmCPackGenerator::SupportsComponentInstallation() const
}
//----------------------------------------------------------------------
+bool cmCPackGenerator::WantsComponentInstallation() const
+{
+ return (!IsOn("CPACK_MONOLITHIC_INSTALL") & SupportsComponentInstallation());
+}
+
+//----------------------------------------------------------------------
cmCPackInstallationType*
cmCPackGenerator::GetInstallationType(const char *projectName,
const char *name)
diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h
index 52def9d..55afb44 100644
--- a/Source/CPack/cmCPackGenerator.h
+++ b/Source/CPack/cmCPackGenerator.h
@@ -189,7 +189,21 @@ protected:
virtual int InstallProjectViaInstallCMakeProjects(
bool setDestDir, const char* tempInstallDirectory);
+ /**
+ * Does the CPack generator support component installation?.
+ * Some Generators requires the user to set
+ * CPACK_<GENNAME>_COMPONENT_INSTALL in order to make this
+ * method return true.
+ * @return true if supported, false otherwise
+ */
virtual bool SupportsComponentInstallation() const;
+ /**
+ * Does the currently running generator want a component installation.
+ * The generator may support component installation but he may
+ * be requiring monolithic install using CPACK_MONOLITHIC_INSTALL.
+ * @return true if component installation is supported and wanted.
+ */
+ virtual bool WantsComponentInstallation() const;
virtual cmCPackInstallationType* GetInstallationType(const char *projectName,
const char* name);
virtual cmCPackComponent* GetComponent(const char *projectName,
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
index 75ad640..363ccea 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -170,23 +170,25 @@ int cmCPackOSXX11Generator::PackageFiles()
<< "\" create -ov -format UDZO -srcfolder \""
<< diskImageDirectory.c_str()
<< "\" \"" << packageFileNames[0] << "\"";
- int retVal = 1;
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Compress disk image using command: "
<< dmgCmd.str().c_str() << std::endl);
// since we get random dashboard failures with this one
// try running it more than once
- int numTries = 4;
+ int retVal = 1;
+ int numTries = 10;
bool res = false;
while(numTries > 0)
{
res = cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output,
&retVal, 0,
this->GeneratorVerbose, 0);
- if(res && retVal)
+ if ( res && !retVal )
{
numTries = -1;
+ break;
}
+ cmSystemTools::Delay(500);
numTries--;
}
if ( !res || retVal )
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index 0c4b1a6..3a0e89b 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -319,17 +319,19 @@ int cmCPackPackageMakerGenerator::PackageFiles()
<< "\" \"" << packageFileNames[0] << "\"";
std::string output;
int retVal = 1;
- int numTries = 4;
+ int numTries = 10;
bool res = false;
while(numTries > 0)
{
res = cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output,
&retVal, 0, this->GeneratorVerbose,
0);
- if(res && retVal)
+ if ( res && !retVal )
{
numTries = -1;
+ break;
}
+ cmSystemTools::Delay(500);
numTries--;
}
if ( !res || retVal )
@@ -353,24 +355,73 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
cmCPackLogger(cmCPackLog::LOG_DEBUG,
"cmCPackPackageMakerGenerator::Initialize()" << std::endl);
this->SetOptionIfNotSet("CPACK_PACKAGING_INSTALL_PREFIX", "/usr");
- std::vector<std::string> path;
- std::string pkgPath
- = "/Developer/Applications/Utilities/PackageMaker.app/Contents";
- std::string versionFile = pkgPath + "/version.plist";
- if ( !cmSystemTools::FileExists(versionFile.c_str()) )
+
+ // Starting with Xcode 4.3, PackageMaker is a separate app, and you
+ // can put it anywhere you want. So... use a variable for its location.
+ // People who put it in unexpected places can use the variable to tell
+ // us where it is.
+ //
+ // Use the following locations, in "most recent installation" order,
+ // to search for the PackageMaker app. Assume people who copy it into
+ // the new Xcode 4.3 app in "/Applications" will copy it into the nested
+ // Applications folder inside the Xcode bundle itself. Or directly in
+ // the "/Applications" directory.
+ //
+ // If found, save result in the CPACK_INSTALLER_PROGRAM variable.
+
+ std::vector<std::string> paths;
+ paths.push_back(
+ "/Applications/Xcode.app/Contents/Applications"
+ "/PackageMaker.app/Contents/MacOS");
+ paths.push_back(
+ "/Applications/Utilities"
+ "/PackageMaker.app/Contents/MacOS");
+ paths.push_back(
+ "/Applications"
+ "/PackageMaker.app/Contents/MacOS");
+ paths.push_back(
+ "/Developer/Applications/Utilities"
+ "/PackageMaker.app/Contents/MacOS");
+ paths.push_back(
+ "/Developer/Applications"
+ "/PackageMaker.app/Contents/MacOS");
+
+ std::string pkgPath;
+ const char *inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM");
+ if (inst_program && *inst_program)
+ {
+ pkgPath = inst_program;
+ }
+ else
{
- pkgPath = "/Developer/Applications/PackageMaker.app/Contents";
- std::string newVersionFile = pkgPath + "/version.plist";
- if ( !cmSystemTools::FileExists(newVersionFile.c_str()) )
+ pkgPath = cmSystemTools::FindProgram("PackageMaker", paths, false);
+ if ( pkgPath.empty() )
{
- cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Cannot find PackageMaker compiler version file: "
- << versionFile.c_str() << " or " << newVersionFile.c_str()
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find PackageMaker compiler"
<< std::endl);
return 0;
}
- versionFile = newVersionFile;
+ this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath.c_str());
}
+
+ // Get path to the real PackageMaker, not a symlink:
+ pkgPath = cmSystemTools::GetRealPath(pkgPath.c_str());
+ // Up from there to find the version.plist file in the "Contents" dir:
+ std::string contents_dir;
+ contents_dir = cmSystemTools::GetFilenamePath(pkgPath);
+ contents_dir = cmSystemTools::GetFilenamePath(contents_dir);
+
+ std::string versionFile = contents_dir + "/version.plist";
+
+ if ( !cmSystemTools::FileExists(versionFile.c_str()) )
+ {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Cannot find PackageMaker compiler version file: "
+ << versionFile.c_str()
+ << std::endl);
+ return 0;
+ }
+
std::ifstream ifs(versionFile.c_str());
if ( !ifs )
{
@@ -378,6 +429,7 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
"Cannot open PackageMaker compiler version file" << std::endl);
return 0;
}
+
// Check the PackageMaker version
cmsys::RegularExpression rexKey("<key>CFBundleShortVersionString</key>");
cmsys::RegularExpression rexVersion("<string>([0-9]+.[0-9.]+)</string>");
@@ -440,17 +492,8 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
this->PackageCompatibilityVersion = 10.3;
}
- pkgPath += "/MacOS";
- path.push_back(pkgPath);
- pkgPath = cmSystemTools::FindProgram("PackageMaker", path, false);
- if ( pkgPath.empty() )
- {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find PackageMaker compiler"
- << std::endl);
- return 0;
- }
- this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", pkgPath.c_str());
- pkgPath = cmSystemTools::FindProgram("hdiutil", path, false);
+ std::vector<std::string> no_paths;
+ pkgPath = cmSystemTools::FindProgram("hdiutil", no_paths, false);
if ( pkgPath.empty() )
{
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot find hdiutil compiler"
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index 1a6c3be..413572e 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -201,7 +201,7 @@ int cmCPackRPMGenerator::PackageFiles()
<< toplevel << std::endl);
/* Are we in the component packaging case */
- if (SupportsComponentInstallation()) {
+ if (WantsComponentInstallation()) {
// CASE 1 : COMPONENT ALL-IN-ONE package
// If ALL COMPONENTS in ONE package has been requested
// then the package file is unique and should be open here.
diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx
index 184c557..966a231 100644
--- a/Source/CPack/cmCPackSTGZGenerator.cxx
+++ b/Source/CPack/cmCPackSTGZGenerator.cxx
@@ -54,21 +54,32 @@ int cmCPackSTGZGenerator::InitializeInternal()
//----------------------------------------------------------------------
int cmCPackSTGZGenerator::PackageFiles()
{
+ bool retval = true;
if ( !this->Superclass::PackageFiles() )
{
return 0;
}
- return cmSystemTools::SetPermissions(packageFileNames[0].c_str(),
+
+ /* TGZ generator (our Superclass) may
+ * have generated several packages (component packaging)
+ * so we must iterate over generated packages.
+ */
+ for (std::vector<std::string>::iterator it=packageFileNames.begin();
+ it != packageFileNames.end(); ++it)
+ {
+ retval &= cmSystemTools::SetPermissions((*it).c_str(),
#if defined( _MSC_VER ) || defined( __MINGW32__ )
- S_IREAD | S_IWRITE | S_IEXEC
+ S_IREAD | S_IWRITE | S_IEXEC
#elif defined( __BORLANDC__ )
- S_IRUSR | S_IWUSR | S_IXUSR
+ S_IRUSR | S_IWUSR | S_IXUSR
#else
- S_IRUSR | S_IWUSR | S_IXUSR |
- S_IRGRP | S_IWGRP | S_IXGRP |
- S_IROTH | S_IWOTH | S_IXOTH
+ S_IRUSR | S_IWUSR | S_IXUSR |
+ S_IRGRP | S_IWGRP | S_IXGRP |
+ S_IROTH | S_IWOTH | S_IXOTH
#endif
- );
+ );
+ }
+ return retval;
}
//----------------------------------------------------------------------
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 34a3e60..27bb06c 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -94,6 +94,7 @@ static const char* cmCTestErrorMatches[] = {
": Invalid argument",
"^The project cannot be built\\.",
"^\\[ERROR\\]",
+ "^Command .* failed with exit code",
0
};
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index f0a98f9..035aaa9 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -679,7 +679,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
" bytes in [0-9,]+ blocks are definitely lost"
" in loss record [0-9,]+ of [0-9,]+");
cmsys::RegularExpression vgPAR(
- "== .*Syscall param .* contains unaddressable byte\\(s\\)");
+ "== .*Syscall param .* (contains|points to) unaddressable byte\\(s\\)");
cmsys::RegularExpression vgMPK1(
"== .*[0-9,]+ bytes in [0-9,]+ blocks are possibly lost in"
" loss record [0-9,]+ of [0-9,]+");
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index 9a776fb..c1d0e9d 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -64,6 +64,12 @@ bool cmAddLibraryCommand
type = cmTarget::MODULE_LIBRARY;
haveSpecifiedType = true;
}
+ else if(libType == "OBJECT")
+ {
+ ++s;
+ type = cmTarget::OBJECT_LIBRARY;
+ haveSpecifiedType = true;
+ }
else if(libType == "UNKNOWN")
{
++s;
@@ -118,6 +124,14 @@ bool cmAddLibraryCommand
this->SetError("called with IMPORTED argument but no library type.");
return false;
}
+ if(type == cmTarget::OBJECT_LIBRARY)
+ {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "The OBJECT library type may not be used for IMPORTED libraries."
+ );
+ return true;
+ }
// Make sure the target does not already exist.
if(this->Makefile->FindTargetToUse(libName.c_str()))
diff --git a/Source/cmAddLibraryCommand.h b/Source/cmAddLibraryCommand.h
index 9ca9cbe..b1ae202 100644
--- a/Source/cmAddLibraryCommand.h
+++ b/Source/cmAddLibraryCommand.h
@@ -112,6 +112,26 @@ public:
"(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) "
"which specifies the location of the main library file on disk. "
"See documentation of the IMPORTED_* properties for more information."
+ "\n"
+ "The signature\n"
+ " add_library(<name> OBJECT <src>...)\n"
+ "creates a special \"object library\" target. "
+ "An object library compiles source files but does not archive or link "
+ "their object files into a library. "
+ "Instead other targets created by add_library or add_executable may "
+ "reference the objects using an expression of the form "
+ "$<TARGET_OBJECTS:objlib> as a source, where \"objlib\" is the "
+ "object library name. "
+ "For example:\n"
+ " add_library(... $<TARGET_OBJECTS:objlib> ...)\n"
+ " add_executable(... $<TARGET_OBJECTS:objlib> ...)\n"
+ "will include objlib's object files in a library and an executable "
+ "along with those compiled from their own sources. "
+ "Object libraries may contain only sources (and headers) that compile "
+ "to object files. "
+ "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."
;
}
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index ab0bb79..47a0e85 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -13,6 +13,7 @@
#include "cmCacheManager.h"
#include "cmSystemTools.h"
#include "cmCacheManager.h"
+#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
#include "cmake.h"
#include "cmVersion.h"
@@ -431,9 +432,8 @@ bool cmCacheManager::SaveCache(const char* path)
{
std::string cacheFile = path;
cacheFile += "/CMakeCache.txt";
- std::string tempFile = cacheFile;
- tempFile += ".tmp";
- std::ofstream fout(tempFile.c_str());
+ cmGeneratedFileStream fout(cacheFile.c_str());
+ fout.SetCopyIfDifferent(true);
if(!fout)
{
cmSystemTools::Error("Unable to open cache file for save. ",
@@ -561,10 +561,7 @@ bool cmCacheManager::SaveCache(const char* path)
}
}
fout << "\n";
- fout.close();
- cmSystemTools::CopyFileIfDifferent(tempFile.c_str(),
- cacheFile.c_str());
- cmSystemTools::RemoveFile(tempFile.c_str());
+ fout.Close();
std::string checkCacheFile = path;
checkCacheFile += cmake::GetCMakeFilesDirectory();
cmSystemTools::MakeDirectory(checkCacheFile.c_str());
diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h
index a211e95..cdb832b 100644
--- a/Source/cmCommandArgumentParserHelper.h
+++ b/Source/cmCommandArgumentParserHelper.h
@@ -81,7 +81,6 @@ private:
cmStdString InputBuffer;
std::vector<char> OutputBuffer;
int CurrentLine;
- int UnionsAvailable;
int Verbose;
void Print(const char* place, const char* str);
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index ddff2d9..055aab0 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -633,6 +633,19 @@ cmTarget* cmComputeLinkDepends::FindTargetToLink(int depender_index,
tgt = 0;
}
+ if(tgt && tgt->GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "Target \"" << this->Target->GetName() << "\" links to "
+ "OBJECT library \"" << tgt->GetName() << "\" but this is not "
+ "allowed. "
+ "One may link only to STATIC or SHARED libraries, or to executables "
+ "with the ENABLE_EXPORTS property set.";
+ this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Target->GetBacktrace());
+ tgt = 0;
+ }
+
// Return the target found, if any.
return tgt;
}
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 57fd5b4..df78bf8 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -1772,6 +1772,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
!linking_for_install);
bool use_link_rpath =
outputRuntime && linking_for_install &&
+ !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH") &&
this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
// Construct the RPATH.
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index 19558fa..9296d4c 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -260,12 +260,27 @@ bool cmDepends::CheckDependencies(std::istream& internalDepends,
//----------------------------------------------------------------------------
void cmDepends::SetIncludePathFromLanguage(const char* lang)
{
+ // Look for the new per "TARGET_" variant first:
+ const char * includePath = 0;
std::string includePathVar = "CMAKE_";
includePathVar += lang;
- includePathVar += "_INCLUDE_PATH";
+ includePathVar += "_TARGET_INCLUDE_PATH";
cmMakefile* mf = this->LocalGenerator->GetMakefile();
- if(const char* includePath = mf->GetDefinition(includePathVar.c_str()))
+ includePath = mf->GetDefinition(includePathVar.c_str());
+ if(includePath)
{
cmSystemTools::ExpandListArgument(includePath, this->IncludePath);
}
+ else
+ {
+ // Fallback to the old directory level variable if no per-target var:
+ includePathVar = "CMAKE_";
+ includePathVar += lang;
+ includePathVar += "_INCLUDE_PATH";
+ includePath = mf->GetDefinition(includePathVar.c_str());
+ if(includePath)
+ {
+ cmSystemTools::ExpandListArgument(includePath, this->IncludePath);
+ }
+ }
}
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index a31dd01..897e516 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -355,7 +355,9 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"If this is set to TRUE, then the rpath information "
"is not added to compiled executables. The default "
"is to add rpath information if the platform supports it. "
- "This allows for easy running from the build tree.",false,
+ "This allows for easy running from the build tree. To omit RPATH"
+ "in the install step, but not the build step, use "
+ "CMAKE_SKIP_INSTALL_RPATH instead.",false,
"Variables that Provide Information");
cm->DefineProperty
("CMAKE_SOURCE_DIR", cmProperty::VARIABLE,
@@ -1201,6 +1203,20 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Variables that Control the Build");
cm->DefineProperty
+ ("CMAKE_SKIP_INSTALL_RPATH", cmProperty::VARIABLE,
+ "Do not include RPATHs in the install tree.",
+ "Normally CMake uses the build tree for the RPATH when building "
+ "executables etc on systems that use RPATH. When the software "
+ "is installed the executables etc are relinked by CMake to have "
+ "the install RPATH. If this variable is set to true then the software "
+ "is always installed without RPATH, even if RPATH is enabled when "
+ "building. This can be useful for example to allow running tests from "
+ "the build directory with RPATH enabled before the installation step. "
+ "To omit RPATH in both the build and install steps, use "
+ "CMAKE_SKIP_RPATH instead.",false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
("CMAKE_EXE_LINKER_FLAGS", cmProperty::VARIABLE,
"Linker flags used to create executables.",
"Flags used by the linker when creating an executable.",false,
@@ -1278,6 +1294,22 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"See that target property for additional information.",
false,
"Variables that Control the Build");
+ cm->DefineProperty
+ ("CMAKE_WIN32_EXECUTABLE", cmProperty::VARIABLE,
+ "Default value for WIN32_EXECUTABLE of targets.",
+ "This variable is used to initialize the "
+ "WIN32_EXECUTABLE property on all the targets. "
+ "See that target property for additional information.",
+ false,
+ "Variables that Control the Build");
+ cm->DefineProperty
+ ("CMAKE_MACOSX_BUNDLE", cmProperty::VARIABLE,
+ "Default value for MACOSX_BUNDLE of targets.",
+ "This variable is used to initialize the "
+ "MACOSX_BUNDLE property on all the targets. "
+ "See that target property for additional information.",
+ false,
+ "Variables that Control the Build");
// Variables defined when the a language is enabled These variables will
// also be defined whenever CMake has loaded its support for compiling (LANG)
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index cb614d4..1cc1754 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -124,6 +124,14 @@ bool cmExportCommand
{
targets.push_back(target);
}
+ else if(target->GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "given OBJECT library \"" << *currentTarget
+ << "\" which may not be exported.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
else
{
cmOStringStream e;
diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx
index ee37352..7728d74 100644
--- a/Source/cmExprParserHelper.cxx
+++ b/Source/cmExprParserHelper.cxx
@@ -30,12 +30,6 @@ cmExprParserHelper::~cmExprParserHelper()
this->CleanupParser();
}
-void cmExprParserHelper::SetLineFile(long line, const char* file)
-{
- this->FileLine = line;
- this->FileName = file;
-}
-
int cmExprParserHelper::ParseString(const char* str, int verb)
{
if ( !str)
diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h
index 0c36b44..690426d 100644
--- a/Source/cmExprParserHelper.h
+++ b/Source/cmExprParserHelper.h
@@ -46,8 +46,6 @@ public:
int GetResult() { return this->Result; }
- void SetLineFile(long line, const char* file);
-
const char* GetError() { return this->ErrorString.c_str(); }
private:
@@ -55,7 +53,6 @@ private:
cmStdString InputBuffer;
std::vector<char> OutputBuffer;
int CurrentLine;
- int UnionsAvailable;
int Verbose;
void Print(const char* place, const char* str);
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 6e246e6..ccb17f0 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -596,16 +596,17 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
// the include directories for this target
std::set<std::string> uniqIncludeDirs;
- const std::vector<std::string>& incDirs =
- target->GetMakefile()->GetIncludeDirectories();
- for(std::vector<std::string>::const_iterator dirIt=incDirs.begin();
- dirIt != incDirs.end();
+
+ std::vector<std::string> includes;
+ target->GetMakefile()->GetLocalGenerator()->
+ GetIncludeDirectories(includes, target);
+ for(std::vector<std::string>::const_iterator dirIt=includes.begin();
+ dirIt != includes.end();
++dirIt)
{
uniqIncludeDirs.insert(*dirIt);
}
-
std::string systemIncludeDirs = makefile->GetSafeDefinition(
"CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
if (!systemIncludeDirs.empty())
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index c8c86c7..65077b3 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -501,6 +501,7 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(
case cmTarget::STATIC_LIBRARY:
case cmTarget::SHARED_LIBRARY:
case cmTarget::MODULE_LIBRARY:
+ case cmTarget::OBJECT_LIBRARY:
{
const char* prefix = (ti->second.GetType()==cmTarget::EXECUTABLE ?
"[exe] " : "[lib] ");
@@ -893,9 +894,13 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
it != this->GlobalGenerator->GetLocalGenerators().end();
++it)
{
- const std::vector<std::string>& includeDirs
- = (*it)->GetMakefile()->GetIncludeDirectories();
- this->AppendIncludeDirectories(fout, includeDirs, emmited);
+ cmTargets & targets = (*it)->GetMakefile()->GetTargets();
+ for (cmTargets::iterator l = targets.begin(); l != targets.end(); ++l)
+ {
+ std::vector<std::string> includeDirs;
+ (*it)->GetIncludeDirectories(includeDirs, &l->second);
+ this->AppendIncludeDirectories(fout, includeDirs, emmited);
+ }
}
// now also the system include directories, in case we found them in
// CMakeSystemSpecificInformation.cmake. This makes Eclipse find the
@@ -1013,6 +1018,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
case cmTarget::STATIC_LIBRARY:
case cmTarget::SHARED_LIBRARY:
case cmTarget::MODULE_LIBRARY:
+ case cmTarget::OBJECT_LIBRARY:
{
const char* prefix = (ti->second.GetType()==cmTarget::EXECUTABLE ?
"[exe] " : "[lib] ");
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 3b368fa..ced26c4 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -152,7 +152,8 @@ public:
"TO_CMAKE_PATH will convert path into a cmake style path with unix /. "
" The input can be a single path or a system path like \"$ENV{PATH}\". "
" Note the double quotes around the ENV call TO_CMAKE_PATH only takes "
- " one argument.\n"
+ " one argument. This command will also convert the native list"
+ " delimiters for a list of paths like the PATH environment variable.\n"
"TO_NATIVE_PATH works just like TO_CMAKE_PATH, but will convert from "
" a cmake style path into the native path style \\ for windows and / "
"for UNIX.\n"
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index a726849..6cdbbf2 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -57,7 +57,13 @@ void cmFindLibraryCommand::GenerateDocumentation()
"the full path to the framework <fullPath>/A.framework. "
"When a full path to a framework is used as a library, "
"CMake will use a -framework A, and a -F<fullPath> to "
- "link the framework to the target. ";
+ "link the framework to the target."
+ "\n"
+ "If the global property FIND_LIBRARY_USE_LIB64_PATHS is set all search "
+ "paths will be tested as normal, with \"64/\" appended, and with all "
+ "matches of \"lib/\" replaced with \"lib64/\". This property is "
+ "automatically set for the platforms that are known to need it if at "
+ "least one of the languages supported by the PROJECT command is enabled.";
}
// cmFindLibraryCommand
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 9177162..ef16ce8 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -90,6 +90,7 @@ void cmFindPackageCommand::GenerateDocumentation()
this->CommandDocumentation =
" find_package(<package> [version] [EXACT] [QUIET] [MODULE]\n"
" [[REQUIRED|COMPONENTS] [components...]]\n"
+ " [OPTIONAL_COMPONENTS components...]\n"
" [NO_POLICY_SCOPE])\n"
"Finds and loads settings from an external project. "
"<package>_FOUND will be set to indicate whether the package was found. "
@@ -98,10 +99,14 @@ void cmFindPackageCommand::GenerateDocumentation()
"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 "
- "package cannot be found. "
- "A package-specific list of components may be listed after the "
- "REQUIRED option or after the COMPONENTS option if no REQUIRED "
- "option is given. "
+ "package cannot be found."
+ "\n"
+ "A package-specific list of required components may be listed after the "
+ "COMPONENTS option or directly after the REQUIRED option. "
+ "Additional optional components may be listed after OPTIONAL_COMPONENTS. "
+ "Available components and their influence on whether a package is "
+ "considered to be found are defined by the target package."
+ "\n"
"The [version] argument requests a version with which the package found "
"should be compatible (format is major[.minor[.patch[.tweak]]]). "
"The EXACT option requests that the version be matched exactly. "
@@ -198,7 +203,7 @@ void cmFindPackageCommand::GenerateDocumentation()
"If no such version file is available then the configuration file "
"is assumed to not be compatible with any requested version. "
"A basic version file containing generic version matching code can be "
- "created using the macro write_basic_config_version_file(), see its "
+ "created using the macro write_basic_package_version_file(), see its "
"documentation for more details. "
"When a version file is found it is loaded to check the requested "
"version number. "
@@ -410,6 +415,8 @@ bool cmFindPackageCommand
this->Name = args[0];
std::string components;
const char* components_sep = "";
+ std::set<std::string> requiredComponents;
+ std::set<std::string> optionalComponents;
// Check ancient compatibility.
this->Compatibility_1_6 =
@@ -420,8 +427,8 @@ bool cmFindPackageCommand
this->SearchPathSuffixes.push_back("");
// Parse the arguments.
- enum Doing { DoingNone, DoingComponents, DoingNames, DoingPaths,
- DoingPathSuffixes, DoingConfigs, DoingHints };
+ enum Doing { DoingNone, DoingComponents, DoingOptionalComponents, DoingNames,
+ DoingPaths, DoingPathSuffixes, DoingConfigs, DoingHints };
Doing doing = DoingNone;
cmsys::RegularExpression version("^[0-9.]+$");
bool haveVersion = false;
@@ -465,6 +472,11 @@ bool cmFindPackageCommand
this->Compatibility_1_6 = false;
doing = DoingComponents;
}
+ else if(args[i] == "OPTIONAL_COMPONENTS")
+ {
+ this->Compatibility_1_6 = false;
+ doing = DoingOptionalComponents;
+ }
else if(args[i] == "NAMES")
{
configArgs.insert(i);
@@ -528,12 +540,23 @@ bool cmFindPackageCommand
this->Compatibility_1_6 = false;
doing = DoingNone;
}
- else if(doing == DoingComponents)
+ else if((doing == DoingComponents) || (doing == DoingOptionalComponents))
{
- // Set a variable telling the find script this component
+ // Set a variable telling the find script whether this component
// is required.
+ const char* isRequired = "1";
+ if (doing == DoingOptionalComponents)
+ {
+ isRequired = "0";
+ optionalComponents.insert(args[i]);
+ }
+ else
+ {
+ requiredComponents.insert(args[i]);
+ }
+
std::string req_var = this->Name + "_FIND_REQUIRED_" + args[i];
- this->AddFindDefinition(req_var.c_str(), "1");
+ this->AddFindDefinition(req_var.c_str(), isRequired);
// Append to the list of required components.
components += components_sep;
@@ -584,6 +607,22 @@ bool cmFindPackageCommand
}
}
+ std::vector<std::string> doubledComponents;
+ std::set_intersection(requiredComponents.begin(), requiredComponents.end(),
+ optionalComponents.begin(), optionalComponents.end(),
+ std::back_inserter(doubledComponents));
+ if(!doubledComponents.empty())
+ {
+ cmOStringStream e;
+ e << "called with components that are both required and optional:\n";
+ for(unsigned int i=0; i<doubledComponents.size(); ++i)
+ {
+ e << " " << doubledComponents[i] << "\n";
+ }
+ this->SetError(e.str().c_str());
+ return false;
+ }
+
// Maybe choose one mode exclusively.
this->UseFindModules = configArgs.empty();
this->UseConfigFiles = moduleArgs.empty();
@@ -952,11 +991,26 @@ bool cmFindPackageCommand::HandlePackageMode()
}
}
+ std::string foundVar = this->Name;
+ foundVar += "_FOUND";
+
// If the directory for the config file was found, try to read the file.
bool result = true;
bool found = false;
+ bool configFileSetFOUNDFalse = false;
+
if(fileFound)
{
+ if ((this->Makefile->IsDefinitionSet(foundVar.c_str()))
+ && (this->Makefile->IsOn(foundVar.c_str()) == false))
+ {
+ // by removing Foo_FOUND here if it is FALSE, we don't really change
+ // the situation for the Config file which is about to be included,
+ // but we make it possible to detect later on whether the Config file
+ // has set Foo_FOUND to FALSE itself:
+ this->Makefile->RemoveDefinition(foundVar.c_str());
+ }
+
// Set the version variables before loading the config file.
// It may override them.
this->StoreVersionFound();
@@ -966,6 +1020,15 @@ bool cmFindPackageCommand::HandlePackageMode()
{
// The package has been found.
found = true;
+
+ // Check whether the Config file has set Foo_FOUND to FALSE:
+ if ((this->Makefile->IsDefinitionSet(foundVar.c_str()))
+ && (this->Makefile->IsOn(foundVar.c_str()) == false))
+ {
+ // we get here if the Config file has set Foo_FOUND actively to FALSE
+ found = false;
+ configFileSetFOUNDFalse = true;
+ }
}
else
{
@@ -973,14 +1036,22 @@ bool cmFindPackageCommand::HandlePackageMode()
result = false;
}
}
- else if(!this->Quiet || this->Required)
+
+ if (result && !found && (!this->Quiet || this->Required))
{
// The variable is not set.
cmOStringStream e;
cmOStringStream aw;
+ if (configFileSetFOUNDFalse)
+ {
+ e << "Found package configuration file:\n"
+ " " << this->FileFound << "\n"
+ "but it set " << foundVar << " to FALSE so package \"" <<
+ this->Name << "\" is considered to be NOT FOUND.";
+ }
// If there are files in ConsideredConfigs, it means that FooConfig.cmake
// have been found, but they didn't have appropriate versions.
- if (this->ConsideredConfigs.size() > 0)
+ else if (this->ConsideredConfigs.size() > 0)
{
e << "Could not find a configuration file for package \""
<< this->Name << "\" that "
@@ -1062,6 +1133,10 @@ bool cmFindPackageCommand::HandlePackageMode()
this->Makefile->IssueMessage(
this->Required? cmake::FATAL_ERROR : cmake::WARNING, e.str());
+ if (this->Required)
+ {
+ cmSystemTools::SetFatalErrorOccured();
+ }
if (!aw.str().empty())
{
@@ -1070,8 +1145,6 @@ bool cmFindPackageCommand::HandlePackageMode()
}
// Set a variable marking whether the package was found.
- std::string foundVar = this->Name;
- foundVar += "_FOUND";
this->Makefile->AddDefinition(foundVar.c_str(), found? "1":"0");
// Set a variable naming the configuration file that was found.
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
new file mode 100644
index 0000000..42dd428
--- /dev/null
+++ b/Source/cmGeneratorTarget.cxx
@@ -0,0 +1,184 @@
+/*============================================================================
+ 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 "cmGeneratorTarget.h"
+
+#include "cmTarget.h"
+#include "cmMakefile.h"
+#include "cmLocalGenerator.h"
+#include "cmGlobalGenerator.h"
+#include "cmSourceFile.h"
+
+//----------------------------------------------------------------------------
+cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t)
+{
+ this->Makefile = this->Target->GetMakefile();
+ this->LocalGenerator = this->Makefile->GetLocalGenerator();
+ this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator();
+ this->ClassifySources();
+ this->LookupObjectLibraries();
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::ClassifySources()
+{
+ cmsys::RegularExpression header(CM_HEADER_REGEX);
+ bool isObjLib = this->Target->GetType() == cmTarget::OBJECT_LIBRARY;
+ std::vector<cmSourceFile*> badObjLib;
+ std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
+ for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
+ si != sources.end(); ++si)
+ {
+ cmSourceFile* sf = *si;
+ std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
+ cmTarget::SourceFileFlags tsFlags =
+ this->Target->GetTargetSourceFileFlags(sf);
+ if(sf->GetCustomCommand())
+ {
+ this->CustomCommands.push_back(sf);
+ }
+ else if(tsFlags.Type != cmTarget::SourceFileTypeNormal)
+ {
+ this->OSXContent.push_back(sf);
+ if(isObjLib) { badObjLib.push_back(sf); }
+ }
+ else if(sf->GetPropertyAsBool("HEADER_FILE_ONLY"))
+ {
+ this->HeaderSources.push_back(sf);
+ }
+ else if(sf->GetPropertyAsBool("EXTERNAL_OBJECT"))
+ {
+ this->ExternalObjects.push_back(sf);
+ if(isObjLib) { badObjLib.push_back(sf); }
+ }
+ else if(sf->GetLanguage())
+ {
+ this->ObjectSources.push_back(sf);
+ }
+ else if(ext == "def")
+ {
+ this->ModuleDefinitionFile = sf->GetFullPath();
+ if(isObjLib) { badObjLib.push_back(sf); }
+ }
+ else if(ext == "idl")
+ {
+ this->IDLSources.push_back(sf);
+ if(isObjLib) { badObjLib.push_back(sf); }
+ }
+ else if(header.find(sf->GetFullPath().c_str()))
+ {
+ this->HeaderSources.push_back(sf);
+ }
+ else if(this->GlobalGenerator->IgnoreFile(sf->GetExtension().c_str()))
+ {
+ // We only get here if a source file is not an external object
+ // and has an extension that is listed as an ignored file type.
+ // No message or diagnosis should be given.
+ this->ExtraSources.push_back(sf);
+ }
+ else
+ {
+ this->ExtraSources.push_back(sf);
+ if(isObjLib && ext != "txt")
+ {
+ badObjLib.push_back(sf);
+ }
+ }
+ }
+
+ if(!badObjLib.empty())
+ {
+ cmOStringStream e;
+ e << "OBJECT library \"" << this->Target->GetName() << "\" contains:\n";
+ for(std::vector<cmSourceFile*>::iterator i = badObjLib.begin();
+ i != badObjLib.end(); ++i)
+ {
+ e << " " << (*i)->GetLocation().GetName() << "\n";
+ }
+ e << "but may contain only headers and sources that compile.";
+ this->GlobalGenerator->GetCMakeInstance()
+ ->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Target->GetBacktrace());
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::LookupObjectLibraries()
+{
+ std::vector<std::string> const& objLibs =
+ this->Target->GetObjectLibraries();
+ for(std::vector<std::string>::const_iterator oli = objLibs.begin();
+ oli != objLibs.end(); ++oli)
+ {
+ std::string const& objLibName = *oli;
+ if(cmTarget* objLib = this->Makefile->FindTargetToUse(objLibName.c_str()))
+ {
+ if(objLib->GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ if(this->Target->GetType() != cmTarget::EXECUTABLE &&
+ this->Target->GetType() != cmTarget::STATIC_LIBRARY &&
+ this->Target->GetType() != cmTarget::SHARED_LIBRARY &&
+ this->Target->GetType() != cmTarget::MODULE_LIBRARY)
+ {
+ this->GlobalGenerator->GetCMakeInstance()
+ ->IssueMessage(cmake::FATAL_ERROR,
+ "Only executables and non-OBJECT libraries may "
+ "reference target objects.",
+ this->Target->GetBacktrace());
+ return;
+ }
+ this->Target->AddUtility(objLib->GetName());
+ this->ObjectLibraries.push_back(objLib);
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "Objects of target \"" << objLibName
+ << "\" referenced but is not an OBJECT library.";
+ this->GlobalGenerator->GetCMakeInstance()
+ ->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Target->GetBacktrace());
+ return;
+ }
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "Objects of target \"" << objLibName
+ << "\" referenced but no such target exists.";
+ this->GlobalGenerator->GetCMakeInstance()
+ ->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Target->GetBacktrace());
+ return;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs)
+{
+ for(std::vector<cmTarget*>::const_iterator
+ ti = this->ObjectLibraries.begin();
+ ti != this->ObjectLibraries.end(); ++ti)
+ {
+ cmTarget* objLib = *ti;
+ cmGeneratorTarget* ogt =
+ this->GlobalGenerator->GetGeneratorTarget(objLib);
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = ogt->ObjectSources.begin();
+ si != ogt->ObjectSources.end(); ++si)
+ {
+ std::string obj = ogt->ObjectDirectory;
+ obj += ogt->Objects[*si];
+ objs.push_back(obj);
+ }
+ }
+}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
new file mode 100644
index 0000000..3e50656
--- /dev/null
+++ b/Source/cmGeneratorTarget.h
@@ -0,0 +1,64 @@
+/*============================================================================
+ 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 cmGeneratorTarget_h
+#define cmGeneratorTarget_h
+
+#include "cmStandardIncludes.h"
+
+class cmCustomCommand;
+class cmGlobalGenerator;
+class cmLocalGenerator;
+class cmMakefile;
+class cmSourceFile;
+class cmTarget;
+
+class cmGeneratorTarget
+{
+public:
+ cmGeneratorTarget(cmTarget*);
+
+ cmTarget* Target;
+ cmMakefile* Makefile;
+ cmLocalGenerator* LocalGenerator;
+ cmGlobalGenerator* GlobalGenerator;
+
+ /** Sources classified by purpose. */
+ std::vector<cmSourceFile*> CustomCommands;
+ std::vector<cmSourceFile*> ExtraSources;
+ std::vector<cmSourceFile*> HeaderSources;
+ std::vector<cmSourceFile*> ObjectSources;
+ std::vector<cmSourceFile*> ExternalObjects;
+ std::vector<cmSourceFile*> OSXContent;
+ std::vector<cmSourceFile*> IDLSources;
+ std::string ModuleDefinitionFile;
+
+ std::map<cmSourceFile const*, std::string> Objects;
+ std::set<cmSourceFile const*> ExplicitObjectName;
+
+ /** Full path with trailing slash to the top-level directory
+ holding object files for this target. Includes the build
+ time config name placeholder if needed for the generator. */
+ std::string ObjectDirectory;
+
+ std::vector<cmTarget*> ObjectLibraries;
+
+ void UseObjectLibraries(std::vector<std::string>& objs);
+
+private:
+ void ClassifySources();
+ void LookupObjectLibraries();
+
+ cmGeneratorTarget(cmGeneratorTarget const&);
+ void operator=(cmGeneratorTarget const&);
+};
+
+#endif
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 8dce053..545f9e8 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -24,6 +24,7 @@
#include "cmExportInstallFileGenerator.h"
#include "cmComputeTargetDepends.h"
#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
#include <cmsys/Directory.hxx>
@@ -74,6 +75,7 @@ cmGlobalGenerator::~cmGlobalGenerator()
delete this->ExtraGenerator;
}
+ this->ClearGeneratorTargets();
this->ClearExportSets();
}
@@ -807,6 +809,7 @@ bool cmGlobalGenerator::IsDependedOn(const char* project,
void cmGlobalGenerator::Configure()
{
this->FirstTimeProgress = 0.0f;
+ this->ClearGeneratorTargets();
this->ClearExportSets();
// Delete any existing cmLocalGenerators
unsigned int i;
@@ -947,6 +950,9 @@ void cmGlobalGenerator::Generate()
this->LocalGenerators[i]->GenerateTargetManifest();
}
+ // Create per-target generator information.
+ this->CreateGeneratorTargets();
+
// Compute the inter-target dependencies.
if(!this->ComputeTargetDepends())
{
@@ -1056,6 +1062,55 @@ void cmGlobalGenerator::CreateAutomocTargets()
#endif
}
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::CreateGeneratorTargets()
+{
+ // Construct per-target generator information.
+ for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
+ {
+ cmTargets& targets =
+ this->LocalGenerators[i]->GetMakefile()->GetTargets();
+ for(cmTargets::iterator ti = targets.begin();
+ ti != targets.end(); ++ti)
+ {
+ cmTarget* t = &ti->second;
+ cmGeneratorTarget* gt = new cmGeneratorTarget(t);
+ this->GeneratorTargets[t] = gt;
+ this->ComputeTargetObjects(gt);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::ClearGeneratorTargets()
+{
+ for(GeneratorTargetsType::iterator i = this->GeneratorTargets.begin();
+ i != this->GeneratorTargets.end(); ++i)
+ {
+ delete i->second;
+ }
+ this->GeneratorTargets.clear();
+}
+
+//----------------------------------------------------------------------------
+cmGeneratorTarget* cmGlobalGenerator::GetGeneratorTarget(cmTarget* t) const
+{
+ GeneratorTargetsType::const_iterator ti = this->GeneratorTargets.find(t);
+ if(ti == this->GeneratorTargets.end())
+ {
+ this->CMakeInstance->IssueMessage(
+ cmake::INTERNAL_ERROR, "Missing cmGeneratorTarget instance!",
+ cmListFileBacktrace());
+ return 0;
+ }
+ return ti->second;
+}
+
+//----------------------------------------------------------------------------
+void cmGlobalGenerator::ComputeTargetObjects(cmGeneratorTarget*) const
+{
+ // Implemented in generator subclasses that need this.
+}
void cmGlobalGenerator::CheckLocalGenerators()
{
@@ -1067,9 +1122,9 @@ void cmGlobalGenerator::CheckLocalGenerators()
{
manager = this->LocalGenerators[i]->GetMakefile()->GetCacheManager();
this->LocalGenerators[i]->ConfigureFinalPass();
- const cmTargets & targets =
+ cmTargets & targets =
this->LocalGenerators[i]->GetMakefile()->GetTargets();
- for (cmTargets::const_iterator l = targets.begin();
+ for (cmTargets::iterator l = targets.begin();
l != targets.end(); l++)
{
const cmTarget::LinkLibraryVectorType& libs =
@@ -1095,27 +1150,28 @@ void cmGlobalGenerator::CheckLocalGenerators()
notFoundMap[varName] = text;
}
}
- }
- const std::vector<std::string>& incs =
- this->LocalGenerators[i]->GetMakefile()->GetIncludeDirectories();
+ std::vector<std::string> incs;
+ this->LocalGenerators[i]->GetIncludeDirectories(incs, &l->second);
- for( std::vector<std::string>::const_iterator incDir = incs.begin();
- incDir != incs.end(); ++incDir)
- {
- if(incDir->size() > 9 &&
- cmSystemTools::IsNOTFOUND(incDir->c_str()))
+ for( std::vector<std::string>::const_iterator incDir = incs.begin();
+ incDir != incs.end(); ++incDir)
{
- std::string varName = incDir->substr(0, incDir->size()-9);
- cmCacheManager::CacheIterator it =
- manager->GetCacheIterator(varName.c_str());
- if(it.GetPropertyAsBool("ADVANCED"))
+ if(incDir->size() > 9 &&
+ cmSystemTools::IsNOTFOUND(incDir->c_str()))
{
- varName += " (ADVANCED)";
+ std::string varName = incDir->substr(0, incDir->size()-9);
+ cmCacheManager::CacheIterator it =
+ manager->GetCacheIterator(varName.c_str());
+ if(it.GetPropertyAsBool("ADVANCED"))
+ {
+ varName += " (ADVANCED)";
+ }
+ std::string text = notFoundMap[varName];
+ text += "\n used as include directory in directory ";
+ text += this->LocalGenerators[i]
+ ->GetMakefile()->GetCurrentDirectory();
+ notFoundMap[varName] = text;
}
- std::string text = notFoundMap[varName];
- text += "\n used as include directory in directory ";
- text += this->LocalGenerators[i]->GetMakefile()->GetCurrentDirectory();
- notFoundMap[varName] = text;
}
}
this->CMakeInstance->UpdateProgress
@@ -1713,7 +1769,7 @@ void cmGlobalGenerator::SetCMakeInstance(cmake* cm)
void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
{
cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
- const char* cmakeCfgIntDir = this->GetCMakeCFGInitDirectory();
+ const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
const char* cmakeCommand = mf->GetRequiredDefinition("CMAKE_COMMAND");
// CPack
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 1a0e41a..80b948b 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -19,6 +19,7 @@
#include "cmTargetDepend.h" // For cmTargetDependSet
#include "cmSystemTools.h" // for cmSystemTools::OutputOption
class cmake;
+class cmGeneratorTarget;
class cmMakefile;
class cmLocalGenerator;
class cmExternalMakefileProjectGenerator;
@@ -183,7 +184,7 @@ public:
const char* GetLanguageOutputExtension(cmSourceFile const&);
///! What is the configurations directory variable called?
- virtual const char* GetCMakeCFGInitDirectory() { return "."; }
+ virtual const char* GetCMakeCFGIntDir() const { return "."; }
/** Get whether the generator should use a script for link commands. */
bool GetUseLinkScript() const { return this->UseLinkScript; }
@@ -251,6 +252,9 @@ public:
// via a target_link_libraries or add_dependencies
TargetDependSet const& GetTargetDirectDepends(cmTarget & target);
+ /** Get per-target generator information. */
+ cmGeneratorTarget* GetGeneratorTarget(cmTarget*) const;
+
const std::map<cmStdString, std::vector<cmLocalGenerator*> >& GetProjectMap()
const {return this->ProjectMap;}
@@ -370,6 +374,13 @@ private:
typedef std::map<cmTarget *, TargetDependSet> TargetDependMap;
TargetDependMap TargetDependencies;
+ // Per-target generator information.
+ typedef std::map<cmTarget*, cmGeneratorTarget*> GeneratorTargetsType;
+ GeneratorTargetsType GeneratorTargets;
+ void CreateGeneratorTargets();
+ void ClearGeneratorTargets();
+ virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+
// Cache directory content and target files to be built.
struct DirectoryContent: public std::set<cmStdString>
{
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
new file mode 100644
index 0000000..9cbd502
--- /dev/null
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -0,0 +1,822 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 "cmGlobalNinjaGenerator.h"
+#include "cmLocalNinjaGenerator.h"
+#include "cmMakefile.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmVersion.h"
+
+const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja";
+const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja";
+const char* cmGlobalNinjaGenerator::INDENT = " ";
+
+void cmGlobalNinjaGenerator::Indent(std::ostream& os, int count)
+{
+ for(int i = 0; i < count; ++i)
+ os << cmGlobalNinjaGenerator::INDENT;
+}
+
+void cmGlobalNinjaGenerator::WriteDivider(std::ostream& os)
+{
+ os
+ << "# ======================================"
+ << "=======================================\n";
+}
+
+void cmGlobalNinjaGenerator::WriteComment(std::ostream& os,
+ const std::string& comment)
+{
+ if (comment.empty())
+ return;
+
+ std::string replace = comment;
+ std::string::size_type lpos = 0;
+ std::string::size_type rpos;
+ while((rpos = replace.find('\n', lpos)) != std::string::npos)
+ {
+ os << "# " << replace.substr(lpos, rpos - lpos) << "\n";
+ lpos = rpos + 1;
+ }
+ os << "# " << replace.substr(lpos) << "\n";
+}
+
+static bool IsIdentChar(char c)
+{
+ return
+ ('a' <= c && c <= 'z') ||
+ ('+' <= c && c <= '9') || // +,-./ and numbers
+ ('A' <= c && c <= 'Z') ||
+ (c == '_') || (c == '$') || (c == '\\') ||
+ (c == ' ') || (c == ':');
+}
+
+std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string &ident,
+ std::ostream &vars) {
+ if (std::find_if(ident.begin(), ident.end(),
+ std::not1(std::ptr_fun(IsIdentChar))) != ident.end()) {
+ static unsigned VarNum = 0;
+ std::ostringstream names;
+ names << "ident" << VarNum++;
+ vars << names.str() << " = " << ident << "\n";
+ return "$" + names.str();
+ } else {
+ std::string result = ident;
+ cmSystemTools::ReplaceString(result, " ", "$ ");
+ cmSystemTools::ReplaceString(result, ":", "$:");
+ return result;
+ }
+}
+
+std::string cmGlobalNinjaGenerator::EncodeLiteral(const std::string &lit)
+{
+ std::string result = lit;
+ cmSystemTools::ReplaceString(result, "$", "$$");
+ return result;
+}
+
+std::string cmGlobalNinjaGenerator::EncodePath(const std::string &path)
+{
+ std::string result = path;
+#ifdef _WIN32
+ cmSystemTools::ReplaceString(result, "/", "\\");
+#endif
+ return EncodeLiteral(result);
+}
+
+void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
+ const std::string& comment,
+ const std::string& rule,
+ const cmNinjaDeps& outputs,
+ const cmNinjaDeps& explicitDeps,
+ const cmNinjaDeps& implicitDeps,
+ const cmNinjaDeps& orderOnlyDeps,
+ const cmNinjaVars& variables)
+{
+ // Make sure there is a rule.
+ if(rule.empty())
+ {
+ cmSystemTools::Error("No rule for WriteBuildStatement! called "
+ "with comment: ",
+ comment.c_str());
+ return;
+ }
+
+ // Make sure there is at least one output file.
+ if(outputs.empty())
+ {
+ cmSystemTools::Error("No output files for WriteBuildStatement! called "
+ "with comment: ",
+ comment.c_str());
+ return;
+ }
+
+ cmGlobalNinjaGenerator::WriteComment(os, comment);
+
+ std::ostringstream builds;
+
+ // TODO: Better formatting for when there are multiple input/output files.
+
+ // Write outputs files.
+ builds << "build";
+ for(cmNinjaDeps::const_iterator i = outputs.begin();
+ i != outputs.end();
+ ++i)
+ builds << " " << EncodeIdent(EncodePath(*i), os);
+ builds << ":";
+
+ // Write the rule.
+ builds << " " << rule;
+
+ // Write explicit dependencies.
+ for(cmNinjaDeps::const_iterator i = explicitDeps.begin();
+ i != explicitDeps.end();
+ ++i)
+ builds << " " << EncodeIdent(EncodePath(*i), os);
+
+ // Write implicit dependencies.
+ if(!implicitDeps.empty())
+ {
+ builds << " |";
+ for(cmNinjaDeps::const_iterator i = implicitDeps.begin();
+ i != implicitDeps.end();
+ ++i)
+ builds << " " << EncodeIdent(EncodePath(*i), os);
+ }
+
+ // Write order-only dependencies.
+ if(!orderOnlyDeps.empty())
+ {
+ builds << " ||";
+ for(cmNinjaDeps::const_iterator i = orderOnlyDeps.begin();
+ i != orderOnlyDeps.end();
+ ++i)
+ builds << " " << EncodeIdent(EncodePath(*i), os);
+ }
+
+ builds << "\n";
+
+ os << builds.str();
+
+ // Write the variables bound to this build statement.
+ for(cmNinjaVars::const_iterator i = variables.begin();
+ i != variables.end();
+ ++i)
+ cmGlobalNinjaGenerator::WriteVariable(os, i->first, i->second, "", 1);
+}
+
+void cmGlobalNinjaGenerator::WritePhonyBuild(std::ostream& os,
+ const std::string& comment,
+ const cmNinjaDeps& outputs,
+ const cmNinjaDeps& explicitDeps,
+ const cmNinjaDeps& implicitDeps,
+ const cmNinjaDeps& orderOnlyDeps,
+ const cmNinjaVars& variables)
+{
+ cmGlobalNinjaGenerator::WriteBuild(os,
+ comment,
+ "phony",
+ outputs,
+ explicitDeps,
+ implicitDeps,
+ orderOnlyDeps,
+ variables);
+}
+
+void cmGlobalNinjaGenerator::AddCustomCommandRule()
+{
+ this->AddRule("CUSTOM_COMMAND",
+ "$COMMAND",
+ "$DESC",
+ "Rule for running custom commands.",
+ /*depfile*/ "",
+ /*restat*/ true);
+}
+
+void
+cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
+ const std::string& description,
+ const std::string& comment,
+ const cmNinjaDeps& outputs,
+ const cmNinjaDeps& deps,
+ const cmNinjaDeps& orderOnlyDeps)
+{
+ this->AddCustomCommandRule();
+
+ cmNinjaVars vars;
+ vars["COMMAND"] = command;
+ vars["DESC"] = EncodeLiteral(description);
+
+ cmGlobalNinjaGenerator::WriteBuild(*this->BuildFileStream,
+ comment,
+ "CUSTOM_COMMAND",
+ outputs,
+ deps,
+ cmNinjaDeps(),
+ orderOnlyDeps,
+ vars);
+}
+
+void cmGlobalNinjaGenerator::WriteRule(std::ostream& os,
+ const std::string& name,
+ const std::string& command,
+ const std::string& description,
+ const std::string& comment,
+ const std::string& depfile,
+ bool restat,
+ bool generator)
+{
+ // Make sure the rule has a name.
+ if(name.empty())
+ {
+ cmSystemTools::Error("No name given for WriteRuleStatement! called "
+ "with comment: ",
+ comment.c_str());
+ return;
+ }
+
+ // Make sure a command is given.
+ if(command.empty())
+ {
+ cmSystemTools::Error("No command given for WriteRuleStatement! called "
+ "with comment: ",
+ comment.c_str());
+ return;
+ }
+
+ cmGlobalNinjaGenerator::WriteComment(os, comment);
+
+ // Write the rule.
+ os << "rule " << name << "\n";
+
+ // Write the depfile if any.
+ if(!depfile.empty())
+ {
+ cmGlobalNinjaGenerator::Indent(os, 1);
+ os << "depfile = " << depfile << "\n";
+ }
+
+ // Write the command.
+ cmGlobalNinjaGenerator::Indent(os, 1);
+ os << "command = " << command << "\n";
+
+ // Write the description if any.
+ if(!description.empty())
+ {
+ cmGlobalNinjaGenerator::Indent(os, 1);
+ os << "description = " << description << "\n";
+ }
+
+ if(restat)
+ {
+ cmGlobalNinjaGenerator::Indent(os, 1);
+ os << "restat = 1\n";
+ }
+
+ if(generator)
+ {
+ cmGlobalNinjaGenerator::Indent(os, 1);
+ os << "generator = 1\n";
+ }
+}
+
+void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os,
+ const std::string& name,
+ const std::string& value,
+ const std::string& comment,
+ int indent)
+{
+ // Make sure we have a name.
+ if(name.empty())
+ {
+ cmSystemTools::Error("No name given for WriteVariable! called "
+ "with comment: ",
+ comment.c_str());
+ return;
+ }
+
+ // Do not add a variable if the value is empty.
+ std::string val = cmSystemTools::TrimWhitespace(value);
+ if(val.empty())
+ {
+ return;
+ }
+
+ cmGlobalNinjaGenerator::WriteComment(os, comment);
+ cmGlobalNinjaGenerator::Indent(os, indent);
+ os << name << " = " << val << "\n";
+}
+
+void cmGlobalNinjaGenerator::WriteInclude(std::ostream& os,
+ const std::string& filename,
+ const std::string& comment)
+{
+ cmGlobalNinjaGenerator::WriteComment(os, comment);
+ os << "include " << filename << "\n";
+}
+
+void cmGlobalNinjaGenerator::WriteDefault(std::ostream& os,
+ const cmNinjaDeps& targets,
+ const std::string& comment)
+{
+ cmGlobalNinjaGenerator::WriteComment(os, comment);
+ os << "default";
+ for(cmNinjaDeps::const_iterator i = targets.begin(); i != targets.end(); ++i)
+ os << " " << *i;
+ os << "\n";
+}
+
+
+cmGlobalNinjaGenerator::cmGlobalNinjaGenerator()
+ : cmGlobalGenerator()
+ , BuildFileStream(0)
+ , RulesFileStream(0)
+ , Rules()
+ , AllDependencies()
+{
+ // // Ninja is not ported to non-Unix OS yet.
+ // this->ForceUnixPaths = true;
+ this->FindMakeProgramFile = "CMakeNinjaFindMake.cmake";
+}
+
+//----------------------------------------------------------------------------
+// Virtual public methods.
+
+cmLocalGenerator* cmGlobalNinjaGenerator::CreateLocalGenerator()
+{
+ cmLocalGenerator* lg = new cmLocalNinjaGenerator;
+ lg->SetGlobalGenerator(this);
+ return lg;
+}
+
+void cmGlobalNinjaGenerator
+::GetDocumentation(cmDocumentationEntry& entry) const
+{
+ entry.Name = this->GetName();
+ entry.Brief = "Generates build.ninja files (experimental).";
+ entry.Full =
+ "A build.ninja file is generated into the build tree. Recent "
+ "versions of the ninja program can build the project through the "
+ "\"all\" target. An \"install\" target is also provided.";
+}
+
+// Implemented in all cmGlobaleGenerator sub-classes.
+// Used in:
+// Source/cmLocalGenerator.cxx
+// Source/cmake.cxx
+void cmGlobalNinjaGenerator::Generate()
+{
+ this->OpenBuildFileStream();
+ this->OpenRulesFileStream();
+
+ this->cmGlobalGenerator::Generate();
+
+ this->WriteAssumedSourceDependencies();
+ this->WriteTargetAliases(*this->BuildFileStream);
+ this->WriteBuiltinTargets(*this->BuildFileStream);
+
+ this->CloseRulesFileStream();
+ this->CloseBuildFileStream();
+}
+
+// Implemented in all cmGlobaleGenerator sub-classes.
+// Used in:
+// Source/cmMakefile.cxx:
+void cmGlobalNinjaGenerator
+::EnableLanguage(std::vector<std::string>const& languages,
+ cmMakefile *mf,
+ bool optional)
+{
+ this->cmGlobalGenerator::EnableLanguage(languages, mf, optional);
+ std::string path;
+ for(std::vector<std::string>::const_iterator l = languages.begin();
+ l != languages.end(); ++l)
+ {
+ if(*l == "NONE")
+ {
+ continue;
+ }
+ 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());
+ }
+ this->ResolveLanguageCompiler(*l, mf, optional);
+ }
+}
+
+// Implemented by:
+// cmGlobalUnixMakefileGenerator3
+// cmGlobalVisualStudio10Generator
+// cmGlobalVisualStudio6Generator
+// cmGlobalVisualStudio7Generator
+// cmGlobalXCodeGenerator
+// Called by:
+// cmGlobalGenerator::Build()
+std::string cmGlobalNinjaGenerator
+::GenerateBuildCommand(const char* makeProgram,
+ const char* projectName,
+ const char* additionalOptions,
+ const char* targetName,
+ const char* config,
+ bool ignoreErrors,
+ bool fast)
+{
+ // Project name and config are not used yet.
+ (void)projectName;
+ (void)config;
+ // Ninja does not have -i equivalent option yet.
+ (void)ignoreErrors;
+ // We do not handle fast build yet.
+ (void)fast;
+
+ std::string makeCommand =
+ cmSystemTools::ConvertToUnixOutputPath(makeProgram);
+
+ if(additionalOptions)
+ {
+ makeCommand += " ";
+ makeCommand += additionalOptions;
+ }
+ if(targetName)
+ {
+ if(strcmp(targetName, "clean") == 0)
+ {
+ makeCommand += " -t clean";
+ }
+ else
+ {
+ makeCommand += " ";
+ makeCommand += targetName;
+ }
+ }
+
+ return makeCommand;
+}
+
+//----------------------------------------------------------------------------
+// Non-virtual public methods.
+
+void cmGlobalNinjaGenerator::AddRule(const std::string& name,
+ const std::string& command,
+ const std::string& description,
+ const std::string& comment,
+ const std::string& depfile,
+ bool restat,
+ bool generator)
+{
+ // Do not add the same rule twice.
+ if (this->HasRule(name))
+ return;
+
+ this->Rules.insert(name);
+ cmGlobalNinjaGenerator::WriteRule(*this->RulesFileStream,
+ name,
+ command,
+ description,
+ comment,
+ depfile,
+ restat,
+ generator);
+}
+
+bool cmGlobalNinjaGenerator::HasRule(const std::string &name)
+{
+ RulesSetType::const_iterator rule = this->Rules.find(name);
+ return (rule != this->Rules.end());
+}
+
+//----------------------------------------------------------------------------
+// Private virtual overrides
+
+// TODO: Refactor to combine with cmGlobalUnixMakefileGenerator3 impl.
+void cmGlobalNinjaGenerator::ComputeTargetObjects(cmGeneratorTarget* gt) const
+{
+ cmTarget* target = gt->Target;
+
+ // Compute full path to object file directory for this target.
+ std::string dir_max;
+ dir_max += gt->Makefile->GetCurrentOutputDirectory();
+ dir_max += "/";
+ dir_max += gt->LocalGenerator->GetTargetDirectory(*target);
+ dir_max += "/";
+ gt->ObjectDirectory = dir_max;
+
+ // Compute the name of each object file.
+ for(std::vector<cmSourceFile*>::iterator
+ si = gt->ObjectSources.begin();
+ si != gt->ObjectSources.end(); ++si)
+ {
+ cmSourceFile* sf = *si;
+ std::string objectName = gt->LocalGenerator
+ ->GetObjectFileNameWithoutTarget(*sf, dir_max);
+ gt->Objects[sf] = objectName;
+ }
+}
+
+//----------------------------------------------------------------------------
+// Private methods
+
+void cmGlobalNinjaGenerator::OpenBuildFileStream()
+{
+ // Compute Ninja's build file path.
+ std::string buildFilePath =
+ this->GetCMakeInstance()->GetHomeOutputDirectory();
+ buildFilePath += "/";
+ buildFilePath += cmGlobalNinjaGenerator::NINJA_BUILD_FILE;
+
+ // Get a stream where to generate things.
+ if (!this->BuildFileStream)
+ {
+ this->BuildFileStream = new cmGeneratedFileStream(buildFilePath.c_str());
+ if (!this->BuildFileStream)
+ {
+ // An error message is generated by the constructor if it cannot
+ // open the file.
+ return;
+ }
+ }
+
+ // Write the do not edit header.
+ this->WriteDisclaimer(*this->BuildFileStream);
+
+ // Write a comment about this file.
+ *this->BuildFileStream
+ << "# This file contains all the build statements describing the\n"
+ << "# compilation DAG.\n\n"
+ ;
+}
+
+void cmGlobalNinjaGenerator::CloseBuildFileStream()
+{
+ if (this->BuildFileStream)
+ {
+ delete this->BuildFileStream;
+ this->BuildFileStream = 0;
+ }
+ else
+ {
+ cmSystemTools::Error("Build file stream was not open.");
+ }
+}
+
+void cmGlobalNinjaGenerator::OpenRulesFileStream()
+{
+ // Compute Ninja's build file path.
+ std::string rulesFilePath =
+ this->GetCMakeInstance()->GetHomeOutputDirectory();
+ rulesFilePath += "/";
+ rulesFilePath += cmGlobalNinjaGenerator::NINJA_RULES_FILE;
+
+ // Get a stream where to generate things.
+ if (!this->RulesFileStream)
+ {
+ this->RulesFileStream = new cmGeneratedFileStream(rulesFilePath.c_str());
+ if (!this->RulesFileStream)
+ {
+ // An error message is generated by the constructor if it cannot
+ // open the file.
+ return;
+ }
+ }
+
+ // Write the do not edit header.
+ this->WriteDisclaimer(*this->RulesFileStream);
+
+ // Write comment about this file.
+ *this->RulesFileStream
+ << "# This file contains all the rules used to get the outputs files\n"
+ << "# built from the input files.\n"
+ << "# It is included in the main '" << NINJA_BUILD_FILE << "'.\n\n"
+ ;
+}
+
+void cmGlobalNinjaGenerator::CloseRulesFileStream()
+{
+ if (this->RulesFileStream)
+ {
+ delete this->RulesFileStream;
+ this->RulesFileStream = 0;
+ }
+ else
+ {
+ cmSystemTools::Error("Rules file stream was not open.");
+ }
+}
+
+void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os)
+{
+ os
+ << "# CMAKE generated file: DO NOT EDIT!\n"
+ << "# Generated by \"" << this->GetName() << "\""
+ << " Generator, CMake Version "
+ << cmVersion::GetMajorVersion() << "."
+ << cmVersion::GetMinorVersion() << "\n\n";
+}
+
+void cmGlobalNinjaGenerator::AddDependencyToAll(cmTarget* target)
+{
+ this->AppendTargetOutputs(target, this->AllDependencies);
+}
+
+void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
+{
+ for (std::map<std::string, std::set<std::string> >::iterator
+ i = this->AssumedSourceDependencies.begin();
+ i != this->AssumedSourceDependencies.end(); ++i) {
+ cmNinjaDeps deps;
+ std::copy(i->second.begin(), i->second.end(), std::back_inserter(deps));
+ WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
+ "Assume dependencies for generated source file.",
+ cmNinjaDeps(1, i->first), deps);
+ }
+}
+
+void
+cmGlobalNinjaGenerator
+::AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs)
+{
+ const char* configName =
+ target->GetMakefile()->GetDefinition("CMAKE_BUILD_TYPE");
+ cmLocalNinjaGenerator *ng =
+ static_cast<cmLocalNinjaGenerator *>(this->LocalGenerators[0]);
+
+ switch (target->GetType()) {
+ case cmTarget::EXECUTABLE:
+ case cmTarget::SHARED_LIBRARY:
+ case cmTarget::STATIC_LIBRARY:
+ case cmTarget::MODULE_LIBRARY:
+ outputs.push_back(ng->ConvertToNinjaPath(
+ target->GetFullPath(configName).c_str()));
+ break;
+
+ case cmTarget::OBJECT_LIBRARY:
+ case cmTarget::UTILITY: {
+ std::string path = ng->ConvertToNinjaPath(
+ target->GetMakefile()->GetStartOutputDirectory());
+ if (path.empty() || path == ".")
+ outputs.push_back(target->GetName());
+ else {
+ path += "/";
+ path += target->GetName();
+ outputs.push_back(path);
+ }
+ break;
+ }
+
+ case cmTarget::GLOBAL_TARGET:
+ // Always use the target in HOME instead of an unused duplicate in a
+ // subdirectory.
+ outputs.push_back(target->GetName());
+ break;
+
+ default:
+ return;
+ }
+}
+
+void
+cmGlobalNinjaGenerator
+::AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs)
+{
+ if (target->GetType() == cmTarget::GLOBAL_TARGET) {
+ // Global targets only depend on other utilities, which may not appear in
+ // the TargetDepends set (e.g. "all").
+ std::set<cmStdString> const& utils = target->GetUtilities();
+ std::copy(utils.begin(), utils.end(), std::back_inserter(outputs));
+ } else {
+ cmTargetDependSet const& targetDeps =
+ this->GetTargetDirectDepends(*target);
+ for (cmTargetDependSet::const_iterator i = targetDeps.begin();
+ i != targetDeps.end(); ++i) {
+ this->AppendTargetOutputs(*i, outputs);
+ }
+ }
+}
+
+void cmGlobalNinjaGenerator::AddTargetAlias(const std::string& alias,
+ cmTarget* target) {
+ cmNinjaDeps outputs;
+ this->AppendTargetOutputs(target, outputs);
+ // Mark the target's outputs as ambiguous to ensure that no other target uses
+ // the output as an alias.
+ for (cmNinjaDeps::iterator i = outputs.begin(); i != outputs.end(); ++i)
+ TargetAliases[*i] = 0;
+
+ // Insert the alias into the map. If the alias was already present in the
+ // map and referred to another target, mark it as ambiguous.
+ std::pair<TargetAliasMap::iterator, bool> newAlias =
+ TargetAliases.insert(make_pair(alias, target));
+ if (newAlias.second && newAlias.first->second != target)
+ newAlias.first->second = 0;
+}
+
+void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
+{
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ os << "# Target aliases.\n\n";
+
+ for (TargetAliasMap::iterator i = TargetAliases.begin();
+ i != TargetAliases.end(); ++i) {
+ // Don't write ambiguous aliases.
+ if (!i->second)
+ continue;
+
+ cmNinjaDeps deps;
+ this->AppendTargetOutputs(i->second, deps);
+
+ cmGlobalNinjaGenerator::WritePhonyBuild(os,
+ "",
+ cmNinjaDeps(1, i->first),
+ deps);
+ }
+}
+
+void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
+{
+ // Write headers.
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ os << "# Built-in targets\n\n";
+
+ this->WriteTargetAll(os);
+ this->WriteTargetRebuildManifest(os);
+}
+
+void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
+{
+ cmNinjaDeps outputs;
+ outputs.push_back("all");
+
+ cmGlobalNinjaGenerator::WritePhonyBuild(os,
+ "The main all target.",
+ outputs,
+ this->AllDependencies);
+
+ cmGlobalNinjaGenerator::WriteDefault(os,
+ outputs,
+ "Make the all target the default.");
+}
+
+void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
+{
+ cmLocalGenerator *lg = this->LocalGenerators[0];
+ cmMakefile* mfRoot = lg->GetMakefile();
+
+ std::ostringstream cmd;
+ cmd << lg->ConvertToOutputFormat(
+ mfRoot->GetRequiredDefinition("CMAKE_COMMAND"),
+ cmLocalGenerator::SHELL)
+ << " -H"
+ << lg->ConvertToOutputFormat(mfRoot->GetHomeDirectory(),
+ cmLocalGenerator::SHELL)
+ << " -B"
+ << lg->ConvertToOutputFormat(mfRoot->GetHomeOutputDirectory(),
+ cmLocalGenerator::SHELL);
+ WriteRule(*this->RulesFileStream,
+ "RERUN_CMAKE",
+ cmd.str(),
+ "Re-running CMake...",
+ "Rule for re-running cmake.",
+ /*depfile=*/ "",
+ /*restat=*/ false,
+ /*generator=*/ true);
+
+ cmNinjaDeps implicitDeps;
+ for (std::vector<cmLocalGenerator *>::const_iterator i =
+ this->LocalGenerators.begin(); i != this->LocalGenerators.end(); ++i) {
+ const std::vector<std::string>& lf = (*i)->GetMakefile()->GetListFiles();
+ implicitDeps.insert(implicitDeps.end(), lf.begin(), lf.end());
+ }
+ std::sort(implicitDeps.begin(), implicitDeps.end());
+ implicitDeps.erase(std::unique(implicitDeps.begin(), implicitDeps.end()),
+ implicitDeps.end());
+ implicitDeps.push_back("CMakeCache.txt");
+
+ WriteBuild(os,
+ "Re-run CMake if any of its inputs changed.",
+ "RERUN_CMAKE",
+ /*outputs=*/ cmNinjaDeps(1, NINJA_BUILD_FILE),
+ /*explicitDeps=*/ cmNinjaDeps(),
+ implicitDeps,
+ /*orderOnlyDeps=*/ cmNinjaDeps(),
+ /*variables=*/ cmNinjaVars());
+
+ WritePhonyBuild(os,
+ "A missing CMake input file is not an error.",
+ implicitDeps,
+ cmNinjaDeps());
+}
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
new file mode 100644
index 0000000..3217581
--- /dev/null
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -0,0 +1,338 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 cmGlobalNinjaGenerator_h
+# define cmGlobalNinjaGenerator_h
+
+# include "cmGlobalGenerator.h"
+# include "cmNinjaTypes.h"
+
+class cmLocalGenerator;
+class cmGeneratedFileStream;
+class cmGeneratorTarget;
+
+/**
+ * \class cmGlobalNinjaGenerator
+ * \brief Write a build.ninja file.
+ *
+ * The main differences between this generator and the UnixMakefile
+ * generator family are:
+ * - We don't care about VERBOSE variable or RULE_MESSAGES property since
+ * it is handle by Ninja's -v option.
+ * - We don't care about computing any progress status since Ninja manages
+ * it itself.
+ * - We don't care about generating a clean target since Ninja already have
+ * a clean tool.
+ * - We generate one build.ninja and one rules.ninja per project.
+ * - We try to minimize the number of generated rules: one per target and
+ * language.
+ * - We use Ninja special variable $in and $out to produce nice output.
+ * - We extensively use Ninja variable overloading system to minimize the
+ * number of generated rules.
+ */
+class cmGlobalNinjaGenerator : public cmGlobalGenerator
+{
+public:
+ /// The default name of Ninja's build file. Typically: build.ninja.
+ static const char* NINJA_BUILD_FILE;
+
+ /// The default name of Ninja's rules file. Typically: rules.ninja.
+ /// It is included in the main build.ninja file.
+ static const char* NINJA_RULES_FILE;
+
+ /// The indentation string used when generating Ninja's build file.
+ static const char* INDENT;
+
+ /// Write @a count times INDENT level to output stream @a os.
+ static void Indent(std::ostream& os, int count);
+
+ /// Write a divider in the given output stream @a os.
+ static void WriteDivider(std::ostream& os);
+
+ static std::string EncodeIdent(const std::string &ident, std::ostream &vars);
+ static std::string EncodeLiteral(const std::string &lit);
+ static std::string EncodePath(const std::string &path);
+
+ /**
+ * Write the given @a comment to the output stream @a os. It
+ * handles new line character properly.
+ */
+ static void WriteComment(std::ostream& os, const std::string& comment);
+
+ /**
+ * Write a build statement to @a os with the @a comment using
+ * the @a rule the list of @a outputs files and inputs.
+ * It also writes the variables bound to this build statement.
+ * @warning no escaping of any kind is done here.
+ */
+ static void WriteBuild(std::ostream& os,
+ const std::string& comment,
+ const std::string& rule,
+ const cmNinjaDeps& outputs,
+ const cmNinjaDeps& explicitDeps,
+ const cmNinjaDeps& implicitDeps,
+ const cmNinjaDeps& orderOnlyDeps,
+ const cmNinjaVars& variables);
+
+ /**
+ * Helper to write a build statement with the special 'phony' rule.
+ */
+ static void WritePhonyBuild(std::ostream& os,
+ const std::string& comment,
+ const cmNinjaDeps& outputs,
+ const cmNinjaDeps& explicitDeps,
+ const cmNinjaDeps& implicitDeps = cmNinjaDeps(),
+ const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps(),
+ const cmNinjaVars& variables = cmNinjaVars());
+
+ void WriteCustomCommandBuild(const std::string& command,
+ const std::string& description,
+ const std::string& comment,
+ const cmNinjaDeps& outputs,
+ const cmNinjaDeps& deps = cmNinjaDeps(),
+ const cmNinjaDeps& orderOnlyDeps = cmNinjaDeps());
+
+ /**
+ * Write a rule statement named @a name to @a os with the @a comment,
+ * the mandatory @a command, the @a depfile and the @a description.
+ * It also writes the variables bound to this rule statement.
+ * @warning no escaping of any kind is done here.
+ */
+ static void WriteRule(std::ostream& os,
+ const std::string& name,
+ const std::string& command,
+ const std::string& description,
+ const std::string& comment = "",
+ const std::string& depfile = "",
+ bool restat = false,
+ bool generator = false);
+
+ /**
+ * Write a variable named @a name to @a os with value @a value and an
+ * optional @a comment. An @a indent level can be specified.
+ * @warning no escaping of any kind is done here.
+ */
+ static void WriteVariable(std::ostream& os,
+ const std::string& name,
+ const std::string& value,
+ const std::string& comment = "",
+ int indent = 0);
+
+ /**
+ * Write an include statement including @a filename with an optional
+ * @a comment to the @a os stream.
+ */
+ static void WriteInclude(std::ostream& os,
+ const std::string& filename,
+ const std::string& comment = "");
+
+ /**
+ * Write a default target statement specifying @a targets as
+ * the default targets.
+ */
+ static void WriteDefault(std::ostream& os,
+ const cmNinjaDeps& targets,
+ const std::string& comment = "");
+
+public:
+ /// Default constructor.
+ cmGlobalNinjaGenerator();
+
+ /// Convenience method for creating an instance of this class.
+ static cmGlobalGenerator* New() {
+ return new cmGlobalNinjaGenerator; }
+
+ /// Destructor.
+ virtual ~cmGlobalNinjaGenerator() { }
+
+ /// Overloaded methods. @see cmGlobalGenerator::CreateLocalGenerator()
+ virtual cmLocalGenerator* CreateLocalGenerator();
+
+ /// Overloaded methods. @see cmGlobalGenerator::GetName().
+ virtual const char* GetName() const {
+ return cmGlobalNinjaGenerator::GetActualName(); }
+
+ /// @return the name of this generator.
+ static const char* GetActualName() { return "Ninja"; }
+
+ /// Overloaded methods. @see cmGlobalGenerator::GetDocumentation()
+ virtual void GetDocumentation(cmDocumentationEntry& entry) const;
+
+ /// Overloaded methods. @see cmGlobalGenerator::Generate()
+ virtual void Generate();
+
+ /// Overloaded methods. @see cmGlobalGenerator::EnableLanguage()
+ virtual void EnableLanguage(std::vector<std::string>const& languages,
+ cmMakefile* mf,
+ bool optional);
+
+ /// Overloaded methods. @see cmGlobalGenerator::GenerateBuildCommand()
+ virtual std::string GenerateBuildCommand(const char* makeProgram,
+ const char* projectName,
+ const char* additionalOptions,
+ const char* targetName,
+ const char* config,
+ bool ignoreErrors,
+ bool fast);
+
+ // Setup target names
+ virtual const char* GetAllTargetName() const { return "all"; }
+ virtual const char* GetInstallTargetName() const { return "install"; }
+ virtual const char* GetInstallLocalTargetName() const {
+ return "install/local";
+ }
+ virtual const char* GetInstallStripTargetName() const {
+ return "install/strip";
+ }
+ virtual const char* GetTestTargetName() const { return "test"; }
+ virtual const char* GetPackageTargetName() const { return "package"; }
+ virtual const char* GetPackageSourceTargetName() const {
+ return "package_source";
+ }
+ virtual const char* GetEditCacheTargetName() const {
+ return "edit_cache";
+ }
+ virtual const char* GetRebuildCacheTargetName() const {
+ return "rebuild_cache";
+ }
+ virtual const char* GetCleanTargetName() const { return "clean"; }
+
+public:
+ cmGeneratedFileStream* GetBuildFileStream() const
+ { return this->BuildFileStream; }
+
+ cmGeneratedFileStream* GetRulesFileStream() const
+ { return this->RulesFileStream; }
+
+ /**
+ * Add a rule to the generated build system.
+ * Call WriteRule() behind the scene but perform some check before like:
+ * - Do not add twice the same rule.
+ */
+ void AddRule(const std::string& name,
+ const std::string& command,
+ const std::string& description,
+ const std::string& comment = "",
+ const std::string& depfile = "",
+ bool restat = false,
+ bool generator = false);
+
+ bool HasRule(const std::string& name);
+
+ void AddCustomCommandRule();
+
+protected:
+
+ /// Overloaded methods.
+ /// @see cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
+ virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() { return true; }
+
+private:
+
+ /// @see cmGlobalGenerator::ComputeTargetObjects
+ virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+
+private:
+ // In order to access the AddDependencyToAll() functions and co.
+ friend class cmLocalNinjaGenerator;
+
+ // In order to access the SeenCustomCommand() function.
+ friend class cmNinjaTargetGenerator;
+ friend class cmNinjaNormalTargetGenerator;
+ friend class cmNinjaUtilityTargetGenerator;
+
+private:
+ void OpenBuildFileStream();
+ void CloseBuildFileStream();
+
+ void OpenRulesFileStream();
+ void CloseRulesFileStream();
+
+ /// Write the common disclaimer text at the top of each build file.
+ void WriteDisclaimer(std::ostream& os);
+
+ void AddDependencyToAll(cmTarget* target);
+
+ void WriteAssumedSourceDependencies();
+
+ void AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs);
+ void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs);
+
+ void AddTargetAlias(const std::string& alias, cmTarget* target);
+ void WriteTargetAliases(std::ostream& os);
+
+ void WriteBuiltinTargets(std::ostream& os);
+ void WriteTargetAll(std::ostream& os);
+ void WriteTargetRebuildManifest(std::ostream& os);
+
+ /// Called when we have seen the given custom command. Returns true
+ /// if we has seen it before.
+ bool SeenCustomCommand(cmCustomCommand const *cc) {
+ return !this->CustomCommands.insert(cc).second;
+ }
+
+ /// Called when we have seen the given custom command output.
+ void SeenCustomCommandOutput(const std::string &output) {
+ this->CustomCommandOutputs.insert(output);
+ // We don't need the assumed dependencies anymore, because we have
+ // an output.
+ this->AssumedSourceDependencies.erase(output);
+ }
+
+ bool HasCustomCommandOutput(const std::string &output) {
+ return this->CustomCommandOutputs.find(output) !=
+ this->CustomCommandOutputs.end();
+ }
+
+ void AddAssumedSourceDependencies(const std::string &source,
+ const cmNinjaDeps &deps) {
+ std::set<std::string> &ASD = this->AssumedSourceDependencies[source];
+ // Because we may see the same source file multiple times (same source
+ // specified in multiple targets), compute the union of any assumed
+ // dependencies.
+ ASD.insert(deps.begin(), deps.end());
+ }
+
+private:
+ /// The file containing the build statement. (the relation ship of the
+ /// compilation DAG).
+ cmGeneratedFileStream* BuildFileStream;
+ /// The file containing the rule statements. (The action attached to each
+ /// edge of the compilation DAG).
+ cmGeneratedFileStream* RulesFileStream;
+
+ /// The type used to store the set of rules added to the generated build
+ /// system.
+ typedef std::set<std::string> RulesSetType;
+
+ /// The set of rules added to the generated build system.
+ RulesSetType Rules;
+
+ /// The set of dependencies to add to the "all" target.
+ cmNinjaDeps AllDependencies;
+
+ /// The set of custom commands we have seen.
+ std::set<cmCustomCommand const*> CustomCommands;
+
+ /// The set of custom command outputs we have seen.
+ std::set<std::string> CustomCommandOutputs;
+
+ /// The mapping from source file to assumed dependencies.
+ std::map<std::string, std::set<std::string> > AssumedSourceDependencies;
+
+ typedef std::map<std::string, cmTarget*> TargetAliasMap;
+ TargetAliasMap TargetAliases;
+
+ static cmLocalGenerator* LocalGenerator;
+};
+
+#endif // ! cmGlobalNinjaGenerator_h
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index a23c0d8..e63de9c 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -17,6 +17,7 @@
#include "cmGeneratedFileStream.h"
#include "cmSourceFile.h"
#include "cmTarget.h"
+#include "cmGeneratorTarget.h"
cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
{
@@ -71,6 +72,38 @@ void cmGlobalUnixMakefileGenerator3
}
//----------------------------------------------------------------------------
+void
+cmGlobalUnixMakefileGenerator3
+::ComputeTargetObjects(cmGeneratorTarget* gt) const
+{
+ cmTarget* target = gt->Target;
+ cmLocalUnixMakefileGenerator3* lg =
+ static_cast<cmLocalUnixMakefileGenerator3*>(gt->LocalGenerator);
+
+ // Compute full path to object file directory for this target.
+ std::string dir_max;
+ dir_max += gt->Makefile->GetCurrentOutputDirectory();
+ dir_max += "/";
+ dir_max += gt->LocalGenerator->GetTargetDirectory(*target);
+ dir_max += "/";
+ gt->ObjectDirectory = dir_max;
+
+ // Compute the name of each object file.
+ for(std::vector<cmSourceFile*>::iterator
+ si = gt->ObjectSources.begin();
+ si != gt->ObjectSources.end(); ++si)
+ {
+ cmSourceFile* sf = *si;
+ bool hasSourceExtension = true;
+ std::string objectName = gt->LocalGenerator
+ ->GetObjectFileNameWithoutTarget(*sf, dir_max,
+ &hasSourceExtension);
+ gt->Objects[sf] = objectName;
+ lg->AddLocalObjectFile(target, sf, objectName, hasSourceExtension);
+ }
+}
+
+//----------------------------------------------------------------------------
std::string EscapeJSON(const std::string& s) {
std::string result;
for (std::string::size_type i = 0; i < s.size(); ++i) {
@@ -378,6 +411,7 @@ void cmGlobalUnixMakefileGenerator3
(l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
(l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
(l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
+ (l->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
(l->second.GetType() == cmTarget::UTILITY))
{
std::string tname = lg->GetRelativeTargetDirectory(l->second);
@@ -413,6 +447,7 @@ cmGlobalUnixMakefileGenerator3
(l->second.GetType() == cmTarget::STATIC_LIBRARY) ||
(l->second.GetType() == cmTarget::SHARED_LIBRARY) ||
(l->second.GetType() == cmTarget::MODULE_LIBRARY) ||
+ (l->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
(l->second.GetType() == cmTarget::UTILITY))
{
// Add this to the list of depends rules in this directory.
@@ -587,6 +622,7 @@ cmGlobalUnixMakefileGenerator3
(t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
(t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
(t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
+ (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
(t->second.GetType() == cmTarget::UTILITY)))
{
// Add a rule to build the target by name.
@@ -673,6 +709,7 @@ cmGlobalUnixMakefileGenerator3
|| (t->second.GetType() == cmTarget::STATIC_LIBRARY)
|| (t->second.GetType() == cmTarget::SHARED_LIBRARY)
|| (t->second.GetType() == cmTarget::MODULE_LIBRARY)
+ || (t->second.GetType() == cmTarget::OBJECT_LIBRARY)
|| (t->second.GetType() == cmTarget::UTILITY)))
{
std::string makefileName;
@@ -982,6 +1019,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule
(t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
(t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
(t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
+ (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
(t->second.GetType() == cmTarget::GLOBAL_TARGET) ||
(t->second.GetType() == cmTarget::UTILITY))
{
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 9663b55..e6dd09d 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -182,6 +182,8 @@ protected:
size_t CountProgressMarksInAll(cmLocalUnixMakefileGenerator3* lg);
cmGeneratedFileStream *CommandDatabase;
+private:
+ virtual void ComputeTargetObjects(cmGeneratorTarget* gt) const;
};
#endif
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 18b483d..750b89c 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -72,7 +72,7 @@ public:
* Studio?
*/
virtual std::string GetUserMacrosRegKeyBase();
- virtual const char* GetCMakeCFGInitDirectory()
+ virtual const char* GetCMakeCFGIntDir() const
{ return "$(Configuration)";}
bool Find64BitTools(cmMakefile* mf);
protected:
diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h
index 77d5370..da08a12 100644
--- a/Source/cmGlobalVisualStudio6Generator.h
+++ b/Source/cmGlobalVisualStudio6Generator.h
@@ -82,7 +82,7 @@ public:
std::string& dir);
///! What is the configurations directory variable called?
- virtual const char* GetCMakeCFGInitDirectory() { return "$(IntDir)"; }
+ virtual const char* GetCMakeCFGIntDir() const { return "$(IntDir)"; }
protected:
virtual const char* GetIDEVersion() { return "6.0"; }
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index adfb757..c92998e 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -87,7 +87,7 @@ public:
std::string& dir);
///! What is the configurations directory variable called?
- virtual const char* GetCMakeCFGInitDirectory() { return "$(OutDir)"; }
+ virtual const char* GetCMakeCFGIntDir() const { return "$(OutDir)"; }
/** Return true if the target project file should have the option
LinkLibraryDependencies and link to .sln dependencies. */
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 449d090..2a918c9 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -12,8 +12,10 @@
#include "cmGlobalVisualStudioGenerator.h"
#include "cmCallVisualStudioMacro.h"
-#include "cmLocalGenerator.h"
+#include "cmGeneratorTarget.h"
+#include "cmLocalVisualStudioGenerator.h"
#include "cmMakefile.h"
+#include "cmSourceFile.h"
#include "cmTarget.h"
//----------------------------------------------------------------------------
@@ -93,11 +95,79 @@ void cmGlobalVisualStudioGenerator::Generate()
// of Visual Studio.
this->ConfigureCMakeVisualStudioMacros();
+ // Add CMakeLists.txt with custom command to rerun CMake.
+ for(std::vector<cmLocalGenerator*>::const_iterator
+ lgi = this->LocalGenerators.begin();
+ lgi != this->LocalGenerators.end(); ++lgi)
+ {
+ cmLocalVisualStudioGenerator* lg =
+ static_cast<cmLocalVisualStudioGenerator*>(*lgi);
+ lg->AddCMakeListsRules();
+ }
+
// Run all the local generators.
this->cmGlobalGenerator::Generate();
}
//----------------------------------------------------------------------------
+void
+cmGlobalVisualStudioGenerator
+::ComputeTargetObjects(cmGeneratorTarget* gt) const
+{
+ cmLocalVisualStudioGenerator* lg =
+ static_cast<cmLocalVisualStudioGenerator*>(gt->LocalGenerator);
+ std::string dir_max = lg->ComputeLongestObjectDirectory(*gt->Target);
+
+ // Count the number of object files with each name. Note that
+ // windows file names are not case sensitive.
+ std::map<cmStdString, int> counts;
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = gt->ObjectSources.begin();
+ si != gt->ObjectSources.end(); ++si)
+ {
+ cmSourceFile* sf = *si;
+ std::string objectNameLower = cmSystemTools::LowerCase(
+ cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
+ objectNameLower += ".obj";
+ counts[objectNameLower] += 1;
+ }
+
+ // For all source files producing duplicate names we need unique
+ // object name computation.
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = gt->ObjectSources.begin();
+ si != gt->ObjectSources.end(); ++si)
+ {
+ cmSourceFile* sf = *si;
+ std::string objectName =
+ cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
+ objectName += ".obj";
+ if(counts[cmSystemTools::LowerCase(objectName)] > 1)
+ {
+ gt->ExplicitObjectName.insert(sf);
+ objectName = lg->GetObjectFileNameWithoutTarget(*sf, dir_max);
+ }
+ gt->Objects[sf] = objectName;
+ }
+
+ std::string dir = gt->Makefile->GetCurrentOutputDirectory();
+ dir += "/";
+ std::string tgtDir = lg->GetTargetDirectory(*gt->Target);
+ if(!tgtDir.empty())
+ {
+ dir += tgtDir;
+ dir += "/";
+ }
+ const char* cd = this->GetCMakeCFGIntDir();
+ if(cd && *cd)
+ {
+ dir += cd;
+ dir += "/";
+ }
+ gt->ObjectDirectory = dir;
+}
+
+//----------------------------------------------------------------------------
bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile,
const std::string& regKeyBase,
std::string& nextAvailableSubKeyName);
@@ -315,6 +385,12 @@ bool cmGlobalVisualStudioGenerator::ComputeTargetDepends()
}
//----------------------------------------------------------------------------
+static bool VSLinkable(cmTarget* t)
+{
+ return t->IsLinkable() || t->GetType() == cmTarget::OBJECT_LIBRARY;
+}
+
+//----------------------------------------------------------------------------
void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target)
{
if(this->VSTargetDepends.find(&target) != this->VSTargetDepends.end())
@@ -398,7 +474,7 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(cmTarget& target)
di != utilDepends.end(); ++di)
{
cmTarget* dep = *di;
- if(allowLinkable || !dep->IsLinkable() || linked.count(dep))
+ if(allowLinkable || !VSLinkable(dep) || linked.count(dep))
{
// Direct dependency allowed.
vsTargetDepend.insert(dep->GetName());
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index bc96f4e..b62ba22 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -97,6 +97,8 @@ protected:
typedef std::map<cmTarget*, cmStdString> UtilityDependsMap;
UtilityDependsMap UtilityDepends;
private:
+ void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+
void FollowLinkDepends(cmTarget* target, std::set<cmTarget*>& linked);
class TargetSetMap: public std::map<cmTarget*, TargetSet> {};
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 859503f..998843f 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -19,6 +19,7 @@
#include "cmComputeLinkInformation.h"
#include "cmSourceFile.h"
#include "cmCustomCommandGenerator.h"
+#include "cmGeneratorTarget.h"
#include <cmsys/auto_ptr.hxx>
@@ -135,8 +136,17 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::New()
{
#if defined(CMAKE_BUILD_WITH_CMAKE)
cmXcodeVersionParser parser;
- parser.ParseFile
- ("/Developer/Applications/Xcode.app/Contents/version.plist");
+ if (cmSystemTools::FileExists(
+ "/Applications/Xcode.app/Contents/version.plist"))
+ {
+ parser.ParseFile
+ ("/Applications/Xcode.app/Contents/version.plist");
+ }
+ else
+ {
+ parser.ParseFile
+ ("/Developer/Applications/Xcode.app/Contents/version.plist");
+ }
cmsys::auto_ptr<cmGlobalXCodeGenerator>
gg(new cmGlobalXCodeGenerator(parser.Version));
if (gg->XcodeVersion == 20)
@@ -179,8 +189,6 @@ void cmGlobalXCodeGenerator::EnableLanguage(std::vector<std::string>const&
mf->AddDefinition("CMAKE_GENERATOR_CC", "gcc");
mf->AddDefinition("CMAKE_GENERATOR_CXX", "g++");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
- // initialize Architectures so it can be used by
- // GetTargetObjectFileDirectories
this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
const char* osxArch =
mf->GetDefinition("CMAKE_OSX_ARCHITECTURES");
@@ -296,6 +304,10 @@ void cmGlobalXCodeGenerator::Generate()
}
this->ForceLinkerLanguages();
this->cmGlobalGenerator::Generate();
+ if(cmSystemTools::GetErrorOccuredFlag())
+ {
+ return;
+ }
for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
{
cmLocalGenerator* root = it->second[0];
@@ -410,6 +422,8 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
// this will make sure that when the next target is built
// things are up-to-date
if((target.GetType() == cmTarget::EXECUTABLE ||
+// Nope - no post-build for OBJECT_LIRBRARY
+// target.GetType() == cmTarget::OBJECT_LIBRARY ||
target.GetType() == cmTarget::STATIC_LIBRARY ||
target.GetType() == cmTarget::SHARED_LIBRARY ||
target.GetType() == cmTarget::MODULE_LIBRARY))
@@ -563,15 +577,43 @@ cmXCodeObject* cmGlobalXCodeGenerator
}
//----------------------------------------------------------------------------
-cmStdString GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf)
+cmStdString
+GetGroupMapKeyFromPath(cmTarget& cmtarget, const std::string& fullpath)
{
cmStdString key(cmtarget.GetName());
key += "-";
- key += sf->GetFullPath();
+ key += fullpath;
return key;
}
//----------------------------------------------------------------------------
+cmStdString
+GetGroupMapKey(cmTarget& cmtarget, cmSourceFile* sf)
+{
+ return GetGroupMapKeyFromPath(cmtarget, sf->GetFullPath());
+}
+
+//----------------------------------------------------------------------------
+cmXCodeObject*
+cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
+ const std::string &fullpath,
+ cmTarget& cmtarget,
+ const std::string &lang)
+{
+ // Using a map and the full path guarantees that we will always get the same
+ // fileRef object for any given full path.
+ //
+ cmXCodeObject* fileRef =
+ this->CreateXCodeFileReferenceFromPath(fullpath, cmtarget, lang);
+
+ cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
+ buildFile->SetComment(fileRef->GetComment());
+ buildFile->AddAttribute("fileRef", this->CreateObjectReference(fileRef));
+
+ return buildFile;
+}
+
+//----------------------------------------------------------------------------
cmXCodeObject*
cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
cmSourceFile* sf,
@@ -605,14 +647,16 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
flags += flagsBuild.GetString();
}
- // Using a map and the full path guarantees that we will always get the same
- // fileRef object for any given full path.
- //
- cmXCodeObject* fileRef = this->CreateXCodeFileReference(sf, cmtarget);
+ const char* lang =
+ this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
+ if (!lang)
+ {
+ lang = "";
+ }
- cmXCodeObject* buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
- buildFile->SetComment(fileRef->GetComment());
- buildFile->AddAttribute("fileRef", this->CreateObjectReference(fileRef));
+ cmXCodeObject* buildFile =
+ this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), cmtarget, lang);
+ cmXCodeObject* fileRef = buildFile->GetObject("fileRef")->GetObject();
cmXCodeObject* settings =
this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
@@ -664,36 +708,12 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
}
//----------------------------------------------------------------------------
-cmXCodeObject*
-cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf,
- cmTarget& cmtarget)
+std::string
+GetSourcecodeValueFromFileExtension(const std::string& _ext,
+ const std::string& lang)
{
- std::string fname = sf->GetFullPath();
- cmXCodeObject* fileRef = this->FileRefs[fname];
- if(!fileRef)
- {
- fileRef = this->CreateObject(cmXCodeObject::PBXFileReference);
- std::string comment = fname;
- //comment += " in ";
- //std::string gname = group->GetObject("name")->GetString();
- //comment += gname.substr(1, gname.size()-2);
- fileRef->SetComment(fname.c_str());
- this->FileRefs[fname] = fileRef;
- }
- cmStdString key = GetGroupMapKey(cmtarget, sf);
- cmXCodeObject* group = this->GroupMap[key];
- cmXCodeObject* children = group->GetObject("children");
- if (!children->HasObject(fileRef))
- {
- children->AddObject(fileRef);
- }
- fileRef->AddAttribute("fileEncoding", this->CreateString("4"));
-
- const char* lang =
- this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
+ std::string ext = cmSystemTools::LowerCase(_ext);
std::string sourcecode = "sourcecode";
- std::string ext = sf->GetExtension();
- ext = cmSystemTools::LowerCase(ext);
if(ext == "o")
{
@@ -728,25 +748,25 @@ cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf,
{
sourcecode += ".cpp.h";
}
- else if(lang && strcmp(lang, "CXX") == 0)
+ else if(ext == "png" || ext == "gif" || ext == "jpg")
{
- sourcecode += ".cpp.cpp";
+ sourcecode = "image";
}
- else if(lang && strcmp(lang, "C") == 0)
+ else if(ext == "txt")
{
- sourcecode += ".c.c";
+ sourcecode += ".text";
}
- else if(lang && strcmp(lang, "Fortran") == 0)
+ else if(lang == "CXX")
{
- sourcecode += ".fortran.f90";
+ sourcecode += ".cpp.cpp";
}
- else if(ext == "png" || ext == "gif" || ext == "jpg")
+ else if(lang == "C")
{
- sourcecode = "image";
+ sourcecode += ".c.c";
}
- else if(ext == "txt")
+ else if(lang == "Fortran")
{
- sourcecode += ".text";
+ sourcecode += ".fortran.f90";
}
//else
// {
@@ -756,11 +776,51 @@ cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf,
// // valid lastKnownFileType value.
// }
+ return sourcecode;
+}
+
+//----------------------------------------------------------------------------
+cmXCodeObject*
+cmGlobalXCodeGenerator::CreateXCodeFileReferenceFromPath(
+ const std::string &fullpath,
+ cmTarget& cmtarget,
+ const std::string &lang)
+{
+ std::string fname = fullpath;
+ cmXCodeObject* fileRef = this->FileRefs[fname];
+ if(!fileRef)
+ {
+ fileRef = this->CreateObject(cmXCodeObject::PBXFileReference);
+ std::string comment = fname;
+ fileRef->SetComment(fname.c_str());
+ this->FileRefs[fname] = fileRef;
+ }
+ cmStdString key = GetGroupMapKeyFromPath(cmtarget, fullpath);
+ cmXCodeObject* group = this->GroupMap[key];
+ cmXCodeObject* children = group->GetObject("children");
+ if (!children->HasObject(fileRef))
+ {
+ children->AddObject(fileRef);
+ }
+ fileRef->AddAttribute("fileEncoding", this->CreateString("4"));
+
+ // Compute the extension.
+ std::string ext;
+ std::string realExt =
+ cmSystemTools::GetFilenameLastExtension(fullpath);
+ if(!realExt.empty())
+ {
+ // Extension without the leading '.'.
+ ext = realExt.substr(1);
+ }
+
+ std::string sourcecode = GetSourcecodeValueFromFileExtension(ext, lang);
+
fileRef->AddAttribute("lastKnownFileType",
this->CreateString(sourcecode.c_str()));
// Store the file path relative to the top of the source tree.
- std::string path = this->RelativeToSource(sf->GetFullPath().c_str());
+ std::string path = this->RelativeToSource(fullpath.c_str());
std::string name = cmSystemTools::GetFilenameName(path.c_str());
const char* sourceTree = (cmSystemTools::FileIsFullPath(path.c_str())?
"<absolute>" : "SOURCE_ROOT");
@@ -775,6 +835,22 @@ cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf,
}
//----------------------------------------------------------------------------
+cmXCodeObject*
+cmGlobalXCodeGenerator::CreateXCodeFileReference(cmSourceFile* sf,
+ cmTarget& cmtarget)
+{
+ const char* lang =
+ this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
+ if (!lang)
+ {
+ lang = "";
+ }
+
+ return this->CreateXCodeFileReferenceFromPath(
+ sf->GetFullPath(), cmtarget, lang);
+}
+
+//----------------------------------------------------------------------------
bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string const& tname)
{
if(tname == "ALL_BUILD" || tname == "XCODE_DEPEND_HELPER" ||
@@ -882,6 +958,20 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
}
}
+ // Add object library contents as external objects. (Equivalent to
+ // the externalObjFiles above, except each one is not a cmSourceFile
+ // within the target.)
+ std::vector<std::string> objs;
+ this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ std::string obj = *oi;
+ cmXCodeObject* xsf =
+ this->CreateXCodeSourceFileFromPath(obj, cmtarget, "");
+ externalObjFiles.push_back(xsf);
+ }
+
// some build phases only apply to bundles and/or frameworks
bool isFrameworkTarget = cmtarget.IsFrameworkOnApple();
bool isBundleTarget = cmtarget.GetPropertyAsBool("MACOSX_BUNDLE");
@@ -1487,7 +1577,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
std::string defFlags;
bool shared = ((target.GetType() == cmTarget::SHARED_LIBRARY) ||
(target.GetType() == cmTarget::MODULE_LIBRARY));
- bool binary = ((target.GetType() == cmTarget::STATIC_LIBRARY) ||
+ bool binary = ((target.GetType() == cmTarget::OBJECT_LIBRARY) ||
+ (target.GetType() == cmTarget::STATIC_LIBRARY) ||
(target.GetType() == cmTarget::EXECUTABLE) ||
shared);
@@ -1574,7 +1665,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
}
const char* linkFlagsProp = "LINK_FLAGS";
- if(target.GetType() == cmTarget::STATIC_LIBRARY)
+ if(target.GetType() == cmTarget::OBJECT_LIBRARY ||
+ target.GetType() == cmTarget::STATIC_LIBRARY)
{
linkFlagsProp = "STATIC_LIBRARY_FLAGS";
}
@@ -1628,11 +1720,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
std::string pnprefix;
std::string pnbase;
std::string pnsuffix;
- target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
- // Store the product name for all target types.
- buildSettings->AddAttribute("PRODUCT_NAME",
- this->CreateString(pnbase.c_str()));
+ target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
// Set attributes to specify the proper name for the target.
std::string pndir = this->CurrentMakefile->GetCurrentOutputDirectory();
@@ -1656,17 +1745,44 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
this->CreateString(pndir.c_str()));
pndir = target.GetDirectory(configName);
}
+
buildSettings->AddAttribute("EXECUTABLE_PREFIX",
this->CreateString(pnprefix.c_str()));
buildSettings->AddAttribute("EXECUTABLE_SUFFIX",
this->CreateString(pnsuffix.c_str()));
}
+ else if(target.GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ pnprefix = "lib";
+ pnbase = target.GetName();
+ pnsuffix = ".a";
+
+ if(this->XcodeVersion >= 21)
+ {
+ std::string pncdir = this->GetObjectsNormalDirectory(
+ this->CurrentProject, configName, &target);
+ buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR",
+ this->CreateString(pncdir.c_str()));
+ }
+ else
+ {
+ buildSettings->AddAttribute("OBJROOT",
+ this->CreateString(pndir.c_str()));
+ pndir = this->GetObjectsNormalDirectory(
+ this->CurrentProject, configName, &target);
+ }
+ }
+
+ // Store the product name for all target types.
+ buildSettings->AddAttribute("PRODUCT_NAME",
+ this->CreateString(pnbase.c_str()));
buildSettings->AddAttribute("SYMROOT",
this->CreateString(pndir.c_str()));
// Handle settings for each target type.
switch(target.GetType())
{
+ case cmTarget::OBJECT_LIBRARY:
case cmTarget::STATIC_LIBRARY:
{
buildSettings->AddAttribute("LIBRARY_STYLE",
@@ -1811,7 +1927,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
BuildObjectListOrString dirs(this, this->XcodeVersion >= 30);
BuildObjectListOrString fdirs(this, this->XcodeVersion >= 30);
std::vector<std::string> includes;
- this->CurrentLocalGenerator->GetIncludeDirectories(includes);
+ this->CurrentLocalGenerator->GetIncludeDirectories(includes, &target);
std::set<cmStdString> emitted;
emitted.insert("/System/Library/Frameworks");
for(std::vector<std::string>::iterator i = includes.begin();
@@ -2170,6 +2286,7 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType(cmTarget& cmtarget)
{
switch(cmtarget.GetType())
{
+ case cmTarget::OBJECT_LIBRARY:
case cmTarget::STATIC_LIBRARY:
return "archive.ar";
case cmTarget::MODULE_LIBRARY:
@@ -2193,6 +2310,7 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType(cmTarget& cmtarget)
{
switch(cmtarget.GetType())
{
+ case cmTarget::OBJECT_LIBRARY:
case cmTarget::STATIC_LIBRARY:
return "com.apple.product-type.library.static";
case cmTarget::MODULE_LIBRARY:
@@ -2250,7 +2368,17 @@ cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget,
{
fileRef->AddAttribute("explicitFileType", this->CreateString(fileType));
}
- std::string fullName = cmtarget.GetFullName(defConfig.c_str());
+ std::string fullName;
+ if(cmtarget.GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ fullName = "lib";
+ fullName += cmtarget.GetName();
+ fullName += ".a";
+ }
+ else
+ {
+ fullName = cmtarget.GetFullName(defConfig.c_str());
+ }
fileRef->AddAttribute("path", this->CreateString(fullName.c_str()));
fileRef->AddAttribute("refType", this->CreateString("0"));
fileRef->AddAttribute("sourceTree",
@@ -2455,7 +2583,8 @@ void cmGlobalXCodeGenerator
}
// Skip link information for static libraries.
- if(cmtarget->GetType() == cmTarget::STATIC_LIBRARY)
+ if(cmtarget->GetType() == cmTarget::OBJECT_LIBRARY ||
+ cmtarget->GetType() == cmTarget::STATIC_LIBRARY)
{
return;
}
@@ -2603,6 +2732,7 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root,
std::vector<cmSourceFile*> classes = cmtarget.GetSourceFiles();
+ // Put cmSourceFile instances in proper groups:
for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
s != classes.end(); s++)
{
@@ -2616,6 +2746,21 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root,
cmStdString key = GetGroupMapKey(cmtarget, sf);
this->GroupMap[key] = pbxgroup;
}
+
+ // Put OBJECT_LIBRARY objects in proper groups:
+ std::vector<std::string> objs;
+ this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs);
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ std::string const& source = *oi;
+ cmSourceGroup& sourceGroup =
+ mf->FindSourceGroup(source.c_str(), sourceGroups);
+ cmXCodeObject* pbxgroup =
+ this->CreateOrGetPBXGroup(cmtarget, &sourceGroup);
+ cmStdString key = GetGroupMapKeyFromPath(cmtarget, source);
+ this->GroupMap[key] = pbxgroup;
+ }
}
}
}
@@ -2878,6 +3023,7 @@ void cmGlobalXCodeGenerator
cmXCodeObject* buildConfigurations =
this->CreateObject(cmXCodeObject::OBJECT_LIST);
std::vector<cmXCodeObject*> configs;
+ const char *defaultConfigName = "Debug";
if(this->XcodeVersion == 15)
{
cmXCodeObject* configDebug =
@@ -2894,6 +3040,10 @@ void cmGlobalXCodeGenerator
for(unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i)
{
const char* name = this->CurrentConfigurationTypes[i].c_str();
+ if (0 == i)
+ {
+ defaultConfigName = name;
+ }
cmXCodeObject* config =
this->CreateObject(cmXCodeObject::XCBuildConfiguration);
config->AddAttribute("name", this->CreateString(name));
@@ -2915,7 +3065,7 @@ void cmGlobalXCodeGenerator
configlist->AddAttribute("defaultConfigurationIsVisible",
this->CreateString("0"));
configlist->AddAttribute("defaultConfigurationName",
- this->CreateString("Debug"));
+ this->CreateString(defaultConfigName));
cmXCodeObject* buildSettings =
this->CreateObject(cmXCodeObject::ATTRIBUTE_GROUP);
const char* osxArch =
@@ -3048,6 +3198,26 @@ void cmGlobalXCodeGenerator
}
//----------------------------------------------------------------------------
+std::string
+cmGlobalXCodeGenerator::GetObjectsNormalDirectory(
+ const std::string &projName,
+ const std::string &configName,
+ const cmTarget *t) const
+{
+ std::string dir =
+ t->GetMakefile()->GetCurrentOutputDirectory();
+ dir += "/";
+ dir += projName;
+ dir += ".build/";
+ dir += configName;
+ dir += "/";
+ dir += t->GetName();
+ dir += ".build/Objects-normal/";
+
+ return dir;
+}
+
+//----------------------------------------------------------------------------
void
cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
std::vector<cmXCodeObject*>& targets)
@@ -3116,6 +3286,8 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
cmTarget* t =target->GetTarget();
if(t->GetType() == cmTarget::EXECUTABLE ||
+// Nope - no post-build for OBJECT_LIRBRARY
+// t->GetType() == cmTarget::OBJECT_LIBRARY ||
t->GetType() == cmTarget::STATIC_LIBRARY ||
t->GetType() == cmTarget::SHARED_LIBRARY ||
t->GetType() == cmTarget::MODULE_LIBRARY)
@@ -3171,15 +3343,8 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
// then remove those exectuables as well
if(this->Architectures.size() > 1)
{
- std::string universal =
- t->GetMakefile()->GetCurrentOutputDirectory();
- universal += "/";
- universal += this->CurrentProject;
- universal += ".build/";
- universal += configName;
- universal += "/";
- universal += t->GetName();
- universal += ".build/Objects-normal/";
+ std::string universal = this->GetObjectsNormalDirectory(
+ this->CurrentProject, configName, t);
for( std::vector<std::string>::iterator arch =
this->Architectures.begin();
arch != this->Architectures.end(); ++arch)
@@ -3285,7 +3450,7 @@ cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
}
//----------------------------------------------------------------------------
-const char* cmGlobalXCodeGenerator::GetCMakeCFGInitDirectory()
+const char* cmGlobalXCodeGenerator::GetCMakeCFGIntDir() const
{
return this->XcodeVersion >= 21 ?
"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" : ".";
@@ -3363,37 +3528,6 @@ std::string cmGlobalXCodeGenerator::XCodeEscapePath(const char* p)
}
//----------------------------------------------------------------------------
-void cmGlobalXCodeGenerator::
-GetTargetObjectFileDirectories(cmTarget* target,
- std::vector<std::string>&
- dirs)
-{
- std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory();
- dir += "/";
- dir += this->CurrentMakefile->GetProjectName();
- dir += ".build/";
- dir += this->GetCMakeCFGInitDirectory();
- dir += "/";
- dir += target->GetName();
- dir += ".build/Objects-normal/";
- std::string dirsave = dir;
- if(this->Architectures.size())
- {
- for(std::vector<std::string>::iterator i = this->Architectures.begin();
- i != this->Architectures.end(); ++i)
- {
- dir += *i;
- dirs.push_back(dir);
- dir = dirsave;
- }
- }
- else
- {
- dirs.push_back(dir);
- }
-}
-
-//----------------------------------------------------------------------------
void
cmGlobalXCodeGenerator
::AppendDirectoryForConfig(const char* prefix,
@@ -3569,3 +3703,51 @@ bool cmGlobalXCodeGenerator::IsMultiConfig()
// Newer Xcode versions are multi config:
return true;
}
+
+ //----------------------------------------------------------------------------
+void
+cmGlobalXCodeGenerator
+::ComputeTargetObjects(cmGeneratorTarget* gt) const
+{
+ // Count the number of object files with each name. Warn about duplicate
+ // names since Xcode names them uniquely automatically with a numeric suffix
+ // to avoid exact duplicate file names. Note that Mac file names are not
+ // typically case sensitive, hence the LowerCase.
+ std::map<cmStdString, int> counts;
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = gt->ObjectSources.begin();
+ si != gt->ObjectSources.end(); ++si)
+ {
+ cmSourceFile* sf = *si;
+ std::string objectName =
+ cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
+ objectName += ".o";
+
+ std::string objectNameLower = cmSystemTools::LowerCase(objectName);
+ counts[objectNameLower] += 1;
+ if (2 == counts[objectNameLower])
+ {
+ // TODO: emit warning about duplicate name?
+ }
+
+ gt->Objects[sf] = objectName;
+ }
+
+ const char* configName = this->GetCMakeCFGIntDir();
+ std::string dir = this->GetObjectsNormalDirectory(
+ this->CurrentProject, configName, gt->Target);
+ if(this->XcodeVersion >= 21)
+ {
+ dir += "$(CURRENT_ARCH)/";
+ }
+ else
+ {
+#ifdef __ppc__
+ dir += "ppc/";
+#endif
+#ifdef __i386
+ dir += "i386/";
+#endif
+ }
+ gt->ObjectDirectory = dir;
+}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index ed54be3..800963b 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -74,11 +74,8 @@ public:
std::string& dir);
///! What is the configurations directory variable called?
- virtual const char* GetCMakeCFGInitDirectory();
+ virtual const char* GetCMakeCFGIntDir() const;
- void GetTargetObjectFileDirectories(cmTarget* target,
- std::vector<std::string>&
- dirs);
void SetCurrentLocalGenerator(cmLocalGenerator*);
/** Return true if the generated build tree may contain multiple builds.
@@ -156,6 +153,12 @@ private:
std::vector<cmLocalGenerator*>& generators);
void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
+ cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string &fullpath,
+ cmTarget& cmtarget,
+ const std::string &lang);
+ cmXCodeObject* CreateXCodeSourceFileFromPath(const std::string &fullpath,
+ cmTarget& cmtarget,
+ const std::string &lang);
cmXCodeObject* CreateXCodeFileReference(cmSourceFile* sf,
cmTarget& cmtarget);
cmXCodeObject* CreateXCodeSourceFile(cmLocalGenerator* gen,
@@ -203,6 +206,13 @@ protected:
std::vector<cmXCodeObject*> XCodeObjects;
cmXCodeObject* RootObject;
private:
+ void ComputeTargetObjects(cmGeneratorTarget* gt) const;
+
+ std::string GetObjectsNormalDirectory(
+ const std::string &projName,
+ const std::string &configName,
+ const cmTarget *t) const;
+
void addObject(cmXCodeObject *obj);
std::string PostBuildMakeTarget(std::string const& tName,
std::string const& configName);
diff --git a/Source/cmIncludeDirectoryCommand.h b/Source/cmIncludeDirectoryCommand.h
index b90fe42..dcc116a 100644
--- a/Source/cmIncludeDirectoryCommand.h
+++ b/Source/cmIncludeDirectoryCommand.h
@@ -58,13 +58,21 @@ public:
{
return
" include_directories([AFTER|BEFORE] [SYSTEM] dir1 dir2 ...)\n"
- "Add the given directories to those searched by the compiler for "
- "include files. By default the directories are appended onto "
- "the current list of directories. This default behavior can be "
- "changed by setting CMAKE_INCLUDE_DIRECTORIES_BEFORE to ON. "
- "By using BEFORE or AFTER you can select between appending and "
- "prepending, independent from the default. "
- "If the SYSTEM option is given the compiler will be told that the "
+ "Add the given directories to those the compiler uses to search "
+ "for include files. "
+ "These 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. "
+ "The target property values are the ones used by the generators."
+ "\n"
+ "By default the directories are appended onto the current list of "
+ "directories. "
+ "This default behavior can be changed by setting "
+ "CMAKE_INCLUDE_DIRECTORIES_BEFORE to ON. "
+ "By using AFTER or BEFORE explicitly, you can select between "
+ "appending and prepending, independent of the default. "
+ "If the SYSTEM option is given, the compiler will be told the "
"directories are meant as system include directories on some "
"platforms.";
}
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index dca528d..c656487 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -357,7 +357,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
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)
{
cmOStringStream e;
e << "TARGETS given target \"" << (*targetIt)
@@ -365,6 +366,14 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->SetError(e.str().c_str());
return false;
}
+ else if(target->GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "TARGETS given OBJECT library \"" << (*targetIt)
+ << "\" which may not be installed.";
+ this->SetError(e.str().c_str());
+ return false;
+ }
// Store the target in the list to be installed.
targets.push_back(target);
}
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index c74dda0..5f9b658 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -90,6 +90,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
case cmTarget::STATIC_LIBRARY: type = cmInstallType_STATIC_LIBRARY; break;
case cmTarget::SHARED_LIBRARY: type = cmInstallType_SHARED_LIBRARY; break;
case cmTarget::MODULE_LIBRARY: type = cmInstallType_MODULE_LIBRARY; break;
+ case cmTarget::OBJECT_LIBRARY:
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
case cmTarget::UNKNOWN_LIBRARY:
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index dc8d1c4..13ede5d 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -556,7 +556,7 @@ void cmLocalGenerator::GenerateTargetManifest()
void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname,
const char* lang,
cmSourceFile& source,
- cmTarget& )
+ cmTarget& target)
{
std::string objectDir = cmSystemTools::GetFilenamePath(std::string(ofname));
objectDir = this->Convert(objectDir.c_str(),START_OUTPUT,SHELL);
@@ -574,7 +574,11 @@ void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname,
std::string flags;
flags += this->Makefile->GetSafeDefinition(varString.c_str());
flags += " ";
- flags += this->GetIncludeFlags(lang);
+ {
+ std::vector<std::string> includes;
+ this->GetIncludeDirectories(includes, &target, lang);
+ flags += this->GetIncludeFlags(includes, lang);
+ }
flags += this->Makefile->GetDefineFlags();
// Construct the command lines.
@@ -1192,24 +1196,16 @@ cmLocalGenerator::ConvertToIncludeReference(std::string const& path)
}
//----------------------------------------------------------------------------
-const char* cmLocalGenerator::GetIncludeFlags(const char* lang,
- bool forResponseFile)
+std::string cmLocalGenerator::GetIncludeFlags(
+ const std::vector<std::string> &includes,
+ const char* lang, bool forResponseFile)
{
if(!lang)
{
return "";
}
- std::string key = lang;
- key += forResponseFile? "@" : "";
- if(this->LanguageToIncludeFlags.count(key))
- {
- return this->LanguageToIncludeFlags[key].c_str();
- }
cmOStringStream includeFlags;
- std::vector<std::string> includes;
- this->GetIncludeDirectories(includes, lang);
- std::vector<std::string>::iterator i;
std::string flagVar = "CMAKE_INCLUDE_FLAG_";
flagVar += lang;
@@ -1251,6 +1247,7 @@ const char* cmLocalGenerator::GetIncludeFlags(const char* lang,
#ifdef __APPLE__
emitted.insert("/System/Library/Frameworks");
#endif
+ std::vector<std::string>::const_iterator i;
for(i = includes.begin(); i != includes.end(); ++i)
{
if(this->Makefile->IsOn("APPLE")
@@ -1311,16 +1308,12 @@ const char* cmLocalGenerator::GetIncludeFlags(const char* lang,
{
flags[flags.size()-1] = ' ';
}
- this->LanguageToIncludeFlags[key] = flags;
-
- // Use this temorary variable for the return value to work-around a
- // bogus GCC 2.95 warning.
- const char* ret = this->LanguageToIncludeFlags[key].c_str();
- return ret;
+ return flags;
}
//----------------------------------------------------------------------------
void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
+ cmTarget* target,
const char* lang)
{
// Need to decide whether to automatically include the source and
@@ -1375,8 +1368,12 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
// Store the automatic include paths.
if(includeBinaryDir)
{
- dirs.push_back(this->Makefile->GetStartOutputDirectory());
- emitted.insert(this->Makefile->GetStartOutputDirectory());
+ if(emitted.find(
+ this->Makefile->GetStartOutputDirectory()) == emitted.end())
+ {
+ dirs.push_back(this->Makefile->GetStartOutputDirectory());
+ emitted.insert(this->Makefile->GetStartOutputDirectory());
+ }
}
if(includeSourceDir)
{
@@ -1402,9 +1399,12 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
}
}
- // Get the project-specified include directories.
- std::vector<std::string>& includes =
- this->Makefile->GetIncludeDirectories();
+ // Get the target-specific include directories.
+ std::vector<std::string> includes;
+ if(target)
+ {
+ includes = target->GetIncludeDirectories();
+ }
// Support putting all the in-project include directories first if
// it is requested by the project.
@@ -1412,7 +1412,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
{
const char* topSourceDir = this->Makefile->GetHomeDirectory();
const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory();
- for(std::vector<std::string>::iterator i = includes.begin();
+ for(std::vector<std::string>::const_iterator i = includes.begin();
i != includes.end(); ++i)
{
// Emit this directory only if it is a subdirectory of the
@@ -1431,7 +1431,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
}
// Construct the final ordered include directory list.
- for(std::vector<std::string>::iterator i = includes.begin();
+ for(std::vector<std::string>::const_iterator i = includes.begin();
i != includes.end(); ++i)
{
if(emitted.insert(*i).second)
@@ -1503,7 +1503,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
linkFlags +=
this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
linkFlags += this->Convert(sf->GetFullPath().c_str(),
- START_OUTPUT, SHELL);
+ FULL, SHELL);
linkFlags += " ";
}
}
@@ -1583,6 +1583,16 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
this->Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE");
linkFlags += " ";
}
+ if (target.IsExecutableWithExports())
+ {
+ std::string exportFlagVar = "CMAKE_EXE_EXPORTS_";
+ exportFlagVar += linkLanguage;
+ exportFlagVar += "_FLAG";
+
+ linkFlags +=
+ this->Makefile->GetSafeDefinition(exportFlagVar.c_str());
+ linkFlags += " ";
+ }
const char* targetLinkFlags = target.GetProperty("LINK_FLAGS");
if(targetLinkFlags)
{
@@ -1904,6 +1914,10 @@ bool cmLocalGenerator::GetRealDependency(const char* inName,
case cmTarget::UNKNOWN_LIBRARY:
dep = target->GetLocation(config);
return true;
+ case cmTarget::OBJECT_LIBRARY:
+ // An object library has no single file on which to depend.
+ // This was listed to get the target-level dependency.
+ return false;
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
// A utility target has no file on which to depend. This was listed
@@ -2963,17 +2977,6 @@ cmLocalGenerator::GetTargetDirectory(cmTarget const&) const
return "";
}
-
-//----------------------------------------------------------------------------
-void
-cmLocalGenerator::GetTargetObjectFileDirectories(cmTarget* ,
- std::vector<std::string>&
- )
-{
- cmSystemTools::Error("GetTargetObjectFileDirectories"
- " called on cmLocalGenerator");
-}
-
//----------------------------------------------------------------------------
unsigned int cmLocalGenerator::GetBackwardsCompatibility()
{
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index c3d057f..3e93819 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -146,8 +146,8 @@ public:
///! Append flags to a string.
virtual void AppendFlags(std::string& flags, const char* newFlags);
///! Get the include flags for the current makefile and language
- const char* GetIncludeFlags(const char* lang,
- bool forResponseFile = false);
+ std::string GetIncludeFlags(const std::vector<std::string> &includes,
+ const char* lang, bool forResponseFile = false);
/**
* Encode a list of preprocessor definitions for the compiler
@@ -198,6 +198,7 @@ public:
/** Get the include flags for the current makefile and language. */
void GetIncludeDirectories(std::vector<std::string>& dirs,
+ cmTarget* target,
const char* lang = "C");
/** Compute the language used to compile the given source file. */
@@ -250,7 +251,7 @@ public:
std::string EscapeForShellOldStyle(const char* str);
/** Escape the given string as an argument in a CMake script. */
- std::string EscapeForCMake(const char* str);
+ static std::string EscapeForCMake(const char* str);
enum FortranFormat
{
@@ -260,14 +261,6 @@ public:
};
FortranFormat GetFortranFormat(const char* value);
- /** Return the directories into which object files will be put.
- * There maybe more than one for fat binary systems like OSX.
- */
- virtual void
- GetTargetObjectFileDirectories(cmTarget* target,
- std::vector<std::string>&
- dirs);
-
/**
* Convert the given remote path to a relative path with respect to
* the given local path. The local path must be given in component
@@ -395,7 +388,6 @@ protected:
std::vector<std::string> StartOutputDirectoryComponents;
cmLocalGenerator* Parent;
std::vector<cmLocalGenerator*> Children;
- std::map<cmStdString, cmStdString> LanguageToIncludeFlags;
std::map<cmStdString, cmStdString> UniqueObjectNamesMap;
std::string::size_type ObjectPathMax;
std::set<cmStdString> ObjectMaxPathViolations;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
new file mode 100644
index 0000000..425b219
--- /dev/null
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -0,0 +1,393 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 "cmLocalNinjaGenerator.h"
+#include "cmCustomCommandGenerator.h"
+#include "cmMakefile.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmNinjaTargetGenerator.h"
+#include "cmGeneratedFileStream.h"
+#include "cmSourceFile.h"
+#include "cmComputeLinkInformation.h"
+#include "cmake.h"
+
+#include <assert.h>
+
+cmLocalNinjaGenerator::cmLocalNinjaGenerator()
+ : cmLocalGenerator()
+ , ConfigName("")
+ , HomeRelativeOutputPath("")
+{
+ this->IsMakefileGenerator = true;
+#ifdef _WIN32
+ this->WindowsShell = true;
+#endif
+ this->TargetImplib = "$TARGET_IMPLIB";
+}
+
+//----------------------------------------------------------------------------
+// Virtual public methods.
+
+cmLocalNinjaGenerator::~cmLocalNinjaGenerator()
+{
+}
+
+void cmLocalNinjaGenerator::Generate()
+{
+ this->SetConfigName();
+
+ this->WriteProcessedMakefile(this->GetBuildFileStream());
+ this->WriteProcessedMakefile(this->GetRulesFileStream());
+
+ this->WriteBuildFileTop();
+
+ cmTargets& targets = this->GetMakefile()->GetTargets();
+ for(cmTargets::iterator t = targets.begin(); t != targets.end(); ++t)
+ {
+ cmNinjaTargetGenerator* tg = cmNinjaTargetGenerator::New(&t->second);
+ if(tg)
+ {
+ tg->Generate();
+ // Add the target to "all" if required.
+ if (!this->GetGlobalNinjaGenerator()->IsExcluded(
+ this->GetGlobalNinjaGenerator()->LocalGenerators[0],
+ t->second))
+ this->GetGlobalNinjaGenerator()->AddDependencyToAll(&t->second);
+ delete tg;
+ }
+ }
+
+ this->WriteCustomCommandBuildStatements();
+}
+
+// Implemented in:
+// cmLocalUnixMakefileGenerator3.
+// Used in:
+// Source/cmMakefile.cxx
+// Source/cmGlobalGenerator.cxx
+void cmLocalNinjaGenerator::Configure()
+{
+ // Compute the path to use when referencing the current output
+ // directory from the top output directory.
+ this->HomeRelativeOutputPath =
+ this->Convert(this->Makefile->GetStartOutputDirectory(), HOME_OUTPUT);
+ if(this->HomeRelativeOutputPath == ".")
+ {
+ this->HomeRelativeOutputPath = "";
+ }
+ this->cmLocalGenerator::Configure();
+
+}
+
+// TODO: Picked up from cmLocalUnixMakefileGenerator3. Refactor it.
+std::string cmLocalNinjaGenerator
+::GetTargetDirectory(cmTarget const& target) const
+{
+ std::string dir = cmake::GetCMakeFilesDirectoryPostSlash();
+ dir += target.GetName();
+#if defined(__VMS)
+ dir += "_dir";
+#else
+ dir += ".dir";
+#endif
+ return dir;
+}
+
+//----------------------------------------------------------------------------
+// Non-virtual public methods.
+
+const cmGlobalNinjaGenerator*
+cmLocalNinjaGenerator::GetGlobalNinjaGenerator() const
+{
+ return
+ static_cast<const cmGlobalNinjaGenerator*>(this->GetGlobalGenerator());
+}
+
+cmGlobalNinjaGenerator* cmLocalNinjaGenerator::GetGlobalNinjaGenerator()
+{
+ return static_cast<cmGlobalNinjaGenerator*>(this->GetGlobalGenerator());
+}
+
+//----------------------------------------------------------------------------
+// Virtual protected methods.
+
+std::string
+cmLocalNinjaGenerator::ConvertToLinkReference(std::string const& lib)
+{
+ return this->Convert(lib.c_str(), HOME_OUTPUT, SHELL);
+}
+
+std::string
+cmLocalNinjaGenerator::ConvertToIncludeReference(std::string const& path)
+{
+ return this->Convert(path.c_str(), HOME_OUTPUT, SHELL);
+}
+
+//----------------------------------------------------------------------------
+// Private methods.
+
+cmGeneratedFileStream& cmLocalNinjaGenerator::GetBuildFileStream() const
+{
+ return *this->GetGlobalNinjaGenerator()->GetBuildFileStream();
+}
+
+cmGeneratedFileStream& cmLocalNinjaGenerator::GetRulesFileStream() const
+{
+ return *this->GetGlobalNinjaGenerator()->GetRulesFileStream();
+}
+
+const cmake* cmLocalNinjaGenerator::GetCMakeInstance() const
+{
+ return this->GetGlobalGenerator()->GetCMakeInstance();
+}
+
+cmake* cmLocalNinjaGenerator::GetCMakeInstance()
+{
+ return this->GetGlobalGenerator()->GetCMakeInstance();
+}
+
+bool cmLocalNinjaGenerator::isRootMakefile() const
+{
+ return (strcmp(this->Makefile->GetCurrentDirectory(),
+ this->GetCMakeInstance()->GetHomeDirectory()) == 0);
+}
+
+void cmLocalNinjaGenerator::WriteBuildFileTop()
+{
+ // We do that only once for the top CMakeLists.txt file.
+ if(!this->isRootMakefile())
+ return;
+
+ // For the build file.
+ this->WriteProjectHeader(this->GetBuildFileStream());
+ this->WriteNinjaFilesInclusion(this->GetBuildFileStream());
+
+ // For the rule file.
+ this->WriteProjectHeader(this->GetRulesFileStream());
+}
+
+void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os)
+{
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ os
+ << "# Project: " << this->GetMakefile()->GetProjectName() << std::endl
+ << "# Configuration: " << this->ConfigName << std::endl
+ ;
+ cmGlobalNinjaGenerator::WriteDivider(os);
+}
+
+void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os)
+{
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ os
+ << "# Include auxiliary files.\n"
+ << "\n"
+ ;
+ cmGlobalNinjaGenerator::WriteInclude(os,
+ cmGlobalNinjaGenerator::NINJA_RULES_FILE,
+ "Include rules file.");
+ os << "\n";
+}
+
+void cmLocalNinjaGenerator::SetConfigName()
+{
+ // Store the configuration name that will be generated.
+ if(const char* config =
+ this->GetMakefile()->GetDefinition("CMAKE_BUILD_TYPE"))
+ {
+ // Use the build type given by the user.
+ this->ConfigName = config;
+ }
+ else
+ {
+ // No configuration type given.
+ this->ConfigName = "";
+ }
+}
+
+void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os)
+{
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ os
+ << "# Write statements declared in CMakeLists.txt:" << std::endl
+ << "# " << this->Makefile->GetCurrentListFile() << std::endl
+ ;
+ if(this->isRootMakefile())
+ os << "# Which is the root file." << std::endl;
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ os << std::endl;
+}
+
+std::string cmLocalNinjaGenerator::ConvertToNinjaPath(const char *path)
+{
+ std::string convPath = this->Convert(path, cmLocalGenerator::HOME_OUTPUT);
+#ifdef _WIN32
+ cmSystemTools::ReplaceString(convPath, "/", "\\");
+#endif
+ return convPath;
+}
+
+void
+cmLocalNinjaGenerator
+::AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs)
+{
+ this->GetGlobalNinjaGenerator()->AppendTargetOutputs(target, outputs);
+}
+
+void
+cmLocalNinjaGenerator
+::AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs)
+{
+ this->GetGlobalNinjaGenerator()->AppendTargetDepends(target, outputs);
+}
+
+void cmLocalNinjaGenerator::AppendCustomCommandDeps(const cmCustomCommand *cc,
+ cmNinjaDeps &ninjaDeps)
+{
+ const std::vector<std::string> &deps = cc->GetDepends();
+ for (std::vector<std::string>::const_iterator i = deps.begin();
+ i != deps.end(); ++i) {
+ std::string dep;
+ if (this->GetRealDependency(i->c_str(), this->GetConfigName(), dep))
+ ninjaDeps.push_back(ConvertToNinjaPath(dep.c_str()));
+ }
+}
+
+std::string cmLocalNinjaGenerator::BuildCommandLine(
+ const std::vector<std::string> &cmdLines)
+{
+ // If we have no commands but we need to build a command anyway, use ":".
+ // This happens when building a POST_BUILD value for link targets that
+ // don't use POST_BUILD.
+ if (cmdLines.empty())
+#ifdef _WIN32
+ return "cd.";
+#else
+ return ":";
+#endif
+
+ // TODO: This will work only on Unix platforms. I don't
+ // want to use a link.txt file because I will lose the benefit of the
+ // $in variables. A discussion about dealing with multiple commands in
+ // a rule is started here:
+ // groups.google.com/group/ninja-build/browse_thread/thread/d515f23a78986008
+ std::ostringstream cmd;
+ for (std::vector<std::string>::const_iterator li = cmdLines.begin();
+ li != cmdLines.end(); ++li) {
+ if (li != cmdLines.begin())
+ cmd << " && ";
+ cmd << *li;
+ }
+ return cmd.str();
+}
+
+void cmLocalNinjaGenerator::AppendCustomCommandLines(const cmCustomCommand *cc,
+ std::vector<std::string> &cmdLines)
+{
+ cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->Makefile);
+ if (ccg.GetNumberOfCommands() > 0) {
+ const char* wd = cc->GetWorkingDirectory();
+ if (!wd)
+ wd = this->GetMakefile()->GetStartOutputDirectory();
+
+ std::ostringstream cdCmd;
+ cdCmd << "cd " << this->ConvertToOutputFormat(wd, SHELL);
+ cmdLines.push_back(cdCmd.str());
+ }
+ for (unsigned i = 0; i != ccg.GetNumberOfCommands(); ++i) {
+ cmdLines.push_back(this->ConvertToOutputFormat(ccg.GetCommand(i).c_str(),
+ SHELL));
+ std::string& cmd = cmdLines.back();
+ ccg.AppendArguments(i, cmd);
+ }
+}
+
+void
+cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
+ cmCustomCommand const *cc, const cmNinjaDeps& orderOnlyDeps)
+{
+ if (this->GetGlobalNinjaGenerator()->SeenCustomCommand(cc))
+ return;
+
+ const std::vector<std::string> &outputs = cc->GetOutputs();
+ cmNinjaDeps ninjaOutputs(outputs.size()), ninjaDeps;
+
+ std::transform(outputs.begin(), outputs.end(),
+ ninjaOutputs.begin(), MapToNinjaPath());
+ this->AppendCustomCommandDeps(cc, ninjaDeps);
+
+ for (cmNinjaDeps::iterator i = ninjaOutputs.begin(); i != ninjaOutputs.end();
+ ++i)
+ this->GetGlobalNinjaGenerator()->SeenCustomCommandOutput(*i);
+
+ std::vector<std::string> cmdLines;
+ this->AppendCustomCommandLines(cc, cmdLines);
+
+ if (cmdLines.empty()) {
+ cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+ "Phony custom command for " +
+ ninjaOutputs[0],
+ ninjaOutputs,
+ ninjaDeps,
+ cmNinjaDeps(),
+ orderOnlyDeps,
+ cmNinjaVars());
+ } else {
+ this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
+ this->BuildCommandLine(cmdLines),
+ this->ConstructComment(*cc),
+ "Custom command for " + ninjaOutputs[0],
+ ninjaOutputs,
+ ninjaDeps,
+ orderOnlyDeps);
+ }
+}
+
+void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc,
+ cmTarget* target)
+{
+ this->CustomCommandTargets[cc].insert(target);
+}
+
+void cmLocalNinjaGenerator::WriteCustomCommandBuildStatements()
+{
+ for (CustomCommandTargetMap::iterator i = this->CustomCommandTargets.begin();
+ i != this->CustomCommandTargets.end(); ++i) {
+ // A custom command may appear on multiple targets. However, some build
+ // systems exist where the target dependencies on some of the targets are
+ // overspecified, leading to a dependency cycle. If we assume all target
+ // dependencies are a superset of the true target dependencies for this
+ // custom command, we can take the set intersection of all target
+ // dependencies to obtain a correct dependency list.
+ //
+ // FIXME: This won't work in certain obscure scenarios involving indirect
+ // dependencies.
+ std::set<cmTarget*>::iterator j = i->second.begin();
+ assert(j != i->second.end());
+ std::vector<std::string> ccTargetDeps;
+ this->AppendTargetDepends(*j, ccTargetDeps);
+ std::sort(ccTargetDeps.begin(), ccTargetDeps.end());
+ ++j;
+
+ for (; j != i->second.end(); ++j) {
+ std::vector<std::string> jDeps, depsIntersection;
+ this->AppendTargetDepends(*j, jDeps);
+ std::sort(jDeps.begin(), jDeps.end());
+ std::set_intersection(ccTargetDeps.begin(), ccTargetDeps.end(),
+ jDeps.begin(), jDeps.end(),
+ std::back_inserter(depsIntersection));
+ ccTargetDeps = depsIntersection;
+ }
+
+ this->WriteCustomCommandBuildStatement(i->first, ccTargetDeps);
+ }
+}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
new file mode 100644
index 0000000..ea44b2f
--- /dev/null
+++ b/Source/cmLocalNinjaGenerator.h
@@ -0,0 +1,133 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 cmLocalNinjaGenerator_h
+# define cmLocalNinjaGenerator_h
+
+# include "cmLocalGenerator.h"
+# include "cmNinjaTypes.h"
+
+class cmGlobalNinjaGenerator;
+class cmGeneratedFileStream;
+class cmake;
+
+/**
+ * \class cmLocalNinjaGenerator
+ * \brief Write a local build.ninja file.
+ *
+ * cmLocalNinjaGenerator produces a local build.ninja file from its
+ * member Makefile.
+ */
+class cmLocalNinjaGenerator : public cmLocalGenerator
+{
+public:
+ /// Default constructor.
+ cmLocalNinjaGenerator();
+
+ /// Destructor.
+ virtual ~cmLocalNinjaGenerator();
+
+ /// Overloaded methods. @see cmLocalGenerator::Generate()
+ virtual void Generate();
+
+ /// Overloaded methods. @see cmLocalGenerator::Configure()
+ virtual void Configure();
+
+ /// Overloaded methods. @see cmLocalGenerator::GetTargetDirectory()
+ virtual std::string GetTargetDirectory(cmTarget const& target) const;
+
+public:
+ const cmGlobalNinjaGenerator* GetGlobalNinjaGenerator() const;
+ cmGlobalNinjaGenerator* GetGlobalNinjaGenerator();
+
+ /**
+ * Shortcut to get the cmake instance throw the global generator.
+ * @return an instance of the cmake object.
+ */
+ const cmake* GetCMakeInstance() const;
+ cmake* GetCMakeInstance();
+
+ const char* GetConfigName() const
+ { return this->ConfigName.c_str(); }
+
+ /// @return whether we are processing the top CMakeLists.txt file.
+ bool isRootMakefile() const;
+
+ /// @returns the relative path between the HomeOutputDirectory and this
+ /// local generators StartOutputDirectory.
+ std::string GetHomeRelativeOutputPath() const
+ { return this->HomeRelativeOutputPath; }
+
+protected:
+ virtual std::string ConvertToLinkReference(std::string const& lib);
+ virtual std::string ConvertToIncludeReference(std::string const& path);
+
+private:
+ friend class cmGlobalNinjaGenerator;
+
+ // In order to access to protected member of the local generator.
+ friend class cmNinjaTargetGenerator;
+ friend class cmNinjaNormalTargetGenerator;
+ friend class cmNinjaUtilityTargetGenerator;
+
+private:
+ cmGeneratedFileStream& GetBuildFileStream() const;
+ cmGeneratedFileStream& GetRulesFileStream() const;
+
+ void WriteBuildFileTop();
+ void WriteProjectHeader(std::ostream& os);
+ void WriteNinjaFilesInclusion(std::ostream& os);
+ void WriteProcessedMakefile(std::ostream& os);
+
+ void SetConfigName();
+
+ std::string ConvertToNinjaPath(const char *path);
+
+ struct map_to_ninja_path;
+ friend struct map_to_ninja_path;
+ struct map_to_ninja_path {
+ cmLocalNinjaGenerator *LocalGenerator;
+ map_to_ninja_path(cmLocalNinjaGenerator *LocalGen)
+ : LocalGenerator(LocalGen) {}
+ std::string operator()(const std::string &path) {
+ return LocalGenerator->ConvertToNinjaPath(path.c_str());
+ }
+ };
+ map_to_ninja_path MapToNinjaPath() {
+ return map_to_ninja_path(this);
+ }
+
+ void AppendTargetOutputs(cmTarget* target, cmNinjaDeps& outputs);
+ void AppendTargetDepends(cmTarget* target, cmNinjaDeps& outputs);
+
+ void AppendCustomCommandDeps(const cmCustomCommand *cc,
+ cmNinjaDeps &ninjaDeps);
+ std::string BuildCommandLine(const std::vector<std::string> &cmdLines);
+ void AppendCustomCommandLines(const cmCustomCommand *cc,
+ std::vector<std::string> &cmdLines);
+ void WriteCustomCommandRule();
+ void WriteCustomCommandBuildStatement(cmCustomCommand const *cc,
+ const cmNinjaDeps& orderOnlyDeps);
+
+ void AddCustomCommandTarget(cmCustomCommand const* cc, cmTarget* target);
+ void WriteCustomCommandBuildStatements();
+
+private:
+ std::string ConfigName;
+ std::string HomeRelativeOutputPath;
+
+ typedef std::map<cmCustomCommand const*, std::set<cmTarget*> >
+ CustomCommandTargetMap;
+ CustomCommandTargetMap CustomCommandTargets;
+};
+
+#endif // ! cmLocalNinjaGenerator_h
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index dd313ca..a645303 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -145,6 +145,20 @@ void cmLocalUnixMakefileGenerator3::Generate()
}
//----------------------------------------------------------------------------
+void cmLocalUnixMakefileGenerator3::AddLocalObjectFile(
+ cmTarget* target, cmSourceFile* sf, std::string objNoTargetDir,
+ bool hasSourceExtension)
+{
+ if(cmSystemTools::FileIsFullPath(objNoTargetDir.c_str()))
+ {
+ objNoTargetDir = cmSystemTools::GetFilenameName(objNoTargetDir);
+ }
+ LocalObjectInfo& info = this->LocalObjectFiles[objNoTargetDir];
+ info.HasSourceExtension = hasSourceExtension;
+ info.push_back(LocalObjectEntry(target, sf->GetLanguage()));
+}
+
+//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::GetIndividualFileTargets
(std::vector<std::string>& targets)
{
@@ -344,6 +358,7 @@ void cmLocalUnixMakefileGenerator3
(t->second.GetType() == cmTarget::STATIC_LIBRARY) ||
(t->second.GetType() == cmTarget::SHARED_LIBRARY) ||
(t->second.GetType() == cmTarget::MODULE_LIBRARY) ||
+ (t->second.GetType() == cmTarget::OBJECT_LIBRARY) ||
(t->second.GetType() == cmTarget::UTILITY))
{
emitted.insert(t->second.GetName());
@@ -452,28 +467,6 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
<< "\n";
}
- // Store the include search path for this directory.
- infoFileStream
- << "# The C and CXX include file search paths:\n";
- infoFileStream
- << "SET(CMAKE_C_INCLUDE_PATH\n";
- std::vector<std::string> includeDirs;
- this->GetIncludeDirectories(includeDirs);
- for(std::vector<std::string>::iterator i = includeDirs.begin();
- i != includeDirs.end(); ++i)
- {
- infoFileStream
- << " \"" << this->Convert(i->c_str(),HOME_OUTPUT).c_str() << "\"\n";
- }
- infoFileStream
- << " )\n";
- infoFileStream
- << "SET(CMAKE_CXX_INCLUDE_PATH ${CMAKE_C_INCLUDE_PATH})\n";
- infoFileStream
- << "SET(CMAKE_Fortran_INCLUDE_PATH ${CMAKE_C_INCLUDE_PATH})\n";
- infoFileStream
- << "SET(CMAKE_ASM_INCLUDE_PATH ${CMAKE_C_INCLUDE_PATH})\n";
-
// Store the include regular expressions for this directory.
infoFileStream
<< "\n"
@@ -2017,45 +2010,6 @@ void cmLocalUnixMakefileGenerator3
}
//----------------------------------------------------------------------------
-std::string
-cmLocalUnixMakefileGenerator3
-::GetObjectFileName(cmTarget& target,
- const cmSourceFile& source,
- std::string* nameWithoutTargetDir,
- bool* hasSourceExtension)
-{
- // Make sure we never hit this old case.
- if(source.GetProperty("MACOSX_PACKAGE_LOCATION"))
- {
- std::string msg = "MACOSX_PACKAGE_LOCATION set on source file: ";
- msg += source.GetFullPath();
- this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR,
- msg.c_str());
- }
-
- // Start with the target directory.
- std::string obj = this->GetTargetDirectory(target);
- obj += "/";
-
- // Get the object file name without the target directory.
- std::string dir_max;
- dir_max += this->Makefile->GetCurrentOutputDirectory();
- dir_max += "/";
- dir_max += obj;
- std::string objectName =
- this->GetObjectFileNameWithoutTarget(source, dir_max,
- hasSourceExtension);
- if(nameWithoutTargetDir)
- {
- *nameWithoutTargetDir = objectName;
- }
-
- // Append the object name to the target directory.
- obj += objectName;
- return obj;
-}
-
-//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream& os)
{
os
@@ -2289,14 +2243,3 @@ void cmLocalUnixMakefileGenerator3
}
}
}
-
-
-void cmLocalUnixMakefileGenerator3
-::GetTargetObjectFileDirectories(cmTarget* target,
- std::vector<std::string>& dirs)
-{
- std::string dir = this->Makefile->GetCurrentOutputDirectory();
- dir += "/";
- dir += this->GetTargetDirectory(*target);
- dirs.push_back(dir);
-}
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 45ac21d..e374959 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -225,24 +225,9 @@ public:
// write the target rules for the local Makefile into the stream
void WriteLocalAllRules(std::ostream& ruleFileStream);
- struct LocalObjectEntry
- {
- cmTarget* Target;
- std::string Language;
- LocalObjectEntry(): Target(0), Language() {}
- LocalObjectEntry(cmTarget* t, const char* lang):
- Target(t), Language(lang) {}
- };
- struct LocalObjectInfo: public std::vector<LocalObjectEntry>
- {
- bool HasSourceExtension;
- bool HasPreprocessRule;
- bool HasAssembleRule;
- LocalObjectInfo():HasSourceExtension(false), HasPreprocessRule(false),
- HasAssembleRule(false) {}
- };
- std::map<cmStdString, LocalObjectInfo> const& GetLocalObjectFiles()
- { return this->LocalObjectFiles;}
+ void AddLocalObjectFile(cmTarget* target, cmSourceFile* sf,
+ std::string objNoTargetDir,
+ bool hasSourceExtension);
std::vector<cmStdString> const& GetLocalHelp() { return this->LocalHelp; }
@@ -257,9 +242,6 @@ public:
{
return !this->SkipAssemblySourceRules;
}
- // Get the directories into which the .o files will go for this target
- void GetTargetObjectFileDirectories(cmTarget* target,
- std::vector<std::string>& dirs);
// Fill the vector with the target names for the object files,
// preprocessed files and assembly files. Currently only used by the
@@ -301,14 +283,6 @@ protected:
void WriteTargetRequiresRule(std::ostream& ruleFileStream,
cmTarget& target,
const std::vector<std::string>& objects);
- void WriteObjectConvenienceRule(std::ostream& ruleFileStream,
- const char* comment, const char* output,
- LocalObjectInfo const& info);
-
- std::string GetObjectFileName(cmTarget& target,
- const cmSourceFile& source,
- std::string* nameWithoutTargetDir = 0,
- bool* hasSourceExtension = 0);
void AppendRuleDepend(std::vector<std::string>& depends,
const char* ruleFileName);
@@ -378,7 +352,27 @@ private:
bool SkipPreprocessedSourceRules;
bool SkipAssemblySourceRules;
+ struct LocalObjectEntry
+ {
+ cmTarget* Target;
+ std::string Language;
+ LocalObjectEntry(): Target(0), Language() {}
+ LocalObjectEntry(cmTarget* t, const char* lang):
+ Target(t), Language(lang) {}
+ };
+ struct LocalObjectInfo: public std::vector<LocalObjectEntry>
+ {
+ bool HasSourceExtension;
+ bool HasPreprocessRule;
+ bool HasAssembleRule;
+ LocalObjectInfo():HasSourceExtension(false), HasPreprocessRule(false),
+ HasAssembleRule(false) {}
+ };
std::map<cmStdString, LocalObjectInfo> LocalObjectFiles;
+ void WriteObjectConvenienceRule(std::ostream& ruleFileStream,
+ const char* comment, const char* output,
+ LocalObjectInfo const& info);
+
std::vector<cmStdString> LocalHelp;
/* does the work for each target */
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index 8b22705..bf0e997 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -74,24 +74,6 @@ void cmLocalVisualStudio10Generator::Generate()
{
cmTargets &tgts = this->Makefile->GetTargets();
- // Create the regeneration custom rule.
- if(!this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION"))
- {
- // Create a rule to regenerate the build system when the target
- // specification source changes.
- if(cmSourceFile* sf = this->CreateVCProjBuildRule())
- {
- // Add the rule to targets that need it.
- for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
- {
- if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET)
- {
- l->second.AddSourceFile(sf);
- }
- }
- }
- }
-
for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
{
if(static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 1dfcbea..99a4c95 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -15,6 +15,7 @@
#include "cmSystemTools.h"
#include "cmSourceFile.h"
#include "cmCacheManager.h"
+#include "cmGeneratorTarget.h"
#include "cmake.h"
#include "cmComputeLinkInformation.h"
@@ -84,6 +85,23 @@ void cmLocalVisualStudio6Generator::AddHelperCommands()
this->CreateCustomTargetsAndCommands(lang);
}
+void cmLocalVisualStudio6Generator::AddCMakeListsRules()
+{
+ cmTargets &tgts = this->Makefile->GetTargets();
+ for(cmTargets::iterator l = tgts.begin();
+ l != tgts.end(); l++)
+ {
+ // Add a rule to regenerate the build system when the target
+ // specification source changes.
+ const char* suppRegenRule =
+ this->Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
+ if (!cmSystemTools::IsOn(suppRegenRule))
+ {
+ this->AddDSPBuildRule(l->second);
+ }
+ }
+}
+
void cmLocalVisualStudio6Generator::Generate()
{
this->OutputDSPFile();
@@ -103,64 +121,9 @@ void cmLocalVisualStudio6Generator::OutputDSPFile()
}
}
- // Setup /I and /LIBPATH options for the resulting DSP file. VS 6
- // truncates long include paths so make it as short as possible if
- // the length threatens this problem.
- unsigned int maxIncludeLength = 3000;
- bool useShortPath = false;
- for(int j=0; j < 2; ++j)
- {
- std::vector<std::string> includes;
- this->GetIncludeDirectories(includes);
- std::vector<std::string>::iterator i;
- for(i = includes.begin(); i != includes.end(); ++i)
- {
- std::string tmp =
- this->ConvertToOptionallyRelativeOutputPath(i->c_str());
- if(useShortPath)
- {
- cmSystemTools::GetShortPath(tmp.c_str(), tmp);
- }
- this->IncludeOptions += " /I ";
-
- // quote if not already quoted
- if (tmp[0] != '"')
- {
- this->IncludeOptions += "\"";
- this->IncludeOptions += tmp;
- this->IncludeOptions += "\"";
- }
- else
- {
- this->IncludeOptions += tmp;
- }
- }
- if(j == 0 && this->IncludeOptions.size() > maxIncludeLength)
- {
- this->IncludeOptions = "";
- useShortPath = true;
- }
- else
- {
- break;
- }
- }
-
// Create the DSP or set of DSP's for libraries and executables
- cmTargets &tgts = this->Makefile->GetTargets();
- for(cmTargets::iterator l = tgts.begin();
- l != tgts.end(); l++)
- {
- // Add a rule to regenerate the build system when the target
- // specification source changes.
- const char* suppRegenRule =
- this->Makefile->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
- if (!cmSystemTools::IsOn(suppRegenRule))
- {
- this->AddDSPBuildRule(l->second);
- }
- }
+ cmTargets &tgts = this->Makefile->GetTargets();
// build any targets
for(cmTargets::iterator l = tgts.begin();
@@ -169,6 +132,7 @@ void cmLocalVisualStudio6Generator::OutputDSPFile()
switch(l->second.GetType())
{
case cmTarget::STATIC_LIBRARY:
+ case cmTarget::OBJECT_LIBRARY:
this->SetBuildType(STATIC_LIBRARY, l->first.c_str(), l->second);
break;
case cmTarget::SHARED_LIBRARY:
@@ -379,9 +343,6 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
}
}
- // Compute which sources need unique object computation.
- this->ComputeObjectNameRequirements(sourceGroups);
-
// Write the DSP file's header.
this->WriteDSPHeader(fout, libName, target, sourceGroups);
@@ -401,6 +362,8 @@ void cmLocalVisualStudio6Generator
::WriteGroup(const cmSourceGroup *sg, cmTarget& target,
std::ostream &fout, const char *libName)
{
+ cmGeneratorTarget* gt =
+ this->GlobalGenerator->GetGeneratorTarget(&target);
const std::vector<const cmSourceFile *> &sourceFiles =
sg->GetSourceFiles();
// If the group is empty, don't write it at all.
@@ -417,28 +380,6 @@ void cmLocalVisualStudio6Generator
this->WriteDSPBeginGroup(fout, name.c_str(), "");
}
- // Compute the maximum length configuration name.
- std::string config_max;
- for(std::vector<std::string>::iterator i = this->Configurations.begin();
- i != this->Configurations.end(); ++i)
- {
- // Strip the subdirectory name out of the configuration name.
- std::string config = this->GetConfigName(*i);
- if(config.size() > config_max.size())
- {
- config_max = config;
- }
- }
-
- // Compute the maximum length full path to the intermediate
- // files directory for any configuration. This is used to construct
- // object file names that do not produce paths that are too long.
- std::string dir_max;
- dir_max += this->Makefile->GetCurrentOutputDirectory();
- dir_max += "/";
- dir_max += config_max;
- dir_max += "/";
-
// Loop through each source in the source group.
for(std::vector<const cmSourceFile *>::const_iterator sf =
sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
@@ -449,11 +390,9 @@ void cmLocalVisualStudio6Generator
std::string compileFlags;
std::vector<std::string> depends;
std::string objectNameDir;
- if(this->NeedObjectName.find(*sf) != this->NeedObjectName.end())
+ if(gt->ExplicitObjectName.find(*sf) != gt->ExplicitObjectName.end())
{
- objectNameDir =
- cmSystemTools::GetFilenamePath(
- this->GetObjectFileNameWithoutTarget(*(*sf), dir_max));
+ objectNameDir = cmSystemTools::GetFilenamePath(gt->Objects[*sf]);
}
// Add per-source file flags.
@@ -895,6 +834,61 @@ inline std::string removeQuotes(const std::string& s)
return s;
}
+
+std::string
+cmLocalVisualStudio6Generator::GetTargetIncludeOptions(cmTarget &target)
+{
+ std::string includeOptions;
+
+ // Setup /I and /LIBPATH options for the resulting DSP file. VS 6
+ // truncates long include paths so make it as short as possible if
+ // the length threatens this problem.
+ unsigned int maxIncludeLength = 3000;
+ bool useShortPath = false;
+ for(int j=0; j < 2; ++j)
+ {
+ std::vector<std::string> includes;
+ this->GetIncludeDirectories(includes, &target);
+
+ std::vector<std::string>::iterator i;
+ for(i = includes.begin(); i != includes.end(); ++i)
+ {
+ std::string tmp =
+ this->ConvertToOptionallyRelativeOutputPath(i->c_str());
+ if(useShortPath)
+ {
+ cmSystemTools::GetShortPath(tmp.c_str(), tmp);
+ }
+ includeOptions += " /I ";
+
+ // quote if not already quoted
+ if (tmp[0] != '"')
+ {
+ includeOptions += "\"";
+ includeOptions += tmp;
+ includeOptions += "\"";
+ }
+ else
+ {
+ includeOptions += tmp;
+ }
+ }
+
+ if(j == 0 && includeOptions.size() > maxIncludeLength)
+ {
+ includeOptions = "";
+ useShortPath = true;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return includeOptions;
+}
+
+
// Code in blocks surrounded by a test for this definition is needed
// only for compatibility with user project's replacement DSP
// templates. The CMake templates no longer use them.
@@ -1132,6 +1126,9 @@ void cmLocalVisualStudio6Generator
}
#endif
+ // Get include options for this target.
+ std::string includeOptions = this->GetTargetIncludeOptions(target);
+
// Get extra linker options for this target type.
std::string extraLinkOptions;
std::string extraLinkOptionsDebug;
@@ -1249,8 +1246,18 @@ void cmLocalVisualStudio6Generator
outputNameMinSizeRel = target.GetFullName("MinSizeRel");
outputNameRelWithDebInfo = target.GetFullName("RelWithDebInfo");
}
+ else if(target.GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ outputName = target.GetName();
+ outputName += ".lib";
+ outputNameDebug = outputName;
+ outputNameRelease = outputName;
+ outputNameMinSizeRel = outputName;
+ outputNameRelWithDebInfo = outputName;
+ }
// Compute the output directory for the target.
+ std::string outputDirOld;
std::string outputDirDebug;
std::string outputDirRelease;
std::string outputDirMinSizeRel;
@@ -1260,6 +1267,11 @@ void cmLocalVisualStudio6Generator
target.GetType() == cmTarget::SHARED_LIBRARY ||
target.GetType() == cmTarget::MODULE_LIBRARY)
{
+#ifdef CM_USE_OLD_VS6
+ outputDirOld =
+ removeQuotes(this->ConvertToOptionallyRelativeOutputPath
+ (target.GetDirectory().c_str()));
+#endif
outputDirDebug =
removeQuotes(this->ConvertToOptionallyRelativeOutputPath(
target.GetDirectory("Debug").c_str()));
@@ -1273,6 +1285,14 @@ void cmLocalVisualStudio6Generator
removeQuotes(this->ConvertToOptionallyRelativeOutputPath(
target.GetDirectory("RelWithDebInfo").c_str()));
}
+ else if(target.GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ std::string outputDir = cmake::GetCMakeFilesDirectoryPostSlash();
+ outputDirDebug = outputDir + "Debug";
+ outputDirRelease = outputDir + "Release";
+ outputDirMinSizeRel = outputDir + "MinSizeRel";
+ outputDirRelWithDebInfo = outputDir + "RelWithDebInfo";
+ }
// Compute the proper link information for the target.
std::string optionsDebug;
@@ -1413,6 +1433,16 @@ void cmLocalVisualStudio6Generator
staticLibOptionsRelWithDebInfo += " ";
staticLibOptionsRelWithDebInfo = libflagsRelWithDebInfo;
}
+ std::string objects;
+ this->OutputObjects(target, "LIB", objects);
+ if(!objects.empty())
+ {
+ objects = "\n" + objects;
+ staticLibOptionsDebug += objects;
+ staticLibOptionsRelease += objects;
+ staticLibOptionsMinSizeRel += objects;
+ staticLibOptionsRelWithDebInfo += objects;
+ }
}
// Add the export symbol definition for shared library objects.
@@ -1441,7 +1471,8 @@ void cmLocalVisualStudio6Generator
libnameExports.c_str());
cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
mfcFlag);
- if(target.GetType() == cmTarget::STATIC_LIBRARY )
+ if(target.GetType() == cmTarget::STATIC_LIBRARY ||
+ target.GetType() == cmTarget::OBJECT_LIBRARY)
{
cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS_DEBUG",
staticLibOptionsDebug.c_str());
@@ -1510,7 +1541,7 @@ void cmLocalVisualStudio6Generator
optionsRelWithDebInfo.c_str());
cmSystemTools::ReplaceString(line, "BUILD_INCLUDES",
- this->IncludeOptions.c_str());
+ includeOptions.c_str());
cmSystemTools::ReplaceString(line, "TARGET_VERSION_FLAG",
targetVersionFlag.c_str());
cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_DEBUG",
@@ -1540,7 +1571,7 @@ void cmLocalVisualStudio6Generator
(exePath.c_str())).c_str());
#endif
- if(targetBuilds)
+ if(targetBuilds || target.GetType() == cmTarget::OBJECT_LIBRARY)
{
cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY_DEBUG",
outputDirDebug.c_str());
@@ -1550,13 +1581,11 @@ void cmLocalVisualStudio6Generator
outputDirMinSizeRel.c_str());
cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY_RELWITHDEBINFO",
outputDirRelWithDebInfo.c_str());
-#ifdef CM_USE_OLD_VS6
- std::string outPath = target.GetDirectory();
- cmSystemTools::ReplaceString
- (line, "OUTPUT_DIRECTORY",
- removeQuotes(this->ConvertToOptionallyRelativeOutputPath
- (outPath.c_str())).c_str());
-#endif
+ if(!outputDirOld.empty())
+ {
+ cmSystemTools::ReplaceString(line, "OUTPUT_DIRECTORY",
+ outputDirOld.c_str());
+ }
}
cmSystemTools::ReplaceString(line,
@@ -1573,7 +1602,7 @@ void cmLocalVisualStudio6Generator
std::string flagsDebug = " ";
std::string flagsDebugRel = " ";
if(target.GetType() >= cmTarget::EXECUTABLE &&
- target.GetType() <= cmTarget::MODULE_LIBRARY)
+ target.GetType() <= cmTarget::OBJECT_LIBRARY)
{
const char* linkLanguage = target.GetLinkerLanguage();
if(!linkLanguage)
@@ -1605,11 +1634,13 @@ void cmLocalVisualStudio6Generator
flagsDebugRel = this->Makefile->GetSafeDefinition(flagVar.c_str());
flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
}
-
- // if unicode is not found, then add -D_MBCS
+
+ // if _UNICODE and _SBCS are not found, then add -D_MBCS
std::string defs = this->Makefile->GetDefineFlags();
if(flags.find("D_UNICODE") == flags.npos &&
- defs.find("D_UNICODE") == flags.npos)
+ defs.find("D_UNICODE") == flags.npos &&
+ flags.find("D_SBCS") == flags.npos &&
+ defs.find("D_SBCS") == flags.npos)
{
flags += " /D \"_MBCS\"";
}
@@ -1726,6 +1757,8 @@ void cmLocalVisualStudio6Generator
ItemVector const& linkLibs = cli.GetItems();
std::vector<std::string> const& linkDirs = cli.GetDirectories();
+ this->OutputObjects(target, "LINK", options);
+
// Build the link options code.
for(std::vector<std::string>::const_iterator d = linkDirs.begin();
d != linkDirs.end(); ++d)
@@ -1770,6 +1803,28 @@ void cmLocalVisualStudio6Generator
}
}
+//----------------------------------------------------------------------------
+void cmLocalVisualStudio6Generator
+::OutputObjects(cmTarget& target, const char* tool,
+ std::string& options)
+{
+ // VS 6 does not support per-config source locations so we
+ // list object library content on the link line instead.
+ cmGeneratorTarget* gt =
+ this->GlobalGenerator->GetGeneratorTarget(&target);
+ std::vector<std::string> objs;
+ gt->UseObjectLibraries(objs);
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ options += "# ADD ";
+ options += tool;
+ options += "32 ";
+ options += this->ConvertToOptionallyRelativeOutputPath(oi->c_str());
+ options += "\n";
+ }
+}
+
std::string
cmLocalVisualStudio6Generator
::GetTargetDirectory(cmTarget const&) const
@@ -1778,15 +1833,34 @@ cmLocalVisualStudio6Generator
return "";
}
-void cmLocalVisualStudio6Generator
-::GetTargetObjectFileDirectories(cmTarget* ,
- std::vector<std::string>&
- dirs)
+//----------------------------------------------------------------------------
+std::string
+cmLocalVisualStudio6Generator
+::ComputeLongestObjectDirectory(cmTarget&) const
{
- std::string dir = this->Makefile->GetCurrentOutputDirectory();
- dir += "/";
- dir += this->GetGlobalGenerator()->GetCMakeCFGInitDirectory();
- dirs.push_back(dir);
+ // Compute the maximum length configuration name.
+ std::string config_max;
+ for(std::vector<std::string>::const_iterator
+ i = this->Configurations.begin();
+ i != this->Configurations.end(); ++i)
+ {
+ // Strip the subdirectory name out of the configuration name.
+ std::string config = this->GetConfigName(*i);
+ if(config.size() > config_max.size())
+ {
+ config_max = config;
+ }
+ }
+
+ // Compute the maximum length full path to the intermediate
+ // files directory for any configuration. This is used to construct
+ // object file names that do not produce paths that are too long.
+ std::string dir_max;
+ dir_max += this->Makefile->GetCurrentOutputDirectory();
+ dir_max += "/";
+ dir_max += config_max;
+ dir_max += "/";
+ return dir_max;
}
std::string
diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h
index 195d654..1decc35 100644
--- a/Source/cmLocalVisualStudio6Generator.h
+++ b/Source/cmLocalVisualStudio6Generator.h
@@ -34,6 +34,7 @@ public:
virtual ~cmLocalVisualStudio6Generator();
virtual void AddHelperCommands();
+ virtual void AddCMakeListsRules();
/**
* Generate the makefile for this directory.
@@ -50,9 +51,7 @@ public:
void SetBuildType(BuildType, const char* libName, cmTarget&);
virtual std::string GetTargetDirectory(cmTarget const& target) const;
- void GetTargetObjectFileDirectories(cmTarget* target,
- std::vector<std::string>&
- dirs);
+ virtual std::string ComputeLongestObjectDirectory(cmTarget&) const;
private:
std::string DSPHeaderTemplate;
std::string DSPFooterTemplate;
@@ -89,7 +88,9 @@ private:
void ComputeLinkOptions(cmTarget& target, const char* configName,
const std::string extraOptions,
std::string& options);
- std::string IncludeOptions;
+ void OutputObjects(cmTarget& target, const char* tool,
+ std::string& options);
+ std::string GetTargetIncludeOptions(cmTarget &target);
std::vector<std::string> Configurations;
std::string GetConfigName(std::string const& configuration) const;
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 11a0387..9faf46d 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -17,6 +17,7 @@
#include "cmSystemTools.h"
#include "cmSourceFile.h"
#include "cmCacheManager.h"
+#include "cmGeneratorTarget.h"
#include "cmake.h"
#include "cmComputeLinkInformation.h"
@@ -38,6 +39,7 @@ public:
LocalGenerator(e) {}
typedef cmComputeLinkInformation::ItemVector ItemVector;
void OutputLibraries(std::ostream& fout, ItemVector const& libs);
+ void OutputObjects(std::ostream& fout, cmTarget* t, const char* isep = 0);
private:
cmLocalVisualStudio7Generator* LocalGenerator;
};
@@ -98,6 +100,28 @@ void cmLocalVisualStudio7Generator::Generate()
this->WriteStampFiles();
}
+void cmLocalVisualStudio7Generator::AddCMakeListsRules()
+{
+ cmTargets &tgts = this->Makefile->GetTargets();
+ // Create the regeneration custom rule.
+ if(!this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION"))
+ {
+ // Create a rule to regenerate the build system when the target
+ // specification source changes.
+ if(cmSourceFile* sf = this->CreateVCProjBuildRule())
+ {
+ // Add the rule to targets that need it.
+ for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
+ {
+ if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET)
+ {
+ l->second.AddSourceFile(sf);
+ }
+ }
+ }
+ }
+}
+
void cmLocalVisualStudio7Generator::FixGlobalTargets()
{
// Visual Studio .NET 2003 Service Pack 1 will not run post-build
@@ -154,24 +178,6 @@ void cmLocalVisualStudio7Generator::WriteProjectFiles()
// Get the set of targets in this directory.
cmTargets &tgts = this->Makefile->GetTargets();
- // Create the regeneration custom rule.
- if(!this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION"))
- {
- // Create a rule to regenerate the build system when the target
- // specification source changes.
- if(cmSourceFile* sf = this->CreateVCProjBuildRule())
- {
- // Add the rule to targets that need it.
- for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
- {
- if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET)
- {
- l->second.AddSourceFile(sf);
- }
- }
- }
- }
-
// Create the project file for each target.
for(cmTargets::iterator l = tgts.begin();
l != tgts.end(); l++)
@@ -641,6 +647,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
bool targetBuilds = true;
switch(target.GetType())
{
+ case cmTarget::OBJECT_LIBRARY:
+ targetBuilds = false; // TODO: PDB for object library?
case cmTarget::STATIC_LIBRARY:
projectType = "typeStaticLibrary";
configType = "4";
@@ -774,6 +782,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
{
fout << "\t\t\tCharacterSet=\"1\">\n";
}
+ else if(targetOptions.UsingSBCS())
+ {
+ fout << "\t\t\tCharacterSet=\"0\">\n";
+ }
else
{
fout << "\t\t\tCharacterSet=\"2\">\n";
@@ -807,7 +819,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
std::vector<std::string> includes;
- this->GetIncludeDirectories(includes);
+ this->GetIncludeDirectories(includes, &target);
std::vector<std::string>::iterator i = includes.begin();
for(;i != includes.end(); ++i)
{
@@ -996,6 +1008,22 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
}
switch(target.GetType())
{
+ case cmTarget::OBJECT_LIBRARY:
+ {
+ std::string libpath = this->GetTargetDirectory(target);
+ libpath += "/";
+ libpath += configName;
+ libpath += "/";
+ libpath += target.GetName();
+ libpath += ".lib";
+ const char* tool =
+ this->FortranProject? "VFLibrarianTool":"VCLibrarianTool";
+ fout << "\t\t\t<Tool\n"
+ << "\t\t\t\tName=\"" << tool << "\"\n";
+ fout << "\t\t\t\tOutputFile=\""
+ << this->ConvertToXMLOutputPathSingle(libpath.c_str()) << "\"/>\n";
+ break;
+ }
case cmTarget::STATIC_LIBRARY:
{
std::string targetNameFull = target.GetFullName(configName);
@@ -1010,6 +1038,15 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
fout << "\t\t\t<Tool\n"
<< "\t\t\t\tName=\"" << tool << "\"\n";
+ if(this->GetVersion() < VS8)
+ {
+ cmOStringStream libdeps;
+ this->Internal->OutputObjects(libdeps, &target);
+ if(!libdeps.str().empty())
+ {
+ fout << "\t\t\t\tAdditionalDependencies=\"" << libdeps.str() << "\"\n";
+ }
+ }
std::string libflags;
if(const char* flags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
{
@@ -1070,8 +1107,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
// Use the NOINHERIT macro to avoid getting VS project default
// libraries which may be set by the user to something bad.
fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
- << this->Makefile->GetSafeDefinition(standardLibsVar.c_str())
- << " ";
+ << this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
+ if(this->GetVersion() < VS8)
+ {
+ this->Internal->OutputObjects(fout, &target, " ");
+ }
+ fout << " ";
this->Internal->OutputLibraries(fout, cli.GetItems());
fout << "\"\n";
temp = target.GetDirectory(configName);
@@ -1151,8 +1192,12 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
// Use the NOINHERIT macro to avoid getting VS project default
// libraries which may be set by the user to something bad.
fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
- << this->Makefile->GetSafeDefinition(standardLibsVar.c_str())
- << " ";
+ << this->Makefile->GetSafeDefinition(standardLibsVar.c_str());
+ if(this->GetVersion() < VS8)
+ {
+ this->Internal->OutputObjects(fout, &target, " ");
+ }
+ fout << " ";
this->Internal->OutputLibraries(fout, cli.GetItems());
fout << "\"\n";
temp = target.GetDirectory(configName);
@@ -1240,6 +1285,30 @@ cmLocalVisualStudio7GeneratorInternals
//----------------------------------------------------------------------------
void
+cmLocalVisualStudio7GeneratorInternals
+::OutputObjects(std::ostream& fout, cmTarget* t, const char* isep)
+{
+ // VS < 8 does not support per-config source locations so we
+ // list object library content on the link line instead.
+ cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
+ cmGeneratorTarget* gt =
+ lg->GetGlobalGenerator()->GetGeneratorTarget(t);
+ std::vector<std::string> objs;
+ gt->UseObjectLibraries(objs);
+ const char* sep = isep? isep : "";
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ std::string rel = lg->Convert(oi->c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::UNCHANGED);
+ fout << sep << lg->ConvertToXMLOutputPath(rel.c_str());
+ sep = " ";
+ }
+}
+
+//----------------------------------------------------------------------------
+void
cmLocalVisualStudio7Generator
::OutputLibraryDirectories(std::ostream& fout,
std::vector<std::string> const& dirs)
@@ -1306,9 +1375,6 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
sourceGroup.AssignSource(*i);
}
- // Compute which sources need unique object computation.
- this->ComputeObjectNameRequirements(sourceGroups);
-
// open the project
this->WriteProjectStart(fout, libName, target, sourceGroups);
// write the configuration information
@@ -1324,7 +1390,27 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
this->WriteGroup(&sg, target, fout, libName, configs);
}
- //}
+ if(this->GetVersion() >= VS8)
+ {
+ // VS >= 8 support per-config source locations so we
+ // list object library content as external objects.
+ cmGeneratorTarget* gt =
+ this->GlobalGenerator->GetGeneratorTarget(&target);
+ std::vector<std::string> objs;
+ gt->UseObjectLibraries(objs);
+ if(!objs.empty())
+ {
+ // TODO: Separate sub-filter for each object library used?
+ fout << "\t\t<Filter Name=\"Object Libraries\">\n";
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ std::string o = this->ConvertToXMLOutputPathSingle(oi->c_str());
+ fout << "\t\t\t<File RelativePath=\"" << o << "\" />\n";
+ }
+ fout << "\t\t</Filter>\n";
+ }
+ }
fout << "\t</Files>\n";
@@ -1348,8 +1434,7 @@ public:
cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
cmTarget& target,
cmSourceFile const& sf,
- std::vector<std::string>* configs,
- std::string const& dir_max);
+ std::vector<std::string>* configs);
std::map<cmStdString, cmLVS7GFileConfig> FileConfigMap;
};
@@ -1357,13 +1442,14 @@ cmLocalVisualStudio7GeneratorFCInfo
::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg,
cmTarget& target,
cmSourceFile const& sf,
- std::vector<std::string>* configs,
- std::string const& dir_max)
+ std::vector<std::string>* configs)
{
+ cmGeneratorTarget* gt =
+ lg->GetGlobalGenerator()->GetGeneratorTarget(&target);
std::string objectName;
- if(lg->NeedObjectName.find(&sf) != lg->NeedObjectName.end())
+ if(gt->ExplicitObjectName.find(&sf) != gt->ExplicitObjectName.end())
{
- objectName = lg->GetObjectFileNameWithoutTarget(sf, dir_max);
+ objectName = gt->Objects[&sf];
}
// Compute per-source, per-config information.
@@ -1474,11 +1560,11 @@ cmLocalVisualStudio7GeneratorFCInfo
}
}
-
-void cmLocalVisualStudio7Generator
-::ComputeMaxDirectoryLength(std::string& maxdir,
- cmTarget& target)
-{
+//----------------------------------------------------------------------------
+std::string
+cmLocalVisualStudio7Generator
+::ComputeLongestObjectDirectory(cmTarget& target) const
+{
std::vector<std::string> *configs =
static_cast<cmGlobalVisualStudio7Generator *>
(this->GlobalGenerator)->GetConfigurations();
@@ -1503,7 +1589,7 @@ void cmLocalVisualStudio7Generator
dir_max += "/";
dir_max += config_max;
dir_max += "/";
- maxdir = dir_max;
+ return dir_max;
}
void cmLocalVisualStudio7Generator
@@ -1526,19 +1612,13 @@ void cmLocalVisualStudio7Generator
this->WriteVCProjBeginGroup(fout, name.c_str(), "");
}
- // Compute the maximum length full path to the intermediate
- // files directory for any configuration. This is used to construct
- // object file names that do not produce paths that are too long.
- std::string dir_max;
- this->ComputeMaxDirectoryLength(dir_max, target);
-
// Loop through each source in the source group.
std::string objectName;
for(std::vector<const cmSourceFile *>::const_iterator sf =
sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
{
std::string source = (*sf)->GetFullPath();
- FCInfo fcinfo(this, target, *(*sf), configs, dir_max);
+ FCInfo fcinfo(this, target, *(*sf), configs);
if (source != libName || target.GetType() == cmTarget::UTILITY ||
target.GetType() == cmTarget::GLOBAL_TARGET )
@@ -2114,19 +2194,6 @@ std::string cmLocalVisualStudio7Generator
return dir;
}
-void cmLocalVisualStudio7Generator::
-GetTargetObjectFileDirectories(cmTarget* target,
- std::vector<std::string>&
- dirs)
-{
- std::string dir = this->Makefile->GetCurrentOutputDirectory();
- dir += "/";
- dir += this->GetTargetDirectory(*target);
- dir += "/";
- dir += this->GetGlobalGenerator()->GetCMakeCFGInitDirectory();
- dirs.push_back(dir);
-}
-
//----------------------------------------------------------------------------
#include <windows.h>
static bool cmLVS6G_IsFAT(const char* dir)
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 5b634b8..9aa408e 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -54,23 +54,17 @@ public:
void SetBuildType(BuildType,const char *name);
void SetPlatformName(const char* n) { this->PlatformName = n;}
- void GetTargetObjectFileDirectories(cmTarget* target,
- std::vector<std::string>&
- dirs);
void SetExtraFlagTable(cmVS7FlagTable const* table)
{ this->ExtraFlagTable = table; }
virtual std::string GetTargetDirectory(cmTarget const&) const;
cmSourceFile* CreateVCProjBuildRule();
void WriteStampFiles();
- // Compute the maximum length full path to the intermediate
- // files directory for any configuration. This is used to construct
- // object file names that do not produce paths that are too long.
- void ComputeMaxDirectoryLength(std::string& maxdir,
- cmTarget& target);
+ virtual std::string ComputeLongestObjectDirectory(cmTarget&) const;
virtual void ReadAndStoreExternalGUID(const char* name,
const char* path);
+ virtual void AddCMakeListsRules();
protected:
void CreateSingleVCProj(const char *lname, cmTarget &tgt);
private:
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index de1ac30..4bcf4de 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -65,96 +65,6 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target,
}
//----------------------------------------------------------------------------
-bool cmLocalVisualStudioGenerator::SourceFileCompiles(const cmSourceFile* sf)
-{
- // Identify the language of the source file.
- if(const char* lang = this->GetSourceFileLanguage(*sf))
- {
- // Check whether this source will actually be compiled.
- return (!sf->GetCustomCommand() &&
- !sf->GetPropertyAsBool("HEADER_FILE_ONLY") &&
- !sf->GetPropertyAsBool("EXTERNAL_OBJECT"));
- }
- else
- {
- // Unknown source file language. Assume it will not be compiled.
- return false;
- }
-}
-
-//----------------------------------------------------------------------------
-void cmLocalVisualStudioGenerator::CountObjectNames(
- const std::vector<cmSourceGroup>& groups,
- std::map<cmStdString, int>& counts)
-{
- for(unsigned int i = 0; i < groups.size(); ++i)
- {
- cmSourceGroup sg = groups[i];
- std::vector<const cmSourceFile*> const& srcs = sg.GetSourceFiles();
- for(std::vector<const cmSourceFile*>::const_iterator s = srcs.begin();
- s != srcs.end(); ++s)
- {
- const cmSourceFile* sf = *s;
- if(this->SourceFileCompiles(sf))
- {
- std::string objectName = cmSystemTools::LowerCase(
- cmSystemTools::GetFilenameWithoutLastExtension(
- sf->GetFullPath()));
- objectName += ".obj";
- counts[objectName] += 1;
- }
- }
- this->CountObjectNames(sg.GetGroupChildren(), counts);
- }
-}
-
-//----------------------------------------------------------------------------
-void cmLocalVisualStudioGenerator::InsertNeedObjectNames(
- const std::vector<cmSourceGroup>& groups,
- std::map<cmStdString, int>& count)
-{
- for(unsigned int i = 0; i < groups.size(); ++i)
- {
- cmSourceGroup sg = groups[i];
- std::vector<const cmSourceFile*> const& srcs = sg.GetSourceFiles();
- for(std::vector<const cmSourceFile*>::const_iterator s = srcs.begin();
- s != srcs.end(); ++s)
- {
- const cmSourceFile* sf = *s;
- if(this->SourceFileCompiles(sf))
- {
- std::string objectName = cmSystemTools::LowerCase(
- cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
- objectName += ".obj";
- if(count[objectName] > 1)
- {
- this->NeedObjectName.insert(sf);
- }
- }
- }
- this->InsertNeedObjectNames(sg.GetGroupChildren(), count);
- }
-}
-
-
-//----------------------------------------------------------------------------
-void cmLocalVisualStudioGenerator::ComputeObjectNameRequirements
-(std::vector<cmSourceGroup> const& sourceGroups)
-{
- // Clear the current set of requirements.
- this->NeedObjectName.clear();
-
- // Count the number of object files with each name. Note that
- // windows file names are not case sensitive.
- std::map<cmStdString, int> objectNameCounts;
- this->CountObjectNames(sourceGroups, objectNameCounts);
-
- // For all source files producing duplicate names we need unique
- // object name computation.
- this->InsertNeedObjectNames(sourceGroups, objectNameCounts);
-}
-
-//----------------------------------------------------------------------------
const char* cmLocalVisualStudioGenerator::ReportErrorLabel() const
{
return ":VCReportError";
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index fcf1f21..9968592 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -56,6 +56,10 @@ public:
/** Version of Visual Studio. */
VSVersion GetVersion() const { return this->Version; }
+ virtual std::string ComputeLongestObjectDirectory(cmTarget&) const = 0;
+
+ virtual void AddCMakeListsRules() = 0;
+
protected:
virtual const char* ReportErrorLabel() const;
virtual bool CustomCommandUseLocal() const { return false; }
@@ -64,16 +68,6 @@ protected:
cmsys::auto_ptr<cmCustomCommand>
MaybeCreateImplibDir(cmTarget& target, const char* config, bool isFortran);
- // Safe object file name generation.
- void ComputeObjectNameRequirements(std::vector<cmSourceGroup> const&);
- bool SourceFileCompiles(const cmSourceFile* sf);
- void CountObjectNames(const std::vector<cmSourceGroup>& groups,
- std::map<cmStdString, int>& count);
- void InsertNeedObjectNames(const std::vector<cmSourceGroup>& groups,
- std::map<cmStdString, int>& count);
- std::set<const cmSourceFile*> NeedObjectName;
- friend class cmVisualStudio10TargetGenerator;
-
VSVersion Version;
};
diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx
index b989870..551ebd3 100644
--- a/Source/cmLocalXCodeGenerator.cxx
+++ b/Source/cmLocalXCodeGenerator.cxx
@@ -33,16 +33,3 @@ cmLocalXCodeGenerator::GetTargetDirectory(cmTarget const&) const
// No per-target directory for this generator (yet).
return "";
}
-
-//----------------------------------------------------------------------------
-void cmLocalXCodeGenerator::
-GetTargetObjectFileDirectories(cmTarget* target,
- std::vector<std::string>&
- dirs)
-{
- cmGlobalXCodeGenerator* g =
- (cmGlobalXCodeGenerator*)this->GetGlobalGenerator();
- g->SetCurrentLocalGenerator(this);
- g->GetTargetObjectFileDirectories(target,
- dirs);
-}
diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h
index 1ab805d..eab228f 100644
--- a/Source/cmLocalXCodeGenerator.h
+++ b/Source/cmLocalXCodeGenerator.h
@@ -27,9 +27,6 @@ public:
cmLocalXCodeGenerator();
virtual ~cmLocalXCodeGenerator();
- void GetTargetObjectFileDirectories(cmTarget* target,
- std::vector<std::string>&
- dirs);
virtual std::string GetTargetDirectory(cmTarget const& target) const;
private:
diff --git a/Source/cmMakeDepend.cxx b/Source/cmMakeDepend.cxx
index 0b4eea5..6055c55 100644
--- a/Source/cmMakeDepend.cxx
+++ b/Source/cmMakeDepend.cxx
@@ -54,16 +54,33 @@ void cmMakeDepend::SetMakefile(cmMakefile* makefile)
this->Makefile->IncludeFileRegularExpression.c_str());
this->ComplainFileRegularExpression.compile(
this->Makefile->ComplainFileRegularExpression.c_str());
-
- // Now extract any include paths from the makefile flags
- const std::vector<std::string>& includes =
- this->Makefile->GetIncludeDirectories();
- for(std::vector<std::string>::const_iterator j = includes.begin();
- j != includes.end(); ++j)
+
+ // Now extract any include paths from the targets
+ std::set<std::string> uniqueIncludes;
+ std::vector<std::string> orderedAndUniqueIncludes;
+ cmTargets & targets = this->Makefile->GetTargets();
+ for (cmTargets::iterator l = targets.begin(); l != targets.end(); ++l)
+ {
+ const std::vector<std::string>& includes =
+ l->second.GetIncludeDirectories();
+ for(std::vector<std::string>::const_iterator j = includes.begin();
+ j != includes.end(); ++j)
+ {
+ std::string path = *j;
+ this->Makefile->ExpandVariablesInString(path);
+ if(uniqueIncludes.insert(path).second)
+ {
+ orderedAndUniqueIncludes.push_back(path);
+ }
+ }
+ }
+
+ for(std::vector<std::string>::const_iterator
+ it = orderedAndUniqueIncludes.begin();
+ it != orderedAndUniqueIncludes.end();
+ ++it)
{
- std::string path = *j;
- this->Makefile->ExpandVariablesInString(path);
- this->AddSearchPath(path.c_str());
+ this->AddSearchPath(it->c_str());
}
}
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index fdf5b31..e7e5eda 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -116,7 +116,6 @@ cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
this->Targets = mf.Targets;
this->SourceFiles = mf.SourceFiles;
this->Tests = mf.Tests;
- this->IncludeDirectories = mf.IncludeDirectories;
this->LinkDirectories = mf.LinkDirectories;
this->SystemIncludeDirectories = mf.SystemIncludeDirectories;
this->ListFiles = mf.ListFiles;
@@ -210,9 +209,9 @@ cmMakefile::~cmMakefile()
{
delete *i;
}
- for(unsigned int i=0; i < this->UsedCommands.size(); i++)
+ for(unsigned int i=0; i < this->FinalPassCommands.size(); i++)
{
- delete this->UsedCommands[i];
+ delete this->FinalPassCommands[i];
}
std::vector<cmFunctionBlocker*>::iterator pos;
for (pos = this->FunctionBlockers.begin();
@@ -278,8 +277,6 @@ void cmMakefile::Print()
this->cmHomeDirectory.c_str() << std::endl;
std::cout << " this->ProjectName; "
<< this->ProjectName.c_str() << std::endl;
- this->PrintStringVector("this->IncludeDirectories;",
- this->IncludeDirectories);
this->PrintStringVector("this->LinkDirectories", this->LinkDirectories);
#if defined(CMAKE_BUILD_WITH_CMAKE)
for( std::vector<cmSourceGroup>::const_iterator i =
@@ -421,7 +418,7 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
else if(pcmd->HasFinalPass())
{
// use the command
- this->UsedCommands.push_back(pcmd.release());
+ this->FinalPassCommands.push_back(pcmd.release());
}
}
else if ( this->GetCMakeInstance()->GetWorkingMode() == cmake::SCRIPT_MODE
@@ -781,10 +778,10 @@ void cmMakefile::SetLocalGenerator(cmLocalGenerator* lg)
("Source Files",
"\\.(C|M|c|c\\+\\+|cc|cpp|cxx|f|f90|for|fpp"
"|ftn|m|mm|rc|def|r|odl|idl|hpj|bat)$");
- this->AddSourceGroup("Header Files",
- "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$");
+ this->AddSourceGroup("Header Files", CM_HEADER_REGEX);
this->AddSourceGroup("CMake Rules", "\\.rule$");
this->AddSourceGroup("Resources", "\\.plist$");
+ this->AddSourceGroup("Object Files", "\\.(lo|o|obj)$");
#endif
this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused();
@@ -813,8 +810,8 @@ void cmMakefile::FinalPass()
// give all the commands a chance to do something
// after the file has been parsed before generation
- for(std::vector<cmCommand*>::iterator i = this->UsedCommands.begin();
- i != this->UsedCommands.end(); ++i)
+ for(std::vector<cmCommand*>::iterator i = this->FinalPassCommands.begin();
+ i != this->FinalPassCommands.end(); ++i)
{
(*i)->FinalPass();
}
@@ -856,6 +853,14 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
cmTargets::iterator ti = this->Targets.find(target);
if(ti != this->Targets.end())
{
+ if(ti->second.GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "Target \"" << target << "\" is an OBJECT library "
+ "that may not have PRE_BUILD, PRE_LINK, or POST_BUILD commands.";
+ this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ }
// Add the command to the appropriate build step for the target.
std::vector<std::string> no_output;
cmCustomCommand cc(this, no_output, depends,
@@ -948,7 +953,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
outName += ".rule";
const char* dir =
this->LocalGenerator->GetGlobalGenerator()->
- GetCMakeCFGInitDirectory();
+ GetCMakeCFGIntDir();
if(dir && dir[0] == '$')
{
cmSystemTools::ReplaceString(outName, dir,
@@ -1478,7 +1483,8 @@ void cmMakefile::InitializeFromParent()
this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure();
// copy include paths
- this->IncludeDirectories = parent->IncludeDirectories;
+ this->SetProperty("INCLUDE_DIRECTORIES",
+ parent->GetProperty("INCLUDE_DIRECTORIES"));
this->SystemIncludeDirectories = parent->SystemIncludeDirectories;
// define flags
@@ -1603,42 +1609,61 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath,
}
}
-void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
+//----------------------------------------------------------------------------
+void AddStringToProperty(cmProperty *prop, const char* name, const char* s,
+ bool before)
{
- // if there is a newline then break it into multiple arguments
- if (!inc)
+ if (!prop)
{
return;
}
- // Don't add an include directory that is already present. Yes,
- // this linear search results in n^2 behavior, but n won't be
- // getting much bigger than 20. We cannot use a set because of
- // order dependency of the include path.
- std::vector<std::string>::iterator i =
- std::find(this->IncludeDirectories.begin(),
- this->IncludeDirectories.end(), inc);
- if(i == this->IncludeDirectories.end())
+ // Don't worry about duplicates at this point. We eliminate them when
+ // we convert the property to a vector in GetIncludeDirectories.
+
+ if (before)
{
- if (before)
+ const char *val = prop->GetValue();
+ cmOStringStream oss;
+
+ if(val && *val)
{
- // WARNING: this *is* expensive (linear time) since it's a vector
- this->IncludeDirectories.insert(this->IncludeDirectories.begin(), inc);
+ oss << s << ";" << val;
}
else
{
- this->IncludeDirectories.push_back(inc);
+ oss << s;
}
+
+ std::string newVal = oss.str();
+ prop->Set(name, newVal.c_str());
}
else
{
- if(before)
- {
- // if this before and already in the path then remove it
- this->IncludeDirectories.erase(i);
- // WARNING: this *is* expensive (linear time) since it's a vector
- this->IncludeDirectories.insert(this->IncludeDirectories.begin(), inc);
- }
+ prop->Append(name, s);
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
+{
+ if (!inc)
+ {
+ return;
+ }
+
+ // Directory property:
+ cmProperty *prop =
+ this->GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES");
+ AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before);
+
+ // 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);
}
}
@@ -1895,8 +1920,11 @@ cmTarget* cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
// wrong type ? default to STATIC
if ( (type != cmTarget::STATIC_LIBRARY)
&& (type != cmTarget::SHARED_LIBRARY)
- && (type != cmTarget::MODULE_LIBRARY))
+ && (type != cmTarget::MODULE_LIBRARY)
+ && (type != cmTarget::OBJECT_LIBRARY))
{
+ this->IssueMessage(cmake::INTERNAL_ERROR,
+ "cmMakefile::AddLibrary given invalid target type.");
type = cmTarget::STATIC_LIBRARY;
}
@@ -2093,17 +2121,37 @@ void cmMakefile::AddExtraDirectory(const char* dir)
}
-// expance CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the
+// expand CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the
// include and library directories.
void cmMakefile::ExpandVariables()
{
// Now expand variables in the include and link strings
- for(std::vector<std::string>::iterator d = this->IncludeDirectories.begin();
- d != this->IncludeDirectories.end(); ++d)
+
+ // May not be necessary anymore... But may need a policy for strict
+ // backwards compatibility
+ const char *includeDirs = this->GetProperty("INCLUDE_DIRECTORIES");
+ if (includeDirs)
{
- this->ExpandVariablesInString(*d, true, true);
+ std::string dirs = includeDirs;
+ this->ExpandVariablesInString(dirs, true, true);
+ this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
}
+
+ // Also for each target's INCLUDE_DIRECTORIES property:
+ for (cmTargets::iterator l = this->Targets.begin();
+ l != this->Targets.end(); ++l)
+ {
+ cmTarget &t = l->second;
+ includeDirs = t.GetProperty("INCLUDE_DIRECTORIES");
+ if (includeDirs)
+ {
+ std::string dirs = includeDirs;
+ this->ExpandVariablesInString(dirs, true, true);
+ t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
+ }
+ }
+
for(std::vector<std::string>::iterator d = this->LinkDirectories.begin();
d != this->LinkDirectories.end(); ++d)
{
@@ -2828,7 +2876,7 @@ void cmMakefile::EnableLanguage(std::vector<std::string> const & lang,
{
this->AddDefinition("CMAKE_CFG_INTDIR",
this->LocalGenerator->GetGlobalGenerator()
- ->GetCMakeCFGInitDirectory());
+ ->GetCMakeCFGIntDir());
this->LocalGenerator->GetGlobalGenerator()->EnableLanguage(lang, this,
optional);
}
@@ -3317,16 +3365,6 @@ void cmMakefile::SetProperty(const char* prop, const char* value)
// handle special props
std::string propname = prop;
- if ( propname == "INCLUDE_DIRECTORIES" )
- {
- std::vector<std::string> varArgsExpanded;
- if(value)
- {
- cmSystemTools::ExpandListArgument(value, varArgsExpanded);
- }
- this->SetIncludeDirectories(varArgsExpanded);
- return;
- }
if ( propname == "LINK_DIRECTORIES" )
{
@@ -3368,17 +3406,6 @@ void cmMakefile::AppendProperty(const char* prop, const char* value,
// handle special props
std::string propname = prop;
- if ( propname == "INCLUDE_DIRECTORIES" )
- {
- std::vector<std::string> varArgsExpanded;
- cmSystemTools::ExpandListArgument(value, varArgsExpanded);
- for(std::vector<std::string>::const_iterator vi = varArgsExpanded.begin();
- vi != varArgsExpanded.end(); ++vi)
- {
- this->AddIncludeDirectory(vi->c_str());
- }
- return;
- }
if ( propname == "LINK_DIRECTORIES" )
{
@@ -3474,23 +3501,6 @@ const char *cmMakefile::GetProperty(const char* prop,
output += this->DefineFlagsOrig;
return output.c_str();
}
- else if (!strcmp("INCLUDE_DIRECTORIES",prop) )
- {
- cmOStringStream str;
- for (std::vector<std::string>::const_iterator
- it = this->GetIncludeDirectories().begin();
- it != this->GetIncludeDirectories().end();
- ++ it )
- {
- if ( it != this->GetIncludeDirectories().begin())
- {
- str << ";";
- }
- str << it->c_str();
- }
- output = str.str();
- return output.c_str();
- }
else if (!strcmp("LINK_DIRECTORIES",prop))
{
cmOStringStream str;
@@ -3861,9 +3871,22 @@ void cmMakefile::DefineProperties(cmake *cm)
cm->DefineProperty
("INCLUDE_DIRECTORIES", cmProperty::DIRECTORY,
"List of preprocessor include file search directories.",
- "This read-only property specifies the list of directories given "
- "so far to the include_directories command. "
- "It is intended for debugging purposes.", false);
+ "This property specifies the list of directories given "
+ "so far to the include_directories command. "
+ "This property exists on directories and targets. "
+ "In addition to accepting values from the include_directories "
+ "command, values may be set directly on any directory or any "
+ "target using the set_property command. "
+ "A target gets its initial value for this property from the value "
+ "of the directory property. "
+ "A directory gets its initial value from its parent directory if "
+ "it has one. "
+ "Both directory and target property values are adjusted by calls "
+ "to the include_directories command."
+ "\n"
+ "The target property values are used by the generators to set "
+ "the include paths for the compiler. "
+ "See also the include_directories command.");
cm->DefineProperty
("LINK_DIRECTORIES", cmProperty::DIRECTORY,
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 1c46a73..960ba39 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -522,22 +522,6 @@ public:
cmTarget* FindTargetToUse(const char* name);
/**
- * Get a list of include directories in the build.
- */
- std::vector<std::string>& GetIncludeDirectories()
- {
- return this->IncludeDirectories;
- }
- const std::vector<std::string>& GetIncludeDirectories() const
- {
- return this->IncludeDirectories;
- }
- void SetIncludeDirectories(const std::vector<std::string>& vec)
- {
- this->IncludeDirectories = vec;
- }
-
- /**
* Mark include directories as system directories.
*/
void AddSystemIncludeDirectory(const char* dir);
@@ -620,12 +604,6 @@ public:
*/
bool CanIWriteThisFile(const char* fileName);
- /**
- * Get the vector of used command instances.
- */
- const std::vector<cmCommand*>& GetUsedCommands() const
- {return this->UsedCommands;}
-
#if defined(CMAKE_BUILD_WITH_CMAKE)
/**
* Get the vector source groups.
@@ -880,9 +858,7 @@ protected:
// Tests
std::map<cmStdString, cmTest*> Tests;
- // The include and link-library paths. These may have order
- // dependency, so they must be vectors (not set).
- std::vector<std::string> IncludeDirectories;
+ // The link-library paths. Order matters, use std::vector (not std::set).
std::vector<std::string> LinkDirectories;
// The set of include directories that are marked as system include
@@ -913,7 +889,7 @@ protected:
std::vector<cmSourceGroup> SourceGroups;
#endif
- std::vector<cmCommand*> UsedCommands;
+ std::vector<cmCommand*> FinalPassCommands;
cmLocalGenerator* LocalGenerator;
bool IsFunctionBlocked(const cmListFileFunction& lff,
cmExecutionStatus &status);
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index b4174cc..38aa59d 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -101,6 +101,9 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
this->WriteModuleLibraryRules(true);
}
break;
+ case cmTarget::OBJECT_LIBRARY:
+ this->WriteObjectLibraryRules();
+ break;
default:
// If language is not known, this is an error.
cmSystemTools::Error("Unknown Library Type");
@@ -122,6 +125,29 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
}
//----------------------------------------------------------------------------
+void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
+{
+ std::vector<std::string> commands;
+ std::vector<std::string> depends;
+
+ // Add post-build rules.
+ this->LocalGenerator->
+ AppendCustomCommands(commands, this->Target->GetPostBuildCommands(),
+ this->Target);
+
+ // Depend on the object files.
+ this->AppendObjectDepends(depends);
+
+ // Write the rule.
+ this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
+ this->Target->GetName(),
+ depends, commands, true);
+
+ // Write the main driver rule to build everything in this target.
+ this->WriteTargetDriverRule(this->Target->GetName(), false);
+}
+
+//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
{
const char* linkLanguage =
diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h
index f3c47db..e6a5867 100644
--- a/Source/cmMakefileLibraryTargetGenerator.h
+++ b/Source/cmMakefileLibraryTargetGenerator.h
@@ -25,6 +25,7 @@ public:
virtual void WriteRuleFiles();
protected:
+ void WriteObjectLibraryRules();
void WriteStaticLibraryRules();
void WriteSharedLibraryRules(bool relink);
void WriteModuleLibraryRules(bool relink);
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index a3a832b..a0e0481 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -11,6 +11,7 @@
============================================================================*/
#include "cmMakefileTargetGenerator.h"
+#include "cmGeneratorTarget.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmGlobalUnixMakefileGenerator3.h"
@@ -42,6 +43,7 @@ cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmTarget* target)
this->GlobalGenerator =
static_cast<cmGlobalUnixMakefileGenerator3*>(
this->LocalGenerator->GetGlobalGenerator());
+ this->GeneratorTarget = this->GlobalGenerator->GetGeneratorTarget(target);
cmake* cm = this->GlobalGenerator->GetCMakeInstance();
this->NoRuleMessages = false;
if(const char* ruleStatus = cm->GetProperty("RULE_MESSAGES"))
@@ -63,6 +65,7 @@ cmMakefileTargetGenerator::New(cmTarget *tgt)
case cmTarget::STATIC_LIBRARY:
case cmTarget::SHARED_LIBRARY:
case cmTarget::MODULE_LIBRARY:
+ case cmTarget::OBJECT_LIBRARY:
result = new cmMakefileLibraryTargetGenerator(tgt);
break;
case cmTarget::UTILITY:
@@ -131,58 +134,49 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
// First generate the object rule files. Save a list of all object
// files for this target.
- const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
- source != sources.end(); ++source)
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->CustomCommands.begin();
+ si != this->GeneratorTarget->CustomCommands.end(); ++si)
{
- cmTarget::SourceFileFlags tsFlags =
- this->Target->GetTargetSourceFileFlags(*source);
- if(cmCustomCommand* cc = (*source)->GetCustomCommand())
- {
- this->GenerateCustomRuleFile(*cc);
- if (clean)
- {
- const std::vector<std::string>& outputs = cc->GetOutputs();
- for(std::vector<std::string>::const_iterator o = outputs.begin();
- o != outputs.end(); ++o)
- {
- this->CleanFiles.push_back
- (this->Convert(o->c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
- }
- }
- else if(tsFlags.Type != cmTarget::SourceFileTypeNormal)
+ cmCustomCommand const* cc = (*si)->GetCustomCommand();
+ this->GenerateCustomRuleFile(*cc);
+ if (clean)
{
- this->WriteMacOSXContentRules(*(*source), tsFlags.MacFolder);
- }
- else if(!(*source)->GetPropertyAsBool("HEADER_FILE_ONLY"))
- {
- if(!this->GlobalGenerator->IgnoreFile
- ((*source)->GetExtension().c_str()))
- {
- // Generate this object file's rule file.
- this->WriteObjectRuleFiles(*(*source));
- }
- else if((*source)->GetPropertyAsBool("EXTERNAL_OBJECT"))
- {
- // This is an external object file. Just add it.
- this->ExternalObjects.push_back((*source)->GetFullPath());
- }
- else if(cmSystemTools::UpperCase((*source)->GetExtension()) == "DEF")
- {
- this->ModuleDefinitionFile = (*source)->GetFullPath();
- }
- else
+ const std::vector<std::string>& outputs = cc->GetOutputs();
+ for(std::vector<std::string>::const_iterator o = outputs.begin();
+ o != outputs.end(); ++o)
{
- // We only get here if a source file is not an external object
- // and has an extension that is listed as an ignored file type
- // for this language. No message or diagnosis should be
- // given.
+ this->CleanFiles.push_back
+ (this->Convert(o->c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::UNCHANGED));
}
}
}
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->OSXContent.begin();
+ si != this->GeneratorTarget->OSXContent.end(); ++si)
+ {
+ cmTarget::SourceFileFlags tsFlags =
+ this->Target->GetTargetSourceFileFlags(*si);
+ this->WriteMacOSXContentRules(**si, tsFlags.MacFolder);
+ }
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ExternalObjects.begin();
+ si != this->GeneratorTarget->ExternalObjects.end(); ++si)
+ {
+ this->ExternalObjects.push_back((*si)->GetFullPath());
+ }
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ObjectSources.begin();
+ si != this->GeneratorTarget->ObjectSources.end(); ++si)
+ {
+ // Generate this object file's rule file.
+ this->WriteObjectRuleFiles(**si);
+ }
+
+ // Add object library contents as external objects.
+ this->GeneratorTarget->UseObjectLibraries(this->ExternalObjects);
}
@@ -428,12 +422,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
}
// Get the full path name of the object file.
- bool hasSourceExtension;
- std::string objNoTargetDir;
- std::string obj =
- this->LocalGenerator->GetObjectFileName(*this->Target, source,
- &objNoTargetDir,
- &hasSourceExtension);
+ std::string const& objectName = this->GeneratorTarget->Objects[&source];
+ std::string obj = this->LocalGenerator->GetTargetDirectory(*this->Target);
+ obj += "/";
+ obj += objectName;
// Avoid generating duplicate rules.
if(this->ObjectFiles.find(obj) == this->ObjectFiles.end())
@@ -487,18 +479,6 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
AddImplicitDepends(*this->Target, lang,
objFullPath.c_str(),
srcFullPath.c_str());
-
- // add this to the list of objects for this local generator
- if(cmSystemTools::FileIsFullPath(objNoTargetDir.c_str()))
- {
- objNoTargetDir = cmSystemTools::GetFilenameName(objNoTargetDir);
- }
- cmLocalUnixMakefileGenerator3::LocalObjectInfo& info =
- this->LocalGenerator->LocalObjectFiles[objNoTargetDir];
- info.HasSourceExtension = hasSourceExtension;
- info.push_back(
- cmLocalUnixMakefileGenerator3::LocalObjectEntry(this->Target, lang)
- );
}
//----------------------------------------------------------------------------
@@ -1069,6 +1049,35 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
}
+ // Target-specific include directories:
+ *this->InfoFileStream
+ << "\n"
+ << "# The include file search paths:\n";
+ *this->InfoFileStream
+ << "SET(CMAKE_C_TARGET_INCLUDE_PATH\n";
+ std::vector<std::string> includes;
+ this->LocalGenerator->GetIncludeDirectories(includes, this->Target);
+ for(std::vector<std::string>::iterator i = includes.begin();
+ i != includes.end(); ++i)
+ {
+ *this->InfoFileStream
+ << " \""
+ << this->LocalGenerator->Convert(i->c_str(),
+ cmLocalGenerator::HOME_OUTPUT)
+ << "\"\n";
+ }
+ *this->InfoFileStream
+ << " )\n";
+ *this->InfoFileStream
+ << "SET(CMAKE_CXX_TARGET_INCLUDE_PATH "
+ << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
+ *this->InfoFileStream
+ << "SET(CMAKE_Fortran_TARGET_INCLUDE_PATH "
+ << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
+ *this->InfoFileStream
+ << "SET(CMAKE_ASM_TARGET_INCLUDE_PATH "
+ << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
+
// and now write the rule to use it
std::vector<std::string> depends;
std::vector<std::string> commands;
@@ -1534,7 +1543,7 @@ std::string cmMakefileTargetGenerator::GetFrameworkFlags()
emitted.insert("/System/Library/Frameworks");
#endif
std::vector<std::string> includes;
- this->LocalGenerator->GetIncludeDirectories(includes);
+ this->LocalGenerator->GetIncludeDirectories(includes, this->Target);
std::vector<std::string>::iterator i;
// check all include directories for frameworks as this
// will already have added a -F for the framework
@@ -1591,7 +1600,7 @@ void cmMakefileTargetGenerator
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator
-::AppendLinkDepends(std::vector<std::string>& depends)
+::AppendObjectDepends(std::vector<std::string>& depends)
{
// Add dependencies on the compiled object files.
std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
@@ -1604,25 +1613,32 @@ void cmMakefileTargetGenerator
depends.push_back(objTarget);
}
- // Add dependencies on targets that must be built first.
- this->AppendTargetDepends(depends);
+ // Add dependencies on the external object files.
+ for(std::vector<std::string>::const_iterator obj
+ = this->ExternalObjects.begin();
+ obj != this->ExternalObjects.end(); ++obj)
+ {
+ depends.push_back(*obj);
+ }
// Add a dependency on the rule file itself.
this->LocalGenerator->AppendRuleDepend(depends,
this->BuildFileNameFull.c_str());
+}
- // Add a dependency on the link definitions file, if any.
- if(!this->ModuleDefinitionFile.empty())
- {
- depends.push_back(this->ModuleDefinitionFile);
- }
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator
+::AppendLinkDepends(std::vector<std::string>& depends)
+{
+ this->AppendObjectDepends(depends);
- // Add dependencies on the external object files.
- for(std::vector<std::string>::const_iterator obj
- = this->ExternalObjects.begin();
- obj != this->ExternalObjects.end(); ++obj)
+ // Add dependencies on targets that must be built first.
+ this->AppendTargetDepends(depends);
+
+ // Add a dependency on the link definitions file, if any.
+ if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
{
- depends.push_back(*obj);
+ depends.push_back(this->GeneratorTarget->ModuleDefinitionFile);
}
// Add user-specified dependencies.
@@ -1829,8 +1845,12 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
responseVar += "_USE_RESPONSE_FILE_FOR_INCLUDES";
bool useResponseFile = this->Makefile->IsOn(responseVar.c_str());
+
+ std::vector<std::string> includes;
+ this->LocalGenerator->GetIncludeDirectories(includes, this->Target, lang);
+
std::string includeFlags =
- this->LocalGenerator->GetIncludeFlags(lang, useResponseFile);
+ this->LocalGenerator->GetIncludeFlags(includes, lang, useResponseFile);
if(includeFlags.empty())
{
return;
@@ -1930,7 +1950,7 @@ void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
{
std::vector<std::string> includes;
- this->LocalGenerator->GetIncludeDirectories(includes);
+ this->LocalGenerator->GetIncludeDirectories(includes, this->Target);
for(std::vector<std::string>::const_iterator idi = includes.begin();
idi != includes.end(); ++idi)
{
@@ -1946,7 +1966,7 @@ void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
{
- if(this->ModuleDefinitionFile.empty())
+ if(this->GeneratorTarget->ModuleDefinitionFile.empty())
{
return;
}
@@ -1963,7 +1983,7 @@ void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
// vs6's "cl -link" pass it to the linker.
std::string flag = defFileFlag;
flag += (this->LocalGenerator->ConvertToLinkReference(
- this->ModuleDefinitionFile.c_str()));
+ this->GeneratorTarget->ModuleDefinitionFile.c_str()));
this->LocalGenerator->AppendFlags(flags, flag.c_str());
}
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index 8fba13f..e1e554b 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -17,6 +17,7 @@
class cmCustomCommand;
class cmDependInformation;
class cmDepends;
+class cmGeneratorTarget;
class cmGeneratedFileStream;
class cmGlobalUnixMakefileGenerator3;
class cmLocalUnixMakefileGenerator3;
@@ -117,6 +118,9 @@ protected:
// append intertarget dependencies
void AppendTargetDepends(std::vector<std::string>& depends);
+ // Append object file dependencies.
+ void AppendObjectDepends(std::vector<std::string>& depends);
+
// Append link rule dependencies (objects, etc.).
void AppendLinkDepends(std::vector<std::string>& depends);
@@ -157,6 +161,7 @@ protected:
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
std::string& linkFlags);
cmTarget *Target;
+ cmGeneratorTarget* GeneratorTarget;
cmLocalUnixMakefileGenerator3 *LocalGenerator;
cmGlobalUnixMakefileGenerator3 *GlobalGenerator;
cmMakefile *Makefile;
@@ -198,9 +203,6 @@ protected:
std::vector<std::string> Objects;
std::vector<std::string> ExternalObjects;
- // The windows module definition source file (.def), if any.
- std::string ModuleDefinitionFile;
-
// Set of object file names that will be built in this directory.
std::set<cmStdString> ObjectFiles;
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
new file mode 100644
index 0000000..2bad32c
--- /dev/null
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -0,0 +1,500 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 "cmNinjaNormalTargetGenerator.h"
+#include "cmLocalNinjaGenerator.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmSourceFile.h"
+#include "cmGeneratedFileStream.h"
+#include "cmMakefile.h"
+
+#include <assert.h>
+
+cmNinjaNormalTargetGenerator::
+cmNinjaNormalTargetGenerator(cmTarget* target)
+ : cmNinjaTargetGenerator(target)
+ , TargetNameOut()
+ , TargetNameSO()
+ , TargetNameReal()
+ , TargetNameImport()
+ , TargetNamePDB()
+{
+ this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName());
+ if (target->GetType() == cmTarget::EXECUTABLE)
+ target->GetExecutableNames(this->TargetNameOut,
+ this->TargetNameReal,
+ this->TargetNameImport,
+ this->TargetNamePDB,
+ GetLocalGenerator()->GetConfigName());
+ else
+ target->GetLibraryNames(this->TargetNameOut,
+ this->TargetNameSO,
+ this->TargetNameReal,
+ this->TargetNameImport,
+ this->TargetNamePDB,
+ GetLocalGenerator()->GetConfigName());
+
+ if(target->GetType() != cmTarget::OBJECT_LIBRARY)
+ {
+ // on Windows the output dir is already needed at compile time
+ // ensure the directory exists (OutDir test)
+ std::string outpath = target->GetDirectory(this->GetConfigName());
+ cmSystemTools::MakeDirectory(outpath.c_str());
+ }
+}
+
+cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator()
+{
+}
+
+void cmNinjaNormalTargetGenerator::Generate()
+{
+ if (!this->TargetLinkLanguage) {
+ cmSystemTools::Error("CMake can not determine linker language for target:",
+ this->GetTarget()->GetName());
+ return;
+ }
+
+ // Write the rules for each language.
+ this->WriteLanguagesRules();
+
+ // Write the build statements
+ this->WriteObjectBuildStatements();
+
+ if(this->GetTarget()->GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ this->WriteObjectLibStatement();
+ }
+ else
+ {
+ this->WriteLinkRule();
+ this->WriteLinkStatement();
+ }
+
+ this->GetBuildFileStream() << "\n";
+ this->GetRulesFileStream() << "\n";
+}
+
+void cmNinjaNormalTargetGenerator::WriteLanguagesRules()
+{
+ cmGlobalNinjaGenerator::WriteDivider(this->GetRulesFileStream());
+ this->GetRulesFileStream()
+ << "# Rules for each languages for "
+ << cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
+ << " target "
+ << this->GetTargetName()
+ << "\n\n";
+
+ std::set<cmStdString> languages;
+ this->GetTarget()->GetLanguages(languages);
+ for(std::set<cmStdString>::const_iterator l = languages.begin();
+ l != languages.end();
+ ++l)
+ this->WriteLanguageRules(*l);
+}
+
+const char *cmNinjaNormalTargetGenerator::GetVisibleTypeName() const
+{
+ switch (this->GetTarget()->GetType()) {
+ case cmTarget::STATIC_LIBRARY:
+ return "static library";
+ case cmTarget::SHARED_LIBRARY:
+ return "shared library";
+ case cmTarget::MODULE_LIBRARY:
+ return "shared module";
+ case cmTarget::EXECUTABLE:
+ return "executable";
+ default:
+ return 0;
+ }
+}
+
+std::string
+cmNinjaNormalTargetGenerator
+::LanguageLinkerRule() const
+{
+ return std::string(this->TargetLinkLanguage)
+ + "_"
+ + cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
+ + "_LINKER";
+}
+
+void
+cmNinjaNormalTargetGenerator
+::WriteLinkRule()
+{
+ cmTarget::TargetType targetType = this->GetTarget()->GetType();
+ std::string ruleName = this->LanguageLinkerRule();
+
+ if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
+ cmLocalGenerator::RuleVariables vars;
+ vars.RuleLauncher = "RULE_LAUNCH_LINK";
+ vars.CMTarget = this->GetTarget();
+ vars.Language = this->TargetLinkLanguage;
+ vars.Objects = "$in";
+ std::string objdir =
+ this->GetLocalGenerator()->GetHomeRelativeOutputPath();
+ objdir += objdir.empty() ? "" : "/";
+ objdir += cmake::GetCMakeFilesDirectoryPostSlash();
+ objdir += this->GetTargetName();
+ objdir += ".dir";
+ objdir = this->GetLocalGenerator()->Convert(objdir.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::SHELL);
+ vars.ObjectDir = objdir.c_str();
+ vars.Target = "$out";
+ vars.TargetSOName = "$SONAME";
+ vars.TargetInstallNameDir = "$INSTALLNAME_DIR";
+ vars.TargetPDB = "$TARGET_PDB";
+
+ // Setup the target version.
+ std::string targetVersionMajor;
+ std::string targetVersionMinor;
+ {
+ cmOStringStream majorStream;
+ cmOStringStream minorStream;
+ int major;
+ int minor;
+ this->GetTarget()->GetTargetVersion(major, minor);
+ majorStream << major;
+ minorStream << minor;
+ targetVersionMajor = majorStream.str();
+ targetVersionMinor = minorStream.str();
+ }
+ vars.TargetVersionMajor = targetVersionMajor.c_str();
+ vars.TargetVersionMinor = targetVersionMinor.c_str();
+
+ vars.LinkLibraries = "$LINK_LIBRARIES";
+ vars.Flags = "$FLAGS";
+ vars.LinkFlags = "$LINK_FLAGS";
+
+ std::string langFlags;
+ this->GetLocalGenerator()->AddLanguageFlags(langFlags,
+ this->TargetLinkLanguage,
+ this->GetConfigName());
+ if (targetType != cmTarget::EXECUTABLE)
+ langFlags += " $ARCH_FLAGS";
+ vars.LanguageCompileFlags = langFlags.c_str();
+
+ // Rule for linking library.
+ std::vector<std::string> linkCmds = this->ComputeLinkCmd();
+ for(std::vector<std::string>::iterator i = linkCmds.begin();
+ i != linkCmds.end();
+ ++i)
+ {
+ this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
+ }
+ linkCmds.insert(linkCmds.begin(), "$PRE_LINK");
+ linkCmds.push_back("$POST_BUILD");
+ std::string linkCmd =
+ this->GetLocalGenerator()->BuildCommandLine(linkCmds);
+
+ // Write the linker rule.
+ std::ostringstream comment;
+ comment << "Rule for linking " << this->TargetLinkLanguage << " "
+ << this->GetVisibleTypeName() << ".";
+ std::ostringstream description;
+ description << "Linking " << this->TargetLinkLanguage << " "
+ << this->GetVisibleTypeName() << " $out";
+ this->GetGlobalGenerator()->AddRule(ruleName,
+ linkCmd,
+ description.str(),
+ comment.str());
+ }
+
+ if (this->TargetNameOut != this->TargetNameReal) {
+ std::string cmakeCommand =
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND"),
+ cmLocalGenerator::SHELL);
+ if (targetType == cmTarget::EXECUTABLE)
+ this->GetGlobalGenerator()->AddRule("CMAKE_SYMLINK_EXECUTABLE",
+ cmakeCommand +
+ " -E cmake_symlink_executable"
+ " $in $out && $POST_BUILD",
+ "Creating executable symlink $out",
+ "Rule for creating executable symlink.");
+ else
+ this->GetGlobalGenerator()->AddRule("CMAKE_SYMLINK_LIBRARY",
+ cmakeCommand +
+ " -E cmake_symlink_library"
+ " $in $SONAME $out && $POST_BUILD",
+ "Creating library symlink $out",
+ "Rule for creating library symlink.");
+ }
+}
+
+std::vector<std::string>
+cmNinjaNormalTargetGenerator
+::ComputeLinkCmd()
+{
+ std::vector<std::string> linkCmds;
+ cmTarget::TargetType targetType = this->GetTarget()->GetType();
+ switch (targetType) {
+ case cmTarget::STATIC_LIBRARY: {
+ // Check if you have a non archive way to create the static library.
+ {
+ std::string linkCmdVar = "CMAKE_";
+ linkCmdVar += this->TargetLinkLanguage;
+ linkCmdVar += "_CREATE_STATIC_LIBRARY";
+ if (const char *linkCmd =
+ this->GetMakefile()->GetDefinition(linkCmdVar.c_str()))
+ {
+ cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ return linkCmds;
+ }
+ }
+
+ // We have archive link commands set. First, delete the existing archive.
+ std::string cmakeCommand =
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND"),
+ cmLocalGenerator::SHELL);
+ linkCmds.push_back(cmakeCommand + " -E remove $out");
+
+ // TODO: Use ARCHIVE_APPEND for archives over a certain size.
+ {
+ std::string linkCmdVar = "CMAKE_";
+ linkCmdVar += this->TargetLinkLanguage;
+ linkCmdVar += "_ARCHIVE_CREATE";
+ const char *linkCmd =
+ this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
+ cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ }
+ {
+ std::string linkCmdVar = "CMAKE_";
+ linkCmdVar += this->TargetLinkLanguage;
+ linkCmdVar += "_ARCHIVE_FINISH";
+ const char *linkCmd =
+ this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
+ cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ }
+ return linkCmds;
+ }
+ case cmTarget::SHARED_LIBRARY:
+ case cmTarget::MODULE_LIBRARY:
+ case cmTarget::EXECUTABLE: {
+ std::string linkCmdVar = "CMAKE_";
+ linkCmdVar += this->TargetLinkLanguage;
+ switch (targetType) {
+ case cmTarget::SHARED_LIBRARY:
+ linkCmdVar += "_CREATE_SHARED_LIBRARY";
+ break;
+ case cmTarget::MODULE_LIBRARY:
+ linkCmdVar += "_CREATE_SHARED_MODULE";
+ break;
+ case cmTarget::EXECUTABLE:
+ linkCmdVar += "_LINK_EXECUTABLE";
+ break;
+ default:
+ assert(0 && "Unexpected target type");
+ }
+
+ const char *linkCmd =
+ this->GetMakefile()->GetRequiredDefinition(linkCmdVar.c_str());
+ cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
+ return linkCmds;
+ }
+ default:
+ assert(0 && "Unexpected target type");
+ }
+ return std::vector<std::string>();
+}
+
+void cmNinjaNormalTargetGenerator::WriteLinkStatement()
+{
+ cmTarget::TargetType targetType = this->GetTarget()->GetType();
+
+ // Write comments.
+ cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
+ this->GetBuildFileStream()
+ << "# Link build statements for "
+ << cmTarget::GetTargetTypeName(targetType)
+ << " target "
+ << this->GetTargetName()
+ << "\n\n";
+
+ cmNinjaDeps emptyDeps;
+ cmNinjaVars vars;
+
+ std::string targetOutput = ConvertToNinjaPath(
+ this->GetTarget()->GetFullPath(this->GetConfigName()).c_str());
+ std::string targetOutputReal = ConvertToNinjaPath(
+ this->GetTarget()->GetFullPath(this->GetConfigName(),
+ /*implib=*/false,
+ /*realpath=*/true).c_str());
+ std::string targetOutputImplib = ConvertToNinjaPath(
+ this->GetTarget()->GetFullPath(this->GetConfigName(),
+ /*implib=*/true).c_str());
+
+ // Compute the comment.
+ std::ostringstream comment;
+ comment << "Link the " << this->GetVisibleTypeName() << " "
+ << targetOutputReal;
+
+ // Compute outputs.
+ cmNinjaDeps outputs;
+ outputs.push_back(targetOutputReal);
+
+ // Compute specific libraries to link with.
+ cmNinjaDeps explicitDeps = this->GetObjects(),
+ implicitDeps = this->ComputeLinkDeps();
+
+ this->GetLocalGenerator()->GetTargetFlags(vars["LINK_LIBRARIES"],
+ vars["FLAGS"],
+ vars["LINK_FLAGS"],
+ *this->GetTarget());
+
+ this->AddModuleDefinitionFlag(vars["LINK_FLAGS"]);
+
+ // Compute architecture specific link flags. Yes, these go into a different
+ // variable for executables, probably due to a mistake made when duplicating
+ // code between the Makefile executable and library generators.
+ this->GetLocalGenerator()
+ ->AddArchitectureFlags(targetType == cmTarget::EXECUTABLE
+ ? vars["FLAGS"]
+ : vars["ARCH_FLAGS"],
+ this->GetTarget(),
+ this->TargetLinkLanguage,
+ this->GetConfigName());
+ vars["SONAME"] = this->TargetNameSO;
+
+ if (targetType == cmTarget::SHARED_LIBRARY) {
+ std::string install_name_dir =
+ this->GetTarget()->GetInstallNameDirForBuildTree(this->GetConfigName());
+
+ if (!install_name_dir.empty()) {
+ vars["INSTALLNAME_DIR"] =
+ this->GetLocalGenerator()->Convert(install_name_dir.c_str(),
+ cmLocalGenerator::NONE,
+ cmLocalGenerator::SHELL, false);
+ }
+ }
+
+ if (!this->TargetNameImport.empty()) {
+ vars["TARGET_IMPLIB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ targetOutputImplib.c_str(), cmLocalGenerator::SHELL);
+ }
+
+ vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->GetTargetPDB().c_str(), cmLocalGenerator::SHELL);
+
+ std::vector<cmCustomCommand> *cmdLists[3] = {
+ &this->GetTarget()->GetPreBuildCommands(),
+ &this->GetTarget()->GetPreLinkCommands(),
+ &this->GetTarget()->GetPostBuildCommands()
+ };
+
+ std::vector<std::string> preLinkCmdLines, postBuildCmdLines;
+ std::vector<std::string> *cmdLineLists[3] = {
+ &preLinkCmdLines,
+ &preLinkCmdLines,
+ &postBuildCmdLines
+ };
+
+ for (unsigned i = 0; i != 3; ++i) {
+ for (std::vector<cmCustomCommand>::const_iterator
+ ci = cmdLists[i]->begin();
+ ci != cmdLists[i]->end(); ++ci) {
+ this->GetLocalGenerator()->AppendCustomCommandLines(&*ci,
+ *cmdLineLists[i]);
+ }
+ }
+
+ // If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for
+ // the link commands.
+ if (!preLinkCmdLines.empty()) {
+ std::string path = this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->GetMakefile()->GetHomeOutputDirectory(),
+ cmLocalGenerator::SHELL);
+ preLinkCmdLines.push_back("cd " + path);
+ }
+
+ vars["PRE_LINK"] =
+ this->GetLocalGenerator()->BuildCommandLine(preLinkCmdLines);
+ std::string postBuildCmdLine =
+ this->GetLocalGenerator()->BuildCommandLine(postBuildCmdLines);
+
+ cmNinjaVars symlinkVars;
+ if (targetOutput == targetOutputReal) {
+ vars["POST_BUILD"] = postBuildCmdLine;
+ } else {
+ vars["POST_BUILD"] = ":";
+ symlinkVars["POST_BUILD"] = postBuildCmdLine;
+ }
+
+ // Write the build statement for this target.
+ cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
+ comment.str(),
+ this->LanguageLinkerRule(),
+ outputs,
+ explicitDeps,
+ implicitDeps,
+ emptyDeps,
+ vars);
+
+ if (targetOutput != targetOutputReal) {
+ if (targetType == cmTarget::EXECUTABLE) {
+ cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
+ "Create executable symlink " + targetOutput,
+ "CMAKE_SYMLINK_EXECUTABLE",
+ cmNinjaDeps(1, targetOutput),
+ cmNinjaDeps(1, targetOutputReal),
+ emptyDeps,
+ emptyDeps,
+ symlinkVars);
+ } else {
+ symlinkVars["SONAME"] = this->GetTargetFilePath(this->TargetNameSO);
+ cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
+ "Create library symlink " + targetOutput,
+ "CMAKE_SYMLINK_LIBRARY",
+ cmNinjaDeps(1, targetOutput),
+ cmNinjaDeps(1, targetOutputReal),
+ emptyDeps,
+ emptyDeps,
+ symlinkVars);
+ }
+ }
+
+ if (!this->TargetNameImport.empty()) {
+ // Since using multiple outputs would mess up the $out variable, use an
+ // alias for the import library.
+ cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+ "Alias for import library.",
+ cmNinjaDeps(1, targetOutputImplib),
+ cmNinjaDeps(1, targetOutputReal));
+ }
+
+ // Add aliases for the file name and the target name.
+ this->GetGlobalGenerator()->AddTargetAlias(this->TargetNameOut,
+ this->GetTarget());
+ this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
+ this->GetTarget());
+}
+
+//----------------------------------------------------------------------------
+void cmNinjaNormalTargetGenerator::WriteObjectLibStatement()
+{
+ // Write a phony output that depends on all object files.
+ cmNinjaDeps outputs;
+ this->GetLocalGenerator()->AppendTargetOutputs(this->GetTarget(), outputs);
+ cmNinjaDeps depends = this->GetObjects();
+ cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+ "Object library "
+ + this->GetTargetName(),
+ outputs,
+ depends);
+
+ // Add aliases for the target name.
+ this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
+ this->GetTarget());
+}
diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h
new file mode 100644
index 0000000..1702caf
--- /dev/null
+++ b/Source/cmNinjaNormalTargetGenerator.h
@@ -0,0 +1,48 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 cmNinjaNormalTargetGenerator_h
+# define cmNinjaNormalTargetGenerator_h
+
+# include "cmNinjaTargetGenerator.h"
+# include "cmNinjaTypes.h"
+
+class cmSourceFile;
+
+class cmNinjaNormalTargetGenerator : public cmNinjaTargetGenerator
+{
+public:
+ cmNinjaNormalTargetGenerator(cmTarget* target);
+ ~cmNinjaNormalTargetGenerator();
+
+ void Generate();
+
+private:
+ std::string LanguageLinkerRule() const;
+ const char* GetVisibleTypeName() const;
+ void WriteLanguagesRules();
+ void WriteLinkRule();
+ void WriteLinkStatement();
+ void WriteObjectLibStatement();
+ std::vector<std::string> ComputeLinkCmd();
+
+private:
+ // Target name info.
+ std::string TargetNameOut;
+ std::string TargetNameSO;
+ std::string TargetNameReal;
+ std::string TargetNameImport;
+ std::string TargetNamePDB;
+ const char *TargetLinkLanguage;
+};
+
+#endif // ! cmNinjaNormalTargetGenerator_h
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
new file mode 100644
index 0000000..c6469f2
--- /dev/null
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -0,0 +1,536 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 "cmNinjaTargetGenerator.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmLocalNinjaGenerator.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmNinjaNormalTargetGenerator.h"
+#include "cmNinjaUtilityTargetGenerator.h"
+#include "cmSystemTools.h"
+#include "cmMakefile.h"
+#include "cmComputeLinkInformation.h"
+#include "cmSourceFile.h"
+#include "cmCustomCommandGenerator.h"
+
+#include <algorithm>
+
+cmNinjaTargetGenerator *
+cmNinjaTargetGenerator::New(cmTarget* target)
+{
+ switch (target->GetType())
+ {
+ case cmTarget::EXECUTABLE:
+ case cmTarget::SHARED_LIBRARY:
+ case cmTarget::STATIC_LIBRARY:
+ case cmTarget::MODULE_LIBRARY:
+ case cmTarget::OBJECT_LIBRARY:
+ return new cmNinjaNormalTargetGenerator(target);
+
+ case cmTarget::UTILITY:
+ return new cmNinjaUtilityTargetGenerator(target);;
+
+ case cmTarget::GLOBAL_TARGET: {
+ // We only want to process global targets that live in the home
+ // (i.e. top-level) directory. CMake creates copies of these targets
+ // in every directory, which we don't need.
+ cmMakefile *mf = target->GetMakefile();
+ if (strcmp(mf->GetStartDirectory(), mf->GetHomeDirectory()) == 0)
+ return new cmNinjaUtilityTargetGenerator(target);
+ // else fallthrough
+ }
+
+ default:
+ return 0;
+ }
+}
+
+cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmTarget* target)
+ : Target(target),
+ Makefile(target->GetMakefile()),
+ LocalGenerator(
+ static_cast<cmLocalNinjaGenerator*>(Makefile->GetLocalGenerator())),
+ Objects()
+{
+ this->GeneratorTarget =
+ this->GetGlobalGenerator()->GetGeneratorTarget(target);
+}
+
+cmNinjaTargetGenerator::~cmNinjaTargetGenerator()
+{
+}
+
+cmGeneratedFileStream& cmNinjaTargetGenerator::GetBuildFileStream() const
+{
+ return *this->GetGlobalGenerator()->GetBuildFileStream();
+}
+
+cmGeneratedFileStream& cmNinjaTargetGenerator::GetRulesFileStream() const
+{
+ return *this->GetGlobalGenerator()->GetRulesFileStream();
+}
+
+cmGlobalNinjaGenerator* cmNinjaTargetGenerator::GetGlobalGenerator() const
+{
+ return this->LocalGenerator->GetGlobalNinjaGenerator();
+}
+
+const char* cmNinjaTargetGenerator::GetConfigName() const
+{
+ return this->LocalGenerator->ConfigName.c_str();
+}
+
+// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
+const char* cmNinjaTargetGenerator::GetFeature(const char* feature)
+{
+ return this->Target->GetFeature(feature, this->GetConfigName());
+}
+
+// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
+bool cmNinjaTargetGenerator::GetFeatureAsBool(const char* feature)
+{
+ return cmSystemTools::IsOn(this->GetFeature(feature));
+}
+
+// TODO: Picked up from cmMakefileTargetGenerator. Refactor it.
+void cmNinjaTargetGenerator::AddFeatureFlags(std::string& flags,
+ const char* lang)
+{
+ // Add language-specific flags.
+ this->LocalGenerator->AddLanguageFlags(flags, lang, this->GetConfigName());
+
+ if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
+ {
+ this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
+ }
+}
+
+// TODO: Most of the code is picked up from
+// void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink),
+// void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
+// Refactor it.
+std::string
+cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
+ const std::string& language)
+{
+ std::string flags;
+
+ this->AddFeatureFlags(flags, language.c_str());
+
+ this->GetLocalGenerator()->AddArchitectureFlags(flags,
+ this->GetTarget(),
+ language.c_str(),
+ this->GetConfigName());
+
+ // TODO: Fortran support.
+ // // Fortran-specific flags computed for this target.
+ // if(*l == "Fortran")
+ // {
+ // this->AddFortranFlags(flags);
+ // }
+
+ // Add shared-library flags if needed.
+ {
+ bool shared = ((this->Target->GetType() == cmTarget::SHARED_LIBRARY) ||
+ (this->Target->GetType() == cmTarget::MODULE_LIBRARY));
+ this->GetLocalGenerator()->AddSharedFlags(flags, language.c_str(), shared);
+ }
+
+ // TODO: Handle response file.
+ // Add include directory flags.
+ {
+ std::vector<std::string> includes;
+ this->LocalGenerator->GetIncludeDirectories(includes, this->Target,
+ language.c_str());
+ std::string includeFlags =
+ this->LocalGenerator->GetIncludeFlags(includes, language.c_str(), false);
+ this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
+ }
+
+ // Append old-style preprocessor definition flags.
+ this->LocalGenerator->AppendFlags(flags, this->Makefile->GetDefineFlags());
+
+ // Add target-specific and source-specific flags.
+ this->LocalGenerator->AppendFlags(flags,
+ this->Target->GetProperty("COMPILE_FLAGS"));
+ this->LocalGenerator->AppendFlags(flags,
+ source->GetProperty("COMPILE_FLAGS"));
+
+ // TODO: Handle Apple frameworks.
+
+ return flags;
+}
+
+// TODO: Refactor with
+// void cmMakefileTargetGenerator::WriteTargetLanguageFlags().
+std::string
+cmNinjaTargetGenerator::
+ComputeDefines(cmSourceFile *source, const std::string& language)
+{
+ std::string defines;
+
+ // Add the export symbol definition for shared library objects.
+ if(const char* exportMacro = this->Target->GetExportMacro())
+ {
+ this->LocalGenerator->AppendDefines(defines, exportMacro,
+ language.c_str());
+ }
+
+ // Add preprocessor definitions for this target and configuration.
+ this->LocalGenerator->AppendDefines
+ (defines,
+ this->Makefile->GetProperty("COMPILE_DEFINITIONS"),
+ language.c_str());
+ this->LocalGenerator->AppendDefines
+ (defines,
+ this->Target->GetProperty("COMPILE_DEFINITIONS"),
+ language.c_str());
+ this->LocalGenerator->AppendDefines
+ (defines,
+ source->GetProperty("COMPILE_DEFINITIONS"),
+ language.c_str());
+ {
+ std::string defPropName = "COMPILE_DEFINITIONS_";
+ defPropName += cmSystemTools::UpperCase(this->GetConfigName());
+ this->LocalGenerator->AppendDefines
+ (defines,
+ this->Makefile->GetProperty(defPropName.c_str()),
+ language.c_str());
+ this->LocalGenerator->AppendDefines
+ (defines,
+ this->Target->GetProperty(defPropName.c_str()),
+ language.c_str());
+ this->LocalGenerator->AppendDefines
+ (defines,
+ source->GetProperty(defPropName.c_str()),
+ language.c_str());
+ }
+
+ return defines;
+}
+
+cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
+{
+ // Static libraries never depend on other targets for linking.
+ if (this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
+ this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
+ return cmNinjaDeps();
+
+ cmComputeLinkInformation* cli =
+ this->Target->GetLinkInformation(this->GetConfigName());
+ if(!cli)
+ return cmNinjaDeps();
+
+ const std::vector<std::string> &deps = cli->GetDepends();
+ cmNinjaDeps result(deps.size());
+ std::transform(deps.begin(), deps.end(), result.begin(), MapToNinjaPath());
+
+ // Add a dependency on the link definitions file, if any.
+ if(!this->ModuleDefinitionFile.empty())
+ {
+ result.push_back(this->ModuleDefinitionFile);
+ }
+
+ return result;
+}
+
+std::string
+cmNinjaTargetGenerator
+::GetSourceFilePath(cmSourceFile* source) const
+{
+ return ConvertToNinjaPath(source->GetFullPath().c_str());
+}
+
+std::string
+cmNinjaTargetGenerator
+::GetObjectFilePath(cmSourceFile* source) const
+{
+ std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
+ if(!path.empty())
+ path += "/";
+ std::string const& objectName = this->GeneratorTarget->Objects[source];
+ path += this->LocalGenerator->GetTargetDirectory(*this->Target);
+ path += "/";
+ path += objectName;
+ return path;
+}
+
+std::string cmNinjaTargetGenerator::GetTargetOutputDir() const
+{
+ std::string dir = this->Target->GetDirectory(this->GetConfigName());
+ return ConvertToNinjaPath(dir.c_str());
+}
+
+std::string
+cmNinjaTargetGenerator
+::GetTargetFilePath(const std::string& name) const
+{
+ std::string path = this->GetTargetOutputDir();
+ if (path.empty() || path == ".")
+ return name;
+ path += "/";
+ path += name;
+ return path;
+}
+
+std::string cmNinjaTargetGenerator::GetTargetName() const
+{
+ return this->Target->GetName();
+}
+
+std::string cmNinjaTargetGenerator::GetTargetPDB() const
+{
+ 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)
+ {
+ targetFullPathPDB = this->Target->GetDirectory(this->GetConfigName());
+ targetFullPathPDB += "/";
+ targetFullPathPDB += this->Target->GetPDBName(this->GetConfigName());
+ }
+
+ return ConvertToNinjaPath(targetFullPathPDB.c_str());
+}
+
+
+void
+cmNinjaTargetGenerator
+::WriteLanguageRules(const std::string& language)
+{
+ this->GetRulesFileStream()
+ << "# Rules for language " << language << "\n\n";
+ this->WriteCompileRule(language);
+ this->GetRulesFileStream() << "\n";
+}
+
+void
+cmNinjaTargetGenerator
+::WriteCompileRule(const std::string& language)
+{
+ cmLocalGenerator::RuleVariables vars;
+ vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
+ vars.CMTarget = this->GetTarget();
+ std::string lang = language;
+ vars.Language = lang.c_str();
+ vars.Source = "$in";
+ vars.Object = "$out";
+ std::string flags = "$FLAGS";
+ vars.Defines = "$DEFINES";
+ vars.TargetPDB = "$TARGET_PDB";
+
+ std::string depfile;
+ std::string depfileFlagsName = "CMAKE_DEPFILE_FLAGS_" + language;
+ const char *depfileFlags =
+ this->GetMakefile()->GetDefinition(depfileFlagsName.c_str());
+ if (depfileFlags) {
+ std::string depfileFlagsStr = depfileFlags;
+ depfile = "$out.d";
+ cmSystemTools::ReplaceString(depfileFlagsStr, "<DEPFILE>",
+ depfile.c_str());
+ cmSystemTools::ReplaceString(depfileFlagsStr, "<OBJECT>",
+ "$out");
+ cmSystemTools::ReplaceString(depfileFlagsStr, "<CMAKE_C_COMPILER>",
+ this->GetMakefile()->GetDefinition("CMAKE_C_COMPILER"));
+ flags += " " + depfileFlagsStr;
+ }
+ vars.Flags = flags.c_str();
+
+
+ // Rule for compiling object file.
+ std::string compileCmdVar = "CMAKE_";
+ compileCmdVar += language;
+ compileCmdVar += "_COMPILE_OBJECT";
+ std::string compileCmd =
+ this->GetMakefile()->GetRequiredDefinition(compileCmdVar.c_str());
+ std::vector<std::string> compileCmds;
+ cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
+
+ for (std::vector<std::string>::iterator i = compileCmds.begin();
+ i != compileCmds.end(); ++i)
+ this->GetLocalGenerator()->ExpandRuleVariables(*i, vars);
+
+ std::string cmdLine =
+ this->GetLocalGenerator()->BuildCommandLine(compileCmds);
+
+ // Write the rule for compiling file of the given language.
+ std::ostringstream comment;
+ comment << "Rule for compiling " << language << " files.";
+ std::ostringstream description;
+ description << "Building " << language << " object $out";
+ this->GetGlobalGenerator()->AddRule(this->LanguageCompilerRule(language),
+ cmdLine,
+ description.str(),
+ comment.str(),
+ depfile);
+}
+
+void
+cmNinjaTargetGenerator
+::WriteObjectBuildStatements()
+{
+ // Write comments.
+ cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
+ this->GetBuildFileStream()
+ << "# Object build statements for "
+ << cmTarget::GetTargetTypeName(this->GetTarget()->GetType())
+ << " target "
+ << this->GetTargetName()
+ << "\n\n";
+
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->CustomCommands.begin();
+ si != this->GeneratorTarget->CustomCommands.end(); ++si)
+ {
+ cmCustomCommand const* cc = (*si)->GetCustomCommand();
+ this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());
+ }
+ // TODO: this->GeneratorTarget->OSXContent
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ExternalObjects.begin();
+ si != this->GeneratorTarget->ExternalObjects.end(); ++si)
+ {
+ this->Objects.push_back(this->GetSourceFilePath(*si));
+ }
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ObjectSources.begin();
+ si != this->GeneratorTarget->ObjectSources.end(); ++si)
+ {
+ this->WriteObjectBuildStatement(*si);
+ }
+ if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
+ {
+ this->ModuleDefinitionFile = this->ConvertToNinjaPath(
+ this->GeneratorTarget->ModuleDefinitionFile.c_str());
+ }
+
+ {
+ // Add object library contents as external objects.
+ std::vector<std::string> objs;
+ this->GeneratorTarget->UseObjectLibraries(objs);
+ for(std::vector<std::string>::iterator oi = objs.begin();
+ oi != objs.end(); ++oi)
+ {
+ this->Objects.push_back(ConvertToNinjaPath(oi->c_str()));
+ }
+ }
+
+ this->GetBuildFileStream() << "\n";
+}
+
+void
+cmNinjaTargetGenerator
+::WriteObjectBuildStatement(cmSourceFile* source)
+{
+ cmNinjaDeps emptyDeps;
+
+ std::string comment;
+ const char* language = source->GetLanguage();
+ std::string rule = this->LanguageCompilerRule(language);
+
+ cmNinjaDeps outputs;
+ std::string objectFileName = this->GetObjectFilePath(source);
+ outputs.push_back(objectFileName);
+ // Add this object to the list of object files.
+ this->Objects.push_back(objectFileName);
+
+ cmNinjaDeps explicitDeps;
+ std::string sourceFileName = this->GetSourceFilePath(source);
+ explicitDeps.push_back(sourceFileName);
+
+ // Ensure that the target dependencies are built before any source file in
+ // the target, using order-only dependencies.
+ cmNinjaDeps orderOnlyDeps;
+ this->GetLocalGenerator()->AppendTargetDepends(this->Target, orderOnlyDeps);
+
+ if(const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) {
+ std::vector<std::string> depList;
+ cmSystemTools::ExpandListArgument(objectDeps, depList);
+ std::transform(depList.begin(), depList.end(),
+ std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ }
+
+ // Add order-only dependencies on custom command outputs.
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->CustomCommands.begin();
+ si != this->GeneratorTarget->CustomCommands.end(); ++si)
+ {
+ cmCustomCommand const* cc = (*si)->GetCustomCommand();
+ const std::vector<std::string>& ccoutputs = cc->GetOutputs();
+ std::transform(ccoutputs.begin(), ccoutputs.end(),
+ std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ }
+
+ // If the source file is GENERATED and does not have a custom command
+ // (either attached to this source file or another one), assume that one of
+ // the target dependencies, OBJECT_DEPENDS or header file custom commands
+ // will rebuild the file.
+ if (source->GetPropertyAsBool("GENERATED") && !source->GetCustomCommand() &&
+ !this->GetGlobalGenerator()->HasCustomCommandOutput(sourceFileName)) {
+ this->GetGlobalGenerator()->AddAssumedSourceDependencies(sourceFileName,
+ orderOnlyDeps);
+ }
+
+ cmNinjaVars vars;
+ vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
+ vars["DEFINES"] = this->ComputeDefines(source, language);
+ vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->GetTargetPDB().c_str(), cmLocalGenerator::SHELL);
+
+ cmGlobalNinjaGenerator::WriteBuild(this->GetBuildFileStream(),
+ comment,
+ rule,
+ outputs,
+ explicitDeps,
+ emptyDeps,
+ orderOnlyDeps,
+ vars);
+
+ if(const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
+ std::vector<std::string> outputList;
+ cmSystemTools::ExpandListArgument(objectOutputs, outputList);
+ std::transform(outputList.begin(), outputList.end(), outputList.begin(),
+ MapToNinjaPath());
+ cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+ "Additional output files.",
+ outputList,
+ outputs);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmNinjaTargetGenerator
+::AddModuleDefinitionFlag(std::string& flags)
+{
+ if(this->ModuleDefinitionFile.empty())
+ {
+ return;
+ }
+
+ // TODO: Create a per-language flag variable.
+ const char* defFileFlag =
+ this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
+ if(!defFileFlag)
+ {
+ return;
+ }
+
+ // Append the flag and value. Use ConvertToLinkReference to help
+ // vs6's "cl -link" pass it to the linker.
+ std::string flag = defFileFlag;
+ flag += (this->LocalGenerator->ConvertToLinkReference(
+ this->ModuleDefinitionFile.c_str()));
+ this->LocalGenerator->AppendFlags(flags, flag.c_str());
+}
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
new file mode 100644
index 0000000..b64ce1e
--- /dev/null
+++ b/Source/cmNinjaTargetGenerator.h
@@ -0,0 +1,126 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 cmNinjaTargetGenerator_h
+#define cmNinjaTargetGenerator_h
+
+#include "cmStandardIncludes.h"
+#include "cmNinjaTypes.h"
+#include "cmLocalNinjaGenerator.h"
+
+class cmTarget;
+class cmGlobalNinjaGenerator;
+class cmGeneratedFileStream;
+class cmGeneratorTarget;
+class cmMakefile;
+class cmSourceFile;
+class cmCustomCommand;
+
+class cmNinjaTargetGenerator
+{
+public:
+ /// Create a cmNinjaTargetGenerator according to the @a target's type.
+ static cmNinjaTargetGenerator* New(cmTarget* target);
+
+ /// Build a NinjaTargetGenerator.
+ cmNinjaTargetGenerator(cmTarget* target);
+
+ /// Destructor.
+ virtual ~cmNinjaTargetGenerator();
+
+ virtual void Generate() = 0;
+
+ std::string GetTargetPDB() const;
+ std::string GetTargetName() const;
+
+protected:
+ cmGeneratedFileStream& GetBuildFileStream() const;
+ cmGeneratedFileStream& GetRulesFileStream() const;
+
+ cmTarget* GetTarget() const
+ { return this->Target; }
+
+ cmLocalNinjaGenerator* GetLocalGenerator() const
+ { return this->LocalGenerator; }
+
+ cmGlobalNinjaGenerator* GetGlobalGenerator() const;
+
+ cmMakefile* GetMakefile() const
+ { return this->Makefile; }
+
+ const char* GetConfigName() const;
+
+ std::string LanguageCompilerRule(const std::string& lang) const
+ { return lang + "_COMPILER"; }
+
+ const char* GetFeature(const char* feature);
+ bool GetFeatureAsBool(const char* feature);
+ void AddFeatureFlags(std::string& flags, const char* lang);
+
+ /**
+ * 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,
+ const std::string& language);
+
+ std::string ComputeDefines(cmSourceFile *source,
+ const std::string& language);
+
+ std::string ConvertToNinjaPath(const char *path) const {
+ return this->GetLocalGenerator()->ConvertToNinjaPath(path);
+ }
+ cmLocalNinjaGenerator::map_to_ninja_path MapToNinjaPath() const {
+ return this->GetLocalGenerator()->MapToNinjaPath();
+ }
+
+ /// @return the list of link dependency for the given target @a target.
+ cmNinjaDeps ComputeLinkDeps() const;
+
+ /// @return the source file path for the given @a source.
+ std::string GetSourceFilePath(cmSourceFile* source) const;
+
+ /// @return the object file path for the given @a source.
+ std::string GetObjectFilePath(cmSourceFile* source) const;
+
+ /// @return the file path where the target named @a name is generated.
+ std::string GetTargetFilePath(const std::string& name) const;
+
+ /// @return the output path for the target.
+ virtual std::string GetTargetOutputDir() const;
+
+ void WriteLanguageRules(const std::string& language);
+ void WriteCompileRule(const std::string& language);
+ void WriteObjectBuildStatements();
+ void WriteObjectBuildStatement(cmSourceFile* source);
+ void WriteCustomCommandBuildStatement(cmCustomCommand *cc);
+
+ cmNinjaDeps GetObjects() const
+ { return this->Objects; }
+
+ // Helper to add flag for windows .def file.
+ void AddModuleDefinitionFlag(std::string& flags);
+
+private:
+ cmTarget* Target;
+ cmGeneratorTarget* GeneratorTarget;
+ cmMakefile* Makefile;
+ cmLocalNinjaGenerator* LocalGenerator;
+ /// List of object files for this target.
+ cmNinjaDeps Objects;
+
+ // The windows module definition source file (.def), if any.
+ std::string ModuleDefinitionFile;
+};
+
+#endif // ! cmNinjaTargetGenerator_h
diff --git a/Source/cmNinjaTypes.h b/Source/cmNinjaTypes.h
new file mode 100644
index 0000000..498f6b6
--- /dev/null
+++ b/Source/cmNinjaTypes.h
@@ -0,0 +1,19 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 cmNinjaTypes_h
+# define cmNinjaTypes_h
+
+typedef std::vector<std::string> cmNinjaDeps;
+typedef std::map<std::string, std::string> cmNinjaVars;
+
+#endif // ! cmNinjaTypes_h
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
new file mode 100644
index 0000000..9c2fd13
--- /dev/null
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -0,0 +1,116 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 "cmNinjaUtilityTargetGenerator.h"
+#include "cmCustomCommand.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalNinjaGenerator.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmTarget.h"
+
+cmNinjaUtilityTargetGenerator::cmNinjaUtilityTargetGenerator(cmTarget *target)
+ : cmNinjaTargetGenerator(target) {}
+
+cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() {}
+
+void cmNinjaUtilityTargetGenerator::Generate()
+{
+ std::vector<std::string> commands;
+ cmNinjaDeps deps, outputs;
+
+ const std::vector<cmCustomCommand> *cmdLists[2] = {
+ &this->GetTarget()->GetPreBuildCommands(),
+ &this->GetTarget()->GetPostBuildCommands()
+ };
+
+ for (unsigned i = 0; i != 2; ++i) {
+ for (std::vector<cmCustomCommand>::const_iterator
+ ci = cmdLists[i]->begin(); ci != cmdLists[i]->end(); ++ci) {
+ this->GetLocalGenerator()->AppendCustomCommandDeps(&*ci, deps);
+ this->GetLocalGenerator()->AppendCustomCommandLines(&*ci, commands);
+ }
+ }
+
+ const std::vector<cmSourceFile*>& sources =
+ this->GetTarget()->GetSourceFiles();
+ for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
+ source != sources.end(); ++source)
+ {
+ if(cmCustomCommand* cc = (*source)->GetCustomCommand())
+ {
+ this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget());
+
+ // Depend on all custom command outputs.
+ const std::vector<std::string>& ccOutputs = cc->GetOutputs();
+ std::transform(ccOutputs.begin(), ccOutputs.end(),
+ std::back_inserter(deps), MapToNinjaPath());
+ }
+ }
+
+ this->GetLocalGenerator()->AppendTargetOutputs(this->GetTarget(), outputs);
+ this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(), deps);
+
+ if (commands.empty()) {
+ cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+ "Utility command for "
+ + this->GetTargetName(),
+ outputs,
+ deps);
+ } else {
+ std::string command =
+ this->GetLocalGenerator()->BuildCommandLine(commands);
+ const char *echoStr = this->GetTarget()->GetProperty("EchoString");
+ std::string desc;
+ if (echoStr)
+ desc = echoStr;
+ else
+ desc = "Running utility command for " + this->GetTargetName();
+
+ // TODO: fix problematic global targets. For now, search and replace the
+ // makefile vars.
+ cmSystemTools::ReplaceString(
+ command,
+ "$(CMAKE_SOURCE_DIR)",
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->GetTarget()->GetMakefile()->GetHomeDirectory(),
+ cmLocalGenerator::SHELL).c_str());
+ cmSystemTools::ReplaceString(
+ command,
+ "$(CMAKE_BINARY_DIR)",
+ this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->GetTarget()->GetMakefile()->GetHomeOutputDirectory(),
+ cmLocalGenerator::SHELL).c_str());
+ cmSystemTools::ReplaceString(command, "$(ARGS)", "");
+
+ if (command.find('$') != std::string::npos)
+ return;
+
+ std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash();
+ utilCommandName += this->GetTargetName() + ".util";
+
+ this->GetGlobalGenerator()->WriteCustomCommandBuild(
+ command,
+ desc,
+ "Utility command for " + this->GetTargetName(),
+ cmNinjaDeps(1, utilCommandName),
+ deps);
+
+ cmGlobalNinjaGenerator::WritePhonyBuild(this->GetBuildFileStream(),
+ "",
+ outputs,
+ cmNinjaDeps(1, utilCommandName));
+ }
+
+ this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
+ this->GetTarget());
+}
diff --git a/Source/cmNinjaUtilityTargetGenerator.h b/Source/cmNinjaUtilityTargetGenerator.h
new file mode 100644
index 0000000..8b82ce4
--- /dev/null
+++ b/Source/cmNinjaUtilityTargetGenerator.h
@@ -0,0 +1,30 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2011 Peter Collingbourne <peter@pcc.me.uk>
+ Copyright 2011 Nicolas Despres <nicolas.despres@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 cmNinjaUtilityTargetGenerator_h
+# define cmNinjaUtilityTargetGenerator_h
+
+# include "cmNinjaTargetGenerator.h"
+# include "cmNinjaTypes.h"
+
+class cmSourceFile;
+
+class cmNinjaUtilityTargetGenerator : public cmNinjaTargetGenerator
+{
+public:
+ cmNinjaUtilityTargetGenerator(cmTarget* target);
+ ~cmNinjaUtilityTargetGenerator();
+
+ void Generate();
+};
+
+#endif // ! cmNinjaUtilityTargetGenerator_h
diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx
index 0d0d80c..ca27530 100644
--- a/Source/cmQtAutomoc.cxx
+++ b/Source/cmQtAutomoc.cxx
@@ -20,6 +20,9 @@
#include <cmsys/Terminal.h>
#include <string.h>
+#if defined(__APPLE__)
+#include <unistd.h>
+#endif
#include "cmQtAutomoc.h"
@@ -202,13 +205,20 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
cmMakefile::ScopePushPop varScope(makefile);
static_cast<void>(varScope);
- makefile->AddDefinition("_moc_target_name", automocTargetName.c_str());
- makefile->AddDefinition("_moc_incs", _moc_incs.c_str());
- makefile->AddDefinition("_moc_defs", _moc_defs.c_str());
- makefile->AddDefinition("_moc_compile_defs", _moc_compile_defs.c_str());
- makefile->AddDefinition("_moc_options", _moc_options.c_str());
- makefile->AddDefinition("_moc_files", _moc_files.c_str());
- makefile->AddDefinition("_moc_headers", _moc_headers.c_str());
+ makefile->AddDefinition("_moc_target_name",
+ cmLocalGenerator::EscapeForCMake(automocTargetName.c_str()).c_str());
+ makefile->AddDefinition("_moc_incs",
+ cmLocalGenerator::EscapeForCMake(_moc_incs.c_str()).c_str());
+ makefile->AddDefinition("_moc_defs",
+ cmLocalGenerator::EscapeForCMake(_moc_defs.c_str()).c_str());
+ makefile->AddDefinition("_moc_compile_defs",
+ cmLocalGenerator::EscapeForCMake(_moc_compile_defs.c_str()).c_str());
+ makefile->AddDefinition("_moc_options",
+ cmLocalGenerator::EscapeForCMake(_moc_options.c_str()).c_str());
+ makefile->AddDefinition("_moc_files",
+ cmLocalGenerator::EscapeForCMake(_moc_files.c_str()).c_str());
+ makefile->AddDefinition("_moc_headers",
+ cmLocalGenerator::EscapeForCMake(_moc_headers.c_str()).c_str());
makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE");
const char* cmakeRoot = makefile->GetSafeDefinition("CMAKE_ROOT");
@@ -340,8 +350,9 @@ void cmQtAutomoc::WriteOldMocDefinitionsFile(const char* targetDirectory)
std::fstream outfile;
outfile.open(filename.c_str(),
std::ios::out | std::ios::trunc);
- outfile << "set(AM_OLD_MOC_DEFINITIONS \""
- << this->Join(this->MocDefinitions, ' ') << "\")\n";
+ outfile << "set(AM_OLD_MOC_DEFINITIONS "
+ << cmLocalGenerator::EscapeForCMake(
+ this->Join(this->MocDefinitions, ' ').c_str()) << ")\n";
outfile.close();
}
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index 55147e1..ae01274 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -116,4 +116,7 @@ private:
std::vector<std::string> Depends;
};
+// TODO: Factor out into platform information modules.
+#define CM_HEADER_REGEX "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$"
+
#endif
diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx
index 19ae8fc..2b34f2b 100644
--- a/Source/cmSourceGroup.cxx
+++ b/Source/cmSourceGroup.cxx
@@ -120,12 +120,6 @@ const std::vector<const cmSourceFile*>& cmSourceGroup::GetSourceFiles() const
}
//----------------------------------------------------------------------------
-std::vector<const cmSourceFile*>& cmSourceGroup::GetSourceFiles()
-{
- return this->SourceFiles;
-}
-
-//----------------------------------------------------------------------------
void cmSourceGroup::AddChild(cmSourceGroup child)
{
this->Internal->GroupChildren.push_back(child);
diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h
index 71ccb51..641dcbd 100644
--- a/Source/cmSourceGroup.h
+++ b/Source/cmSourceGroup.h
@@ -100,7 +100,6 @@ public:
* source group.
*/
const std::vector<const cmSourceFile*>& GetSourceFiles() const;
- std::vector<const cmSourceFile*>& GetSourceFiles();
std::vector<cmSourceGroup> const& GetGroupChildren() const;
private:
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 81ee5ce..25975e0 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -201,6 +201,20 @@ std::string cmSystemTools::EscapeQuotes(const char* str)
return result;
}
+std::string cmSystemTools::TrimWhitespace(const std::string& s)
+{
+ std::string::const_iterator start = s.begin();
+ while(start != s.end() && *start == ' ')
+ ++start;
+ if (start == s.end())
+ return "";
+
+ std::string::const_iterator stop = s.end()-1;
+ while(*stop == ' ')
+ --stop;
+ return std::string(start, stop+1);
+}
+
void cmSystemTools::Error(const char* m1, const char* m2,
const char* m3, const char* m4)
{
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 7afc701..5f21de2 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -49,6 +49,11 @@ public:
///! Escape quotes in a string.
static std::string EscapeQuotes(const char* str);
+ /**
+ * Returns a string that has whitespace removed from the start and the end.
+ */
+ static std::string TrimWhitespace(const std::string& s);
+
typedef void (*ErrorCallback)(const char*, const char*, bool&, void*);
/**
* Set the function used by GUI's to display error messages
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index da99eb9..cfa9976 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -37,6 +37,8 @@ const char* cmTarget::GetTargetTypeName(TargetType targetType)
return "MODULE_LIBRARY";
case cmTarget::SHARED_LIBRARY:
return "SHARED_LIBRARY";
+ case cmTarget::OBJECT_LIBRARY:
+ return "OBJECT_LIBRARY";
case cmTarget::EXECUTABLE:
return "EXECUTABLE";
case cmTarget::UTILITY:
@@ -480,6 +482,26 @@ void cmTarget::DefineProperties(cmake *cm)
"undefined behavior.");
cm->DefineProperty
+ ("INCLUDE_DIRECTORIES", cmProperty::TARGET,
+ "List of preprocessor include file search directories.",
+ "This property specifies the list of directories given "
+ "so far to the include_directories command. "
+ "This property exists on directories and targets. "
+ "In addition to accepting values from the include_directories "
+ "command, values may be set directly on any directory or any "
+ "target using the set_property command. "
+ "A target gets its initial value for this property from the value "
+ "of the directory property. "
+ "A directory gets its initial value from its parent directory if "
+ "it has one. "
+ "Both directory and target property values are adjusted by calls "
+ "to the include_directories command."
+ "\n"
+ "The target property values are used by the generators to set "
+ "the include paths for the compiler. "
+ "See also the include_directories command.");
+
+ cm->DefineProperty
("INSTALL_NAME_DIR", cmProperty::TARGET,
"Mac OSX directory name for installed targets.",
"INSTALL_NAME_DIR is a string specifying the "
@@ -825,9 +847,10 @@ void cmTarget::DefineProperties(cmake *cm)
cm->DefineProperty
("SUFFIX", cmProperty::TARGET,
- "What comes after the library name.",
+ "What comes after the target name.",
"A target property that can be set to override the suffix "
- "(such as \".so\") on a library name.");
+ "(such as \".so\" or \".exe\") on the name of a library, module or "
+ "executable.");
cm->DefineProperty
("TYPE", cmProperty::TARGET,
@@ -861,7 +884,9 @@ void cmTarget::DefineProperties(cmake *cm)
"of of just main()."
"This makes it a GUI executable instead of a console application. "
"See the CMAKE_MFC_FLAG variable documentation to configure use "
- "of MFC for WinMain executables.");
+ "of MFC for WinMain executables. "
+ "This property is initialized by the value of the variable "
+ "CMAKE_WIN32_EXECUTABLE if it is set when a target is created.");
cm->DefineProperty
("MACOSX_BUNDLE", cmProperty::TARGET,
@@ -871,7 +896,9 @@ void cmTarget::DefineProperties(cmake *cm)
"This makes it a GUI executable that can be launched from "
"the Finder. "
"See the MACOSX_BUNDLE_INFO_PLIST target property for information "
- "about creation of the Info.plist file for the application bundle.");
+ "about creation of the Info.plist file for the application bundle. "
+ "This property is initialized by the value of the variable "
+ "CMAKE_MACOSX_BUNDLE if it is set when a target is created.");
cm->DefineProperty
("MACOSX_BUNDLE_INFO_PLIST", cmProperty::TARGET,
@@ -958,7 +985,12 @@ void cmTarget::DefineProperties(cmake *cm)
"When this property is not set the modules will be placed in the "
"build directory corresponding to the target's source directory. "
"If the variable CMAKE_Fortran_MODULE_DIRECTORY is set when a target "
- "is created its value is used to initialize this property.");
+ "is created its value is used to initialize this property."
+ "\n"
+ "Note that some compilers will automatically search the module output "
+ "directory for modules USEd during compilation but others will not. "
+ "If your sources USE modules their location must be specified by "
+ "INCLUDE_DIRECTORIES regardless of this property.");
cm->DefineProperty
("GNUtoMS", cmProperty::TARGET,
@@ -1077,17 +1109,6 @@ void cmTarget::DefineProperties(cmake *cm)
"better if VS_GLOBAL_QtVersion is set to the version "
"FindQt4.cmake found. For example, \"4.7.3\"");
-#if 0
- cm->DefineProperty
- ("OBJECT_FILES", cmProperty::TARGET,
- "Used to get the resulting list of object files that make up a "
- "target.",
- "This can be used to put object files from one library "
- "into another library. It is a read only property. It "
- "converts the source list for the target into a list of full "
- "paths to object names that will be produced by the target.");
-#endif
-
#define CM_TARGET_FILE_TYPES_DOC \
"There are three kinds of target files that may be built: " \
"archive, library, and runtime. " \
@@ -1224,6 +1245,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->SetPropertyDefault("AUTOMOC", 0);
this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", 0);
this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0);
+ this->SetPropertyDefault("WIN32_EXECUTABLE", 0);
+ this->SetPropertyDefault("MACOSX_BUNDLE", 0);
// Collect the set of configuration types.
std::vector<std::string> configNames;
@@ -1263,6 +1286,11 @@ void cmTarget::SetMakefile(cmMakefile* mf)
// Save the backtrace of target construction.
this->Makefile->GetBacktrace(this->Internal->Backtrace);
+ // Initialize the INCLUDE_DIRECTORIES property based on the current value
+ // of the same directory property:
+ this->SetProperty("INCLUDE_DIRECTORIES",
+ this->Makefile->GetProperty("INCLUDE_DIRECTORIES"));
+
// Record current policies for later use.
this->PolicyStatusCMP0003 =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0003);
@@ -1702,7 +1730,15 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs)
for(std::vector<std::string>::const_iterator i = srcs.begin();
i != srcs.end(); ++i)
{
- this->AddSource(i->c_str());
+ const char* src = i->c_str();
+ if(src[0] == '$' && src[1] == '<')
+ {
+ this->ProcessSourceExpression(*i);
+ }
+ else
+ {
+ this->AddSource(src);
+ }
}
}
@@ -1721,6 +1757,24 @@ cmSourceFile* cmTarget::AddSource(const char* s)
}
//----------------------------------------------------------------------------
+void cmTarget::ProcessSourceExpression(std::string const& expr)
+{
+ if(strncmp(expr.c_str(), "$<TARGET_OBJECTS:", 17) == 0 &&
+ expr[expr.size()-1] == '>')
+ {
+ std::string objLibName = expr.substr(17, expr.size()-18);
+ this->ObjectLibraries.push_back(objLibName);
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "Unrecognized generator expression:\n"
+ << " " << expr;
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ }
+}
+
+//----------------------------------------------------------------------------
struct cmTarget::SourceFileFlags
cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf)
{
@@ -2582,54 +2636,6 @@ const char *cmTarget::GetProperty(const char* prop)
}
//----------------------------------------------------------------------------
-void cmTarget::ComputeObjectFiles()
-{
- if (this->IsImported())
- {
- return;
- }
-#if 0
- std::vector<std::string> dirs;
- this->Makefile->GetLocalGenerator()->
- GetTargetObjectFileDirectories(this,
- dirs);
- std::string objectFiles;
- std::string objExtensionLookup1 = "CMAKE_";
- std::string objExtensionLookup2 = "_OUTPUT_EXTENSION";
-
- for(std::vector<std::string>::iterator d = dirs.begin();
- d != dirs.end(); ++d)
- {
- for(std::vector<cmSourceFile*>::iterator s = this->SourceFiles.begin();
- s != this->SourceFiles.end(); ++s)
- {
- cmSourceFile* sf = *s;
- if(const char* lang = sf->GetLanguage())
- {
- std::string lookupObj = objExtensionLookup1 + lang;
- lookupObj += objExtensionLookup2;
- const char* obj = this->Makefile->GetDefinition(lookupObj.c_str());
- if(obj)
- {
- if(objectFiles.size())
- {
- objectFiles += ";";
- }
- std::string objFile = *d;
- objFile += "/";
- objFile += this->Makefile->GetLocalGenerator()->
- GetSourceObjectName(*sf);
- objFile += obj;
- objectFiles += objFile;
- }
- }
- }
- }
- this->SetProperty("OBJECT_FILES", objectFiles.c_str());
-#endif
-}
-
-//----------------------------------------------------------------------------
const char *cmTarget::GetProperty(const char* prop,
cmProperty::ScopeType scope)
{
@@ -3586,7 +3592,8 @@ bool cmTarget::HaveBuildTreeRPATH()
bool cmTarget::HaveInstallTreeRPATH()
{
const char* install_rpath = this->GetProperty("INSTALL_RPATH");
- return install_rpath && *install_rpath;
+ return (install_rpath && *install_rpath) &&
+ !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
}
//----------------------------------------------------------------------------
@@ -3693,7 +3700,8 @@ std::string cmTarget::GetInstallNameDirForInstallTree(const char* config,
{
std::string dir;
- if(!this->Makefile->IsOn("CMAKE_SKIP_RPATH"))
+ if(!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
+ !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH"))
{
const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
if(install_name_dir && *install_name_dir)
@@ -4566,7 +4574,21 @@ void cmTarget::ComputeLinkImplementation(const char* config,
// This target needs runtime libraries for its source languages.
std::set<cmStdString> languages;
+ // Get languages used in our source files.
this->GetLanguages(languages);
+ // Get languages used in object library sources.
+ for(std::vector<std::string>::iterator i = this->ObjectLibraries.begin();
+ i != this->ObjectLibraries.end(); ++i)
+ {
+ if(cmTarget* objLib = this->Makefile->FindTargetToUse(i->c_str()))
+ {
+ if(objLib->GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ objLib->GetLanguages(languages);
+ }
+ }
+ }
+ // Copy the set of langauges to the link implementation.
for(std::set<cmStdString>::iterator li = languages.begin();
li != languages.end(); ++li)
{
@@ -4660,6 +4682,30 @@ cmTarget::GetLinkInformation(const char* config)
}
//----------------------------------------------------------------------------
+std::vector<std::string> cmTarget::GetIncludeDirectories()
+{
+ std::vector<std::string> includes;
+ const char *prop = this->GetProperty("INCLUDE_DIRECTORIES");
+ if(prop)
+ {
+ cmSystemTools::ExpandListArgument(prop, 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)
+ {
+ if(uniqueIncludes.insert(*li).second)
+ {
+ orderedAndUniqueIncludes.push_back(*li);
+ }
+ }
+
+ return orderedAndUniqueIncludes;
+}
+
+//----------------------------------------------------------------------------
cmTargetLinkInformationMap
::cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r): derived()
{
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index f4b6955..d41c827 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -59,7 +59,8 @@ class cmTarget
public:
cmTarget();
enum TargetType { EXECUTABLE, STATIC_LIBRARY,
- SHARED_LIBRARY, MODULE_LIBRARY, UTILITY, GLOBAL_TARGET,
+ SHARED_LIBRARY, MODULE_LIBRARY,
+ OBJECT_LIBRARY, UTILITY, GLOBAL_TARGET,
UNKNOWN_LIBRARY};
static const char* GetTargetTypeName(TargetType targetType);
enum CustomCommandType { PRE_BUILD, PRE_LINK, POST_BUILD };
@@ -116,6 +117,10 @@ public:
*/
std::vector<cmSourceFile*> const& GetSourceFiles();
void AddSourceFile(cmSourceFile* sf);
+ std::vector<std::string> const& GetObjectLibraries() const
+ {
+ return this->ObjectLibraries;
+ }
/** Get sources that must be built before the given source. */
std::vector<cmSourceFile*> const* GetSourceDepends(cmSourceFile* sf);
@@ -403,9 +408,6 @@ public:
// Define the properties
static void DefineProperties(cmake *cm);
- // Compute the OBJECT_FILES property only when requested
- void ComputeObjectFiles();
-
/** Get the macro to define when building sources in this target.
If no macro should be defined null is returned. */
const char* GetExportMacro();
@@ -457,6 +459,9 @@ public:
directory. */
bool UsesDefaultOutputDir(const char* config, bool implib);
+ /** Get the include directories for this target. */
+ std::vector<std::string> GetIncludeDirectories();
+
private:
/**
* A list of direct dependencies. Use in conjunction with DependencyMap.
@@ -548,6 +553,7 @@ private:
std::vector<cmCustomCommand> PostBuildCommands;
TargetType TargetTypeValue;
std::vector<cmSourceFile*> SourceFiles;
+ std::vector<std::string> ObjectLibraries;
LinkLibraryVectorType LinkLibraries;
LinkLibraryVectorType PrevLinkedLibraries;
bool LinkLibrariesAnalyzed;
@@ -589,6 +595,8 @@ private:
void MaybeInvalidatePropertyCache(const char* prop);
+ void ProcessSourceExpression(std::string const& expr);
+
// The cmMakefile instance that owns this target. This should
// always be set.
cmMakefile* Makefile;
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index 36c4ca8..dbea1c3 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -84,6 +84,16 @@ bool cmTargetLinkLibrariesCommand
return true;
}
+ if(this->Target->GetType() == cmTarget::OBJECT_LIBRARY)
+ {
+ cmOStringStream e;
+ e << "Object library target \"" << args[0] << "\" "
+ << "may not link to anything.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+
// but we might not have any libs after variable expansion
if(args.size() < 2)
{
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 9418761..6caaad1 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -11,6 +11,7 @@
============================================================================*/
#include "cmVisualStudio10TargetGenerator.h"
#include "cmGlobalVisualStudio10Generator.h"
+#include "cmGeneratorTarget.h"
#include "cmTarget.h"
#include "cmComputeLinkInformation.h"
#include "cmGeneratedFileStream.h"
@@ -62,6 +63,7 @@ cmVisualStudio10TargetGenerator(cmTarget* target,
{
this->GlobalGenerator = gg;
this->Target = target;
+ this->GeneratorTarget = gg->GetGeneratorTarget(target);
this->Makefile = target->GetMakefile();
this->LocalGenerator =
(cmLocalVisualStudio7Generator*)
@@ -70,7 +72,6 @@ cmVisualStudio10TargetGenerator(cmTarget* target,
this->GlobalGenerator->CreateGUID(this->Name.c_str());
this->GUID = this->GlobalGenerator->GetGUID(this->Name.c_str());
this->Platform = gg->GetPlatformName();
- this->ComputeObjectNames();
this->BuildFileStream = 0;
}
@@ -147,7 +148,7 @@ void cmVisualStudio10TargetGenerator::Generate()
this->Target->SetProperty("GENERATOR_FILE_NAME",this->Name.c_str());
this->Target->SetProperty("GENERATOR_FILE_NAME_EXT",
".vcxproj");
- if(this->Target->GetType() <= cmTarget::MODULE_LIBRARY)
+ if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY)
{
if(!this->ComputeClOptions())
{
@@ -252,8 +253,7 @@ void cmVisualStudio10TargetGenerator::Generate()
this->WritePathAndIncrementalLinkOptions();
this->WriteItemDefinitionGroups();
this->WriteCustomCommands();
- this->WriteObjSources();
- this->WriteCLSources();
+ this->WriteAllSources();
this->WriteDotNetReferences();
this->WriteWinRTReferences();
this->WriteProjectReferences();
@@ -358,6 +358,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
case cmTarget::MODULE_LIBRARY:
configType += "DynamicLibrary";
break;
+ case cmTarget::OBJECT_LIBRARY:
case cmTarget::STATIC_LIBRARY:
configType += "StaticLibrary";
break;
@@ -388,12 +389,17 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
mfcLine += useOfMfcValue + "</UseOfMfc>\n";
this->WriteString(mfcLine.c_str(), 2);
- if(this->Target->GetType() <= cmTarget::MODULE_LIBRARY &&
+ if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY &&
this->ClOptions[*i]->UsingUnicode() ||
this->Target->GetPropertyAsBool("VS_WINRT_EXTENSIONS"))
{
this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2);
}
+ else if (this->Target->GetType() <= cmTarget::MODULE_LIBRARY &&
+ this->ClOptions[*i]->UsingSBCS())
+ {
+ this->WriteString("<CharacterSet>NotSet</CharacterSet>\n", 2);
+ }
else
{
this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2);
@@ -416,12 +422,11 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
void cmVisualStudio10TargetGenerator::WriteCustomCommands()
{
this->SourcesVisited.clear();
- std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
- source != sources.end(); ++source)
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->CustomCommands.begin();
+ si != this->GeneratorTarget->CustomCommands.end(); ++si)
{
- cmSourceFile* sf = *source;
- this->WriteCustomCommand(sf);
+ this->WriteCustomCommand(*si);
}
}
@@ -629,6 +634,25 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->WriteGroupSources("Midl", idls, sourceGroups);
this->WriteGroupSources("CustomBuild", customBuild, sourceGroups);
+ // Add object library contents as external objects.
+ std::vector<std::string> objs;
+ this->GeneratorTarget->UseObjectLibraries(objs);
+ if(!objs.empty())
+ {
+ this->WriteString("<ItemGroup>\n", 1);
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
+ {
+ std::string obj = *oi;
+ this->WriteString("<Object Include=\"", 2);
+ this->ConvertToWindowsSlash(obj);
+ (*this->BuildFileStream ) << obj << "\">\n";
+ this->WriteString("<Filter>Object Libraries</Filter>\n", 3);
+ this->WriteString("</Object>\n", 2);
+ }
+ this->WriteString("</ItemGroup>\n", 1);
+ }
+
this->WriteString("<ItemGroup>\n", 1);
for(std::set<cmSourceGroup*>::iterator g = groupsUsed.begin();
g != groupsUsed.end(); ++g)
@@ -652,6 +676,18 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->WriteString("</Filter>\n", 2);
}
}
+ if(!objs.empty())
+ {
+ this->WriteString("<Filter Include=\"Object Libraries\">\n", 2);
+ std::string guidName = "SG_Filter_Object Libraries";
+ this->GlobalGenerator->CreateGUID(guidName.c_str());
+ this->WriteString("<UniqueIdentifier>", 3);
+ std::string guid =
+ this->GlobalGenerator->GetGUID(guidName.c_str());
+ (*this->BuildFileStream) << "{" << guid << "}"
+ << "</UniqueIdentifier>\n";
+ this->WriteString("</Filter>\n", 2);
+ }
this->WriteString("</ItemGroup>\n", 1);
this->WriteGroupSources("None", none, sourceGroups);
this->WriteString("</Project>\n", 0);
@@ -758,107 +794,56 @@ WriteGroupSources(const char* name,
this->WriteString("</ItemGroup>\n", 1);
}
-void cmVisualStudio10TargetGenerator::WriteObjSources()
-{
- if(this->Target->GetType() > cmTarget::MODULE_LIBRARY)
- {
- return;
- }
- bool first = true;
- std::vector<cmSourceFile*>const & sources = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
- source != sources.end(); ++source)
- {
- std::string ext =
- cmSystemTools::LowerCase((*source)->GetExtension());
- if(ext == "obj" || ext == "o")
- {
- if(first)
- {
- this->WriteString("<ItemGroup>\n", 1);
- first = false;
- }
- // If an object file is generated, then vs10
- // will use it in the build, and we have to list
- // it as None instead of Object
- if((*source)->GetPropertyAsBool("GENERATED"))
- {
- this->WriteString("<None Include=\"", 2);
- }
- // If it is not a generated object then we have
- // to use the Object type
- else
- {
- this->WriteString("<Object Include=\"", 2);
- }
- (*this->BuildFileStream ) << (*source)->GetFullPath() << "\" />\n";
- }
- }
- if(!first)
+void cmVisualStudio10TargetGenerator::WriteSource(
+ const char* tool, cmSourceFile* sf, bool end)
+{
+ std::string sourceFile = sf->GetFullPath();
+ // do not use a relative path here because it means that you
+ // can not use as long a path to the file.
+ this->ConvertToWindowsSlash(sourceFile);
+ this->WriteString("<", 2);
+ (*this->BuildFileStream ) << tool <<
+ " Include=\"" << sourceFile << (end? "\" />\n" : "\" ");
+}
+
+void cmVisualStudio10TargetGenerator::WriteSources(
+ const char* tool, std::vector<cmSourceFile*> const& sources)
+{
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = sources.begin(); si != sources.end(); ++si)
{
- this->WriteString("</ItemGroup>\n", 1);
+ this->WriteSource(tool, *si);
}
}
-
-void cmVisualStudio10TargetGenerator::WriteCLSources()
+void cmVisualStudio10TargetGenerator::WriteAllSources()
{
if(this->Target->GetType() > cmTarget::UTILITY)
{
return;
}
this->WriteString("<ItemGroup>\n", 1);
- std::vector<cmSourceFile*>const& sources = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
- source != sources.end(); ++source)
+
+ this->WriteSources("ClInclude", this->GeneratorTarget->HeaderSources);
+ this->WriteSources("Midl", this->GeneratorTarget->IDLSources);
+
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ObjectSources.begin();
+ si != this->GeneratorTarget->ObjectSources.end(); ++si)
{
- std::string ext = cmSystemTools::LowerCase((*source)->GetExtension());
- if((*source)->GetCustomCommand() || ext == "o" || ext == "obj")
- {
- continue;
- }
- // If it is not a custom command and it is not a pre-built obj file,
- // then add it as a source (c/c++/header/rc/idl) file
- bool header = (*source)->GetPropertyAsBool("HEADER_FILE_ONLY")
- || this->GlobalGenerator->IgnoreFile(ext.c_str());
- const char* lang = (*source)->GetLanguage();
- bool cl = lang && (strcmp(lang, "C") == 0 || strcmp(lang, "CXX") ==0);
- bool rc = lang && (strcmp(lang, "RC") == 0);
- bool idl = ext == "idl";
- std::string sourceFile = (*source)->GetFullPath();
- // do not use a relative path here because it means that you
- // can not use as long a path to the file.
- this->ConvertToWindowsSlash(sourceFile);
- // output the source file
- if(header)
- {
- this->WriteString("<ClInclude Include=\"", 2);
- }
- else if(cl)
- {
- this->WriteString("<ClCompile Include=\"", 2);
- }
- else if(rc)
- {
- this->WriteString("<ResourceCompile Include=\"", 2);
- }
- else if(idl)
- {
- this->WriteString("<Midl Include=\"", 2);
- }
- else
- {
- this->WriteString("<None Include=\"", 2);
- }
- (*this->BuildFileStream ) << sourceFile << "\"";
+ const char* lang = (*si)->GetLanguage();
+ bool cl = strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0;
+ bool rc = strcmp(lang, "RC") == 0;
+ const char* tool = cl? "ClCompile" : (rc? "ResourceCompile" : "None");
+ this->WriteSource(tool, *si, false);
// ouput any flags specific to this source file
- if(!header && cl && this->OutputSourceSpecificFlags(*source))
+ if(cl && this->OutputSourceSpecificFlags(*si))
{
// if the source file has specific flags the tag
// is ended on a new line
this->WriteString("</ClCompile>\n", 2);
}
- else if(!header && rc && this->OutputSourceSpecificFlags(*source))
+ else if(rc && this->OutputSourceSpecificFlags(*si))
{
this->WriteString("</ResourceCompile>\n", 2);
}
@@ -867,32 +852,32 @@ void cmVisualStudio10TargetGenerator::WriteCLSources()
(*this->BuildFileStream ) << " />\n";
}
}
- this->WriteString("</ItemGroup>\n", 1);
-}
-void cmVisualStudio10TargetGenerator::ComputeObjectNames()
-{
- // We may be modifying the source groups temporarily, so make a copy.
- std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
+ for(std::vector<cmSourceFile*>::const_iterator
+ si = this->GeneratorTarget->ExternalObjects.begin();
+ si != this->GeneratorTarget->ExternalObjects.end(); ++si)
+ {
+ // 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);
+ }
+
+ this->WriteSources("None", this->GeneratorTarget->ExtraSources);
- // get the classes from the source lists then add them to the groups
- std::vector<cmSourceFile*>const & classes = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); i++)
+ // Add object library contents as external objects.
+ std::vector<std::string> objs;
+ this->GeneratorTarget->UseObjectLibraries(objs);
+ for(std::vector<std::string>::const_iterator
+ oi = objs.begin(); oi != objs.end(); ++oi)
{
- // Add the file to the list of sources.
- std::string source = (*i)->GetFullPath();
- if(cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF")
- {
- this->ModuleDefinitionFile = (*i)->GetFullPath();
- }
- cmSourceGroup& sourceGroup =
- this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
- sourceGroup.AssignSource(*i);
+ std::string obj = *oi;
+ this->WriteString("<Object Include=\"", 2);
+ this->ConvertToWindowsSlash(obj);
+ (*this->BuildFileStream ) << obj << "\" />\n";
}
- // Compute which sources need unique object computation.
- this->LocalGenerator->ComputeObjectNameRequirements(sourceGroups);
+ this->WriteString("</ItemGroup>\n", 1);
}
bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
@@ -901,16 +886,11 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
cmSourceFile& sf = *source;
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
- // Compute the maximum length full path to the intermediate
- // files directory for any configuration. This is used to construct
- // object file names that do not produce paths that are too long.
- std::string dir_max;
- lg->ComputeMaxDirectoryLength(dir_max, *this->Target);
-
std::string objectName;
- if(lg->NeedObjectName.find(&sf) != lg->NeedObjectName.end())
+ if(this->GeneratorTarget->ExplicitObjectName.find(&sf)
+ != this->GeneratorTarget->ExplicitObjectName.end())
{
- objectName = lg->GetObjectFileNameWithoutTarget(sf, dir_max);
+ objectName = this->GeneratorTarget->Objects[&sf];
}
std::string flags;
std::string defines;
@@ -1031,20 +1011,29 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
}
else
{
- std::string targetNameFull =
- this->Target->GetFullName(config->c_str());
std::string intermediateDir = this->LocalGenerator->
GetTargetDirectory(*this->Target);
intermediateDir += "/";
intermediateDir += *config;
intermediateDir += "/";
+ std::string outDir;
+ std::string targetNameFull;
+ if(ttype == cmTarget::OBJECT_LIBRARY)
+ {
+ outDir = intermediateDir;
+ targetNameFull = this->Target->GetName();
+ targetNameFull += ".lib";
+ }
+ else
+ {
+ outDir = this->Target->GetDirectory(config->c_str()) + "/";
+ targetNameFull = this->Target->GetFullName(config->c_str());
+ }
this->ConvertToWindowsSlash(intermediateDir);
- std::string outDir = this->Target->GetDirectory(config->c_str());
this->ConvertToWindowsSlash(outDir);
this->WritePlatformConfigTag("OutDir", config->c_str(), 3);
*this->BuildFileStream << outDir
- << "\\"
<< "</OutDir>\n";
this->WritePlatformConfigTag("IntDir", config->c_str(), 3);
@@ -1278,11 +1267,15 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
*this->BuildFileStream << configName
<< "</AssemblerListingLocation>\n";
this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
- this->WriteString("<ProgramDataBaseFileName>", 3);
- *this->BuildFileStream << this->Target->GetDirectory(configName.c_str())
- << "/"
- << this->Target->GetPDBName(configName.c_str())
- << "</ProgramDataBaseFileName>\n";
+ if(this->Target->GetType() != cmTarget::OBJECT_LIBRARY)
+ {
+ // TODO: PDB for object library?
+ this->WriteString("<ProgramDataBaseFileName>", 3);
+ *this->BuildFileStream << this->Target->GetDirectory(configName.c_str())
+ << "/"
+ << this->Target->GetPDBName(configName.c_str())
+ << "</ProgramDataBaseFileName>\n";
+ }
this->WriteString("</ClCompile>\n", 2);
}
@@ -1514,10 +1507,10 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
linkOptions.AddFlag("ImportLibrary", imLib.c_str());
linkOptions.AddFlag("ProgramDataBaseFile", pdb.c_str());
linkOptions.Parse(flags.c_str());
- if(!this->ModuleDefinitionFile.empty())
+ if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
{
linkOptions.AddFlag("ModuleDefinitionFile",
- this->ModuleDefinitionFile.c_str());
+ this->GeneratorTarget->ModuleDefinitionFile.c_str());
}
linkOptions.RemoveFlag("GenerateManifest");
@@ -1586,14 +1579,14 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
static_cast<cmGlobalVisualStudio7Generator *>
(this->GlobalGenerator)->GetConfigurations();
std::vector<std::string> includes;
- this->LocalGenerator->GetIncludeDirectories(includes);
+ this->LocalGenerator->GetIncludeDirectories(includes, this->Target);
for(std::vector<std::string>::iterator i = configs->begin();
i != configs->end(); ++i)
{
this->WritePlatformConfigTag("ItemDefinitionGroup", i->c_str(), 1);
*this->BuildFileStream << "\n";
// output cl compile flags <ClCompile></ClCompile>
- if(this->Target->GetType() <= cmTarget::MODULE_LIBRARY)
+ if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY)
{
this->WriteClOptions(*i, includes);
// output rc compile flags <ResourceCompile></ResourceCompile>
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 90035f2..20a443b 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -15,6 +15,7 @@
class cmTarget;
class cmMakefile;
+class cmGeneratorTarget;
class cmGeneratedFileStream;
class cmGlobalVisualStudio10Generator;
class cmSourceFile;
@@ -46,10 +47,11 @@ private:
void WriteString(const char* line, int indentLevel);
void WriteProjectConfigurations();
void WriteProjectConfigurationValues();
- void WriteCLSources();
+ void WriteSource(const char* tool, cmSourceFile* sf, bool end = true);
+ void WriteSources(const char* tool, std::vector<cmSourceFile*> const&);
+ void WriteAllSources();
void WriteDotNetReferences();
void WriteWinRTReferences();
- void WriteObjSources();
void WritePathAndIncrementalLinkOptions();
void WriteItemDefinitionGroups();
bool ComputeClOptions();
@@ -75,7 +77,6 @@ private:
void WriteEvents(std::string const& configName);
void WriteEvent(const char* name, std::vector<cmCustomCommand> & commands,
std::string const& configName);
- void ComputeObjectNames();
void WriteGroupSources(const char* name,
std::vector<cmSourceFile*> const& sources,
std::vector<cmSourceGroup>& );
@@ -87,9 +88,9 @@ private:
typedef cmVisualStudioGeneratorOptions Options;
typedef std::map<cmStdString, Options*> OptionsMap;
OptionsMap ClOptions;
- std::string ModuleDefinitionFile;
std::string PathToVcxproj;
cmTarget* Target;
+ cmGeneratorTarget* GeneratorTarget;
cmMakefile* Makefile;
std::string Platform;
std::string GUID;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 41230e7..9369af6 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -117,6 +117,20 @@ bool cmVisualStudioGeneratorOptions::UsingUnicode()
}
return false;
}
+//----------------------------------------------------------------------------
+bool cmVisualStudioGeneratorOptions::UsingSBCS()
+{
+ // Look for the a _SBCS definition.
+ for(std::vector<std::string>::const_iterator di = this->Defines.begin();
+ di != this->Defines.end(); ++di)
+ {
+ if(*di == "_SBCS")
+ {
+ return true;
+ }
+ }
+ return false;
+}
//----------------------------------------------------------------------------
void cmVisualStudioGeneratorOptions::Parse(const char* flags)
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index 51a1362..a1a55da 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -48,6 +48,7 @@ public:
// Check for specific options.
bool UsingUnicode();
+ bool UsingSBCS();
bool IsDebug();
// Write options to output.
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 0b7a996..846aef5 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -84,6 +84,10 @@
#endif
#include "cmGlobalUnixMakefileGenerator3.h"
+#ifdef CMAKE_USE_NINJA
+# include "cmGlobalNinjaGenerator.h"
+#endif
+
#if defined(CMAKE_HAVE_VS_GENERATORS)
#include "cmCallVisualStudioMacro.h"
#endif
@@ -598,14 +602,10 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
std::string includes = mf->GetSafeDefinition("PACKAGE_INCLUDE_DIRS");
std::vector<std::string> includeDirs;
cmSystemTools::ExpandListArgument(includes, includeDirs);
- for(std::vector<std::string>::const_iterator dirIt=includeDirs.begin();
- dirIt != includeDirs.end();
- ++dirIt)
- {
- mf->AddIncludeDirectory(dirIt->c_str(), false);
- }
- std::string includeFlags = lg->GetIncludeFlags(language.c_str(), false);
+ std::string includeFlags = lg->GetIncludeFlags(includeDirs,
+ language.c_str(), false);
+
std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS");
printf("%s %s\n", includeFlags.c_str(), definitions.c_str());
}
@@ -2597,6 +2597,10 @@ void cmake::AddDefaultGenerators()
#endif
this->Generators[cmGlobalUnixMakefileGenerator3::GetActualName()] =
&cmGlobalUnixMakefileGenerator3::New;
+#ifdef CMAKE_USE_NINJA
+ this->Generators[cmGlobalNinjaGenerator::GetActualName()] =
+ &cmGlobalNinjaGenerator::New;
+#endif
#ifdef CMAKE_USE_XCODE
this->Generators[cmGlobalXCodeGenerator::GetActualName()] =
&cmGlobalXCodeGenerator::New;
diff --git a/Source/cmake.h b/Source/cmake.h
index 161e656..94c6f12 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -102,8 +102,8 @@ class cmake
//@{
/**
* Set/Get the home directory (or output directory) in the project. The
- * home directory is the top directory of the project. It is where
- * cmake was run. Remember that CMake processes
+ * home directory is the top directory of the project. It is the
+ * path-to-source cmake was run with. Remember that CMake processes
* CMakeLists files by recursing up the tree starting at the StartDirectory
* and going up until it reaches the HomeDirectory.
*/
@@ -294,7 +294,7 @@ class cmake
void SetWorkingMode(WorkingMode mode) { this->CurrentWorkingMode = mode; }
WorkingMode GetWorkingMode() { return this->CurrentWorkingMode; }
- ///! Debug the try compile stuff by not delelting the files
+ ///! Debug the try compile stuff by not deleting the files
bool GetDebugTryCompile(){return this->DebugTryCompile;}
void DebugTryCompileOn(){this->DebugTryCompile = true;}
@@ -372,7 +372,7 @@ class cmake
/** Display a message to the user. */
void IssueMessage(cmake::MessageType t, std::string const& text,
cmListFileBacktrace const& backtrace);
- // * run the --build option
+ ///! run the --build option
int Build(const std::string& dir,
const std::string& target,
const std::string& config,
@@ -436,7 +436,7 @@ protected:
void SetDirectoriesFromFile(const char* arg);
//! Make sure all commands are what they say they are and there is no
- //macros.
+ /// macros.
void CleanupCommandsAndMacros();
void GenerateGraphViz(const char* fileName) const;
diff --git a/Source/kwsys/kwsysDateStamp.cmake b/Source/kwsys/kwsysDateStamp.cmake
index e424fec..3d0f03d 100644
--- a/Source/kwsys/kwsysDateStamp.cmake
+++ b/Source/kwsys/kwsysDateStamp.cmake
@@ -15,7 +15,7 @@
SET(KWSYS_DATE_STAMP_YEAR 2012)
# KWSys version date month component. Format is MM.
-SET(KWSYS_DATE_STAMP_MONTH 03)
+SET(KWSYS_DATE_STAMP_MONTH 04)
# KWSys version date day component. Format is DD.
-SET(KWSYS_DATE_STAMP_DAY 03)
+SET(KWSYS_DATE_STAMP_DAY 20)
diff --git a/Tests/BuildDepends/CMakeLists.txt b/Tests/BuildDepends/CMakeLists.txt
index 31392b5..aa32d67 100644
--- a/Tests/BuildDepends/CMakeLists.txt
+++ b/Tests/BuildDepends/CMakeLists.txt
@@ -40,6 +40,8 @@ if("${CMAKE_GENERATOR}" MATCHES "Make")
endif()
list(APPEND _cmake_options "-DTEST_LINK_DEPENDS=${TEST_LINK_DEPENDS}")
+list(APPEND _cmake_options "-DCMAKE_FORCE_DEPFILES=1")
+
file(MAKE_DIRECTORY ${BuildDepends_BINARY_DIR}/Project)
message("Creating Project/foo.cxx")
write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx
diff --git a/Tests/CMakeCommands/CMakeLists.txt b/Tests/CMakeCommands/CMakeLists.txt
deleted file mode 100644
index aa400d0..0000000
--- a/Tests/CMakeCommands/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-macro(add_CMakeCommands_test test)
- add_test(CMakeCommands.${test} ${CMAKE_CMAKE_COMMAND}
- -DCMake_SOURCE_DIR=${CMake_SOURCE_DIR} # TODO: Remove
- -Ddir=${CMAKE_CURRENT_BINARY_DIR}/${test}
- -Dgen=${CMAKE_TEST_GENERATOR}
- -P "${CMAKE_CURRENT_SOURCE_DIR}/${test}/test.cmake"
- )
-endmacro()
-
-add_CMakeCommands_test(build_command)
-add_CMakeCommands_test(find_package)
diff --git a/Tests/CMakeCommands/build_command/test.cmake b/Tests/CMakeCommands/build_command/test.cmake
deleted file mode 100644
index 55d9359..0000000
--- a/Tests/CMakeCommands/build_command/test.cmake
+++ /dev/null
@@ -1,86 +0,0 @@
-if(NOT DEFINED CMake_SOURCE_DIR)
- message(FATAL_ERROR "CMake_SOURCE_DIR not defined")
-endif()
-
-if(NOT DEFINED dir)
- message(FATAL_ERROR "dir not defined")
-endif()
-
-if(NOT DEFINED gen)
- message(FATAL_ERROR "gen not defined")
-endif()
-
-message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
-
-# Run cmake:
-#
-function(run_cmake build_dir extra_args expected_result expected_output expected_error)
- message(STATUS "run_cmake build_dir='${build_dir}' extra_args='${extra_args}'")
-
- # Ensure build_dir exists:
- #
- execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${build_dir})
-
- # Run cmake:
- #
- execute_process(COMMAND ${CMAKE_COMMAND}
- ${extra_args}
- -G ${gen} ${CMake_SOURCE_DIR}/Tests/CMakeCommands/build_command
- RESULT_VARIABLE result
- OUTPUT_VARIABLE stdout
- ERROR_VARIABLE stderr
- WORKING_DIRECTORY ${build_dir}
- )
-
- message(STATUS "result='${result}'")
- message(STATUS "stdout='${stdout}'")
- message(STATUS "stderr='${stderr}'")
- message(STATUS "")
-
- # Verify result and output match expectations:
- #
- if("0" STREQUAL "${expected_result}")
- if(NOT "${result}" STREQUAL "0")
- message(FATAL_ERROR
- "error: result='${result}' is non-zero and different than expected_result='${expected_result}'")
- endif()
- else()
- if("${result}" STREQUAL "0")
- message(FATAL_ERROR
- "error: result='${result}' is zero and different than expected_result='${expected_result}'")
- endif()
- endif()
-
- foreach(e ${expected_output})
- if(NOT stdout MATCHES "${e}")
- message(FATAL_ERROR
- "error: stdout does not match expected_output item e='${e}'")
- else()
- message(STATUS "info: stdout matches '${e}'")
- endif()
- endforeach()
-
- foreach(e ${expected_error})
- if(NOT stderr MATCHES "${e}")
- message(FATAL_ERROR
- "error: stderr does not match expected_error item e='${e}'")
- else()
- message(STATUS "info: stderr matches '${e}'")
- endif()
- endforeach()
-
- message(STATUS "result, stdout and stderr match all expectations: test passes")
- message(STATUS "")
-endfunction()
-
-
-# Expect this case to succeed:
-run_cmake("${dir}/b1" "" 0
- "Build files have been written to:"
- "skipping cases 1, 2 and 3 because TEST_ERROR_CONDITIONS is OFF")
-
-
-# Expect this one to fail:
-run_cmake("${dir}/b2" "-DTEST_ERROR_CONDITIONS:BOOL=ON" 1
- "Configuring incomplete, errors occurred!"
- "build_command requires at least one argument naming a CMake variable;build_command unknown argument ")
diff --git a/Tests/CMakeCommands/find_package/CMakeLists.txt b/Tests/CMakeCommands/find_package/CMakeLists.txt
deleted file mode 100644
index c2deed0..0000000
--- a/Tests/CMakeCommands/find_package/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-cmake_minimum_required(VERSION 2.8)
-project(${TEST} NONE)
-include(${TEST}.cmake)
diff --git a/Tests/CMakeCommands/find_package/MissingConfig.cmake b/Tests/CMakeCommands/find_package/MissingConfig.cmake
deleted file mode 100644
index 3cebef1..0000000
--- a/Tests/CMakeCommands/find_package/MissingConfig.cmake
+++ /dev/null
@@ -1 +0,0 @@
-find_package(NotHere CONFIG)
diff --git a/Tests/CMakeCommands/find_package/MissingConfigRequired.cmake b/Tests/CMakeCommands/find_package/MissingConfigRequired.cmake
deleted file mode 100644
index 3c28552..0000000
--- a/Tests/CMakeCommands/find_package/MissingConfigRequired.cmake
+++ /dev/null
@@ -1 +0,0 @@
-find_package(NotHere CONFIG REQUIRED)
diff --git a/Tests/CMakeCommands/find_package/MissingModule.cmake b/Tests/CMakeCommands/find_package/MissingModule.cmake
deleted file mode 100644
index 420539f..0000000
--- a/Tests/CMakeCommands/find_package/MissingModule.cmake
+++ /dev/null
@@ -1 +0,0 @@
-find_package(NotHere MODULE)
diff --git a/Tests/CMakeCommands/find_package/MissingModuleRequired.cmake b/Tests/CMakeCommands/find_package/MissingModuleRequired.cmake
deleted file mode 100644
index 07f36c5..0000000
--- a/Tests/CMakeCommands/find_package/MissingModuleRequired.cmake
+++ /dev/null
@@ -1 +0,0 @@
-find_package(NotHere MODULE REQUIRED)
diff --git a/Tests/CMakeCommands/find_package/MissingNormal.cmake b/Tests/CMakeCommands/find_package/MissingNormal.cmake
deleted file mode 100644
index 778cd38..0000000
--- a/Tests/CMakeCommands/find_package/MissingNormal.cmake
+++ /dev/null
@@ -1 +0,0 @@
-find_package(NotHere)
diff --git a/Tests/CMakeCommands/find_package/MissingNormalRequired.cmake b/Tests/CMakeCommands/find_package/MissingNormalRequired.cmake
deleted file mode 100644
index 5c33fca..0000000
--- a/Tests/CMakeCommands/find_package/MissingNormalRequired.cmake
+++ /dev/null
@@ -1 +0,0 @@
-find_package(NotHere REQUIRED)
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 00cac94..c0b7cd6 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -53,7 +53,7 @@ IF(BUILD_TESTING)
ADD_SUBDIRECTORY(CMakeLib)
ADD_SUBDIRECTORY(CMakeOnly)
- ADD_SUBDIRECTORY(CMakeCommands)
+ ADD_SUBDIRECTORY(RunCMake)
ADD_SUBDIRECTORY(FindPackageModeMakefileTest)
@@ -199,6 +199,7 @@ IF(BUILD_TESTING)
ADD_TEST_MACRO(CxxOnly CxxOnly)
ADD_TEST_MACRO(IPO COnly/COnly)
ADD_TEST_MACRO(OutDir runtime/OutDir)
+ ADD_TEST_MACRO(ObjectLibrary UseCshared)
ADD_TEST_MACRO(NewlineArgs NewlineArgs)
ADD_TEST_MACRO(SetLang SetLang)
ADD_TEST_MACRO(ExternalOBJ ExternalOBJ)
@@ -233,12 +234,35 @@ IF(BUILD_TESTING)
LIST(APPEND TEST_BUILD_DIRS ${CMake_TEST_INSTALL_PREFIX})
+ IF(NOT QT4_FOUND)
+ FIND_PACKAGE(Qt4)
+ ENDIF(NOT QT4_FOUND)
+
+ IF(QT4_FOUND)
+ # test whether the Qt4 which has been found works, on some machines
+ # which run nightly builds there were errors like "wrong file format"
+ # for libQtCore.so. So first check it works, and only if it does add
+ # the automoc test.
+ INCLUDE(CheckCXXSourceCompiles)
+ SET(_save_CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES}")
+ SET(_save_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
+
+ SET(CMAKE_REQUIRED_INCLUDES ${QT_INCLUDES})
+ SET(CMAKE_REQUIRED_LIBRARIES ${QT_QTCORE_LIBRARIES})
+
+ CHECK_CXX_SOURCE_COMPILES("#include <QCoreApplication>\n int main() {return (qApp == 0 ? 0 : 1); }\n"
+ QT4_WORKS)
+
+ SET(CMAKE_REQUIRED_INCLUDES "${_save_CMAKE_REQUIRED_INCLUDES}")
+ SET(CMAKE_REQUIRED_LIBRARIES "${_save_CMAKE_REQUIRED_LIBRARIES}")
+ ENDIF()
# run test for BundleUtilities on supported platforms/compilers
if(MSVC OR
CMAKE_SYSTEM_NAME MATCHES "Linux" OR
CMAKE_SYSTEM_NAME MATCHES "Darwin")
if(NOT "${CMAKE_TEST_GENERATOR}" STREQUAL "Watcom WMake")
+
ADD_TEST(BundleUtilities ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/BundleUtilities"
@@ -248,6 +272,24 @@ IF(BUILD_TESTING)
--build-project BundleUtilities
)
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BundleUtilities")
+
+ # run test for DeployQt4 on supported platforms/compilers (which depends on BundleUtilities)
+ # this test also depends on the existence of the standard qtiff plugin
+ if(QT4_WORKS AND QT_QTSQL_FOUND)
+ ADD_TEST(Qt4Deploy ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Qt4Deploy"
+ "${CMake_BINARY_DIR}/Tests/Qt4Deploy"
+ --build-generator ${CMAKE_TEST_GENERATOR}
+ --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
+ --build-project Qt4Deploy
+ --build-options
+ -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
+ -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
+ )
+ LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Qt4Deploy")
+ endif()
+
endif()
endif()
@@ -366,6 +408,15 @@ IF(BUILD_TESTING)
--build-target car
--test-command car
)
+
+ IF(${CMAKE_TEST_GENERATOR} MATCHES "Ninja")
+ # The Ninja generator does not create a recursive build system. Start
+ # from the root directory.
+ SET(SubProject_SUBDIR)
+ ELSE()
+ SET(SubProject_SUBDIR "/foo")
+ ENDIF()
+
# For stage 2, do not run cmake again.
# Then build the foo sub project which should build
# the bar library which should be referenced because
@@ -373,13 +424,14 @@ IF(BUILD_TESTING)
# directly in the foo sub project
ADD_TEST(SubProject-Stage2 ${CMAKE_CTEST_COMMAND}
--build-and-test
- "${CMake_SOURCE_DIR}/Tests/SubProject/foo"
- "${CMake_BINARY_DIR}/Tests/SubProject/foo"
+ "${CMake_SOURCE_DIR}/Tests/SubProject${SubProject_SUBDIR}"
+ "${CMake_BINARY_DIR}/Tests/SubProject${SubProject_SUBDIR}"
--build-generator ${CMAKE_TEST_GENERATOR}
--build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
--build-nocmake
--build-project foo
--build-target foo
+ --build-exe-dir "${CMake_BINARY_DIR}/Tests/SubProject/foo"
--test-command foo
)
SET_TESTS_PROPERTIES ( SubProject-Stage2 PROPERTIES DEPENDS SubProject)
@@ -861,43 +913,20 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
)
LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Environment")
- IF(NOT QT4_FOUND)
- FIND_PACKAGE(Qt4)
- ENDIF(NOT QT4_FOUND)
-
- IF(QT4_FOUND)
- # test whether the Qt4 which has been found works, on some machines
- # which run nightly builds there were errors like "wrong file format"
- # for libQtCore.so. So first check it works, and only if it does add
- # the automoc test.
- INCLUDE(CheckCXXSourceCompiles)
- SET(_save_CMAKE_REQUIRED_INCLUDES "${CMAKE_REQUIRED_INCLUDES}")
- SET(_save_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
-
- SET(CMAKE_REQUIRED_INCLUDES ${QT_INCLUDES})
- SET(CMAKE_REQUIRED_LIBRARIES ${QT_QTCORE_LIBRARIES})
-
- CHECK_CXX_SOURCE_COMPILES("#include <QCoreApplication>\n int main() {return (qApp == 0 ? 0 : 1); }\n"
- QT4_WORKS_FOR_AUTOMOC_TEST)
-
- SET(CMAKE_REQUIRED_INCLUDES "${_save_CMAKE_REQUIRED_INCLUDES}")
- SET(CMAKE_REQUIRED_LIBRARIES "${_save_CMAKE_REQUIRED_LIBRARIES}")
-
- IF(QT4_WORKS_FOR_AUTOMOC_TEST)
- ADD_TEST(QtAutomoc ${CMAKE_CTEST_COMMAND}
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/QtAutomoc"
- "${CMake_BINARY_DIR}/Tests/QtAutomoc"
- --build-generator ${CMAKE_TEST_GENERATOR}
- --build-project QtAutomoc
- --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
- --build-exe-dir "${CMake_BINARY_DIR}/Tests/QtAutomoc"
- --force-new-ctest-process
- --build-options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
- --test-command ${CMAKE_CTEST_COMMAND} -V
- )
- LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomoc")
- ENDIF()
+ IF(QT4_WORKS AND QT_QTGUI_FOUND)
+ ADD_TEST(QtAutomoc ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/QtAutomoc"
+ "${CMake_BINARY_DIR}/Tests/QtAutomoc"
+ --build-generator ${CMAKE_TEST_GENERATOR}
+ --build-project QtAutomoc
+ --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
+ --build-exe-dir "${CMake_BINARY_DIR}/Tests/QtAutomoc"
+ --force-new-ctest-process
+ --build-options -DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}
+ --test-command ${CMAKE_CTEST_COMMAND} -V
+ )
+ LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/QtAutomoc")
ENDIF()
ADD_TEST(ExternalProject ${CMAKE_CTEST_COMMAND}
@@ -1320,6 +1349,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
endif()
IF(${CMAKE_TEST_GENERATOR} MATCHES "Visual Studio")
+ IF(NOT MSVC60)
+ ADD_TEST_MACRO(SBCS SBCS)
+ ENDIF(NOT MSVC60)
+
ADD_TEST(VSExternalInclude ${CMAKE_CTEST_COMMAND}
--build-and-test
"${CMake_SOURCE_DIR}/Tests/VSExternalInclude"
diff --git a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
index e6e4c74..6604208 100644
--- a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
+++ b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
@@ -48,11 +48,21 @@ endif (NOT QT4_FOUND)
macro(check_version_string MODULE_NAME VERSION_VAR)
if (${MODULE_NAME}_FOUND)
if (DEFINED ${VERSION_VAR})
- if (NOT ${VERSION_VAR} MATCHES "^[0-9][0-9\\.]*[-A-Za-z_\\+]*[0-9\\.]*$")
- message(SEND_ERROR "${VERSION_VAR} has unexpected content ${${VERSION_VAR}}")
+ message(STATUS "${VERSION_VAR}='${${VERSION_VAR}}'")
+ if (NOT ${VERSION_VAR} MATCHES "^[0-9]")
+ message(SEND_ERROR "unexpected: ${VERSION_VAR} does not begin with a decimal digit")
+ endif()
+ if ("${${VERSION_VAR}}" STREQUAL "")
+ message(SEND_ERROR "unexpected: ${VERSION_VAR} is empty")
+ endif()
+ if (${VERSION_VAR} VERSION_EQUAL 0)
+ message(SEND_ERROR "unexpected: ${VERSION_VAR} is VERSION_EQUAL 0")
+ endif()
+ if (NOT ${VERSION_VAR} VERSION_GREATER 0)
+ message(SEND_ERROR "unexpected: ${VERSION_VAR} is NOT VERSION_GREATER 0")
endif()
else()
- message(SEND_ERROR "${MODULE_NAME}_FOUND is set but no version number is defined")
+ message(SEND_ERROR "${MODULE_NAME}_FOUND is set but version number variable ${VERSION_VAR} is NOT DEFINED")
endif()
endif ()
endmacro(check_version_string)
@@ -61,7 +71,7 @@ endmacro(check_version_string)
# reported.
foreach(VTEST ALSA ARMADILLO BZIP2 CUPS CURL EXPAT FREETYPE GETTEXT GIT HSPELL
- JASPER LIBXML2 LIBXSLT PERL PostgreSQL TCLSH TIFF ZLIB)
+ JASPER LIBXML2 LIBXSLT PERL PostgreSQL TIFF ZLIB)
check_version_string(${VTEST} ${VTEST}_VERSION_STRING)
endforeach(VTEST)
diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt
index aa4d52e..c42c490 100644
--- a/Tests/CMakeTests/CMakeLists.txt
+++ b/Tests/CMakeTests/CMakeLists.txt
@@ -22,6 +22,7 @@ AddCMakeTest(ConfigureFile "")
AddCMakeTest(SeparateArguments "")
AddCMakeTest(ImplicitLinkInfo "")
AddCMakeTest(ModuleNotices "")
+AddCMakeTest(GetProperty "")
AddCMakeTest(If "")
AddCMakeTest(String "")
AddCMakeTest(Math "")
@@ -56,14 +57,13 @@ AddCMakeTest(GetPrerequisites "${GetPrerequisites_PreArgs}")
# suite. It detects if any changes have been made to the CMake source tree
# by any previous configure, build or test steps.
#
-if(do_cvs_tests OR GIT_EXECUTABLE)
+if(GIT_EXECUTABLE)
string(REPLACE "\\" "/" ENV_HOME "$ENV{HOME}")
set(CheckSourceTree_PreArgs
"-DCMake_BINARY_DIR:PATH=${CMake_BINARY_DIR}"
"-DCMake_SOURCE_DIR:PATH=${CMake_SOURCE_DIR}"
- "-DCVS_EXECUTABLE:STRING=${CVS_EXECUTABLE}"
"-DGIT_EXECUTABLE:STRING=${GIT_EXECUTABLE}"
"-DHOME:STRING=${ENV_HOME}"
)
AddCMakeTest(CheckSourceTree "${CheckSourceTree_PreArgs}")
-endif(do_cvs_tests OR GIT_EXECUTABLE)
+endif()
diff --git a/Tests/CMakeTests/CheckSourceTreeTest.cmake.in b/Tests/CMakeTests/CheckSourceTreeTest.cmake.in
index 73f8b01..59b2890 100644
--- a/Tests/CMakeTests/CheckSourceTreeTest.cmake.in
+++ b/Tests/CMakeTests/CheckSourceTreeTest.cmake.in
@@ -5,7 +5,6 @@ message("CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
message("")
message("CMake_BINARY_DIR='${CMake_BINARY_DIR}'")
message("CMake_SOURCE_DIR='${CMake_SOURCE_DIR}'")
-message("CVS_EXECUTABLE='${CVS_EXECUTABLE}'")
message("GIT_EXECUTABLE='${GIT_EXECUTABLE}'")
message("HOME='${HOME}'")
message("ENV{DASHBOARD_TEST_FROM_CTEST}='$ENV{DASHBOARD_TEST_FROM_CTEST}'")
@@ -43,7 +42,7 @@ message("in_source_build='${in_source_build}'")
message("")
-# If this does not appear to be a git or CVS checkout, just pass the test here
+# If this does not appear to be a git checkout, just pass the test here
# and now. (Do not let the test fail if it is run in a tree *exported* from a
# repository or unpacked from a .zip file source installer...)
#
@@ -52,29 +51,13 @@ if(EXISTS "${CMake_SOURCE_DIR}/.git")
set(is_git_checkout 1)
endif()
-set(is_cvs_checkout 0)
-if(EXISTS "${CMake_SOURCE_DIR}/CVS/Root")
- set(is_cvs_checkout 1)
-endif()
-
message("is_git_checkout='${is_git_checkout}'")
-message("is_cvs_checkout='${is_cvs_checkout}'")
message("")
-if(NOT is_cvs_checkout)
if(NOT is_git_checkout)
- message("source tree is neither git nor CVS checkout... test passes by early return...")
+ message("source tree is not a git checkout... test passes by early return...")
return()
endif()
-endif()
-
-if(is_cvs_checkout)
-if(is_git_checkout)
- message("warning: source tree has both git *and* CVS file system bits???")
- # should this condition be a FATAL_ERROR test failure...?
-endif()
-endif()
-
# This test looks for the following types of changes in the source tree:
#
@@ -83,51 +66,13 @@ set(conflicts 0)
set(modifications 0)
set(nonadditions 0)
-# ov == output variable... conditionally filled in by either cvs or git below:
+# ov == output variable... conditionally filled in by either git below:
#
set(cmd "")
set(ov "")
set(ev "")
set(rv "")
-
-if(is_cvs_checkout AND CVS_EXECUTABLE)
- # Check with "cvs -q -n up -dP" if there are any local modifications to the
- # CMake source tree:
- #
- message("=============================================================================")
- message("This is a cvs checkout, using cvs to verify source tree....")
- message("")
-
- execute_process(COMMAND ${CVS_EXECUTABLE} --version
- WORKING_DIRECTORY ${CMake_SOURCE_DIR}
- OUTPUT_VARIABLE version_output
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- message("=== output of 'cvs --version' ===")
- message("${version_output}")
- message("=== end output ===")
- message("")
-
- file(READ "${CMake_SOURCE_DIR}/CVS/Root" contents)
- message("=== content of CVS/Root ===")
- message("${contents}")
- message("=== end content ===")
- message("")
-
- file(READ "${CMake_SOURCE_DIR}/CVS/Repository" contents)
- message("=== content of CVS/Repository ===")
- message("${contents}")
- message("=== end content ===")
- message("")
-
- message("Copy/paste this command to reproduce:")
- message("cd \"${CMake_SOURCE_DIR}\" && \"${CVS_EXECUTABLE}\" -q -n up -dP")
- message("")
-
- set(cmd ${CVS_EXECUTABLE} -q -n up -dP)
-endif()
-
-
# If no GIT_EXECUTABLE, see if we can figure out which git was used
# for the ctest_update step on this dashboard...
#
@@ -268,8 +213,8 @@ endif()
if(cmd)
- # Use the HOME value passed in to the script for calling cvs/git so it can
- # find its .cvspass or user/global config settings...
+ # Use the HOME value passed in to the script for calling git so it can
+ # find its user/global config settings...
#
set(original_ENV_HOME "$ENV{HOME}")
set(ENV{HOME} "${HOME}")
@@ -322,28 +267,6 @@ if(NOT ov STREQUAL "")
endif()
if(consider)
- if(is_cvs_checkout)
- if(line MATCHES "^A ")
- message(" locally added file/directory detected...")
- set(additions 1)
- endif()
-
- if(line MATCHES "^C ")
- message(" conflict detected...")
- set(conflicts 1)
- endif()
-
- if(line MATCHES "^M ")
- message(" locally modified file detected...")
- set(modifications 1)
- endif()
-
- if(line MATCHES "^\\? ")
- message(" locally non-added file/directory detected...")
- set(nonadditions 1)
- endif()
- endif()
-
if(is_git_checkout)
if(line MATCHES "^#[ \t]*modified:")
message(" locally modified file detected...")
diff --git a/Tests/CMakeTests/GetProperty-Bad-Argument.cmake b/Tests/CMakeTests/GetProperty-Bad-Argument.cmake
new file mode 100644
index 0000000..382dabb
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-Bad-Argument.cmake
@@ -0,0 +1 @@
+get_property(FOO GLOBAL PROPERTY FOO FOO)
diff --git a/Tests/CMakeTests/GetProperty-Bad-Directory.cmake b/Tests/CMakeTests/GetProperty-Bad-Directory.cmake
new file mode 100644
index 0000000..cdbfa80
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-Bad-Directory.cmake
@@ -0,0 +1 @@
+get_property(FOO DIRECTORY NonExistentSubDir PROPERTY FOO)
diff --git a/Tests/CMakeTests/GetProperty-Bad-Scope.cmake b/Tests/CMakeTests/GetProperty-Bad-Scope.cmake
new file mode 100644
index 0000000..ea8566b
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-Bad-Scope.cmake
@@ -0,0 +1 @@
+get_property(FOO FOO FOO)
diff --git a/Tests/CMakeTests/GetProperty-Bad-Target.cmake b/Tests/CMakeTests/GetProperty-Bad-Target.cmake
new file mode 100644
index 0000000..9992dab
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-Bad-Target.cmake
@@ -0,0 +1 @@
+get_property(FOO TARGET FOO PROPERTY FOO)
diff --git a/Tests/CMakeTests/GetProperty-Bad-Test.cmake b/Tests/CMakeTests/GetProperty-Bad-Test.cmake
new file mode 100644
index 0000000..44bf3eb
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-Bad-Test.cmake
@@ -0,0 +1 @@
+get_property(FOO TEST FOO PROPERTY FOO)
diff --git a/Tests/CMakeTests/GetProperty-Doc-Properties.cmake b/Tests/CMakeTests/GetProperty-Doc-Properties.cmake
new file mode 100644
index 0000000..6c2c362
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-Doc-Properties.cmake
@@ -0,0 +1,10 @@
+get_property(FOO_BRIEF GLOBAL PROPERTY FOO BRIEF_DOCS)
+get_property(FOO_FULL GLOBAL PROPERTY FOO FULL_DOCS)
+
+if (NOT FOO_BRIEF STREQUAL "NOTFOUND")
+ message(SEND_ERROR "property FOO has BRIEF_DOCS set to '${FOO_BRIEF}'")
+endif ()
+
+if (NOT FOO_FULL STREQUAL "NOTFOUND")
+ message(SEND_ERROR "property FOO has FULL_DOCS set to '${FOO_FULL}'")
+endif ()
diff --git a/Tests/CMakeTests/GetProperty-Global-Name.cmake b/Tests/CMakeTests/GetProperty-Global-Name.cmake
new file mode 100644
index 0000000..497700c
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-Global-Name.cmake
@@ -0,0 +1 @@
+get_property(FOO GLOBAL FOO PROPERTY FOO)
diff --git a/Tests/CMakeTests/GetProperty-Missing-Argument.cmake b/Tests/CMakeTests/GetProperty-Missing-Argument.cmake
new file mode 100644
index 0000000..f0d004d
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-Missing-Argument.cmake
@@ -0,0 +1 @@
+get_property()
diff --git a/Tests/CMakeTests/GetProperty-No-Cache.cmake b/Tests/CMakeTests/GetProperty-No-Cache.cmake
new file mode 100644
index 0000000..9719fe7
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-No-Cache.cmake
@@ -0,0 +1 @@
+get_property(FOO CACHE PROPERTY FOO)
diff --git a/Tests/CMakeTests/GetProperty-No-Property.cmake b/Tests/CMakeTests/GetProperty-No-Property.cmake
new file mode 100644
index 0000000..bee230d
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-No-Property.cmake
@@ -0,0 +1 @@
+get_property(FOO GLOBAL PROPERTY)
diff --git a/Tests/CMakeTests/GetProperty-No-Source.cmake b/Tests/CMakeTests/GetProperty-No-Source.cmake
new file mode 100644
index 0000000..89773c8
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-No-Source.cmake
@@ -0,0 +1 @@
+get_property(FOO SOURCE PROPERTY FOO)
diff --git a/Tests/CMakeTests/GetProperty-No-Target.cmake b/Tests/CMakeTests/GetProperty-No-Target.cmake
new file mode 100644
index 0000000..8f1fa23
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-No-Target.cmake
@@ -0,0 +1 @@
+get_property(FOO TARGET PROPERTY FOO)
diff --git a/Tests/CMakeTests/GetProperty-No-Test.cmake b/Tests/CMakeTests/GetProperty-No-Test.cmake
new file mode 100644
index 0000000..045bd56
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-No-Test.cmake
@@ -0,0 +1 @@
+get_property(FOO TEST PROPERTY FOO)
diff --git a/Tests/CMakeTests/GetProperty-Variable-Name.cmake b/Tests/CMakeTests/GetProperty-Variable-Name.cmake
new file mode 100644
index 0000000..9190f80
--- /dev/null
+++ b/Tests/CMakeTests/GetProperty-Variable-Name.cmake
@@ -0,0 +1 @@
+get_property(FOO VARIABLE FOO PROPERTY FOO)
diff --git a/Tests/CMakeTests/GetPropertyTest.cmake.in b/Tests/CMakeTests/GetPropertyTest.cmake.in
new file mode 100644
index 0000000..ab96e5b
--- /dev/null
+++ b/Tests/CMakeTests/GetPropertyTest.cmake.in
@@ -0,0 +1,98 @@
+include("@CMAKE_CURRENT_SOURCE_DIR@/CheckCMakeTest.cmake")
+
+set(Missing-Argument-RESULT 1)
+set(Missing-Argument-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-Missing-Argument.cmake:1 \\(get_property\\):.*get_property called with incorrect number of arguments.*")
+
+check_cmake_test(GetProperty
+ Missing-Argument
+)
+
+set(Bad-Scope-RESULT 1)
+set(Bad-Scope-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-Bad-Scope.cmake:1 \\(get_property\\):.*get_property given invalid scope FOO\\..*")
+
+check_cmake_test(GetProperty
+ Bad-Scope
+)
+
+set(Bad-Argument-RESULT 1)
+set(Bad-Argument-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-Bad-Argument.cmake:1 \\(get_property\\):.*get_property given invalid argument \"FOO\"\\..*")
+
+check_cmake_test(GetProperty
+ Bad-Argument
+)
+
+set(No-Property-RESULT 1)
+set(No-Property-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-No-Property.cmake:1 \\(get_property\\):.*get_property not given a PROPERTY <name> argument\\..*")
+
+check_cmake_test(GetProperty
+ No-Property
+)
+
+set(Doc-Properties-RESULT 0)
+
+check_cmake_test(GetProperty
+ Doc-Properties
+)
+
+set(Global-Name-RESULT 1)
+set(Global-Name-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-Global-Name.cmake:1 \\(get_property\\):.*get_property given name for GLOBAL scope\\..*")
+
+check_cmake_test(GetProperty
+ Global-Name
+)
+
+set(Bad-Directory-RESULT 1)
+set(Bad-Directory-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-Bad-Directory.cmake:1 \\(get_property\\):.*get_property DIRECTORY scope provided but requested directory was not.*found\\..*")
+
+check_cmake_test(GetProperty
+ Bad-Directory
+)
+
+set(No-Target-RESULT 1)
+set(No-Target-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-No-Target.cmake:1 \\(get_property\\):.*get_property not given name for TARGET scope\\..*")
+
+check_cmake_test(GetProperty
+ No-Target
+)
+
+set(Bad-Target-RESULT 1)
+set(Bad-Target-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-Bad-Target.cmake:1 \\(get_property\\):.*get_property could not find TARGET FOO\\..*")
+
+check_cmake_test(GetProperty
+ Bad-Target
+)
+
+set(No-Source-RESULT 1)
+set(No-Source-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-No-Source.cmake:1 \\(get_property\\):.*get_property not given name for SOURCE scope\\..*")
+
+check_cmake_test(GetProperty
+ No-Source
+)
+
+set(No-Test-RESULT 1)
+set(No-Test-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-No-Test.cmake:1 \\(get_property\\):.*get_property not given name for TEST scope\\..*")
+
+check_cmake_test(GetProperty
+ No-Test
+)
+
+set(Bad-Test-RESULT 1)
+set(Bad-Test-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-Bad-Test.cmake:1 \\(get_property\\):.*get_property given TEST name that does not exist: FOO.*")
+
+check_cmake_test(GetProperty
+ Bad-Test
+)
+
+set(Variable-Name-RESULT 1)
+set(Variable-Name-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-Variable-Name.cmake:1 \\(get_property\\):.*get_property given name for VARIABLE scope\\..*")
+
+check_cmake_test(GetProperty
+ Variable-Name
+)
+
+set(No-Cache-RESULT 1)
+set(No-Cache-STDERR ".*CMake Error at (@CMAKE_CURRENT_SOURCE_DIR@/)?GetProperty-No-Cache.cmake:1 \\(get_property\\):.*get_property not given name for CACHE scope\\..*")
+
+check_cmake_test(GetProperty
+ No-Cache
+)
diff --git a/Tests/CTestUpdateCVS.cmake.in b/Tests/CTestUpdateCVS.cmake.in
index a04673e..f7f5db6 100644
--- a/Tests/CTestUpdateCVS.cmake.in
+++ b/Tests/CTestUpdateCVS.cmake.in
@@ -18,6 +18,19 @@ set(CVS "@CVS_EXECUTABLE@")
message(" cvs = ${CVS}")
set(REPO ${TOP}/repo)
+
+# The MSYS cvs tool interprets "c:/" as a "machine:" name for SSH.
+# Detect the MSYS cvs and convert the repo path to an MSYS path.
+if(WIN32)
+ if(EXISTS "${CVS}")
+ file(STRINGS "${CVS}" cvs_is_msys LIMIT_COUNT 1 REGEX "[Mm][Ss][Yy][Ss]")
+ if(cvs_is_msys)
+ message(" '${CVS}' is from MSYS (contains '${cvs_is_msys}')")
+ string(REGEX REPLACE "^([A-Za-z]):" "/\\1" REPO "${REPO}")
+ endif()
+ endif()
+endif()
+
set(CVSCMD ${CVS} -d${REPO})
# CVSNT requires an extra option to 'cvs init'.
diff --git a/Tests/CTestUpdateHG.cmake.in b/Tests/CTestUpdateHG.cmake.in
index 543ddd9..640d2c6 100644
--- a/Tests/CTestUpdateHG.cmake.in
+++ b/Tests/CTestUpdateHG.cmake.in
@@ -28,7 +28,10 @@ run_child(
WORKING_DIRECTORY ${TOP}/repo.hg
COMMAND ${HG} init
)
-set(REPO file://${TOP}/repo.hg)
+if(NOT "${TOP}" MATCHES "^/")
+ set(slash /)
+endif()
+set(REPO file://${slash}${TOP}/repo.hg)
#-----------------------------------------------------------------------------
# Import initial content into the repository.
diff --git a/Tests/ExternalOBJ/CMakeLists.txt b/Tests/ExternalOBJ/CMakeLists.txt
index f12de11..683e799 100644
--- a/Tests/ExternalOBJ/CMakeLists.txt
+++ b/Tests/ExternalOBJ/CMakeLists.txt
@@ -59,3 +59,5 @@ ADD_EXECUTABLE(ExternalOBJ executable.cxx ${CUSTOM_OBJECT})
# not didn't work. So, repeat the executable using the object
# directly and not from the output of the copy.
ADD_EXECUTABLE(ExternalOBJ2 executable.cxx ${EXTERNAL_OBJECT})
+
+ADD_SUBDIRECTORY(Sub)
diff --git a/Tests/ExternalOBJ/Sub/CMakeLists.txt b/Tests/ExternalOBJ/Sub/CMakeLists.txt
new file mode 100644
index 0000000..35cd30c
--- /dev/null
+++ b/Tests/ExternalOBJ/Sub/CMakeLists.txt
@@ -0,0 +1,3 @@
+set_property(SOURCE ${CUSTOM_OBJECT} PROPERTY GENERATED 1)
+add_executable(ExternalOBJSub ../executable.cxx ${CUSTOM_OBJECT})
+add_dependencies(ExternalOBJSub ExternalOBJ) # depend on generating target
diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt
index ac70129..7a76261 100644
--- a/Tests/ExternalProject/CMakeLists.txt
+++ b/Tests/ExternalProject/CMakeLists.txt
@@ -280,6 +280,18 @@ if(do_cvs_tests)
set_property(TARGET ${proj}
PROPERTY FOLDER "SetupRepos/Local/Deeply/Nested/For/Testing")
+ # The MSYS cvs tool interprets "c:/" as a "machine:" name for SSH.
+ # Detect the MSYS cvs and convert the repo path to an MSYS path.
+ if(WIN32)
+ if(EXISTS "${CVS_EXECUTABLE}")
+ file(STRINGS "${CVS_EXECUTABLE}" cvs_is_msys LIMIT_COUNT 1 REGEX "[Mm][Ss][Yy][Ss]")
+ if(cvs_is_msys)
+ message(STATUS "'${CVS_EXECUTABLE}' is from MSYS (contains '${cvs_is_msys}')")
+ string(REGEX REPLACE "^([A-Za-z]):" "/\\1" local_cvs_repo "${local_cvs_repo}")
+ endif()
+ endif()
+ endif()
+
# CVS by date stamp:
#
set(proj TutorialStep1-CVS-20090626)
diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt
index 9a4bdfe..5862094 100644
--- a/Tests/FindPackageTest/CMakeLists.txt
+++ b/Tests/FindPackageTest/CMakeLists.txt
@@ -37,6 +37,12 @@ FIND_PACKAGE(VersionTestB 1.2)
FIND_PACKAGE(VersionTestC 1.2.3)
FIND_PACKAGE(VersionTestD 1.2.3.4)
+
+FIND_PACKAGE(LotsOfComponents COMPONENTS AComp OPTIONAL_COMPONENTS BComp CComp)
+IF(NOT LOTSOFCOMPONENTS_FOUND)
+ MESSAGE(SEND_ERROR "LotsOfComponents not found !")
+ENDIF()
+
#-----------------------------------------------------------------------------
# Test system package registry if possible.
SET(CMakeTestSystemPackage "")
@@ -82,6 +88,7 @@ SET(PACKAGES
RecursiveA RecursiveB RecursiveC
ArchA ArchB ArchC ArchD
EnvA EnvB
+ SetFoundTRUE SetFoundFALSE
${CMakeTestSystemPackage}
)
FOREACH(p ${PACKAGES})
@@ -117,6 +124,10 @@ FIND_PACKAGE(VersionedC 4.0 EXACT NAMES zot)
FIND_PACKAGE(VersionedD 1.1 EXACT NAMES Baz)
FIND_PACKAGE(VersionedE 1.2 EXACT NAMES Baz)
+# Test Config files which set Xyz_FOUND themselves:
+FIND_PACKAGE(SetFoundTRUE NO_MODULE)
+FIND_PACKAGE(SetFoundFALSE NO_MODULE)
+
# Test wrong initial path when result is present.
SET(WrongA_DIR "${VersionedD_DIR}")
FIND_PACKAGE(WrongA 1.2 EXACT NAMES Baz)
@@ -201,6 +212,8 @@ SET(ArchC_EXPECTED "lib/arch/zot-3.1/zot-config.cmake")
SET(ArchD_EXPECTED "lib/arch/cmake/zot-4.0/zot-config.cmake")
SET(EnvA_EXPECTED "lib/zot-3.1/zot-config.cmake")
SET(EnvB_MISSING "EnvB_DIR-NOTFOUND")
+SET(SetFoundTRUE_EXPECTED "cmake/SetFoundTRUEConfig.cmake")
+SET(SetFoundFALSE_MISSING "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
SET(CMakeTestSystemPackage_EXPECTED "SystemPackage/CMakeTestSystemPackageConfig.cmake")
# Check the results.
@@ -212,6 +225,11 @@ FOREACH(p ${PACKAGES})
"Package ${p} should have been [${${p}_MISSING}] but "
"was [${${p}_DIR}]")
ENDIF()
+ IF(${p}_FOUND)
+ MESSAGE(SEND_ERROR
+ "Package ${p} should not have been found, but ${p}_FOUND is set to "
+ "\"${${p}_FOUND}\"")
+ ENDIF()
ELSEIF(${p}_FOUND)
# Convert to relative path for comparison to expected location.
FILE(RELATIVE_PATH REL_${p}_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}"
@@ -305,13 +323,49 @@ STRING(REGEX REPLACE "-.*$" "" version ${CMAKE_VERSION})
FIND_PACKAGE(CMakeTestExportPackage 1.${version} EXACT REQUIRED)
#-----------------------------------------------------------------------------
-# Test write_basic_config_version_file().
+# Test configure_package_config_file().
-include(WriteBasicConfigVersionFile)
+include(CMakePackageConfigHelpers)
-write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/Foo123ConfigVersion.cmake
- VERSION 1.2.3
- COMPATIBILITY AnyNewerVersion)
+set(INCLUDE_INSTALL_DIR include )
+set(SHARE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/" )
+set(CURRENT_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}" )
+
+configure_package_config_file(RelocatableConfig.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/RelocatableConfig.cmake"
+ INSTALL_DESTINATION "${CMAKE_INSTALL_PREFIX}"
+ PATH_VARS INCLUDE_INSTALL_DIR SHARE_INSTALL_DIR CURRENT_BUILD_DIR
+ )
+
+set(Relocatable_FIND_COMPONENTS AComp BComp CComp)
+set(Relocatable_FIND_REQUIRED_BComp 1)
+include("${CMAKE_CURRENT_BINARY_DIR}/RelocatableConfig.cmake")
+
+if(NOT "${RELOC_INCLUDE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/include")
+ message(SEND_ERROR "RELOC_INCLUDE_DIR set by configure_package_config_file() is set to \"${RELOC_INCLUDE_DIR}\" (expected \"${CMAKE_CURRENT_BINARY_DIR}/include\")")
+endif()
+
+if(NOT "${RELOC_SHARE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/share/")
+ message(SEND_ERROR "RELOC_SHARE_DIR set by configure_package_config_file() is set to \"${RELOC_SHARE_DIR}\" (expected \"${CMAKE_CURRENT_BINARY_DIR}/share/\")")
+endif()
+
+if(NOT "${RELOC_BUILD_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}")
+ message(SEND_ERROR "RELOC_BUILD_DIR set by configure_package_config_file() is set to \"${RELOC_BUILD_DIR}\" (expected \"${CMAKE_CURRENT_BINARY_DIR}\")")
+endif()
+
+if(NOT DEFINED Relocatable_FOUND)
+ message(SEND_ERROR "Relocatable_FOUND not defined !")
+endif()
+
+if(Relocatable_FOUND)
+ message(SEND_ERROR "Relocatable_FOUND set to TRUE !")
+endif()
+
+#-----------------------------------------------------------------------------
+# Test write_basic_config_version_file().
+
+write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/Foo123ConfigVersion.cmake
+ VERSION 1.2.3
+ COMPATIBILITY AnyNewerVersion)
set(PACKAGE_FIND_VERSION 2.3.4)
include(${CMAKE_CURRENT_BINARY_DIR}/Foo123ConfigVersion.cmake)
@@ -345,6 +399,7 @@ endif()
#######################
+include(WriteBasicConfigVersionFile)
write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/Boo123ConfigVersion.cmake
VERSION 1.2.3
@@ -394,3 +449,73 @@ endif()
if(PACKAGE_VERSION_UNSUITABLE)
message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, but must not be !")
endif()
+
+#######################
+
+write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake
+ VERSION 1.2.3.17
+ COMPATIBILITY ExactVersion)
+
+set(PACKAGE_VERSION_EXACT FALSE)
+set(PACKAGE_FIND_VERSION 2.3.4)
+include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
+if(PACKAGE_VERSION_COMPATIBLE)
+ message(SEND_ERROR "Found Bar123 with version 1.2.3 (2.3.4 was requested) !")
+endif()
+if(PACKAGE_VERSION_EXACT)
+ message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
+endif()
+
+set(PACKAGE_FIND_VERSION 1.2)
+include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
+if(PACKAGE_VERSION_COMPATIBLE)
+ message(SEND_ERROR "Found Bar123 with version 1.2.3 (1.2 was requested) !")
+endif()
+if(PACKAGE_VERSION_EXACT)
+ message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
+endif()
+
+set(PACKAGE_FIND_VERSION 1)
+include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
+if(PACKAGE_VERSION_COMPATIBLE)
+ message(SEND_ERROR "Found Bar123 with version 1.2.3 (1 was requested) !")
+endif()
+if(PACKAGE_VERSION_EXACT)
+ message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
+endif()
+
+set(PACKAGE_FIND_VERSION 1.2.3.4)
+include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
+if(NOT PACKAGE_VERSION_COMPATIBLE)
+ message(SEND_ERROR "Did not find Bar123 with version 1.2.3 (1.2.3.4 was requested) !")
+endif()
+if(PACKAGE_VERSION_EXACT)
+ message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
+endif()
+
+set(PACKAGE_FIND_VERSION 1.2.3)
+set(PACKAGE_VERSION_EXACT FALSE)
+set(PACKAGE_VERSION_COMPATIBLE FALSE)
+include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
+if(NOT PACKAGE_VERSION_COMPATIBLE)
+ message(SEND_ERROR "Did not find Bar123 with version 1.2.3 (1.2.3 was requested) !")
+endif()
+if(PACKAGE_VERSION_EXACT)
+ message(SEND_ERROR "PACKAGE_VERSION_EXACT set, although it should not be !")
+endif()
+
+
+set(PACKAGE_FIND_VERSION 1.2.3.17)
+set(PACKAGE_VERSION_EXACT FALSE)
+set(PACKAGE_VERSION_COMPATIBLE FALSE)
+include(${CMAKE_CURRENT_BINARY_DIR}/Bar123ConfigVersion.cmake)
+if(NOT PACKAGE_VERSION_COMPATIBLE)
+ message(SEND_ERROR "Did not find Bar123 with version 1.2.3 (1.2.3.17 was requested) !")
+endif()
+if(NOT PACKAGE_VERSION_EXACT)
+ message(SEND_ERROR "PACKAGE_VERSION_EXACT not set, although it should be !")
+endif()
+
+if(PACKAGE_VERSION_UNSUITABLE)
+ message(SEND_ERROR "PACKAGE_VERSION_UNSUITABLE set, but must not be !")
+endif()
diff --git a/Tests/FindPackageTest/FindLotsOfComponents.cmake b/Tests/FindPackageTest/FindLotsOfComponents.cmake
new file mode 100644
index 0000000..9076d86
--- /dev/null
+++ b/Tests/FindPackageTest/FindLotsOfComponents.cmake
@@ -0,0 +1,10 @@
+set(LOC_FOO TRUE)
+
+set(LotsOfComponents_AComp_FOUND TRUE)
+set(LotsOfComponents_BComp_FOUND FALSE)
+set(LotsOfComponents_CComp_FOUND TRUE)
+
+include(FindPackageHandleStandardArgs)
+
+find_package_handle_standard_args(LotsOfComponents REQUIRED_VARS LOC_FOO
+ HANDLE_COMPONENTS)
diff --git a/Tests/FindPackageTest/RelocatableConfig.cmake.in b/Tests/FindPackageTest/RelocatableConfig.cmake.in
new file mode 100644
index 0000000..4a4b4e9
--- /dev/null
+++ b/Tests/FindPackageTest/RelocatableConfig.cmake.in
@@ -0,0 +1,11 @@
+@PACKAGE_INIT@
+
+set(RELOC_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")
+set(RELOC_SHARE_DIR "@PACKAGE_SHARE_INSTALL_DIR@")
+set_and_check(RELOC_BUILD_DIR "@PACKAGE_CURRENT_BUILD_DIR@")
+
+set(Relocatable_AComp_FOUND TRUE)
+set(Relocatable_BComp_FOUND FALSE)
+set(Relocatable_CComp_FOUND FALSE)
+
+check_required_components(Relocatable)
diff --git a/Tests/FindPackageTest/cmake/SetFoundFALSEConfig.cmake b/Tests/FindPackageTest/cmake/SetFoundFALSEConfig.cmake
new file mode 100644
index 0000000..ae6bd14
--- /dev/null
+++ b/Tests/FindPackageTest/cmake/SetFoundFALSEConfig.cmake
@@ -0,0 +1 @@
+set(SetFoundFALSE_FOUND FALSE)
diff --git a/Tests/FindPackageTest/cmake/SetFoundTRUEConfig.cmake b/Tests/FindPackageTest/cmake/SetFoundTRUEConfig.cmake
new file mode 100644
index 0000000..19d0711
--- /dev/null
+++ b/Tests/FindPackageTest/cmake/SetFoundTRUEConfig.cmake
@@ -0,0 +1 @@
+set(SetFoundTRUE_FOUND TRUE)
diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt
index 60b8c22..60f5e5e 100644
--- a/Tests/IncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/CMakeLists.txt
@@ -45,3 +45,5 @@ else()
set_target_properties(IncludeDirectories
PROPERTIES COMPILE_FLAGS "-ITarProp")
endif()
+
+add_subdirectory(TargetIncludeDirectories)
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
new file mode 100644
index 0000000..2cf36f5
--- /dev/null
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
@@ -0,0 +1,26 @@
+
+cmake_minimum_required(VERSION 2.8)
+
+project(TargetIncludeDirectories)
+
+macro(create_header _name)
+ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_name}")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_name}/${_name}.h"
+ "//${_name}.h
+ ")
+endmacro()
+
+create_header(bar)
+create_header(bat)
+create_header(foo)
+create_header(baz)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+include_directories("${CMAKE_CURRENT_BINARY_DIR}/bar")
+
+add_executable(TargetIncludeDirectories main.cpp)
+set_property(TARGET TargetIncludeDirectories APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/bat")
+set_property(TARGET TargetIncludeDirectories APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/foo")
+
+include_directories("${CMAKE_CURRENT_BINARY_DIR}/baz")
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp b/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
new file mode 100644
index 0000000..8aa3532
--- /dev/null
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
@@ -0,0 +1,10 @@
+
+#include "bar.h"
+#include "bat.h"
+#include "foo.h"
+#include "baz.h"
+
+int main(int, char**)
+{
+ return 0;
+}
diff --git a/Tests/ModuleDefinition/CMakeLists.txt b/Tests/ModuleDefinition/CMakeLists.txt
index b463a3c..a30f643 100644
--- a/Tests/ModuleDefinition/CMakeLists.txt
+++ b/Tests/ModuleDefinition/CMakeLists.txt
@@ -4,6 +4,14 @@ project(ModuleDefinition C)
# Test .def file source recognition for DLLs.
add_library(example_dll SHARED example_dll.c example_dll.def)
+# Test generated .def file.
+add_custom_command(OUTPUT example_dll_gen.def
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/example_dll_gen.def.in
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/example_dll_gen.def.in
+ ${CMAKE_CURRENT_BINARY_DIR}/example_dll_gen.def
+ )
+add_library(example_dll_gen SHARED example_dll_gen.c example_dll_gen.def)
+
# Test /DEF:<file> flag recognition for VS.
if(MSVC OR "${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$")
add_library(example_dll_2 SHARED example_dll_2.c)
@@ -16,7 +24,7 @@ endif()
# Test .def file source recognition for EXEs.
add_executable(example_exe example_exe.c example_exe.def)
set_property(TARGET example_exe PROPERTY ENABLE_EXPORTS 1)
-target_link_libraries(example_exe example_dll ${example_dll_2})
+target_link_libraries(example_exe example_dll example_dll_gen ${example_dll_2})
# Test linking to the executable.
add_library(example_mod_1 MODULE example_mod_1.c)
diff --git a/Tests/ModuleDefinition/example_dll_gen.c b/Tests/ModuleDefinition/example_dll_gen.c
new file mode 100644
index 0000000..be5d1ee
--- /dev/null
+++ b/Tests/ModuleDefinition/example_dll_gen.c
@@ -0,0 +1 @@
+int example_dll_gen_function(void) { return 0; }
diff --git a/Tests/ModuleDefinition/example_dll_gen.def.in b/Tests/ModuleDefinition/example_dll_gen.def.in
new file mode 100644
index 0000000..c489dbc
--- /dev/null
+++ b/Tests/ModuleDefinition/example_dll_gen.def.in
@@ -0,0 +1,2 @@
+EXPORTS
+example_dll_gen_function
diff --git a/Tests/ModuleDefinition/example_exe.c b/Tests/ModuleDefinition/example_exe.c
index c521b3a..253ae8b 100644
--- a/Tests/ModuleDefinition/example_exe.c
+++ b/Tests/ModuleDefinition/example_exe.c
@@ -1,4 +1,5 @@
extern int __declspec(dllimport) example_dll_function(void);
+extern int __declspec(dllimport) example_dll_gen_function(void);
#ifdef EXAMPLE_DLL_2
extern int __declspec(dllimport) example_dll_2_function(void);
#endif
@@ -7,6 +8,7 @@ int main(void)
{
return
example_dll_function() +
+ example_dll_gen_function() +
#ifdef EXAMPLE_DLL_2
example_dll_2_function() +
#endif
diff --git a/Tests/ObjectLibrary/A/CMakeLists.txt b/Tests/ObjectLibrary/A/CMakeLists.txt
new file mode 100644
index 0000000..121a8ac
--- /dev/null
+++ b/Tests/ObjectLibrary/A/CMakeLists.txt
@@ -0,0 +1,17 @@
+# Add -fPIC so objects can be used in shared libraries.
+# TODO: Need property for this.
+if(CMAKE_SHARED_LIBRARY_C_FLAGS AND NOT WATCOM)
+ set(CMAKE_C_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS} ${CMAKE_C_FLAGS}")
+endif()
+
+add_definitions(-DA_DEF)
+
+add_custom_command(
+ OUTPUT a1.c
+ DEPENDS a1.c.in
+ COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/a1.c.in
+ ${CMAKE_CURRENT_BINARY_DIR}/a1.c
+ )
+include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+add_library(A OBJECT a1.c a2.c)
diff --git a/Tests/ObjectLibrary/A/a.h b/Tests/ObjectLibrary/A/a.h
new file mode 100644
index 0000000..7259f98
--- /dev/null
+++ b/Tests/ObjectLibrary/A/a.h
@@ -0,0 +1,6 @@
+#ifndef A_DEF
+# error "A_DEF not defined"
+#endif
+#ifdef B_DEF
+# error "B_DEF must not be defined"
+#endif
diff --git a/Tests/ObjectLibrary/A/a1.c.in b/Tests/ObjectLibrary/A/a1.c.in
new file mode 100644
index 0000000..d1eaf58
--- /dev/null
+++ b/Tests/ObjectLibrary/A/a1.c.in
@@ -0,0 +1,2 @@
+#include "a.h"
+int a1(void) { return 0; }
diff --git a/Tests/ObjectLibrary/A/a2.c b/Tests/ObjectLibrary/A/a2.c
new file mode 100644
index 0000000..d8f225e
--- /dev/null
+++ b/Tests/ObjectLibrary/A/a2.c
@@ -0,0 +1,2 @@
+#include "a.h"
+int a2(void) { return 0; }
diff --git a/Tests/ObjectLibrary/AB.def b/Tests/ObjectLibrary/AB.def
new file mode 100644
index 0000000..3f2b5c0
--- /dev/null
+++ b/Tests/ObjectLibrary/AB.def
@@ -0,0 +1,5 @@
+EXPORTS
+a1
+a2
+b1
+b2
diff --git a/Tests/ObjectLibrary/B/CMakeLists.txt b/Tests/ObjectLibrary/B/CMakeLists.txt
new file mode 100644
index 0000000..67172d1
--- /dev/null
+++ b/Tests/ObjectLibrary/B/CMakeLists.txt
@@ -0,0 +1,15 @@
+if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
+ # VS 6 generator does not use per-target object locations.
+ set(vs6 _vs6)
+endif()
+
+# Add -fPIC so objects can be used in shared libraries.
+# TODO: Need property for this.
+if(CMAKE_SHARED_LIBRARY_C_FLAGS AND NOT WATCOM)
+ set(CMAKE_C_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS} ${CMAKE_C_FLAGS}")
+endif()
+
+add_definitions(-DB_DEF)
+add_library(B OBJECT b1.c b2.c)
+add_library(Bexport OBJECT b1${vs6}.c b2${vs6}.c)
+set_property(TARGET Bexport PROPERTY COMPILE_DEFINITIONS Bexport)
diff --git a/Tests/ObjectLibrary/B/b.h b/Tests/ObjectLibrary/B/b.h
new file mode 100644
index 0000000..11b22f4
--- /dev/null
+++ b/Tests/ObjectLibrary/B/b.h
@@ -0,0 +1,11 @@
+#ifdef A_DEF
+# error "A_DEF must not be defined"
+#endif
+#ifndef B_DEF
+# error "B_DEF not defined"
+#endif
+#if defined(_WIN32) && defined(Bexport)
+# define EXPORT_B __declspec(dllexport)
+#else
+# define EXPORT_B
+#endif
diff --git a/Tests/ObjectLibrary/B/b1.c b/Tests/ObjectLibrary/B/b1.c
new file mode 100644
index 0000000..fdeffe4
--- /dev/null
+++ b/Tests/ObjectLibrary/B/b1.c
@@ -0,0 +1,2 @@
+#include "b.h"
+EXPORT_B int b1(void) { return 0; }
diff --git a/Tests/ObjectLibrary/B/b1_vs6.c b/Tests/ObjectLibrary/B/b1_vs6.c
new file mode 100644
index 0000000..b606e10
--- /dev/null
+++ b/Tests/ObjectLibrary/B/b1_vs6.c
@@ -0,0 +1 @@
+#include "b1.c"
diff --git a/Tests/ObjectLibrary/B/b2.c b/Tests/ObjectLibrary/B/b2.c
new file mode 100644
index 0000000..6e0d17c
--- /dev/null
+++ b/Tests/ObjectLibrary/B/b2.c
@@ -0,0 +1,2 @@
+#include "b.h"
+EXPORT_B int b2(void) { return 0; }
diff --git a/Tests/ObjectLibrary/B/b2_vs6.c b/Tests/ObjectLibrary/B/b2_vs6.c
new file mode 100644
index 0000000..d96a43e
--- /dev/null
+++ b/Tests/ObjectLibrary/B/b2_vs6.c
@@ -0,0 +1 @@
+#include "b2.c"
diff --git a/Tests/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt
new file mode 100644
index 0000000..8723415
--- /dev/null
+++ b/Tests/ObjectLibrary/CMakeLists.txt
@@ -0,0 +1,52 @@
+cmake_minimum_required(VERSION 2.8)
+project(ObjectLibrary C)
+
+add_subdirectory(A)
+add_subdirectory(B)
+
+add_library(Cstatic STATIC c.c $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>)
+add_executable(UseCstatic main.c)
+target_link_libraries(UseCstatic Cstatic)
+
+add_library(Cshared SHARED c.c $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:Bexport>)
+add_executable(UseCshared main.c)
+set_property(TARGET UseCshared PROPERTY COMPILE_DEFINITIONS SHARED_C)
+target_link_libraries(UseCshared Cshared)
+
+add_executable(UseCinternal main.c c.c $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>)
+
+if("${CMAKE_GENERATOR}" MATCHES "^Visual Studio (6|7|7 .NET 2003)$")
+ # VS 6 and 7 generators do not add objects as sources so we need a
+ # dummy object to convince the IDE to build the targets below.
+ set(dummy dummy.obj) # In MinGW: gcc -c dummy.c -o dummy.obj
+elseif("${CMAKE_GENERATOR}" MATCHES "Xcode")
+ # Xcode does not seem to support targets without sources.
+ set(dummy dummy.c)
+endif()
+
+# Test static library without its own sources.
+add_library(ABstatic STATIC ${dummy} $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>)
+add_executable(UseABstatic mainAB.c)
+target_link_libraries(UseABstatic ABstatic)
+
+# Test module definition file to export object library symbols in the test
+# below if the platform needs and supports it.
+set(ABshared_SRCS $<TARGET_OBJECTS:A>)
+if(CMAKE_LINK_DEF_FILE_FLAG OR NOT WIN32)
+ list(APPEND ABshared_SRCS $<TARGET_OBJECTS:B> AB.def)
+else()
+ set(NO_A NO_A)
+ list(APPEND ABshared_SRCS $<TARGET_OBJECTS:Bexport>)
+endif()
+
+# Test shared library without its own sources.
+add_library(ABshared SHARED ${dummy} ${ABshared_SRCS})
+add_executable(UseABshared mainAB.c)
+set_property(TARGET UseABshared PROPERTY COMPILE_DEFINITIONS SHARED_B ${NO_A})
+target_link_libraries(UseABshared ABshared)
+
+# Test executable without its own sources.
+add_library(ABmain OBJECT mainAB.c)
+add_executable(UseABinternal ${dummy}
+ $<TARGET_OBJECTS:ABmain> $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>
+ )
diff --git a/Tests/ObjectLibrary/c.c b/Tests/ObjectLibrary/c.c
new file mode 100644
index 0000000..968095b
--- /dev/null
+++ b/Tests/ObjectLibrary/c.c
@@ -0,0 +1,19 @@
+#if defined(_WIN32) && defined(Cshared_EXPORTS)
+# define EXPORT_C __declspec(dllexport)
+#else
+# define EXPORT_C
+#endif
+
+extern int a1(void);
+extern int a2(void);
+extern int b1(void);
+extern int b2(void);
+EXPORT_C int c(void)
+{
+ return 0
+ + a1()
+ + a2()
+ + b1()
+ + b2()
+ ;
+}
diff --git a/Tests/ObjectLibrary/dummy.c b/Tests/ObjectLibrary/dummy.c
new file mode 100644
index 0000000..2b17d81
--- /dev/null
+++ b/Tests/ObjectLibrary/dummy.c
@@ -0,0 +1 @@
+int dummy(void) {return 0;}
diff --git a/Tests/ObjectLibrary/dummy.obj b/Tests/ObjectLibrary/dummy.obj
new file mode 100644
index 0000000..77f6f2f
--- /dev/null
+++ b/Tests/ObjectLibrary/dummy.obj
Binary files differ
diff --git a/Tests/ObjectLibrary/main.c b/Tests/ObjectLibrary/main.c
new file mode 100644
index 0000000..6819f1c
--- /dev/null
+++ b/Tests/ObjectLibrary/main.c
@@ -0,0 +1,16 @@
+#if defined(_WIN32) && defined(SHARED_C)
+# define IMPORT_C __declspec(dllimport)
+#else
+# define IMPORT_C
+#endif
+extern IMPORT_C int b1(void);
+extern IMPORT_C int b2(void);
+extern IMPORT_C int c(void);
+int main(void)
+{
+ return 0
+ + c()
+ + b1()
+ + b2()
+ ;
+}
diff --git a/Tests/ObjectLibrary/mainAB.c b/Tests/ObjectLibrary/mainAB.c
new file mode 100644
index 0000000..556898b
--- /dev/null
+++ b/Tests/ObjectLibrary/mainAB.c
@@ -0,0 +1,22 @@
+#if defined(_WIN32) && defined(SHARED_B)
+# define IMPORT_B __declspec(dllimport)
+#else
+# define IMPORT_B
+#endif
+extern IMPORT_B int b1(void);
+extern IMPORT_B int b2(void);
+#ifndef NO_A
+extern int a1(void);
+extern int a2(void);
+#endif
+int main(void)
+{
+ return 0
+#ifndef NO_A
+ + a1()
+ + a2()
+#endif
+ + b1()
+ + b2()
+ ;
+}
diff --git a/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt b/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt
index c7cc090..c362e79 100644
--- a/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt
+++ b/Tests/OutOfSource/OutOfSourceSubdir/CMakeLists.txt
@@ -24,6 +24,12 @@ IF ("${PROJECT_SOURCE_DIR}" STREQUAL "${ANOTHER_PROJ_SOURCE_DIR}")
MATH(EXPR MAXPATH "${MAXPATH} - 46")
ENDIF()
+ # Ninja imposes a maximum path component count of 30. Permit more
+ # path components in the source path.
+ IF(${CMAKE_GENERATOR} MATCHES "Ninja")
+ MATH(EXPR MAXPATH "${MAXPATH} - 44")
+ ENDIF()
+
# MAXPATH less 25 for last /and/deeper/simple.cxx part and small safety
MATH(EXPR MAXPATH "${MAXPATH} - 25")
STRING(LENGTH "${DEEPDIR}" DEEPDIR_LEN)
diff --git a/Tests/PrecompiledHeader/CMakeLists.txt b/Tests/PrecompiledHeader/CMakeLists.txt
index d423cae..3374e32 100644
--- a/Tests/PrecompiledHeader/CMakeLists.txt
+++ b/Tests/PrecompiledHeader/CMakeLists.txt
@@ -47,7 +47,8 @@ SET_SOURCE_FILES_PROPERTIES(foo_precompile.c PROPERTIES
# Setup dependencies for precompiled header creation and use. The VS
# IDE takes care of this automatically.
-IF("${CMAKE_GENERATOR}" MATCHES "Makefile")
+IF("${CMAKE_GENERATOR}" MATCHES "Makefile" OR
+ "${CMAKE_GENERATOR}" MATCHES "Ninja")
# This source file creates the precompiled header as a side-effect.
SET_SOURCE_FILES_PROPERTIES(foo_precompile.c PROPERTIES
OBJECT_OUTPUTS "${PCH_DIR}/foo_precompiled.pch")
diff --git a/Tests/Qt4Deploy/CMakeLists.txt b/Tests/Qt4Deploy/CMakeLists.txt
new file mode 100644
index 0000000..646ea9f
--- /dev/null
+++ b/Tests/Qt4Deploy/CMakeLists.txt
@@ -0,0 +1,70 @@
+cmake_minimum_required(VERSION 2.8)
+
+project(Qt4Deploy)
+set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install)
+
+find_package(Qt4 REQUIRED QtMain QtCore QtSql)
+include(${QT_USE_FILE})
+
+add_executable(testdeploy MACOSX_BUNDLE testdeploy.cpp)
+target_link_libraries(testdeploy ${QT_LIBRARIES})
+set_target_properties(testdeploy PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}")
+
+if(CMAKE_CONFIGURATION_TYPES AND QT_QTCORE_LIBRARY_RELEASE AND QT_QTCORE_LIBRARY_DEBUG)
+ # note: installing debug Qt libraries from a Qt installation configured with
+ # -debug-and-release not yet supported (very low priority).
+ install(CODE "
+ if(\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"^([Dd][Ee][Bb][Uu][Gg])$\")
+ return()
+ endif()
+ ")
+endif()
+
+# install the Qt4 app with qsqlite plugin
+install(CODE "file(REMOVE_RECURSE \"${CMAKE_INSTALL_PREFIX}\")")
+install(TARGETS testdeploy DESTINATION .)
+include(../../Modules/DeployQt4.cmake)
+if(APPLE)
+ install_qt4_executable(testdeploy.app "qsqlite")
+elseif(WIN32)
+ install_qt4_executable(testdeploy.exe "qsqlite")
+else()
+ install_qt4_executable(testdeploy "qsqlite")
+endif()
+
+
+# test depends on standard qsqlite plugin
+if(QT_QSQLITE_PLUGIN_DEBUG OR QT_QSQLITE_PLUGIN_RELEASE)
+
+ # test the deployed Qt application
+ if(APPLE)
+ install(CODE "
+ message(STATUS \"executing: ${CMAKE_INSTALL_PREFIX}/testdeploy.app/Contents/MacOS/testdeploy\")
+ execute_process(COMMAND \"${CMAKE_INSTALL_PREFIX}/testdeploy.app/Contents/MacOS/testdeploy\"
+ RESULT_VARIABLE result)
+ if(NOT result STREQUAL \"0\")
+ message(FATAL_ERROR \"error running testdeploy app\")
+ endif()
+ ")
+ else()
+ install(CODE "
+ message(STATUS \"executing: ${CMAKE_INSTALL_PREFIX}/testdeploy\")
+ execute_process(COMMAND \"${CMAKE_INSTALL_PREFIX}/testdeploy\"
+ RESULT_VARIABLE result)
+ if(NOT result STREQUAL \"0\")
+ message(FATAL_ERROR \"error running testdeploy app\")
+ endif()
+ ")
+ endif()
+
+ # custom target to install and test the installation at build time
+ if(CMAKE_CONFIGURATION_TYPES)
+ set(install_config "-DCMAKE_INSTALL_CONFIG_NAME=${CMAKE_CFG_INTDIR}")
+ endif()
+
+ add_custom_target(testdeploy_test ALL
+ COMMAND ${CMAKE_COMMAND} ${install_config} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake
+ COMMENT "${CMAKE_COMMAND} ${install_config} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake"
+ DEPENDS testdeploy)
+
+endif()
diff --git a/Tests/Qt4Deploy/testdeploy.cpp b/Tests/Qt4Deploy/testdeploy.cpp
new file mode 100644
index 0000000..8b9c8d6
--- /dev/null
+++ b/Tests/Qt4Deploy/testdeploy.cpp
@@ -0,0 +1,29 @@
+#include <QCoreApplication>
+#include <QSqlDatabase>
+#include <QLibraryInfo>
+#include <QDebug>
+#include <QStringList>
+
+int main(int argc, char** argv)
+{
+ QCoreApplication app(argc, argv);
+
+ qDebug() << "App path:" << app.applicationDirPath();
+ qDebug() << "Plugin path:" << QLibraryInfo::location(QLibraryInfo::PluginsPath);
+
+ bool foundSqlite = false;
+
+ qDebug() << "Supported Database Drivers:";
+ foreach(const QString &sqlDriver, QSqlDatabase::drivers())
+ {
+ qDebug() << " " << sqlDriver;
+ if(sqlDriver == "QSQLITE")
+ foundSqlite = true;
+ }
+
+ if(foundSqlite)
+ qDebug() << "Found sqlite support from plugin.";
+ else
+ qDebug() << "Could not find sqlite support from plugin.";
+ return foundSqlite ? 0 : 1;
+}
diff --git a/Tests/QtAutomoc/CMakeLists.txt b/Tests/QtAutomoc/CMakeLists.txt
index d255a5a..5e3686d 100644
--- a/Tests/QtAutomoc/CMakeLists.txt
+++ b/Tests/QtAutomoc/CMakeLists.txt
@@ -8,7 +8,7 @@ include(UseQt4)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
-add_definitions(-DFOO)
+add_definitions(-DFOO -DSomeDefine="Barx")
# enable relaxed mode so automoc can handle all the special cases:
set(CMAKE_AUTOMOC_RELAXED_MODE TRUE)
diff --git a/Tests/README b/Tests/README
index 9b0f5c1..8b2fda8 100644
--- a/Tests/README
+++ b/Tests/README
@@ -16,10 +16,15 @@ your test to the test runs.
This includes tests that will build something using try_compile() and friends,
but nothing that expects add_executable(), add_library(), or add_test() to run.
-If this matches your test you should put it into the Tests/CMakeOnly/ directory.
-Create a subdirectory named like your test and write the CMakeLists.txt you
-need into that subdirectory. Use the add_CMakeOnly_test() macro from
-Tests/CMakeOnly/CMakeLists.txt to add your test to the test runs.
+If the test configures the project only once and it must succeed then put it
+into the Tests/CMakeOnly/ directory. Create a subdirectory named like your
+test and write the CMakeLists.txt you need into that subdirectory. Use the
+add_CMakeOnly_test() macro from Tests/CMakeOnly/CMakeLists.txt to add your
+test to the test runs.
+
+If the test configures the project with multiple variations and verifies
+success or failure each time then put it into the Tests/RunCMake/ directory.
+Read the instructions in Tests/RunCMake/CMakeLists.txt to add a test.
3. If you are testing something from the Modules directory
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
new file mode 100644
index 0000000..0b79efa
--- /dev/null
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -0,0 +1,46 @@
+# This directory contains tests that run CMake to configure a project
+# but do not actually build anything. To add a test:
+#
+# 1.) Add a subdirectory named for the test.
+#
+# 2.) Call add_RunCMake_test and pass the test directory name.
+#
+# 3.) Create a RunCMakeTest.cmake script in the directory containing
+# include(RunCMake)
+# run_cmake(SubTest1)
+# ...
+# run_cmake(SubTestN)
+# where SubTest1..SubTestN are sub-test names each corresponding to
+# an independent CMake run and project configuration.
+#
+# 3.) Create a CMakeLists.txt file in the directory containing
+# cmake_minimum_required(...)
+# project(${RunCMake_TEST} NONE) # or languages needed
+# include(${RunCMake_TEST}.cmake)
+# where "${RunCMake_TEST}" is literal. A value for RunCMake_TEST
+# will be passed to CMake by the run_cmake macro when running each
+# sub-test.
+#
+# 4.) Create a <SubTest>.cmake file for each sub-test named above
+# containing the actual test code. Optionally create files
+# containing expected test results:
+# <SubTest>-result.txt = Process result expected if not "0"
+# <SubTest>-stdout.txt = Regex matching expected stdout content
+# <SubTest>-stderr.txt = Regex matching expected stderr content
+# Note that trailing newlines will be stripped from actual test
+# output before matching against the stdout and stderr expressions.
+
+macro(add_RunCMake_test test)
+ add_test(RunCMake.${test} ${CMAKE_CMAKE_COMMAND}
+ -DCMAKE_MODULE_PATH=${CMAKE_CURRENT_SOURCE_DIR}
+ -DRunCMake_GENERATOR=${CMAKE_TEST_GENERATOR}
+ -DRunCMake_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}/${test}
+ -DRunCMake_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}/${test}
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/${test}/RunCMakeTest.cmake"
+ )
+endmacro()
+
+add_RunCMake_test(ObjectLibrary)
+
+add_RunCMake_test(build_command)
+add_RunCMake_test(find_package)
diff --git a/Tests/CMakeCommands/find_package/MixedModeOptions-result.txt b/Tests/RunCMake/ObjectLibrary/BadObjSource1-result.txt
index d00491f..d00491f 100644
--- a/Tests/CMakeCommands/find_package/MixedModeOptions-result.txt
+++ b/Tests/RunCMake/ObjectLibrary/BadObjSource1-result.txt
diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource1-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadObjSource1-stderr.txt
new file mode 100644
index 0000000..b31225b
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadObjSource1-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at BadObjSource1.cmake:1 \(add_library\):
+ OBJECT library "A" contains:
+
+ bad.def
+
+ but may contain only headers and sources that compile.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource1.cmake b/Tests/RunCMake/ObjectLibrary/BadObjSource1.cmake
new file mode 100644
index 0000000..aa3514d
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadObjSource1.cmake
@@ -0,0 +1 @@
+add_library(A OBJECT a.c bad.def)
diff --git a/Tests/CMakeCommands/find_package/MissingNormalRequired-result.txt b/Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt
index d00491f..d00491f 100644
--- a/Tests/CMakeCommands/find_package/MissingNormalRequired-result.txt
+++ b/Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt
diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt
new file mode 100644
index 0000000..906cf0b
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at BadObjSource2.cmake:1 \(add_library\):
+ OBJECT library "A" contains:
+
+ bad.obj
+
+ but may contain only headers and sources that compile.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource2.cmake b/Tests/RunCMake/ObjectLibrary/BadObjSource2.cmake
new file mode 100644
index 0000000..7957c99
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadObjSource2.cmake
@@ -0,0 +1 @@
+add_library(A OBJECT a.c bad.obj)
diff --git a/Tests/CMakeCommands/find_package/MissingModuleRequired-result.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-result.txt
index d00491f..d00491f 100644
--- a/Tests/CMakeCommands/find_package/MissingModuleRequired-result.txt
+++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-result.txt
diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt
new file mode 100644
index 0000000..a1cac36
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error at BadSourceExpression1.cmake:1 \(add_library\):
+ Unrecognized generator expression:
+
+ \$<BAD_EXPRESSION>
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression1.cmake b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1.cmake
new file mode 100644
index 0000000..020c9a0
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1.cmake
@@ -0,0 +1 @@
+add_library(A STATIC a.c $<BAD_EXPRESSION>)
diff --git a/Tests/CMakeCommands/find_package/MissingConfigRequired-result.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-result.txt
index d00491f..d00491f 100644
--- a/Tests/CMakeCommands/find_package/MissingConfigRequired-result.txt
+++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-result.txt
diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt
new file mode 100644
index 0000000..f1fcbe8
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at BadSourceExpression2.cmake:1 \(add_library\):
+ Objects of target "DoesNotExist" referenced but no such target exists.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression2.cmake b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2.cmake
new file mode 100644
index 0000000..ed5dc43
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2.cmake
@@ -0,0 +1 @@
+add_library(A STATIC a.c $<TARGET_OBJECTS:DoesNotExist>)
diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-result.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt
new file mode 100644
index 0000000..ad14a35
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at BadSourceExpression3.cmake:2 \(add_library\):
+ Objects of target "NotObjLib" referenced but is not an OBJECT library.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3.cmake b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3.cmake
new file mode 100644
index 0000000..c3d9a62
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3.cmake
@@ -0,0 +1,2 @@
+add_library(NotObjLib STATIC a.c)
+add_library(A STATIC a.c $<TARGET_OBJECTS:NotObjLib>)
diff --git a/Tests/RunCMake/ObjectLibrary/CMakeLists.txt b/Tests/RunCMake/ObjectLibrary/CMakeLists.txt
new file mode 100644
index 0000000..a7f0779
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8)
+project(${RunCMake_TEST} C)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/ObjectLibrary/Export-result.txt b/Tests/RunCMake/ObjectLibrary/Export-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/Export-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/Export-stderr.txt b/Tests/RunCMake/ObjectLibrary/Export-stderr.txt
new file mode 100644
index 0000000..bdadca4
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/Export-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at Export.cmake:2 \(export\):
+ export given OBJECT library "A" which may not be exported.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/Export.cmake b/Tests/RunCMake/ObjectLibrary/Export.cmake
new file mode 100644
index 0000000..a3f104e
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/Export.cmake
@@ -0,0 +1,2 @@
+add_library(A OBJECT a.c)
+export(TARGETS A FILE AExport.cmake)
diff --git a/Tests/RunCMake/ObjectLibrary/ExportLanguages.cmake b/Tests/RunCMake/ObjectLibrary/ExportLanguages.cmake
new file mode 100644
index 0000000..0796c21
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ExportLanguages.cmake
@@ -0,0 +1,15 @@
+enable_language(CXX)
+add_library(A OBJECT a.cxx)
+add_library(B STATIC a.c $<TARGET_OBJECTS:A>)
+
+# Verify that object library languages are propagated.
+export(TARGETS B NAMESPACE Exp FILE BExport.cmake)
+include(${CMAKE_CURRENT_BINARY_DIR}/BExport.cmake)
+get_property(configs TARGET ExpB PROPERTY IMPORTED_CONFIGURATIONS)
+foreach(c ${configs})
+ get_property(langs TARGET ExpB PROPERTY IMPORTED_LINK_INTERFACE_LANGUAGES_${c})
+ list(FIND langs CXX pos)
+ if(${pos} LESS 0)
+ message(FATAL_ERROR "Target export does not list object library languages.")
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/ObjectLibrary/Import-result.txt b/Tests/RunCMake/ObjectLibrary/Import-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/Import-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/Import-stderr.txt b/Tests/RunCMake/ObjectLibrary/Import-stderr.txt
new file mode 100644
index 0000000..74b496a
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/Import-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at Import.cmake:1 \(add_library\):
+ The OBJECT library type may not be used for IMPORTED libraries.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/Import.cmake b/Tests/RunCMake/ObjectLibrary/Import.cmake
new file mode 100644
index 0000000..806b44a
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/Import.cmake
@@ -0,0 +1 @@
+add_library(A OBJECT IMPORTED)
diff --git a/Tests/RunCMake/ObjectLibrary/Install-result.txt b/Tests/RunCMake/ObjectLibrary/Install-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/Install-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/Install-stderr.txt b/Tests/RunCMake/ObjectLibrary/Install-stderr.txt
new file mode 100644
index 0000000..d2f9f4a
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/Install-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at Install.cmake:2 \(install\):
+ install TARGETS given OBJECT library "A" which may not be installed.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/Install.cmake b/Tests/RunCMake/ObjectLibrary/Install.cmake
new file mode 100644
index 0000000..c1d214b
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/Install.cmake
@@ -0,0 +1,2 @@
+add_library(A OBJECT a.c)
+install(TARGETS A DESTINATION lib)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt b/Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt b/Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt
new file mode 100644
index 0000000..90e828b
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at LinkObjLHS.cmake:2 \(target_link_libraries\):
+ Object library target "AnObjLib" may not link to anything.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake
new file mode 100644
index 0000000..5d7831a
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake
@@ -0,0 +1,2 @@
+add_library(AnObjLib OBJECT a.c)
+target_link_libraries(AnObjLib OtherLib)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt
new file mode 100644
index 0000000..8809f89
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error at LinkObjRHS1.cmake:3 \(target_link_libraries\):
+ Target "AnObjLib" of type OBJECT_LIBRARY may not be linked into another
+ target. One may link only to STATIC or SHARED libraries, or to executables
+ with the ENABLE_EXPORTS property set.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake
new file mode 100644
index 0000000..113d6a8
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake
@@ -0,0 +1,3 @@
+add_library(A STATIC a.c)
+add_library(AnObjLib OBJECT a.c)
+target_link_libraries(A AnObjLib)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt
new file mode 100644
index 0000000..3295fca
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error at LinkObjRHS2.cmake:1 \(add_library\):
+ Target "A" links to OBJECT library "AnObjLib" but this is not allowed. One
+ may link only to STATIC or SHARED libraries, or to executables with the
+ ENABLE_EXPORTS property set.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake
new file mode 100644
index 0000000..6163729
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake
@@ -0,0 +1,3 @@
+add_library(A SHARED a.c)
+target_link_libraries(A AnObjLib)
+add_library(AnObjLib OBJECT a.c)
diff --git a/Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt b/Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt b/Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt
new file mode 100644
index 0000000..d67b4ae
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at ObjWithObj.cmake:2 \(add_library\):
+ Only executables and non-OBJECT libraries may reference target objects.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/ObjWithObj.cmake b/Tests/RunCMake/ObjectLibrary/ObjWithObj.cmake
new file mode 100644
index 0000000..d0ef34b
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/ObjWithObj.cmake
@@ -0,0 +1,2 @@
+add_library(A OBJECT a.c)
+add_library(B OBJECT $<TARGET_OBJECTS:A>)
diff --git a/Tests/RunCMake/ObjectLibrary/PostBuild-result.txt b/Tests/RunCMake/ObjectLibrary/PostBuild-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/PostBuild-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/PostBuild-stderr.txt b/Tests/RunCMake/ObjectLibrary/PostBuild-stderr.txt
new file mode 100644
index 0000000..4b067bb
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/PostBuild-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at PostBuild.cmake:2 \(add_custom_command\):
+ Target "A" is an OBJECT library that may not have PRE_BUILD, PRE_LINK, or
+ POST_BUILD commands.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/PostBuild.cmake b/Tests/RunCMake/ObjectLibrary/PostBuild.cmake
new file mode 100644
index 0000000..dea9a09
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/PostBuild.cmake
@@ -0,0 +1,4 @@
+add_library(A OBJECT a.c)
+add_custom_command(TARGET A POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "A post-build"
+ )
diff --git a/Tests/RunCMake/ObjectLibrary/PreBuild-result.txt b/Tests/RunCMake/ObjectLibrary/PreBuild-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/PreBuild-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/PreBuild-stderr.txt b/Tests/RunCMake/ObjectLibrary/PreBuild-stderr.txt
new file mode 100644
index 0000000..3b27a6d
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/PreBuild-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at PreBuild.cmake:2 \(add_custom_command\):
+ Target "A" is an OBJECT library that may not have PRE_BUILD, PRE_LINK, or
+ POST_BUILD commands.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/PreBuild.cmake b/Tests/RunCMake/ObjectLibrary/PreBuild.cmake
new file mode 100644
index 0000000..e4424c1
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/PreBuild.cmake
@@ -0,0 +1,4 @@
+add_library(A OBJECT a.c)
+add_custom_command(TARGET A PRE_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo "A pre-build"
+ )
diff --git a/Tests/RunCMake/ObjectLibrary/PreLink-result.txt b/Tests/RunCMake/ObjectLibrary/PreLink-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/PreLink-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/ObjectLibrary/PreLink-stderr.txt b/Tests/RunCMake/ObjectLibrary/PreLink-stderr.txt
new file mode 100644
index 0000000..947b9f1
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/PreLink-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error at PreLink.cmake:2 \(add_custom_command\):
+ Target "A" is an OBJECT library that may not have PRE_BUILD, PRE_LINK, or
+ POST_BUILD commands.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/PreLink.cmake b/Tests/RunCMake/ObjectLibrary/PreLink.cmake
new file mode 100644
index 0000000..b889055
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/PreLink.cmake
@@ -0,0 +1,4 @@
+add_library(A OBJECT a.c)
+add_custom_command(TARGET A PRE_LINK
+ COMMAND ${CMAKE_COMMAND} -E echo "A pre-link"
+ )
diff --git a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
new file mode 100644
index 0000000..55db14d
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
@@ -0,0 +1,18 @@
+include(RunCMake)
+
+run_cmake(BadSourceExpression1)
+run_cmake(BadSourceExpression2)
+run_cmake(BadSourceExpression3)
+run_cmake(BadObjSource1)
+run_cmake(BadObjSource2)
+run_cmake(Export)
+run_cmake(ExportLanguages)
+run_cmake(Import)
+run_cmake(Install)
+run_cmake(LinkObjLHS)
+run_cmake(LinkObjRHS1)
+run_cmake(LinkObjRHS2)
+run_cmake(ObjWithObj)
+run_cmake(PostBuild)
+run_cmake(PreBuild)
+run_cmake(PreLink)
diff --git a/Tests/RunCMake/ObjectLibrary/a.c b/Tests/RunCMake/ObjectLibrary/a.c
new file mode 100644
index 0000000..af20d3f
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/a.c
@@ -0,0 +1 @@
+int a(void) { return 0; }
diff --git a/Tests/RunCMake/ObjectLibrary/a.cxx b/Tests/RunCMake/ObjectLibrary/a.cxx
new file mode 100644
index 0000000..ae9c87c
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/a.cxx
@@ -0,0 +1 @@
+extern "C" int acxx(void) { return 0; }
diff --git a/Tests/RunCMake/ObjectLibrary/bad.def b/Tests/RunCMake/ObjectLibrary/bad.def
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/bad.def
diff --git a/Tests/RunCMake/ObjectLibrary/bad.obj b/Tests/RunCMake/ObjectLibrary/bad.obj
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/bad.obj
diff --git a/Tests/CMakeCommands/find_package/test.cmake b/Tests/RunCMake/RunCMake.cmake
index dd1072e..2639463 100644
--- a/Tests/CMakeCommands/find_package/test.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -1,15 +1,16 @@
-if(NOT DEFINED dir)
- message(FATAL_ERROR "dir not defined")
-endif()
-
-if(NOT DEFINED gen)
- message(FATAL_ERROR "gen not defined")
-endif()
+foreach(arg
+ RunCMake_GENERATOR
+ RunCMake_SOURCE_DIR
+ RunCMake_BINARY_DIR
+ )
+ if(NOT DEFINED ${arg})
+ message(FATAL_ERROR "${arg} not given!")
+ endif()
+endforeach()
-# TODO: Generalize this for other tests.
-function(run_test test)
- set(top_src "${CMAKE_CURRENT_LIST_DIR}")
- set(top_bin "${dir}")
+function(run_cmake test)
+ set(top_src "${RunCMake_SOURCE_DIR}")
+ set(top_bin "${RunCMake_BINARY_DIR}")
if(EXISTS ${top_src}/${test}-result.txt)
file(READ ${top_src}/${test}-result.txt expect_result)
string(REGEX REPLACE "\n+$" "" expect_result "${expect_result}")
@@ -29,7 +30,8 @@ function(run_test test)
file(REMOVE_RECURSE "${binary_dir}")
file(MAKE_DIRECTORY "${binary_dir}")
execute_process(
- COMMAND ${CMAKE_COMMAND} "${source_dir}" -G "${gen}" -DTEST=${test}
+ COMMAND ${CMAKE_COMMAND} "${source_dir}"
+ -G "${RunCMake_GENERATOR}" -DRunCMake_TEST=${test}
WORKING_DIRECTORY "${binary_dir}"
OUTPUT_VARIABLE actual_stdout
ERROR_VARIABLE actual_stderr
@@ -65,16 +67,3 @@ function(run_test test)
message(STATUS "${test} - PASSED")
endif()
endfunction()
-
-run_test(MissingNormal)
-run_test(MissingNormalRequired)
-run_test(MissingNormalVersion)
-run_test(MissingNormalWarnNoModuleOld)
-run_test(MissingNormalWarnNoModuleNew)
-run_test(MissingModule)
-run_test(MissingModuleRequired)
-run_test(MissingConfig)
-run_test(MissingConfigOneName)
-run_test(MissingConfigRequired)
-run_test(MissingConfigVersion)
-run_test(MixedModeOptions)
diff --git a/Tests/CMakeCommands/build_command/CMakeLists.txt b/Tests/RunCMake/build_command/CMakeLists.txt
index 990ac90..0fbb948 100644
--- a/Tests/CMakeCommands/build_command/CMakeLists.txt
+++ b/Tests/RunCMake/build_command/CMakeLists.txt
@@ -1,3 +1,7 @@
+cmake_minimum_required(VERSION 2.8)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
+
# This CMakeLists file is *sometimes expected* to result in a configure error.
#
# expect this to succeed:
@@ -12,12 +16,9 @@
# ...even purposefully calling it with known-bad argument lists to cover
# error handling code.
#
-cmake_minimum_required(VERSION 2.8)
-project(test_build_command)
set(cmd "initial")
-message("CTEST_FULL_OUTPUT")
message("0. begin")
if(TEST_ERROR_CONDITIONS)
diff --git a/Tests/RunCMake/build_command/ErrorsOFF-stderr.txt b/Tests/RunCMake/build_command/ErrorsOFF-stderr.txt
new file mode 100644
index 0000000..331885b
--- /dev/null
+++ b/Tests/RunCMake/build_command/ErrorsOFF-stderr.txt
@@ -0,0 +1 @@
+skipping cases 1, 2 and 3 because TEST_ERROR_CONDITIONS is OFF
diff --git a/Tests/RunCMake/build_command/ErrorsOFF-stdout.txt b/Tests/RunCMake/build_command/ErrorsOFF-stdout.txt
new file mode 100644
index 0000000..cf66a9d
--- /dev/null
+++ b/Tests/RunCMake/build_command/ErrorsOFF-stdout.txt
@@ -0,0 +1 @@
+Build files have been written to:
diff --git a/Tests/RunCMake/build_command/ErrorsOFF.cmake b/Tests/RunCMake/build_command/ErrorsOFF.cmake
new file mode 100644
index 0000000..a243fab
--- /dev/null
+++ b/Tests/RunCMake/build_command/ErrorsOFF.cmake
@@ -0,0 +1 @@
+set(TEST_ERROR_CONDITIONS OFF)
diff --git a/Tests/RunCMake/build_command/ErrorsON-result.txt b/Tests/RunCMake/build_command/ErrorsON-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/build_command/ErrorsON-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/build_command/ErrorsON-stderr.txt b/Tests/RunCMake/build_command/ErrorsON-stderr.txt
new file mode 100644
index 0000000..0be7475
--- /dev/null
+++ b/Tests/RunCMake/build_command/ErrorsON-stderr.txt
@@ -0,0 +1,12 @@
+CMake Error at CMakeLists.txt:[0-9]+ \(build_command\):
+ build_command requires at least one argument naming a CMake variable
+
++
+1. cmd='initial'
+CMake Error at CMakeLists.txt:[0-9]+ \(build_command\):
+ build_command unknown argument "BOGUS"
+
++
+2. cmd='initial'
+CMake Error at CMakeLists.txt:[0-9]+ \(build_command\):
+ build_command unknown argument "STUFF"
diff --git a/Tests/RunCMake/build_command/ErrorsON-stdout.txt b/Tests/RunCMake/build_command/ErrorsON-stdout.txt
new file mode 100644
index 0000000..841dd0d
--- /dev/null
+++ b/Tests/RunCMake/build_command/ErrorsON-stdout.txt
@@ -0,0 +1 @@
+Configuring incomplete, errors occurred!
diff --git a/Tests/RunCMake/build_command/ErrorsON.cmake b/Tests/RunCMake/build_command/ErrorsON.cmake
new file mode 100644
index 0000000..27814bf
--- /dev/null
+++ b/Tests/RunCMake/build_command/ErrorsON.cmake
@@ -0,0 +1 @@
+set(TEST_ERROR_CONDITIONS ON)
diff --git a/Tests/RunCMake/build_command/RunCMakeTest.cmake b/Tests/RunCMake/build_command/RunCMakeTest.cmake
new file mode 100644
index 0000000..4525c57
--- /dev/null
+++ b/Tests/RunCMake/build_command/RunCMakeTest.cmake
@@ -0,0 +1,4 @@
+include(RunCMake)
+
+run_cmake(ErrorsOFF)
+run_cmake(ErrorsON)
diff --git a/Tests/RunCMake/find_package/CMakeLists.txt b/Tests/RunCMake/find_package/CMakeLists.txt
new file mode 100644
index 0000000..e8db6b0
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/find_package/ComponentRequiredAndOptional-result.txt b/Tests/RunCMake/find_package/ComponentRequiredAndOptional-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_package/ComponentRequiredAndOptional-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_package/ComponentRequiredAndOptional-stderr.txt b/Tests/RunCMake/find_package/ComponentRequiredAndOptional-stderr.txt
new file mode 100644
index 0000000..db8f512
--- /dev/null
+++ b/Tests/RunCMake/find_package/ComponentRequiredAndOptional-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at ComponentRequiredAndOptional.cmake:1 \(find_package\):
+ find_package called with components that are both required and optional:
+
+ CompA
+ CompB
+
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/find_package/ComponentRequiredAndOptional.cmake b/Tests/RunCMake/find_package/ComponentRequiredAndOptional.cmake
new file mode 100644
index 0000000..0355f5a
--- /dev/null
+++ b/Tests/RunCMake/find_package/ComponentRequiredAndOptional.cmake
@@ -0,0 +1 @@
+find_package(NotHere REQUIRED CompA CompB CompC OPTIONAL_COMPONENTS CompA CompB CompD)
diff --git a/Tests/CMakeCommands/find_package/MissingConfig-stderr.txt b/Tests/RunCMake/find_package/MissingConfig-stderr.txt
index 0d14dcb..1eae0bb 100644
--- a/Tests/CMakeCommands/find_package/MissingConfig-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingConfig-stderr.txt
@@ -11,3 +11,9 @@ CMake Warning at MissingConfig.cmake:1 \(find_package\):
been installed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
+
+
+CMake Warning at MissingConfig.cmake:2 \(message\):
+ This warning must be reachable.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/find_package/MissingConfig.cmake b/Tests/RunCMake/find_package/MissingConfig.cmake
new file mode 100644
index 0000000..238e7e4
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingConfig.cmake
@@ -0,0 +1,2 @@
+find_package(NotHere CONFIG)
+message(WARNING "This warning must be reachable.")
diff --git a/Tests/CMakeCommands/find_package/MissingConfigOneName-stderr.txt b/Tests/RunCMake/find_package/MissingConfigOneName-stderr.txt
index 10e71fa..10e71fa 100644
--- a/Tests/CMakeCommands/find_package/MissingConfigOneName-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingConfigOneName-stderr.txt
diff --git a/Tests/CMakeCommands/find_package/MissingConfigOneName.cmake b/Tests/RunCMake/find_package/MissingConfigOneName.cmake
index 11676a9..11676a9 100644
--- a/Tests/CMakeCommands/find_package/MissingConfigOneName.cmake
+++ b/Tests/RunCMake/find_package/MissingConfigOneName.cmake
diff --git a/Tests/RunCMake/find_package/MissingConfigRequired-result.txt b/Tests/RunCMake/find_package/MissingConfigRequired-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingConfigRequired-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/CMakeCommands/find_package/MissingConfigRequired-stderr.txt b/Tests/RunCMake/find_package/MissingConfigRequired-stderr.txt
index 56325d8..2ba774a 100644
--- a/Tests/CMakeCommands/find_package/MissingConfigRequired-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingConfigRequired-stderr.txt
@@ -10,4 +10,4 @@ CMake Error at MissingConfigRequired.cmake:1 \(find_package\):
"NotHere" provides a separate development package or SDK, be sure it has
been installed.
Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/find_package/MissingConfigRequired.cmake b/Tests/RunCMake/find_package/MissingConfigRequired.cmake
new file mode 100644
index 0000000..0ae6702
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingConfigRequired.cmake
@@ -0,0 +1,2 @@
+find_package(NotHere CONFIG REQUIRED)
+message(FATAL_ERROR "This error must not be reachable.")
diff --git a/Tests/CMakeCommands/find_package/MissingConfigVersion-stderr.txt b/Tests/RunCMake/find_package/MissingConfigVersion-stderr.txt
index 2f5086e..2f5086e 100644
--- a/Tests/CMakeCommands/find_package/MissingConfigVersion-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingConfigVersion-stderr.txt
diff --git a/Tests/CMakeCommands/find_package/MissingConfigVersion.cmake b/Tests/RunCMake/find_package/MissingConfigVersion.cmake
index ac35a79..ac35a79 100644
--- a/Tests/CMakeCommands/find_package/MissingConfigVersion.cmake
+++ b/Tests/RunCMake/find_package/MissingConfigVersion.cmake
diff --git a/Tests/CMakeCommands/find_package/MissingModule-stderr.txt b/Tests/RunCMake/find_package/MissingModule-stderr.txt
index 71b5eae..2ad460f 100644
--- a/Tests/CMakeCommands/find_package/MissingModule-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingModule-stderr.txt
@@ -19,3 +19,8 @@ CMake Warning \(dev\) at MissingModule.cmake:1 \(find_package\):
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning at MissingModule.cmake:2 \(message\):
+ This warning must be reachable.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/find_package/MissingModule.cmake b/Tests/RunCMake/find_package/MissingModule.cmake
new file mode 100644
index 0000000..76bcef2
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingModule.cmake
@@ -0,0 +1,2 @@
+find_package(NotHere MODULE)
+message(WARNING "This warning must be reachable.")
diff --git a/Tests/RunCMake/find_package/MissingModuleRequired-result.txt b/Tests/RunCMake/find_package/MissingModuleRequired-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingModuleRequired-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/CMakeCommands/find_package/MissingModuleRequired-stderr.txt b/Tests/RunCMake/find_package/MissingModuleRequired-stderr.txt
index c3cd350..fec05f1 100644
--- a/Tests/CMakeCommands/find_package/MissingModuleRequired-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingModuleRequired-stderr.txt
@@ -18,4 +18,4 @@ CMake Warning \(dev\) at MissingModuleRequired.cmake:1 \(find_package\):
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
-This warning is for project developers. Use -Wno-dev to suppress it.
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/find_package/MissingModuleRequired.cmake b/Tests/RunCMake/find_package/MissingModuleRequired.cmake
new file mode 100644
index 0000000..897eda6
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingModuleRequired.cmake
@@ -0,0 +1,2 @@
+find_package(NotHere MODULE REQUIRED)
+message(FATAL_ERROR "This error must not be reachable.")
diff --git a/Tests/CMakeCommands/find_package/MissingNormal-stderr.txt b/Tests/RunCMake/find_package/MissingNormal-stderr.txt
index e5cbd97..f4c6fba 100644
--- a/Tests/CMakeCommands/find_package/MissingNormal-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingNormal-stderr.txt
@@ -15,3 +15,9 @@ CMake Warning at MissingNormal.cmake:1 \(find_package\):
been installed.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
+
+
+CMake Warning at MissingNormal.cmake:2 \(message\):
+ This warning must be reachable.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/find_package/MissingNormal.cmake b/Tests/RunCMake/find_package/MissingNormal.cmake
new file mode 100644
index 0000000..fb90e01
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingNormal.cmake
@@ -0,0 +1,2 @@
+find_package(NotHere)
+message(WARNING "This warning must be reachable.")
diff --git a/Tests/RunCMake/find_package/MissingNormalRequired-result.txt b/Tests/RunCMake/find_package/MissingNormalRequired-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingNormalRequired-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/CMakeCommands/find_package/MissingNormalRequired-stderr.txt b/Tests/RunCMake/find_package/MissingNormalRequired-stderr.txt
index ac52aec..7bb7902 100644
--- a/Tests/CMakeCommands/find_package/MissingNormalRequired-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingNormalRequired-stderr.txt
@@ -14,4 +14,4 @@ CMake Error at MissingNormalRequired.cmake:1 \(find_package\):
"NotHere" provides a separate development package or SDK, be sure it has
been installed.
Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
+ CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/find_package/MissingNormalRequired.cmake b/Tests/RunCMake/find_package/MissingNormalRequired.cmake
new file mode 100644
index 0000000..33353d8
--- /dev/null
+++ b/Tests/RunCMake/find_package/MissingNormalRequired.cmake
@@ -0,0 +1,2 @@
+find_package(NotHere REQUIRED)
+message(FATAL_ERROR "This error must not be reachable.")
diff --git a/Tests/CMakeCommands/find_package/MissingNormalVersion-stderr.txt b/Tests/RunCMake/find_package/MissingNormalVersion-stderr.txt
index 36de800..36de800 100644
--- a/Tests/CMakeCommands/find_package/MissingNormalVersion-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingNormalVersion-stderr.txt
diff --git a/Tests/CMakeCommands/find_package/MissingNormalVersion.cmake b/Tests/RunCMake/find_package/MissingNormalVersion.cmake
index 2d9ce4e..2d9ce4e 100644
--- a/Tests/CMakeCommands/find_package/MissingNormalVersion.cmake
+++ b/Tests/RunCMake/find_package/MissingNormalVersion.cmake
diff --git a/Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleNew-stderr.txt b/Tests/RunCMake/find_package/MissingNormalWarnNoModuleNew-stderr.txt
index d34f23c..d34f23c 100644
--- a/Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleNew-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingNormalWarnNoModuleNew-stderr.txt
diff --git a/Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleNew.cmake b/Tests/RunCMake/find_package/MissingNormalWarnNoModuleNew.cmake
index 0211249..0211249 100644
--- a/Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleNew.cmake
+++ b/Tests/RunCMake/find_package/MissingNormalWarnNoModuleNew.cmake
diff --git a/Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleOld-stderr.txt b/Tests/RunCMake/find_package/MissingNormalWarnNoModuleOld-stderr.txt
index b336b56..b336b56 100644
--- a/Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleOld-stderr.txt
+++ b/Tests/RunCMake/find_package/MissingNormalWarnNoModuleOld-stderr.txt
diff --git a/Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleOld.cmake b/Tests/RunCMake/find_package/MissingNormalWarnNoModuleOld.cmake
index 1c4a775..1c4a775 100644
--- a/Tests/CMakeCommands/find_package/MissingNormalWarnNoModuleOld.cmake
+++ b/Tests/RunCMake/find_package/MissingNormalWarnNoModuleOld.cmake
diff --git a/Tests/RunCMake/find_package/MixedModeOptions-result.txt b/Tests/RunCMake/find_package/MixedModeOptions-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_package/MixedModeOptions-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/CMakeCommands/find_package/MixedModeOptions-stderr.txt b/Tests/RunCMake/find_package/MixedModeOptions-stderr.txt
index b867022..b867022 100644
--- a/Tests/CMakeCommands/find_package/MixedModeOptions-stderr.txt
+++ b/Tests/RunCMake/find_package/MixedModeOptions-stderr.txt
diff --git a/Tests/CMakeCommands/find_package/MixedModeOptions.cmake b/Tests/RunCMake/find_package/MixedModeOptions.cmake
index 7f78ee0..7f78ee0 100644
--- a/Tests/CMakeCommands/find_package/MixedModeOptions.cmake
+++ b/Tests/RunCMake/find_package/MixedModeOptions.cmake
diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake
new file mode 100644
index 0000000..42705b7
--- /dev/null
+++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake
@@ -0,0 +1,16 @@
+include(RunCMake)
+
+run_cmake(ComponentRequiredAndOptional)
+run_cmake(MissingNormal)
+run_cmake(MissingNormalRequired)
+run_cmake(MissingNormalVersion)
+run_cmake(MissingNormalWarnNoModuleOld)
+run_cmake(MissingNormalWarnNoModuleNew)
+run_cmake(MissingModule)
+run_cmake(MissingModuleRequired)
+run_cmake(MissingConfig)
+run_cmake(MissingConfigOneName)
+run_cmake(MissingConfigRequired)
+run_cmake(MissingConfigVersion)
+run_cmake(MixedModeOptions)
+run_cmake(SetFoundFALSE)
diff --git a/Tests/RunCMake/find_package/SetFoundFALSE-stderr.txt b/Tests/RunCMake/find_package/SetFoundFALSE-stderr.txt
new file mode 100644
index 0000000..695f645
--- /dev/null
+++ b/Tests/RunCMake/find_package/SetFoundFALSE-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning at SetFoundFALSE.cmake:2 \(find_package\):
+ Found package configuration file:
+
+ .*/Tests/RunCMake/find_package/SetFoundFALSEConfig.cmake
+
+ but it set SetFoundFALSE_FOUND to FALSE so package "SetFoundFALSE" is
+ considered to be NOT FOUND.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/find_package/SetFoundFALSE.cmake b/Tests/RunCMake/find_package/SetFoundFALSE.cmake
new file mode 100644
index 0000000..fbcec3c
--- /dev/null
+++ b/Tests/RunCMake/find_package/SetFoundFALSE.cmake
@@ -0,0 +1,2 @@
+set(SetFoundFALSE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+find_package(SetFoundFALSE CONFIG)
diff --git a/Tests/RunCMake/find_package/SetFoundFALSEConfig.cmake b/Tests/RunCMake/find_package/SetFoundFALSEConfig.cmake
new file mode 100644
index 0000000..ae6bd14
--- /dev/null
+++ b/Tests/RunCMake/find_package/SetFoundFALSEConfig.cmake
@@ -0,0 +1 @@
+set(SetFoundFALSE_FOUND FALSE)
diff --git a/Tests/SBCS/CMakeLists.txt b/Tests/SBCS/CMakeLists.txt
new file mode 100644
index 0000000..b3c3c2c
--- /dev/null
+++ b/Tests/SBCS/CMakeLists.txt
@@ -0,0 +1,6 @@
+# a SBCS test case
+project (SBCS)
+
+add_definitions(-D_SBCS)
+
+add_executable (SBCS SBCS.cxx)
diff --git a/Tests/SBCS/SBCS.cxx b/Tests/SBCS/SBCS.cxx
new file mode 100644
index 0000000..6ce2c9f
--- /dev/null
+++ b/Tests/SBCS/SBCS.cxx
@@ -0,0 +1,22 @@
+// Test to verify that _SBCS being defined causes CharacterSet to be set to 0 (Single Byte Character Set)
+
+int main ()
+{
+#ifdef _UNICODE
+ bool UnicodeSet=true;
+#else
+ bool UnicodeSet=false;
+#endif
+
+#ifdef _MBCS
+ bool MBCSSet=true;
+#else
+ bool MBCSSet=false;
+#endif
+
+ // if neither _UNICODE nor _MBCS is set, CharacterSet must be set to SBCS.
+ bool SBCSSet=(!UnicodeSet && !MBCSSet);
+
+ // Reverse boolean to indicate error case correctly
+ return !SBCSSet;
+}
diff --git a/Utilities/.gitattributes b/Utilities/.gitattributes
new file mode 100644
index 0000000..e3a9e61
--- /dev/null
+++ b/Utilities/.gitattributes
@@ -0,0 +1,2 @@
+/Git export-ignore
+SetupForDevelopment.sh export-ignore
diff --git a/Utilities/GitSetup/.gitattributes b/Utilities/GitSetup/.gitattributes
new file mode 100644
index 0000000..facbbb2
--- /dev/null
+++ b/Utilities/GitSetup/.gitattributes
@@ -0,0 +1,7 @@
+.git* export-ignore
+
+# Exclude from source archives files specific to Git work tree.
+* export-ignore
+
+tips eol=lf whitespace=indent-with-non-tab
+setup-* eol=lf whitespace=indent-with-non-tab
diff --git a/Utilities/GitSetup/LICENSE b/Utilities/GitSetup/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/Utilities/GitSetup/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/Utilities/GitSetup/NOTICE b/Utilities/GitSetup/NOTICE
new file mode 100644
index 0000000..0d32c02
--- /dev/null
+++ b/Utilities/GitSetup/NOTICE
@@ -0,0 +1,5 @@
+Kitware Local Git Setup Scripts
+Copyright 2010-2012 Kitware, Inc.
+
+This product includes software developed at Kitware, Inc.
+(http://www.kitware.com/).
diff --git a/Utilities/GitSetup/README b/Utilities/GitSetup/README
new file mode 100644
index 0000000..cf468fb
--- /dev/null
+++ b/Utilities/GitSetup/README
@@ -0,0 +1,80 @@
+Kitware Local Git Setup Scripts
+
+
+Introduction
+------------
+
+This is a collection of local Git development setup scripts meant for
+inclusion in project source trees to aid their development workflow.
+Project-specific information needed by the scripts may be configured
+in a "config" file added next to them in the project.
+
+
+Import
+------
+
+A project may import these scripts into their source tree by
+initializing a subtree merge. Bring up a Git prompt and set the
+current working directory inside a clone of the target project.
+Fetch the "setup" branch from the GitSetup repository:
+
+ $ git fetch ../GitSetup setup:setup
+
+Prepare to merge the branch but place the content in a subdirectory.
+Any prefix (with trailing '/') may be chosen so long as it is used
+consistently within a project through the rest of these instructions:
+
+ $ git merge -s ours --no-commit setup
+ $ git read-tree -u --prefix=Utilities/GitSetup/ setup
+
+Commit the merge with an informative message:
+
+ $ git commit
+ ------------------------------------------------------------------------
+ Merge branch 'setup'
+
+ Add Utilities/GitSetup/ directory using subtree merge from
+ the general GitSetup repository "setup" branch.
+ ------------------------------------------------------------------------
+
+
+Configuration
+-------------
+
+Read the "Project configuration instructions" comment in each script.
+Add a "config" file next to the scripts with desired configuration
+(optionally copy and modify "config.sample"). For example, to
+configure the "setup-hooks" script:
+
+ $ git config -f Utilities/GitSetup/config hooks.url "$url"
+
+where "$url" is the project repository publishing the "hooks" branch.
+When finished, add and commit the configuration file:
+
+ $ git add Utilities/GitSetup/config
+ $ git commit
+
+
+Update
+------
+
+A project may update these scripts from the GitSetup repository.
+Bring up a Git prompt and set the current working directory inside a
+clone of the target project. Fetch the "setup" branch from the
+GitSetup repository:
+
+ $ git fetch ../GitSetup setup:setup
+
+Merge the "setup" branch into the subtree:
+
+ $ git merge -X subtree=Utilities/GitSetup setup
+
+where "Utilities/GitSetup" is the same prefix used during the import
+setup, but without a trailing '/'.
+
+
+License
+-------
+
+Distributed under the Apache License 2.0.
+See LICENSE and NOTICE for details.
diff --git a/Utilities/GitSetup/config b/Utilities/GitSetup/config
new file mode 100644
index 0000000..b7d5423
--- /dev/null
+++ b/Utilities/GitSetup/config
@@ -0,0 +1,9 @@
+[hooks]
+ url = http://cmake.org/cmake.git
+[ssh]
+ host = cmake.org
+ key = id_git_cmake
+ request-url = https://www.kitware.com/Admin/SendPassword.cgi
+[stage]
+ url = git://cmake.org/stage/cmake.git
+ pushurl = git@cmake.org:stage/cmake.git
diff --git a/Utilities/GitSetup/config.sample b/Utilities/GitSetup/config.sample
new file mode 100644
index 0000000..bba2382
--- /dev/null
+++ b/Utilities/GitSetup/config.sample
@@ -0,0 +1,22 @@
+# Kitware Local Git Setup Scripts - Sample Project Configuration
+#
+# Copy to "config" and edit as necessary.
+
+[hooks]
+ url = http://public.kitware.com/GitSetup.git
+ #branch = hooks
+
+[ssh]
+ host = public.kitware.com
+ key = id_git_public
+ request-url = https://www.kitware.com/Admin/SendPassword.cgi
+
+[stage]
+ #url = git://public.kitware.com/stage/Project.git
+ #pushurl = git@public.kitware.com:stage/Project.git
+
+[gerrit]
+ #project = Project
+ site = http://review.source.kitware.com
+ # pushurl placeholder "$username" is literal
+ pushurl = $username@review.source.kitware.com:Project
diff --git a/Utilities/GitSetup/setup-gerrit b/Utilities/GitSetup/setup-gerrit
new file mode 100755
index 0000000..9e8fa62
--- /dev/null
+++ b/Utilities/GitSetup/setup-gerrit
@@ -0,0 +1,142 @@
+#!/usr/bin/env bash
+#=============================================================================
+# Copyright 2010-2012 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+# Run this script to set up the local Git repository to push to
+# a Gerrit Code Review instance for this project.
+
+# Project configuration instructions:
+#
+# - Run a Gerrit Code Review server
+#
+# - Populate adjacent "config" file with:
+# gerrit.site = Top Gerrit URL (not project-specific)
+# gerrit.project = Name of project in Gerrit
+# gerrit.pushurl = Review site push URL with "$username" placeholder
+# gerrit.remote = Gerrit remote name, if not "gerrit"
+# gerrit.url = Gerrit project URL, if not "$site/p/$project"
+
+die() {
+ echo 1>&2 "$@" ; exit 1
+}
+
+# Make sure we are inside the repository.
+cd "${BASH_SOURCE%/*}" &&
+
+# Load the project configuration.
+site=$(git config -f config --get gerrit.site) &&
+project=$(git config -f config --get gerrit.project) &&
+pushurl_=$(git config -f config --get gerrit.pushurl) &&
+remote=$(git config -f config --get gerrit.remote ||
+ echo "gerrit") &&
+fetchurl=$(git config -f config --get gerrit.url ||
+ echo "$site/p/$project") ||
+die 'This project is not configured to use Gerrit.'
+
+# Get current gerrit push URL.
+pushurl=$(git config --get remote."$remote".pushurl ||
+ git config --get remote."$remote".url || echo '') &&
+
+# Tell user about current configuration.
+if test -n "$pushurl"; then
+ echo 'Remote "'"$remote"'" is currently configured to push to
+
+ '"$pushurl"'
+' &&
+ read -ep 'Reconfigure Gerrit? [y/N]: ' ans &&
+ if [ "$ans" == "y" ] || [ "$ans" == "Y" ]; then
+ setup=1
+ else
+ setup=''
+ fi
+else
+ echo 'Remote "'"$remote"'" is not yet configured.
+
+'"$project"' changes must be pushed to our Gerrit Code Review site:
+
+ '"$fetchurl"'
+
+Register a Gerrit account and select a username (used below).
+You will need an OpenID:
+
+ http://openid.net/get-an-openid/
+' &&
+ read -ep 'Configure Gerrit? [Y/n]: ' ans &&
+ if [ "$ans" == "n" ] || [ "$ans" == "N" ]; then
+ exit 0
+ else
+ setup=1
+ fi
+fi &&
+
+# Perform setup if necessary.
+if test -n "$setup"; then
+ echo 'Sign-in to Gerrit to get/set your username at
+
+ '"$site"'/#/settings
+
+Add your SSH public keys at
+
+ '"$site"'/#/settings/ssh-keys
+' &&
+ read -ep "Gerrit username? [$USER]: " gu &&
+ if test -z "$gu"; then
+ gu="$USER"
+ fi &&
+ if test -z "$pushurl"; then
+ git remote add "$remote" "$fetchurl"
+ else
+ git config remote."$remote".url "$fetchurl"
+ fi &&
+ pushurl="${pushurl_/\$username/$gu}" &&
+ git config remote."$remote".pushurl "$pushurl" &&
+ echo 'Remote "'"$remote"'" is now configured to push to
+
+ '"$pushurl"'
+'
+fi &&
+
+# Optionally test Gerrit access.
+if test -n "$pushurl"; then
+ read -ep 'Test access to Gerrit (SSH)? [y/N]: ' ans &&
+ if [ "$ans" == "y" ] || [ "$ans" == "Y" ]; then
+ echo -n 'Testing Gerrit access by SSH...'
+ if git ls-remote --heads "$pushurl" >/dev/null; then
+ echo 'passed.'
+ else
+ echo 'failed.' &&
+ die 'Could not access Gerrit. Add your SSH public keys at
+
+ '"$site"'/#/settings/ssh-keys
+'
+ fi
+ fi
+fi &&
+
+# Set up GerritId hook.
+hook=$(git config --get hooks.GerritId || echo '') &&
+if test -z "$hook"; then
+ echo '
+Enabling GerritId hook to add a "Change-Id" footer to commit
+messages for interaction with Gerrit. Run
+
+ git config hooks.GerritId false
+
+to disable this feature (but you will be on your own).' &&
+ git config hooks.GerritId true
+else
+ echo 'GerritId hook already configured to "'"$hook"'".'
+fi
diff --git a/Utilities/GitSetup/setup-hooks b/Utilities/GitSetup/setup-hooks
new file mode 100755
index 0000000..c07985a
--- /dev/null
+++ b/Utilities/GitSetup/setup-hooks
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+#=============================================================================
+# Copyright 2010-2012 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+# Run this script to set up local Git hooks for this project.
+
+# Project configuration instructions:
+#
+# - Publish a "hooks" branch in the project repository such that
+# clones will have "refs/remotes/origin/hooks".
+#
+# - Populate adjacent "config" file with:
+# hooks.url = Repository URL publishing "hooks" branch
+# hooks.branch = Repository branch instead of "hooks"
+
+egrep-q() {
+ egrep "$@" >/dev/null 2>/dev/null
+}
+
+die() {
+ echo 1>&2 "$@" ; exit 1
+}
+
+# Make sure we are inside the repository.
+cd "${BASH_SOURCE%/*}" &&
+
+# Select a hooks branch.
+if url=$(git config --get hooks.url); then
+ # Fetch hooks from locally configured repository.
+ branch=$(git config hooks.branch || echo hooks)
+elif git for-each-ref refs/remotes/origin/hooks 2>/dev/null |
+ egrep-q 'refs/remotes/origin/hooks$'; then
+ # Use hooks cloned from origin.
+ url=.. && branch=remotes/origin/hooks
+elif url=$(git config -f config --get hooks.url); then
+ # Fetch hooks from project-configured repository.
+ branch=$(git config -f config hooks.branch || echo hooks)
+else
+ die 'This project is not configured to install local hooks.'
+fi &&
+
+# Populate ".git/hooks".
+echo 'Setting up git hooks...' &&
+git_dir=$(git rev-parse --git-dir) &&
+cd "$git_dir/hooks" &&
+if ! test -e .git; then
+ git init -q || die 'Could not run git init for hooks.'
+fi &&
+git fetch -q "$url" "$branch" &&
+git reset -q --hard FETCH_HEAD || die 'Failed to install hooks'
diff --git a/Utilities/GitSetup/setup-ssh b/Utilities/GitSetup/setup-ssh
new file mode 100755
index 0000000..8920a5b
--- /dev/null
+++ b/Utilities/GitSetup/setup-ssh
@@ -0,0 +1,111 @@
+#!/usr/bin/env bash
+#=============================================================================
+# Copyright 2010-2012 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+# Run this script to set up ssh push access to the repository host.
+
+# Project configuration instructions:
+#
+# - Populate adjacent "config" file with:
+# ssh.host = Repository host name
+# ssh.user = Username on host, if not "git"
+# ssh.key = Local ssh key name
+# ssh.request-url = Web page URL to request ssh access
+
+egrep-q() {
+ egrep "$@" >/dev/null 2>/dev/null
+}
+
+die() {
+ echo 1>&2 "$@" ; exit 1
+}
+
+# Make sure we are inside the repository.
+cd "${BASH_SOURCE%/*}" &&
+
+# Load the project configuration.
+host=$(git config -f config --get ssh.host) &&
+user=$(git config -f config --get ssh.user || echo git) &&
+key=$(git config -f config --get ssh.key) &&
+request_url=$(git config -f config --get ssh.request-url) ||
+die 'This project is not configured for ssh push access.'
+
+# Check for existing configuration.
+if test -r ~/.ssh/config &&
+ egrep-q 'Host[= ]'"${host//\./\\.}" ~/.ssh/config; then
+ echo 'Host "'"$host"'" is already in ~/.ssh/config' &&
+ setup= &&
+ question='Test'
+else
+ echo 'Host "'"$host"'" not found in ~/.ssh/config' &&
+ setup=1 &&
+ question='Setup and test'
+fi &&
+
+# Ask the user whether to make changes.
+echo '' &&
+read -ep "${question} push access by ssh to $user@$host? [y/N]: " access &&
+if test "$access" != "y" -a "$access" != "Y"; then
+ exit 0
+fi &&
+
+# Setup host configuration if necessary.
+if test -n "$setup"; then
+ if ! test -d ~/.ssh; then
+ mkdir -p ~/.ssh &&
+ chmod 700 ~/.ssh
+ fi &&
+ if ! test -f ~/.ssh/config; then
+ touch ~/.ssh/config &&
+ chmod 600 ~/.ssh/config
+ fi &&
+ ssh_config='Host='"$host"'
+ IdentityFile ~/.ssh/'"$key" &&
+ echo "Adding to ~/.ssh/config:
+
+$ssh_config
+" &&
+ echo "$ssh_config" >> ~/.ssh/config &&
+ if ! test -e ~/.ssh/"$key"; then
+ if test -f ~/.ssh/id_rsa; then
+ # Take care of the common case.
+ ln -s id_rsa ~/.ssh/"$key"
+ echo '
+Assuming ~/.ssh/id_rsa is the private key corresponding to the public key for
+
+ '"$user@$host"'
+
+If this is incorrect place private key at "~/.ssh/'"$key"'".'
+ else
+ echo '
+Place the private key corresponding to the public key registered for
+
+ '"$user@$host"'
+
+at "~/.ssh/'"$key"'".'
+ fi
+ read -e -n 1 -p 'Press any key to continue...'
+ fi
+fi || exit 1
+
+# Test access configuration.
+echo 'Testing ssh push access to "'"$user@$host"'"...' &&
+if ! ssh "$user@$host" info; then
+ die 'No ssh push access to "'"$user@$host"'". You may need to request access at
+
+ '"$request_url"'
+'
+fi
diff --git a/Utilities/GitSetup/setup-stage b/Utilities/GitSetup/setup-stage
new file mode 100755
index 0000000..ef53b99
--- /dev/null
+++ b/Utilities/GitSetup/setup-stage
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+#=============================================================================
+# Copyright 2010-2012 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+# Run this script to set up the topic stage for pushing changes.
+
+# Project configuration instructions:
+#
+# - Run a Topic Stage repository next to the main project repository.
+#
+# - Populate adjacent "config" file with:
+# stage.url = Topic Stage repository URL
+# stage.pushurl = Topic Stage push URL if not "$url"
+
+egrep-q() {
+ egrep "$@" >/dev/null 2>/dev/null
+}
+
+die() {
+ echo 1>&2 "$@" ; exit 1
+}
+
+# Make sure we are inside the repository.
+cd "${BASH_SOURCE%/*}" &&
+
+# Load the project configuration.
+url=$(git config -f config --get stage.url) &&
+pushurl=$(git config -f config --get stage.pushurl || echo '') ||
+die 'This project is not configured to use a topic stage.'
+
+# Configure the remote if necessary.
+if git config remote.stage.url >/dev/null; then
+ echo 'Topic stage already configured.'
+else
+ echo 'Setting up the topic stage...' &&
+ git remote add stage "$url" &&
+ if test -n "$pushurl"; then
+ git config remote.stage.pushurl "$pushurl"
+ fi
+fi || die 'Could not add the topic stage remote.'
diff --git a/Utilities/GitSetup/setup-user b/Utilities/GitSetup/setup-user
new file mode 100755
index 0000000..1af439c
--- /dev/null
+++ b/Utilities/GitSetup/setup-user
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+#=============================================================================
+# Copyright 2010-2012 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+# Run this script to configure Git user info in this repository.
+
+# Project configuration instructions: NONE
+
+for (( ; ; )); do
+ user_name=$(git config user.name || echo '') &&
+ user_email=$(git config user.email || echo '') &&
+ if test -n "$user_name" -a -n "$user_email"; then
+ echo 'Your commits will record as Author:
+
+ '"$user_name <$user_email>"'
+' &&
+ read -ep 'Is the author name and email address above correct? [Y/n] ' correct &&
+ if test "$correct" != "n" -a "$correct" != "N"; then
+ break
+ fi
+ fi &&
+ read -ep 'Enter your full name e.g. "John Doe": ' name &&
+ read -ep 'Enter your email address e.g. "john@gmail.com": ' email &&
+ git config user.name "$name" &&
+ git config user.email "$email"
+done
diff --git a/Utilities/GitSetup/tips b/Utilities/GitSetup/tips
new file mode 100755
index 0000000..784e1ed
--- /dev/null
+++ b/Utilities/GitSetup/tips
@@ -0,0 +1,55 @@
+#!/usr/bin/env bash
+#=============================================================================
+# Copyright 2010-2012 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+# This script makes optional suggestions for working with Git.
+
+# Project configuration instructions: NONE
+
+egrep-q() {
+ egrep "$@" >/dev/null 2>/dev/null
+}
+
+# Suggest color configuration.
+if test -z "$(git config --get color.ui)"; then
+ echo '
+One may enable color output from Git commands with
+
+ git config --global color.ui auto
+'
+fi
+
+# Suggest bash completion.
+if ! bash -i -c 'echo $PS1' | egrep-q '__git_ps1'; then
+ echo '
+A dynamic, informative Git shell prompt can be obtained by sourcing
+the git bash-completion script in your "~/.bashrc". Set the PS1
+environmental variable as suggested in the comments at the top of the
+bash-completion script. You may need to install the bash-completion
+package from your distribution to obtain it.
+'
+fi
+
+# Suggest merge tool.
+if test -z "$(git config --get merge.tool)"; then
+ echo '
+One may configure Git to load a merge tool with
+
+ git config merge.tool <toolname>
+
+See "git help mergetool" for more information.
+'
+fi
diff --git a/Utilities/KWIML/test/test_INT_format.h.in b/Utilities/KWIML/test/test_INT_format.h.in
index 72a62f2..71b443d 100644
--- a/Utilities/KWIML/test/test_INT_format.h.in
+++ b/Utilities/KWIML/test/test_INT_format.h.in
@@ -18,17 +18,15 @@
# define LANG "C "
#endif
-#define VALUE(T, U) \
- (@KWIML@_INT_##T)((@KWIML@_INT_##U)0xab << \
- ((sizeof(@KWIML@_INT_##T)-1)<<3)) \
+#define VALUE(T, U) (T)((U)0xab << ((sizeof(T)-1)<<3))
-#define TEST_C(C, V, PRI, T, U) \
+#define TEST_C_(C, V, PRI, T, U) \
{ \
- @KWIML@_INT_##T const x = VALUE(T, U); \
- @KWIML@_INT_##T y = @KWIML@_INT_##C(V); \
- printf(LANG "@KWIML@_INT_" #C ":" \
- " expression [%"@KWIML@_INT_PRI##PRI"]," \
- " literal [%"@KWIML@_INT_PRI##PRI"]", x, y); \
+ T const x = VALUE(T, U); \
+ T y = C(V); \
+ printf(LANG #C ":" \
+ " expression [%" @KWIML@_INT_PRI##PRI "]," \
+ " literal [%" @KWIML@_INT_PRI##PRI "]", x, y); \
if(x == y) \
{ \
printf(", PASSED\n"); \
@@ -40,11 +38,11 @@
} \
}
-#define TEST_PRI(PRI, T, U, STR) \
+#define TEST_PRI_(PRI, T, U, STR) \
{ \
- @KWIML@_INT_##T const x = VALUE(T, U); \
+ T const x = VALUE(T, U); \
char const* str = STR; \
- sprintf(buf, "%"@KWIML@_INT_PRI##PRI, x); \
+ sprintf(buf, "%" @KWIML@_INT_PRI##PRI, x); \
printf(LANG "@KWIML@_INT_PRI" #PRI ":" \
" expected [%s], got [%s]", str, buf); \
if(strcmp(str, buf) == 0) \
@@ -58,19 +56,19 @@
} \
}
-#define TEST_SCN(SCN, T, U, STR) TEST_SCN2(SCN, SCN, T, U, STR)
-#define TEST_SCN2(PRI, SCN, T, U, STR) \
+#define TEST_SCN_(SCN, T, U, STR) TEST_SCN2_(SCN, SCN, T, U, STR)
+#define TEST_SCN2_(PRI, SCN, T, U, STR) \
{ \
- @KWIML@_INT_##T const x = VALUE(T, U); \
- @KWIML@_INT_##T y; \
+ T const x = VALUE(T, U); \
+ T y; \
char const* str = STR; \
- if(sscanf(str, "%"@KWIML@_INT_SCN##SCN, &y) != 1) \
+ if(sscanf(str, "%" @KWIML@_INT_SCN##SCN, &y) != 1) \
{ \
y = 0; \
} \
printf(LANG "@KWIML@_INT_SCN" #SCN ":" \
- " expected [%"@KWIML@_INT_PRI##PRI"]," \
- " got [%"@KWIML@_INT_PRI##PRI"]", x, y); \
+ " expected [%" @KWIML@_INT_PRI##PRI "]," \
+ " got [%" @KWIML@_INT_PRI##PRI "]", x, y); \
if(x == y) \
{ \
printf(", PASSED\n"); \
@@ -82,10 +80,24 @@
} \
}
-#define TEST(FMT, T, U, STR) TEST2(FMT, FMT, T, U, STR)
-#define TEST2(PRI, SCN, T, U, STR) \
- TEST_PRI(PRI, T, U, STR) \
- TEST_SCN2(PRI, SCN, T, U, STR)
+#define TEST_(FMT, T, U, STR) TEST2_(FMT, FMT, T, U, STR)
+#define TEST2_(PRI, SCN, T, U, STR) \
+ TEST_PRI_(PRI, T, U, STR) \
+ TEST_SCN2_(PRI, SCN, T, U, STR)
+
+/* Concatenate T and U now to avoid expanding them. */
+#define TEST(FMT, T, U, STR) \
+ TEST_(FMT, @KWIML@_INT_##T, @KWIML@_INT_##U, STR)
+#define TEST2(PRI, SCN, T, U, STR) \
+ TEST2_(PRI, SCN, @KWIML@_INT_##T, @KWIML@_INT_##U, STR)
+#define TEST_C(C, V, PRI, T, U) \
+ TEST_C_(@KWIML@_INT_##C, V, PRI, @KWIML@_INT_##T, @KWIML@_INT_##U)
+#define TEST_PRI(PRI, T, U, STR) \
+ TEST_PRI_(PRI, @KWIML@_INT_##T, @KWIML@_INT_##U, STR)
+#define TEST_SCN(SCN, T, U, STR) \
+ TEST_SCN_(SCN, @KWIML@_INT_##T, @KWIML@_INT_##U, STR)
+#define TEST_SCN2(PRI, SCN, T, U, STR) \
+ TEST_SCN2_(PRI, SCN, @KWIML@_INT_##T, @KWIML@_INT_##U, STR)
static int test_INT_format(void)
{
diff --git a/Utilities/Release/Cygwin/cygwin-setup.hint.in b/Utilities/Release/Cygwin/cygwin-setup.hint.in
index 9706c0d..a2532fc 100644
--- a/Utilities/Release/Cygwin/cygwin-setup.hint.in
+++ b/Utilities/Release/Cygwin/cygwin-setup.hint.in
@@ -1,5 +1,5 @@
# CMake setup.hint file for cygwin setup.exe program
-category: Devel
-requires: @CMAKE_NCURSES_VERSION@ cygwin
-sdesc: "A cross platform build manager"
-ldesc: "CMake is a cross platform build manager. It allows you to specify build parameters for C and C++ programs in a cross platform manner. For cygwin Makefiles will be generated. CMake is also capable of generating microsoft project files, nmake, and borland makefiles. CMake can also perform system inspection operations like finding installed libraries and header files."
+category: Devel
+requires: libgcc1 libidn11 @CMAKE_NCURSES_VERSION@ libstdc++6
+sdesc: "A cross platform build manager"
+ldesc: "CMake is a cross platform build manager. It allows you to specify build parameters for C and C++ programs in a cross platform manner. For cygwin Makefiles will be generated. CMake is also capable of generating microsoft project files, nmake, and borland makefiles. CMake can also perform system inspection operations like finding installed libraries and header files."
diff --git a/Utilities/SetupForDevelopment.sh b/Utilities/SetupForDevelopment.sh
new file mode 100755
index 0000000..0a9df7e
--- /dev/null
+++ b/Utilities/SetupForDevelopment.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+cd "${BASH_SOURCE%/*}/.." &&
+Utilities/GitSetup/setup-user && echo &&
+Utilities/GitSetup/setup-hooks && echo &&
+Utilities/GitSetup/setup-stage && echo &&
+(Utilities/GitSetup/setup-ssh ||
+ echo 'Failed to setup SSH. Run this again to retry.') && echo &&
+Utilities/GitSetup/tips
+
+# Rebase master by default
+git config rebase.stat true
+git config branch.master.rebase true
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 29ce25d6..caa44f1 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -126,9 +126,9 @@ IF(CURL_MALLOC_DEBUG)
ENDIF(CURL_MALLOC_DEBUG)
# On windows preload settings
-IF(WIN32)
+IF(WIN32 AND NOT MINGW)
INCLUDE(${LIBCURL_SOURCE_DIR}/Platforms/WindowsCache.cmake)
-ENDIF(WIN32)
+ENDIF()
# This macro checks if the symbol exists in the library and if it
# does, it appends library to the list.
diff --git a/bootstrap b/bootstrap
index 665c6c5..0069754 100755
--- a/bootstrap
+++ b/bootstrap
@@ -18,18 +18,11 @@ die() {
# Version number extraction function.
cmake_version_component()
{
- cat "${cmake_source_dir}/CMakeLists.txt" | sed -n "
+ cat "${cmake_source_dir}/Source/CMakeVersion.cmake" | sed -n "
/^SET(CMake_VERSION_${1}/ {s/SET(CMake_VERSION_${1} *\([0-9]*\))/\1/;p;}
"
}
-cmake_date_stamp_component()
-{
- cat "${cmake_source_dir}/Source/kwsys/kwsysDateStamp.cmake" | sed -n "
-/KWSYS_DATE_STAMP_${1}/ {s/^.* \([0-9][0-9]*\))$/\1/;p;}
-"
-}
-
cmake_toupper()
{
echo "$1" | sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'
@@ -46,9 +39,6 @@ cmake_version_minor="`cmake_version_component MINOR`"
cmake_version_patch="`cmake_version_component PATCH`"
cmake_version="${cmake_version_major}.${cmake_version_minor}.${cmake_version_patch}"
cmake_version_tweak="`cmake_version_component TWEAK`"
-if [ "x$cmake_version_tweak" = "x" ]; then
- cmake_version_tweak="`cmake_date_stamp_component YEAR``cmake_date_stamp_component MONTH``cmake_date_stamp_component DAY`"
-fi
if [ "$cmake_version_tweak" != "0" ]; then
cmake_version="${cmake_version}.${cmake_version_tweak}"
fi
@@ -208,6 +198,7 @@ CMAKE_CXX_SOURCES="\
cmExportInstallFileGenerator \
cmInstallDirectoryGenerator \
cmGeneratedFileStream \
+ cmGeneratorTarget \
cmGeneratorExpression \
cmGlobalGenerator \
cmLocalGenerator \