summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.rst2
-rw-r--r--CompileFlags.cmake23
-rw-r--r--Help/command/COMPILE_OPTIONS_SHELL.txt9
-rw-r--r--Help/command/FIND_XXX.txt29
-rw-r--r--Help/command/add_compile_options.rst2
-rw-r--r--Help/command/add_library.rst8
-rw-r--r--Help/command/export.rst9
-rw-r--r--Help/command/file.rst17
-rw-r--r--Help/command/find_file.rst3
-rw-r--r--Help/command/find_library.rst3
-rw-r--r--Help/command/find_package.rst24
-rw-r--r--Help/command/find_path.rst3
-rw-r--r--Help/command/find_program.rst2
-rw-r--r--Help/command/install.rst7
-rw-r--r--Help/command/list.rst169
-rw-r--r--Help/command/project.rst24
-rw-r--r--Help/command/string.rst29
-rw-r--r--Help/command/target_compile_options.rst2
-rw-r--r--Help/command/target_link_libraries.rst64
-rw-r--r--Help/manual/cmake-buildsystem.7.rst41
-rw-r--r--Help/manual/cmake-developer.7.rst2
-rw-r--r--Help/manual/cmake-generator-expressions.7.rst7
-rw-r--r--Help/manual/cmake-policies.7.rst9
-rw-r--r--Help/manual/cmake-properties.7.rst4
-rw-r--r--Help/manual/cmake-variables.7.rst5
-rw-r--r--Help/manual/ctest.1.rst24
-rw-r--r--Help/policy/CMP0073.rst25
-rw-r--r--Help/policy/CMP0074.rst22
-rw-r--r--Help/prop_dir/TESTS.rst7
-rw-r--r--Help/prop_test/PROCESSORS.rst3
-rw-r--r--Help/prop_test/PROCESSOR_AFFINITY.rst11
-rw-r--r--Help/prop_test/WORKING_DIRECTORY.rst6
-rw-r--r--Help/prop_tgt/EXPORT_PROPERTIES.rst14
-rw-r--r--Help/prop_tgt/VS_DEBUGGER_COMMAND.rst9
-rw-r--r--Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst3
-rw-r--r--Help/release/dev/0-sample-topic.rst7
-rw-r--r--Help/release/dev/UseSWIG-modernize-module.rst6
-rw-r--r--Help/release/dev/avoid-LIB_DEPENDS.rst5
-rw-r--r--Help/release/dev/compile-options-shell.rst6
-rw-r--r--Help/release/dev/ctest-affinity.rst6
-rw-r--r--Help/release/dev/curl-target.rst4
-rw-r--r--Help/release/dev/directory-property-TESTS.rst5
-rw-r--r--Help/release/dev/export-properties.rst6
-rw-r--r--Help/release/dev/file_cmd_touch.rst6
-rw-r--r--Help/release/dev/find-package_root-restore.rst8
-rw-r--r--Help/release/dev/genex-IN_LIST-logical-operator.rst5
-rw-r--r--Help/release/dev/genex-TARGET_EXISTS.rst6
-rw-r--r--Help/release/dev/libxml2-target.rst4
-rw-r--r--Help/release/dev/object-library-linking.rst6
-rw-r--r--Help/release/dev/project-homepage.rst7
-rw-r--r--Help/release/dev/string-join.rst5
-rw-r--r--Help/release/dev/variable-CMAKE_SUPPRESS_REGENERATION.rst6
-rw-r--r--Help/release/dev/vs-debugger-config.rst6
-rw-r--r--Help/release/index.rst2
-rw-r--r--Help/variable/CMAKE_PROJECT_DESCRIPTION.rst34
-rw-r--r--Help/variable/CMAKE_PROJECT_HOMEPAGE_URL.rst35
-rw-r--r--Help/variable/CMAKE_PROJECT_NAME.rst34
-rw-r--r--Help/variable/CMAKE_SUPPRESS_REGENERATION.rst11
-rw-r--r--Help/variable/PROJECT-NAME_DESCRIPTION.rst5
-rw-r--r--Help/variable/PROJECT-NAME_HOMEPAGE_URL.rst5
-rw-r--r--Help/variable/PROJECT_DESCRIPTION.rst5
-rw-r--r--Help/variable/PROJECT_HOMEPAGE_URL.rst9
-rw-r--r--Help/variable/PROJECT_NAME.rst4
-rw-r--r--Modules/CMakeDetermineFortranCompiler.cmake20
-rw-r--r--Modules/CMakeFindBinUtils.cmake19
-rw-r--r--Modules/CMakeTestCSharpCompiler.cmake2
-rw-r--r--Modules/CMakeTestCUDACompiler.cmake2
-rw-r--r--Modules/CMakeTestCXXCompiler.cmake2
-rw-r--r--Modules/CMakeTestFortranCompiler.cmake2
-rw-r--r--Modules/CMakeTestJavaCompiler.cmake2
-rw-r--r--Modules/CMakeTestRCCompiler.cmake2
-rw-r--r--Modules/CMakeTestSwiftCompiler.cmake2
-rw-r--r--Modules/CPackDeb.cmake7
-rw-r--r--Modules/CPackFreeBSD.cmake4
-rw-r--r--Modules/CPackNSIS.cmake2
-rw-r--r--Modules/CPackRPM.cmake8
-rw-r--r--Modules/CheckCSourceRuns.cmake11
-rw-r--r--Modules/ExternalData.cmake2
-rw-r--r--Modules/FindCUDA.cmake10
-rw-r--r--Modules/FindCURL.cmake34
-rw-r--r--Modules/FindGDAL.cmake46
-rw-r--r--Modules/FindJava.cmake8
-rw-r--r--Modules/FindLibXml2.cmake12
-rw-r--r--Modules/FindLua.cmake1
-rw-r--r--Modules/FindOpenMP.cmake30
-rw-r--r--Modules/FindZLIB.cmake4
-rw-r--r--Modules/FindwxWidgets.cmake2
-rw-r--r--Modules/GenerateExportHeader.cmake47
-rw-r--r--Modules/Platform/Windows-MSVC.cmake28
-rw-r--r--Modules/UseJava.cmake2
-rw-r--r--Modules/UseSWIG.cmake485
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/CMakeVersion.cmake4
-rw-r--r--Source/CMakeVersionCompute.cmake7
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx16
-rw-r--r--Source/CPack/cmCPackGenerator.cxx8
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx22
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx22
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx16
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx47
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h2
-rw-r--r--Source/CTest/cmCTestRunTest.cxx54
-rw-r--r--Source/CTest/cmCTestRunTest.h5
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx2
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx19
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx11
-rw-r--r--Source/CTest/cmCTestTestHandler.h2
-rw-r--r--Source/CTest/cmProcess.cxx18
-rw-r--r--Source/CTest/cmProcess.h2
-rw-r--r--Source/cmAffinity.cxx62
-rw-r--r--Source/cmAffinity.h12
-rw-r--r--Source/cmCTest.h2
-rw-r--r--Source/cmCacheManager.cxx16
-rw-r--r--Source/cmComputeLinkInformation.cxx3
-rw-r--r--Source/cmComputeTargetDepends.cxx6
-rw-r--r--Source/cmDepends.cxx7
-rw-r--r--Source/cmDepends.h6
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.cxx3
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.h6
-rw-r--r--Source/cmExportBuildFileGenerator.cxx33
-rw-r--r--Source/cmExportBuildFileGenerator.h3
-rw-r--r--Source/cmExportCommand.cxx11
-rw-r--r--Source/cmExportFileGenerator.cxx46
-rw-r--r--Source/cmExportFileGenerator.h8
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.cxx3
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.h6
-rw-r--r--Source/cmExportInstallFileGenerator.cxx28
-rw-r--r--Source/cmExportInstallFileGenerator.h4
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx2
-rw-r--r--Source/cmExtraCodeLiteGenerator.cxx11
-rw-r--r--Source/cmFileCommand.cxx184
-rw-r--r--Source/cmFileCommand.h1
-rw-r--r--Source/cmFileTimeComparison.h4
-rw-r--r--Source/cmFindBase.cxx22
-rw-r--r--Source/cmFindCommon.cxx7
-rw-r--r--Source/cmFindCommon.h3
-rw-r--r--Source/cmFindPackageCommand.cxx58
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h12
-rw-r--r--Source/cmGeneratorExpressionNode.cxx58
-rw-r--r--Source/cmGeneratorExpressionParser.cxx7
-rw-r--r--Source/cmGeneratorTarget.cxx99
-rw-r--r--Source/cmGlobalGenerator.cxx14
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx23
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx30
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx193
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx2
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx34
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx40
-rw-r--r--Source/cmIDEOptions.cxx42
-rw-r--r--Source/cmIDEOptions.h13
-rw-r--r--Source/cmInstallCommand.cxx36
-rw-r--r--Source/cmLocalNinjaGenerator.cxx88
-rw-r--r--Source/cmLocalNinjaGenerator.h9
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx47
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx7
-rw-r--r--Source/cmMakefile.cxx58
-rw-r--r--Source/cmMakefile.h12
-rw-r--r--Source/cmMakefileTargetGenerator.cxx41
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx6
-rw-r--r--Source/cmNinjaTargetGenerator.cxx61
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx4
-rw-r--r--Source/cmOutputConverter.cxx67
-rw-r--r--Source/cmOutputConverter.h4
-rw-r--r--Source/cmPolicies.h10
-rw-r--r--Source/cmProjectCommand.cxx92
-rw-r--r--Source/cmQtAutoGeneratorMocUic.cxx6
-rw-r--r--Source/cmRulePlaceholderExpander.h2
-rw-r--r--Source/cmSearchPath.h4
-rw-r--r--Source/cmStringCommand.cxx25
-rw-r--r--Source/cmStringCommand.h5
-rw-r--r--Source/cmTarget.cxx61
-rw-r--r--Source/cmTarget.h3
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx15
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx813
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h30
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx60
-rw-r--r--Source/cmVisualStudioGeneratorOptions.h4
-rw-r--r--Source/cmWorkingDirectory.cxx16
-rw-r--r--Source/cmWorkingDirectory.h17
-rw-r--r--Source/cmXMLWriter.h52
-rw-r--r--Source/cmake.cxx19
-rw-r--r--Source/cmcmd.cxx28
-rw-r--r--Tests/CMakeLib/CMakeLists.txt3
-rw-r--r--Tests/CMakeLib/testAffinity.cxx18
-rw-r--r--Tests/CMakeLists.txt15
-rw-r--r--Tests/CSharpLinkFromCxx/.gitattributes1
-rw-r--r--Tests/CSharpLinkFromCxx/CMakeLists.txt19
-rw-r--r--Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs16
-rw-r--r--Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs12
-rw-r--r--Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp15
-rw-r--r--Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp16
-rw-r--r--Tests/CTestTest/test.cmake.in2
-rw-r--r--Tests/CommandLength/CMakeLists.txt17
-rw-r--r--Tests/CommandLength/test.c4
-rw-r--r--Tests/CompileOptions/CMakeLists.txt12
-rw-r--r--Tests/CompileOptions/main.cpp25
-rw-r--r--Tests/Complex/Cache/CMakeCache.txt2
-rw-r--r--Tests/ComplexOneConfig/Cache/CMakeCache.txt2
-rw-r--r--Tests/Contracts/PLplot/CMakeLists.txt2
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt37
-rw-r--r--Tests/ExportImport/Export/testLib9.c15
-rw-r--r--Tests/ExportImport/Export/testLib9ObjIface.c11
-rw-r--r--Tests/ExportImport/Export/testLib9ObjPriv.c4
-rw-r--r--Tests/ExportImport/Export/testLib9ObjPub.c4
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt51
-rw-r--r--Tests/ExportImport/Import/A/imp_testLib9.c16
-rw-r--r--Tests/FindCURL/CMakeLists.txt10
-rw-r--r--Tests/FindCURL/Test/CMakeLists.txt16
-rw-r--r--Tests/FindCURL/Test/main.c17
-rw-r--r--Tests/FindLibXml2/CMakeLists.txt10
-rw-r--r--Tests/FindLibXml2/Test/CMakeLists.txt16
-rw-r--r--Tests/FindLibXml2/Test/main.c19
-rw-r--r--Tests/GeneratorExpression/CMakeLists.txt5
-rw-r--r--Tests/GeneratorExpression/check-part1.cmake5
-rw-r--r--Tests/QtAutogen/RerunRccDepends/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/CMakeLists.txt9
-rw-r--r--Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake20
-rw-r--r--Tests/RunCMake/CTestCommandLine/TestAffinity-stdout.txt1
-rw-r--r--Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-check.cmake6
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg-result.txt (renamed from Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-result.txt)0
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg-stderr.txt8
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg.cmake2
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg-result.txt (renamed from Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt)0
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg-stderr.txt8
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg.cmake2
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-not-a-target-check.cmake6
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-not-a-target.cmake2
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_EXISTS.cmake3
-rw-r--r--Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt9
-rw-r--r--Tests/RunCMake/ObjectLibrary/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt5
-rw-r--r--Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-result.txt (renamed from Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt)0
-rw-r--r--Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-stderr.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/InstallLinkedObj1.cmake6
-rw-r--r--Tests/RunCMake/ObjectLibrary/InstallLinkedObj2.cmake6
-rw-r--r--Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake2
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake7
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjLHSStatic.cmake7
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt6
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake3
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt6
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake3
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHSObject-build-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHSObject-build-stdout.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHSObject.cmake12
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHSObject2-build-result.txt1
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHSObject2.cmake12
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHSShared.cmake13
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHSShared2.cmake14
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHSStatic.cmake10
-rw-r--r--Tests/RunCMake/ObjectLibrary/LinkObjRHSStatic2.cmake11
-rw-r--r--Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt4
-rw-r--r--Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake39
-rw-r--r--Tests/RunCMake/ObjectLibrary/a.c8
-rw-r--r--Tests/RunCMake/ObjectLibrary/b.c14
-rw-r--r--Tests/RunCMake/ObjectLibrary/exe.c14
-rw-r--r--Tests/RunCMake/ObjectLibrary/requires.c8
-rw-r--r--Tests/RunCMake/RunCMake.cmake2
-rw-r--r--Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt1
-rw-r--r--Tests/RunCMake/UseSWIG/BasicConfiguration.cmake68
-rw-r--r--Tests/RunCMake/UseSWIG/BasicPerl.cmake18
-rw-r--r--Tests/RunCMake/UseSWIG/BasicPython.cmake9
-rw-r--r--Tests/RunCMake/UseSWIG/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake (renamed from Tests/SwigTest/CMakeLists.txt)29
-rw-r--r--Tests/RunCMake/UseSWIG/LegacyPerl.cmake18
-rw-r--r--Tests/RunCMake/UseSWIG/LegacyPython.cmake9
-rw-r--r--Tests/RunCMake/UseSWIG/MultipleModules.cmake30
-rw-r--r--Tests/RunCMake/UseSWIG/RunCMakeTest.cmake23
-rw-r--r--Tests/RunCMake/UseSWIG/example.cxx (renamed from Tests/SwigTest/example.cxx)0
-rw-r--r--Tests/RunCMake/UseSWIG/example.h (renamed from Tests/SwigTest/example.h)0
-rw-r--r--Tests/RunCMake/UseSWIG/example.i (renamed from Tests/SwigTest/example.i)1
-rw-r--r--Tests/RunCMake/UseSWIG/runme.php4 (renamed from Tests/SwigTest/runme.php4)0
-rw-r--r--[-rwxr-xr-x]Tests/RunCMake/UseSWIG/runme.pike (renamed from Tests/SwigTest/runme.pike)0
-rw-r--r--Tests/RunCMake/UseSWIG/runme.pl (renamed from Tests/SwigTest/runme.pl)1
-rw-r--r--Tests/RunCMake/UseSWIG/runme.py52
-rw-r--r--Tests/RunCMake/UseSWIG/runme.rb (renamed from Tests/SwigTest/runme.rb)0
-rw-r--r--Tests/RunCMake/UseSWIG/runme.tcl (renamed from Tests/SwigTest/runme.tcl)1
-rw-r--r--Tests/RunCMake/UseSWIG/runme2.tcl (renamed from Tests/SwigTest/runme2.tcl)1
-rw-r--r--Tests/RunCMake/VS10Project/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake3
-rw-r--r--Tests/RunCMake/VS10Project/VsDebuggerCommand-check.cmake22
-rw-r--r--Tests/RunCMake/VS10Project/VsDebuggerCommand.cmake5
-rw-r--r--Tests/RunCMake/WorkingDirectory/CMakeLists.txt.in3
-rw-r--r--Tests/RunCMake/WorkingDirectory/CTestConfig.cmake.in1
-rw-r--r--Tests/RunCMake/WorkingDirectory/RunCMakeTest.cmake9
-rw-r--r--Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-check.cmake3
-rw-r--r--Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-result.txt1
-rw-r--r--Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-stdout.txt1
-rw-r--r--Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir.cmake7
-rw-r--r--Tests/RunCMake/WorkingDirectory/dirNotExist-result.txt1
-rw-r--r--Tests/RunCMake/WorkingDirectory/dirNotExist-stderr.txt1
-rw-r--r--Tests/RunCMake/WorkingDirectory/dirNotExist-stdout.txt10
-rw-r--r--Tests/RunCMake/WorkingDirectory/dirNotExist.cmake6
-rw-r--r--Tests/RunCMake/WorkingDirectory/test.cmake.in15
-rw-r--r--Tests/RunCMake/add_library/CMP0073-stdout.txt3
-rw-r--r--Tests/RunCMake/add_library/CMP0073.cmake18
-rw-r--r--Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt5
-rw-r--r--Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-stderr.txt16
-rw-r--r--Tests/RunCMake/add_library/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/add_library/empty.c0
-rw-r--r--Tests/RunCMake/export/ForbiddenToExportImportedProperties-result.txt (renamed from Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt)0
-rw-r--r--Tests/RunCMake/export/ForbiddenToExportImportedProperties-stderr.txt3
-rw-r--r--Tests/RunCMake/export/ForbiddenToExportImportedProperties.cmake12
-rw-r--r--Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-result.txt (renamed from Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt)0
-rw-r--r--Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-stderr.txt3
-rw-r--r--Tests/RunCMake/export/ForbiddenToExportInterfaceProperties.cmake12
-rw-r--r--Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-result.txt (renamed from Tests/RunCMake/ObjectLibrary/ExportNotSupported-result.txt)0
-rw-r--r--Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-stderr.txt3
-rw-r--r--Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp.cmake12
-rw-r--r--Tests/RunCMake/export/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/export/empty.cpp7
-rw-r--r--Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS-result.txt (renamed from Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt)0
-rw-r--r--Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS-stderr.txt4
-rw-r--r--Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS.cmake1
-rw-r--r--Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg-result.txt1
-rw-r--r--Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg-stderr.txt4
-rw-r--r--Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg.cmake1
-rw-r--r--Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES-result.txt1
-rw-r--r--Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES-stderr.txt4
-rw-r--r--Tests/RunCMake/file/GLOB-noexp-RELATIVE-result.txt1
-rw-r--r--Tests/RunCMake/file/GLOB-noexp-RELATIVE-stderr.txt4
-rw-r--r--Tests/RunCMake/file/GLOB-noexp-RELATIVE.cmake1
-rw-r--r--Tests/RunCMake/file/GLOB-sort-dedup-stderr.txt2
-rw-r--r--Tests/RunCMake/file/GLOB-sort-dedup.cmake21
-rw-r--r--Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS-result.txt1
-rw-r--r--Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS-stderr.txt4
-rw-r--r--Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS.cmake1
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake12
-rw-r--r--Tests/RunCMake/file/TOUCH-error-in-source-directory-result.txt1
-rw-r--r--Tests/RunCMake/file/TOUCH-error-in-source-directory-stderr.txt1
-rw-r--r--Tests/RunCMake/file/TOUCH-error-in-source-directory.cmake2
-rw-r--r--Tests/RunCMake/file/TOUCH-error-missing-directory-result.txt1
-rw-r--r--Tests/RunCMake/file/TOUCH-error-missing-directory-stderr.txt1
-rw-r--r--Tests/RunCMake/file/TOUCH-error-missing-directory.cmake1
-rw-r--r--Tests/RunCMake/file/TOUCH-result.txt1
-rw-r--r--Tests/RunCMake/file/TOUCH-stderr.txt9
-rw-r--r--Tests/RunCMake/file/TOUCH.cmake16
-rw-r--r--Tests/RunCMake/find_package/CMP0074-OLD-stderr.txt12
-rw-r--r--Tests/RunCMake/find_package/CMP0074-OLD.cmake2
-rw-r--r--Tests/RunCMake/find_package/CMP0074-WARN-stderr.txt28
-rw-r--r--Tests/RunCMake/find_package/CMP0074-WARN.cmake2
-rw-r--r--Tests/RunCMake/find_package/CMP0074-common.cmake46
-rw-r--r--Tests/RunCMake/find_package/PackageRoot.cmake2
-rw-r--r--Tests/RunCMake/find_package/PackageRootNestedConfig.cmake2
-rw-r--r--Tests/RunCMake/find_package/PackageRootNestedModule.cmake2
-rw-r--r--Tests/RunCMake/find_package/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/get_property/directory_properties-stderr.txt10
-rw-r--r--Tests/RunCMake/get_property/directory_properties.cmake9
-rw-r--r--Tests/RunCMake/get_property/directory_properties/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/project/LanguagesUnordered-stderr.txt1
-rw-r--r--Tests/RunCMake/project/LanguagesUnordered.cmake1
-rw-r--r--Tests/RunCMake/project/ProjectDescriptionNoArg-stderr.txt2
-rw-r--r--Tests/RunCMake/project/ProjectDescriptionNoArg.cmake2
-rw-r--r--Tests/RunCMake/project/ProjectDescriptionNoArg2-stderr.txt2
-rw-r--r--Tests/RunCMake/project/ProjectDescriptionNoArg2.cmake2
-rw-r--r--Tests/RunCMake/project/ProjectHomepage-stdout.txt3
-rw-r--r--Tests/RunCMake/project/ProjectHomepage.cmake14
-rw-r--r--Tests/RunCMake/project/ProjectHomepage2-result.txt1
-rw-r--r--Tests/RunCMake/project/ProjectHomepage2-stderr.txt4
-rw-r--r--Tests/RunCMake/project/ProjectHomepage2.cmake2
-rw-r--r--Tests/RunCMake/project/ProjectHomepageNoArg-stderr.txt5
-rw-r--r--Tests/RunCMake/project/ProjectHomepageNoArg.cmake2
-rw-r--r--Tests/RunCMake/project/RunCMakeTest.cmake6
-rw-r--r--Tests/RunCMake/project/VersionMissingLanguages-stderr.txt3
-rw-r--r--Tests/RunCMake/project/VersionMissingValueOkay-stderr.txt2
-rw-r--r--Tests/RunCMake/string/Join.cmake16
-rw-r--r--Tests/RunCMake/string/JoinNoArgs-result.txt1
-rw-r--r--Tests/RunCMake/string/JoinNoArgs-stderr.txt4
-rw-r--r--Tests/RunCMake/string/JoinNoArgs.cmake1
-rw-r--r--Tests/RunCMake/string/JoinNoVar-result.txt1
-rw-r--r--Tests/RunCMake/string/JoinNoVar-stderr.txt4
-rw-r--r--Tests/RunCMake/string/JoinNoVar.cmake1
-rw-r--r--Tests/RunCMake/string/RunCMakeTest.cmake4
-rw-r--r--Tests/SwigTest/runme.py51
-rw-r--r--Utilities/cmlibuv/include/uv.h14
-rw-r--r--Utilities/cmlibuv/src/unix/core.c12
-rw-r--r--Utilities/cmlibuv/src/unix/process.c55
-rw-r--r--Utilities/cmlibuv/src/win/core.c4
-rw-r--r--Utilities/cmlibuv/src/win/process.c56
-rwxr-xr-xbootstrap4
384 files changed, 4767 insertions, 1662 deletions
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 381769d..fa2c23d 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -29,6 +29,8 @@ To contribute patches:
#. Base all new work on the upstream ``master`` branch.
Base work on the upstream ``release`` branch only if it fixes a
regression or bug in a feature new to that release.
+ If in doubt, prefer ``master``. Reviewers may simply ask for
+ a rebase if deemed appropriate in particular cases.
#. Create commits making incremental, distinct, logically complete changes
with appropriate `commit messages`_.
#. Push a topic branch to a personal repository fork on GitLab.
diff --git a/CompileFlags.cmake b/CompileFlags.cmake
index 32e7005..ec9b31b 100644
--- a/CompileFlags.cmake
+++ b/CompileFlags.cmake
@@ -82,3 +82,26 @@ endif ()
if (CMAKE_ANSI_CFLAGS)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ANSI_CFLAGS}")
endif ()
+
+# Allow per-translation-unit parallel builds when using MSVC
+if(CMAKE_GENERATOR MATCHES "Visual Studio" AND
+ (CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel" OR
+ CMAKE_CXX_COMPILER_ID MATCHES "MSVC|Intel"))
+
+ set(CMake_MSVC_PARALLEL ON CACHE STRING "\
+Enables /MP flag for parallel builds using MSVC. Specify an \
+integer value to control the number of threads used (Only \
+works on some older versions of Visual Studio). Setting to \
+ON lets the toolchain decide how many threads to use. Set to \
+OFF to disable /MP completely." )
+
+ if(CMake_MSVC_PARALLEL)
+ if(CMake_MSVC_PARALLEL GREATER 0)
+ string(APPEND CMAKE_C_FLAGS " /MP${CMake_MSVC_PARALLEL}")
+ string(APPEND CMAKE_CXX_FLAGS " /MP${CMake_MSVC_PARALLEL}")
+ else()
+ string(APPEND CMAKE_C_FLAGS " /MP")
+ string(APPEND CMAKE_CXX_FLAGS " /MP")
+ endif()
+ endif()
+endif()
diff --git a/Help/command/COMPILE_OPTIONS_SHELL.txt b/Help/command/COMPILE_OPTIONS_SHELL.txt
new file mode 100644
index 0000000..a1316c8
--- /dev/null
+++ b/Help/command/COMPILE_OPTIONS_SHELL.txt
@@ -0,0 +1,9 @@
+The final set of compile options used for a target is constructed by
+accumulating options from the current target and the usage requirements of
+it dependencies. The set of options is de-duplicated to avoid repetition.
+While beneficial for individual options, the de-duplication step can break
+up option groups. For example, ``-D A -D B`` becomes ``-D A B``. One may
+specify a group of options using shell-like quoting along with a ``SHELL:``
+prefix. The ``SHELL:`` prefix is dropped and the rest of the option string
+is parsed using the :command:`separate_arguments` ``UNIX_COMMAND`` mode.
+For example, ``"SHELL:-D A" "SHELL:-D B"`` becomes ``-D A -D B``.
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt
index 7db221c..13ea8ab 100644
--- a/Help/command/FIND_XXX.txt
+++ b/Help/command/FIND_XXX.txt
@@ -16,6 +16,7 @@ The general signature is:
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[DOC "cache documentation string"]
[NO_DEFAULT_PATH]
+ [NO_PACKAGE_ROOT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
@@ -60,6 +61,10 @@ If ``NO_DEFAULT_PATH`` is specified, then no additional paths are
added to the search.
If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR| replace::
+ |prefix_XXX_SUBDIR| for each ``<prefix>`` in ``PackageName_ROOT`` if called
+ from within a find module
+
.. |CMAKE_PREFIX_PATH_XXX_SUBDIR| replace::
|prefix_XXX_SUBDIR| for each ``<prefix>`` in :variable:`CMAKE_PREFIX_PATH`
@@ -71,7 +76,19 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
|prefix_XXX_SUBDIR| for each ``<prefix>`` in
:variable:`CMAKE_SYSTEM_PREFIX_PATH`
-1. Search paths specified in cmake-specific cache variables.
+1. If called from within a find module, search prefix paths unique to the
+ current package being found. Specifically look in the ``PackageName_ROOT``
+ CMake and environment variables. The package root variables are maintained
+ as a stack so if called from nested find modules, root paths from the
+ parent's find module will be searchd after paths from the current module,
+ i.e. ``CurrentPackage_ROOT``, ``ENV{CurrentPackage_ROOT}``,
+ ``ParentPackage_ROOT``, ``ENV{ParentPacakge_ROOT}``, etc.
+ This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed.
+ See policy :policy:`CMP0074`.
+
+ * |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX|
+
+2. Search paths specified in cmake-specific cache variables.
These are intended to be used on the command line with a ``-DVAR=value``.
The values are interpreted as :ref:`;-lists <CMake Language Lists>`.
This can be skipped if ``NO_CMAKE_PATH`` is passed.
@@ -80,7 +97,7 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
* |CMAKE_XXX_PATH|
* |CMAKE_XXX_MAC_PATH|
-2. Search paths specified in cmake-specific environment variables.
+3. Search paths specified in cmake-specific environment variables.
These are intended to be set in the user's shell configuration,
and therefore use the host's native path separator
(``;`` on Windows and ``:`` on UNIX).
@@ -90,17 +107,17 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
* |CMAKE_XXX_PATH|
* |CMAKE_XXX_MAC_PATH|
-3. Search the paths specified by the ``HINTS`` option.
+4. Search the paths specified by the ``HINTS`` option.
These should be paths computed by system introspection, such as a
hint provided by the location of another item already found.
Hard-coded guesses should be specified with the ``PATHS`` option.
-4. Search the standard system environment variables.
+5. Search the standard system environment variables.
This can be skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is an argument.
* |SYSTEM_ENVIRONMENT_PATH_XXX|
-5. Search cmake variables defined in the Platform files
+6. Search cmake variables defined in the Platform files
for the current system. This can be skipped if ``NO_CMAKE_SYSTEM_PATH``
is passed.
@@ -108,7 +125,7 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows:
* |CMAKE_SYSTEM_XXX_PATH|
* |CMAKE_SYSTEM_XXX_MAC_PATH|
-6. Search the paths specified by the PATHS option
+7. Search the paths specified by the PATHS option
or in the short-hand version of the command.
These are typically hard-coded guesses.
diff --git a/Help/command/add_compile_options.rst b/Help/command/add_compile_options.rst
index 3fe2a33..44924e6 100644
--- a/Help/command/add_compile_options.rst
+++ b/Help/command/add_compile_options.rst
@@ -21,3 +21,5 @@ Arguments to ``add_compile_options`` may use "generator expressions" with
the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
manual for more on defining buildsystem properties.
+
+.. include:: COMPILE_OPTIONS_SHELL.txt
diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst
index 3706153..8fa0df7 100644
--- a/Help/command/add_library.rst
+++ b/Help/command/add_library.rst
@@ -110,10 +110,10 @@ along with those compiled from their own sources. Object libraries
may contain only sources that compile, header files, and other files
that would not affect linking of a normal library (e.g. ``.txt``).
They may contain custom commands generating such sources, but not
-``PRE_BUILD``, ``PRE_LINK``, or ``POST_BUILD`` commands. Object libraries
-cannot be linked. Some native build systems (such as Xcode) may not like
-targets that have only object files, so consider adding at least one real
-source file to any target that references ``$<TARGET_OBJECTS:objlib>``.
+``PRE_BUILD``, ``PRE_LINK``, or ``POST_BUILD`` commands. Some native build
+systems (such as Xcode) may not like targets that have only object files, so
+consider adding at least one real source file to any target that references
+``$<TARGET_OBJECTS:objlib>``.
Alias Libraries
^^^^^^^^^^^^^^^
diff --git a/Help/command/export.rst b/Help/command/export.rst
index 53675a7..0c676c6 100644
--- a/Help/command/export.rst
+++ b/Help/command/export.rst
@@ -40,6 +40,15 @@ policy CMP0022 is NEW. If a library target is included in the export
but a target to which it links is not included the behavior is
unspecified.
+.. note::
+
+ :ref:`Object Libraries` under :generator:`Xcode` have special handling if
+ multiple architectures are listed in :variable:`CMAKE_OSX_ARCHITECTURES`.
+ In this case they will be exported as :ref:`Interface Libraries` with
+ no object files available to clients. This is sufficient to satisfy
+ transitive usage requirements of other targets that link to the
+ object libraries in their implementation.
+
::
export(PACKAGE <name>)
diff --git a/Help/command/file.rst b/Help/command/file.rst
index 5ce86e5..5e18077 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -285,6 +285,23 @@ If neither ``TLS`` option is given CMake will check variables
::
+ file(TOUCH [<files>...])
+ file(TOUCH_NOCREATE [<files>...])
+
+Create a file with no content if it does not yet exist. If the file already
+exists, its access and/or modification will be updated to the time when the
+function call is executed.
+
+Use TOUCH_NOCREATE to touch a file if it exists but not create it. If a file
+does not exist it will be silently ignored.
+
+With TOUCH and TOUCH_NOCREATE the contents of an existing file will not be
+modified.
+
+------------------------------------------------------------------------------
+
+::
+
file(TIMESTAMP <filename> <variable> [<format>] [UTC])
Compute a string representation of the modification time of ``<filename>``
diff --git a/Help/command/find_file.rst b/Help/command/find_file.rst
index e56097b..2a14ad7 100644
--- a/Help/command/find_file.rst
+++ b/Help/command/find_file.rst
@@ -8,6 +8,9 @@ find_file
.. |prefix_XXX_SUBDIR| replace:: ``<prefix>/include``
.. |entry_XXX_SUBDIR| replace:: ``<entry>/include``
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+ ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
+ is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
.. |CMAKE_PREFIX_PATH_XXX| replace::
``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
is set, and |CMAKE_PREFIX_PATH_XXX_SUBDIR|
diff --git a/Help/command/find_library.rst b/Help/command/find_library.rst
index f774f17..0861d67 100644
--- a/Help/command/find_library.rst
+++ b/Help/command/find_library.rst
@@ -8,6 +8,9 @@ find_library
.. |prefix_XXX_SUBDIR| replace:: ``<prefix>/lib``
.. |entry_XXX_SUBDIR| replace:: ``<entry>/lib``
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+ ``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set,
+ and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
.. |CMAKE_PREFIX_PATH_XXX| replace::
``<prefix>/lib/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE` is set,
and |CMAKE_PREFIX_PATH_XXX_SUBDIR|
diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst
index b2e70f2..89c5a7a 100644
--- a/Help/command/find_package.rst
+++ b/Help/command/find_package.rst
@@ -64,6 +64,7 @@ The complete Config mode command signature is::
[PATHS path1 [path2 ... ]]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
[NO_DEFAULT_PATH]
+ [NO_PACKAGE_ROOT_PATH]
[NO_CMAKE_PATH]
[NO_CMAKE_ENVIRONMENT_PATH]
[NO_SYSTEM_ENVIRONMENT_PATH]
@@ -249,7 +250,14 @@ The set of installation prefixes is constructed using the following
steps. If ``NO_DEFAULT_PATH`` is specified all ``NO_*`` options are
enabled.
-1. Search paths specified in cmake-specific cache variables. These
+1. Search paths specified in the ``PackageName_ROOT`` CMake and environment
+ variables. The package root variables are maintained as a stack so if
+ called from within a find module, root paths from the parent's find
+ module will also be searched after paths for the current package.
+ This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed.
+ See policy :policy:`CMP0074`.
+
+2. Search paths specified in cmake-specific cache variables. These
are intended to be used on the command line with a ``-DVAR=value``.
The values are interpreted as :ref:`;-lists <CMake Language Lists>`.
This can be skipped if ``NO_CMAKE_PATH`` is passed::
@@ -258,7 +266,7 @@ enabled.
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
-2. Search paths specified in cmake-specific environment variables.
+3. Search paths specified in cmake-specific environment variables.
These are intended to be set in the user's shell configuration,
and therefore use the host's native path separator
(``;`` on Windows and ``:`` on UNIX).
@@ -269,26 +277,26 @@ enabled.
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
-3. Search paths specified by the ``HINTS`` option. These should be paths
+4. Search paths specified by the ``HINTS`` option. These should be paths
computed by system introspection, such as a hint provided by the
location of another item already found. Hard-coded guesses should
be specified with the ``PATHS`` option.
-4. Search the standard system environment variables. This can be
+5. Search the standard system environment variables. This can be
skipped if ``NO_SYSTEM_ENVIRONMENT_PATH`` is passed. Path entries
ending in ``/bin`` or ``/sbin`` are automatically converted to their
parent directories::
PATH
-5. Search paths stored in the CMake :ref:`User Package Registry`.
+6. Search paths stored in the CMake :ref:`User Package Registry`.
This can be skipped if ``NO_CMAKE_PACKAGE_REGISTRY`` is passed or by
setting the :variable:`CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY`
to ``TRUE``.
See the :manual:`cmake-packages(7)` manual for details on the user
package registry.
-6. Search cmake variables defined in the Platform files for the
+7. Search cmake variables defined in the Platform files for the
current system. This can be skipped if ``NO_CMAKE_SYSTEM_PATH`` is
passed::
@@ -296,14 +304,14 @@ enabled.
CMAKE_SYSTEM_FRAMEWORK_PATH
CMAKE_SYSTEM_APPBUNDLE_PATH
-7. Search paths stored in the CMake :ref:`System Package Registry`.
+8. Search paths stored in the CMake :ref:`System Package Registry`.
This can be skipped if ``NO_CMAKE_SYSTEM_PACKAGE_REGISTRY`` is passed
or by setting the
:variable:`CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY` to ``TRUE``.
See the :manual:`cmake-packages(7)` manual for details on the system
package registry.
-8. Search paths specified by the ``PATHS`` option. These are typically
+9. Search paths specified by the ``PATHS`` option. These are typically
hard-coded guesses.
.. |FIND_XXX| replace:: find_package
diff --git a/Help/command/find_path.rst b/Help/command/find_path.rst
index 76342d0..988a3fa 100644
--- a/Help/command/find_path.rst
+++ b/Help/command/find_path.rst
@@ -8,6 +8,9 @@ find_path
.. |prefix_XXX_SUBDIR| replace:: ``<prefix>/include``
.. |entry_XXX_SUBDIR| replace:: ``<entry>/include``
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+ ``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
+ is set, and |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
.. |CMAKE_PREFIX_PATH_XXX| replace::
``<prefix>/include/<arch>`` if :variable:`CMAKE_LIBRARY_ARCHITECTURE`
is set, and |CMAKE_PREFIX_PATH_XXX_SUBDIR|
diff --git a/Help/command/find_program.rst b/Help/command/find_program.rst
index d3430c0..4f00773 100644
--- a/Help/command/find_program.rst
+++ b/Help/command/find_program.rst
@@ -8,6 +8,8 @@ find_program
.. |prefix_XXX_SUBDIR| replace:: ``<prefix>/[s]bin``
.. |entry_XXX_SUBDIR| replace:: ``<entry>/[s]bin``
+.. |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| replace::
+ |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX_SUBDIR|
.. |CMAKE_PREFIX_PATH_XXX| replace::
|CMAKE_PREFIX_PATH_XXX_SUBDIR|
.. |CMAKE_XXX_PATH| replace:: :variable:`CMAKE_PROGRAM_PATH`
diff --git a/Help/command/install.rst b/Help/command/install.rst
index 2506f98..eb7b07c 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -183,6 +183,13 @@ export called ``<export-name>``. It must appear before any ``RUNTIME``,
``LIBRARY``, ``ARCHIVE``, or ``OBJECTS`` options. To actually install the
export file itself, call ``install(EXPORT)``, documented below.
+:ref:`Interface Libraries` may be listed among the targets to install.
+They install no artifacts but will be included in an associated ``EXPORT``.
+If :ref:`Object Libraries` are listed but given no destination for their
+object files, they will be exported as :ref:`Interface Libraries`.
+This is sufficient to satisfy transitive usage requirements of other
+targets that link to the object libraries in their implementation.
+
Installing a target with the :prop_tgt:`EXCLUDE_FROM_ALL` target property
set to ``TRUE`` has undefined behavior.
diff --git a/Help/command/list.rst b/Help/command/list.rst
index f6b75bc..e6a7069 100644
--- a/Help/command/list.rst
+++ b/Help/command/list.rst
@@ -1,68 +1,151 @@
list
----
+.. only:: html
+
+ .. contents::
+
List operations.
+The list subcommands ``APPEND``, ``INSERT``, ``FILTER``, ``REMOVE_AT``,
+``REMOVE_ITEM``, ``REMOVE_DUPLICATES``, ``REVERSE`` and ``SORT`` may create
+new values for the list within the current CMake variable scope. Similar to
+the :command:`set` command, the LIST command creates new variable values in
+the current scope, even if the list itself is actually defined in a parent
+scope. To propagate the results of these operations upwards, use
+:command:`set` with ``PARENT_SCOPE``, :command:`set` with
+``CACHE INTERNAL``, or some other means of value propagation.
+
+.. note::
+
+ A list in cmake is a ``;`` separated group of strings. To create a
+ list the set command can be used. For example, ``set(var a b c d e)``
+ creates a list with ``a;b;c;d;e``, and ``set(var "a b c d e")`` creates a
+ string or a list with one item in it. (Note macro arguments are not
+ variables, and therefore cannot be used in LIST commands.)
+
+.. note::
+
+ When specifying index values, if ``<element index>`` is 0 or greater, it
+ is indexed from the beginning of the list, with 0 representing the
+ first list element. If ``<element index>`` is -1 or lesser, it is indexed
+ from the end of the list, with -1 representing the last list element.
+ Be careful when counting with negative indices: they do not start from
+ 0. -0 is equivalent to 0, the first list element.
+
+Capacity and Element access
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+LENGTH
+""""""
+
::
list(LENGTH <list> <output variable>)
- list(GET <list> <element index> [<element index> ...]
- <output variable>)
+
+Returns the list's length.
+
+GET
+"""
+
+::
+
+ list(GET <list> <element index> [<element index> ...] <output variable>)
+
+Returns the list of elements specified by indices from the list.
+
+Search
+^^^^^^
+
+FIND
+""""
+
+::
+
+ list(FIND <list> <value> <output variable>)
+
+Returns the index of the element specified in the list or -1
+if it wasn't found.
+
+Modification
+^^^^^^^^^^^^
+
+APPEND
+""""""
+
+::
+
list(APPEND <list> [<element> ...])
+
+Appends elements to the list.
+
+FILTER
+""""""
+
+::
+
list(FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)
- list(FIND <list> <value> <output variable>)
+
+Includes or removes items from the list that match the mode's pattern.
+In ``REGEX`` mode, items will be matched against the given regular expression.
+
+For more information on regular expressions see also the
+:command:`string` command.
+
+INSERT
+""""""
+
+::
+
list(INSERT <list> <element_index> <element> [<element> ...])
+
+Inserts elements to the list to the specified location.
+
+REMOVE_ITEM
+"""""""""""
+
+::
+
list(REMOVE_ITEM <list> <value> [<value> ...])
+
+Removes the given items from the list.
+
+REMOVE_AT
+"""""""""
+
+::
+
list(REMOVE_AT <list> <index> [<index> ...])
- list(REMOVE_DUPLICATES <list>)
- list(REVERSE <list>)
- list(SORT <list>)
-``LENGTH`` will return a given list's length.
+Removes items at given indices from the list.
-``GET`` will return list of elements specified by indices from the list.
+REMOVE_DUPLICATES
+"""""""""""""""""
-``APPEND`` will append elements to the list.
+::
-``FILTER`` will include or remove items from the list that match the
-mode's pattern.
-In ``REGEX`` mode, items will be matched against the given regular expression.
-For more information on regular expressions see also the :command:`string`
-command.
+ list(REMOVE_DUPLICATES <list>)
-``FIND`` will return the index of the element specified in the list or -1
-if it wasn't found.
+Removes duplicated items in the list.
+
+Sorting
+^^^^^^^
+
+REVERSE
+"""""""
-``INSERT`` will insert elements to the list to the specified location.
+::
-``REMOVE_AT`` and ``REMOVE_ITEM`` will remove items from the list. The
-difference is that ``REMOVE_ITEM`` will remove the given items, while
-``REMOVE_AT`` will remove the items at the given indices.
+ list(REVERSE <list>)
-``REMOVE_DUPLICATES`` will remove duplicated items in the list.
+Reverses the contents of the list in-place.
-``REVERSE`` reverses the contents of the list in-place.
+SORT
+""""
-``SORT`` sorts the list in-place alphabetically.
+::
+
+ list(SORT <list>)
-The list subcommands ``APPEND``, ``INSERT``, ``FILTER``, ``REMOVE_AT``,
-``REMOVE_ITEM``, ``REMOVE_DUPLICATES``, ``REVERSE`` and ``SORT`` may create new
-values for the list within the current CMake variable scope. Similar to the
-:command:`set` command, the LIST command creates new variable values in the
-current scope, even if the list itself is actually defined in a parent
-scope. To propagate the results of these operations upwards, use
-:command:`set` with ``PARENT_SCOPE``, :command:`set` with
-``CACHE INTERNAL``, or some other means of value propagation.
-NOTES: A list in cmake is a ``;`` separated group of strings. To create a
-list the set command can be used. For example, ``set(var a b c d e)``
-creates a list with ``a;b;c;d;e``, and ``set(var "a b c d e")`` creates a
-string or a list with one item in it. (Note macro arguments are not
-variables, and therefore cannot be used in LIST commands.)
-
-When specifying index values, if ``<element index>`` is 0 or greater, it
-is indexed from the beginning of the list, with 0 representing the
-first list element. If ``<element index>`` is -1 or lesser, it is indexed
-from the end of the list, with -1 representing the last list element.
-Be careful when counting with negative indices: they do not start from
-0. -0 is equivalent to 0, the first list element.
+Sorts the list in-place alphabetically.
diff --git a/Help/command/project.rst b/Help/command/project.rst
index eb185e4..e46dd69 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -1,7 +1,7 @@
project
-------
-Set a name, version, and enable languages for the entire project.
+Sets project details such as name, version, etc. and enables languages.
.. code-block:: cmake
@@ -9,6 +9,7 @@ Set a name, version, and enable languages for the entire project.
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[DESCRIPTION <project-description-string>]
+ [HOMEPAGE_URL <url-string>]
[LANGUAGES <language-name>...])
Sets the name of the project and stores the name in the
@@ -41,9 +42,18 @@ in variables
Variables corresponding to unspecified versions are set to the empty string
(if policy :policy:`CMP0048` is set to ``NEW``).
-If optional ``DESCRIPTION`` is given, then additional :variable:`PROJECT_DESCRIPTION`
-variable will be set to its argument. The argument must be a string with short
-description of the project (only a few words).
+If the optional ``DESCRIPTION`` is given, then :variable:`PROJECT_DESCRIPTION`
+and :variable:`<PROJECT-NAME>_DESCRIPTION` will be set to its argument.
+The description is expected to be a relatively short string, usually no more
+than a few words.
+
+The optional ``HOMEPAGE_URL`` sets the analogous variables
+:variable:`PROJECT_HOMEPAGE_URL` and :variable:`<PROJECT-NAME>_HOMEPAGE_URL`.
+When this option is given, the URL provided should be the canonical home for
+the project.
+
+Note that the description and homepage URL may be used as defaults for
+things like packaging meta-data, documentation, etc.
Optionally you can specify which languages your project supports.
Example languages include ``C``, ``CXX`` (i.e. C++), ``CUDA``,
@@ -63,7 +73,11 @@ The top-level ``CMakeLists.txt`` file for a project must contain a
literal, direct call to the :command:`project` command; loading one
through the :command:`include` command is not sufficient. If no such
call exists CMake will implicitly add one to the top that enables the
-default languages (``C`` and ``CXX``).
+default languages (``C`` and ``CXX``). The name of the project set in
+the top level ``CMakeLists.txt`` file is available from the
+:variable:`CMAKE_PROJECT_NAME` variable, its description from
+:variable:`CMAKE_PROJECT_DESCRIPTION` and its homepage URL from
+:variable:`CMAKE_PROJECT_HOMEPAGE_URL`.
.. note::
Call the :command:`cmake_minimum_required` command at the beginning
diff --git a/Help/command/string.rst b/Help/command/string.rst
index fb3893f..cd94bb4 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -151,6 +151,16 @@ CONCAT
Concatenate all the input arguments together and store
the result in the named output variable.
+JOIN
+""""
+
+::
+
+ string(JOIN <glue> <output variable> [<input>...])
+
+Join all the input arguments together using the glue
+string and store the result in the named output variable.
+
TOLOWER
"""""""
@@ -282,6 +292,18 @@ CONFIGURE
Transform a string like :command:`configure_file` transforms a file.
+MAKE_C_IDENTIFIER
+"""""""""""""""""
+
+::
+
+ string(MAKE_C_IDENTIFIER <input string> <output variable>)
+
+Convert each non-alphanumeric character in the ``<input string>`` to an
+underscore and store the result in the ``<output variable>``. If the first
+character of the string is a digit, an underscore will also be prepended to
+the result.
+
RANDOM
""""""
@@ -346,13 +368,6 @@ If no explicit ``<format string>`` is given it will default to:
%Y-%m-%dT%H:%M:%S for local time.
%Y-%m-%dT%H:%M:%SZ for UTC.
-
-::
-
- string(MAKE_C_IDENTIFIER <input string> <output variable>)
-
-Write a string which can be used as an identifier in C.
-
.. note::
If the ``SOURCE_DATE_EPOCH`` environment variable is set,
diff --git a/Help/command/target_compile_options.rst b/Help/command/target_compile_options.rst
index 3e7dc47..b7b4dc1 100644
--- a/Help/command/target_compile_options.rst
+++ b/Help/command/target_compile_options.rst
@@ -38,3 +38,5 @@ Arguments to ``target_compile_options`` may use "generator expressions"
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
manual for more on defining buildsystem properties.
+
+.. include:: COMPILE_OPTIONS_SHELL.txt
diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst
index 2ec8744..fcc2c07 100644
--- a/Help/command/target_link_libraries.rst
+++ b/Help/command/target_link_libraries.rst
@@ -183,6 +183,70 @@ is not ``NEW``, they are also appended to the
``general`` (or without any keyword) are treated as if specified for both
``debug`` and ``optimized``.
+Linking Object Libraries
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+:ref:`Object Libraries` may be used as the ``<target>`` (first) argument
+of ``target_link_libraries`` to specify dependencies of their sources
+on other libraries. For example, the code
+
+.. code-block:: cmake
+
+ add_library(A SHARED a.c)
+ target_compile_definitions(A PUBLIC A)
+
+ add_library(obj OBJECT obj.c)
+ target_compile_definitions(obj PUBLIC OBJ)
+ target_link_libraries(obj PUBLIC A)
+
+compiles ``obj.c`` with ``-DA -DOBJ`` and establishes usage requirements
+for ``obj`` that propagate to its dependents.
+
+Normal libraries and executables may link to :ref:`Object Libraries`
+to get their objects and usage requirements. Continuing the above
+example, the code
+
+.. code-block:: cmake
+
+ add_library(B SHARED b.c)
+ target_link_libraries(B PUBLIC obj)
+
+compiles ``b.c`` with ``-DA -DOBJ``, creates shared library ``B``
+with object files from ``b.c`` and ``obj.c``, and links ``B`` to ``A``.
+Furthermore, the code
+
+.. code-block:: cmake
+
+ add_executable(main main.c)
+ target_link_libraries(main B)
+
+compiles ``main.c`` with ``-DA -DOBJ`` and links executable ``main``
+to ``B`` and ``A``. The object library's usage requirements are
+propagated transitively through ``B``, but its object files are not.
+
+:ref:`Object Libraries` may "link" to other object libraries to get
+usage requirements, but since they do not have a link step nothing
+is done with their object files. Continuing from the above example,
+the code:
+
+.. code-block:: cmake
+
+ add_library(obj2 OBJECT obj2.c)
+ target_link_libraries(obj2 PUBLIC obj)
+
+ add_executable(main2 main2.c)
+ target_link_libraries(main2 obj2)
+
+compiles ``obj2.c`` with ``-DA -DOBJ``, creates executable ``main2``
+with object files from ``main2.c`` and ``obj2.c``, and links ``main2``
+to ``A``.
+
+In other words, when :ref:`Object Libraries` appear in a target's
+:prop_tgt:`INTERFACE_LINK_LIBRARIES` property they will be
+treated as :ref:`Interface Libraries`, but when they appear in
+a target's :prop_tgt:`LINK_LIBRARIES` property their object files
+will be included in the link too.
+
Cyclic Dependencies of Static Libraries
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst
index b672ea6..50c4087 100644
--- a/Help/manual/cmake-buildsystem.7.rst
+++ b/Help/manual/cmake-buildsystem.7.rst
@@ -113,9 +113,9 @@ and it uniquely identifies the bundle.
Object Libraries
^^^^^^^^^^^^^^^^
-The ``OBJECT`` library type is also not linked to. It defines a non-archival
-collection of object files resulting from compiling the given source files.
-The object files collection can be used as source inputs to other targets:
+The ``OBJECT`` library type defines a non-archival collection of object files
+resulting from compiling the given source files. The object files collection
+may be used as source inputs to other targets:
.. code-block:: cmake
@@ -125,22 +125,31 @@ The object files collection can be used as source inputs to other targets:
add_executable(test_exe $<TARGET_OBJECTS:archive> test.cpp)
-``OBJECT`` libraries may not be used in the right hand side of
-:command:`target_link_libraries`. They also may not be used as the ``TARGET``
-in a use of the :command:`add_custom_command(TARGET)` command signature. They
-may be installed, and will be exported as an INTERFACE library.
+The link (or archiving) step of those other targets will use the object
+files collection in addition to those from their own sources.
-Although object libraries may not be named directly in calls to
-the :command:`target_link_libraries` command, they can be "linked"
-indirectly by using an :ref:`Interface Library <Interface Libraries>`
-whose :prop_tgt:`INTERFACE_SOURCES` target property is set to name
-``$<TARGET_OBJECTS:objlib>``.
+Alternatively, object libraries may be linked into other targets:
-Although object libraries may not be used as the ``TARGET``
-in a use of the :command:`add_custom_command(TARGET)` command signature,
-the list of objects can be used by :command:`add_custom_command(OUTPUT)` or
-:command:`file(GENERATE)` by using ``$<TARGET_OBJECTS:objlib>``.
+.. code-block:: cmake
+
+ add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)
+
+ add_library(archiveExtras STATIC extras.cpp)
+ target_link_libraries(archiveExtras PUBLIC archive)
+
+ add_executable(test_exe test.cpp)
+ target_link_libraries(test_exe archive)
+
+The link (or archiving) step of those other targets will use the object
+files from object libraries that are *directly* linked. Additionally,
+usage requirements of the object libraries will be honored when compiling
+sources in those other targets. Furthermore, those usage requirements
+will propagate transitively to dependents of those other targets.
+Object libraries may not be used as the ``TARGET`` in a use of the
+:command:`add_custom_command(TARGET)` command signature. However,
+the list of objects can be used by :command:`add_custom_command(OUTPUT)`
+or :command:`file(GENERATE)` by using ``$<TARGET_OBJECTS:objlib>``.
Build Specification and Usage Requirements
==========================================
diff --git a/Help/manual/cmake-developer.7.rst b/Help/manual/cmake-developer.7.rst
index cd509ac..41fe90c 100644
--- a/Help/manual/cmake-developer.7.rst
+++ b/Help/manual/cmake-developer.7.rst
@@ -943,7 +943,7 @@ populated:
endif()
The ``RELEASE`` variant should be listed first in the property
-so that that variant is chosen if the user uses a configuration which is
+so that the variant is chosen if the user uses a configuration which is
not an exact match for any listed ``IMPORTED_CONFIGURATIONS``.
Most of the cache variables should be hidden in the ``ccmake`` interface unless
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 0f6d4cf..d3514ab 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -57,6 +57,10 @@ Available logical expressions are:
``1`` if ``a`` is STREQUAL ``b``, else ``0``
``$<EQUAL:a,b>``
``1`` if ``a`` is EQUAL ``b`` in a numeric comparison, else ``0``
+``$<IN_LIST:a,b>``
+ ``1`` if ``a`` is IN_LIST ``b``, else ``0``
+``$<TARGET_EXISTS:tgt>``
+ ``1`` if ``tgt`` is an existed target name, else ``0``.
``$<CONFIG:cfg>``
``1`` if config is ``cfg``, else ``0``. This is a case-insensitive comparison.
The mapping in :prop_tgt:`MAP_IMPORTED_CONFIG_<CONFIG>` is also considered by
@@ -289,7 +293,8 @@ Available output expressions are:
``$<UPPER_CASE:...>``
Content of ``...`` converted to upper case.
``$<MAKE_C_IDENTIFIER:...>``
- Content of ``...`` converted to a C identifier.
+ Content of ``...`` converted to a C identifier. The conversion follows the
+ same behavior as :command:`string(MAKE_C_IDENTIFIER)`.
``$<TARGET_OBJECTS:objLib>``
List of objects resulting from build of ``objLib``. ``objLib`` must be an
object of type ``OBJECT_LIBRARY``.
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst
index 96d5c7d..7e2255d 100644
--- a/Help/manual/cmake-policies.7.rst
+++ b/Help/manual/cmake-policies.7.rst
@@ -51,6 +51,15 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used
to determine whether to report an error on use of deprecated macros or
functions.
+Policies Introduced by CMake 3.12
+=================================
+
+.. toctree::
+ :maxdepth: 1
+
+ CMP0074: find_package uses PackageName_ROOT variables. </policy/CMP0074>
+ CMP0073: Do not produce legacy _LIB_DEPENDS cache entries. </policy/CMP0073>
+
Policies Introduced by CMake 3.11
=================================
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 00a932f..7ace270 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -84,6 +84,7 @@ Properties on Directories
/prop_dir/RULE_LAUNCH_LINK
/prop_dir/SOURCE_DIR
/prop_dir/SUBDIRECTORIES
+ /prop_dir/TESTS
/prop_dir/TEST_INCLUDE_FILES
/prop_dir/VARIABLES
/prop_dir/VS_GLOBAL_SECTION_POST_section
@@ -175,6 +176,7 @@ Properties on Targets
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD_CONFIG
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD
/prop_tgt/EXPORT_NAME
+ /prop_tgt/EXPORT_PROPERTIES
/prop_tgt/FOLDER
/prop_tgt/Fortran_FORMAT
/prop_tgt/Fortran_MODULE_DIRECTORY
@@ -295,6 +297,7 @@ Properties on Targets
/prop_tgt/VISIBILITY_INLINES_HIDDEN
/prop_tgt/VS_CONFIGURATION_TYPE
/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY
+ /prop_tgt/VS_DEBUGGER_COMMAND
/prop_tgt/VS_DESKTOP_EXTENSIONS_VERSION
/prop_tgt/VS_DOTNET_REFERENCE_refname
/prop_tgt/VS_DOTNET_REFERENCEPROP_refname_TAG_tagname
@@ -347,6 +350,7 @@ Properties on Tests
/prop_test/LABELS
/prop_test/MEASUREMENT
/prop_test/PASS_REGULAR_EXPRESSION
+ /prop_test/PROCESSOR_AFFINITY
/prop_test/PROCESSORS
/prop_test/REQUIRED_FILES
/prop_test/RESOURCE_LOCK
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 3ac5123..0cb90d4 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -67,6 +67,7 @@ Variables that Provide Information
/variable/CMAKE_PARENT_LIST_FILE
/variable/CMAKE_PATCH_VERSION
/variable/CMAKE_PROJECT_DESCRIPTION
+ /variable/CMAKE_PROJECT_HOMEPAGE_URL
/variable/CMAKE_PROJECT_NAME
/variable/CMAKE_RANLIB
/variable/CMAKE_ROOT
@@ -97,6 +98,8 @@ Variables that Provide Information
/variable/CMAKE_XCODE_GENERATE_SCHEME
/variable/CMAKE_XCODE_PLATFORM_TOOLSET
/variable/PROJECT-NAME_BINARY_DIR
+ /variable/PROJECT-NAME_DESCRIPTION
+ /variable/PROJECT-NAME_HOMEPAGE_URL
/variable/PROJECT-NAME_SOURCE_DIR
/variable/PROJECT-NAME_VERSION
/variable/PROJECT-NAME_VERSION_MAJOR
@@ -105,6 +108,7 @@ Variables that Provide Information
/variable/PROJECT-NAME_VERSION_TWEAK
/variable/PROJECT_BINARY_DIR
/variable/PROJECT_DESCRIPTION
+ /variable/PROJECT_HOMEPAGE_URL
/variable/PROJECT_NAME
/variable/PROJECT_SOURCE_DIR
/variable/PROJECT_VERSION
@@ -178,6 +182,7 @@ Variables that Change Behavior
/variable/CMAKE_STAGING_PREFIX
/variable/CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS
/variable/CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE
+ /variable/CMAKE_SUPPRESS_REGENERATION
/variable/CMAKE_SYSROOT
/variable/CMAKE_SYSROOT_COMPILE
/variable/CMAKE_SYSROOT_LINK
diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst
index a04c403..75af22e 100644
--- a/Help/manual/ctest.1.rst
+++ b/Help/manual/ctest.1.rst
@@ -368,15 +368,17 @@ for "SubprojectB").
Build and Test Mode
===================
-CTest provides a command-line signature to to configure (i.e. run cmake on),
-build, and or execute a test::
+CTest provides a command-line signature to configure (i.e. run cmake on),
+build, and/or execute a test::
ctest --build-and-test <path-to-source> <path-to-build>
- --build-generator <generator> [<options>...] [-- <build-options>...]
- [--test-command <test>]
+ --build-generator <generator>
+ [<options>...]
+ [--build-options <opts>...]
+ [--test-command <command> [<args>...]]
The configure and test steps are optional. The arguments to this command line
-are the source and binary directories. The ``--build-generator`` option *must*
+are the source and binary directories. The ``--build-generator`` option *must*
be provided to use ``--build-and-test``. If ``--test-command`` is specified
then that will be run after the build is complete. Other options that affect
this mode include:
@@ -425,13 +427,15 @@ this mode include:
should be used. e.g. Debug/Release/etc.
``--build-options``
- Add extra options to the build step.
-
- This option must be the last option with the exception of
- ``--test-command``
+ Additional options for configuring the build (i.e. for CMake, not for
+ the build tool). Note that if this is specified, the ``--build-options``
+ keyword and its arguments must be the last option given on the command
+ line, with the possible exception of ``--test-command``.
``--test-command``
- The test to run with the ``--build-and-test`` option.
+ The command to run as the test step with the ``--build-and-test`` option.
+ All arguments following this keyword will be assumed to be part of the
+ test command line, so it must be the last option given.
``--test-timeout``
The time limit in seconds
diff --git a/Help/policy/CMP0073.rst b/Help/policy/CMP0073.rst
new file mode 100644
index 0000000..9bfa0e9
--- /dev/null
+++ b/Help/policy/CMP0073.rst
@@ -0,0 +1,25 @@
+CMP0073
+-------
+
+Do not produce legacy ``_LIB_DEPENDS`` cache entries.
+
+Ancient CMake versions once used ``<tgt>_LIB_DEPENDS`` cache entries to
+propagate library link dependencies. This has long been done by other
+means, leaving the :command:`export_library_dependencies` command as the
+only user of these values. That command has long been disallowed by
+policy :policy:`CMP0033`, but the ``<tgt>_LIB_DEPENDS`` cache entries
+were left for compatibility with possible non-standard uses by projects.
+
+CMake 3.12 and above now prefer to not produce these cache entries
+at all. This policy provides compatibility with projects that have
+not been updated to avoid using them.
+
+The ``OLD`` behavior for this policy is to set ``<tgt>_LIB_DEPENDS`` cache
+entries. The ``NEW`` behavior for this policy is to not set them.
+
+This policy was introduced in CMake version 3.12. Use the
+:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
+Unlike most policies, CMake version |release| does *not* warn
+when this policy is not set and simply uses ``OLD`` behavior.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/policy/CMP0074.rst b/Help/policy/CMP0074.rst
new file mode 100644
index 0000000..ffac4a7
--- /dev/null
+++ b/Help/policy/CMP0074.rst
@@ -0,0 +1,22 @@
+CMP0074
+-------
+
+:command:`find_package` uses ``PackageName_ROOT`` variables.
+
+In CMake 3.12 and above the ``find_package(PackageName)`` command now searches
+a prefix specified by a ``PackageName_ROOT`` CMake or environment variable.
+Package roots are maintained as a stack so nested calls to all ``find_*``
+commands inside find modules also search the roots as prefixes. This policy
+provides compatibility with projects that have not been updated to avoid using
+``PackageName_ROOT`` variables for other purposes.
+
+The ``OLD`` behavior for this policy is to ignore ``PackageName_ROOT``
+variables. The ``NEW`` behavior for this policy is to use ``PackageName_ROOT``
+variables.
+
+This policy was introduced in CMake version 3.12. CMake version
+|release| warns when the policy is not set and uses ``OLD`` behavior.
+Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
+explicitly.
+
+.. include:: DEPRECATED.txt
diff --git a/Help/prop_dir/TESTS.rst b/Help/prop_dir/TESTS.rst
new file mode 100644
index 0000000..c6e1d88
--- /dev/null
+++ b/Help/prop_dir/TESTS.rst
@@ -0,0 +1,7 @@
+TESTS
+-----
+
+List of tests.
+
+This read-only property holds a :ref:`;-list <CMake Language Lists>` of tests
+defined so far by the :command:`add_test` command.
diff --git a/Help/prop_test/PROCESSORS.rst b/Help/prop_test/PROCESSORS.rst
index a1211fb..a927c10 100644
--- a/Help/prop_test/PROCESSORS.rst
+++ b/Help/prop_test/PROCESSORS.rst
@@ -2,6 +2,7 @@ PROCESSORS
----------
Set to specify how many process slots this test requires.
+If not set, the default is ``1`` processor.
Denotes the number of processors that this test will require. This is
typically used for MPI tests, and should be used in conjunction with
@@ -11,3 +12,5 @@ This will also be used to display a weighted test timing result in label and
subproject summaries in the command line output of :manual:`ctest(1)`. The wall
clock time for the test run will be multiplied by this property to give a
better idea of how much cpu resource CTest allocated for the test.
+
+See also the :prop_test:`PROCESSOR_AFFINITY` test property.
diff --git a/Help/prop_test/PROCESSOR_AFFINITY.rst b/Help/prop_test/PROCESSOR_AFFINITY.rst
new file mode 100644
index 0000000..38ec179
--- /dev/null
+++ b/Help/prop_test/PROCESSOR_AFFINITY.rst
@@ -0,0 +1,11 @@
+PROCESSOR_AFFINITY
+------------------
+
+Set to a true value to ask CTest to launch the test process with CPU affinity
+for a fixed set of processors. If enabled and supported for the current
+platform, CTest will choose a set of processors to place in the CPU affinity
+mask when launching the test process. The number of processors in the set is
+determined by the :prop_test:`PROCESSORS` test property or the number of
+processors available to CTest, whichever is smaller. The set of processors
+chosen will be disjoint from the processors assigned to other concurrently
+running tests that also have the ``PROCESSOR_AFFINITY`` property enabled.
diff --git a/Help/prop_test/WORKING_DIRECTORY.rst b/Help/prop_test/WORKING_DIRECTORY.rst
index 5222a19..92a0409 100644
--- a/Help/prop_test/WORKING_DIRECTORY.rst
+++ b/Help/prop_test/WORKING_DIRECTORY.rst
@@ -3,5 +3,7 @@ WORKING_DIRECTORY
The directory from which the test executable will be called.
-If this is not set it is called from the directory the test executable
-is located in.
+If this is not set, the test will be run with the working directory set to the
+binary directory associated with where the test was created (i.e. the
+:variable:`CMAKE_CURRENT_BINARY_DIR` for where :command:`add_test` was
+called).
diff --git a/Help/prop_tgt/EXPORT_PROPERTIES.rst b/Help/prop_tgt/EXPORT_PROPERTIES.rst
new file mode 100644
index 0000000..bcf47a6
--- /dev/null
+++ b/Help/prop_tgt/EXPORT_PROPERTIES.rst
@@ -0,0 +1,14 @@
+EXPORT_PROPERTIES
+-----------------
+
+List additional properties to export for a target.
+
+This property contains a list of property names that should be exported by
+the :command:`install(EXPORT)` and :command:`export` commands. By default
+only a limited number of properties are exported. This property can be used
+to additionally export other properties as well.
+
+Properties starting with ``INTERFACE_`` or ``IMPORTED_`` are not allowed as
+they are reserved for internal CMake use.
+
+Properties containing generator expressions are also not allowed.
diff --git a/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst b/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst
new file mode 100644
index 0000000..f898750
--- /dev/null
+++ b/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst
@@ -0,0 +1,9 @@
+VS_DEBUGGER_COMMAND
+-------------------
+
+Sets the local debugger command for Visual Studio C++ targets.
+This is defined in ``<LocalDebuggerCommand>`` in the Visual Studio
+project file.
+
+This property only works for Visual Studio 2010 and above;
+it is ignored on other generators.
diff --git a/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst b/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst
index 0af85cb..fb0389e 100644
--- a/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst
+++ b/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst
@@ -4,3 +4,6 @@ VS_DEBUGGER_WORKING_DIRECTORY
Sets the local debugger working directory for Visual Studio C++ targets.
This is defined in ``<LocalDebuggerWorkingDirectory>`` in the Visual Studio
project file.
+
+This property only works for Visual Studio 2010 and above;
+it is ignored on other generators.
diff --git a/Help/release/dev/0-sample-topic.rst b/Help/release/dev/0-sample-topic.rst
new file mode 100644
index 0000000..e4cc01e
--- /dev/null
+++ b/Help/release/dev/0-sample-topic.rst
@@ -0,0 +1,7 @@
+0-sample-topic
+--------------
+
+* This is a sample release note for the change in a topic.
+ Developers should add similar notes for each topic branch
+ making a noteworthy change. Each document should be named
+ and titled to match the topic name to avoid merge conflicts.
diff --git a/Help/release/dev/UseSWIG-modernize-module.rst b/Help/release/dev/UseSWIG-modernize-module.rst
new file mode 100644
index 0000000..925c119
--- /dev/null
+++ b/Help/release/dev/UseSWIG-modernize-module.rst
@@ -0,0 +1,6 @@
+UseSWIG-modernize-module
+------------------------
+
+* The :module:`UseSWIG` gained a whole refresh and is now more consistent with
+ standard CMake commands to generate libraries and is fully configurable through
+ properties.
diff --git a/Help/release/dev/avoid-LIB_DEPENDS.rst b/Help/release/dev/avoid-LIB_DEPENDS.rst
new file mode 100644
index 0000000..b89d8f9
--- /dev/null
+++ b/Help/release/dev/avoid-LIB_DEPENDS.rst
@@ -0,0 +1,5 @@
+avoid-LIB_DEPENDS
+-----------------
+
+* CMake no longer produces ``<tgt>_LIB_DEPENDS`` cache entries
+ for library targets. See policy :policy:`CMP0073`.
diff --git a/Help/release/dev/compile-options-shell.rst b/Help/release/dev/compile-options-shell.rst
new file mode 100644
index 0000000..3f83e0c
--- /dev/null
+++ b/Help/release/dev/compile-options-shell.rst
@@ -0,0 +1,6 @@
+compile-options-shell
+---------------------
+
+* :command:`target_compile_options` and :command:`add_compile_options`
+ commands gained a ``SHELL:`` prefix to specify a group of related
+ options using shell-like quoting.
diff --git a/Help/release/dev/ctest-affinity.rst b/Help/release/dev/ctest-affinity.rst
new file mode 100644
index 0000000..f4f72a5
--- /dev/null
+++ b/Help/release/dev/ctest-affinity.rst
@@ -0,0 +1,6 @@
+ctest-affinity
+--------------
+
+* A :prop_test:`PROCESSOR_AFFINITY` test property was added to request
+ that CTest run a test with CPU affinity for a set of processors
+ disjoint from other concurrently running tests with the property set.
diff --git a/Help/release/dev/curl-target.rst b/Help/release/dev/curl-target.rst
new file mode 100644
index 0000000..dc65f64
--- /dev/null
+++ b/Help/release/dev/curl-target.rst
@@ -0,0 +1,4 @@
+curl-target
+-----------
+
+* The :module:`FindCURL` module now provides imported targets.
diff --git a/Help/release/dev/directory-property-TESTS.rst b/Help/release/dev/directory-property-TESTS.rst
new file mode 100644
index 0000000..9de2531
--- /dev/null
+++ b/Help/release/dev/directory-property-TESTS.rst
@@ -0,0 +1,5 @@
+directory-property-TESTS
+------------------------
+
+* The :prop_dir:`TESTS` directory property was added to hold the list of tests defined by
+ command :command:`add_test`.
diff --git a/Help/release/dev/export-properties.rst b/Help/release/dev/export-properties.rst
new file mode 100644
index 0000000..9b20799
--- /dev/null
+++ b/Help/release/dev/export-properties.rst
@@ -0,0 +1,6 @@
+EXPORT_PROPERTIES
+-----------------
+
+* An :prop_tgt:`EXPORT_PROPERTIES` target property was added to specify a
+ custom list of target properties to include in targets exported by the
+ :command:`install(EXPORT)` and :command:`export` commands.
diff --git a/Help/release/dev/file_cmd_touch.rst b/Help/release/dev/file_cmd_touch.rst
new file mode 100644
index 0000000..b1b1e3c
--- /dev/null
+++ b/Help/release/dev/file_cmd_touch.rst
@@ -0,0 +1,6 @@
+file_cmd_touch
+------------------
+
+* The :command:`file(TOUCH)` and :command:`file(TOUCH_NOCREATE)` commands
+ were added to expose TOUCH functionality without having to use CMake's
+ command-line tool mode with :command:`execute_process`.
diff --git a/Help/release/dev/find-package_root-restore.rst b/Help/release/dev/find-package_root-restore.rst
new file mode 100644
index 0000000..3e6b69e
--- /dev/null
+++ b/Help/release/dev/find-package_root-restore.rst
@@ -0,0 +1,8 @@
+find-package_root-restore
+-------------------------
+
+* The :command:`find_package` command now searches a prefix specified by
+ a ``PackageName_ROOT`` CMake or environment variable. Package roots are
+ maintained as a stack so nested calls to all ``find_*`` commands inside
+ find modules also search the roots as prefixes.
+ See policy :policy:`CMP0074`.
diff --git a/Help/release/dev/genex-IN_LIST-logical-operator.rst b/Help/release/dev/genex-IN_LIST-logical-operator.rst
new file mode 100644
index 0000000..28fa7ce
--- /dev/null
+++ b/Help/release/dev/genex-IN_LIST-logical-operator.rst
@@ -0,0 +1,5 @@
+genex-IN_LIST-logical-operator
+------------------------------
+
+* A new ``$<IN_LIST:...>`` :manual:`generator expression <cmake-generator-expressions(7)>`
+ has been added.
diff --git a/Help/release/dev/genex-TARGET_EXISTS.rst b/Help/release/dev/genex-TARGET_EXISTS.rst
new file mode 100644
index 0000000..f305522
--- /dev/null
+++ b/Help/release/dev/genex-TARGET_EXISTS.rst
@@ -0,0 +1,6 @@
+genex-TARGET_EXISTS
+-------------------
+
+* A new ``$<TARGET_EXISTS:...>``
+ :manual:`generator expression <cmake-generator-expressions(7)>`
+ has been added.
diff --git a/Help/release/dev/libxml2-target.rst b/Help/release/dev/libxml2-target.rst
new file mode 100644
index 0000000..f9933d7
--- /dev/null
+++ b/Help/release/dev/libxml2-target.rst
@@ -0,0 +1,4 @@
+libxml2-target
+--------------
+
+* The :module:`FindLibXml2` module now provides imported targets.
diff --git a/Help/release/dev/object-library-linking.rst b/Help/release/dev/object-library-linking.rst
new file mode 100644
index 0000000..131430f
--- /dev/null
+++ b/Help/release/dev/object-library-linking.rst
@@ -0,0 +1,6 @@
+object-library-linking
+----------------------
+
+* The :command:`target_link_libraries` command now supports
+ :ref:`Object Libraries`. Linking to an object library uses its object
+ files in direct dependents and also propagates usage requirements.
diff --git a/Help/release/dev/project-homepage.rst b/Help/release/dev/project-homepage.rst
new file mode 100644
index 0000000..25799a4
--- /dev/null
+++ b/Help/release/dev/project-homepage.rst
@@ -0,0 +1,7 @@
+project-homepage
+----------------
+
+* The :command:`project` command learned an optional ``HOMEPAGE_URL``
+ parameter which has the effect of setting variables like
+ :variable:`PROJECT_HOMEPAGE_URL`, :variable:`<PROJECT-NAME>_HOMEPAGE_URL`
+ and :variable:`CMAKE_PROJECT_HOMEPAGE_URL`.
diff --git a/Help/release/dev/string-join.rst b/Help/release/dev/string-join.rst
new file mode 100644
index 0000000..5cca711
--- /dev/null
+++ b/Help/release/dev/string-join.rst
@@ -0,0 +1,5 @@
+string-join
+-----------
+
+* The :command:`string` command learned a ``JOIN`` sub-command
+ to concatenate input strings separated by a glue string.
diff --git a/Help/release/dev/variable-CMAKE_SUPPRESS_REGENERATION.rst b/Help/release/dev/variable-CMAKE_SUPPRESS_REGENERATION.rst
new file mode 100644
index 0000000..dfe678c
--- /dev/null
+++ b/Help/release/dev/variable-CMAKE_SUPPRESS_REGENERATION.rst
@@ -0,0 +1,6 @@
+variable-CMAKE_SUPPRESS_REGENERATION
+------------------------------------
+
+* The :variable:`CMAKE_SUPPRESS_REGENERATION` variable was extended to support the
+ :generator:`Ninja` and :ref:`Makefile Generators`.
+* The :variable:`CMAKE_SUPPRESS_REGENERATION` variable is now documented.
diff --git a/Help/release/dev/vs-debugger-config.rst b/Help/release/dev/vs-debugger-config.rst
new file mode 100644
index 0000000..bddae0c
--- /dev/null
+++ b/Help/release/dev/vs-debugger-config.rst
@@ -0,0 +1,6 @@
+vs-debugger-configuration
+-------------------------
+
+* For the :ref:`Visual Studio Generators` for VS 2010 and above
+ the debugging command line can be set using a new
+ :prop_tgt:`VS_DEBUGGER_COMMAND` target property.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 7375faf..552922e 100644
--- a/Help/release/index.rst
+++ b/Help/release/index.rst
@@ -7,6 +7,8 @@ CMake Release Notes
This file should include the adjacent "dev.txt" file
in development versions but not in release versions.
+.. include:: dev.txt
+
Releases
========
diff --git a/Help/variable/CMAKE_PROJECT_DESCRIPTION.rst b/Help/variable/CMAKE_PROJECT_DESCRIPTION.rst
index f1911ec..51b0592 100644
--- a/Help/variable/CMAKE_PROJECT_DESCRIPTION.rst
+++ b/Help/variable/CMAKE_PROJECT_DESCRIPTION.rst
@@ -1,7 +1,35 @@
CMAKE_PROJECT_DESCRIPTION
-------------------------
-The description of the current project.
+The description of the top level project.
-This specifies description of the current project from the closest inherited
-:command:`project` command.
+This variable holds the description of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. In the event that
+the top level CMakeLists.txt contains multiple :command:`project` calls,
+the most recently called one from that top level CMakeLists.txt will determine
+the value that ``CMAKE_PROJECT_DESCRIPTION`` contains. For example, consider
+the following top level CMakeLists.txt:
+
+.. code-block:: cmake
+
+ cmake_minimum_required(VERSION 3.0)
+ project(First DESCRIPTION "I am First")
+ project(Second DESCRIPTION "I am Second")
+ add_subdirectory(sub)
+ project(Third DESCRIPTION "I am Third")
+
+And ``sub/CMakeLists.txt`` with the following contents:
+
+.. code-block:: cmake
+
+ project(SubProj DESCRIPTION "I am SubProj")
+ message("CMAKE_PROJECT_DESCRIPTION = ${CMAKE_PROJECT_DESCRIPTION}")
+
+The most recently seen :command:`project` command from the top level
+CMakeLists.txt would be ``project(Second ...)``, so this will print::
+
+ CMAKE_PROJECT_DESCRIPTION = I am Second
+
+To obtain the description from the most recent call to :command:`project` in
+the current directory scope or above, see the :variable:`PROJECT_DESCRIPTION`
+variable.
diff --git a/Help/variable/CMAKE_PROJECT_HOMEPAGE_URL.rst b/Help/variable/CMAKE_PROJECT_HOMEPAGE_URL.rst
new file mode 100644
index 0000000..ee0bf7c
--- /dev/null
+++ b/Help/variable/CMAKE_PROJECT_HOMEPAGE_URL.rst
@@ -0,0 +1,35 @@
+CMAKE_PROJECT_HOMEPAGE_URL
+--------------------------
+
+The homepage URL of the top level project.
+
+This variable holds the homepage URL of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. In the event that
+the top level CMakeLists.txt contains multiple :command:`project` calls,
+the most recently called one from that top level CMakeLists.txt will determine
+the value that ``CMAKE_PROJECT_HOMEPAGE_URL`` contains. For example, consider
+the following top level CMakeLists.txt:
+
+.. code-block:: cmake
+
+ cmake_minimum_required(VERSION 3.0)
+ project(First HOMEPAGE_URL "http://first.example.com")
+ project(Second HOMEPAGE_URL "http://second.example.com")
+ add_subdirectory(sub)
+ project(Third HOMEPAGE_URL "http://third.example.com")
+
+And ``sub/CMakeLists.txt`` with the following contents:
+
+.. code-block:: cmake
+
+ project(SubProj HOMEPAGE_URL "http://subproj.example.com")
+ message("CMAKE_PROJECT_HOMEPAGE_URL = ${CMAKE_PROJECT_HOMEPAGE_URL}")
+
+The most recently seen :command:`project` command from the top level
+CMakeLists.txt would be ``project(Second ...)``, so this will print::
+
+ CMAKE_PROJECT_HOMEPAGE_URL = http://second.example.com
+
+To obtain the homepage URL from the most recent call to :command:`project` in
+the current directory scope or above, see the :variable:`PROJECT_HOMEPAGE_URL`
+variable.
diff --git a/Help/variable/CMAKE_PROJECT_NAME.rst b/Help/variable/CMAKE_PROJECT_NAME.rst
index 431e9f3..94b8dba 100644
--- a/Help/variable/CMAKE_PROJECT_NAME.rst
+++ b/Help/variable/CMAKE_PROJECT_NAME.rst
@@ -1,7 +1,35 @@
CMAKE_PROJECT_NAME
------------------
-The name of the current project.
+The name of the top level project.
-This specifies name of the current project from the closest inherited
-:command:`project` command.
+This variable holds the name of the project as specified in the top
+level CMakeLists.txt file by a :command:`project` command. In the event that
+the top level CMakeLists.txt contains multiple :command:`project` calls,
+the most recently called one from that top level CMakeLists.txt will determine
+the name that ``CMAKE_PROJECT_NAME`` contains. For example, consider
+the following top level CMakeLists.txt:
+
+.. code-block:: cmake
+
+ cmake_minimum_required(VERSION 3.0)
+ project(First)
+ project(Second)
+ add_subdirectory(sub)
+ project(Third)
+
+And ``sub/CMakeLists.txt`` with the following contents:
+
+.. code-block:: cmake
+
+ project(SubProj)
+ message("CMAKE_PROJECT_NAME = ${CMAKE_PROJECT_NAME}")
+
+The most recently seen :command:`project` command from the top level
+CMakeLists.txt would be ``project(Second)``, so this will print::
+
+ CMAKE_PROJECT_NAME = Second
+
+To obtain the name from the most recent call to :command:`project` in
+the current directory scope or above, see the :variable:`PROJECT_NAME`
+variable.
diff --git a/Help/variable/CMAKE_SUPPRESS_REGENERATION.rst b/Help/variable/CMAKE_SUPPRESS_REGENERATION.rst
new file mode 100644
index 0000000..ed47e1a
--- /dev/null
+++ b/Help/variable/CMAKE_SUPPRESS_REGENERATION.rst
@@ -0,0 +1,11 @@
+CMAKE_SUPPRESS_REGENERATION
+---------------------------
+
+If CMAKE_SUPPRESS_REGENERATION is ``OFF``, which is default, then CMake adds a
+special target on which all other targets depend that checks the build system
+and optionally re-runs CMake to regenerate the build system when the target
+specification source changes.
+
+If this variable evaluates to ``ON`` at the end of the top-level
+``CMakeLists.txt`` file, CMake will not add the regeneration target to the
+build system or perform any build system checks.
diff --git a/Help/variable/PROJECT-NAME_DESCRIPTION.rst b/Help/variable/PROJECT-NAME_DESCRIPTION.rst
new file mode 100644
index 0000000..2b88b1a
--- /dev/null
+++ b/Help/variable/PROJECT-NAME_DESCRIPTION.rst
@@ -0,0 +1,5 @@
+<PROJECT-NAME>_DESCRIPTION
+--------------------------
+
+Value given to the ``DESCRIPTION`` option of the most recent call to the
+:command:`project` command with project name ``<PROJECT-NAME>``, if any.
diff --git a/Help/variable/PROJECT-NAME_HOMEPAGE_URL.rst b/Help/variable/PROJECT-NAME_HOMEPAGE_URL.rst
new file mode 100644
index 0000000..22cc304
--- /dev/null
+++ b/Help/variable/PROJECT-NAME_HOMEPAGE_URL.rst
@@ -0,0 +1,5 @@
+<PROJECT-NAME>_HOMEPAGE_URL
+---------------------------
+
+Value given to the ``HOMEPAGE_URL`` option of the most recent call to the
+:command:`project` command with project name ``<PROJECT-NAME>``, if any.
diff --git a/Help/variable/PROJECT_DESCRIPTION.rst b/Help/variable/PROJECT_DESCRIPTION.rst
index 05ede8f..2833e11 100644
--- a/Help/variable/PROJECT_DESCRIPTION.rst
+++ b/Help/variable/PROJECT_DESCRIPTION.rst
@@ -3,4 +3,7 @@ PROJECT_DESCRIPTION
Short project description given to the project command.
-This is the description given to the most recent :command:`project` command.
+This is the description given to the most recently called :command:`project`
+command in the current directory scope or above. To obtain the description
+of the top level project, see the :variable:`CMAKE_PROJECT_DESCRIPTION`
+variable.
diff --git a/Help/variable/PROJECT_HOMEPAGE_URL.rst b/Help/variable/PROJECT_HOMEPAGE_URL.rst
new file mode 100644
index 0000000..754c9e8
--- /dev/null
+++ b/Help/variable/PROJECT_HOMEPAGE_URL.rst
@@ -0,0 +1,9 @@
+PROJECT_HOMEPAGE_URL
+--------------------
+
+The homepage URL of the project.
+
+This is the homepage URL given to the most recently called :command:`project`
+command in the current directory scope or above. To obtain the homepage URL
+of the top level project, see the :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
+variable.
diff --git a/Help/variable/PROJECT_NAME.rst b/Help/variable/PROJECT_NAME.rst
index 61aa8bc..672680a 100644
--- a/Help/variable/PROJECT_NAME.rst
+++ b/Help/variable/PROJECT_NAME.rst
@@ -3,4 +3,6 @@ PROJECT_NAME
Name of the project given to the project command.
-This is the name given to the most recent :command:`project` command.
+This is the name given to the most recently called :command:`project`
+command in the current directory scope or above. To obtain the name of
+the top level project, see the :variable:`CMAKE_PROJECT_NAME` variable.
diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake
index cf502f6..5ddd64f 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -66,12 +66,20 @@ else()
# The order is 95 or newer compilers first, then 90,
# then 77 or older compilers, gnu is always last in the group,
# so if you paid for a compiler it is picked by default.
- set(CMAKE_Fortran_COMPILER_LIST
- ftn
- ifort ifc af95 af90 efc f95 pathf2003 pathf95 pgf95 pgfortran lf95 xlf95
- fort flang gfortran gfortran-4 g95 f90 pathf90 pgf90 xlf90 epcf90 fort77
- frt pgf77 xlf fl32 af77 g77 f77 nag
- )
+ if(CMAKE_HOST_WIN32)
+ set(CMAKE_Fortran_COMPILER_LIST
+ ifort pgf95 pgfortran lf95 fort
+ flang gfortran gfortran-4 g95 f90 pgf90
+ pgf77 g77 f77 nag
+ )
+ else()
+ set(CMAKE_Fortran_COMPILER_LIST
+ ftn
+ ifort ifc efc pgf95 pgfortran lf95 xlf95 fort
+ flang gfortran gfortran-4 g95 f90 pgf90
+ frt pgf77 xlf g77 f77 nag
+ )
+ endif()
# Vendor-specific compiler names.
set(_Fortran_COMPILER_NAMES_GNU gfortran gfortran-4 g95 g77)
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index ece0547..1b6823c 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -19,6 +19,25 @@
# on UNIX, cygwin and mingw
+if(CMAKE_LINKER)
+ # we only get here if CMAKE_LINKER was specified using -D or a pre-made CMakeCache.txt
+ # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
+ # find the linker in the PATH if necessary
+ get_filename_component(_CMAKE_USER_LINKER_PATH "${CMAKE_LINKER}" PATH)
+ if(NOT _CMAKE_USER_LINKER_PATH)
+ find_program(CMAKE_LINKER_WITH_PATH NAMES ${CMAKE_LINKER} HINTS ${_CMAKE_TOOLCHAIN_LOCATION})
+ if(CMAKE_LINKER_WITH_PATH)
+ set(CMAKE_LINKER ${CMAKE_LINKER_WITH_PATH})
+ get_property(_CMAKE_LINKER_CACHED CACHE CMAKE_LINKER PROPERTY TYPE)
+ if(_CMAKE_LINKER_CACHED)
+ set(CMAKE_LINKER "${CMAKE_LINKER}" CACHE STRING "Default Linker" FORCE)
+ endif()
+ unset(_CMAKE_LINKER_CACHED)
+ endif()
+ unset(CMAKE_LINKER_WITH_PATH CACHE)
+ endif()
+endif()
+
# if it's the MS C/CXX compiler, search for link
if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC"
OR "x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL "xMSVC"
diff --git a/Modules/CMakeTestCSharpCompiler.cmake b/Modules/CMakeTestCSharpCompiler.cmake
index f3b95fd..6715c30 100644
--- a/Modules/CMakeTestCSharpCompiler.cmake
+++ b/Modules/CMakeTestCSharpCompiler.cmake
@@ -15,7 +15,7 @@ unset(CMAKE_CSharp_COMPILER_WORKS CACHE)
set(test_compile_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCSharpCompiler.cs")
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected C# compiler can actually compile
+# determine that the selected C# compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake
index df5ec72..f0454da 100644
--- a/Modules/CMakeTestCUDACompiler.cmake
+++ b/Modules/CMakeTestCUDACompiler.cmake
@@ -15,7 +15,7 @@ include(CMakeTestCompilerCommon)
unset(CMAKE_CUDA_COMPILER_WORKS CACHE)
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected cuda compiler can actually compile
+# determine that the selected cuda compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake
index 7b80dc0..e4d49ae 100644
--- a/Modules/CMakeTestCXXCompiler.cmake
+++ b/Modules/CMakeTestCXXCompiler.cmake
@@ -16,7 +16,7 @@ include(CMakeTestCompilerCommon)
unset(CMAKE_CXX_COMPILER_WORKS CACHE)
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected C++ compiler can actually compile
+# determine that the selected C++ compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake
index 3c150a8..e9860e9 100644
--- a/Modules/CMakeTestFortranCompiler.cmake
+++ b/Modules/CMakeTestFortranCompiler.cmake
@@ -16,7 +16,7 @@ include(CMakeTestCompilerCommon)
unset(CMAKE_Fortran_COMPILER_WORKS CACHE)
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected Fortran compiler can actually compile
+# determine that the selected Fortran compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
diff --git a/Modules/CMakeTestJavaCompiler.cmake b/Modules/CMakeTestJavaCompiler.cmake
index 23fdbdc..3c33573 100644
--- a/Modules/CMakeTestJavaCompiler.cmake
+++ b/Modules/CMakeTestJavaCompiler.cmake
@@ -3,7 +3,7 @@
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected Fortran compiler can actually compile
+# determine that the selected Fortran compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
diff --git a/Modules/CMakeTestRCCompiler.cmake b/Modules/CMakeTestRCCompiler.cmake
index c510d3a..3123a6c 100644
--- a/Modules/CMakeTestRCCompiler.cmake
+++ b/Modules/CMakeTestRCCompiler.cmake
@@ -3,7 +3,7 @@
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected RC compiler can actually compile
+# determine that the selected RC compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
diff --git a/Modules/CMakeTestSwiftCompiler.cmake b/Modules/CMakeTestSwiftCompiler.cmake
index bcd5c33..858c1be 100644
--- a/Modules/CMakeTestSwiftCompiler.cmake
+++ b/Modules/CMakeTestSwiftCompiler.cmake
@@ -16,7 +16,7 @@ include(CMakeTestCompilerCommon)
unset(CMAKE_Swift_COMPILER_WORKS CACHE)
# This file is used by EnableLanguage in cmGlobalGenerator to
-# determine that that selected C++ compiler can actually compile
+# determine that the selected C++ compiler can actually compile
# and link the most basic of programs. If not, a fatal error
# is set and cmake stops processing commands and will not generate
# any makefiles or projects.
diff --git a/Modules/CPackDeb.cmake b/Modules/CPackDeb.cmake
index 35447c9..444f632 100644
--- a/Modules/CPackDeb.cmake
+++ b/Modules/CPackDeb.cmake
@@ -254,7 +254,7 @@
# upstream documentation or information may be found.
#
# * Mandatory : NO
-# * Default : -
+# * Default : :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
#
# .. note::
#
@@ -914,6 +914,11 @@ function(cpack_deb_prepare_package_vars)
endif()
endif()
+ # Homepage: (optional)
+ if(NOT CPACK_DEBIAN_PACKAGE_HOMEPAGE AND CMAKE_PROJECT_HOMEPAGE_URL)
+ set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${CMAKE_PROJECT_HOMEPAGE_URL}")
+ endif()
+
# Section: (recommended)
if(NOT CPACK_DEBIAN_PACKAGE_SECTION)
set(CPACK_DEBIAN_PACKAGE_SECTION "devel")
diff --git a/Modules/CPackFreeBSD.cmake b/Modules/CPackFreeBSD.cmake
index 7fec78a..b681d4f 100644
--- a/Modules/CPackFreeBSD.cmake
+++ b/Modules/CPackFreeBSD.cmake
@@ -80,7 +80,8 @@ the RPM information (e.g. package license).
* Mandatory: YES
* Default:
- - :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
+ - :variable:`CMAKE_PROJECT_HOMEPAGE_URL`, or if that is not set,
+ :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
for Debian packaging, so we may as well re-use it).
.. variable:: CPACK_FREEBSD_PACKAGE_LICENSE
@@ -208,6 +209,7 @@ _cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_DESCRIPTION"
# There's really only one homepage for a project, so
# re-use the Debian setting if it's there.
_cpack_freebsd_fallback_var("CPACK_FREEBSD_PACKAGE_WWW"
+ "CMAKE_PROJECT_HOMEPAGE_URL"
"CPACK_DEBIAN_PACKAGE_HOMEPAGE"
"_cpack_freebsd_fallback_www"
)
diff --git a/Modules/CPackNSIS.cmake b/Modules/CPackNSIS.cmake
index 18d1871..5bc4395 100644
--- a/Modules/CPackNSIS.cmake
+++ b/Modules/CPackNSIS.cmake
@@ -126,7 +126,7 @@
# .. 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
+# "link" "link name". The link may be a URL or a path relative to
# installation prefix. Like::
#
# set(CPACK_NSIS_MENU_LINKS
diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake
index bb5181f..87385de 100644
--- a/Modules/CPackRPM.cmake
+++ b/Modules/CPackRPM.cmake
@@ -191,7 +191,7 @@
# The projects URL.
#
# * Mandatory : NO
-# * Default : -
+# * Default : :variable:`CMAKE_PROJECT_HOMEPAGE_URL`
#
# .. variable:: CPACK_RPM_PACKAGE_DESCRIPTION
# CPACK_RPM_<component>_PACKAGE_DESCRIPTION
@@ -1787,6 +1787,10 @@ function(cpack_rpm_generate_package)
endif()
endif()
+ if(NOT CPACK_RPM_PACKAGE_URL AND CMAKE_PROJECT_HOMEPAGE_URL)
+ set(CPACK_RPM_PACKAGE_URL "${CMAKE_PROJECT_HOMEPAGE_URL}")
+ endif()
+
# CPACK_RPM_PACKAGE_NAME (mandatory)
if(NOT CPACK_RPM_PACKAGE_NAME)
string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_RPM_PACKAGE_NAME)
@@ -1984,7 +1988,7 @@ function(cpack_rpm_generate_package)
endif()
if(DEFINED CPACK_RPM_PACKAGE_${_RPM_SPEC_HEADER})
- # Prefix can be replaced by Prefixes but the old version stil works so we'll ignore it for now
+ # Prefix can be replaced by Prefixes but the old version still works so we'll ignore it for now
# Requires* is a special case because it gets transformed to Requires(pre/post/preun/postun)
# Auto* is a special case because the tags can not be queried by querytags rpmbuild flag
set(special_case_tags_ PREFIX REQUIRES_PRE REQUIRES_POST REQUIRES_PREUN REQUIRES_POSTUN AUTOPROV AUTOREQ AUTOREQPROV)
diff --git a/Modules/CheckCSourceRuns.cmake b/Modules/CheckCSourceRuns.cmake
index fa51346..7eb050c 100644
--- a/Modules/CheckCSourceRuns.cmake
+++ b/Modules/CheckCSourceRuns.cmake
@@ -92,7 +92,8 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR)
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
-DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
"${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}"
- COMPILE_OUTPUT_VARIABLE OUTPUT)
+ COMPILE_OUTPUT_VARIABLE OUTPUT
+ RUN_OUTPUT_VARIABLE RUN_OUTPUT)
# if it did not compile make the return value fail code of 1
if(NOT ${VAR}_COMPILED)
set(${VAR}_EXITCODE 1)
@@ -104,8 +105,10 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR)
message(STATUS "Performing Test ${VAR} - Success")
endif()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
- "Performing C SOURCE FILE Test ${VAR} succeeded with the following output:\n"
+ "Performing C SOURCE FILE Test ${VAR} succeeded with the following compile output:\n"
"${OUTPUT}\n"
+ "...and run output:\n"
+ "${RUN_OUTPUT}\n"
"Return value: ${${VAR}}\n"
"Source file was:\n${SOURCE}\n")
else()
@@ -119,8 +122,10 @@ macro(CHECK_C_SOURCE_RUNS SOURCE VAR)
message(STATUS "Performing Test ${VAR} - Failed")
endif()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
- "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
+ "Performing C SOURCE FILE Test ${VAR} failed with the following compile output:\n"
"${OUTPUT}\n"
+ "...and run output:\n"
+ "${RUN_OUTPUT}\n"
"Return value: ${${VAR}_EXITCODE}\n"
"Source file was:\n${SOURCE}\n")
diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake
index 7331fb2..e5dbcd9 100644
--- a/Modules/ExternalData.cmake
+++ b/Modules/ExternalData.cmake
@@ -1133,7 +1133,7 @@ if("${ExternalData_ACTION}" STREQUAL "fetch")
if(file_up_to_date)
# Touch the file to convince the build system it is up to date.
- execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${file}")
+ file(TOUCH "${file}")
else()
_ExternalData_link_or_copy("${obj}" "${file}")
endif()
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index 0a31ac2..119fc13 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -175,7 +175,7 @@
# -- Same as CUDA_ADD_EXECUTABLE except that a library is created.
#
# CUDA_BUILD_CLEAN_TARGET()
-# -- Creates a convience target that deletes all the dependency files
+# -- Creates a convenience target that deletes all the dependency files
# generated. You should make clean after running this target to ensure the
# dependency files get regenerated.
#
@@ -1564,7 +1564,7 @@ macro(CUDA_WRAP_SRCS cuda_target format generated_files)
# Bring in the dependencies. Creates a variable CUDA_NVCC_DEPEND #######
cuda_include_nvcc_dependencies(${cmake_dependency_file})
- # Convience string for output ###########################################
+ # Convenience string for output #########################################
if(CUDA_BUILD_EMULATION)
set(cuda_build_type "Emulation")
else()
@@ -1975,9 +1975,9 @@ endmacro()
###############################################################################
###############################################################################
macro(CUDA_BUILD_CLEAN_TARGET)
- # Call this after you add all your CUDA targets, and you will get a convience
- # target. You should also make clean after running this target to get the
- # build system to generate all the code again.
+ # Call this after you add all your CUDA targets, and you will get a
+ # convenience target. You should also make clean after running this target
+ # to get the build system to generate all the code again.
set(cuda_clean_target_name clean_cuda_depends)
if (CMAKE_GENERATOR MATCHES "Visual Studio")
diff --git a/Modules/FindCURL.cmake b/Modules/FindCURL.cmake
index f4bcc36..e66ae92 100644
--- a/Modules/FindCURL.cmake
+++ b/Modules/FindCURL.cmake
@@ -5,16 +5,30 @@
# FindCURL
# --------
#
-# Find curl
-#
# Find the native CURL headers and libraries.
#
-# ::
+# IMPORTED Targets
+# ^^^^^^^^^^^^^^^^
+#
+# This module defines :prop_tgt:`IMPORTED` target ``CURL::CURL``, if
+# curl has been found.
+#
+# Result Variables
+# ^^^^^^^^^^^^^^^^
+#
+# This module defines the following variables:
#
-# CURL_INCLUDE_DIRS - where to find curl/curl.h, etc.
-# CURL_LIBRARIES - List of libraries when using curl.
-# CURL_FOUND - True if curl found.
-# CURL_VERSION_STRING - the version of curl found (since CMake 2.8.8)
+# ``CURL_FOUND``
+# True if curl found.
+#
+# ``CURL_INCLUDE_DIRS``
+# where to find curl/curl.h, etc.
+#
+# ``CURL_LIBRARIES``
+# List of libraries when using curl.
+#
+# ``CURL_VERSION_STRING``
+# The version of curl found.
# Look for the header file.
find_path(CURL_INCLUDE_DIR NAMES curl/curl.h)
@@ -52,4 +66,10 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(CURL
if(CURL_FOUND)
set(CURL_LIBRARIES ${CURL_LIBRARY})
set(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR})
+
+ if(NOT TARGET CURL::CURL)
+ add_library(CURL::CURL UNKNOWN IMPORTED)
+ set_target_properties(CURL::CURL PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CURL_INCLUDE_DIRS}")
+ set_property(TARGET CURL::CURL APPEND PROPERTY IMPORTED_LOCATION "${CURL_LIBRARY}")
+ endif()
endif()
diff --git a/Modules/FindGDAL.cmake b/Modules/FindGDAL.cmake
index 2b940b0..ff2976e 100644
--- a/Modules/FindGDAL.cmake
+++ b/Modules/FindGDAL.cmake
@@ -66,11 +66,49 @@ if(UNIX)
if(GDAL_CONFIG)
exec_program(${GDAL_CONFIG} ARGS --libs OUTPUT_VARIABLE GDAL_CONFIG_LIBS)
+
if(GDAL_CONFIG_LIBS)
- string(REGEX MATCHALL "-l[^ ]+" _gdal_dashl ${GDAL_CONFIG_LIBS})
- string(REPLACE "-l" "" _gdal_lib "${_gdal_dashl}")
- string(REGEX MATCHALL "-L[^ ]+" _gdal_dashL ${GDAL_CONFIG_LIBS})
- string(REPLACE "-L" "" _gdal_libpath "${_gdal_dashL}")
+ # treat the output as a command line and split it up
+ separate_arguments(args NATIVE_COMMAND "${GDAL_CONFIG_LIBS}")
+
+ # only consider libraries whose name matches this pattern
+ set(name_pattern "[gG][dD][aA][lL]")
+
+ # consider each entry as a possible library path, name, or parent directory
+ foreach(arg IN LISTS args)
+ # library name
+ if("${arg}" MATCHES "^-l(.*)$")
+ set(lib "${CMAKE_MATCH_1}")
+
+ # only consider libraries whose name matches the expected pattern
+ if("${lib}" MATCHES "${name_pattern}")
+ list(APPEND _gdal_lib "${lib}")
+ endif()
+ # library search path
+ elseif("${arg}" MATCHES "^-L(.*)$")
+ list(APPEND _gdal_libpath "${CMAKE_MATCH_1}")
+ # assume this is a full path to a library
+ elseif(IS_ABSOLUTE "${arg}" AND EXISTS "${arg}")
+ # extract the file name
+ get_filename_component(lib "${arg}" NAME)
+
+ # only consider libraries whose name matches the expected pattern
+ if(NOT "${lib}" MATCHES "${name_pattern}")
+ continue()
+ endif()
+
+ # extract the file directory
+ get_filename_component(dir "${arg}" DIRECTORY)
+
+ # remove library prefixes/suffixes
+ string(REGEX REPLACE "^(${CMAKE_SHARED_LIBRARY_PREFIX}|${CMAKE_STATIC_LIBRARY_PREFIX})" "" lib "${lib}")
+ string(REGEX REPLACE "(${CMAKE_SHARED_LIBRARY_SUFFIX}|${CMAKE_STATIC_LIBRARY_SUFFIX})$" "" lib "${lib}")
+
+ # use the file name and directory as hints
+ list(APPEND _gdal_libpath "${dir}")
+ list(APPEND _gdal_lib "${lib}")
+ endif()
+ endforeach()
endif()
endif()
endif()
diff --git a/Modules/FindJava.cmake b/Modules/FindJava.cmake
index e3f5af6..c56c197 100644
--- a/Modules/FindJava.cmake
+++ b/Modules/FindJava.cmake
@@ -18,7 +18,7 @@
# ::
#
# Runtime = User just want to execute some Java byte-compiled
-# Development = Development tools (java, javac, javah and javadoc), includes Runtime component
+# Development = Development tools (java, javac, javah, jar and javadoc), includes Runtime component
# IdlJ = idl compiler for Java
# JarSigner = signer tool for jar
#
@@ -237,16 +237,16 @@ if(Java_FIND_COMPONENTS)
endif()
elseif(component STREQUAL "Development")
list(APPEND _JAVA_REQUIRED_VARS Java_JAVA_EXECUTABLE Java_JAVAC_EXECUTABLE
- Java_JAVADOC_EXECUTABLE)
+ Java_JAR_EXECUTABLE Java_JAVADOC_EXECUTABLE)
if(Java_VERSION VERSION_LESS "1.10")
list(APPEND _JAVA_REQUIRED_VARS Java_JAVAH_EXECUTABLE)
if(Java_JAVA_EXECUTABLE AND Java_JAVAC_EXECUTABLE
- AND Java_JAVAH_EXECUTABLE AND Java_JAVADOC_EXECUTABLE)
+ AND Java_JAVAH_EXECUTABLE AND Java_JAR_EXECUTABLE AND Java_JAVADOC_EXECUTABLE)
set(Java_Development_FOUND TRUE)
endif()
else()
if(Java_JAVA_EXECUTABLE AND Java_JAVAC_EXECUTABLE
- AND Java_JAVADOC_EXECUTABLE)
+ AND Java_JAR_EXECUTABLE AND Java_JAVADOC_EXECUTABLE)
set(Java_Development_FOUND TRUE)
endif()
endif()
diff --git a/Modules/FindLibXml2.cmake b/Modules/FindLibXml2.cmake
index 8ac2980..615de49 100644
--- a/Modules/FindLibXml2.cmake
+++ b/Modules/FindLibXml2.cmake
@@ -7,6 +7,12 @@
#
# Find the XML processing library (libxml2).
#
+# IMPORTED Targets
+# ^^^^^^^^^^^^^^^^
+#
+# This module defines :prop_tgt:`IMPORTED` target ``LibXml2::LibXml2``, if
+# libxml2 has been found.
+#
# Result variables
# ^^^^^^^^^^^^^^^^
#
@@ -87,3 +93,9 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXml2
VERSION_VAR LIBXML2_VERSION_STRING)
mark_as_advanced(LIBXML2_INCLUDE_DIR LIBXML2_LIBRARY LIBXML2_XMLLINT_EXECUTABLE)
+
+if(LibXml2_FOUND AND NOT TARGET LibXml2::LibXml2)
+ add_library(LibXml2::LibXml2 UNKNOWN IMPORTED)
+ set_target_properties(LibXml2::LibXml2 PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBXML2_INCLUDE_DIRS}")
+ set_property(TARGET LibXml2::LibXml2 APPEND PROPERTY IMPORTED_LOCATION "${LIBXML2_LIBRARY}")
+endif()
diff --git a/Modules/FindLua.cmake b/Modules/FindLua.cmake
index b59b9b3..7eba206 100644
--- a/Modules/FindLua.cmake
+++ b/Modules/FindLua.cmake
@@ -122,6 +122,7 @@ endif ()
if (NOT LUA_VERSION_STRING)
foreach (subdir IN LISTS _lua_include_subdirs)
unset(LUA_INCLUDE_PREFIX CACHE)
+ unset(LUA_INCLUDE_PREFIX)
find_path(LUA_INCLUDE_PREFIX ${subdir}/lua.h
HINTS
ENV LUA_DIR
diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index ced092e..e252ba5 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -85,6 +85,7 @@ function(_OPENMP_FLAG_CANDIDATES LANG)
set(OMP_FLAG_GNU "-fopenmp")
set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp")
+ set(OMP_FLAG_AppleClang "-Xclang -fopenmp")
set(OMP_FLAG_HP "+Oopenmp")
if(WIN32)
set(OMP_FLAG_Intel "-Qopenmp")
@@ -125,6 +126,7 @@ set(OpenMP_C_CXX_TEST_SOURCE
#include <omp.h>
int main() {
#ifdef _OPENMP
+ int n = omp_get_max_threads();
return 0;
#else
breaks_on_purpose
@@ -163,7 +165,7 @@ function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_F
set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE)
endfunction()
-include(${CMAKE_ROOT}/Modules/CMakeParseImplicitLinkInfo.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseImplicitLinkInfo.cmake)
function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
_OPENMP_FLAG_CANDIDATES("${LANG}")
@@ -255,6 +257,28 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
endif()
endif()
break()
+ elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "AppleClang"
+ AND CMAKE_${LANG}_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0")
+
+ # Check for separate OpenMP library on AppleClang 7+
+ find_library(OpenMP_libomp_LIBRARY
+ NAMES omp gomp iomp5
+ HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES}
+ )
+ mark_as_advanced(OpenMP_libomp_LIBRARY)
+
+ if(OpenMP_libomp_LIBRARY)
+ try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC}
+ CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}"
+ LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY}
+ OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT
+ )
+ if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG})
+ set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE)
+ set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE)
+ break()
+ endif()
+ endif()
endif()
set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE)
set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE)
@@ -423,6 +447,8 @@ endif()
unset(_OpenMP_MIN_VERSION)
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+
foreach(LANG IN LISTS OpenMP_FINDLIST)
if(CMAKE_${LANG}_COMPILER_LOADED)
if (NOT OpenMP_${LANG}_SPEC_DATE AND OpenMP_${LANG}_FLAGS)
@@ -432,8 +458,6 @@ foreach(LANG IN LISTS OpenMP_FINDLIST)
_OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}")
endif()
- include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
-
set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY})
set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED})
set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION})
diff --git a/Modules/FindZLIB.cmake b/Modules/FindZLIB.cmake
index 4065999..a5c04ac 100644
--- a/Modules/FindZLIB.cmake
+++ b/Modules/FindZLIB.cmake
@@ -75,8 +75,8 @@ endforeach()
# Allow ZLIB_LIBRARY to be set manually, as the location of the zlib library
if(NOT ZLIB_LIBRARY)
foreach(search ${_ZLIB_SEARCHES})
- find_library(ZLIB_LIBRARY_RELEASE NAMES ${ZLIB_NAMES} ${${search}} PATH_SUFFIXES lib)
- find_library(ZLIB_LIBRARY_DEBUG NAMES ${ZLIB_NAMES_DEBUG} ${${search}} PATH_SUFFIXES lib)
+ find_library(ZLIB_LIBRARY_RELEASE NAMES ${ZLIB_NAMES} NAMES_PER_DIR ${${search}} PATH_SUFFIXES lib)
+ find_library(ZLIB_LIBRARY_DEBUG NAMES ${ZLIB_NAMES_DEBUG} NAMES_PER_DIR ${${search}} PATH_SUFFIXES lib)
endforeach()
include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
diff --git a/Modules/FindwxWidgets.cmake b/Modules/FindwxWidgets.cmake
index e21ec38..965948e 100644
--- a/Modules/FindwxWidgets.cmake
+++ b/Modules/FindwxWidgets.cmake
@@ -837,7 +837,7 @@ else()
# extract linkdirs (-L) for rpath (i.e., LINK_DIRECTORIES)
string(REGEX MATCHALL "-L[^;]+"
wxWidgets_LIBRARY_DIRS "${wxWidgets_LIBRARIES}")
- string(REPLACE "-L" ""
+ string(REGEX REPLACE "-L([^;]+)" "\\1"
wxWidgets_LIBRARY_DIRS "${wxWidgets_LIBRARY_DIRS}")
DBG_MSG_V("wxWidgets_LIBRARIES=${wxWidgets_LIBRARIES}")
diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake
index 17a3357..e6dcd00 100644
--- a/Modules/GenerateExportHeader.cmake
+++ b/Modules/GenerateExportHeader.cmake
@@ -185,6 +185,7 @@
# :prop_tgt:`CXX_VISIBILITY_PRESET <<LANG>_VISIBILITY_PRESET>` and
# :prop_tgt:`VISIBILITY_INLINES_HIDDEN` instead.
+include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
# TODO: Install this macro separately?
@@ -194,6 +195,13 @@ macro(_check_cxx_compiler_attribute _ATTRIBUTE _RESULT)
)
endmacro()
+# TODO: Install this macro separately?
+macro(_check_c_compiler_attribute _ATTRIBUTE _RESULT)
+ check_c_source_compiles("${_ATTRIBUTE} int somefunc() { return 0; }
+ int main() { return somefunc();}" ${_RESULT}
+ )
+endmacro()
+
macro(_test_compiler_hidden_visibility)
if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.2")
@@ -213,9 +221,15 @@ macro(_test_compiler_hidden_visibility)
AND NOT CMAKE_CXX_COMPILER_ID MATCHES XL
AND NOT CMAKE_CXX_COMPILER_ID MATCHES PGI
AND NOT CMAKE_CXX_COMPILER_ID MATCHES Watcom)
- check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
- check_cxx_compiler_flag(-fvisibility-inlines-hidden
- COMPILER_HAS_HIDDEN_INLINE_VISIBILITY)
+ if (CMAKE_CXX_COMPILER_LOADED)
+ check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
+ check_cxx_compiler_flag(-fvisibility-inlines-hidden
+ COMPILER_HAS_HIDDEN_INLINE_VISIBILITY)
+ else()
+ check_c_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY)
+ check_c_compiler_flag(-fvisibility-inlines-hidden
+ COMPILER_HAS_HIDDEN_INLINE_VISIBILITY)
+ endif()
endif()
endmacro()
@@ -232,14 +246,27 @@ macro(_test_compiler_has_deprecated)
set(COMPILER_HAS_DEPRECATED "" CACHE INTERNAL
"Compiler support for a deprecated attribute")
else()
- _check_cxx_compiler_attribute("__attribute__((__deprecated__))"
- COMPILER_HAS_DEPRECATED_ATTR)
- if(COMPILER_HAS_DEPRECATED_ATTR)
- set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}"
- CACHE INTERNAL "Compiler support for a deprecated attribute")
+ if (CMAKE_CXX_COMPILER_LOADED)
+ _check_cxx_compiler_attribute("__attribute__((__deprecated__))"
+ COMPILER_HAS_DEPRECATED_ATTR)
+ if(COMPILER_HAS_DEPRECATED_ATTR)
+ set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}"
+ CACHE INTERNAL "Compiler support for a deprecated attribute")
+ else()
+ _check_cxx_compiler_attribute("__declspec(deprecated)"
+ COMPILER_HAS_DEPRECATED)
+ endif()
else()
- _check_cxx_compiler_attribute("__declspec(deprecated)"
- COMPILER_HAS_DEPRECATED)
+ _check_c_compiler_attribute("__attribute__((__deprecated__))"
+ COMPILER_HAS_DEPRECATED_ATTR)
+ if(COMPILER_HAS_DEPRECATED_ATTR)
+ set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}"
+ CACHE INTERNAL "Compiler support for a deprecated attribute")
+ else()
+ _check_c_compiler_attribute("__declspec(deprecated)"
+ COMPILER_HAS_DEPRECATED)
+ endif()
+
endif()
endif()
endmacro()
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index 0737c12..a1f54c0 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -293,6 +293,34 @@ macro(__windows_compiler_msvc lang)
set(CMAKE_${lang}_LINK_EXECUTABLE
"${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}")
+ if("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xMSVC")
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "/GL")
+ set(CMAKE_${lang}_LINK_OPTIONS_IPO "/INCREMENTAL:NO" "/LTCG")
+ string(REPLACE "<LINK_FLAGS> " "/LTCG <LINK_FLAGS> "
+ CMAKE_${lang}_CREATE_STATIC_LIBRARY_IPO "${CMAKE_${lang}_CREATE_STATIC_LIBRARY}")
+ elseif("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xClang" OR
+ "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xFlang")
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+
+ # '-flto=thin' available since Clang 3.9 and Xcode 8
+ # * http://clang.llvm.org/docs/ThinLTO.html#clang-llvm
+ # * https://trac.macports.org/wiki/XcodeVersionInfo
+ set(_CMAKE_LTO_THIN TRUE)
+ if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.9)
+ set(_CMAKE_LTO_THIN FALSE)
+ endif()
+
+ if(_CMAKE_LTO_THIN)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin")
+ else()
+ set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto")
+ endif()
+ endif()
+
if("x${lang}" STREQUAL "xC" OR
"x${lang}" STREQUAL "xCXX")
if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
diff --git a/Modules/UseJava.cmake b/Modules/UseJava.cmake
index 939bd7b..7b138f5 100644
--- a/Modules/UseJava.cmake
+++ b/Modules/UseJava.cmake
@@ -36,7 +36,7 @@
# The default OUTPUT_DIR can also be changed by setting the variable
# CMAKE_JAVA_TARGET_OUTPUT_DIR.
#
-# Optionaly, using option GENERATE_NATIVE_HEADERS, native header files can be generated
+# Optionally, using option GENERATE_NATIVE_HEADERS, native header files can be generated
# for methods declared as native. These files provide the connective glue that allow your
# Java and C code to interact. An INTERFACE target will be created for an easy usage
# of generated files. Sub-option DESTINATION can be used to specify output directory for
diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake
index 959893f..6d35d1b 100644
--- a/Modules/UseSWIG.cmake
+++ b/Modules/UseSWIG.cmake
@@ -5,7 +5,7 @@
UseSWIG
-------
-Defines the following macros for use with SWIG:
+Defines the following command for use with SWIG:
.. command:: swig_add_library
@@ -14,20 +14,47 @@ Defines the following macros for use with SWIG:
swig_add_library(<name>
[TYPE <SHARED|MODULE|STATIC|USE_BUILD_SHARED_LIBS>]
LANGUAGE <language>
+ [NO_PROXY]
+ [OUTPUT_DIR <directory>]
+ [OUTFILE_DIR <directory>]
SOURCES <file>...
- )
+ )
- The variable ``SWIG_MODULE_<name>_REAL_NAME`` will be set to the name
- of the swig module target library.
+ Targets created with command ``swig_add_library`` have the same capabilities as targets
+ created with command :command:`add_library`, so can be used with any command accepting a target
+ especially command :command:`target_link_libraries`.
-.. command:: swig_link_libraries
+ The arguments are:
- Link libraries to swig module::
+ ``TYPE``
+ ``SHARED``, ``MODULE`` and ``STATIC`` have same semantic as command :command:`add_library`.
+ if ``USE_BUILD_SHARED_LIBS`` is specified, library type will be ``STATIC`` or ``SHARED``
+ based on whether the current value of the variable :variable:`BUILD_SHARED_LIBS` is ``ON``.
+ If none is specified, ``MODULE`` will be used.
- swig_link_libraries(<name> [ libraries ])
+ ``LANGUAGE``
+ Specify the target language.
-Source file properties on module files can be set before the invocation
-of the ``swig_add_library`` macro to specify special behavior of SWIG:
+ ``NO_PROXY``
+ Prevent the generation of the wrapper layer (swig ``-noproxy`` option).
+
+ ``OUTPUT_DIR``
+ Specify where to write the language specific files (swig ``-outdir`` option).
+ If not specified, variable ``CMAKE_SWIG_OUTDIR`` will be used. If none is specified,
+ :variable:`CMAKE_CURRENT_BINARY_DIR` is used.
+
+ ``OUTFILE_DIR``
+ Specify an output directory name where the generated source file will be placed
+ (swig -o option). If not specified, variable ``SWIG_OUTFILE_DIR`` will be used.
+ If none is specified, option ``OUTPUT_DIR`` or variable ``CMAKE_SWIG_OUTDIR`` is used.
+
+ ``SOURCES``
+ List of sources for the library. Files with extension ``.i`` will be identified as sources
+ for ``SWIG`` tool. Other files will be handled in the standard way.
+
+Source files properties on module files **must** be set before the invocation
+of the ``swig_add_library`` command to specify special behavior of SWIG and ensure
+generated files will receive required settings.
``CPLUSPLUS``
Call SWIG in c++ mode. For example:
@@ -37,9 +64,17 @@ of the ``swig_add_library`` macro to specify special behavior of SWIG:
set_property(SOURCE mymod.i PROPERTY CPLUSPLUS ON)
swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
-``SWIG_FLAGS``
- Add custom flags to the SWIG executable.
+``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS`` and ``COMPILE_OPTIONS``
+ Add custom flags to SWIG compiler and have same semantic as properties
+ :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and :prop_sf:`COMPILE_OPTIONS`.
+
+``GENERATED_INCLUDE_DIRECTORIES``, ``GENERATED_COMPILE_DEFINITIONS`` and ``GENERATED_COMPILE_OPTIONS``
+ Add custom flags to the C/C++ generated source. They will fill, respectively,
+ properties :prop_sf:`INCLUDE_DIRECTORIES`, :prop_sf:`COMPILE_DEFINITIONS` and
+ :prop_sf:`COMPILE_OPTIONS` of generated C/C++ file.
+``DEPENDS``
+ Specify additional dependencies to the source file.
``SWIG_MODULE_NAME``
Specify the actual import name of the module in the target language.
@@ -50,6 +85,34 @@ of the ``swig_add_library`` macro to specify special behavior of SWIG:
set_property(SOURCE mymod.i PROPERTY SWIG_MODULE_NAME mymod_realname)
+Target library properties can be set to apply same configuration to all SWIG input files.
+
+``SWIG_INCLUDE_DIRECTORIES``, ``SWIG_COMPILE_DEFINITIONS`` and ``SWIG_COMPILE_OPTIONS``
+ These properties will be applied to all SWIG input files and have same semantic as
+ target properties :prop_tgt:`INCLUDE_DIRECTORIES`, :prop_tgt:`COMPILE_DEFINITIONS` and
+ :prop_tgt:`COMPILE_OPTIONS`.
+
+ .. code-block:: cmake
+
+ swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
+ set_property(TARGET mymod PROPERTY SWIG_COMPILE_DEFINITIONS MY_DEF1 MY_DEF2)
+ set_property(TARGET mymod PROPERTY SWIG_COMPILE_OPTIONS -bla -blb)
+
+``SWIG_GENERATED_INCLUDE_DIRECTORIES``, ``SWIG_GENERATED_COMPILE_DEFINITIONS`` and ``SWIG_GENERATED_COMPILE_OPTIONS``
+ These properties will populate, respectively, properties :prop_sf:`INCLUDE_DIRECTORIES`,
+ :prop_sf:`COMPILE_DEFINITIONS` and :prop_sf:`COMPILE_FLAGS` of all generated C/C++ files.
+
+``SWIG_DEPENDS``
+ Add dependencies to all SWIG input files.
+
+``SWIG_SUPPORT_FILES``
+ This output property list of wrapper files generated during SWIG compilation.
+
+ .. code-block:: cmake
+
+ swig_add_library(mymod LANGUAGE python SOURCES mymod.i)
+ get_property(support_files TARGET mymod PROPERTY SWIG_SUPPORT_FILES)
+
Some variables can be set to specify special behavior of SWIG:
``CMAKE_SWIG_FLAGS``
@@ -66,34 +129,56 @@ Some variables can be set to specify special behavior of SWIG:
Specify extra dependencies for the generated module for ``<name>``.
#]=======================================================================]
+
+cmake_policy (VERSION 3.11)
+
set(SWIG_CXX_EXTENSION "cxx")
set(SWIG_EXTRA_LIBRARIES "")
set(SWIG_PYTHON_EXTRA_FILE_EXTENSIONS ".py")
set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java")
+##
+## PRIVATE functions
+##
+function (__SWIG_COMPUTE_TIMESTAMP name language infile workingdir __timestamp)
+ get_filename_component(filename "${infile}" NAME_WE)
+ set(${__timestamp}
+ "${workingdir}/${filename}${language}.stamp" PARENT_SCOPE)
+ # get_filename_component(filename "${infile}" ABSOLUTE)
+ # string(UUID uuid NAMESPACE 9735D882-D2F8-4E1D-88C9-A0A4F1F6ECA4
+ # NAME ${name}-${language}-${filename} TYPE SHA1)
+ # set(${__timestamp} "${workingdir}/${uuid}.stamp" PARENT_SCOPE)
+endfunction()
+
#
# For given swig module initialize variables associated with it
#
macro(SWIG_MODULE_INITIALIZE name language)
- string(TOUPPER "${language}" swig_uppercase_language)
- string(TOLOWER "${language}" swig_lowercase_language)
- set(SWIG_MODULE_${name}_LANGUAGE "${swig_uppercase_language}")
- set(SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${swig_lowercase_language}")
+ string(TOUPPER "${language}" SWIG_MODULE_${name}_LANGUAGE)
+ string(TOLOWER "${language}" SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG)
- set(SWIG_MODULE_${name}_REAL_NAME "${name}")
- if (";${CMAKE_SWIG_FLAGS};" MATCHES ";-noproxy;")
+ set(SWIG_MODULE_${name}_NAME "${name}")
+ set(SWIG_MODULE_${name}_EXTRA_FLAGS)
+ if (NOT DEFINED SWIG_MODULE_${name}_NOPROXY)
+ set (SWIG_MODULE_${name}_NOPROXY FALSE)
+ endif()
+ if ("-noproxy" IN_LIST CMAKE_SWIG_FLAGS)
set (SWIG_MODULE_${name}_NOPROXY TRUE)
endif ()
- if("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xUNKNOWN")
+
+ if (SWIG_MODULE_${name}_NOPROXY AND NOT "-noproxy" IN_LIST CMAKE_SWIG_FLAGS)
+ list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-noproxy")
+ endif()
+ if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "UNKNOWN")
message(FATAL_ERROR "SWIG Error: Language \"${language}\" not found")
- elseif("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xPYTHON" AND NOT SWIG_MODULE_${name}_NOPROXY)
+ elseif(SWIG_MODULE_${name}_LANGUAGE STREQUAL "PYTHON" AND NOT SWIG_MODULE_${name}_NOPROXY)
# swig will produce a module.py containing an 'import _modulename' statement,
# which implies having a corresponding _modulename.so (*NIX), _modulename.pyd (Win32),
# unless the -noproxy flag is used
- set(SWIG_MODULE_${name}_REAL_NAME "_${name}")
- elseif("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xPERL")
- set(SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
+ set(SWIG_MODULE_${name}_NAME "_${name}")
+ elseif(SWIG_MODULE_${name}_LANGUAGE STREQUAL "PERL")
+ list(APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
endif()
endmacro()
@@ -102,79 +187,108 @@ endmacro()
# will be generated. This is internal swig macro.
#
-macro(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
- set(${outfiles} "")
- get_source_file_property(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename
- ${infile} SWIG_MODULE_NAME)
- if(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename STREQUAL "NOTFOUND")
+function(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
+ set(files)
+ get_source_file_property(module_basename
+ "${infile}" SWIG_MODULE_NAME)
+ if(NOT swig_module_basename)
# try to get module name from "%module foo" syntax
- if ( EXISTS ${infile} )
- file ( STRINGS ${infile} _MODULE_NAME REGEX "[ ]*%module[ ]*[a-zA-Z0-9_]+.*" )
+ if ( EXISTS "${infile}" )
+ file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*[a-zA-Z0-9_]+.*" )
endif ()
- if ( _MODULE_NAME )
- string ( REGEX REPLACE "[ ]*%module[ ]*([a-zA-Z0-9_]+).*" "\\1" _MODULE_NAME "${_MODULE_NAME}" )
- set(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${_MODULE_NAME}")
+ if ( module_basename )
+ string ( REGEX REPLACE "[ ]*%module[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" )
else ()
# try to get module name from "%module (options=...) foo" syntax
- if ( EXISTS ${infile} )
- file ( STRINGS ${infile} _MODULE_NAME REGEX "[ ]*%module[ ]*\\(.*\\)[ ]*[a-zA-Z0-9_]+.*" )
+ if ( EXISTS "${infile}" )
+ file ( STRINGS "${infile}" module_basename REGEX "[ ]*%module[ ]*\\(.*\\)[ ]*[a-zA-Z0-9_]+.*" )
endif ()
- if ( _MODULE_NAME )
- string ( REGEX REPLACE "[ ]*%module[ ]*\\(.*\\)[ ]*([a-zA-Z0-9_]+).*" "\\1" _MODULE_NAME "${_MODULE_NAME}" )
- set(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${_MODULE_NAME}")
+ if ( module_basename )
+ string ( REGEX REPLACE "[ ]*%module[ ]*\\(.*\\)[ ]*([a-zA-Z0-9_]+).*" "\\1" module_basename "${module_basename}" )
else ()
# fallback to file basename
- get_filename_component(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename ${infile} NAME_WE)
+ get_filename_component(module_basename "${infile}" NAME_WE)
endif ()
endif ()
endif()
foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSIONS})
- set(extra_file "${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}${it}")
- list(APPEND ${outfiles} ${extra_file})
- # Treat extra outputs as plain files regardless of language.
- set_property(SOURCE "${extra_file}" PROPERTY LANGUAGE "")
+ set(extra_file "${generatedpath}/${module_basename}${it}")
+ list(APPEND files "${extra_file}")
endforeach()
-endmacro()
+ # Treat extra outputs as plain files regardless of language.
+ set_source_files_properties(${files} PROPERTIES LANGUAGE "")
+
+ set (${outfiles} ${files} PARENT_SCOPE)
+endfunction()
#
# Take swig (*.i) file and add proper custom commands for it
#
-macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
- set(swig_full_infile ${infile})
+function(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
get_filename_component(swig_source_file_name_we "${infile}" NAME_WE)
- get_source_file_property(swig_source_file_generated ${infile} GENERATED)
- get_source_file_property(swig_source_file_cplusplus ${infile} CPLUSPLUS)
- get_source_file_property(swig_source_file_flags ${infile} SWIG_FLAGS)
- if("${swig_source_file_flags}" STREQUAL "NOTFOUND")
- set(swig_source_file_flags "")
- endif()
- get_filename_component(swig_source_file_fullname "${infile}" ABSOLUTE)
+ get_source_file_property(swig_source_file_cplusplus "${infile}" CPLUSPLUS)
# If CMAKE_SWIG_OUTDIR was specified then pass it to -outdir
if(CMAKE_SWIG_OUTDIR)
- set(swig_outdir ${CMAKE_SWIG_OUTDIR})
+ set(outdir ${CMAKE_SWIG_OUTDIR})
else()
- set(swig_outdir ${CMAKE_CURRENT_BINARY_DIR})
+ set(outdir ${CMAKE_CURRENT_BINARY_DIR})
endif()
if(SWIG_OUTFILE_DIR)
- set(swig_outfile_dir ${SWIG_OUTFILE_DIR})
+ set(outfiledir ${SWIG_OUTFILE_DIR})
else()
- set(swig_outfile_dir ${swig_outdir})
+ set(outfiledir ${outdir})
+ endif()
+
+ if(SWIG_WORKING_DIR)
+ set (workingdir "${SWIG_WORKING_DIR}")
+ else()
+ set(workingdir "${outdir}")
+ endif()
+
+ set (swig_source_file_flags ${CMAKE_SWIG_FLAGS})
+ # handle various swig compile flags properties
+ get_source_file_property (include_directories "${infile}" INCLUDE_DIRECTORIES)
+ if (include_directories)
+ list (APPEND swig_source_file_flags "-I$<JOIN:${include_directories},$<SEMICOLON>-I>")
+ endif()
+ set (property "$<TARGET_PROPERTY:${name},SWIG_INCLUDE_DIRECTORIES>")
+ list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-I$<JOIN:${property},$<SEMICOLON>-I>>")
+
+ set (property "$<TARGET_PROPERTY:${name},SWIG_COMPILE_DEFINITIONS>")
+ list (APPEND swig_source_file_flags "$<$<BOOL:${property}>:-D$<JOIN:${property},$<SEMICOLON>-D>>")
+ get_source_file_property (compile_definitions "${infile}" COMPILE_DEFINITIONS)
+ if (compile_definitions)
+ list (APPEND swig_source_file_flags "-D$<JOIN:${compile_definitions},$<SEMICOLON>-D>")
+ endif()
+
+ list (APPEND swig_source_file_flags "$<TARGET_PROPERTY:${name},SWIG_COMPILE_OPTIONS>")
+ get_source_file_property (compile_options "${infile}" COMPILE_OPTIONS)
+ if (compile_options)
+ list (APPEND swig_source_file_flags ${compile_options})
+ endif()
+
+ # legacy support
+ get_source_file_property (swig_flags "${infile}" SWIG_FLAGS)
+ if (swig_flags)
+ list (APPEND swig_source_file_flags ${swig_flags})
endif()
+ get_filename_component(swig_source_file_fullname "${infile}" ABSOLUTE)
+
if (NOT SWIG_MODULE_${name}_NOPROXY)
SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE}
swig_extra_generated_files
- "${swig_outdir}"
+ "${outdir}"
"${swig_source_file_fullname}")
endif()
set(swig_generated_file_fullname
- "${swig_outfile_dir}/${swig_source_file_name_we}")
+ "${outfiledir}/${swig_source_file_name_we}")
# add the language into the name of the file (i.e. TCL_wrap)
# this allows for the same .i file to be wrapped into different languages
string(APPEND swig_generated_file_fullname
@@ -188,45 +302,47 @@ macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
".c")
endif()
- #message("Full path to source file: ${swig_source_file_fullname}")
- #message("Full path to the output file: ${swig_generated_file_fullname}")
- get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES)
- list(REMOVE_DUPLICATES cmake_include_directories)
- set(swig_include_dirs)
- foreach(it ${cmake_include_directories})
- set(swig_include_dirs ${swig_include_dirs} "-I${it}")
- endforeach()
+ get_directory_property (cmake_include_directories INCLUDE_DIRECTORIES)
+ list (REMOVE_DUPLICATES cmake_include_directories)
+ set (swig_include_dirs)
+ if (cmake_include_directories)
+ set (swig_include_dirs "-I$<JOIN:${cmake_include_directories},$<SEMICOLON>-I>")
+ endif()
set(swig_special_flags)
# default is c, so add c++ flag if it is c++
if(swig_source_file_cplusplus)
- set(swig_special_flags ${swig_special_flags} "-c++")
+ list (APPEND swig_special_flags "-c++")
endif()
- if("x${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "xCSHARP")
- if(NOT ";${swig_source_file_flags};${CMAKE_SWIG_FLAGS};" MATCHES ";-dllimport;")
+
+ set (swig_extra_flags)
+ if(SWIG_MODULE_${name}_LANGUAGE STREQUAL "CSHARP")
+ if(NOT ("-dllimport" IN_LIST swig_source_file_flags OR "-dllimport" IN_LIST SWIG_MODULE_${name}_EXTRA_FLAGS))
# This makes sure that the name used in the generated DllImport
# matches the library name created by CMake
- set(SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport;${name}")
+ list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-dllimport" "${name}")
endif()
endif()
- set(swig_extra_flags)
- if(SWIG_MODULE_${name}_EXTRA_FLAGS)
- set(swig_extra_flags ${swig_extra_flags} ${SWIG_MODULE_${name}_EXTRA_FLAGS})
+ list (APPEND swig_extra_flags ${SWIG_MODULE_${name}_EXTRA_FLAGS})
+
+ # dependencies
+ set (swig_dependencies ${SWIG_MODULE_${name}_EXTRA_DEPS} $<TARGET_PROPERTY:${name},SWIG_DEPENDS>)
+ get_source_file_property(file_depends "${infile}" DEPENDS)
+ if (file_depends)
+ list (APPEND swig_dependencies ${file_depends})
endif()
+
# IMPLICIT_DEPENDS below can not handle situations where a dependent file is
# removed. We need an extra step with timestamp and custom target, see #16830
# As this is needed only for Makefile generator do it conditionally
if(CMAKE_GENERATOR MATCHES "Make")
- get_filename_component(swig_generated_timestamp
- "${swig_generated_file_fullname}" NAME_WE)
- set(swig_gen_target gen_${name}_${swig_generated_timestamp})
- set(swig_generated_timestamp
- "${swig_outdir}/${swig_generated_timestamp}.stamp")
- set(swig_custom_output ${swig_generated_timestamp})
+ __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE}
+ "${infile}" "${workingdir}" swig_generated_timestamp)
+ set(swig_custom_output "${swig_generated_timestamp}")
set(swig_custom_products
BYPRODUCTS "${swig_generated_file_fullname}" ${swig_extra_generated_files})
set(swig_timestamp_command
- COMMAND ${CMAKE_COMMAND} -E touch ${swig_generated_timestamp})
+ COMMAND ${CMAKE_COMMAND} -E touch "${swig_generated_timestamp}")
else()
set(swig_custom_output
"${swig_generated_file_fullname}" ${swig_extra_generated_files})
@@ -236,34 +352,41 @@ macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
add_custom_command(
OUTPUT ${swig_custom_output}
${swig_custom_products}
- # Let's create the ${swig_outdir} at execution time, in case dir contains $(OutDir)
- COMMAND ${CMAKE_COMMAND} -E make_directory ${swig_outdir}
+ # Let's create the ${outdir} at execution time, in case dir contains $(OutDir)
+ COMMAND "${CMAKE_COMMAND}" -E make_directory ${outdir} ${outfiledir}
${swig_timestamp_command}
COMMAND "${SWIG_EXECUTABLE}"
- ARGS "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
- ${swig_source_file_flags}
- ${CMAKE_SWIG_FLAGS}
- -outdir ${swig_outdir}
+ "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
+ "${swig_source_file_flags}"
+ -outdir "${outdir}"
${swig_special_flags}
${swig_extra_flags}
- ${swig_include_dirs}
+ "${swig_include_dirs}"
-o "${swig_generated_file_fullname}"
"${swig_source_file_fullname}"
MAIN_DEPENDENCY "${swig_source_file_fullname}"
- DEPENDS ${SWIG_MODULE_${name}_EXTRA_DEPS}
+ DEPENDS ${swig_dependencies}
IMPLICIT_DEPENDS CXX "${swig_source_file_fullname}"
- COMMENT "Swig source")
- if(CMAKE_GENERATOR MATCHES "Make")
- add_custom_target(${swig_gen_target} DEPENDS ${swig_generated_timestamp})
- endif()
- unset(swig_generated_timestamp)
- unset(swig_custom_output)
- unset(swig_custom_products)
- unset(swig_timestamp_command)
+ COMMENT "Swig source"
+ COMMAND_EXPAND_LISTS)
set_source_files_properties("${swig_generated_file_fullname}" ${swig_extra_generated_files}
PROPERTIES GENERATED 1)
- set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files})
-endmacro()
+
+ ## add all properties for generated file to various properties
+ get_property (include_directories SOURCE "${infile}" PROPERTY GENERATED_INCLUDE_DIRECTORIES)
+ set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY INCLUDE_DIRECTORIES ${include_directories} $<TARGET_PROPERTY:${name},SWIG_GENERATED_INCLUDE_DIRECTORIES>)
+
+ get_property (compile_definitions SOURCE "${infile}" PROPERTY GENERATED_COMPILE_DEFINITIONS)
+ set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_DEFINITIONS $<TARGET_PROPERTY:${name},SWIG_GENERATED_COMPILE_DEFINITIONS> ${compile_definitions})
+
+ get_property (compile_options SOURCE "${infile}" PROPERTY GENERATED_COMPILE_OPTIONS)
+ set_property (SOURCE "${swig_generated_file_fullname}" PROPERTY COMPILE_OPTIONS $<TARGET_PROPERTY:${name},SWIG_GENERATED_COMPILE_OPTIONS> ${compile_options})
+
+ set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files} PARENT_SCOPE)
+
+ # legacy support
+ set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE)
+endfunction()
#
# Create Swig module
@@ -277,13 +400,26 @@ macro(SWIG_ADD_MODULE name language)
endmacro()
-macro(SWIG_ADD_LIBRARY name)
- set(options "")
+function(SWIG_ADD_LIBRARY name)
+ set(options NO_PROXY)
set(oneValueArgs LANGUAGE
- TYPE)
+ TYPE
+ OUTPUT_DIR
+ OUTFILE_DIR)
set(multiValueArgs SOURCES)
cmake_parse_arguments(_SAM "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ if (TARGET ${name})
+ # a target with same name is already defined.
+ # call NOW add_library command to raise the most useful error message
+ add_library(${name})
+ return()
+ endif()
+
+ if (_SAM_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "SWIG_ADD_LIBRARY: ${_SAM_UNPARSED_ARGUMENTS}: unexpected arguments")
+ endif()
+
if(NOT DEFINED _SAM_LANGUAGE)
message(FATAL_ERROR "SWIG_ADD_LIBRARY: Missing LANGUAGE argument")
endif()
@@ -294,50 +430,83 @@ macro(SWIG_ADD_LIBRARY name)
if(NOT DEFINED _SAM_TYPE)
set(_SAM_TYPE MODULE)
- elseif("${_SAM_TYPE}" STREQUAL "USE_BUILD_SHARED_LIBS")
+ elseif(_SAM_TYPE STREQUAL "USE_BUILD_SHARED_LIBS")
unset(_SAM_TYPE)
endif()
- swig_module_initialize(${name} ${_SAM_LANGUAGE})
+ set (workingdir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${name}.dir")
+ # set special variable to pass extra information to command SWIG_ADD_SOURCE_TO_MODULE
+ # which cannot be changed due to legacy compatibility
+ set (SWIG_WORKING_DIR "${workingdir}")
- set(swig_dot_i_sources)
- set(swig_other_sources)
- foreach(it ${_SAM_SOURCES})
- if(${it} MATCHES "\\.i$")
- set(swig_dot_i_sources ${swig_dot_i_sources} "${it}")
+ set (outputdir "${_SAM_OUTPUT_DIR}")
+ if (NOT _SAM_OUTPUT_DIR)
+ if (CMAKE_SWIG_OUTDIR)
+ set (outputdir "${CMAKE_SWIG_OUTDIR}")
else()
- set(swig_other_sources ${swig_other_sources} "${it}")
+ set (outputdir "${CMAKE_CURRENT_BINARY_DIR}")
endif()
- endforeach()
+ endif()
+
+ set (outfiledir "${_SAM_OUTFILE_DIR}")
+ if(NOT _SAM_OUTFILE_DIR)
+ if (SWIG_OUTFILE_DIR)
+ set (outfiledir "${SWIG_OUTFILE_DIR}")
+ else()
+ if (_SAM_OUTPUT_DIR OR CMAKE_SWIG_OUTDIR)
+ set (outfiledir "${outputdir}")
+ else()
+ set (outfiledir "${workingdir}")
+ endif()
+ endif()
+ endif()
+ # set again, locally, predefined variables to ensure compatibility
+ # with command SWIG_ADD_SOURCE_TO_MODULE
+ set(CMAKE_SWIG_OUTDIR "${outputdir}")
+ set(SWIG_OUTFILE_DIR "${outfiledir}")
+
+ set (SWIG_MODULE_${name}_NOPROXY ${_SAM_NO_PROXY})
+ swig_module_initialize(${name} ${_SAM_LANGUAGE})
+
+ set(swig_dot_i_sources ${_SAM_SOURCES})
+ list(FILTER swig_dot_i_sources INCLUDE REGEX "\\.i$")
+ set(swig_other_sources ${_SAM_SOURCES})
+ list(REMOVE_ITEM swig_other_sources ${swig_dot_i_sources})
set(swig_generated_sources)
- set(swig_generated_targets)
- foreach(it ${swig_dot_i_sources})
- SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source ${it})
- set(swig_generated_sources ${swig_generated_sources} "${swig_generated_source}")
- list(APPEND swig_generated_targets "${swig_gen_target}")
+ set(swig_generated_timestamps)
+ foreach(swig_it IN LISTS swig_dot_i_sources)
+ SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source "${swig_it}")
+ list (APPEND swig_generated_sources "${swig_generated_source}")
+ if(CMAKE_GENERATOR MATCHES "Make")
+ __swig_compute_timestamp(${name} ${SWIG_MODULE_${name}_LANGUAGE} "${swig_it}"
+ "${workingdir}" swig_timestamp)
+ list (APPEND swig_generated_timestamps "${swig_timestamp}")
+ endif()
endforeach()
- get_directory_property(swig_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
- set_directory_properties(PROPERTIES
- ADDITIONAL_MAKE_CLEAN_FILES "${swig_extra_clean_files};${swig_generated_sources}")
- add_library(${SWIG_MODULE_${name}_REAL_NAME}
+ set_property (DIRECTORY APPEND PROPERTY
+ ADDITIONAL_MAKE_CLEAN_FILES ${swig_generated_sources} ${swig_generated_timestamps})
+
+ add_library(${name}
${_SAM_TYPE}
${swig_generated_sources}
${swig_other_sources})
+ set_target_properties(${name} PROPERTIES OUTPUT_NAME "${SWIG_MODULE_${name}_NAME}")
if(CMAKE_GENERATOR MATCHES "Make")
# see IMPLICIT_DEPENDS above
- add_dependencies(${SWIG_MODULE_${name}_REAL_NAME} ${swig_generated_targets})
+ add_custom_target(${name}_swig_compilation DEPENDS ${swig_generated_timestamps})
+ add_dependencies(${name} ${name}_swig_compilation)
endif()
- if("${_SAM_TYPE}" STREQUAL "MODULE")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES NO_SONAME ON)
+ if(_SAM_TYPE STREQUAL "MODULE")
+ set_target_properties(${name} PROPERTIES NO_SONAME ON)
endif()
string(TOLOWER "${_SAM_LANGUAGE}" swig_lowercase_language)
- if ("${swig_lowercase_language}" STREQUAL "octave")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".oct")
- elseif ("${swig_lowercase_language}" STREQUAL "go")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
- elseif ("${swig_lowercase_language}" STREQUAL "java")
+ if (swig_lowercase_language STREQUAL "octave")
+ set_target_properties(${name} PROPERTIES PREFIX "")
+ set_target_properties(${name} PROPERTIES SUFFIX ".oct")
+ elseif (swig_lowercase_language STREQUAL "go")
+ set_target_properties(${name} PROPERTIES PREFIX "")
+ elseif (swig_lowercase_language STREQUAL "java")
if (APPLE)
# In java you want:
# System.loadLibrary("LIBRARY");
@@ -345,15 +514,15 @@ macro(SWIG_ADD_LIBRARY name)
# MacOS : libLIBRARY.jnilib
# Windows: LIBRARY.dll
# Linux : libLIBRARY.so
- set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".jnilib")
+ set_target_properties (${name} PROPERTIES SUFFIX ".jnilib")
endif ()
- elseif ("${swig_lowercase_language}" STREQUAL "lua")
- if("${_SAM_TYPE}" STREQUAL "MODULE")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+ elseif (swig_lowercase_language STREQUAL "lua")
+ if(_SAM_TYPE STREQUAL "MODULE")
+ set_target_properties(${name} PROPERTIES PREFIX "")
endif()
- elseif ("${swig_lowercase_language}" STREQUAL "python")
+ elseif (swig_lowercase_language STREQUAL "python")
# this is only needed for the python case where a _modulename.so is generated
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+ set_target_properties(${name} PROPERTIES PREFIX "")
# Python extension modules on Windows must have the extension ".pyd"
# instead of ".dll" as of Python 2.5. Older python versions do support
# this suffix.
@@ -363,34 +532,60 @@ macro(SWIG_ADD_LIBRARY name)
# .pyd is now the only filename extension that will be searched for.
# </quote>
if(WIN32 AND NOT CYGWIN)
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".pyd")
+ set_target_properties(${name} PROPERTIES SUFFIX ".pyd")
endif()
- elseif ("${swig_lowercase_language}" STREQUAL "r")
- set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
- elseif ("${swig_lowercase_language}" STREQUAL "ruby")
+ elseif (swig_lowercase_language STREQUAL "r")
+ set_target_properties(${name} PROPERTIES PREFIX "")
+ elseif (swig_lowercase_language STREQUAL "ruby")
# In ruby you want:
# require 'LIBRARY'
# then ruby will look for a library whose name is platform dependent, namely
# MacOS : LIBRARY.bundle
# Windows: LIBRARY.dll
# Linux : LIBRARY.so
- set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+ set_target_properties (${name} PROPERTIES PREFIX "")
+ if (APPLE)
+ set_target_properties (${name} PROPERTIES SUFFIX ".bundle")
+ endif ()
+ elseif (swig_lowercase_language STREQUAL "perl")
+ # assume empty prefix because we expect the module to be dynamically loaded
+ set_target_properties (${name} PROPERTIES PREFIX "")
if (APPLE)
- set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".bundle")
+ set_target_properties (${name} PROPERTIES SUFFIX ".dylib")
endif ()
else()
# assume empty prefix because we expect the module to be dynamically loaded
- set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
+ set_target_properties (${name} PROPERTIES PREFIX "")
endif ()
-endmacro()
+ # target property SWIG_SUPPORT_FILES lists proxy support files
+ if (NOT SWIG_MODULE_${name}_NOPROXY)
+ string(TOUPPER "${_SAM_LANGUAGE}" swig_uppercase_language)
+ foreach (swig_it IN LISTS SWIG_${swig_uppercase_language}_EXTRA_FILE_EXTENSIONS)
+ set (swig_support_files ${swig_generated_sources})
+ list (FILTER swig_support_files INCLUDE REGEX ".*${swig_it}$")
+ set_property (TARGET ${name} APPEND PROPERTY SWIG_SUPPORT_FILES ${swig_support_files})
+ endforeach()
+ endif()
+
+ # to ensure legacy behavior, export some variables
+ set (SWIG_MODULE_${name}_LANGUAGE "${SWIG_MODULE_${name}_LANGUAGE}" PARENT_SCOPE)
+ set (SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}" PARENT_SCOPE)
+ set (SWIG_MODULE_${name}_REAL_NAME "${name}" PARENT_SCOPE)
+ set (SWIG_MODULE_${name}_NOPROXY "${SWIG_MODULE_${name}_NOPROXY}" PARENT_SCOPE)
+ set (SWIG_MODULE_${name}_EXTRA_FLAGS "${SWIG_MODULE_${name}_EXTRA_FLAGS}" PARENT_SCOPE)
+ # the last one is a bit crazy but it is documented, so...
+ # NOTA: works as expected if only ONE input file is specified
+ set (swig_generated_file_fullname "${swig_generated_file_fullname}" PARENT_SCOPE)
+endfunction()
#
# Like TARGET_LINK_LIBRARIES but for swig modules
#
-macro(SWIG_LINK_LIBRARIES name)
+function(SWIG_LINK_LIBRARIES name)
+ message(DEPRECATION "SWIG_LINK_LIBRARIES is deprecated. Use TARGET_LINK_LIBRARIES instead.")
if(SWIG_MODULE_${name}_REAL_NAME)
- target_link_libraries(${SWIG_MODULE_${name}_REAL_NAME} ${ARGN})
+ target_link_libraries(${name} ${ARGN})
else()
message(SEND_ERROR "Cannot find Swig library \"${name}\".")
endif()
-endmacro()
+endfunction()
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index a0010a2..e547356 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -131,6 +131,8 @@ set(SRCS
LexerParser/cmListFileLexer.c
LexerParser/cmListFileLexer.in.l
+ cmAffinity.cxx
+ cmAffinity.h
cmArchiveWrite.cxx
cmBase32.cxx
cmCacheManager.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 50a14da..ca63858 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 11)
-set(CMake_VERSION_PATCH 0)
-set(CMake_VERSION_RC 3)
+set(CMake_VERSION_PATCH 20180319)
+#set(CMake_VERSION_RC 1)
diff --git a/Source/CMakeVersionCompute.cmake b/Source/CMakeVersionCompute.cmake
index 79264ed..72a5800 100644
--- a/Source/CMakeVersionCompute.cmake
+++ b/Source/CMakeVersionCompute.cmake
@@ -32,7 +32,12 @@ endif()
# components in the RC file are 16-bit integers so we may have to
# split the patch component.
if(CMake_VERSION_PATCH MATCHES "^([0-9]+)([0-9][0-9][0-9][0-9])$")
- set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMAKE_MATCH_1},${CMAKE_MATCH_2})
+ set(CMake_RCVERSION_YEAR "${CMAKE_MATCH_1}")
+ set(CMake_RCVERSION_MONTH_DAY "${CMAKE_MATCH_2}")
+ string(REGEX REPLACE "^0+" "" CMake_RCVERSION_MONTH_DAY "${CMake_RCVERSION_MONTH_DAY}")
+ set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_RCVERSION_YEAR},${CMake_RCVERSION_MONTH_DAY})
+ unset(CMake_RCVERSION_MONTH_DAY)
+ unset(CMake_RCVERSION_YEAR)
else()
set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH})
endif()
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 9ff547a..00fbdab 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -9,6 +9,7 @@
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
+#include <cstring>
#include <ostream>
#include <utility>
#include <vector>
@@ -51,6 +52,7 @@ int cmCPackArchiveGenerator::InitializeInternal()
this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1");
return this->Superclass::InitializeInternal();
}
+
int cmCPackArchiveGenerator::addOneComponentToArchive(
cmArchiveWrite& archive, cmCPackComponent* component)
{
@@ -61,6 +63,13 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
localToplevel += "/" + component->Name;
// Change to local toplevel
cmWorkingDirectory workdir(localToplevel);
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << localToplevel << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ return 0;
+ }
std::string filePrefix;
if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME");
@@ -237,6 +246,13 @@ int cmCPackArchiveGenerator::PackageFiles()
// CASE 3 : NON COMPONENT package.
DECLARE_AND_OPEN_ARCHIVE(packageFileNames[0], archive);
cmWorkingDirectory workdir(toplevel);
+ if (workdir.Failed()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR,
+ "Failed to change working directory to "
+ << toplevel << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ return 0;
+ }
for (std::string const& file : files) {
// Get the relative path to the file
std::string rp = cmSystemTools::RelativePath(toplevel, file);
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index d838b30..d41a9e5 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -6,6 +6,7 @@
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <cstring>
#include <memory> // IWYU pragma: keep
#include <utility>
@@ -404,6 +405,13 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Change dir to: " << goToDir
<< std::endl);
cmWorkingDirectory workdir(goToDir);
+ if (workdir.Failed()) {
+ cmCPackLogger(
+ cmCPackLog::LOG_ERROR, "Failed to change working directory to "
+ << goToDir << " : " << std::strerror(workdir.GetLastResult())
+ << std::endl);
+ return 0;
+ }
for (auto const& symlinked : symlinkedFiles) {
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Will create a symlink: "
<< symlinked.second << "--> " << symlinked.first
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 2e1ea4c..b2c68e7 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -11,6 +11,7 @@
#include "cmsys/Process.h"
#include <chrono>
+#include <cstring>
#include <ratio>
#include <stdlib.h>
@@ -196,6 +197,16 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
cmSystemTools::MakeDirectory(this->BinaryDir);
}
cmWorkingDirectory workdir(this->BinaryDir);
+ if (workdir.Failed()) {
+ auto msg = "Failed to change working directory to " + this->BinaryDir +
+ " : " + std::strerror(workdir.GetLastResult()) + "\n";
+ if (outstring) {
+ *outstring = msg;
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, msg);
+ }
+ return 1;
+ }
if (this->BuildNoCMake) {
// Make the generator available for the Build call below.
@@ -307,7 +318,16 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
// run the test from the this->BuildRunDir if set
if (!this->BuildRunDir.empty()) {
out << "Run test in directory: " << this->BuildRunDir << "\n";
- cmSystemTools::ChangeDirectory(this->BuildRunDir);
+ if (!workdir.SetDirectory(this->BuildRunDir)) {
+ out << "Failed to change working directory : "
+ << std::strerror(workdir.GetLastResult()) << "\n";
+ if (outstring) {
+ *outstring = out.str();
+ } else {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, out.str());
+ }
+ return 1;
+ }
}
out << "Running test command: \"" << fullPath << "\"";
for (std::string const& testCommandArg : this->TestCommandArgs) {
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 9c66e73..6cf0ac2 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -23,6 +23,7 @@
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <chrono>
+#include <cstring>
#include <iomanip>
#include <iterator>
#include <sstream>
@@ -975,7 +976,12 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
std::string tempDir = testingDir + "/CoverageInfo";
- cmSystemTools::MakeDirectory(tempDir);
+ if (!cmSystemTools::MakeDirectory(tempDir)) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to make directory: " << tempDir << std::endl);
+ cont->Error++;
+ return 0;
+ }
cmWorkingDirectory workdir(tempDir);
int gcovStyle = 0;
@@ -1376,6 +1382,14 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
this->Quiet);
std::string fileDir = cmSystemTools::GetFilenamePath(f);
cmWorkingDirectory workdir(fileDir);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to change working directory to "
+ << fileDir << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ cont->Error++;
+ continue;
+ }
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Current coverage dir: " << fileDir << std::endl,
@@ -1600,6 +1614,12 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
gl.RecurseThroughSymlinksOff();
std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory");
cmWorkingDirectory workdir(buildDir);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ "Unable to change working directory to " << buildDir
+ << std::endl);
+ return false;
+ }
// Run profmerge to merge all *.dyn files into dpi files
if (!cmSystemTools::RunSingleCommand("profmerge")) {
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 5a7baf5..1fff2fa 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -9,6 +9,7 @@
#include "cmWorkingDirectory.h"
#include "cmake.h"
+#include <cstring>
#include <sstream>
#include <stdlib.h>
@@ -218,6 +219,21 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
}
cmWorkingDirectory workdir(
this->CTest->GetCTestConfiguration("BuildDirectory"));
+ if (workdir.Failed()) {
+ this->SetError("failed to change directory to " +
+ this->CTest->GetCTestConfiguration("BuildDirectory") +
+ " : " + std::strerror(workdir.GetLastResult()));
+ if (capureCMakeError) {
+ this->Makefile->AddDefinition(this->Values[ct_CAPTURE_CMAKE_ERROR],
+ "-1");
+ cmCTestLog(this->CTest, ERROR_MESSAGE, this->GetName()
+ << " " << this->GetError() << "\n");
+ // return success because failure is recorded in CAPTURE_CMAKE_ERROR
+ return true;
+ }
+ return false;
+ }
+
int res = handler->ProcessHandler();
if (this->Values[ct_RETURN_VALUE] && *this->Values[ct_RETURN_VALUE]) {
std::ostringstream str;
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 50c2d86..14b5caa 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestMultiProcessHandler.h"
+#include "cmAffinity.h"
#include "cmCTest.h"
#include "cmCTestRunTest.h"
#include "cmCTestScriptHandler.h"
@@ -19,6 +20,7 @@
#include <algorithm>
#include <chrono>
+#include <cstring>
#include <iomanip>
#include <list>
#include <math.h>
@@ -53,6 +55,8 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler()
this->TestLoad = 0;
this->Completed = 0;
this->RunningCount = 0;
+ this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable();
+ this->HaveAffinity = this->ProcessorsAvailable.size();
this->StopTimePassed = false;
this->HasCycles = false;
this->SerialTestRunning = false;
@@ -127,6 +131,21 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
return false;
}
+ if (this->HaveAffinity && this->Properties[test]->WantAffinity) {
+ size_t needProcessors = this->GetProcessorsUsed(test);
+ if (needProcessors > this->ProcessorsAvailable.size()) {
+ return false;
+ }
+ std::vector<size_t> affinity;
+ affinity.reserve(needProcessors);
+ for (size_t i = 0; i < needProcessors; ++i) {
+ auto p = this->ProcessorsAvailable.begin();
+ affinity.push_back(*p);
+ this->ProcessorsAvailable.erase(p);
+ }
+ this->Properties[test]->Affinity = std::move(affinity);
+ }
+
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"test " << test << "\n", this->Quiet);
this->TestRunningMap[test] = true; // mark the test as running
@@ -151,13 +170,19 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test)
}
}
- cmWorkingDirectory workdir(this->Properties[test]->Directory);
-
- // Lock the resources we'll be using
+ // Always lock the resources we'll be using, even if we fail to set the
+ // working directory because FinishTestProcess() will try to unlock them
this->LockResources(test);
- if (testRun->StartTest(this->Total)) {
- return true;
+ cmWorkingDirectory workdir(this->Properties[test]->Directory);
+ if (workdir.Failed()) {
+ testRun->StartFailure("Failed to change working directory to " +
+ this->Properties[test]->Directory + " : " +
+ std::strerror(workdir.GetLastResult()));
+ } else {
+ if (testRun->StartTest(this->Total)) {
+ return true;
+ }
}
this->FinishTestProcess(testRun, false);
@@ -200,6 +225,11 @@ inline size_t cmCTestMultiProcessHandler::GetProcessorsUsed(int test)
if (processors > this->ParallelLevel) {
processors = this->ParallelLevel;
}
+ // Cap tests that want affinity to the maximum affinity available.
+ if (this->HaveAffinity && processors > this->HaveAffinity &&
+ this->Properties[test]->WantAffinity) {
+ processors = this->HaveAffinity;
+ }
return processors;
}
@@ -398,6 +428,11 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner,
this->UnlockResources(test);
this->RunningCount -= GetProcessorsUsed(test);
+ for (auto p : properties->Affinity) {
+ this->ProcessorsAvailable.insert(p);
+ }
+ properties->Affinity.clear();
+
delete runner;
if (started) {
this->StartNextTests();
@@ -666,6 +701,8 @@ void cmCTestMultiProcessHandler::PrintTestList()
count++;
cmCTestTestHandler::cmCTestTestProperties& p = *it.second;
+ // Don't worry if this fails, we are only showing the test list, not
+ // running the tests
cmWorkingDirectory workdir(p.Directory);
cmCTestRunTest testRun(*this);
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index 7837ff9..19e1a35 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -119,6 +119,8 @@ protected:
// Number of tests that are complete
size_t Completed;
size_t RunningCount;
+ std::set<size_t> ProcessorsAvailable;
+ size_t HaveAffinity;
bool StopTimePassed;
// list of test properties (indices concurrent to the test map)
PropertiesMap Properties;
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 30ad38c..8d8ebaa 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -14,6 +14,7 @@
#include "cmsys/RegularExpression.hxx"
#include <chrono>
#include <cmAlgorithms.h>
+#include <cstring>
#include <iomanip>
#include <ratio>
#include <sstream>
@@ -248,11 +249,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
*this->TestHandler->LogFile << "Test time = " << buf << std::endl;
}
- // Set the working directory to the tests directory to process Dart files.
- {
- cmWorkingDirectory workdir(this->TestProperties->Directory);
- this->DartProcessing();
- }
+ this->DartProcessing();
// if this is doing MemCheck then all the output needs to be put into
// Output since that is what is parsed by cmCTestMemCheckHandler
@@ -338,6 +335,13 @@ bool cmCTestRunTest::StartAgain()
this->RunAgain = false; // reset
// change to tests directory
cmWorkingDirectory workdir(this->TestProperties->Directory);
+ if (workdir.Failed()) {
+ this->StartFailure("Failed to change working directory to " +
+ this->TestProperties->Directory + " : " +
+ std::strerror(workdir.GetLastResult()));
+ return true;
+ }
+
this->StartTest(this->TotalNumberOfTests);
return true;
}
@@ -386,6 +390,37 @@ void cmCTestRunTest::MemCheckPostProcess()
handler->PostProcessTest(this->TestResult, this->Index);
}
+void cmCTestRunTest::StartFailure(std::string const& output)
+{
+ // Still need to log the Start message so the test summary records our
+ // attempt to start this test
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ std::setw(2 * getNumWidth(this->TotalNumberOfTests) + 8)
+ << "Start "
+ << std::setw(getNumWidth(this->TestHandler->GetMaxIndex()))
+ << this->TestProperties->Index << ": "
+ << this->TestProperties->Name << std::endl);
+
+ this->ProcessOutput.clear();
+ if (!output.empty()) {
+ *this->TestHandler->LogFile << output << std::endl;
+ cmCTestLog(this->CTest, ERROR_MESSAGE, output << std::endl);
+ }
+
+ this->TestResult.Properties = this->TestProperties;
+ this->TestResult.ExecutionTime = cmDuration::zero();
+ this->TestResult.CompressOutput = false;
+ this->TestResult.ReturnValue = -1;
+ this->TestResult.CompletionStatus = "Failed to start";
+ this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
+ this->TestResult.TestCount = this->TestProperties->Index;
+ this->TestResult.Name = this->TestProperties->Name;
+ this->TestResult.Path = this->TestProperties->Directory;
+ this->TestResult.Output = output;
+ this->TestResult.FullCommandLine.clear();
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
+}
+
// Starts the execution of a test. Returns once it has started
bool cmCTestRunTest::StartTest(size_t total)
{
@@ -515,7 +550,8 @@ bool cmCTestRunTest::StartTest(size_t total)
}
return this->ForkProcess(timeout, this->TestProperties->ExplicitTimeout,
- &this->TestProperties->Environment);
+ &this->TestProperties->Environment,
+ &this->TestProperties->Affinity);
}
void cmCTestRunTest::ComputeArguments()
@@ -591,7 +627,8 @@ void cmCTestRunTest::DartProcessing()
}
bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
- std::vector<std::string>* environment)
+ std::vector<std::string>* environment,
+ std::vector<size_t>* affinity)
{
this->TestProcess = cm::make_unique<cmProcess>(*this);
this->TestProcess->SetId(this->Index);
@@ -637,7 +674,8 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
cmSystemTools::AppendEnv(*environment);
}
- return this->TestProcess->StartProcess(this->MultiTestHandler.Loop);
+ return this->TestProcess->StartProcess(this->MultiTestHandler.Loop,
+ affinity);
}
void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index 4d57357..3b1d674 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -74,6 +74,8 @@ public:
bool StartAgain();
+ void StartFailure(std::string const& output);
+
cmCTest* GetCTest() const { return this->CTest; }
void FinalizeTest();
@@ -83,7 +85,8 @@ private:
void DartProcessing();
void ExeNotFound(std::string exe);
bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
- std::vector<std::string>* environment);
+ std::vector<std::string>* environment,
+ std::vector<size_t>* affinity);
void WriteLogOutputTop(size_t completed, size_t total);
// Run post processing of the process output for MemCheck
void MemCheckPostProcess();
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index e0bffd4..5fff730 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -527,7 +527,7 @@ int cmCTestScriptHandler::RunConfigurationScript(
return result;
}
- // only run the curent script if we should
+ // only run the current script if we should
if (this->Makefile && this->Makefile->IsOn("CTEST_RUN_CURRENT_SCRIPT") &&
this->ShouldRunCurrentScript) {
return this->RunCurrentScript();
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index 08d05c8..3bab81e 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -7,6 +7,7 @@
#include "cm_jsoncpp_value.h"
#include "cmsys/Process.h"
#include <chrono>
+#include <cstring>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
@@ -1532,6 +1533,15 @@ int cmCTestSubmitHandler::ProcessHandler()
// change to the build directory so that we can uses a relative path
// on windows since scp doesn't support "c:" a drive in the path
cmWorkingDirectory workdir(buildDirectory);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Failed to change directory to "
+ << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ ofs << " Failed to change directory to " << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl;
+ return -1;
+ }
if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"),
"Testing/" + this->CTest->GetCurrentTag(), files,
@@ -1551,6 +1561,15 @@ int cmCTestSubmitHandler::ProcessHandler()
// change to the build directory so that we can uses a relative path
// on windows since scp doesn't support "c:" a drive in the path
cmWorkingDirectory workdir(buildDirectory);
+ if (workdir.Failed()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE,
+ " Failed to change directory to "
+ << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl);
+ ofs << " Failed to change directory to " << buildDirectory << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl;
+ return -1;
+ }
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
" Change directory: " << buildDirectory << std::endl,
this->Quiet);
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 84d8926..cbaf984 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -6,6 +6,7 @@
#include <cmsys/Base64.h>
#include <cmsys/Directory.hxx>
#include <cmsys/RegularExpression.hxx>
+#include <cstring>
#include <functional>
#include <iomanip>
#include <iterator>
@@ -14,7 +15,6 @@
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <time.h>
#include "cmAlgorithms.h"
@@ -85,6 +85,11 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
bool readit = false;
{
cmWorkingDirectory workdir(fname);
+ if (workdir.Failed()) {
+ this->SetError("Failed to change directory to " + fname + " : " +
+ std::strerror(workdir.GetLastResult()));
+ return false;
+ }
const char* testFilename;
if (cmSystemTools::FileExists("CTestTestfile.cmake")) {
// does the CTestTestfile.cmake exist ?
@@ -2165,6 +2170,9 @@ bool cmCTestTestHandler::SetTestsProperties(
rt.Processors = 1;
}
}
+ if (key == "PROCESSOR_AFFINITY") {
+ rt.WantAffinity = cmSystemTools::IsOn(val.c_str());
+ }
if (key == "SKIP_RETURN_CODE") {
rt.SkipReturnCode = atoi(val.c_str());
if (rt.SkipReturnCode < 0 || rt.SkipReturnCode > 255) {
@@ -2336,6 +2344,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
test.ExplicitTimeout = false;
test.Cost = 0;
test.Processors = 1;
+ test.WantAffinity = false;
test.SkipReturnCode = -1;
test.PreviousRuns = 0;
if (this->UseIncludeRegExpFlag &&
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index f4978b6..d2694a1 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -130,6 +130,8 @@ public:
int Index;
// Requested number of process slots
int Processors;
+ bool WantAffinity;
+ std::vector<size_t> Affinity;
// return code of test which will mark test as "not run"
int SkipReturnCode;
std::vector<std::string> Environment;
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 09ed0a9..5c9b169 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -83,7 +83,7 @@ void cmProcess::SetCommandArguments(std::vector<std::string> const& args)
this->Arguments = args;
}
-bool cmProcess::StartProcess(uv_loop_t& loop)
+bool cmProcess::StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity)
{
this->ProcessState = cmProcess::State::Error;
if (this->Command.empty()) {
@@ -138,6 +138,22 @@ bool cmProcess::StartProcess(uv_loop_t& loop)
options.stdio_count = 3; // in, out and err
options.exit_cb = &cmProcess::OnExitCB;
options.stdio = stdio;
+#if !defined(CMAKE_USE_SYSTEM_LIBUV)
+ std::vector<char> cpumask;
+ if (affinity && !affinity->empty()) {
+ cpumask.resize(static_cast<size_t>(uv_cpumask_size()), 0);
+ for (auto p : *affinity) {
+ cpumask[p] = 1;
+ }
+ options.cpumask = cpumask.data();
+ options.cpumask_size = cpumask.size();
+ } else {
+ options.cpumask = nullptr;
+ options.cpumask_size = 0;
+ }
+#else
+ static_cast<void>(affinity);
+#endif
status =
uv_read_start(pipe_reader, &cmProcess::OnAllocateCB, &cmProcess::OnReadCB);
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index 20e24b9..b2d87fa 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -36,7 +36,7 @@ public:
void ChangeTimeout(cmDuration t);
void ResetStartTime();
// Return true if the process starts
- bool StartProcess(uv_loop_t& loop);
+ bool StartProcess(uv_loop_t& loop, std::vector<size_t>* affinity);
enum class State
{
diff --git a/Source/cmAffinity.cxx b/Source/cmAffinity.cxx
new file mode 100644
index 0000000..bdf1f42
--- /dev/null
+++ b/Source/cmAffinity.cxx
@@ -0,0 +1,62 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAffinity.h"
+
+#include "cm_uv.h"
+
+#ifndef CMAKE_USE_SYSTEM_LIBUV
+#ifdef _WIN32
+#define CM_HAVE_CPU_AFFINITY
+#include <windows.h>
+#elif defined(__linux__) || defined(__FreeBSD__)
+#define CM_HAVE_CPU_AFFINITY
+#include <pthread.h>
+#include <sched.h>
+#if defined(__FreeBSD__)
+#include <pthread_np.h>
+#include <sys/cpuset.h>
+#include <sys/param.h>
+#endif
+#if defined(__linux__)
+typedef cpu_set_t cm_cpuset_t;
+#else
+typedef cpuset_t cm_cpuset_t;
+#endif
+#endif
+#endif
+
+namespace cmAffinity {
+
+std::set<size_t> GetProcessorsAvailable()
+{
+ std::set<size_t> processorsAvailable;
+#ifdef CM_HAVE_CPU_AFFINITY
+ int cpumask_size = uv_cpumask_size();
+ if (cpumask_size > 0) {
+#ifdef _WIN32
+ DWORD_PTR procmask;
+ DWORD_PTR sysmask;
+ if (GetProcessAffinityMask(GetCurrentProcess(), &procmask, &sysmask) !=
+ 0) {
+ for (int i = 0; i < cpumask_size; ++i) {
+ if (procmask & (((DWORD_PTR)1) << i)) {
+ processorsAvailable.insert(i);
+ }
+ }
+ }
+#else
+ cm_cpuset_t cpuset;
+ CPU_ZERO(&cpuset); // NOLINT(clang-tidy)
+ if (pthread_getaffinity_np(pthread_self(), sizeof(cpuset), &cpuset) == 0) {
+ for (int i = 0; i < cpumask_size; ++i) {
+ if (CPU_ISSET(i, &cpuset)) {
+ processorsAvailable.insert(i);
+ }
+ }
+ }
+#endif
+ }
+#endif
+ return processorsAvailable;
+}
+}
diff --git a/Source/cmAffinity.h b/Source/cmAffinity.h
new file mode 100644
index 0000000..3775bae
--- /dev/null
+++ b/Source/cmAffinity.h
@@ -0,0 +1,12 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <cstddef>
+#include <set>
+
+namespace cmAffinity {
+
+std::set<size_t> GetProcessorsAvailable();
+}
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index 673a40e..b2f4f25 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -347,7 +347,7 @@ public:
const std::string& cmake_var,
bool suppress = false);
- /** Make string safe to be send as an URL */
+ /** Make string safe to be sent as a URL */
static std::string MakeURLSafe(const std::string&);
/** Decode a URL to the original string. */
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index fab2445..85ac985 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -160,14 +160,14 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
currentcwd += "/CMakeCache.txt";
oldcwd += "/CMakeCache.txt";
if (!cmSystemTools::SameFile(oldcwd, currentcwd)) {
- std::string message =
- std::string("The current CMakeCache.txt directory ") + currentcwd +
- std::string(" is different than the directory ") +
- std::string(this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")) +
- std::string(" where CMakeCache.txt was created. This may result "
- "in binaries being created in the wrong place. If you "
- "are not sure, reedit the CMakeCache.txt");
- cmSystemTools::Error(message.c_str());
+ std::ostringstream message;
+ message << "The current CMakeCache.txt directory " << currentcwd
+ << " is different than the directory "
+ << this->GetInitializedCacheValue("CMAKE_CACHEFILE_DIR")
+ << " where CMakeCache.txt was created. This may result "
+ "in binaries being created in the wrong place. If you "
+ "are not sure, reedit the CMakeCache.txt";
+ cmSystemTools::Error(message.str().c_str());
}
}
return true;
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 8a5a6de..e00450f 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -611,6 +611,9 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
if (!libName.empty()) {
this->AddItem(libName, nullptr);
}
+ } else if (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ // Ignore object library!
+ // Its object-files should already have been extracted for linking.
} else {
// Decide whether to use an import library.
bool implib =
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 18767a3..efdd3a5 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -211,11 +211,11 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
if (depender->GetType() != cmStateEnums::EXECUTABLE &&
depender->GetType() != cmStateEnums::STATIC_LIBRARY &&
depender->GetType() != cmStateEnums::SHARED_LIBRARY &&
- depender->GetType() != cmStateEnums::MODULE_LIBRARY) {
+ depender->GetType() != cmStateEnums::MODULE_LIBRARY &&
+ depender->GetType() != cmStateEnums::OBJECT_LIBRARY) {
this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
cmake::FATAL_ERROR,
- "Only executables and non-OBJECT libraries may "
- "reference target objects.",
+ "Only executables and libraries may reference target objects.",
depender->GetBacktrace());
return;
}
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index cdab671..4716e14 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -7,7 +7,6 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
-#include "cmWorkingDirectory.h"
#include "cmsys/FStream.hxx"
#include <sstream>
@@ -15,8 +14,7 @@
#include <utility>
cmDepends::cmDepends(cmLocalGenerator* lg, const char* targetDir)
- : CompileDirectory()
- , LocalGenerator(lg)
+ : LocalGenerator(lg)
, Verbose(false)
, FileComparison(nullptr)
, TargetDirectory(targetDir)
@@ -73,9 +71,6 @@ bool cmDepends::Finalize(std::ostream& /*unused*/, std::ostream& /*unused*/)
bool cmDepends::Check(const char* makeFile, const char* internalFile,
std::map<std::string, DependencyVector>& validDeps)
{
- // Dependency checks must be done in proper working directory.
- cmWorkingDirectory workdir(this->CompileDirectory);
-
// Check whether dependencies must be regenerated.
bool okay = true;
cmsys::ifstream fin(internalFile);
diff --git a/Source/cmDepends.h b/Source/cmDepends.h
index a4fee3c..4b9e05a 100644
--- a/Source/cmDepends.h
+++ b/Source/cmDepends.h
@@ -31,9 +31,6 @@ public:
path from the build directory to the target file. */
cmDepends(cmLocalGenerator* lg = nullptr, const char* targetDir = "");
- /** at what level will the compile be done from */
- void SetCompileDirectory(const char* dir) { this->CompileDirectory = dir; }
-
/** Set the local generator for the directory in which we are
scanning dependencies. This is not a full local generator; it
has been setup to do relative path conversions for the current
@@ -95,9 +92,6 @@ protected:
virtual bool Finalize(std::ostream& makeDepends,
std::ostream& internalDepends);
- // The directory in which the build rule for the target file is executed.
- std::string CompileDirectory;
-
// The local generator.
cmLocalGenerator* LocalGenerator;
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index 817b5d9..0ceac85 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -41,7 +41,8 @@ void cmExportBuildAndroidMKGenerator::GenerateExpectedTargetsCode(
}
void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/)
{
std::string targetName = this->Namespace;
targetName += target->GetExportName();
diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h
index c80839b..a9b6107 100644
--- a/Source/cmExportBuildAndroidMKGenerator.h
+++ b/Source/cmExportBuildAndroidMKGenerator.h
@@ -11,6 +11,7 @@
#include "cmExportBuildFileGenerator.h"
#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
class cmGeneratorTarget;
@@ -47,8 +48,9 @@ protected:
void GenerateImportHeaderCode(std::ostream& os,
const std::string& config = "") override;
void GenerateImportFooterCode(std::ostream& os) override;
- void GenerateImportTargetCode(std::ostream& os,
- const cmGeneratorTarget* target) override;
+ void GenerateImportTargetCode(
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/) override;
void GenerateExpectedTargetsCode(
std::ostream& os, const std::string& expectedTargets) override;
void GenerateImportPropertyCode(
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index f7aa6e8..bbbc998 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -59,7 +59,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->LG->GetMakefile()->GetBacktrace());
return false;
}
- if (te->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) {
this->GenerateRequiredCMakeVersion(os, "3.0.0");
}
}
@@ -71,7 +71,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
// Create all the imported targets.
for (cmGeneratorTarget* gte : this->Exports) {
- this->GenerateImportTargetCode(os, gte);
+ this->GenerateImportTargetCode(os, gte, this->GetExportTargetType(gte));
gte->Target->AppendBuildInterfaceIncludes();
@@ -97,6 +97,15 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", gte,
properties);
+
+ std::string errorMessage;
+ if (!this->PopulateExportProperties(gte, properties, errorMessage)) {
+ this->LG->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR, errorMessage,
+ this->LG->GetMakefile()->GetBacktrace());
+ return false;
+ }
+
const bool newCMP0022Behavior =
gte->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
gte->GetPolicyStatusCMP0022() != cmPolicies::OLD;
@@ -128,12 +137,13 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
// Collect import properties for this target.
ImportPropertyMap properties;
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(target) != cmStateEnums::INTERFACE_LIBRARY) {
this->SetImportLocationProperty(config, suffix, target, properties);
}
if (!properties.empty()) {
// Get the rest of the target details.
- if (target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(target) !=
+ cmStateEnums::INTERFACE_LIBRARY) {
this->SetImportDetailProperties(config, suffix, target, properties,
missingTargets);
this->SetImportLinkInterface(config, suffix,
@@ -153,6 +163,21 @@ void cmExportBuildFileGenerator::GenerateImportTargetsConfig(
}
}
+cmStateEnums::TargetType cmExportBuildFileGenerator::GetExportTargetType(
+ cmGeneratorTarget const* target) const
+{
+ cmStateEnums::TargetType targetType = target->GetType();
+ // An object library exports as an interface library if we cannot
+ // tell clients where to find the objects. This is sufficient
+ // to support transitive usage requirements on other targets that
+ // use the object library.
+ if (targetType == cmStateEnums::OBJECT_LIBRARY &&
+ !this->LG->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) {
+ targetType = cmStateEnums::INTERFACE_LIBRARY;
+ }
+ return targetType;
+}
+
void cmExportBuildFileGenerator::SetExportSet(cmExportSet* exportSet)
{
this->ExportSet = exportSet;
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 6457a77..ada2709 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
#include <iosfwd>
#include <string>
@@ -53,6 +54,8 @@ protected:
void GenerateImportTargetsConfig(
std::ostream& os, const std::string& config, std::string const& suffix,
std::vector<std::string>& missingTargets) override;
+ cmStateEnums::TargetType GetExportTargetType(
+ cmGeneratorTarget const* target) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender,
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index c8a727d..655ebe8 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -146,17 +146,6 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
}
if (cmTarget* target = gg->FindTarget(currentTarget)) {
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string reason;
- if (!this->Makefile->GetGlobalGenerator()
- ->HasKnownObjectFileLocation(&reason)) {
- std::ostringstream e;
- e << "given OBJECT library \"" << currentTarget
- << "\" which may not be exported" << reason << ".";
- this->SetError(e.str());
- return false;
- }
- }
if (target->GetType() == cmStateEnums::UTILITY) {
this->SetError("given custom target \"" + currentTarget +
"\" which may not be exported.");
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 434abdc..2dcbfa0 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -11,6 +11,8 @@
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
+#include "cmPropertyMap.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
@@ -901,8 +903,10 @@ void cmExportFileGenerator::GenerateExpectedTargetsCode(
"\n\n";
/* clang-format on */
}
+
void cmExportFileGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType targetType)
{
// Construct the imported target name.
std::string targetName = this->Namespace;
@@ -911,7 +915,7 @@ void cmExportFileGenerator::GenerateImportTargetCode(
// Create the imported target.
os << "# Create imported target " << targetName << "\n";
- switch (target->GetType()) {
+ switch (targetType) {
case cmStateEnums::EXECUTABLE:
os << "add_executable(" << targetName << " IMPORTED)\n";
break;
@@ -1095,3 +1099,41 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode(
os << ")\n\n";
}
+
+bool cmExportFileGenerator::PopulateExportProperties(
+ cmGeneratorTarget* gte, ImportPropertyMap& properties,
+ std::string& errorMessage)
+{
+ auto& targetProperties = gte->Target->GetProperties();
+ const auto& exportProperties = targetProperties.find("EXPORT_PROPERTIES");
+ if (exportProperties != targetProperties.end()) {
+ std::vector<std::string> propsToExport;
+ cmSystemTools::ExpandListArgument(exportProperties->second.GetValue(),
+ propsToExport);
+ for (auto& prop : propsToExport) {
+ /* Black list reserved properties */
+ if (cmSystemTools::StringStartsWith(prop, "IMPORTED_") ||
+ cmSystemTools::StringStartsWith(prop, "INTERFACE_")) {
+ std::ostringstream e;
+ e << "Target \"" << gte->Target->GetName() << "\" contains property \""
+ << prop << "\" in EXPORT_PROPERTIES but IMPORTED_* and INTERFACE_* "
+ << "properties are reserved.";
+ errorMessage = e.str();
+ return false;
+ }
+ auto propertyValue = targetProperties.GetPropertyValue(prop);
+ std::string evaluatedValue = cmGeneratorExpression::Preprocess(
+ propertyValue, cmGeneratorExpression::StripAllGeneratorExpressions);
+ if (evaluatedValue != propertyValue) {
+ std::ostringstream e;
+ e << "Target \"" << gte->Target->GetName() << "\" contains property \""
+ << prop << "\" in EXPORT_PROPERTIES but this property contains a "
+ << "generator expression. This is not allowed.";
+ errorMessage = e.str();
+ return false;
+ }
+ properties[prop] = propertyValue;
+ }
+ }
+ return true;
+}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 985c8f6..954e6c5 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmGeneratorExpression.h"
+#include "cmStateTypes.h"
#include "cmVersion.h"
#include "cmVersionConfig.h"
@@ -76,7 +77,8 @@ protected:
virtual void GenerateImportFooterCode(std::ostream& os);
void GenerateImportVersionCode(std::ostream& os);
virtual void GenerateImportTargetCode(std::ostream& os,
- cmGeneratorTarget const* target);
+ cmGeneratorTarget const* target,
+ cmStateEnums::TargetType targetType);
virtual void GenerateImportPropertyCode(std::ostream& os,
const std::string& config,
cmGeneratorTarget const* target,
@@ -166,6 +168,10 @@ protected:
virtual void GenerateRequiredCMakeVersion(std::ostream& os,
const char* versionString);
+ bool PopulateExportProperties(cmGeneratorTarget* gte,
+ ImportPropertyMap& properties,
+ std::string& errorMessage);
+
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
index fe565e6..9bc8089 100644
--- a/Source/cmExportInstallAndroidMKGenerator.cxx
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -55,7 +55,8 @@ void cmExportInstallAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
}
void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
- std::ostream& os, const cmGeneratorTarget* target)
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/)
{
std::string targetName = this->Namespace;
targetName += target->GetExportName();
diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h
index 91554ee..8883ffa 100644
--- a/Source/cmExportInstallAndroidMKGenerator.h
+++ b/Source/cmExportInstallAndroidMKGenerator.h
@@ -12,6 +12,7 @@
#include "cmExportFileGenerator.h"
#include "cmExportInstallFileGenerator.h"
+#include "cmStateTypes.h"
class cmGeneratorTarget;
class cmInstallExportGenerator;
@@ -41,8 +42,9 @@ protected:
void GenerateImportHeaderCode(std::ostream& os,
const std::string& config = "") override;
void GenerateImportFooterCode(std::ostream& os) override;
- void GenerateImportTargetCode(std::ostream& os,
- const cmGeneratorTarget* target) override;
+ void GenerateImportTargetCode(
+ std::ostream& os, cmGeneratorTarget const* target,
+ cmStateEnums::TargetType /*targetType*/) override;
void GenerateExpectedTargetsCode(
std::ostream& os, const std::string& expectedTargets) override;
void GenerateImportPropertyCode(
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 954b561..63d04a6 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -75,11 +75,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
// Create all the imported targets.
for (cmTargetExport* te : allTargets) {
cmGeneratorTarget* gt = te->Target;
+ cmStateEnums::TargetType targetType = this->GetExportTargetType(te);
requiresConfigFiles =
- requiresConfigFiles || gt->GetType() != cmStateEnums::INTERFACE_LIBRARY;
+ requiresConfigFiles || targetType != cmStateEnums::INTERFACE_LIBRARY;
- this->GenerateImportTargetCode(os, gt);
+ this->GenerateImportTargetCode(os, gt, targetType);
ImportPropertyMap properties;
@@ -103,6 +104,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
+ std::string errorMessage;
+ if (!this->PopulateExportProperties(gt, properties, errorMessage)) {
+ cmSystemTools::Error(errorMessage.c_str());
+ return false;
+ }
+
const bool newCMP0022Behavior =
gt->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
gt->GetPolicyStatusCMP0022() != cmPolicies::OLD;
@@ -114,7 +121,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
require2_8_12 = true;
}
}
- if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (targetType == cmStateEnums::INTERFACE_LIBRARY) {
require3_0_0 = true;
}
if (gt->GetProperty("INTERFACE_SOURCES")) {
@@ -308,7 +315,7 @@ void cmExportInstallFileGenerator::GenerateImportTargetsConfig(
// Add each target in the set to the export.
for (cmTargetExport* te : *this->IEGen->GetExportSet()->GetTargetExports()) {
// Collect import properties for this target.
- if (te->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (this->GetExportTargetType(te) == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
@@ -426,6 +433,19 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
}
}
+cmStateEnums::TargetType cmExportInstallFileGenerator::GetExportTargetType(
+ cmTargetExport const* targetExport) const
+{
+ cmStateEnums::TargetType targetType = targetExport->Target->GetType();
+ // An OBJECT library installed with no OBJECTS DESTINATION
+ // is transformed to an INTERFACE library.
+ if (targetType == cmStateEnums::OBJECT_LIBRARY &&
+ targetExport->ObjectsGenerator == nullptr) {
+ targetType = cmStateEnums::INTERFACE_LIBRARY;
+ }
+ return targetType;
+}
+
void cmExportInstallFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender, cmGeneratorTarget* dependee)
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index cda8433..ea607fb 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmExportFileGenerator.h"
+#include "cmStateTypes.h"
#include <iosfwd>
#include <map>
@@ -17,6 +18,7 @@ class cmGeneratorTarget;
class cmGlobalGenerator;
class cmInstallExportGenerator;
class cmInstallTargetGenerator;
+class cmTargetExport;
/** \class cmExportInstallFileGenerator
* \brief Generate a file exporting targets from an install tree.
@@ -57,6 +59,8 @@ protected:
void GenerateImportTargetsConfig(
std::ostream& os, const std::string& config, std::string const& suffix,
std::vector<std::string>& missingTargets) override;
+ cmStateEnums::TargetType GetExportTargetType(
+ cmTargetExport const* targetExport) const;
void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmGeneratorTarget* depender,
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index ae8cd37..87648cb 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -33,7 +33,7 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
this->Exports.pop_back();
if (emitted.insert(te).second) {
emittedDeps.insert(te);
- this->GenerateImportTargetCode(os, te);
+ this->GenerateImportTargetCode(os, te, te->GetType());
ImportPropertyMap properties;
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 4dbaa3f..c7c780c 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -408,7 +408,6 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
const std::string& projectPath, const cmMakefile* mf,
const std::string& projectType, const std::string& targetName)
{
-
cmXMLWriter& xml(*_xml);
FindMatchingHeaderfiles(cFiles, otherFiles);
// Create 2 virtual folders: src and include
@@ -469,10 +468,14 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
xml.EndElement(); // ResourceCompiler
xml.StartElement("General");
- std::string outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ std::string outputPath =
+ mf->GetSafeDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY");
+ if (outputPath.empty()) {
+ outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
+ }
std::string relapath;
if (!outputPath.empty()) {
- relapath = cmSystemTools::RelativePath(this->WorkspacePath, outputPath);
+ relapath = cmSystemTools::RelativePath(projectPath, outputPath);
xml.Attribute("OutputFile", relapath + "/$(ProjectName)");
} else {
xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
@@ -635,7 +638,7 @@ std::string cmExtraCodeLiteGenerator::GetBuildCommand(
if (generator == "NMake Makefiles" || generator == "Ninja") {
ss << make;
} else if (generator == "MinGW Makefiles" || generator == "Unix Makefiles") {
- ss << make << " -j " << this->CpuCount;
+ ss << make << " -f$(ProjectPath)/Makefile -j " << this->CpuCount;
}
if (!targetName.empty()) {
ss << " " << targetName;
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index d3dcc01..90b943b 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -160,6 +160,12 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "TO_NATIVE_PATH") {
return this->HandleCMakePathCommand(args, true);
}
+ if (subCommand == "TOUCH") {
+ return this->HandleTouchCommand(args, true);
+ }
+ if (subCommand == "TOUCH_NOCREATE") {
+ return this->HandleTouchCommand(args, false);
+ }
if (subCommand == "TIMESTAMP") {
return this->HandleTimestampCommand(args);
}
@@ -751,9 +757,9 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
}
}
- std::string output;
- bool first = true;
- for (; i != args.end(); ++i) {
+ std::vector<std::string> files;
+ bool warnFollowedSymlinks = false;
+ while (i != args.end()) {
if (*i == "LIST_DIRECTORIES") {
++i;
if (i != args.end()) {
@@ -771,103 +777,105 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
this->SetError("LIST_DIRECTORIES missing bool value.");
return false;
}
- continue;
- }
-
- if (recurse && (*i == "FOLLOW_SYMLINKS")) {
+ ++i;
+ if (i == args.end()) {
+ this->SetError("GLOB requires a glob expression after the bool.");
+ return false;
+ }
+ } else if (*i == "FOLLOW_SYMLINKS") {
+ if (!recurse) {
+ this->SetError("FOLLOW_SYMLINKS is not a valid parameter for GLOB.");
+ return false;
+ }
explicitFollowSymlinks = true;
g.RecurseThroughSymlinksOn();
++i;
if (i == args.end()) {
this->SetError(
- "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS");
+ "GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS.");
return false;
}
- }
-
- if (*i == "RELATIVE") {
+ } else if (*i == "RELATIVE") {
++i; // skip RELATIVE
if (i == args.end()) {
- this->SetError("GLOB requires a directory after the RELATIVE tag");
+ this->SetError("GLOB requires a directory after the RELATIVE tag.");
return false;
}
g.SetRelative(i->c_str());
++i;
if (i == args.end()) {
- this->SetError("GLOB requires a glob expression after the directory");
+ this->SetError("GLOB requires a glob expression after the directory.");
return false;
}
- }
-
- cmsys::Glob::GlobMessages globMessages;
- if (!cmsys::SystemTools::FileIsFullPath(*i)) {
- std::string expr = this->Makefile->GetCurrentSourceDirectory();
- // Handle script mode
- if (!expr.empty()) {
- expr += "/" + *i;
- g.FindFiles(expr, &globMessages);
- } else {
- g.FindFiles(*i, &globMessages);
- }
} else {
- g.FindFiles(*i, &globMessages);
- }
-
- if (!globMessages.empty()) {
- bool shouldExit = false;
- for (cmsys::Glob::Message const& globMessage : globMessages) {
- if (globMessage.type == cmsys::Glob::cyclicRecursion) {
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
- "Cyclic recursion detected while globbing for '" + *i + "':\n" +
- globMessage.content);
+ std::string expr = *i;
+ if (!cmsys::SystemTools::FileIsFullPath(*i)) {
+ expr = this->Makefile->GetCurrentSourceDirectory();
+ // Handle script mode
+ if (!expr.empty()) {
+ expr += "/" + *i;
} else {
- this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "Error has occurred while globbing for '" +
- *i + "' - " + globMessage.content);
- shouldExit = true;
+ expr = *i;
}
}
- if (shouldExit) {
- return false;
+
+ cmsys::Glob::GlobMessages globMessages;
+ g.FindFiles(expr, &globMessages);
+
+ if (!globMessages.empty()) {
+ bool shouldExit = false;
+ for (cmsys::Glob::Message const& globMessage : globMessages) {
+ if (globMessage.type == cmsys::Glob::cyclicRecursion) {
+ this->Makefile->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ "Cyclic recursion detected while globbing for '" + *i + "':\n" +
+ globMessage.content);
+ } else {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR, "Error has occurred while globbing for '" +
+ *i + "' - " + globMessage.content);
+ shouldExit = true;
+ }
+ }
+ if (shouldExit) {
+ return false;
+ }
}
- }
- std::vector<std::string>::size_type cc;
- std::vector<std::string>& files = g.GetFiles();
- std::sort(files.begin(), files.end());
- for (cc = 0; cc < files.size(); cc++) {
- if (!first) {
- output += ";";
+ if (recurse && !explicitFollowSymlinks &&
+ g.GetFollowedSymlinkCount() != 0) {
+ warnFollowedSymlinks = true;
}
- output += files[cc];
- first = false;
+
+ std::vector<std::string>& foundFiles = g.GetFiles();
+ files.insert(files.end(), foundFiles.begin(), foundFiles.end());
+ ++i;
}
}
- if (recurse && !explicitFollowSymlinks) {
- switch (status) {
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- // Correct behavior, yay!
- break;
- case cmPolicies::OLD:
- // Probably not really the expected behavior, but the author explicitly
- // asked for the old behavior... no warning.
- case cmPolicies::WARN:
- // Possibly unexpected old behavior *and* we actually traversed
- // symlinks without being explicitly asked to: warn the author.
- if (g.GetFollowedSymlinkCount() != 0) {
- this->Makefile->IssueMessage(
- cmake::AUTHOR_WARNING,
- cmPolicies::GetPolicyWarning(cmPolicies::CMP0009));
- }
- break;
- }
+ switch (status) {
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Correct behavior, yay!
+ break;
+ case cmPolicies::OLD:
+ // Probably not really the expected behavior, but the author explicitly
+ // asked for the old behavior... no warning.
+ case cmPolicies::WARN:
+ // Possibly unexpected old behavior *and* we actually traversed
+ // symlinks without being explicitly asked to: warn the author.
+ if (warnFollowedSymlinks) {
+ this->Makefile->IssueMessage(
+ cmake::AUTHOR_WARNING,
+ cmPolicies::GetPolicyWarning(cmPolicies::CMP0009));
+ }
+ break;
}
- this->Makefile->AddDefinition(variable, output.c_str());
+ std::sort(files.begin(), files.end());
+ files.erase(std::unique(files.begin(), files.end()), files.end());
+ this->Makefile->AddDefinition(variable, cmJoin(files, ";").c_str());
return true;
}
@@ -905,6 +913,38 @@ bool cmFileCommand::HandleMakeDirectoryCommand(
return true;
}
+bool cmFileCommand::HandleTouchCommand(std::vector<std::string> const& args,
+ bool create)
+{
+ // File command has at least one argument
+ assert(args.size() > 1);
+
+ std::vector<std::string>::const_iterator i = args.begin();
+
+ i++; // Get rid of subcommand
+
+ for (; i != args.end(); ++i) {
+ std::string tfile = *i;
+ if (!cmsys::SystemTools::FileIsFullPath(tfile)) {
+ tfile = this->Makefile->GetCurrentSourceDirectory();
+ tfile += "/" + *i;
+ }
+ if (!this->Makefile->CanIWriteThisFile(tfile)) {
+ std::string e =
+ "attempted to touch a file: " + tfile + " in a source directory.";
+ this->SetError(e);
+ cmSystemTools::SetFatalErrorOccured();
+ return false;
+ }
+ if (!cmSystemTools::Touch(tfile, create)) {
+ std::string error = "problem touching file: " + tfile;
+ this->SetError(error);
+ return false;
+ }
+ }
+ return true;
+}
+
bool cmFileCommand::HandleDifferentCommand(
std::vector<std::string> const& args)
{
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 17269f3..719dca2 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -39,6 +39,7 @@ protected:
bool HandleHashCommand(std::vector<std::string> const& args);
bool HandleStringsCommand(std::vector<std::string> const& args);
bool HandleGlobCommand(std::vector<std::string> const& args, bool recurse);
+ bool HandleTouchCommand(std::vector<std::string> const& args, bool create);
bool HandleMakeDirectoryCommand(std::vector<std::string> const& args);
bool HandleRelativePathCommand(std::vector<std::string> const& args);
diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h
index b1f8ed6..114989b 100644
--- a/Source/cmFileTimeComparison.h
+++ b/Source/cmFileTimeComparison.h
@@ -8,9 +8,9 @@
class cmFileTimeComparisonInternal;
/** \class cmFileTimeComparison
- * \brief Helper class for performing globbing searches.
+ * \brief Helper class for comparing file modification times.
*
- * Finds all files that match a given globbing expression.
+ * Compare file modification times or test if file modification times differ.
*/
class cmFileTimeComparison
{
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 417cdd2..865595b 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -67,8 +67,6 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
}
this->AlreadyInCache = false;
- this->SelectDefaultNoPackageRootPath();
-
// Find the current root path mode.
this->SelectDefaultRootPathMode();
@@ -206,16 +204,12 @@ void cmFindBase::FillPackageRootPath()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];
- // Add package specific search prefixes
- // NOTE: This should be using const_reverse_iterator but HP aCC and
- // Oracle sunCC both currently have standard library issues
- // with the reverse iterator APIs.
- for (std::deque<std::string>::reverse_iterator pkg =
- this->Makefile->FindPackageModuleStack.rbegin();
- pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) {
- std::string varName = *pkg + "_ROOT";
- paths.AddCMakePrefixPath(varName);
- paths.AddEnvPrefixPath(varName);
+ // Add the PACKAGE_ROOT_PATH from each enclosing find_package call.
+ for (std::deque<std::vector<std::string>>::const_reverse_iterator pkgPaths =
+ this->Makefile->FindPackageRootPathStack.rbegin();
+ pkgPaths != this->Makefile->FindPackageRootPathStack.rend();
+ ++pkgPaths) {
+ paths.AddPrefixPaths(*pkgPaths);
}
paths.AddSuffixes(this->SearchPathSuffixes);
@@ -225,8 +219,8 @@ void cmFindBase::FillCMakeVariablePath()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::CMake];
- // Add CMake varibles of the same name as the previous environment
- // varibles CMAKE_*_PATH to be used most of the time with -D
+ // Add CMake variables of the same name as the previous environment
+ // variables CMAKE_*_PATH to be used most of the time with -D
// command line options
std::string var = "CMAKE_";
var += this->CMakePathName;
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index 4a467f3..64108d7 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -88,13 +88,6 @@ void cmFindCommon::InitializeSearchPathGroups()
std::make_pair(PathLabel::Guess, cmSearchPath(this)));
}
-void cmFindCommon::SelectDefaultNoPackageRootPath()
-{
- if (!this->Makefile->IsOn("__UNDOCUMENTED_CMAKE_FIND_PACKAGE_ROOT")) {
- this->NoPackageRootPath = true;
- }
-}
-
void cmFindCommon::SelectDefaultRootPathMode()
{
// Check the policy variable for this find command type.
diff --git a/Source/cmFindCommon.h b/Source/cmFindCommon.h
index b237f1b..89ff174 100644
--- a/Source/cmFindCommon.h
+++ b/Source/cmFindCommon.h
@@ -84,9 +84,6 @@ protected:
/** Compute final search path list (reroot + trailing slash). */
void ComputeFinalPaths();
- /** Decide whether to enable the PACKAGE_ROOT search entries. */
- void SelectDefaultNoPackageRootPath();
-
/** Compute the current default root path mode. */
void SelectDefaultRootPathMode();
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 2f3a85b..e9ac4a7 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -21,6 +21,7 @@
#include "cmAlgorithms.h"
#include "cmMakefile.h"
+#include "cmPolicies.h"
#include "cmSearchPath.h"
#include "cmState.h"
#include "cmStateTypes.h"
@@ -209,8 +210,6 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
this->SortDirection = strcmp(sd, "ASC") == 0 ? Asc : Dec;
}
- this->SelectDefaultNoPackageRootPath();
-
// Find the current root path mode.
this->SelectDefaultRootPathMode();
@@ -454,6 +453,38 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
+ {
+ // Allocate a PACKAGE_ROOT_PATH for the current find_package call.
+ this->Makefile->FindPackageRootPathStack.emplace_back();
+ std::vector<std::string>& rootPaths =
+ *this->Makefile->FindPackageRootPathStack.rbegin();
+
+ // Add root paths from <PackageName>_ROOT CMake and environment variables,
+ // subject to CMP0074.
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0074)) {
+ case cmPolicies::WARN:
+ this->Makefile->MaybeWarnCMP0074(this->Name);
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // OLD behavior is to ignore the <pkg>_ROOT variables.
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0074));
+ break;
+ case cmPolicies::NEW: {
+ // NEW behavior is to honor the <pkg>_ROOT variables.
+ std::string const rootVar = this->Name + "_ROOT";
+ if (const char* pkgRoot = this->Makefile->GetDefinition(rootVar)) {
+ cmSystemTools::ExpandListArgument(pkgRoot, rootPaths, false);
+ }
+ cmSystemTools::GetPath(rootPaths, rootVar.c_str());
+ } break;
+ }
+ }
+
this->SetModuleVariables(components);
// See if there is a Find<package>.cmake module.
@@ -589,9 +620,6 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
exact += "_FIND_VERSION_EXACT";
this->AddFindDefinition(exact, this->VersionExact ? "1" : "0");
}
-
- // Push on to the package stack
- this->Makefile->FindPackageModuleStack.push_back(this->Name);
}
void cmFindPackageCommand::AddFindDefinition(const std::string& var,
@@ -1076,7 +1104,7 @@ void cmFindPackageCommand::AppendSuccessInformation()
this->RestoreFindDefinitions();
// Pop the package stack
- this->Makefile->FindPackageModuleStack.pop_back();
+ this->Makefile->FindPackageRootPathStack.pop_back();
}
void cmFindPackageCommand::ComputePrefixes()
@@ -1116,16 +1144,14 @@ void cmFindPackageCommand::FillPrefixesPackageRoot()
{
cmSearchPath& paths = this->LabeledPaths[PathLabel::PackageRoot];
- // Add package specific search prefixes
- // NOTE: This should be using const_reverse_iterator but HP aCC and
- // Oracle sunCC both currently have standard library issues
- // with the reverse iterator APIs.
- for (std::deque<std::string>::reverse_iterator pkg =
- this->Makefile->FindPackageModuleStack.rbegin();
- pkg != this->Makefile->FindPackageModuleStack.rend(); ++pkg) {
- std::string varName = *pkg + "_ROOT";
- paths.AddCMakePath(varName);
- paths.AddEnvPath(varName);
+ // Add the PACKAGE_ROOT_PATH from each enclosing find_package call.
+ for (std::deque<std::vector<std::string>>::const_reverse_iterator pkgPaths =
+ this->Makefile->FindPackageRootPathStack.rbegin();
+ pkgPaths != this->Makefile->FindPackageRootPathStack.rend();
+ ++pkgPaths) {
+ for (std::string const& path : *pkgPaths) {
+ paths.AddPath(path);
+ }
}
}
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 92dac79..0561799 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <string>
+#include <utility>
#include <vector>
struct cmGeneratorExpressionContext;
@@ -64,17 +65,16 @@ private:
struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
{
GeneratorExpressionContent(const char* startContent, size_t length);
- void SetIdentifier(
- std::vector<cmGeneratorExpressionEvaluator*> const& identifier)
+
+ void SetIdentifier(std::vector<cmGeneratorExpressionEvaluator*> identifier)
{
- this->IdentifierChildren = identifier;
+ this->IdentifierChildren = std::move(identifier);
}
void SetParameters(
- std::vector<std::vector<cmGeneratorExpressionEvaluator*>> const&
- parameters)
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*>> parameters)
{
- this->ParamChildren = parameters;
+ this->ParamChildren = std::move(parameters);
}
Type GetType() const override
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index c1f1ee4..f444113 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -275,6 +275,62 @@ static const struct EqualNode : public cmGeneratorExpressionNode
}
} equalNode;
+static const struct InListNode : public cmGeneratorExpressionNode
+{
+ InListNode() {}
+
+ int NumExpectedParameters() const override { return 2; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* /*context*/,
+ const GeneratorExpressionContent* /*content*/,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ std::vector<std::string> values;
+ cmSystemTools::ExpandListArgument(parameters[1], values);
+ if (values.empty()) {
+ return "0";
+ }
+
+ return std::find(values.cbegin(), values.cend(), parameters.front()) ==
+ values.cend()
+ ? "0"
+ : "1";
+ }
+} inListNode;
+
+static const struct TargetExistsNode : public cmGeneratorExpressionNode
+{
+ TargetExistsNode() {}
+
+ int NumExpectedParameters() const override { return 1; }
+
+ std::string Evaluate(
+ const std::vector<std::string>& parameters,
+ cmGeneratorExpressionContext* context,
+ const GeneratorExpressionContent* content,
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
+ {
+ if (parameters.size() != 1) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_EXISTS:...> expression requires one parameter");
+ return std::string();
+ }
+
+ std::string targetName = parameters.front();
+ if (targetName.empty() ||
+ !cmGeneratorExpression::IsValidTargetName(targetName)) {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_EXISTS:tgt> expression requires a non-empty "
+ "valid target name.");
+ return std::string();
+ }
+
+ return context->LG->GetMakefile()->FindTargetToUse(targetName) ? "1" : "0";
+ }
+} targetExistsNode;
+
static const struct LowerCaseNode : public cmGeneratorExpressionNode
{
LowerCaseNode() {}
@@ -1827,6 +1883,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
nodeMap["TARGET_BUNDLE_CONTENT_DIR"] = &targetBundleContentDirNode;
nodeMap["STREQUAL"] = &strEqualNode;
nodeMap["EQUAL"] = &equalNode;
+ nodeMap["IN_LIST"] = &inListNode;
nodeMap["LOWER_CASE"] = &lowerCaseNode;
nodeMap["UPPER_CASE"] = &upperCaseNode;
nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode;
@@ -1839,6 +1896,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
nodeMap["TARGET_NAME"] = &targetNameNode;
nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
nodeMap["TARGET_POLICY"] = &targetPolicyNode;
+ nodeMap["TARGET_EXISTS"] = &targetExistsNode;
nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;
nodeMap["INSTALL_PREFIX"] = &installPrefixNode;
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
index 278de04..7b4dc7b 100644
--- a/Source/cmGeneratorExpressionParser.cxx
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -6,6 +6,7 @@
#include <assert.h>
#include <stddef.h>
+#include <utility>
cmGeneratorExpressionParser::cmGeneratorExpressionParser(
const std::vector<cmGeneratorExpressionToken>& tokens)
@@ -92,7 +93,7 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
assert(this->it != this->Tokens.end());
++this->it;
--this->NestingLevel;
- content->SetIdentifier(identifier);
+ content->SetIdentifier(std::move(identifier));
result.push_back(content);
return;
}
@@ -198,8 +199,8 @@ void cmGeneratorExpressionParser::ParseGeneratorExpression(
((this->it - 1)->Content - startToken->Content) + (this->it - 1)->Length;
GeneratorExpressionContent* content =
new GeneratorExpressionContent(startToken->Content, contentLength);
- content->SetIdentifier(identifier);
- content->SetParameters(parameters);
+ content->SetIdentifier(std::move(identifier));
+ content->SetParameters(std::move(parameters));
result.push_back(content);
}
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 2bb01b2..63bfbc6 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -132,8 +132,8 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
this->SourceEntries, true);
this->DLLPlatform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
+ "") != 0;
this->PolicyMap = t->PolicyMap;
}
@@ -240,13 +240,16 @@ const char* cmGeneratorTarget::GetOutputTargetType(
case cmStateEnums::MODULE_LIBRARY:
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
- // Module import libraries are treated as archive targets.
+ // Module libraries are always treated as library targets.
return "LIBRARY";
case cmStateEnums::ImportLibraryArtifact:
- // Module libraries are always treated as library targets.
+ // Module import libraries are treated as archive targets.
return "ARCHIVE";
}
break;
+ case cmStateEnums::OBJECT_LIBRARY:
+ // Object libraries are always treated as object targets.
+ return "OBJECT";
case cmStateEnums::EXECUTABLE:
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
@@ -808,6 +811,26 @@ static void AddInterfaceEntries(
}
}
+static void AddObjectEntries(
+ cmGeneratorTarget const* thisTarget, std::string const& config,
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries)
+{
+ if (cmLinkImplementationLibraries const* impl =
+ thisTarget->GetLinkImplementationLibraries(config)) {
+ for (cmLinkImplItem const& lib : impl->Libraries) {
+ if (lib.Target &&
+ lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ std::string genex = "$<TARGET_OBJECTS:" + lib + ">";
+ cmGeneratorExpression ge(lib.Backtrace);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex);
+ cge->SetEvaluateForBuildsystem(true);
+ entries.push_back(
+ new cmGeneratorTarget::TargetPropertyEntry(std::move(cge), lib));
+ }
+ }
+ }
+}
+
static bool processSources(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
@@ -848,13 +871,10 @@ static bool processSources(
std::ostringstream err;
if (!targetName.empty()) {
err << "Target \"" << targetName
- << "\" contains relative "
- "path in its INTERFACE_SOURCES:\n"
- " \""
+ << "\" contains relative path in its INTERFACE_SOURCES:\n \""
<< src << "\"";
} else {
- err << "Found relative path while evaluating sources of "
- "\""
+ err << "Found relative path while evaluating sources of \""
<< tgt->GetName() << "\":\n \"" << src << "\"\n";
}
tgt->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, err.str());
@@ -931,23 +951,32 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<std::string>& files,
processSources(this, this->SourceEntries, files, uniqueSrcs, &dagChecker,
config, debugSources);
+ // Collect INTERFACE_SOURCES of all direct link-dependencies.
std::vector<cmGeneratorTarget::TargetPropertyEntry*>
linkInterfaceSourcesEntries;
-
AddInterfaceEntries(this, config, "INTERFACE_SOURCES",
linkInterfaceSourcesEntries);
-
std::vector<std::string>::size_type numFilesBefore = files.size();
bool contextDependentInterfaceSources =
processSources(this, linkInterfaceSourcesEntries, files, uniqueSrcs,
&dagChecker, config, debugSources);
+ // Collect TARGET_OBJECTS of direct object link-dependencies.
+ std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkObjectsEntries;
+ AddObjectEntries(this, config, linkObjectsEntries);
+ std::vector<std::string>::size_type numFilesBefore2 = files.size();
+ bool contextDependentObjects =
+ processSources(this, linkObjectsEntries, files, uniqueSrcs, &dagChecker,
+ config, debugSources);
+
if (!contextDependentDirectSources &&
- !(contextDependentInterfaceSources && numFilesBefore < files.size())) {
+ !(contextDependentInterfaceSources && numFilesBefore < files.size()) &&
+ !(contextDependentObjects && numFilesBefore2 < files.size())) {
this->LinkImplementationLanguageIsContextDependent = false;
}
cmDeleteAll(linkInterfaceSourcesEntries);
+ cmDeleteAll(linkObjectsEntries);
}
void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
@@ -1053,9 +1082,6 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
kind = SourceKindHeader;
} else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
kind = SourceKindExternalObject;
- if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- badObjLib.push_back(sf);
- }
} else if (!sf->GetLanguage().empty()) {
kind = SourceKindObjectSource;
} else if (ext == "def") {
@@ -1673,6 +1699,7 @@ bool cmGeneratorTarget::HaveWellDefinedOutputFiles() const
return this->GetType() == cmStateEnums::STATIC_LIBRARY ||
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
+ this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
this->GetType() == cmStateEnums::EXECUTABLE;
}
@@ -2001,8 +2028,13 @@ void cmGeneratorTarget::ComputeModuleDefinitionInfo(
info.WindowsExportAllSymbols =
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") &&
this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS");
+#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE)
info.DefFileGenerated =
info.WindowsExportAllSymbols || info.Sources.size() > 1;
+#else
+ // Our __create_def helper is only available on Windows.
+ info.DefFileGenerated = false;
+#endif
if (info.DefFileGenerated) {
info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def";
} else if (!info.Sources.empty()) {
@@ -2592,13 +2624,20 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
return includes;
}
+enum class OptionsParse
+{
+ None,
+ Shell
+};
+
static void processCompileOptionsInternal(
cmGeneratorTarget const* tgt,
const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries,
std::vector<std::string>& options,
std::unordered_set<std::string>& uniqueOptions,
cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config,
- bool debugOptions, const char* logName, std::string const& language)
+ bool debugOptions, const char* logName, std::string const& language,
+ OptionsParse parse)
{
for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) {
std::vector<std::string> entryOptions;
@@ -2609,7 +2648,12 @@ static void processCompileOptionsInternal(
std::string usedOptions;
for (std::string const& opt : entryOptions) {
if (uniqueOptions.insert(opt).second) {
- options.push_back(opt);
+ if (parse == OptionsParse::Shell &&
+ cmHasLiteralPrefix(opt, "SHELL:")) {
+ cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, options);
+ } else {
+ options.push_back(opt);
+ }
if (debugOptions) {
usedOptions += " * " + opt + "\n";
}
@@ -2634,7 +2678,7 @@ static void processCompileOptions(
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions, "options",
- language);
+ language, OptionsParse::Shell);
}
void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result,
@@ -2688,7 +2732,7 @@ static void processCompileFeatures(
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions, "features",
- std::string());
+ std::string(), OptionsParse::None);
}
void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result,
@@ -2738,7 +2782,7 @@ static void processCompileDefinitions(
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions,
- "definitions", language);
+ "definitions", language, OptionsParse::None);
}
void cmGeneratorTarget::GetCompileDefinitions(
@@ -5325,20 +5369,6 @@ cmGeneratorTarget* cmGeneratorTarget::FindTargetToLink(
tgt = nullptr;
}
- if (tgt && tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::ostringstream e;
- e << "Target \"" << this->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.";
- cmake* cm = this->LocalGenerator->GetCMakeInstance();
- cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
- tgt = nullptr;
- }
-
return tgt;
}
@@ -5402,6 +5432,7 @@ bool cmGeneratorTarget::IsLinkable() const
this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY ||
this->GetType() == cmStateEnums::UNKNOWN_LIBRARY ||
+ this->GetType() == cmStateEnums::OBJECT_LIBRARY ||
this->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
this->IsExecutableWithExports());
}
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index c805b98..f9eb90f 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -6,11 +6,11 @@
#include "cmsys/FStream.hxx"
#include <algorithm>
#include <assert.h>
+#include <cstring>
#include <iterator>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
@@ -1806,6 +1806,8 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
cmSystemTools::OutputOption outputflag,
std::vector<std::string> const& nativeOptions)
{
+ bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
+
/**
* Run an executable command and put the stdout in output.
*/
@@ -1813,9 +1815,17 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
output += "Change Dir: ";
output += bindir;
output += "\n";
+ if (workdir.Failed()) {
+ cmSystemTools::SetRunCommandHideConsole(hideconsole);
+ cmSystemTools::Error("Failed to change directory: ",
+ std::strerror(workdir.GetLastResult()));
+ output += "Failed to change directory: ";
+ output += std::strerror(workdir.GetLastResult());
+ output += "\n";
+ return 1;
+ }
int retVal;
- bool hideconsole = cmSystemTools::GetRunCommandHideConsole();
cmSystemTools::SetRunCommandHideConsole(true);
std::string outputBuffer;
std::string* outputPtr = &outputBuffer;
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index b251f86..55a403e 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1223,11 +1223,13 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
for (std::string const& file : files) {
knownDependencies.insert(this->ConvertToNinjaPath(file));
}
- // get list files which are implicit dependencies as well and will be phony
- // for rebuild manifest
- std::vector<std::string> const& lf = lg->GetMakefile()->GetListFiles();
- for (std::string const& j : lf) {
- knownDependencies.insert(this->ConvertToNinjaPath(j));
+ if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ // get list files which are implicit dependencies as well and will be
+ // phony for rebuild manifest
+ std::vector<std::string> const& lf = lg->GetMakefile()->GetListFiles();
+ for (std::string const& j : lf) {
+ knownDependencies.insert(this->ConvertToNinjaPath(j));
+ }
}
std::vector<cmGeneratorExpressionEvaluationFile*> const& ef =
lg->GetMakefile()->GetEvaluationFiles();
@@ -1335,6 +1337,9 @@ void cmGlobalNinjaGenerator::WriteTargetAll(std::ostream& os)
void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return;
+ }
cmLocalGenerator* lg = this->LocalGenerators[0];
std::ostringstream cmd;
@@ -1384,8 +1389,14 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
/*explicitDeps=*/cmNinjaDeps(), implicitDeps,
/*orderOnlyDeps=*/cmNinjaDeps(), variables);
+ cmNinjaDeps missingInputs;
+ std::set_difference(std::make_move_iterator(implicitDeps.begin()),
+ std::make_move_iterator(implicitDeps.end()),
+ CustomCommandOutputs.begin(), CustomCommandOutputs.end(),
+ std::back_inserter(missingInputs));
+
this->WritePhonyBuild(os, "A missing CMake input file is not an error.",
- implicitDeps, cmNinjaDeps());
+ missingInputs, cmNinjaDeps());
}
std::string cmGlobalNinjaGenerator::ninjaCmd() const
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index d990a6c..c92df55 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -241,6 +241,10 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
lg->WriteMakeRule(makefileStream, "The main recursive preinstall target",
"preinstall", depends, no_commands, true);
+ // Write an empty clean:
+ lg->WriteMakeRule(makefileStream, "The main recursive clean target", "clean",
+ depends, no_commands, true);
+
// Write out the "special" stuff
lg->WriteSpecialTargetsTop(makefileStream);
@@ -256,6 +260,10 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
{
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return;
+ }
+
// Open the output file. This should not be copy-if-different
// because the check-build-system step compares the makefile time to
// see if the build system must be regenerated.
@@ -525,7 +533,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
std::vector<std::string> depends;
std::vector<std::string> commands;
- depends.push_back("cmake_check_build_system");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
// write the target convenience rules
for (cmLocalGenerator* localGen : this->LocalGenerators) {
@@ -558,7 +569,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
tmp += "Makefile2";
commands.push_back(lg->GetRecursiveMakeCall(tmp.c_str(), name));
depends.clear();
- depends.push_back("cmake_check_build_system");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
lg->WriteMakeRule(ruleFileStream, "Build rule for target.", name,
depends, commands, true);
@@ -609,7 +622,10 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
// write the directory level rules for this local gen
this->WriteDirectoryRules2(ruleFileStream, lg);
- depends.push_back("cmake_check_build_system");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
// for each target Generate the rule files for each target.
const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
@@ -715,7 +731,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
commands.push_back(progCmd.str());
}
depends.clear();
- depends.push_back("cmake_check_build_system");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
localName = lg->GetRelativeTargetDirectory(gtarget);
localName += "/rule";
lg->WriteMakeRule(ruleFileStream,
@@ -898,7 +916,9 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
"for this Makefile:");
lg->AppendEcho(commands, "... all (the default if no target is provided)");
lg->AppendEcho(commands, "... clean");
- lg->AppendEcho(commands, "... depend");
+ if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ lg->AppendEcho(commands, "... depend");
+ }
// Keep track of targets already listed.
std::set<std::string> emittedTargets;
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 73a5dae..205e0d0 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -636,126 +636,89 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
cmsys::ofstream fout(vcxprojAbs.c_str());
cmXMLWriter xw(fout);
- /* clang-format off */
- xw.StartDocument();
- xw.StartElement("Project");
- xw.Attribute("DefaultTargets", "Build");
- xw.Attribute("ToolsVersion", "4.0");
- xw.Attribute("xmlns",
- "http://schemas.microsoft.com/developer/msbuild/2003");
- if (this->IsNsightTegra()) {
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "NsightTegraProject");
- xw.StartElement("NsightTegraProjectRevisionNumber");
- xw.Content("6");
- xw.EndElement(); // NsightTegraProjectRevisionNumber
- xw.EndElement(); // PropertyGroup
- }
- xw.StartElement("ItemGroup");
- xw.Attribute("Label", "ProjectConfigurations");
- xw.StartElement("ProjectConfiguration");
- xw.Attribute("Include", "Debug|" + this->GetPlatformName());
- xw.StartElement("Configuration");
- xw.Content("Debug");
- xw.EndElement(); // Configuration
- xw.StartElement("Platform");
- xw.Content(this->GetPlatformName());
- xw.EndElement(); // Platform
- xw.EndElement(); // ProjectConfiguration
- xw.EndElement(); // ItemGroup
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "Globals");
- xw.StartElement("ProjectGuid");
- xw.Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
- xw.EndElement(); // ProjectGuid
- xw.StartElement("Keyword");
- xw.Content("Win32Proj");
- xw.EndElement(); // Keyword
- xw.StartElement("Platform");
- xw.Content(this->GetPlatformName());
- xw.EndElement(); // Platform
- if (this->GetSystemName() == "WindowsPhone") {
- xw.StartElement("ApplicationType");
- xw.Content("Windows Phone");
- xw.EndElement(); // ApplicationType
- xw.StartElement("ApplicationTypeRevision");
- xw.Content(this->GetSystemVersion());
- xw.EndElement(); // ApplicationTypeRevision
- } else if (this->GetSystemName() == "WindowsStore") {
- xw.StartElement("ApplicationType");
- xw.Content("Windows Store");
- xw.EndElement(); // ApplicationType
- xw.StartElement("ApplicationTypeRevision");
- xw.Content(this->GetSystemVersion());
- xw.EndElement(); // ApplicationTypeRevision
- }
- if (!this->WindowsTargetPlatformVersion.empty()) {
- xw.StartElement("WindowsTargetPlatformVersion");
- xw.Content(this->WindowsTargetPlatformVersion);
- xw.EndElement(); // WindowsTargetPlatformVersion
- }
- if (this->GetPlatformName() == "ARM64") {
- xw.StartElement("WindowsSDKDesktopARM64Support");
- xw.Content("true");
- xw.EndElement(); // WindowsSDK64DesktopARMSupport
- }
- else if (this->GetPlatformName() == "ARM") {
- xw.StartElement("WindowsSDKDesktopARMSupport");
- xw.Content("true");
- xw.EndElement(); // WindowsSDKDesktopARMSupport
- }
- xw.EndElement(); // PropertyGroup
- xw.StartElement("Import");
- xw.Attribute("Project",
- "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
- xw.EndElement(); // Import
+ cmXMLDocument doc(xw);
+ cmXMLElement eprj(doc, "Project");
+ eprj.Attribute("DefaultTargets", "Build");
+ eprj.Attribute("ToolsVersion", "4.0");
+ eprj.Attribute("xmlns",
+ "http://schemas.microsoft.com/developer/msbuild/2003");
+ if (this->IsNsightTegra()) {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "NsightTegraProject");
+ cmXMLElement(epg, "NsightTegraProjectRevisionNumber").Content("6");
+ }
+ {
+ cmXMLElement eig(eprj, "ItemGroup");
+ eig.Attribute("Label", "ProjectConfigurations");
+ cmXMLElement epc(eig, "ProjectConfiguration");
+ epc.Attribute("Include", "Debug|" + this->GetPlatformName());
+ cmXMLElement(epc, "Configuration").Content("Debug");
+ cmXMLElement(epc, "Platform").Content(this->GetPlatformName());
+ }
+ {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "Globals");
+ cmXMLElement(epg, "ProjectGuid")
+ .Content("{F3FC6D86-508D-3FB1-96D2-995F08B142EC}");
+ cmXMLElement(epg, "Keyword").Content("Win32Proj");
+ cmXMLElement(epg, "Platform").Content(this->GetPlatformName());
+ if (this->GetSystemName() == "WindowsPhone") {
+ cmXMLElement(epg, "ApplicationType").Content("Windows Phone");
+ cmXMLElement(epg, "ApplicationTypeRevision")
+ .Content(this->GetSystemVersion());
+ } else if (this->GetSystemName() == "WindowsStore") {
+ cmXMLElement(epg, "ApplicationType").Content("Windows Store");
+ cmXMLElement(epg, "ApplicationTypeRevision")
+ .Content(this->GetSystemVersion());
+ }
+ if (!this->WindowsTargetPlatformVersion.empty()) {
+ cmXMLElement(epg, "WindowsTargetPlatformVersion")
+ .Content(this->WindowsTargetPlatformVersion);
+ }
+ if (this->GetPlatformName() == "ARM64") {
+ cmXMLElement(epg, "WindowsSDKDesktopARM64Support").Content("true");
+ } else if (this->GetPlatformName() == "ARM") {
+ cmXMLElement(epg, "WindowsSDKDesktopARMSupport").Content("true");
+ }
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props");
if (!this->GeneratorToolsetHostArchitecture.empty()) {
- xw.StartElement("PropertyGroup");
- xw.StartElement("PreferredToolArchitecture");
- xw.Content(this->GeneratorToolsetHostArchitecture);
- xw.EndElement(); // PreferredToolArchitecture
- xw.EndElement(); // PropertyGroup
+ cmXMLElement epg(eprj, "PropertyGroup");
+ cmXMLElement(epg, "PreferredToolArchitecture")
+ .Content(this->GeneratorToolsetHostArchitecture);
}
- xw.StartElement("PropertyGroup");
- xw.Attribute("Label", "Configuration");
- xw.StartElement("ConfigurationType");
+ {
+ cmXMLElement epg(eprj, "PropertyGroup");
+ epg.Attribute("Label", "Configuration");
+ {
+ cmXMLElement ect(epg, "ConfigurationType");
+ if (this->IsNsightTegra()) {
+ // Tegra-Android platform does not understand "Utility".
+ ect.Content("StaticLibrary");
+ } else {
+ ect.Content("Utility");
+ }
+ }
+ cmXMLElement(epg, "CharacterSet").Content("MultiByte");
if (this->IsNsightTegra()) {
- // Tegra-Android platform does not understand "Utility".
- xw.Content("StaticLibrary");
+ cmXMLElement(epg, "NdkToolchainVersion")
+ .Content(this->GetPlatformToolsetString());
} else {
- xw.Content("Utility");
+ cmXMLElement(epg, "PlatformToolset")
+ .Content(this->GetPlatformToolsetString());
}
- xw.EndElement(); // ConfigurationType
- xw.StartElement("CharacterSet");
- xw.Content("MultiByte");
- xw.EndElement(); // CharacterSet
- if (this->IsNsightTegra()) {
- xw.StartElement("NdkToolchainVersion");
- xw.Content(this->GetPlatformToolsetString());
- xw.EndElement(); // NdkToolchainVersion
- } else {
- xw.StartElement("PlatformToolset");
- xw.Content(this->GetPlatformToolsetString());
- xw.EndElement(); // PlatformToolset
- }
- xw.EndElement(); // PropertyGroup
- xw.StartElement("Import");
- xw.Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
- xw.EndElement(); // Import
- xw.StartElement("ItemDefinitionGroup");
- xw.StartElement("PostBuildEvent");
- xw.StartElement("Command");
- xw.Content("echo VCTargetsPath=$(VCTargetsPath)");
- xw.EndElement(); // Command
- xw.EndElement(); // PostBuildEvent
- xw.EndElement(); // ItemDefinitionGroup
- xw.StartElement("Import");
- xw.Attribute("Project",
- "$(VCTargetsPath)\\Microsoft.Cpp.targets");
- xw.EndElement(); // Import
- xw.EndElement(); // Project
- xw.EndDocument();
- /* clang-format on */
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props");
+ {
+ cmXMLElement eidg(eprj, "ItemDefinitionGroup");
+ cmXMLElement epbe(eidg, "PostBuildEvent");
+ cmXMLElement(epbe, "Command")
+ .Content("echo VCTargetsPath=$(VCTargetsPath)");
+ }
+ cmXMLElement(eprj, "Import")
+ .Attribute("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets");
}
std::vector<std::string> cmd;
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index ab8ad70..87804ff 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -217,7 +217,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
cmMakefile* mf = lg->GetMakefile();
// Skip the target if no regeneration is to be done.
- if (mf->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ if (this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
return false;
}
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index a4570e1..fa7dc51 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -737,26 +737,24 @@ bool cmGlobalVisualStudioGenerator::TargetIsFortranOnly(
bool cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(
cmGeneratorTarget const* gt)
{
- // check to see if this is a C# build
- std::set<std::string> languages;
- {
- // Issue diagnostic if the source files depend on the config.
- std::vector<cmSourceFile*> sources;
- if (!gt->GetConfigCommonSourceFiles(sources)) {
- return false;
- }
- // Only "real" targets are allowed to be C# targets.
- if (gt->Target->GetType() > cmStateEnums::OBJECT_LIBRARY) {
- return false;
- }
+ // C# targets can be defined with add_library() (using SHARED or STATIC) and
+ // also using add_executable(). We do not treat imported C# targets the same
+ // (these come in as UTILITY)
+ if (gt->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ gt->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ gt->GetType() != cmStateEnums::EXECUTABLE) {
+ return false;
}
- gt->GetLanguages(languages, "");
- if (languages.size() == 1) {
- if (*languages.begin() == "CSharp") {
- return true;
- }
+
+ // Issue diagnostic if the source files depend on the config.
+ std::vector<cmSourceFile*> sources;
+ if (!gt->GetConfigCommonSourceFiles(sources)) {
+ return false;
}
- return false;
+
+ std::set<std::string> languages;
+ gt->GetLanguages(languages, "");
+ return languages.size() == 1 && languages.count("CSharp") > 0;
}
bool cmGlobalVisualStudioGenerator::TargetCanBeReferenced(
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 8f61071..f8597af 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -458,7 +458,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
makeHelper.push_back(""); // placeholder, see below
// Add ZERO_CHECK
- bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
+ bool regenerate = !this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
bool generateTopLevelProjectOnly =
mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
bool isTopLevel =
@@ -466,7 +466,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) {
this->CreateReRunCMakeFile(root, gens);
std::string file =
- this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile.c_str());
+ this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile);
cmSystemTools::ReplaceString(file, "\\ ", " ");
cmTarget* check = mf->AddUtilityCommand(
CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmMakefile::TargetOrigin::Generator,
@@ -553,7 +553,7 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
for (const auto& lfile : lfiles) {
makefileStream << "TARGETS += $(subst $(space),$(spaceplus),$(wildcard "
- << this->ConvertToRelativeForMake(lfile.c_str()) << "))\n";
+ << this->ConvertToRelativeForMake(lfile) << "))\n";
}
std::string checkCache = root->GetBinaryDirectory();
@@ -562,11 +562,11 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
checkCache += "cmake.check_cache";
makefileStream << "\n"
- << this->ConvertToRelativeForMake(checkCache.c_str())
+ << this->ConvertToRelativeForMake(checkCache)
<< ": $(TARGETS)\n";
makefileStream << "\t"
<< this->ConvertToRelativeForMake(
- cmSystemTools::GetCMakeCommand().c_str())
+ cmSystemTools::GetCMakeCommand())
<< " -H"
<< this->ConvertToRelativeForMake(root->GetSourceDirectory())
<< " -B"
@@ -1571,12 +1571,11 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(
}
std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
- cdir = this->ConvertToRelativeForMake(cdir.c_str());
+ cdir = this->ConvertToRelativeForMake(cdir);
std::string makecmd = "make -C ";
makecmd += cdir;
makecmd += " -f ";
- makecmd +=
- this->ConvertToRelativeForMake((makefile + "$CONFIGURATION").c_str());
+ makecmd += this->ConvertToRelativeForMake((makefile + "$CONFIGURATION"));
makecmd += " all";
buildphase->AddAttribute("shellScript", this->CreateString(makecmd));
buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
@@ -1611,8 +1610,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
const std::vector<std::string>& outputs = ccg.GetOutputs();
if (!outputs.empty()) {
for (auto const& output : outputs) {
- makefileStream << "\\\n\t"
- << this->ConvertToRelativeForMake(output.c_str());
+ makefileStream << "\\\n\t" << this->ConvertToRelativeForMake(output);
}
} else {
std::ostringstream str;
@@ -1633,8 +1631,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
// There is at least one output, start the rule for it
const char* sep = "";
for (auto const& output : outputs) {
- makefileStream << sep
- << this->ConvertToRelativeForMake(output.c_str());
+ makefileStream << sep << this->ConvertToRelativeForMake(output);
sep = " ";
}
makefileStream << ": ";
@@ -1646,8 +1643,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
std::string dep;
if (this->CurrentLocalGenerator->GetRealDependency(d, configName,
dep)) {
- makefileStream << "\\\n"
- << this->ConvertToRelativeForMake(dep.c_str());
+ makefileStream << "\\\n" << this->ConvertToRelativeForMake(dep);
}
}
makefileStream << "\n";
@@ -1664,12 +1660,12 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
// Build the command line in a single string.
std::string cmd2 = ccg.GetCommand(c);
cmSystemTools::ReplaceString(cmd2, "/./", "/");
- cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
+ cmd2 = this->ConvertToRelativeForMake(cmd2);
std::string cmd;
std::string wd = ccg.GetWorkingDirectory();
if (!wd.empty()) {
cmd += "cd ";
- cmd += this->ConvertToRelativeForMake(wd.c_str());
+ cmd += this->ConvertToRelativeForMake(wd);
cmd += " && ";
}
cmd += cmd2;
@@ -3193,7 +3189,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
std::string tfull = gt->GetFullPath(configName);
- std::string trel = this->ConvertToRelativeForMake(tfull.c_str());
+ std::string trel = this->ConvertToRelativeForMake(tfull);
// Add this target to the post-build phases of its dependencies.
std::map<std::string, cmXCodeObject::StringVec>::const_iterator y =
@@ -3221,7 +3217,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
target->GetDependLibraries().find(configName);
if (x != target->GetDependLibraries().end()) {
for (auto const& deplib : x->second) {
- std::string file = this->ConvertToRelativeForMake(deplib.c_str());
+ std::string file = this->ConvertToRelativeForMake(deplib);
makefileStream << "\\\n\t" << file;
dummyRules.insert(file);
}
@@ -3236,7 +3232,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
d += objLibName;
d += ".a";
- std::string dependency = this->ConvertToRelativeForMake(d.c_str());
+ std::string dependency = this->ConvertToRelativeForMake(d);
makefileStream << "\\\n\t" << dependency;
dummyRules.insert(dependency);
}
@@ -3244,8 +3240,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
// Write the action to remove the target if it is out of date.
makefileStream << "\n";
makefileStream << "\t/bin/rm -f "
- << this->ConvertToRelativeForMake(tfull.c_str())
- << "\n";
+ << this->ConvertToRelativeForMake(tfull) << "\n";
// if building for more than one architecture
// then remove those executables as well
if (this->Architectures.size() > 1) {
@@ -3257,8 +3252,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
universalFile += "/";
universalFile += gt->GetFullName(configName);
makefileStream << "\t/bin/rm -f "
- << this->ConvertToRelativeForMake(
- universalFile.c_str())
+ << this->ConvertToRelativeForMake(universalFile)
<< "\n";
}
}
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index 354b757..f996788 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -25,7 +25,7 @@ cmIDEOptions::~cmIDEOptions()
{
}
-void cmIDEOptions::HandleFlag(const char* flag)
+void cmIDEOptions::HandleFlag(std::string const& flag)
{
// If the last option was -D then this option is the definition.
if (this->DoingDefine) {
@@ -49,26 +49,27 @@ void cmIDEOptions::HandleFlag(const char* flag)
}
// Look for known arguments.
- if (flag[0] == '-' || (this->AllowSlash && flag[0] == '/')) {
+ size_t len = flag.length();
+ if (len > 0 && (flag[0] == '-' || (this->AllowSlash && flag[0] == '/'))) {
// Look for preprocessor definitions.
- if (this->AllowDefine && flag[1] == 'D') {
- if (flag[2] == '\0') {
+ if (this->AllowDefine && len > 1 && flag[1] == 'D') {
+ if (len <= 2) {
// The next argument will have the definition.
this->DoingDefine = true;
} else {
// Store this definition.
- this->Defines.push_back(flag + 2);
+ this->Defines.push_back(flag.substr(2));
}
return;
}
// Look for include directory.
- if (this->AllowInclude && flag[1] == 'I') {
- if (flag[2] == '\0') {
+ if (this->AllowInclude && len > 1 && flag[1] == 'I') {
+ if (len <= 2) {
// The next argument will have the include directory.
this->DoingInclude = true;
} else {
// Store this include directory.
- this->Includes.push_back(flag + 2);
+ this->Includes.push_back(flag.substr(2));
}
return;
}
@@ -92,8 +93,9 @@ void cmIDEOptions::HandleFlag(const char* flag)
}
bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
- const char* flag, bool& flag_handled)
+ std::string const& flag, bool& flag_handled)
{
+ const char* pf = flag.c_str() + 1;
// Look for an entry in the flag table matching this flag.
for (cmIDEFlagTable const* entry = table; entry->IDEName; ++entry) {
bool entry_found = false;
@@ -102,17 +104,17 @@ bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
// the entry specifies UserRequired we must match only if a
// non-empty value is given.
int n = static_cast<int>(strlen(entry->commandFlag));
- if ((strncmp(flag + 1, entry->commandFlag, n) == 0 ||
+ if ((strncmp(pf, entry->commandFlag, n) == 0 ||
(entry->special & cmIDEFlagTable::CaseInsensitive &&
- cmsysString_strncasecmp(flag + 1, entry->commandFlag, n))) &&
+ cmsysString_strncasecmp(pf, entry->commandFlag, n))) &&
(!(entry->special & cmIDEFlagTable::UserRequired) ||
- static_cast<int>(strlen(flag + 1)) > n)) {
- this->FlagMapUpdate(entry, flag + n + 1);
+ static_cast<int>(strlen(pf)) > n)) {
+ this->FlagMapUpdate(entry, std::string(pf + n));
entry_found = true;
}
- } else if (strcmp(flag + 1, entry->commandFlag) == 0 ||
+ } else if (strcmp(pf, entry->commandFlag) == 0 ||
(entry->special & cmIDEFlagTable::CaseInsensitive &&
- cmsysString_strcasecmp(flag + 1, entry->commandFlag) == 0)) {
+ cmsysString_strcasecmp(pf, entry->commandFlag) == 0)) {
if (entry->special & cmIDEFlagTable::UserFollowing) {
// This flag expects a value in the following argument.
this->DoingFollowing = entry;
@@ -137,7 +139,7 @@ bool cmIDEOptions::CheckFlagTable(cmIDEFlagTable const* table,
}
void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
- const char* new_value)
+ std::string const& new_value)
{
if (entry->special & cmIDEFlagTable::UserIgnored) {
// Ignore the user-specified value.
@@ -157,9 +159,9 @@ void cmIDEOptions::AddDefine(const std::string& def)
this->Defines.push_back(def);
}
-void cmIDEOptions::AddDefines(const char* defines)
+void cmIDEOptions::AddDefines(std::string const& defines)
{
- if (defines) {
+ if (!defines.empty()) {
// Expand the list of definitions.
cmSystemTools::ExpandListArgument(defines, this->Defines);
}
@@ -179,9 +181,9 @@ void cmIDEOptions::AddInclude(const std::string& include)
this->Includes.push_back(include);
}
-void cmIDEOptions::AddIncludes(const char* includes)
+void cmIDEOptions::AddIncludes(std::string const& includes)
{
- if (includes) {
+ if (!includes.empty()) {
// Expand the list of includes.
cmSystemTools::ExpandListArgument(includes, this->Includes);
}
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index 54cb524..a4e5757 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -22,12 +22,12 @@ public:
// Store definitions, includes and flags.
void AddDefine(const std::string& define);
- void AddDefines(const char* defines);
+ void AddDefines(std::string const& defines);
void AddDefines(const std::vector<std::string>& defines);
std::vector<std::string> const& GetDefines() const;
void AddInclude(const std::string& includes);
- void AddIncludes(const char* includes);
+ void AddIncludes(std::string const& includes);
void AddIncludes(const std::vector<std::string>& includes);
std::vector<std::string> const& GetIncludes() const;
@@ -95,11 +95,12 @@ protected:
FlagTableCount = 16
};
cmIDEFlagTable const* FlagTable[FlagTableCount];
- void HandleFlag(const char* flag);
- bool CheckFlagTable(cmIDEFlagTable const* table, const char* flag,
+ void HandleFlag(std::string const& flag);
+ bool CheckFlagTable(cmIDEFlagTable const* table, std::string const& flag,
bool& flag_handled);
- void FlagMapUpdate(cmIDEFlagTable const* entry, const char* new_value);
- virtual void StoreUnknownFlag(const char* flag) = 0;
+ void FlagMapUpdate(cmIDEFlagTable const* entry,
+ std::string const& new_value);
+ virtual void StoreUnknownFlag(std::string const& flag) = 0;
};
#endif
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 394f976..b5291a1 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -5,6 +5,7 @@
#include "cmsys/Glob.hxx"
#include <sstream>
#include <stddef.h>
+#include <string.h>
#include <utility>
#include "cmAlgorithms.h"
@@ -334,8 +335,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// Check whether this is a DLL platform.
bool dll_platform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
+ "") != 0;
for (std::string const& tgt : targetList.GetVector()) {
@@ -360,17 +361,6 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->SetError(e.str());
return false;
}
- if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::string reason;
- if (!this->Makefile->GetGlobalGenerator()->HasKnownObjectFileLocation(
- &reason)) {
- std::ostringstream e;
- e << "TARGETS given OBJECT library \"" << tgt
- << "\" which may not be installed" << reason << ".";
- this->SetError(e.str());
- return false;
- }
- }
// Store the target in the list to be installed.
targets.push_back(target);
} else {
@@ -534,15 +524,23 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
case cmStateEnums::OBJECT_LIBRARY: {
// Objects use OBJECT properties.
if (!objectArgs.GetDestination().empty()) {
+ // Verify that we know where the objects are to install them.
+ std::string reason;
+ if (!this->Makefile->GetGlobalGenerator()
+ ->HasKnownObjectFileLocation(&reason)) {
+ std::ostringstream e;
+ e << "TARGETS given OBJECT library \"" << target.GetName()
+ << "\" whose objects may not be installed" << reason << ".";
+ this->SetError(e.str());
+ return false;
+ }
+
objectGenerator =
CreateInstallTargetGenerator(target, objectArgs, false);
} else {
- std::ostringstream e;
- e << "TARGETS given no OBJECTS DESTINATION for object library "
- "target \""
- << target.GetName() << "\".";
- this->SetError(e.str());
- return false;
+ // Installing an OBJECT library without a destination transforms
+ // it to an INTERFACE library. It installs no files but can be
+ // exported.
}
} break;
case cmStateEnums::EXECUTABLE: {
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 8c889fc..c1af92f 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <utility>
+#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
@@ -24,6 +25,7 @@
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmake.h"
+#include "cmsys/FStream.hxx"
cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg,
cmMakefile* mf)
@@ -286,8 +288,51 @@ void cmLocalNinjaGenerator::AppendCustomCommandDeps(
}
}
+std::string cmLocalNinjaGenerator::WriteCommandScript(
+ std::vector<std::string> const& cmdLines, std::string const& customStep,
+ cmGeneratorTarget const* target) const
+{
+ std::string scriptPath;
+ if (target) {
+ scriptPath = target->GetSupportDirectory();
+ } else {
+ scriptPath = this->GetCurrentBinaryDirectory();
+ scriptPath += cmake::GetCMakeFilesDirectory();
+ }
+ cmSystemTools::MakeDirectory(scriptPath);
+ scriptPath += '/';
+ scriptPath += customStep;
+#ifdef _WIN32
+ scriptPath += ".bat";
+#else
+ scriptPath += ".sh";
+#endif
+
+ cmsys::ofstream script(scriptPath.c_str());
+
+#ifndef _WIN32
+ script << "set -e\n\n";
+#endif
+
+ for (auto const& i : cmdLines) {
+ std::string cmd = i;
+ // The command line was built assuming it would be written to
+ // the build.ninja file, so it uses '$$' for '$'. Remove this
+ // for the raw shell script.
+ cmSystemTools::ReplaceString(cmd, "$$", "$");
+#ifdef _WIN32
+ script << cmd << " || exit /b" << '\n';
+#else
+ script << cmd << '\n';
+#endif
+ }
+
+ return scriptPath;
+}
+
std::string cmLocalNinjaGenerator::BuildCommandLine(
- const std::vector<std::string>& cmdLines)
+ std::vector<std::string> const& cmdLines, std::string const& customStep,
+ cmGeneratorTarget const* target) const
{
// If we have no commands but we need to build a command anyway, use noop.
// This happens when building a POST_BUILD value for link targets that
@@ -296,6 +341,35 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
return cmGlobalNinjaGenerator::SHELL_NOOP;
}
+ // If this is a custom step then we will have no '$VAR' ninja placeholders.
+ // This means we can deal with long command sequences by writing to a script.
+ // Do this if the command lines are on the scale of the OS limit.
+ if (!customStep.empty()) {
+ size_t cmdLinesTotal = 0;
+ for (std::string const& cmd : cmdLines) {
+ cmdLinesTotal += cmd.length() + 6;
+ }
+ if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) {
+ std::string const scriptPath =
+ this->WriteCommandScript(cmdLines, customStep, target);
+ std::string cmd
+#ifndef _WIN32
+ = "/bin/sh "
+#endif
+ ;
+ cmd += this->ConvertToOutputFormat(
+ this->GetGlobalNinjaGenerator()->ConvertToNinjaPath(scriptPath),
+ cmOutputConverter::SHELL);
+
+ // Add an unused argument based on script content so that Ninja
+ // knows when the command lines change.
+ cmd += " ";
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ cmd += hash.HashFile(scriptPath).substr(0, 16);
+ return cmd;
+ }
+ }
+
std::ostringstream cmd;
for (std::vector<std::string>::const_iterator li = cmdLines.begin();
li != cmdLines.end(); ++li)
@@ -406,10 +480,16 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
"Phony custom command for " + ninjaOutputs[0], ninjaOutputs, ninjaDeps,
cmNinjaDeps(), orderOnlyDeps, cmNinjaVars());
} else {
+ std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
+ // Hash full path to make unique.
+ customStep += '-';
+ cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+ customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
+
this->GetGlobalNinjaGenerator()->WriteCustomCommandBuild(
- this->BuildCommandLine(cmdLines), this->ConstructComment(ccg),
- "Custom command for " + ninjaOutputs[0], cc->GetDepfile(),
- cc->GetUsesTerminal(),
+ this->BuildCommandLine(cmdLines, customStep),
+ this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
+ cc->GetDepfile(), cc->GetUsesTerminal(),
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, ninjaDeps,
orderOnlyDeps);
}
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 95d8a61..f772fb0 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -59,7 +59,10 @@ public:
return this->HomeRelativeOutputPath;
}
- std::string BuildCommandLine(const std::vector<std::string>& cmdLines);
+ std::string BuildCommandLine(
+ std::vector<std::string> const& cmdLines,
+ std::string const& customStep = std::string(),
+ cmGeneratorTarget const* target = nullptr) const;
void AppendTargetOutputs(cmGeneratorTarget* target, cmNinjaDeps& outputs);
void AppendTargetDepends(
@@ -98,6 +101,10 @@ private:
std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg);
+ std::string WriteCommandScript(std::vector<std::string> const& cmdLines,
+ std::string const& customStep,
+ cmGeneratorTarget const* target) const;
+
std::string HomeRelativeOutputPath;
typedef std::map<cmCustomCommand const*, std::set<cmGeneratorTarget*>>
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index ddd8cc4..c9237a8 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -760,7 +760,8 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom(
// Write special "cmake_check_build_system" target to run cmake with
// the --check-build-system flag.
- {
+ if (!this->GlobalGenerator->GlobalSettingIsOn(
+ "CMAKE_SUPPRESS_REGENERATION")) {
// Build command to run CMake to check if anything needs regenerating.
std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
cmakefileName += "Makefile.cmake";
@@ -1580,7 +1581,11 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
std::string recursiveTarget = this->GetCurrentBinaryDirectory();
recursiveTarget += "/all";
- depends.push_back("cmake_check_build_system");
+ bool regenerate =
+ !this->GlobalGenerator->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
+ if (regenerate) {
+ depends.push_back("cmake_check_build_system");
+ }
std::string progressDir = this->GetBinaryDirectory();
progressDir += cmake::GetCMakeFilesDirectory();
@@ -1643,7 +1648,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
if (!noall || cmSystemTools::IsOff(noall)) {
// Drive the build before installing.
depends.push_back("all");
- } else {
+ } else if (regenerate) {
// At least make sure the build system is up to date.
depends.push_back("cmake_check_build_system");
}
@@ -1657,24 +1662,26 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
this->WriteMakeRule(ruleFileStream, "Prepare targets for installation.",
"preinstall/fast", depends, commands, true);
- // write the depend rule, really a recompute depends rule
- depends.clear();
- commands.clear();
- std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
- cmakefileName += "Makefile.cmake";
- {
- std::string runRule =
- "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
- runRule += " --check-build-system ";
- runRule +=
- this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
- runRule += " 1";
- commands.push_back(std::move(runRule));
+ if (regenerate) {
+ // write the depend rule, really a recompute depends rule
+ depends.clear();
+ commands.clear();
+ std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
+ cmakefileName += "Makefile.cmake";
+ {
+ std::string runRule =
+ "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
+ runRule += " --check-build-system ";
+ runRule +=
+ this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
+ runRule += " 1";
+ commands.push_back(std::move(runRule));
+ }
+ this->CreateCDCommand(commands, this->GetBinaryDirectory(),
+ this->GetCurrentBinaryDirectory());
+ this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
+ commands, true);
}
- this->CreateCDCommand(commands, this->GetBinaryDirectory(),
- this->GetCurrentBinaryDirectory());
- this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
- commands, true);
}
void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 98b1c44..500a0aa 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -210,7 +210,8 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj(
cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
{
- if (this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ if (this->GlobalGenerator->GlobalSettingIsOn(
+ "CMAKE_SUPPRESS_REGENERATION")) {
return nullptr;
}
@@ -1677,8 +1678,8 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
}
Options fileOptions(this, tool, table, gg->ExtraFlagTable);
fileOptions.Parse(fc.CompileFlags.c_str());
- fileOptions.AddDefines(fc.CompileDefs.c_str());
- fileOptions.AddDefines(fc.CompileDefsConfig.c_str());
+ fileOptions.AddDefines(fc.CompileDefs);
+ fileOptions.AddDefines(fc.CompileDefsConfig);
// validate source level include directories
std::vector<std::string> includes;
this->AppendIncludeDirectories(includes, fc.IncludeDirs, **sf);
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index b468208..1191490 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -6,12 +6,12 @@
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <assert.h>
+#include <cstring>
#include <ctype.h>
#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdlib.h>
-#include <string.h>
#include <utility>
#include "cmAlgorithms.h"
@@ -158,6 +158,26 @@ bool cmMakefile::CheckCMP0037(std::string const& targetName,
return true;
}
+void cmMakefile::MaybeWarnCMP0074(std::string const& pkg)
+{
+ // Warn if a <pkg>_ROOT variable we may use is set.
+ std::string const varName = pkg + "_ROOT";
+ bool const haveVar = this->GetDefinition(varName) != nullptr;
+ bool const haveEnv = cmSystemTools::HasEnv(varName);
+ if ((haveVar || haveEnv) && this->WarnedCMP0074.insert(varName).second) {
+ std::ostringstream w;
+ w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0074) << "\n";
+ if (haveVar) {
+ w << "CMake variable " << varName << " is set.\n";
+ }
+ if (haveEnv) {
+ w << "Environment variable " << varName << " is set.\n";
+ }
+ w << "For compatibility, CMake is ignoring the variable.";
+ this->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
+}
+
cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const
{
return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries();
@@ -1867,7 +1887,7 @@ cmTarget* cmMakefile::AddLibrary(const std::string& lname,
// Clear its dependencies. Otherwise, dependencies might persist
// over changes in CMakeLists.txt, making the information stale and
// hence useless.
- target->ClearDependencyInformation(*this, lname);
+ target->ClearDependencyInformation(*this);
if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
@@ -3138,6 +3158,14 @@ void cmMakefile::SetArgcArgv(const std::vector<std::string>& args)
cmSourceFile* cmMakefile::GetSource(const std::string& sourceName,
cmSourceFileLocationKind kind) const
{
+ // First check "Known" paths (avoids the creation of cmSourceFileLocation)
+ if (kind == cmSourceFileLocationKind::Known) {
+ auto sfsi = this->KnownFileSearchIndex.find(sourceName);
+ if (sfsi != this->KnownFileSearchIndex.end()) {
+ return sfsi->second;
+ }
+ }
+
cmSourceFileLocation sfl(this, sourceName, kind);
auto name = this->GetCMakeInstance()->StripExtension(sfl.GetName());
#if defined(_WIN32) || defined(__APPLE__)
@@ -3170,6 +3198,10 @@ cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName,
name = cmSystemTools::LowerCase(name);
#endif
this->SourceFileSearchIndex[name].push_back(sf);
+ // for "Known" paths add direct lookup (used for faster lookup in GetSource)
+ if (kind == cmSourceFileLocationKind::Known) {
+ this->KnownFileSearchIndex[sourceName] = sf;
+ }
return sf;
}
@@ -3238,6 +3270,14 @@ int cmMakefile::TryCompile(const std::string& srcdir,
// change to the tests directory and run cmake
// use the cmake object instead of calling cmake
cmWorkingDirectory workdir(bindir);
+ if (workdir.Failed()) {
+ this->IssueMessage(cmake::FATAL_ERROR,
+ "Failed to set working directory to " + bindir + " : " +
+ std::strerror(workdir.GetLastResult()));
+ cmSystemTools::SetFatalErrorOccured();
+ this->IsSourceFileTryCompile = false;
+ return 1;
+ }
// make sure the same generator is used
// use this program as the cmake to be run, it should not
@@ -3641,6 +3681,20 @@ void cmMakefile::AppendProperty(const std::string& prop, const char* value,
const char* cmMakefile::GetProperty(const std::string& prop) const
{
+ // Check for computed properties.
+ static std::string output;
+ if (prop == "TESTS") {
+ std::vector<std::string> keys;
+ // get list of keys
+ std::transform(this->Tests.begin(), this->Tests.end(),
+ std::back_inserter(keys),
+ [](decltype(this->Tests)::value_type const& pair) {
+ return pair.first;
+ });
+ output = cmJoin(keys, ";");
+ return output.c_str();
+ }
+
return this->StateSnapshot.GetDirectory().GetProperty(prop);
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 5a30790..aafe60b 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -832,9 +832,11 @@ public:
void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen);
void AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen);
- // Maintain a stack of package names to determine the depth of find modules
- // we are currently being called with
- std::deque<std::string> FindPackageModuleStack;
+ // Maintain a stack of package roots to allow nested PACKAGE_ROOT_PATH
+ // searches
+ std::deque<std::vector<std::string>> FindPackageRootPathStack;
+
+ void MaybeWarnCMP0074(std::string const& pkg);
protected:
// add link libraries and directories to the target
@@ -861,6 +863,9 @@ protected:
typedef std::unordered_map<std::string, SourceFileVec> SourceFileMap;
SourceFileMap SourceFileSearchIndex;
+ // For "Known" paths we can store a direct filename to cmSourceFile map
+ std::unordered_map<std::string, cmSourceFile*> KnownFileSearchIndex;
+
// Tests
std::map<std::string, cmTest*> Tests;
@@ -998,6 +1003,7 @@ private:
bool WarnUnused;
bool CheckSystemVars;
bool CheckCMP0000;
+ std::set<std::string> WarnedCMP0074;
bool IsSourceFileTryCompile;
mutable bool SuppressWatches;
};
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 73cf1f0..abe5ff3 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -643,6 +643,18 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
source.GetFullPath(), workingDirectory, compileCommand);
}
+ // See if we need to use a compiler launcher like ccache or distcc
+ std::string compilerLauncher;
+ if (!compileCommands.empty() && (lang == "C" || lang == "CXX" ||
+ lang == "Fortran" || lang == "CUDA")) {
+ std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
+ const char* clauncher =
+ this->GeneratorTarget->GetProperty(clauncher_prop);
+ if (clauncher && *clauncher) {
+ compilerLauncher = clauncher;
+ }
+ }
+
// Maybe insert an include-what-you-use runner.
if (!compileCommands.empty() && (lang == "C" || lang == "CXX")) {
std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
@@ -656,6 +668,13 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint) ||
(cppcheck && *cppcheck)) {
std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_co_compile";
+ if (!compilerLauncher.empty()) {
+ // In __run_co_compile case the launcher command is supplied
+ // via --launcher=<maybe-list> and consumed
+ run_iwyu += " --launcher=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
+ compilerLauncher.clear();
+ }
if (iwyu && *iwyu) {
run_iwyu += " --iwyu=";
run_iwyu += this->LocalGenerator->EscapeForShell(iwyu);
@@ -682,21 +701,15 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
}
}
- // Maybe insert a compiler launcher like ccache or distcc
- if (!compileCommands.empty() && (lang == "C" || lang == "CXX" ||
- lang == "Fortran" || lang == "CUDA")) {
- std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
- const char* clauncher =
- this->GeneratorTarget->GetProperty(clauncher_prop);
- if (clauncher && *clauncher) {
- std::vector<std::string> launcher_cmd;
- cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true);
- for (std::string& i : launcher_cmd) {
- i = this->LocalGenerator->EscapeForShell(i);
- }
- std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " ";
- compileCommands.front().insert(0, run_launcher);
+ // If compiler launcher was specified and not consumed above, it
+ // goes to the beginning of the command line.
+ if (!compileCommands.empty() && !compilerLauncher.empty()) {
+ std::vector<std::string> args;
+ cmSystemTools::ExpandListArgument(compilerLauncher, args, true);
+ for (std::string& i : args) {
+ i = this->LocalGenerator->EscapeForShell(i);
}
+ compileCommands.front().insert(0, cmJoin(args, " ") + " ");
}
std::string launcher;
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index ddbc772..f1fb2d2 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -976,8 +976,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
preLinkCmdLines.push_back("cd " + homeOutDir);
}
- vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines);
- std::string postBuildCmdLine = localGen.BuildCommandLine(postBuildCmdLines);
+ vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link",
+ this->GeneratorTarget);
+ std::string postBuildCmdLine = localGen.BuildCommandLine(
+ postBuildCmdLines, "post-build", this->GeneratorTarget);
cmNinjaVars symlinkVars;
bool const symlinkNeeded =
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index f4faf47..fa7d95a 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -653,6 +653,17 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
cmSystemTools::ExpandListArgument(compileCmd, compileCmds);
}
+ // See if we need to use a compiler launcher like ccache or distcc
+ std::string compilerLauncher;
+ if (!compileCmds.empty() &&
+ (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA")) {
+ std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
+ const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
+ if (clauncher && *clauncher) {
+ compilerLauncher = clauncher;
+ }
+ }
+
// Maybe insert an include-what-you-use runner.
if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) {
std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE";
@@ -668,6 +679,13 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
std::string run_iwyu = this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
run_iwyu += " -E __run_co_compile";
+ if (!compilerLauncher.empty()) {
+ // In __run_co_compile case the launcher command is supplied
+ // via --launcher=<maybe-list> and consumed
+ run_iwyu += " --launcher=";
+ run_iwyu += this->LocalGenerator->EscapeForShell(compilerLauncher);
+ compilerLauncher.clear();
+ }
if (iwyu && *iwyu) {
run_iwyu += " --iwyu=";
run_iwyu += this->GetLocalGenerator()->EscapeForShell(iwyu);
@@ -693,20 +711,15 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
}
}
- // Maybe insert a compiler launcher like ccache or distcc
- if (!compileCmds.empty() &&
- (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA")) {
- std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
- const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
- if (clauncher && *clauncher) {
- std::vector<std::string> launcher_cmd;
- cmSystemTools::ExpandListArgument(clauncher, launcher_cmd, true);
- for (std::string& i : launcher_cmd) {
- i = this->LocalGenerator->EscapeForShell(i);
- }
- std::string const& run_launcher = cmJoin(launcher_cmd, " ") + " ";
- compileCmds.front().insert(0, run_launcher);
+ // If compiler launcher was specified and not consumed above, it
+ // goes to the beginning of the command line.
+ if (!compileCmds.empty() && !compilerLauncher.empty()) {
+ std::vector<std::string> args;
+ cmSystemTools::ExpandListArgument(compilerLauncher, args, true);
+ for (std::string& i : args) {
+ i = this->LocalGenerator->EscapeForShell(i);
}
+ compileCmds.front().insert(0, cmJoin(args, " ") + " ");
}
if (!compileCmds.empty()) {
@@ -856,9 +869,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
vars["DEFINES"] = this->ComputeDefines(source, language);
vars["INCLUDES"] = this->ComputeIncludes(source, language);
+
if (!this->NeedDepTypeMSVC(language)) {
- vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
- objectFileName + ".d", cmOutputConverter::SHELL);
+ bool replaceExt(false);
+ if (!language.empty()) {
+ std::string repVar = "CMAKE_";
+ repVar += language;
+ repVar += "_DEPFILE_EXTENSION_REPLACE";
+ replaceExt = this->Makefile->IsOn(repVar);
+ }
+ if (!replaceExt) {
+ // use original code
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileName + ".d", cmOutputConverter::SHELL);
+ } else {
+ // Replace the original source file extension with the
+ // depend file extension.
+ std::string dependFileName =
+ cmSystemTools::GetFilenameWithoutLastExtension(objectFileName) + ".d";
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ objectFileDir + "/" + dependFileName, cmOutputConverter::SHELL);
+ }
}
this->ExportObjectCompileCommand(
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 7adeb8e..cc6d4b9 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -96,8 +96,8 @@ void cmNinjaUtilityTargetGenerator::Generate()
this->GetBuildFileStream(),
"Utility command for " + this->GetTargetName(), outputs, deps);
} else {
- std::string command =
- this->GetLocalGenerator()->BuildCommandLine(commands);
+ std::string command = this->GetLocalGenerator()->BuildCommandLine(
+ commands, "utility", this->GeneratorTarget);
const char* echoStr =
this->GetGeneratorTarget()->GetProperty("EchoString");
std::string desc;
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 25db929..fd42c53 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -6,7 +6,7 @@
#include <assert.h>
#include <ctype.h>
#include <set>
-#include <sstream>
+#include <string.h>
#include <vector>
#include "cmAlgorithms.h"
@@ -341,12 +341,13 @@ redirection character (for example, ^>, ^<, or ^| ). If you need to
use the caret character itself (^), use two in a row (^^).
*/
-int cmOutputConverter::Shell__CharIsWhitespace(char c)
+/* Some helpers to identify character classes */
+static int Shell__CharIsWhitespace(char c)
{
return ((c == ' ') || (c == '\t'));
}
-int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c)
+static int Shell__CharNeedsQuotesOnUnix(char c)
{
return ((c == '\'') || (c == '`') || (c == ';') || (c == '#') ||
(c == '&') || (c == '$') || (c == '(') || (c == ')') || (c == '~') ||
@@ -354,12 +355,17 @@ int cmOutputConverter::Shell__CharNeedsQuotesOnUnix(char c)
(c == '\\'));
}
-int cmOutputConverter::Shell__CharNeedsQuotesOnWindows(char c)
+static int Shell__CharNeedsQuotesOnWindows(char c)
{
return ((c == '\'') || (c == '#') || (c == '&') || (c == '<') ||
(c == '>') || (c == '|') || (c == '^'));
}
+static int Shell__CharIsMakeVariableName(char c)
+{
+ return c && (c == '_' || isalpha((static_cast<int>(c))));
+}
+
int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
{
/* On Windows the built-in command shell echo never needs quotes. */
@@ -386,11 +392,6 @@ int cmOutputConverter::Shell__CharNeedsQuotes(char c, int flags)
return 0;
}
-int cmOutputConverter::Shell__CharIsMakeVariableName(char c)
-{
- return c && (c == '_' || isalpha((static_cast<int>(c))));
-}
-
const char* cmOutputConverter::Shell__SkipMakeVariables(const char* c)
{
while (*c == '$' && *(c + 1) == '(') {
@@ -481,7 +482,9 @@ int cmOutputConverter::Shell__ArgumentNeedsQuotes(const char* in, int flags)
std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
{
- std::ostringstream out;
+ /* Output will be at least as long as input string. */
+ std::string out;
+ out.reserve(strlen(in));
/* String iterator. */
const char* c;
@@ -495,11 +498,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
/* Add the opening quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) {
if (flags & Shell_Flag_IsUnix) {
- out << '"';
+ out += '"';
}
- out << '\'';
+ out += '\'';
} else {
- out << '"';
+ out += '"';
}
}
@@ -511,7 +514,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
if (skip != c) {
/* Copy to the end of the make variable references. */
while (c != skip) {
- out << *c++;
+ out += *c++;
}
/* The make variable reference eliminates any escaping needed
@@ -531,7 +534,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
quoted argument. */
if (*c == '\\' || *c == '"' || *c == '`' || *c == '$') {
/* This character needs a backslash to escape it. */
- out << '\\';
+ out += '\\';
}
} else if (flags & Shell_Flag_EchoWindows) {
/* On Windows the built-in command shell echo never needs escaping. */
@@ -545,11 +548,11 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
backslashes. */
while (windows_backslashes > 0) {
--windows_backslashes;
- out << '\\';
+ out += '\\';
}
/* Add the backslash to escape the double-quote. */
- out << '\\';
+ out += '\\';
} else {
/* We encountered a normal character. This eliminates any
escaping needed for preceding backslashes. */
@@ -562,7 +565,7 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
if (flags & Shell_Flag_Make) {
/* In Makefiles a dollar is written $$. The make tool will
replace it with just $ before passing it to the shell. */
- out << "$$";
+ out += "$$";
} else if (flags & Shell_Flag_VSIDE) {
/* In a VS IDE a dollar is written "$". If this is written in
an un-quoted argument it starts a quoted segment, inserts
@@ -570,30 +573,30 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
argument it ends quoting, inserts the $ and restarts
quoting. Either way the $ is isolated from surrounding
text to avoid looking like a variable reference. */
- out << "\"$\"";
+ out += "\"$\"";
} else {
/* Otherwise a dollar is written just $. */
- out << '$';
+ out += '$';
}
} else if (*c == '#') {
if ((flags & Shell_Flag_Make) && (flags & Shell_Flag_WatcomWMake)) {
/* In Watcom WMake makefiles a pound is written $#. The make
tool will replace it with just # before passing it to the
shell. */
- out << "$#";
+ out += "$#";
} else {
/* Otherwise a pound is written just #. */
- out << '#';
+ out += '#';
}
} else if (*c == '%') {
if ((flags & Shell_Flag_VSIDE) ||
((flags & Shell_Flag_Make) &&
((flags & Shell_Flag_MinGWMake) || (flags & Shell_Flag_NMake)))) {
/* In the VS IDE, NMake, or MinGW make a percent is written %%. */
- out << "%%";
+ out += "%%";
} else {
/* Otherwise a percent is written just %. */
- out << '%';
+ out += '%';
}
} else if (*c == ';') {
if (flags & Shell_Flag_VSIDE) {
@@ -602,14 +605,14 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
inserts the ; and ends the segment. If it is written in a
quoted argument it ends quoting, inserts the ; and restarts
quoting. Either way the ; is isolated. */
- out << "\";\"";
+ out += "\";\"";
} else {
/* Otherwise a semicolon is written just ;. */
- out << ';';
+ out += ';';
}
} else {
/* Store this character. */
- out << *c;
+ out += *c;
}
}
@@ -617,19 +620,19 @@ std::string cmOutputConverter::Shell__GetArgument(const char* in, int flags)
/* Add enough backslashes to escape any trailing ones. */
while (windows_backslashes > 0) {
--windows_backslashes;
- out << '\\';
+ out += '\\';
}
/* Add the closing quote for this argument. */
if (flags & Shell_Flag_WatcomQuote) {
- out << '\'';
+ out += '\'';
if (flags & Shell_Flag_IsUnix) {
- out << '"';
+ out += '"';
}
} else {
- out << '"';
+ out += '"';
}
}
- return out.str();
+ return out;
}
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index ae15055..ed7143c 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -117,11 +117,7 @@ public:
private:
cmState* GetState() const;
- static int Shell__CharIsWhitespace(char c);
- static int Shell__CharNeedsQuotesOnUnix(char c);
- static int Shell__CharNeedsQuotesOnWindows(char c);
static int Shell__CharNeedsQuotes(char c, int flags);
- static int Shell__CharIsMakeVariableName(char c);
static const char* Shell__SkipMakeVariables(const char* c);
static int Shell__ArgumentNeedsQuotes(const char* in, int flags);
static std::string Shell__GetArgument(const char* in, int flags);
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index c39f927..34fe09d 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -214,7 +214,12 @@ class cmMakefile;
3, 10, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0072, \
"FindOpenGL prefers GLVND by default when available.", 3, 11, 0, \
- cmPolicies::WARN)
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0073, \
+ "Do not produce legacy _LIB_DEPENDS cache entries.", 3, 12, 0, \
+ cmPolicies::WARN) \
+ SELECT(POLICY, CMP0074, "find_package uses PackageName_ROOT variables.", 3, \
+ 12, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -238,7 +243,8 @@ class cmMakefile;
F(CMP0063) \
F(CMP0065) \
F(CMP0068) \
- F(CMP0069)
+ F(CMP0069) \
+ F(CMP0073)
/** \class cmPolicies
* \brief Handles changes in CMake behavior and policies
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index dfa1858..6ddb0b8 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -3,9 +3,11 @@
#include "cmProjectCommand.h"
#include "cmsys/RegularExpression.hxx"
+#include <functional>
#include <sstream>
#include <stdio.h>
+#include "cmAlgorithms.h"
#include "cmMakefile.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
@@ -66,12 +68,19 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
bool haveVersion = false;
bool haveLanguages = false;
bool haveDescription = false;
+ bool haveHomepage = false;
std::string version;
std::string description;
+ std::string homepage;
std::vector<std::string> languages;
+ std::function<void()> missedValueReporter;
+ auto resetReporter = [&missedValueReporter]() {
+ missedValueReporter = std::function<void()>();
+ };
enum Doing
{
DoingDescription,
+ DoingHomepage,
DoingLanguages,
DoingVersion
};
@@ -85,7 +94,18 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
haveLanguages = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingLanguages;
+ if (!languages.empty()) {
+ std::string msg =
+ "the following parameters must be specified after LANGUAGES "
+ "keyword: ";
+ msg += cmJoin(languages, ", ");
+ msg += '.';
+ this->Makefile->IssueMessage(cmake::WARNING, msg);
+ }
} else if (args[i] == "VERSION") {
if (haveVersion) {
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
@@ -94,7 +114,17 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
haveVersion = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingVersion;
+ missedValueReporter = [this, &resetReporter]() {
+ this->Makefile->IssueMessage(
+ cmake::WARNING,
+ "VERSION keyword not followed by a value or was followed by a "
+ "value that expanded to nothing.");
+ resetReporter();
+ };
} else if (args[i] == "DESCRIPTION") {
if (haveDescription) {
this->Makefile->IssueMessage(
@@ -103,23 +133,61 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
haveDescription = true;
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
doing = DoingDescription;
+ missedValueReporter = [this, &resetReporter]() {
+ this->Makefile->IssueMessage(
+ cmake::WARNING,
+ "DESCRIPTION keyword not followed by a value or was followed "
+ "by a value that expanded to nothing.");
+ resetReporter();
+ };
+ } else if (args[i] == "HOMEPAGE_URL") {
+ if (haveHomepage) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR, "HOMEPAGE_URL may be specified at most once.");
+ cmSystemTools::SetFatalErrorOccured();
+ return true;
+ }
+ haveHomepage = true;
+ doing = DoingHomepage;
+ missedValueReporter = [this, &resetReporter]() {
+ this->Makefile->IssueMessage(
+ cmake::WARNING,
+ "HOMEPAGE_URL keyword not followed by a value or was followed "
+ "by a value that expanded to nothing.");
+ resetReporter();
+ };
} else if (doing == DoingVersion) {
doing = DoingLanguages;
version = args[i];
+ resetReporter();
} else if (doing == DoingDescription) {
doing = DoingLanguages;
description = args[i];
+ resetReporter();
+ } else if (doing == DoingHomepage) {
+ doing = DoingLanguages;
+ homepage = args[i];
+ resetReporter();
} else // doing == DoingLanguages
{
languages.push_back(args[i]);
}
}
- if (haveVersion && !haveLanguages && !languages.empty()) {
+ if (missedValueReporter) {
+ missedValueReporter();
+ }
+
+ if ((haveVersion || haveDescription || haveHomepage) && !haveLanguages &&
+ !languages.empty()) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
- "project with VERSION must use LANGUAGES before language names.");
+ "project with VERSION, DESCRIPTION or HOMEPAGE_URL must "
+ "use LANGUAGES before language names.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
@@ -216,6 +284,8 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
if (haveDescription) {
this->Makefile->AddDefinition("PROJECT_DESCRIPTION", description.c_str());
+ this->Makefile->AddDefinition(projectName + "_DESCRIPTION",
+ description.c_str());
// Set the CMAKE_PROJECT_DESCRIPTION variable to be the highest-level
// project name in the tree. If there are two project commands
// in the same CMakeLists.txt file, and it is the top level
@@ -230,6 +300,24 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
}
}
+ if (haveHomepage) {
+ this->Makefile->AddDefinition("PROJECT_HOMEPAGE_URL", homepage.c_str());
+ this->Makefile->AddDefinition(projectName + "_HOMEPAGE_URL",
+ homepage.c_str());
+ // Set the CMAKE_PROJECT_HOMEPAGE_URL variable to be the highest-level
+ // project name in the tree. If there are two project commands
+ // in the same CMakeLists.txt file, and it is the top level
+ // CMakeLists.txt file, then go with the last one.
+ if (!this->Makefile->GetDefinition("CMAKE_PROJECT_HOMEPAGE_URL") ||
+ (this->Makefile->IsRootMakefile())) {
+ this->Makefile->AddDefinition("CMAKE_PROJECT_HOMEPAGE_URL",
+ homepage.c_str());
+ this->Makefile->AddCacheDefinition(
+ "CMAKE_PROJECT_HOMEPAGE_URL", homepage.c_str(),
+ "Value Computed by CMake", cmStateEnums::STATIC);
+ }
+ }
+
if (languages.empty()) {
// if no language is specified do c and c++
languages.push_back("C");
diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
index 6be65ee..37cf0f8 100644
--- a/Source/cmQtAutoGeneratorMocUic.cxx
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -434,7 +434,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
JobHandleT jobHandle(new JobMocT(std::move(jobPre.SourceFile), FileName,
std::move(jobPre.IncludeString)));
if (jobPre.self) {
- // Read depdendencies from this source
+ // Read dependencies from this source
static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
}
if (!wrk.Gen().ParallelJobPushMoc(jobHandle)) {
@@ -452,7 +452,7 @@ bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocHeader(WorkerT& wrk,
if (!macroName.empty()) {
JobHandleT jobHandle(
new JobMocT(std::string(FileName), std::string(), std::string()));
- // Read depdendencies from this source
+ // Read dependencies from this source
static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
success = wrk.Gen().ParallelJobPushMoc(jobHandle);
}
@@ -1373,7 +1373,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
// Compare list sizes
if (sources.size() != options.size()) {
std::ostringstream ost;
- ost << "files/options lists sizes missmatch (" << sources.size() << "/"
+ ost << "files/options lists sizes mismatch (" << sources.size() << "/"
<< options.size() << ")";
Log().ErrorFile(GeneratorT::UIC, InfoFile(), ost.str());
return false;
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
index 7b19210..a7d8cee 100644
--- a/Source/cmRulePlaceholderExpander.h
+++ b/Source/cmRulePlaceholderExpander.h
@@ -24,7 +24,7 @@ public:
this->TargetImpLib = targetImpLib;
}
- // Create a struct to hold the varibles passed into
+ // Create a struct to hold the variables passed into
// ExpandRuleVariables
struct RuleVariables
{
diff --git a/Source/cmSearchPath.h b/Source/cmSearchPath.h
index fd0c7c5..2a576ed 100644
--- a/Source/cmSearchPath.h
+++ b/Source/cmSearchPath.h
@@ -39,10 +39,10 @@ public:
void AddCMakePrefixPath(const std::string& variable);
void AddEnvPrefixPath(const std::string& variable, bool stripBin = false);
void AddSuffixes(const std::vector<std::string>& suffixes);
-
-protected:
void AddPrefixPaths(const std::vector<std::string>& paths,
const char* base = nullptr);
+
+protected:
void AddPathInternal(const std::string& path, const char* base = nullptr);
cmFindCommon* FC;
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 55af078..9631912 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -68,6 +68,9 @@ bool cmStringCommand::InitialPass(std::vector<std::string> const& args,
if (subCommand == "CONCAT") {
return this->HandleConcatCommand(args);
}
+ if (subCommand == "JOIN") {
+ return this->HandleJoinCommand(args);
+ }
if (subCommand == "SUBSTRING") {
return this->HandleSubstringCommand(args);
}
@@ -677,8 +680,26 @@ bool cmStringCommand::HandleConcatCommand(std::vector<std::string> const& args)
return false;
}
- std::string const& variableName = args[1];
- std::string value = cmJoin(cmMakeRange(args).advance(2), std::string());
+ return this->joinImpl(args, std::string(), 1);
+}
+
+bool cmStringCommand::HandleJoinCommand(std::vector<std::string> const& args)
+{
+ if (args.size() < 3) {
+ this->SetError("sub-command JOIN requires at least two arguments.");
+ return false;
+ }
+
+ return this->joinImpl(args, args[1], 2);
+}
+
+bool cmStringCommand::joinImpl(std::vector<std::string> const& args,
+ std::string const& glue, const size_t varIdx)
+{
+ std::string const& variableName = args[varIdx];
+ // NOTE Items to concat/join placed right after the variable for
+ // both `CONCAT` and `JOIN` sub-commands.
+ std::string value = cmJoin(cmMakeRange(args).advance(varIdx + 1), glue);
this->Makefile->AddDefinition(variableName, value.c_str());
return true;
diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h
index b287e37..569ed83 100644
--- a/Source/cmStringCommand.h
+++ b/Source/cmStringCommand.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <cstddef>
#include <string>
#include <vector>
@@ -48,6 +49,7 @@ protected:
bool HandleAppendCommand(std::vector<std::string> const& args);
bool HandlePrependCommand(std::vector<std::string> const& args);
bool HandleConcatCommand(std::vector<std::string> const& args);
+ bool HandleJoinCommand(std::vector<std::string> const& args);
bool HandleStripCommand(std::vector<std::string> const& args);
bool HandleRandomCommand(std::vector<std::string> const& args);
bool HandleFindCommand(std::vector<std::string> const& args);
@@ -56,6 +58,9 @@ protected:
bool HandleGenexStripCommand(std::vector<std::string> const& args);
bool HandleUuidCommand(std::vector<std::string> const& args);
+ bool joinImpl(std::vector<std::string> const& args, std::string const& glue,
+ size_t varIdx);
+
class RegexReplacement
{
public:
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index cd11c4b..6137223 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -114,15 +114,12 @@ const char* cmTargetPropertyComputer::GetSources<cmTarget>(
}
if (!noMessage) {
e << "Target \"" << tgt->GetName()
- << "\" contains "
- "$<TARGET_OBJECTS> generator expression in its sources "
- "list. "
- "This content was not previously part of the SOURCES "
- "property "
- "when that property was read at configure time. Code "
- "reading "
- "that property needs to be adapted to ignore the generator "
- "expression using the string(GENEX_STRIP) command.";
+ << "\" contains $<TARGET_OBJECTS> generator expression in its "
+ "sources list. This content was not previously part of the "
+ "SOURCES property when that property was read at configure "
+ "time. Code reading that property needs to be adapted to "
+ "ignore the generator expression using the string(GENEX_STRIP) "
+ "command.";
messenger->IssueMessage(messageType, e.str(), context);
}
if (addContent) {
@@ -189,18 +186,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
this->BuildInterfaceIncludesAppended = false;
- // only add dependency information for library targets
- if (this->TargetTypeValue >= cmStateEnums::STATIC_LIBRARY &&
- this->TargetTypeValue <= cmStateEnums::MODULE_LIBRARY) {
- this->RecordDependencies = true;
- } else {
- this->RecordDependencies = false;
- }
-
// Check whether this is a DLL platform.
this->DLLPlatform =
- (this->Makefile->IsOn("WIN32") || this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
+ strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"),
+ "") != 0;
// Check whether we are targeting an Android platform.
this->IsAndroid =
@@ -509,7 +498,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s)
{
std::string src = s;
- // For backwards compatibility replace varibles in source names.
+ // For backwards compatibility replace variables in source names.
// This should eventually be removed.
this->Makefile->ExpandVariablesInString(src);
if (src != s) {
@@ -638,27 +627,11 @@ const std::vector<std::string>& cmTarget::GetLinkDirectories() const
return this->LinkDirectories;
}
-void cmTarget::ClearDependencyInformation(cmMakefile& mf,
- const std::string& target)
+void cmTarget::ClearDependencyInformation(cmMakefile& mf)
{
- // Clear the dependencies. The cache variable must exist iff we are
- // recording dependency information for this target.
- std::string depname = target;
+ std::string depname = this->GetName();
depname += "_LIB_DEPENDS";
- if (this->RecordDependencies) {
- mf.AddCacheDefinition(depname, "", "Dependencies for target",
- cmStateEnums::STATIC);
- } else {
- if (mf.GetDefinition(depname)) {
- std::string message = "Target ";
- message += target;
- message += " has dependency information when it shouldn't.\n";
- message += "Your cache is probably stale. Please remove the entry\n ";
- message += depname;
- message += "\nfrom the cache.";
- cmSystemTools::Error(message.c_str());
- }
- }
+ mf.RemoveCacheDefinition(depname);
}
std::string cmTarget::GetDebugGeneratorExpressions(
@@ -742,7 +715,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
}
if (cmGeneratorExpression::Find(lib) != std::string::npos ||
- (tgt && tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) ||
+ (tgt && (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) ||
(this->Name == lib)) {
return;
}
@@ -754,7 +728,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
this->OriginalLinkLibraries.emplace_back(lib, llt);
}
- // Add the explicit dependency information for this target. This is
+ // Add the explicit dependency information for libraries. This is
// simply a set of libraries separated by ";". There should always
// be a trailing ";". These library names are not canonical, in that
// they may be "-framework x", "-ly", "/path/libz.a", etc.
@@ -762,7 +736,10 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
// may be purposefully duplicated to handle recursive dependencies,
// and we removing one instance will break the link line. Duplicates
// will be appropriately eliminated at emit time.
- if (this->RecordDependencies) {
+ if (this->TargetTypeValue >= cmStateEnums::STATIC_LIBRARY &&
+ this->TargetTypeValue <= cmStateEnums::MODULE_LIBRARY &&
+ (this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
+ this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
std::string targetEntry = this->Name;
targetEntry += "_LIB_DEPENDS";
std::string dependencies;
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 56f3e3a..62c4e22 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -137,7 +137,7 @@ public:
/**
* Clear the dependency information recorded for this target, if any.
*/
- void ClearDependencyInformation(cmMakefile& mf, const std::string& target);
+ void ClearDependencyInformation(cmMakefile& mf);
void AddLinkLibrary(cmMakefile& mf, const std::string& lib,
cmTargetLinkLibraryType llt);
@@ -310,7 +310,6 @@ private:
cmTargetInternalPointer Internal;
cmStateEnums::TargetType TargetTypeValue;
bool HaveInstallRule;
- bool RecordDependencies;
bool DLLPlatform;
bool IsAndroid;
bool IsImportedTarget;
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index 9e4575a..699fff8 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -94,16 +94,6 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
return true;
}
- // OBJECT libraries are not allowed on the LHS of the command.
- if (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
- std::ostringstream e;
- e << "Object library target \"" << args[0] << "\" "
- << "may not link to anything.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- cmSystemTools::SetFatalErrorOccured();
- return true;
- }
-
// Having a UTILITY library on the LHS is a bug.
if (this->Target->GetType() == cmStateEnums::UTILITY) {
std::ostringstream e;
@@ -401,14 +391,15 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) &&
(tgt->GetType() != cmStateEnums::SHARED_LIBRARY) &&
(tgt->GetType() != cmStateEnums::UNKNOWN_LIBRARY) &&
+ (tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
(tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
!tgt->IsExecutableWithExports()) {
std::ostringstream e;
e << "Target \"" << lib << "\" of type "
<< cmState::GetTargetTypeName(tgt->GetType())
<< " may not be linked into another target. One may link only to "
- "INTERFACE, STATIC or SHARED libraries, or to executables with the "
- "ENABLE_EXPORTS property set.";
+ "INTERFACE, OBJECT, STATIC or SHARED libraries, or to executables "
+ "with the ENABLE_EXPORTS property set.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index ec31bd6..87d3c78 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -18,6 +18,58 @@
#include <iterator>
#include <memory> // IWYU pragma: keep
+struct cmVisualStudio10TargetGenerator::Elem
+{
+ cmGeneratedFileStream& S;
+ int Indent;
+ bool HasElements = false;
+
+ Elem(cmGeneratedFileStream& s, int i)
+ : S(s)
+ , Indent(i)
+ {
+ }
+ Elem(Elem& par)
+ : S(par.S)
+ , Indent(par.Indent + 1)
+ {
+ par.SetHasElements();
+ }
+ void SetHasElements()
+ {
+ if (!HasElements) {
+ S << ">\n";
+ HasElements = true;
+ }
+ }
+ void WriteEndTag(const char* tag)
+ {
+ if (HasElements) {
+ S.fill(' ');
+ S.width(Indent * 2);
+ S << "</" << tag << ">\n";
+ } else {
+ S << " />\n";
+ }
+ }
+};
+
+inline void cmVisualStudio10TargetGenerator::WriteElem(const char* tag,
+ const char* val,
+ int indentLevel)
+{
+ this->WriteString("<", indentLevel);
+ (*this->BuildFileStream) << tag << ">" << val << "</" << tag << ">\n";
+}
+
+inline void cmVisualStudio10TargetGenerator::WriteElem(const char* tag,
+ std::string const& val,
+ int indentLevel)
+{
+ this->WriteString("<", indentLevel);
+ (*this->BuildFileStream) << tag << ">" << val << "</" << tag << ">\n";
+}
+
static void ConvertToWindowsSlash(std::string& s);
static std::string cmVS10EscapeXML(std::string arg)
@@ -28,6 +80,12 @@ static std::string cmVS10EscapeXML(std::string arg)
return arg;
}
+inline void cmVisualStudio10TargetGenerator::WriteElemEscapeXML(
+ const char* tag, std::string const& val, int indentLevel)
+{
+ this->WriteElem(tag, cmVS10EscapeXML(val), indentLevel);
+}
+
static std::string cmVS10EscapeQuotes(std::string arg)
{
cmSystemTools::ReplaceString(arg, "\"", "&quot;");
@@ -84,16 +142,15 @@ static std::string computeProjectFileExtension(cmGeneratorTarget const* t,
cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
cmGeneratorTarget* target, cmGlobalVisualStudio10Generator* gg)
+ : GeneratorTarget(target)
+ , Makefile(target->Target->GetMakefile())
+ , Platform(gg->GetPlatformName())
+ , Name(target->GetName())
+ , GUID(gg->GetGUID(this->Name))
+ , GlobalGenerator(gg)
+ , LocalGenerator((cmLocalVisualStudio7Generator*)target->GetLocalGenerator())
{
- this->GlobalGenerator = gg;
- this->GeneratorTarget = target;
- this->Makefile = target->Target->GetMakefile();
this->Makefile->GetConfigurations(this->Configurations);
- this->LocalGenerator =
- (cmLocalVisualStudio7Generator*)this->GeneratorTarget->GetLocalGenerator();
- this->Name = this->GeneratorTarget->GetName();
- this->GUID = this->GlobalGenerator->GetGUID(this->Name);
- this->Platform = gg->GetPlatformName();
this->NsightTegra = gg->IsNsightTegra();
for (int i = 0; i < 4; ++i) {
this->NsightTegraVersion[i] = 0;
@@ -266,16 +323,10 @@ void cmVisualStudio10TargetGenerator::Generate()
}
(*this->BuildFileStream) << "</NsightTegraProjectRevisionNumber>\n";
// Tell newer versions to upgrade silently when loading.
- this->WriteString("<NsightTegraUpgradeOnceWithoutPrompt>"
- "true"
- "</NsightTegraUpgradeOnceWithoutPrompt>\n",
- 2);
+ this->WriteElem("NsightTegraUpgradeOnceWithoutPrompt", "true", 2);
} else {
// Require Nsight Tegra 1.6 for JCompile support.
- this->WriteString("<NsightTegraProjectRevisionNumber>"
- "7"
- "</NsightTegraProjectRevisionNumber>\n",
- 2);
+ this->WriteElem("NsightTegraProjectRevisionNumber", "7", 2);
}
this->WriteString("</PropertyGroup>\n", 1);
}
@@ -283,9 +334,7 @@ void cmVisualStudio10TargetGenerator::Generate()
if (const char* hostArch =
this->GlobalGenerator->GetPlatformToolsetHostArchitecture()) {
this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<PreferredToolArchitecture>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(hostArch)
- << "</PreferredToolArchitecture>\n";
+ this->WriteElemEscapeXML("PreferredToolArchitecture", hostArch, 2);
this->WriteString("</PropertyGroup>\n", 1);
}
@@ -293,8 +342,7 @@ void cmVisualStudio10TargetGenerator::Generate()
this->WriteProjectConfigurations();
}
this->WriteString("<PropertyGroup Label=\"Globals\">\n", 1);
- this->WriteString("<ProjectGuid>", 2);
- (*this->BuildFileStream) << "{" << this->GUID << "}</ProjectGuid>\n";
+ this->WriteElem("ProjectGuid", "{" + this->GUID + "}", 2);
if (this->MSTools &&
this->GeneratorTarget->GetType() <= cmStateEnums::GLOBAL_TARGET) {
@@ -323,61 +371,45 @@ void cmVisualStudio10TargetGenerator::Generate()
this->GeneratorTarget->GetProperty("VS_SCC_PROVIDER");
if (vsProjectName && vsLocalPath && vsProvider) {
- this->WriteString("<SccProjectName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProjectName)
- << "</SccProjectName>\n";
- this->WriteString("<SccLocalPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsLocalPath)
- << "</SccLocalPath>\n";
- this->WriteString("<SccProvider>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsProvider)
- << "</SccProvider>\n";
+ this->WriteElemEscapeXML("SccProjectName", vsProjectName, 2);
+ this->WriteElemEscapeXML("SccLocalPath", vsLocalPath, 2);
+ this->WriteElemEscapeXML("SccProvider", vsProvider, 2);
const char* vsAuxPath =
this->GeneratorTarget->GetProperty("VS_SCC_AUXPATH");
if (vsAuxPath) {
- this->WriteString("<SccAuxPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsAuxPath)
- << "</SccAuxPath>\n";
+ this->WriteElemEscapeXML("SccAuxPath", vsAuxPath, 2);
}
}
if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT")) {
- this->WriteString("<WinMDAssembly>true</WinMDAssembly>\n", 2);
+ this->WriteElem("WinMDAssembly", "true", 2);
}
const char* vsGlobalKeyword =
this->GeneratorTarget->GetProperty("VS_GLOBAL_KEYWORD");
if (!vsGlobalKeyword) {
- this->WriteString("<Keyword>Win32Proj</Keyword>\n", 2);
+ this->WriteElem("Keyword", "Win32Proj", 2);
} else {
- this->WriteString("<Keyword>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalKeyword)
- << "</Keyword>\n";
+ this->WriteElemEscapeXML("Keyword", vsGlobalKeyword, 2);
}
const char* vsGlobalRootNamespace =
this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE");
if (vsGlobalRootNamespace) {
- this->WriteString("<RootNamespace>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(vsGlobalRootNamespace)
- << "</RootNamespace>\n";
+ this->WriteElemEscapeXML("RootNamespace", vsGlobalRootNamespace, 2);
}
- this->WriteString("<Platform>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
- << "</Platform>\n";
+ this->WriteElemEscapeXML("Platform", this->Platform, 2);
const char* projLabel = this->GeneratorTarget->GetProperty("PROJECT_LABEL");
if (!projLabel) {
projLabel = this->Name.c_str();
}
- this->WriteString("<ProjectName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(projLabel) << "</ProjectName>\n";
+ this->WriteElemEscapeXML("ProjectName", projLabel, 2);
if (const char* targetFrameworkVersion = this->GeneratorTarget->GetProperty(
"VS_DOTNET_TARGET_FRAMEWORK_VERSION")) {
- this->WriteString("<TargetFrameworkVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetFrameworkVersion)
- << "</TargetFrameworkVersion>\n";
+ this->WriteElemEscapeXML("TargetFrameworkVersion", targetFrameworkVersion,
+ 2);
}
// Disable the project upgrade prompt that is displayed the first time a
@@ -385,9 +417,7 @@ void cmVisualStudio10TargetGenerator::Generate()
// the IDE (respected by VS 2013 and above).
if (this->GlobalGenerator->GetVersion() >=
cmGlobalVisualStudioGenerator::VS12) {
- this->WriteString("<VCProjectUpgraderObjectName>NoUpgrade"
- "</VCProjectUpgraderObjectName>\n",
- 2);
+ this->WriteElem("VCProjectUpgraderObjectName", "NoUpgrade", 2);
}
std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
@@ -438,8 +468,7 @@ void cmVisualStudio10TargetGenerator::Generate()
}
outputType += "</OutputType>\n";
this->WriteString(outputType.c_str(), 2);
- this->WriteString("<AppDesignerFolder>Properties</AppDesignerFolder>\n",
- 2);
+ this->WriteElem("AppDesignerFolder", "Properties", 2);
}
this->WriteString("</PropertyGroup>\n", 1);
@@ -602,8 +631,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
if (!name.empty()) {
std::string path = i.second.GetValue();
if (!cmsys::SystemTools::FileIsFullPath(path)) {
- path = std::string(this->GeneratorTarget->Target->GetMakefile()
- ->GetCurrentSourceDirectory()) +
+ path = std::string(this->Makefile->GetCurrentSourceDirectory()) +
"/" + path;
}
ConvertToWindowsSlash(path);
@@ -637,12 +665,8 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference(
{
this->WriteString("<Reference Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(ref) << "\">\n";
- this->WriteString("<CopyLocalSatelliteAssemblies>true"
- "</CopyLocalSatelliteAssemblies>\n",
- 3);
- this->WriteString("<ReferenceOutputAssembly>true"
- "</ReferenceOutputAssembly>\n",
- 3);
+ this->WriteElem("CopyLocalSatelliteAssemblies", "true", 3);
+ this->WriteElem("ReferenceOutputAssembly", "true", 3);
if (!hint.empty()) {
const char* privateReference = "True";
if (const char* value = this->GeneratorTarget->GetProperty(
@@ -651,10 +675,8 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReference(
privateReference = "False";
}
}
- this->WriteString("<Private>", 3);
- (*this->BuildFileStream) << privateReference << "</Private>\n";
- this->WriteString("<HintPath>", 3);
- (*this->BuildFileStream) << hint << "</HintPath>\n";
+ this->WriteElem("Private", privateReference, 3);
+ this->WriteElem("HintPath", hint, 3);
}
this->WriteDotNetReferenceCustomTags(ref);
this->WriteString("</Reference>\n", 2);
@@ -713,9 +735,8 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
(*this->BuildFileStream) << obj << "\">\n";
if (this->ProjectType != csproj) {
- this->WriteString("<DependentUpon>", 3);
std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
- (*this->BuildFileStream) << hFileName << "</DependentUpon>\n";
+ this->WriteElem("DependentUpon", hFileName, 3);
for (std::string const& i : this->Configurations) {
this->WritePlatformConfigTag("LogicalName", i, 3);
@@ -743,8 +764,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
link = cmsys::SystemTools::GetFilenameName(obj);
}
if (!link.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ this->WriteElem("Link", link, 3);
}
}
// Determine if this is a generated resource from a .Designer.cs file
@@ -758,9 +778,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
generator = g;
}
if (!generator.empty()) {
- this->WriteString("<Generator>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(generator)
- << "</Generator>\n";
+ this->WriteElemEscapeXML("Generator", generator, 3);
if (designerResource.find(srcDir) == 0) {
designerResource = designerResource.substr(srcDir.length() + 1);
} else if (designerResource.find(binDir) == 0) {
@@ -770,9 +788,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
cmsys::SystemTools::GetFilenameName(designerResource);
}
ConvertToWindowsSlash(designerResource);
- this->WriteString("<LastGenOutput>", 3);
- (*this->BuildFileStream) << designerResource
- << "</LastGenOutput>\n";
+ this->WriteElem("LastGenOutput", designerResource, 3);
}
}
const cmPropertyMap& props = oi->GetProperties();
@@ -807,7 +823,7 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
this->WriteString("<ItemGroup>\n", 1);
for (cmSourceFile const* oi : xamlObjs) {
std::string obj = oi->GetFullPath();
- std::string xamlType;
+ const char* xamlType;
const char* xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE");
if (xamlTypeProperty) {
xamlType = xamlTypeProperty;
@@ -815,7 +831,9 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
xamlType = "Page";
}
- this->WriteSource(xamlType, oi, ">\n");
+ Elem e2(*this->BuildFileStream, 2);
+ this->WriteSource(xamlType, oi);
+ e2.SetHasElements();
if (this->ProjectType == csproj && !this->InSourceBuild) {
// add <Link> tag to written XAML source if necessary
const std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
@@ -830,13 +848,11 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
}
if (!link.empty()) {
ConvertToWindowsSlash(link);
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ this->WriteElem("Link", link, 3);
}
}
- this->WriteString("<SubType>Designer</SubType>\n", 3);
- this->WriteString("</", 2);
- (*this->BuildFileStream) << xamlType << ">\n";
+ this->WriteElem("SubType", "Designer", 3);
+ e2.WriteEndTag(xamlType);
}
this->WriteString("</ItemGroup>\n", 1);
}
@@ -858,10 +874,7 @@ void cmVisualStudio10TargetGenerator::WriteTargetSpecificReferences()
void cmVisualStudio10TargetGenerator::WriteTargetsFileReferences()
{
- for (std::vector<TargetsFileAndConfigs>::iterator i =
- this->TargetsFileAndConfigsVec.begin();
- i != this->TargetsFileAndConfigsVec.end(); ++i) {
- TargetsFileAndConfigs const& tac = *i;
+ for (TargetsFileAndConfigs const& tac : this->TargetsFileAndConfigsVec) {
this->WriteString("<Import Project=\"", 3);
(*this->BuildFileStream) << tac.File << "\" ";
(*this->BuildFileStream) << "Condition=\"";
@@ -896,11 +909,10 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
}
if (!references.empty()) {
this->WriteString("<ItemGroup>\n", 1);
- for (std::vector<std::string>::iterator ri = references.begin();
- ri != references.end(); ++ri) {
+ for (std::string const& ri : references) {
this->WriteString("<Reference Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(*ri) << "\">\n";
- this->WriteString("<IsWinMDFile>true</IsWinMDFile>\n", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(ri) << "\">\n";
+ this->WriteElem("IsWinMDFile", "true", 3);
this->WriteString("</Reference>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
@@ -912,16 +924,11 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences()
void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
{
this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1);
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
+ for (std::string const& c : this->Configurations) {
this->WriteString("<ProjectConfiguration Include=\"", 2);
- (*this->BuildFileStream) << *i << "|" << this->Platform << "\">\n";
- this->WriteString("<Configuration>", 3);
- (*this->BuildFileStream) << *i << "</Configuration>\n";
- this->WriteString("<Platform>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
- << "</Platform>\n";
+ (*this->BuildFileStream) << c << "|" << this->Platform << "\">\n";
+ this->WriteElem("Configuration", c, 3);
+ this->WriteElemEscapeXML("Platform", this->Platform, 3);
this->WriteString("</ProjectConfiguration>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
@@ -929,10 +936,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
{
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WritePlatformConfigTag("PropertyGroup", *i, 1,
+ for (std::string const& c : this->Configurations) {
+ this->WritePlatformConfigTag("PropertyGroup", c, 1,
" Label=\"Configuration\"", "\n");
if (this->ProjectType != csproj) {
@@ -979,12 +984,12 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
if (this->MSTools) {
if (!this->Managed) {
- this->WriteMSToolConfigurationValues(*i);
+ this->WriteMSToolConfigurationValues(c);
} else {
- this->WriteMSToolConfigurationValuesManaged(*i);
+ this->WriteMSToolConfigurationValuesManaged(c);
}
} else if (this->NsightTegra) {
- this->WriteNsightTegraConfigurationValues(*i);
+ this->WriteNsightTegraConfigurationValues(c);
}
this->WriteString("</PropertyGroup>\n", 1);
@@ -994,11 +999,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues()
void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
- const char* mfcFlag =
- this->GeneratorTarget->Target->GetMakefile()->GetDefinition(
- "CMAKE_MFC_FLAG");
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
+ const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
if (mfcFlag) {
std::string const mfcFlagValue = mfcFlag;
@@ -1010,9 +1012,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
useOfMfcValue = "Dynamic";
}
}
- std::string mfcLine = "<UseOfMfc>";
- mfcLine += useOfMfcValue + "</UseOfMfc>\n";
- this->WriteString(mfcLine.c_str(), 2);
+ this->WriteElem("UseOfMfc", useOfMfcValue, 2);
}
if ((this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY &&
@@ -1021,57 +1021,46 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues(
this->GlobalGenerator->TargetsWindowsPhone() ||
this->GlobalGenerator->TargetsWindowsStore() ||
this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
- this->WriteString("<CharacterSet>Unicode</CharacterSet>\n", 2);
+ this->WriteElem("CharacterSet", "Unicode", 2);
} else if (this->GeneratorTarget->GetType() <=
cmStateEnums::MODULE_LIBRARY &&
this->ClOptions[config]->UsingSBCS()) {
- this->WriteString("<CharacterSet>NotSet</CharacterSet>\n", 2);
+ this->WriteElem("CharacterSet", "NotSet", 2);
} else {
- this->WriteString("<CharacterSet>MultiByte</CharacterSet>\n", 2);
+ this->WriteElem("CharacterSet", "MultiByte", 2);
}
if (const char* toolset = gg->GetPlatformToolset()) {
- std::string pts = "<PlatformToolset>";
- pts += toolset;
- pts += "</PlatformToolset>\n";
- this->WriteString(pts.c_str(), 2);
+ this->WriteElem("PlatformToolset", toolset, 2);
}
if (this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_COMPONENT") ||
this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) {
- this->WriteString("<WindowsAppContainer>true"
- "</WindowsAppContainer>\n",
- 2);
+ this->WriteElem("WindowsAppContainer", "true", 2);
}
}
void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
Options& o = *(this->ClOptions[config]);
if (o.IsDebug()) {
- this->WriteString("<DebugSymbols>true</DebugSymbols>\n", 2);
- this->WriteString("<DefineDebug>true</DefineDebug>\n", 2);
+ this->WriteElem("DebugSymbols", "true", 2);
+ this->WriteElem("DefineDebug", "true", 2);
}
std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
ConvertToWindowsSlash(outDir);
- this->WriteString("<OutputPath>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(outDir) << "</OutputPath>\n";
+ this->WriteElemEscapeXML("OutputPath", outDir, 2);
if (o.HasFlag("Platform")) {
- this->WriteString("<PlatformTarget>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(o.GetFlag("Platform"))
- << "</PlatformTarget>\n";
+ this->WriteElemEscapeXML("PlatformTarget", o.GetFlag("Platform"), 2);
o.RemoveFlag("Platform");
}
if (const char* toolset = gg->GetPlatformToolset()) {
- this->WriteString("<PlatformToolset>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(toolset)
- << "</PlatformToolset>\n";
+ this->WriteElemEscapeXML("PlatformToolset", toolset, 2);
}
std::string postfixName = cmSystemTools::UpperCase(config);
@@ -1081,12 +1070,10 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) {
assemblyName += postfix;
}
- this->WriteString("<AssemblyName>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(assemblyName)
- << "</AssemblyName>\n";
+ this->WriteElemEscapeXML("AssemblyName", assemblyName, 2);
if (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType()) {
- this->WriteString("<StartAction>Program</StartAction>\n", 2);
+ this->WriteElem("StartAction", "Program", 2);
this->WriteString("<StartProgram>", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(outDir)
<< cmVS10EscapeXML(assemblyName)
@@ -1100,8 +1087,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
std::string const&)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
const char* toolset = gg->GetPlatformToolset();
std::string ntv = "<NdkToolchainVersion>";
ntv += toolset ? toolset : "Default";
@@ -1109,27 +1095,20 @@ void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues(
this->WriteString(ntv.c_str(), 2);
if (const char* minApi =
this->GeneratorTarget->GetProperty("ANDROID_API_MIN")) {
- this->WriteString("<AndroidMinAPI>", 2);
- (*this->BuildFileStream) << "android-" << cmVS10EscapeXML(minApi)
- << "</AndroidMinAPI>\n";
+ this->WriteElem("AndroidMinAPI", "android-" + cmVS10EscapeXML(minApi), 2);
}
if (const char* api = this->GeneratorTarget->GetProperty("ANDROID_API")) {
- this->WriteString("<AndroidTargetAPI>", 2);
- (*this->BuildFileStream) << "android-" << cmVS10EscapeXML(api)
- << "</AndroidTargetAPI>\n";
+ this->WriteElem("AndroidTargetAPI", "android-" + cmVS10EscapeXML(api), 2);
}
if (const char* cpuArch =
this->GeneratorTarget->GetProperty("ANDROID_ARCH")) {
- this->WriteString("<AndroidArch>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(cpuArch) << "</AndroidArch>\n";
+ this->WriteElemEscapeXML("AndroidArch", cpuArch, 2);
}
if (const char* stlType =
this->GeneratorTarget->GetProperty("ANDROID_STL_TYPE")) {
- this->WriteString("<AndroidStlType>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(stlType)
- << "</AndroidStlType>\n";
+ this->WriteElemEscapeXML("AndroidStlType", stlType, 2);
}
}
@@ -1139,10 +1118,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommands()
this->CSharpCustomCommandNames.clear();
std::vector<cmSourceFile const*> customCommands;
this->GeneratorTarget->GetCustomCommands(customCommands, "");
- for (std::vector<cmSourceFile const*>::const_iterator si =
- customCommands.begin();
- si != customCommands.end(); ++si) {
- this->WriteCustomCommand(*si);
+ for (cmSourceFile const* si : customCommands) {
+ this->WriteCustomCommand(si);
}
// Add CMakeLists.txt file with rule to re-run CMake for user convenience.
@@ -1161,9 +1138,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommand(
if (this->SourcesVisited.insert(sf).second) {
if (std::vector<cmSourceFile*> const* depends =
this->GeneratorTarget->GetSourceDepends(sf)) {
- for (std::vector<cmSourceFile*>::const_iterator di = depends->begin();
- di != depends->end(); ++di) {
- this->WriteCustomCommand(*di);
+ for (cmSourceFile const* di : *depends) {
+ this->WriteCustomCommand(di);
}
}
if (cmCustomCommand const* command = sf->GetCustomCommand()) {
@@ -1186,10 +1162,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
// VS 10 will always rebuild a custom command attached to a .rule
// file that doesn't exist so create the file explicitly.
if (source->GetPropertyAsBool("__CMAKE_RULE")) {
- if (!cmSystemTools::FileExists(sourcePath.c_str())) {
+ if (!cmSystemTools::FileExists(sourcePath)) {
// Make sure the path exists for the file
std::string path = cmSystemTools::GetFilenamePath(sourcePath);
- cmSystemTools::MakeDirectory(path.c_str());
+ cmSystemTools::MakeDirectory(path);
cmsys::ofstream fout(sourcePath.c_str());
if (fout) {
fout << "# generated from CMake\n";
@@ -1209,34 +1185,33 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
}
cmLocalVisualStudio7Generator* lg = this->LocalGenerator;
+ Elem e2(*this->BuildFileStream, 2);
if (this->ProjectType != csproj) {
- this->WriteSource("CustomBuild", source, ">\n");
+ this->WriteSource("CustomBuild", source);
+ e2.SetHasElements();
} else {
this->WriteString("<ItemGroup>\n", 1);
std::string link;
this->GetCSharpSourceLink(source, link);
- this->WriteSource("None", source, ">\n");
+ this->WriteSource("None", source);
+ e2.SetHasElements();
if (!link.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << link << "</Link>\n";
+ this->WriteElem("Link", link, 3);
}
- this->WriteString("</None>\n", 2);
+ e2.WriteEndTag("None");
this->WriteString("</ItemGroup>\n", 1);
}
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- cmCustomCommandGenerator ccg(command, *i, this->LocalGenerator);
+ for (std::string const& c : this->Configurations) {
+ cmCustomCommandGenerator ccg(command, c, lg);
std::string comment = lg->ConstructComment(ccg);
comment = cmVS10EscapeComment(comment);
std::string script = cmVS10EscapeXML(lg->ConstructScript(ccg));
// input files for custom command
std::stringstream inputs;
inputs << cmVS10EscapeXML(source->GetFullPath());
- for (std::vector<std::string>::const_iterator d = ccg.GetDepends().begin();
- d != ccg.GetDepends().end(); ++d) {
+ for (std::string const& d : ccg.GetDepends()) {
std::string dep;
- if (this->LocalGenerator->GetRealDependency(*d, *i, dep)) {
+ if (lg->GetRealDependency(d, c, dep)) {
ConvertToWindowsSlash(dep);
inputs << ";" << cmVS10EscapeXML(dep);
}
@@ -1244,15 +1219,14 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
// output files for custom command
std::stringstream outputs;
const char* sep = "";
- for (std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin();
- o != ccg.GetOutputs().end(); ++o) {
- std::string out = *o;
+ for (std::string const& o : ccg.GetOutputs()) {
+ std::string out = o;
ConvertToWindowsSlash(out);
outputs << sep << cmVS10EscapeXML(out);
sep = ";";
}
if (this->ProjectType == csproj) {
- std::string name = "CustomCommand_" + *i + "_" +
+ std::string name = "CustomCommand_" + c + "_" +
cmSystemTools::ComputeStringMD5(sourcePath);
std::string inputs_s = inputs.str();
std::string outputs_s = outputs.str();
@@ -1260,15 +1234,15 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
script = cmVS10EscapeQuotes(script);
inputs_s = cmVS10EscapeQuotes(inputs_s);
outputs_s = cmVS10EscapeQuotes(outputs_s);
- this->WriteCustomRuleCSharp(*i, name, script, inputs_s, outputs_s,
+ this->WriteCustomRuleCSharp(c, name, script, inputs_s, outputs_s,
comment);
} else {
- this->WriteCustomRuleCpp(*i, script, inputs.str(), outputs.str(),
+ this->WriteCustomRuleCpp(c, script, inputs.str(), outputs.str(),
comment);
}
}
if (this->ProjectType != csproj) {
- this->WriteString("</CustomBuild>\n", 2);
+ e2.WriteEndTag("CustomBuild");
}
}
@@ -1321,8 +1295,8 @@ std::string cmVisualStudio10TargetGenerator::ConvertPath(
{
return forceRelative
? cmSystemTools::RelativePath(
- this->LocalGenerator->GetCurrentBinaryDirectory(), path.c_str())
- : path.c_str();
+ this->LocalGenerator->GetCurrentBinaryDirectory(), path)
+ : path;
}
static void ConvertToWindowsSlash(std::string& s)
@@ -1334,6 +1308,7 @@ static void ConvertToWindowsSlash(std::string& s)
pos++;
}
}
+
void cmVisualStudio10TargetGenerator::WriteGroups()
{
if (this->ProjectType == csproj) {
@@ -1347,10 +1322,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->GeneratorTarget->GetAllConfigSources();
std::set<cmSourceGroup*> groupsUsed;
- for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
- sources.begin();
- si != sources.end(); ++si) {
- std::string const& source = si->Source->GetFullPath();
+ for (cmGeneratorTarget::AllConfigSource const& si : sources) {
+ std::string const& source = si.Source->GetFullPath();
cmSourceGroup* sourceGroup =
this->Makefile->FindSourceGroup(source, sourceGroups);
groupsUsed.insert(sourceGroup);
@@ -1382,9 +1355,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
"xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n");
this->WriteString(project_defaults.c_str(), 0);
- for (ToolSourceMap::const_iterator ti = this->Tools.begin();
- ti != this->Tools.end(); ++ti) {
- this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
+ for (auto const& ti : this->Tools) {
+ this->WriteGroupSources(ti.first.c_str(), ti.second, sourceGroups);
}
// Added files are images and the manifest.
@@ -1396,23 +1368,23 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
if (fileName == "wmappmanifest.xml") {
this->WriteString("<XML Include=\"", 2);
(*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteElem("Filter", "Resource Files", 3);
this->WriteString("</XML>\n", 2);
} else if (cmSystemTools::GetFilenameExtension(fileName) ==
".appxmanifest") {
this->WriteString("<AppxManifest Include=\"", 2);
(*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteElem("Filter", "Resource Files", 3);
this->WriteString("</AppxManifest>\n", 2);
} else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx") {
this->WriteString("<None Include=\"", 2);
(*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteElem("Filter", "Resource Files", 3);
this->WriteString("</None>\n", 2);
} else {
this->WriteString("<Image Include=\"", 2);
(*this->BuildFileStream) << oi << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteElem("Filter", "Resource Files", 3);
this->WriteString("</Image>\n", 2);
}
}
@@ -1428,7 +1400,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->WriteString("<EmbeddedResource Include=\"", 2);
ConvertToWindowsSlash(obj);
(*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\">\n";
- this->WriteString("<Filter>Resource Files</Filter>\n", 3);
+ this->WriteElem("Filter", "Resource Files", 3);
this->WriteString("</EmbeddedResource>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
@@ -1447,10 +1419,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
(*this->BuildFileStream) << name << "\">\n";
std::string guidName = "SG_Filter_";
guidName += name;
- this->WriteString("<UniqueIdentifier>", 3);
std::string guid = this->GlobalGenerator->GetGUID(guidName);
- (*this->BuildFileStream) << "{" << guid << "}"
- << "</UniqueIdentifier>\n";
+ this->WriteElem("UniqueIdentifier", "{" + guid + "}", 3);
this->WriteString("</Filter>\n", 2);
}
}
@@ -1458,10 +1428,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
if (!resxObjs.empty() || !this->AddedFiles.empty()) {
this->WriteString("<Filter Include=\"Resource Files\">\n", 2);
std::string guidName = "SG_Filter_Resource Files";
- this->WriteString("<UniqueIdentifier>", 3);
std::string guid = this->GlobalGenerator->GetGUID(guidName);
- (*this->BuildFileStream) << "{" << guid << "}"
- << "</UniqueIdentifier>\n";
+ this->WriteElem("UniqueIdentifier", "{" + guid + "}", 3);
this->WriteString("<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;", 3);
(*this->BuildFileStream) << "gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;";
(*this->BuildFileStream) << "mfcribbon-ms</Extensions>\n";
@@ -1516,7 +1484,7 @@ void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
}
void cmVisualStudio10TargetGenerator::WriteGroupSources(
- const char* name, ToolSources const& sources,
+ std::string const& name, ToolSources const& sources,
std::vector<cmSourceGroup>& sourceGroups)
{
this->WriteString("<ItemGroup>\n", 1);
@@ -1532,8 +1500,7 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources(
(*this->BuildFileStream) << name << " Include=\"" << cmVS10EscapeXML(path);
if (!filter.empty()) {
(*this->BuildFileStream) << "\">\n";
- this->WriteString("<Filter>", 3);
- (*this->BuildFileStream) << filter << "</Filter>\n";
+ this->WriteElem("Filter", filter, 3);
this->WriteString("</", 2);
(*this->BuildFileStream) << name << ">\n";
} else {
@@ -1546,25 +1513,23 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources(
void cmVisualStudio10TargetGenerator::WriteHeaderSource(cmSourceFile const* sf)
{
std::string const& fileName = sf->GetFullPath();
+ Elem e2(*this->BuildFileStream, 2);
+ this->WriteSource("ClInclude", sf);
if (this->IsResxHeader(fileName)) {
- this->WriteSource("ClInclude", sf, ">\n");
- this->WriteString("<FileType>CppForm</FileType>\n", 3);
- this->WriteString("</ClInclude>\n", 2);
+ e2.SetHasElements();
+ this->WriteElem("FileType", "CppForm", 3);
} else if (this->IsXamlHeader(fileName)) {
- this->WriteSource("ClInclude", sf, ">\n");
- this->WriteString("<DependentUpon>", 3);
std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
- (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n";
- this->WriteString("</ClInclude>\n", 2);
- } else {
- this->WriteSource("ClInclude", sf);
+ e2.SetHasElements();
+ this->WriteElem("DependentUpon", xamlFileName, 3);
}
+ e2.WriteEndTag("ClInclude");
}
void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
{
bool toolHasSettings = false;
- std::string tool = "None";
+ const char* tool = "None";
std::string shaderType;
std::string shaderEntryPoint;
std::string shaderModel;
@@ -1714,8 +1679,10 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
}
}
+ Elem e2(*this->BuildFileStream, 2);
+ this->WriteSource(tool, sf);
if (toolHasSettings) {
- this->WriteSource(tool, sf, ">\n");
+ e2.SetHasElements();
if (!deployContent.empty()) {
cmGeneratorExpression ge;
@@ -1749,19 +1716,13 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
}
}
if (!shaderType.empty()) {
- this->WriteString("<ShaderType>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderType)
- << "</ShaderType>\n";
+ this->WriteElemEscapeXML("ShaderType", shaderType, 3);
}
if (!shaderEntryPoint.empty()) {
- this->WriteString("<EntryPointName>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderEntryPoint)
- << "</EntryPointName>\n";
+ this->WriteElemEscapeXML("EntryPointName", shaderEntryPoint, 3);
}
if (!shaderModel.empty()) {
- this->WriteString("<ShaderModel>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderModel)
- << "</ShaderModel>\n";
+ this->WriteElemEscapeXML("ShaderModel", shaderModel, 3);
}
if (!outputHeaderFile.empty()) {
for (size_t i = 0; i != this->Configurations.size(); ++i) {
@@ -1786,60 +1747,42 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
}
}
if (!shaderEnableDebug.empty()) {
- this->WriteString("<EnableDebuggingInformation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderEnableDebug)
- << "</EnableDebuggingInformation>\n";
+ this->WriteElemEscapeXML("EnableDebuggingInformation", shaderEnableDebug,
+ 3);
}
if (!shaderDisableOptimizations.empty()) {
- this->WriteString("<DisableOptimizations>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderDisableOptimizations)
- << "</DisableOptimizations>\n";
+ this->WriteElemEscapeXML("DisableOptimizations",
+ shaderDisableOptimizations, 3);
}
if (!shaderAdditionalFlags.empty()) {
- this->WriteString("<AdditionalOptions>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags)
- << "</AdditionalOptions>\n";
+ this->WriteElemEscapeXML("AdditionalOptions", shaderAdditionalFlags, 3);
}
if (!settingsGenerator.empty()) {
- this->WriteString("<Generator>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(settingsGenerator)
- << "</Generator>\n";
+ this->WriteElemEscapeXML("Generator", settingsGenerator, 3);
}
if (!settingsLastGenOutput.empty()) {
- this->WriteString("<LastGenOutput>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(settingsLastGenOutput)
- << "</LastGenOutput>\n";
+ this->WriteElemEscapeXML("LastGenOutput", settingsLastGenOutput, 3);
}
if (!sourceLink.empty()) {
- this->WriteString("<Link>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(sourceLink) << "</Link>\n";
+ this->WriteElemEscapeXML("Link", sourceLink, 3);
}
if (!subType.empty()) {
- this->WriteString("<SubType>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(subType) << "</SubType>\n";
+ this->WriteElemEscapeXML("SubType", subType, 3);
}
if (!copyToOutDir.empty()) {
- this->WriteString("<CopyToOutputDirectory>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(copyToOutDir)
- << "</CopyToOutputDirectory>\n";
+ this->WriteElemEscapeXML("CopyToOutputDirectory", copyToOutDir, 3);
}
if (!includeInVsix.empty()) {
- this->WriteString("<IncludeInVSIX>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(includeInVsix)
- << "</IncludeInVSIX>\n";
+ this->WriteElemEscapeXML("IncludeInVSIX", includeInVsix, 3);
}
// write source file specific tags
this->WriteCSharpSourceProperties(sourceFileTags);
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- this->WriteSource(tool, sf);
}
+ e2.WriteEndTag(tool);
}
void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
- cmSourceFile const* sf,
- const char* end)
+ cmSourceFile const* sf)
{
// Visual Studio tools append relative paths to the current dir, as in:
//
@@ -1853,7 +1796,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative);
if (this->LocalGenerator->GetVersion() ==
cmGlobalVisualStudioGenerator::VS10 &&
- cmSystemTools::FileIsFullPath(sourceFile.c_str())) {
+ cmSystemTools::FileIsFullPath(sourceFile)) {
// Normal path conversion resulted in a full path. VS 10 (but not 11)
// refuses to show the property page in the IDE for a source file with a
// full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a
@@ -1876,8 +1819,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
ConvertToWindowsSlash(sourceFile);
this->WriteString("<", 2);
(*this->BuildFileStream) << tool << " Include=\""
- << cmVS10EscapeXML(sourceFile) << "\""
- << (end ? end : " />\n");
+ << cmVS10EscapeXML(sourceFile) << "\"";
ToolSource toolSource = { sf, forceRelative };
this->Tools[tool].push_back(toolSource);
@@ -1899,7 +1841,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
this->GeneratorTarget->GetAllConfigSources();
for (cmGeneratorTarget::AllConfigSource const& si : sources) {
- std::string tool;
+ const char* tool = nullptr;
switch (si.Kind) {
case cmGeneratorTarget::SourceKindAppManifest:
tool = "AppxManifest";
@@ -1968,7 +1910,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
break;
}
- if (!tool.empty()) {
+ if (tool) {
// Compute set of configurations to exclude, if any.
std::vector<size_t> const& include_configs = si.Configs;
std::vector<size_t> exclude_configs;
@@ -1976,31 +1918,15 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
include_configs.begin(), include_configs.end(),
std::back_inserter(exclude_configs));
+ Elem e2(*this->BuildFileStream, 2);
+ this->WriteSource(tool, si.Source);
if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) {
- // FIXME: refactor generation to avoid tracking XML syntax state.
- this->WriteSource(tool, si.Source, "");
- bool have_nested = this->OutputSourceSpecificFlags(si.Source);
- if (!exclude_configs.empty()) {
- if (!have_nested) {
- (*this->BuildFileStream) << ">\n";
- }
- this->WriteExcludeFromBuild(exclude_configs);
- have_nested = true;
- }
- if (have_nested) {
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- (*this->BuildFileStream) << " />\n";
- }
- } else if (!exclude_configs.empty()) {
- this->WriteSource(tool, si.Source, ">\n");
- this->WriteExcludeFromBuild(exclude_configs);
- this->WriteString("</", 2);
- (*this->BuildFileStream) << tool << ">\n";
- } else {
- this->WriteSource(tool, si.Source);
+ this->OutputSourceSpecificFlags(e2, si.Source);
}
+ if (!exclude_configs.empty()) {
+ this->WriteExcludeFromBuild(e2, exclude_configs);
+ }
+ e2.WriteEndTag(tool);
}
}
@@ -2011,8 +1937,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
this->WriteString("</ItemGroup>\n", 1);
}
-bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
- cmSourceFile const* source)
+void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
+ Elem& e2, cmSourceFile const* source)
{
cmSourceFile const& sf = *source;
@@ -2072,22 +1998,14 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
}
bool noWinRT = this->TargetCompileAsWinRT && lang == "C";
- bool hasFlags = false;
// for the first time we need a new line if there is something
// produced here.
- const char* firstString = ">\n";
if (!objectName.empty()) {
- (*this->BuildFileStream) << firstString;
- firstString = "";
- hasFlags = true;
+ e2.SetHasElements();
if (lang == "CUDA") {
- this->WriteString("<CompileOut>", 3);
- (*this->BuildFileStream) << "$(IntDir)/" << objectName
- << "</CompileOut>\n";
+ this->WriteElem("CompileOut", "$(IntDir)/" + objectName, 3);
} else {
- this->WriteString("<ObjectFileName>", 3);
- (*this->BuildFileStream) << "$(IntDir)/" << objectName
- << "</ObjectFileName>\n";
+ this->WriteElem("ObjectFileName", "$(IntDir)/" + objectName, 3);
}
}
for (std::string const& config : this->Configurations) {
@@ -2107,11 +2025,8 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
// use them
if (!flags.empty() || !options.empty() || !configDefines.empty() ||
!includes.empty() || compileAs || noWinRT) {
- (*this->BuildFileStream) << firstString;
- firstString = ""; // only do firstString once
- hasFlags = true;
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ e2.SetHasElements();
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
cmIDEFlagTable const* flagtable = nullptr;
const std::string& srclang = source->GetLanguage();
if (srclang == "C" || srclang == "CXX") {
@@ -2163,7 +2078,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
clOptions.AddDefines(
genexInterpreter.Evaluate(configDefines, "COMPILE_DEFINITIONS"));
} else {
- clOptions.AddDefines(configDefines.c_str());
+ clOptions.AddDefines(configDefines);
}
std::vector<std::string> includeList;
if (configDependentIncludes) {
@@ -2175,7 +2090,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
*source);
}
clOptions.AddIncludes(includeList);
- clOptions.SetConfiguration(config.c_str());
+ clOptions.SetConfiguration(config);
clOptions.PrependInheritedString("AdditionalOptions");
clOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
" ", "\n", lang);
@@ -2185,13 +2100,10 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
}
if (this->IsXamlSource(source->GetFullPath())) {
- (*this->BuildFileStream) << firstString;
- firstString = ""; // only do firstString once
- hasFlags = true;
- this->WriteString("<DependentUpon>", 3);
+ e2.SetHasElements();
const std::string& fileName = source->GetFullPath();
std::string xamlFileName = fileName.substr(0, fileName.find_last_of("."));
- (*this->BuildFileStream) << xamlFileName << "</DependentUpon>\n";
+ this->WriteElem("DependentUpon", xamlFileName, 3);
}
if (this->ProjectType == csproj) {
std::string f = source->GetFullPath();
@@ -2206,19 +2118,16 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
this->GetCSharpSourceProperties(&sf, sourceFileTags);
// write source file specific tags
if (!sourceFileTags.empty()) {
- hasFlags = true;
- (*this->BuildFileStream) << firstString;
- firstString = "";
+ e2.SetHasElements();
this->WriteCSharpSourceProperties(sourceFileTags);
}
}
-
- return hasFlags;
}
void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild(
- std::vector<size_t> const& exclude_configs)
+ Elem& e2, std::vector<size_t> const& exclude_configs)
{
+ e2.SetHasElements();
for (size_t ci : exclude_configs) {
this->WriteString("", 3);
(*this->BuildFileStream)
@@ -2239,9 +2148,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
}
this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<_ProjectFileVersion>10.0.20506.1"
- "</_ProjectFileVersion>\n",
- 2);
+ this->WriteElem("_ProjectFileVersion", "10.0.20506.1", 2);
for (std::string const& config : this->Configurations) {
if (ttype >= cmStateEnums::UTILITY) {
this->WritePlatformConfigTag("IntDir", config, 2);
@@ -2282,6 +2189,13 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
<< "</LocalDebuggerWorkingDirectory>\n";
}
+ if (const char* debuggerCommand =
+ this->GeneratorTarget->GetProperty("VS_DEBUGGER_COMMAND")) {
+ this->WritePlatformConfigTag("LocalDebuggerCommand", config, 2);
+ *this->BuildFileStream << cmVS10EscapeXML(debuggerCommand)
+ << "</LocalDebuggerCommand>\n";
+ }
+
std::string name =
cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
this->WritePlatformConfigTag("TargetName", config, 2);
@@ -2374,8 +2288,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
// copied from cmLocalVisualStudio7Generator.cxx 805
// TODO: Integrate code below with cmLocalVisualStudio7Generator.
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
std::unique_ptr<Options> pOptions;
switch (this->ProjectType) {
case vcxproj:
@@ -2422,15 +2335,11 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
std::string baseFlagVar = "CMAKE_";
baseFlagVar += langForClCompile;
baseFlagVar += "_FLAGS";
- flags =
- this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- baseFlagVar);
+ flags = this->Makefile->GetRequiredDefinition(baseFlagVar);
std::string flagVar =
baseFlagVar + std::string("_") + cmSystemTools::UpperCase(configName);
flags += " ";
- flags +=
- this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- flagVar);
+ flags += this->Makefile->GetRequiredDefinition(flagVar);
this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
langForClCompile, configName);
}
@@ -2446,8 +2355,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName);
// Get preprocessor definitions for this directory.
- std::string defineFlags =
- this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+ std::string defineFlags = this->Makefile->GetDefineFlags();
if (this->MSTools) {
if (this->ProjectType == vcxproj) {
clOptions.FixExceptionHandlingDefault();
@@ -2552,9 +2460,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
if (this->NsightTegra) {
if (const char* processMax =
this->GeneratorTarget->GetProperty("ANDROID_PROCESS_MAX")) {
- this->WriteString("<ProcessMax>", 3);
- *this->BuildFileStream << cmVS10EscapeXML(processMax)
- << "</ProcessMax>\n";
+ this->WriteElemEscapeXML("ProcessMax", processMax, 3);
}
}
@@ -2562,12 +2468,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
cmsys::RegularExpression clangToolset("v[0-9]+_clang_.*");
const char* toolset = this->GlobalGenerator->GetPlatformToolset();
if (toolset && clangToolset.find(toolset)) {
- this->WriteString("<ObjectFileName>"
- "$(IntDir)%(filename).obj"
- "</ObjectFileName>\n",
- 3);
+ this->WriteElem("ObjectFileName", "$(IntDir)%(filename).obj", 3);
} else {
- this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
+ this->WriteElem("ObjectFileName", "$(IntDir)", 3);
}
// If not in debug mode, write the DebugInformationFormat field
@@ -2583,9 +2486,7 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
if (!pdb.empty()) {
ConvertToWindowsSlash(pdb);
- this->WriteString("<ProgramDataBaseFileName>", 3);
- *this->BuildFileStream << cmVS10EscapeXML(pdb)
- << "</ProgramDataBaseFileName>\n";
+ this->WriteElemEscapeXML("ProgramDataBaseFileName", pdb, 3);
}
}
@@ -2605,8 +2506,7 @@ bool cmVisualStudio10TargetGenerator::ComputeRcOptions()
bool cmVisualStudio10TargetGenerator::ComputeRcOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::ResourceCompiler, gg->GetRcFlagTable());
Options& rcOptions = *pOptions;
@@ -2666,8 +2566,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
Options& cudaOptions = *pOptions;
@@ -2683,8 +2582,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
configName);
// Get preprocessor definitions for this directory.
- std::string defineFlags =
- this->GeneratorTarget->Target->GetMakefile()->GetDefineFlags();
+ std::string defineFlags = this->Makefile->GetDefineFlags();
cudaOptions.Parse(flags.c_str());
cudaOptions.Parse(defineFlags.c_str());
@@ -2804,8 +2702,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::CudaCompiler, gg->GetCudaFlagTable());
Options& cudaLinkOptions = *pOptions;
@@ -2873,8 +2770,7 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::MasmCompiler, gg->GetMasmFlagTable());
Options& masmOptions = *pOptions;
@@ -2933,8 +2829,7 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
std::string const& configName)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions = cm::make_unique<Options>(
this->LocalGenerator, Options::NasmCompiler, gg->GetNasmFlagTable());
Options& nasmOptions = *pOptions;
@@ -2994,8 +2889,7 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions(
libflags, cmSystemTools::UpperCase(config), this->GeneratorTarget);
if (!libflags.empty()) {
this->WriteString("<Lib>\n", 2);
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
cmVisualStudioGeneratorOptions libOptions(
this->LocalGenerator, cmVisualStudioGeneratorOptions::Linker,
gg->GetLibFlagTable(), 0, this);
@@ -3011,9 +2905,7 @@ void cmVisualStudio10TargetGenerator::WriteLibOptions(
if (this->GlobalGenerator->TargetsWindowsPhone() ||
this->GlobalGenerator->TargetsWindowsStore()) {
this->WriteString("<Link>\n", 2);
- this->WriteString("<GenerateWindowsMetadata>false"
- "</GenerateWindowsMetadata>\n",
- 3);
+ this->WriteElem("GenerateWindowsMetadata", "false", 3);
this->WriteString("</Link>\n", 2);
}
}
@@ -3064,32 +2956,28 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
{
std::string antBuildPath = rootDir;
this->WriteString("<AntBuild>\n", 2);
- this->WriteString("<AntBuildPath>", 3);
ConvertToWindowsSlash(antBuildPath);
- (*this->BuildFileStream) << cmVS10EscapeXML(antBuildPath)
- << "</AntBuildPath>\n";
+ this->WriteElemEscapeXML("AntBuildPath", antBuildPath, 3);
}
if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_SKIP_ANT_STEP")) {
- this->WriteString("<SkipAntStep>true</SkipAntStep>\n", 3);
+ this->WriteElem("SkipAntStep", "true", 3);
}
if (this->GeneratorTarget->GetPropertyAsBool("ANDROID_PROGUARD")) {
- this->WriteString("<EnableProGuard>true</EnableProGuard>\n", 3);
+ this->WriteElem("EnableProGuard", "true", 3);
}
if (const char* proGuardConfigLocation =
this->GeneratorTarget->GetProperty("ANDROID_PROGUARD_CONFIG_PATH")) {
- this->WriteString("<ProGuardConfigLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(proGuardConfigLocation)
- << "</ProGuardConfigLocation>\n";
+ this->WriteElemEscapeXML("ProGuardConfigLocation", proGuardConfigLocation,
+ 3);
}
if (const char* securePropertiesLocation =
this->GeneratorTarget->GetProperty("ANDROID_SECURE_PROPS_PATH")) {
- this->WriteString("<SecurePropertiesLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(securePropertiesLocation)
- << "</SecurePropertiesLocation>\n";
+ this->WriteElemEscapeXML("SecurePropertiesLocation",
+ securePropertiesLocation, 3);
}
if (const char* nativeLibDirectoriesExpression =
@@ -3099,9 +2987,7 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
ge.Parse(nativeLibDirectoriesExpression);
std::string nativeLibDirs =
cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<NativeLibDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(nativeLibDirs)
- << "</NativeLibDirectories>\n";
+ this->WriteElemEscapeXML("NativeLibDirectories", nativeLibDirs, 3);
}
if (const char* nativeLibDependenciesExpression =
@@ -3112,16 +2998,12 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
ge.Parse(nativeLibDependenciesExpression);
std::string nativeLibDeps =
cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<NativeLibDependencies>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(nativeLibDeps)
- << "</NativeLibDependencies>\n";
+ this->WriteElemEscapeXML("NativeLibDependencies", nativeLibDeps, 3);
}
if (const char* javaSourceDir =
this->GeneratorTarget->GetProperty("ANDROID_JAVA_SOURCE_DIR")) {
- this->WriteString("<JavaSourceDir>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(javaSourceDir)
- << "</JavaSourceDir>\n";
+ this->WriteElemEscapeXML("JavaSourceDir", javaSourceDir, 3);
}
if (const char* jarDirectoriesExpression =
@@ -3131,31 +3013,23 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
ge.Parse(jarDirectoriesExpression);
std::string jarDirectories =
cge->Evaluate(this->LocalGenerator, configName);
- this->WriteString("<JarDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(jarDirectories)
- << "</JarDirectories>\n";
+ this->WriteElemEscapeXML("JarDirectories", jarDirectories, 3);
}
if (const char* jarDeps =
this->GeneratorTarget->GetProperty("ANDROID_JAR_DEPENDENCIES")) {
- this->WriteString("<JarDependencies>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(jarDeps)
- << "</JarDependencies>\n";
+ this->WriteElemEscapeXML("JarDependencies", jarDeps, 3);
}
if (const char* assetsDirectories =
this->GeneratorTarget->GetProperty("ANDROID_ASSETS_DIRECTORIES")) {
- this->WriteString("<AssetsDirectories>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(assetsDirectories)
- << "</AssetsDirectories>\n";
+ this->WriteElemEscapeXML("AssetsDirectories", assetsDirectories, 3);
}
{
std::string manifest_xml = rootDir + "/AndroidManifest.xml";
ConvertToWindowsSlash(manifest_xml);
- this->WriteString("<AndroidManifestLocation>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(manifest_xml)
- << "</AndroidManifestLocation>\n";
+ this->WriteElemEscapeXML("AndroidManifestLocation", manifest_xml, 3);
}
if (const char* antAdditionalOptions =
@@ -3185,8 +3059,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
std::string const& config)
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
auto pOptions =
cm::make_unique<Options>(this->LocalGenerator, Options::Linker,
gg->GetLinkFlagTable(), nullptr, this);
@@ -3217,12 +3090,10 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
linkFlagVarBase += linkType;
linkFlagVarBase += "_LINKER_FLAGS";
flags += " ";
- flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- linkFlagVarBase);
+ flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase);
std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
flags += " ";
- flags += this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
- linkFlagVar);
+ flags += this->Makefile->GetRequiredDefinition(linkFlagVar);
const char* targetLinkFlags =
this->GeneratorTarget->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
@@ -3376,7 +3247,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
this->GeneratorTarget->GetModuleDefinitionInfo(config);
if (mdi && !mdi->DefFile.empty()) {
- linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile.c_str());
+ linkOptions.AddFlag("ModuleDefinitionFile", mdi->DefFile);
}
linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries",
"%(IgnoreSpecificDefaultLibraries)");
@@ -3459,8 +3330,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(
if (!this->GlobalGenerator->NeedLinkLibraryDependencies(
this->GeneratorTarget)) {
this->WriteString("<ProjectReference>\n", 2);
- this->WriteString(
- "<LinkLibraryDependencies>false</LinkLibraryDependencies>\n", 3);
+ this->WriteElem("LinkLibraryDependencies", "false", 3);
this->WriteString("</ProjectReference>\n", 2);
}
}
@@ -3474,6 +3344,17 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
std::string currentBinDir =
this->LocalGenerator->GetCurrentBinaryDirectory();
for (cmComputeLinkInformation::Item const& l : libs) {
+ // Do not allow C# targets to be added to the LIB listing. LIB files are
+ // used for linking C++ dependencies. C# libraries do not have lib files.
+ // Instead, they compile down to C# reference libraries (DLL files). The
+ // `<ProjectReference>` elements added to the vcxproj are enough for the
+ // IDE to deduce the DLL file required by other C# projects that need its
+ // reference library.
+ if (l.Target &&
+ cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(l.Target)) {
+ continue;
+ }
+
if (l.IsPath) {
std::string path =
this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value);
@@ -3543,15 +3424,11 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions(
this->WriteString("%(AdditionalIncludeDirectories)"
"</AdditionalIncludeDirectories>\n",
0);
- this->WriteString("<OutputDirectory>$(ProjectDir)/$(IntDir)"
- "</OutputDirectory>\n",
- 3);
- this->WriteString("<HeaderFileName>%(Filename).h</HeaderFileName>\n", 3);
- this->WriteString("<TypeLibraryName>%(Filename).tlb</TypeLibraryName>\n", 3);
- this->WriteString("<InterfaceIdentifierFileName>"
- "%(Filename)_i.c</InterfaceIdentifierFileName>\n",
- 3);
- this->WriteString("<ProxyFileName>%(Filename)_p.c</ProxyFileName>\n", 3);
+ this->WriteElem("OutputDirectory", "$(ProjectDir)/$(IntDir)", 3);
+ this->WriteElem("HeaderFileName", "%(Filename).h", 3);
+ this->WriteElem("TypeLibraryName", "%(Filename).tlb", 3);
+ this->WriteElem("InterfaceIdentifierFileName", "%(Filename)_i.c", 3);
+ this->WriteElem("ProxyFileName", "%(Filename)_p.c", 3);
this->WriteString("</Midl>\n", 2);
}
@@ -3643,8 +3520,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
}
comment = cmVS10EscapeComment(comment);
if (this->ProjectType != csproj) {
- this->WriteString("<Message>", 3);
- (*this->BuildFileStream) << cmVS10EscapeXML(comment) << "</Message>\n";
+ this->WriteElemEscapeXML("Message", comment, 3);
this->WriteString("<Command>", 3);
} else {
std::string strippedComment = comment;
@@ -3679,8 +3555,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
}
// skip fortran targets as they can not be processed by MSBuild
// the only reference will be in the .sln file
- if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetIsFortranOnly(dt)) {
+ if (this->GlobalGenerator->TargetIsFortranOnly(dt)) {
continue;
}
this->WriteString("<ProjectReference Include=\"", 2);
@@ -3698,18 +3573,13 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
}
ConvertToWindowsSlash(path);
(*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n";
- this->WriteString("<Project>", 3);
- (*this->BuildFileStream) << "{" << this->GlobalGenerator->GetGUID(name)
- << "}";
- (*this->BuildFileStream) << "</Project>\n";
- this->WriteString("<Name>", 3);
- (*this->BuildFileStream) << name << "</Name>\n";
+ this->WriteElem("Project",
+ "{" + this->GlobalGenerator->GetGUID(name) + "}", 3);
+ this->WriteElem("Name", name, 3);
this->WriteDotNetReferenceCustomTags(name);
if (csproj == this->ProjectType) {
- if (!static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetCanBeReferenced(dt)) {
- this->WriteString(
- "<ReferenceOutputAssembly>false</ReferenceOutputAssembly>\n", 3);
+ if (!this->GlobalGenerator->TargetCanBeReferenced(dt)) {
+ this->WriteElem("ReferenceOutputAssembly", "false", 3);
}
}
this->WriteString("</ProjectReference>\n", 2);
@@ -3839,14 +3709,12 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
ConvertToWindowsSlash(artifactDir);
this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<AppxPackageArtifactsDir>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(artifactDir)
- << "\\</AppxPackageArtifactsDir>\n";
- this->WriteString("<ProjectPriFullPath>", 2);
+ this->WriteElemEscapeXML("AppxPackageArtifactsDir", artifactDir + "\\",
+ 2);
std::string resourcePriFile =
this->DefaultArtifactDir + "/resources.pri";
ConvertToWindowsSlash(resourcePriFile);
- (*this->BuildFileStream) << resourcePriFile << "</ProjectPriFullPath>\n";
+ this->WriteElem("ProjectPriFullPath", resourcePriFile, 2);
// If we are missing files and we don't have a certificate and
// aren't targeting WP8.0, add a default certificate
@@ -3860,26 +3728,18 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
this->AddedFiles.push_back(pfxFile);
}
- this->WriteString("<", 2);
- (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile
- << "</PackageCertificateKeyFile>\n";
+ this->WriteElem("PackageCertificateKeyFile", pfxFile, 2);
std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
if (!thumb.empty()) {
- this->WriteString("<PackageCertificateThumbprint>", 2);
- (*this->BuildFileStream) << thumb
- << "</PackageCertificateThumbprint>\n";
+ this->WriteElem("PackageCertificateThumbprint", thumb, 2);
}
this->WriteString("</PropertyGroup>\n", 1);
} else if (!pfxFile.empty()) {
this->WriteString("<PropertyGroup>\n", 1);
- this->WriteString("<", 2);
- (*this->BuildFileStream) << "PackageCertificateKeyFile>" << pfxFile
- << "</PackageCertificateKeyFile>\n";
+ this->WriteElem("PackageCertificateKeyFile", pfxFile, 2);
std::string thumb = cmSystemTools::ComputeCertificateThumbprint(pfxFile);
if (!thumb.empty()) {
- this->WriteString("<PackageCertificateThumbprint>", 2);
- (*this->BuildFileStream) << thumb
- << "</PackageCertificateThumbprint>\n";
+ this->WriteElem("PackageCertificateThumbprint", thumb, 2);
}
this->WriteString("</PropertyGroup>\n", 1);
}
@@ -3921,52 +3781,35 @@ bool cmVisualStudio10TargetGenerator::IsXamlSource(
void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
{
- cmGlobalVisualStudio10Generator* gg =
- static_cast<cmGlobalVisualStudio10Generator*>(this->GlobalGenerator);
+ cmGlobalVisualStudio10Generator* gg = this->GlobalGenerator;
bool isAppContainer = false;
bool const isWindowsPhone = this->GlobalGenerator->TargetsWindowsPhone();
bool const isWindowsStore = this->GlobalGenerator->TargetsWindowsStore();
std::string const& v = this->GlobalGenerator->GetSystemVersion();
if (isWindowsPhone || isWindowsStore) {
- this->WriteString("<ApplicationType>", 2);
- (*this->BuildFileStream)
- << (isWindowsPhone ? "Windows Phone" : "Windows Store")
- << "</ApplicationType>\n";
- this->WriteString("<DefaultLanguage>en-US"
- "</DefaultLanguage>\n",
- 2);
+ this->WriteElem("ApplicationType",
+ (isWindowsPhone ? "Windows Phone" : "Windows Store"), 2);
+ this->WriteElem("DefaultLanguage", "en-US", 2);
if (cmHasLiteralPrefix(v, "10.0")) {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML("10.0")
- << "</ApplicationTypeRevision>\n";
+ this->WriteElemEscapeXML("ApplicationTypeRevision", "10.0", 2);
// Visual Studio 14.0 is necessary for building 10.0 apps
- this->WriteString("<MinimumVisualStudioVersion>14.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ this->WriteElem("MinimumVisualStudioVersion", "14.0", 2);
if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
isAppContainer = true;
}
} else if (v == "8.1") {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(v)
- << "</ApplicationTypeRevision>\n";
+ this->WriteElemEscapeXML("ApplicationTypeRevision", v, 2);
// Visual Studio 12.0 is necessary for building 8.1 apps
- this->WriteString("<MinimumVisualStudioVersion>12.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ this->WriteElem("MinimumVisualStudioVersion", "12.0", 2);
if (this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
isAppContainer = true;
}
} else if (v == "8.0") {
- this->WriteString("<ApplicationTypeRevision>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(v)
- << "</ApplicationTypeRevision>\n";
+ this->WriteElemEscapeXML("ApplicationTypeRevision", v, 2);
// Visual Studio 11.0 is necessary for building 8.0 apps
- this->WriteString("<MinimumVisualStudioVersion>11.0"
- "</MinimumVisualStudioVersion>\n",
- 2);
+ this->WriteElem("MinimumVisualStudioVersion", "11.0", 2);
if (isWindowsStore &&
this->GeneratorTarget->GetType() < cmStateEnums::UTILITY) {
@@ -3974,52 +3817,42 @@ void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings()
} else if (isWindowsPhone &&
this->GeneratorTarget->GetType() ==
cmStateEnums::EXECUTABLE) {
- this->WriteString("<XapOutputs>true</XapOutputs>\n", 2);
- this->WriteString("<XapFilename>", 2);
- (*this->BuildFileStream)
- << cmVS10EscapeXML(this->Name)
- << "_$(Configuration)_$(Platform).xap</XapFilename>\n";
+ this->WriteElem("XapOutputs", "true", 2);
+ this->WriteElem("XapFilename", cmVS10EscapeXML(this->Name) +
+ "_$(Configuration)_$(Platform).xap",
+ 2);
}
}
}
if (isAppContainer) {
- this->WriteString("<AppContainerApplication>true"
- "</AppContainerApplication>\n",
- 2);
+ this->WriteElem("AppContainerApplication", "true", 2);
} else if (this->Platform == "ARM64") {
- this->WriteString("<WindowsSDKDesktopARM64Support>true"
- "</WindowsSDKDesktopARM64Support>\n",
- 2);
+ this->WriteElem("WindowsSDKDesktopARM64Support", "true", 2);
} else if (this->Platform == "ARM") {
- this->WriteString("<WindowsSDKDesktopARMSupport>true"
- "</WindowsSDKDesktopARMSupport>\n",
- 2);
+ this->WriteElem("WindowsSDKDesktopARMSupport", "true", 2);
}
std::string const& targetPlatformVersion =
gg->GetWindowsTargetPlatformVersion();
if (!targetPlatformVersion.empty()) {
- this->WriteString("<WindowsTargetPlatformVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion)
- << "</WindowsTargetPlatformVersion>\n";
+ this->WriteElemEscapeXML("WindowsTargetPlatformVersion",
+ targetPlatformVersion, 2);
}
const char* targetPlatformMinVersion = this->GeneratorTarget->GetProperty(
"VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION");
if (targetPlatformMinVersion) {
- this->WriteString("<WindowsTargetPlatformMinVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformMinVersion)
- << "</WindowsTargetPlatformMinVersion>\n";
+ this->WriteElemEscapeXML("WindowsTargetPlatformMinVersion",
+ targetPlatformMinVersion, 2);
} else if (isWindowsStore && cmHasLiteralPrefix(v, "10.0")) {
// If the min version is not set, then use the TargetPlatformVersion
if (!targetPlatformVersion.empty()) {
- this->WriteString("<WindowsTargetPlatformMinVersion>", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(targetPlatformVersion)
- << "</WindowsTargetPlatformMinVersion>\n";
+ this->WriteElemEscapeXML("WindowsTargetPlatformMinVersion",
+ targetPlatformVersion, 2);
}
}
// Added IoT Startup Task support
if (this->GeneratorTarget->GetPropertyAsBool("VS_IOT_STARTUP_TASK")) {
- this->WriteString("<ContainsStartupTask>true</ContainsStartupTask>\n", 2);
+ this->WriteElem("ContainsStartupTask", "true", 2);
}
}
@@ -4150,7 +3983,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
ConvertToWindowsSlash(sourceFile);
this->WriteString("<Xml Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n";
- this->WriteString("<SubType>Designer</SubType>\n", 3);
+ this->WriteElem("SubType", "Designer", 3);
this->WriteString("</Xml>\n", 2);
this->AddedFiles.push_back(sourceFile);
@@ -4428,7 +4261,7 @@ void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
ConvertToWindowsSlash(sourceFile);
this->WriteString("<AppxManifest Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n";
- this->WriteString("<SubType>Designer</SubType>\n", 3);
+ this->WriteElem("SubType", "Designer", 3);
this->WriteString("</AppxManifest>\n", 2);
this->AddedFiles.push_back(sourceFile);
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 33d4fb7..d557255 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -53,8 +53,14 @@ private:
std::vector<std::string> Configs;
};
+ struct Elem;
+
std::string ConvertPath(std::string const& path, bool forceRelative);
void WriteString(const char* line, int indentLevel);
+ void WriteElem(const char* tag, const char* val, int indentLevel);
+ void WriteElem(const char* tag, std::string const& val, int indentLevel);
+ void WriteElemEscapeXML(const char* tag, std::string const& val,
+ int indentLevel);
void WriteProjectConfigurations();
void WriteProjectConfigurationValues();
void WriteMSToolConfigurationValues(std::string const& config);
@@ -62,9 +68,9 @@ private:
void WriteHeaderSource(cmSourceFile const* sf);
void WriteExtraSource(cmSourceFile const* sf);
void WriteNsightTegraConfigurationValues(std::string const& config);
- void WriteSource(std::string const& tool, cmSourceFile const* sf,
- const char* end = 0);
- void WriteExcludeFromBuild(std::vector<size_t> const& exclude_configs);
+ void WriteSource(std::string const& tool, cmSourceFile const* sf);
+ void WriteExcludeFromBuild(Elem&,
+ std::vector<size_t> const& exclude_configs);
void WriteAllSources();
void WriteDotNetReferences();
void WriteDotNetReference(std::string const& ref, std::string const& hint);
@@ -141,7 +147,7 @@ private:
void WriteGroups();
void WriteProjectReferences();
void WriteApplicationTypeSettings();
- bool OutputSourceSpecificFlags(cmSourceFile const* source);
+ void OutputSourceSpecificFlags(Elem&, cmSourceFile const* source);
void AddLibraries(cmComputeLinkInformation& cli,
std::vector<std::string>& libVec,
std::vector<std::string>& vsTargetVec);
@@ -153,7 +159,7 @@ private:
void WriteEvent(const char* name,
std::vector<cmCustomCommand> const& commands,
std::string const& configName);
- void WriteGroupSources(const char* name, ToolSources const& sources,
+ void WriteGroupSources(std::string const& name, ToolSources const& sources,
std::vector<cmSourceGroup>&);
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups);
@@ -190,19 +196,19 @@ private:
bool InSourceBuild;
std::vector<std::string> Configurations;
std::vector<TargetsFileAndConfigs> TargetsFileAndConfigsVec;
- cmGeneratorTarget* GeneratorTarget;
- cmMakefile* Makefile;
- std::string Platform;
- std::string GUID;
- std::string Name;
+ cmGeneratorTarget* const GeneratorTarget;
+ cmMakefile* const Makefile;
+ std::string const Platform;
+ std::string const Name;
+ std::string const GUID;
bool MSTools;
bool Managed;
bool NsightTegra;
int NsightTegraVersion[4];
bool TargetCompileAsWinRT;
- cmGlobalVisualStudio10Generator* GlobalGenerator;
+ cmGlobalVisualStudio10Generator* const GlobalGenerator;
cmGeneratedFileStream* BuildFileStream;
- cmLocalVisualStudio7Generator* LocalGenerator;
+ cmLocalVisualStudio7Generator* const LocalGenerator;
std::set<cmSourceFile const*> SourcesVisited;
std::set<std::string> CSharpCustomCommandNames;
bool IsMissingFiles;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index ccbff83..2095d23 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -152,9 +152,8 @@ bool cmVisualStudioGeneratorOptions::IsManaged() const
bool cmVisualStudioGeneratorOptions::UsingUnicode() const
{
// Look for the a _UNICODE definition.
- for (std::vector<std::string>::const_iterator di = this->Defines.begin();
- di != this->Defines.end(); ++di) {
- if (*di == "_UNICODE") {
+ for (std::string const& di : this->Defines) {
+ if (di == "_UNICODE") {
return true;
}
}
@@ -163,9 +162,8 @@ bool cmVisualStudioGeneratorOptions::UsingUnicode() const
bool cmVisualStudioGeneratorOptions::UsingSBCS() const
{
// 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") {
+ for (std::string const& di : this->Defines) {
+ if (di == "_SBCS") {
return true;
}
}
@@ -227,7 +225,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
// It translates to -arch=<virtual> -code=<real>.
cmSystemTools::ReplaceString(arch_name, "sm_", "compute_");
}
- for (auto const& c : codes) {
+ for (std::string const& c : codes) {
std::string entry = arch_name + "," + c;
result.push_back(entry);
}
@@ -237,7 +235,7 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
// -gencode=<arch>,<code>
// -gencode=<arch>,[<code1>,<code2>]
// -gencode=<arch>,"<code1>,<code2>"
- for (auto const& e : gencode) {
+ for (std::string const& e : gencode) {
std::string entry = e;
cmSystemTools::ReplaceString(entry, "arch=", "");
cmSystemTools::ReplaceString(entry, "code=", "");
@@ -285,7 +283,7 @@ void cmVisualStudioGeneratorOptions::FixManifestUACFlags()
uacExecuteLevelMap["highestAvailable"] = "HighestAvailable";
uacExecuteLevelMap["requireAdministrator"] = "RequireAdministrator";
- for (auto const& subopt : subOptions) {
+ for (std::string const& subopt : subOptions) {
std::vector<std::string> keyValue;
cmsys::SystemTools::Split(subopt, keyValue, '=');
if (keyValue.size() != 2 || (uacMap.find(keyValue[0]) == uacMap.end())) {
@@ -332,9 +330,8 @@ void cmVisualStudioGeneratorOptions::Parse(const char* flags)
// Process flags that need to be represented specially in the IDE
// project file.
- for (std::vector<std::string>::iterator ai = args.begin(); ai != args.end();
- ++ai) {
- this->HandleFlag(ai->c_str());
+ for (std::string const& ai : args) {
+ this->HandleFlag(ai);
}
}
@@ -396,23 +393,23 @@ void cmVisualStudioGeneratorOptions::Reparse(std::string const& key)
this->Parse(original.c_str());
}
-void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
+void cmVisualStudioGeneratorOptions::StoreUnknownFlag(std::string const& flag)
{
// Look for Intel Fortran flags that do not map well in the flag table.
if (this->CurrentTool == FortranCompiler) {
- if (strcmp(flag, "/dbglibs") == 0) {
+ if (flag == "/dbglibs") {
this->FortranRuntimeDebug = true;
return;
}
- if (strcmp(flag, "/threads") == 0) {
+ if (flag == "/threads") {
this->FortranRuntimeMT = true;
return;
}
- if (strcmp(flag, "/libs:dll") == 0) {
+ if (flag == "/libs:dll") {
this->FortranRuntimeDLL = true;
return;
}
- if (strcmp(flag, "/libs:static") == 0) {
+ if (flag == "/libs:static") {
this->FortranRuntimeDLL = false;
return;
}
@@ -420,7 +417,7 @@ void cmVisualStudioGeneratorOptions::StoreUnknownFlag(const char* flag)
// This option is not known. Store it in the output flags.
std::string const opts = cmOutputConverter::EscapeWindowsShellArgument(
- flag, cmOutputConverter::Shell_Flag_AllowMakeVariables |
+ flag.c_str(), cmOutputConverter::Shell_Flag_AllowMakeVariables |
cmOutputConverter::Shell_Flag_VSIDE);
this->AppendFlagString(this->UnknownFlagField, opts);
}
@@ -437,7 +434,8 @@ cmIDEOptions::FlagValue cmVisualStudioGeneratorOptions::TakeFlag(
return value;
}
-void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config)
+void cmVisualStudioGeneratorOptions::SetConfiguration(
+ const std::string& config)
{
this->Configuration = config;
}
@@ -566,31 +564,27 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
const char* indent)
{
if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
- for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m) {
+ for (auto const& m : this->FlagMap) {
fout << indent;
if (!this->Configuration.empty()) {
this->TargetGenerator->WritePlatformConfigTag(
- m->first.c_str(), this->Configuration.c_str(), 0, 0, 0, &fout);
+ m.first.c_str(), this->Configuration.c_str(), 0, 0, 0, &fout);
} else {
- fout << "<" << m->first << ">";
+ fout << "<" << m.first << ">";
}
const char* sep = "";
- for (std::vector<std::string>::iterator i = m->second.begin();
- i != m->second.end(); ++i) {
- fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(*i);
+ for (std::string const& i : m.second) {
+ fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(i);
sep = ";";
}
- fout << "</" << m->first << ">\n";
+ fout << "</" << m.first << ">\n";
}
} else {
- for (std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
- m != this->FlagMap.end(); ++m) {
- fout << indent << m->first << "=\"";
+ for (auto const& m : this->FlagMap) {
+ fout << indent << m.first << "=\"";
const char* sep = "";
- for (std::vector<std::string>::iterator i = m->second.begin();
- i != m->second.end(); ++i) {
- fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(*i);
+ for (std::string const& i : m.second) {
+ fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(i);
sep = ";";
}
fout << "\"\n";
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index 2dffe9b..5c3e415 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -91,7 +91,7 @@ public:
const char* suffix,
const std::string& lang);
void OutputFlagMap(std::ostream& fout, const char* indent);
- void SetConfiguration(const char* config);
+ void SetConfiguration(const std::string& config);
private:
cmLocalVisualStudioGenerator* LocalGenerator;
@@ -107,7 +107,7 @@ private:
std::string UnknownFlagField;
- virtual void StoreUnknownFlag(const char* flag);
+ void StoreUnknownFlag(std::string const& flag) override;
FlagValue TakeFlag(std::string const& key);
};
diff --git a/Source/cmWorkingDirectory.cxx b/Source/cmWorkingDirectory.cxx
index 99c9ba8..816f104 100644
--- a/Source/cmWorkingDirectory.cxx
+++ b/Source/cmWorkingDirectory.cxx
@@ -4,10 +4,12 @@
#include "cmSystemTools.h"
+#include <cerrno>
+
cmWorkingDirectory::cmWorkingDirectory(std::string const& newdir)
{
this->OldDir = cmSystemTools::GetCurrentWorkingDirectory();
- cmSystemTools::ChangeDirectory(newdir);
+ this->SetDirectory(newdir);
}
cmWorkingDirectory::~cmWorkingDirectory()
@@ -15,10 +17,20 @@ cmWorkingDirectory::~cmWorkingDirectory()
this->Pop();
}
+bool cmWorkingDirectory::SetDirectory(std::string const& newdir)
+{
+ if (cmSystemTools::ChangeDirectory(newdir) == 0) {
+ this->ResultCode = 0;
+ return true;
+ }
+ this->ResultCode = errno;
+ return false;
+}
+
void cmWorkingDirectory::Pop()
{
if (!this->OldDir.empty()) {
- cmSystemTools::ChangeDirectory(this->OldDir);
+ this->SetDirectory(this->OldDir);
this->OldDir.clear();
}
}
diff --git a/Source/cmWorkingDirectory.h b/Source/cmWorkingDirectory.h
index aff9267..1f18ce7 100644
--- a/Source/cmWorkingDirectory.h
+++ b/Source/cmWorkingDirectory.h
@@ -9,6 +9,12 @@
/** \class cmWorkingDirectory
* \brief An RAII class to manipulate the working directory.
+ *
+ * The current working directory is set to the location given to the
+ * constructor. The working directory can be changed again as needed
+ * by calling SetDirectory(). When the object is destroyed, the destructor
+ * will restore the working directory to what it was when the object was
+ * created, regardless of any calls to SetDirectory() in the meantime.
*/
class cmWorkingDirectory
{
@@ -16,10 +22,21 @@ public:
cmWorkingDirectory(std::string const& newdir);
~cmWorkingDirectory();
+ bool SetDirectory(std::string const& newdir);
void Pop();
+ bool Failed() const { return ResultCode != 0; }
+
+ /** \return 0 if the last attempt to set the working directory was
+ * successful. If it failed, the value returned will be the
+ * \c errno value associated with the failure. A description
+ * of the error code can be obtained by passing the result
+ * to \c std::strerror().
+ */
+ int GetLastResult() const { return ResultCode; }
private:
std::string OldDir;
+ int ResultCode;
};
#endif
diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h
index 7bae21e..80940ee 100644
--- a/Source/cmXMLWriter.h
+++ b/Source/cmXMLWriter.h
@@ -133,4 +133,56 @@ private:
bool IsContent;
};
+class cmXMLElement; // IWYU pragma: keep
+
+class cmXMLDocument
+{
+public:
+ cmXMLDocument(cmXMLWriter& xml)
+ : xmlwr(xml)
+ {
+ xmlwr.StartDocument();
+ }
+ ~cmXMLDocument() { xmlwr.EndDocument(); }
+private:
+ friend class cmXMLElement;
+ cmXMLWriter& xmlwr;
+};
+
+class cmXMLElement
+{
+public:
+ cmXMLElement(cmXMLWriter& xml, const char* tag)
+ : xmlwr(xml)
+ {
+ xmlwr.StartElement(tag);
+ }
+ cmXMLElement(cmXMLElement& par, const char* tag)
+ : xmlwr(par.xmlwr)
+ {
+ xmlwr.StartElement(tag);
+ }
+ cmXMLElement(cmXMLDocument& doc, const char* tag)
+ : xmlwr(doc.xmlwr)
+ {
+ xmlwr.StartElement(tag);
+ }
+ ~cmXMLElement() { xmlwr.EndElement(); }
+
+ template <typename T>
+ cmXMLElement& Attribute(const char* name, T const& value)
+ {
+ xmlwr.Attribute(name, value);
+ return *this;
+ }
+ template <typename T>
+ void Content(T const& content)
+ {
+ xmlwr.Content(content);
+ }
+
+private:
+ cmXMLWriter& xmlwr;
+};
+
#endif
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 5620723..323bcf6 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -98,13 +98,13 @@
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <cstring>
#include <iostream>
#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <utility>
namespace {
@@ -2209,6 +2209,15 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
{
// now run cmake on the CMakeLists file
cmWorkingDirectory workdir(destPath);
+ if (workdir.Failed()) {
+ // We created the directory and we were able to copy the CMakeLists.txt
+ // file to it, so we wouldn't expect to get here unless the default
+ // permissions are questionable or some other process has deleted the
+ // directory
+ std::cerr << "Failed to change to directory " << destPath << " : "
+ << std::strerror(workdir.GetLastResult()) << std::endl;
+ return 1;
+ }
std::vector<std::string> args2;
args2.push_back(args[0]);
args2.push_back(destPath);
@@ -2387,17 +2396,17 @@ int cmake::Build(const std::string& dir, const std::string& target,
std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
return 1;
}
- std::unique_ptr<cmGlobalGenerator> gen(
- this->CreateGlobalGenerator(cachedGenerator));
- if (!gen.get()) {
+ cmGlobalGenerator* gen = this->CreateGlobalGenerator(cachedGenerator);
+ if (!gen) {
std::cerr << "Error: could create CMAKE_GENERATOR \"" << cachedGenerator
<< "\"\n";
return 1;
}
+ this->SetGlobalGenerator(gen);
const char* cachedGeneratorInstance =
this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE");
if (cachedGeneratorInstance) {
- cmMakefile mf(gen.get(), this->GetCurrentSnapshot());
+ cmMakefile mf(gen, this->GetCurrentSnapshot());
if (!gen->SetGeneratorInstance(cachedGeneratorInstance, &mf)) {
return 1;
}
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 0988c3c..6f3a90f 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -359,7 +359,8 @@ struct CoCompileJob
int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
{
std::vector<CoCompileJob> jobs;
- std::string sourceFile; // store --source=
+ std::string sourceFile; // store --source=
+ std::vector<std::string> launchers; // store --launcher=
// Default is to run the original command found after -- if the option
// does not need to do that, it should be specified here, currently only
@@ -390,15 +391,17 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
}
}
}
- if (cmHasLiteralPrefix(arg, "--source=")) {
- sourceFile = arg.substr(9);
- optionFound = true;
- }
- // if it was not a co-compiler or --source then error
if (!optionFound) {
- std::cerr << "__run_co_compile given unknown argument: " << arg
- << "\n";
- return 1;
+ if (cmHasLiteralPrefix(arg, "--source=")) {
+ sourceFile = arg.substr(9);
+ } else if (cmHasLiteralPrefix(arg, "--launcher=")) {
+ cmSystemTools::ExpandListArgument(arg.substr(11), launchers, true);
+ } else {
+ // if it was not a co-compiler or --source/--launcher then error
+ std::cerr << "__run_co_compile given unknown argument: " << arg
+ << "\n";
+ return 1;
+ }
}
} else { // if not doing_options then push to orig_cmd
orig_cmd.push_back(arg);
@@ -436,6 +439,11 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
return 0;
}
+ // Prepend launcher argument(s), if any
+ if (!launchers.empty()) {
+ orig_cmd.insert(orig_cmd.begin(), launchers.begin(), launchers.end());
+ }
+
// Now run the real compiler command and return its result value
int ret;
if (!cmSystemTools::RunSingleCommand(orig_cmd, nullptr, nullptr, &ret,
@@ -689,8 +697,6 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Touch file
if (args[1] == "touch_nocreate" && args.size() > 2) {
for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- // Complain if the file could not be removed, still exists,
- // and the -f option was not given.
if (!cmSystemTools::Touch(args[cc], false)) {
return 1;
}
diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt
index 06df53f..126076d 100644
--- a/Tests/CMakeLib/CMakeLists.txt
+++ b/Tests/CMakeLib/CMakeLists.txt
@@ -49,3 +49,6 @@ if(TEST_CompileCommandOutput)
endif()
add_subdirectory(PseudoMemcheck)
+
+add_executable(testAffinity testAffinity.cxx)
+target_link_libraries(testAffinity CMakeLib)
diff --git a/Tests/CMakeLib/testAffinity.cxx b/Tests/CMakeLib/testAffinity.cxx
new file mode 100644
index 0000000..4b82280
--- /dev/null
+++ b/Tests/CMakeLib/testAffinity.cxx
@@ -0,0 +1,18 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmAffinity.h"
+
+#include <cstddef>
+#include <iostream>
+#include <set>
+
+int main()
+{
+ std::set<size_t> cpus = cmAffinity::GetProcessorsAvailable();
+ if (!cpus.empty()) {
+ std::cout << "CPU affinity mask count is '" << cpus.size() << "'.\n";
+ } else {
+ std::cout << "CPU affinity not supported on this platform.\n";
+ }
+ return 0;
+}
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 08bfebe..101502f 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -348,6 +348,7 @@ if(BUILD_TESTING)
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
ADD_TEST_MACRO(CSharpOnly CSharpOnly)
ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx)
+ ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx)
endif()
ADD_TEST_MACRO(COnly COnly)
@@ -816,6 +817,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
ADD_TEST_MACRO(CustomCommandByproducts CustomCommandByproducts)
+ ADD_TEST_MACRO(CommandLength CommandLength)
+
ADD_TEST_MACRO(EmptyDepends ${CMAKE_CTEST_COMMAND})
add_test(CustomCommandWorkingDirectory ${CMAKE_CTEST_COMMAND}
@@ -1323,6 +1326,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
add_subdirectory(FindBZip2)
endif()
+ if(CMake_TEST_FindCURL)
+ add_subdirectory(FindCURL)
+ endif()
+
if(CMake_TEST_FindDoxygen)
add_subdirectory(FindDoxygen)
endif()
@@ -1364,6 +1371,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
add_subdirectory(FindLibUV)
endif()
+ if(CMake_TEST_FindLibXml2)
+ add_subdirectory(FindLibXml2)
+ endif()
+
if(CMake_TEST_FindLTTngUST)
add_subdirectory(FindLTTngUST)
endif()
@@ -1443,6 +1454,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProject")
set_tests_properties(ExternalProject PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
add_test(NAME ExternalProjectSubdir
@@ -1482,6 +1494,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectLocal")
set_tests_properties(ExternalProjectLocal PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
add_test(ExternalProjectUpdateSetup ${CMAKE_CTEST_COMMAND}
@@ -1497,6 +1510,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectUpdate")
set_tests_properties(ExternalProjectUpdateSetup PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT})
add_test(NAME ExternalProjectUpdate
@@ -1511,6 +1525,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
)
list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ExternalProjectUpdate")
set_tests_properties(ExternalProjectUpdate PROPERTIES
+ RUN_SERIAL 1
TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT}
WORKING_DIRECTORY ${CMake_SOURCE_DIR}/Tests/ExternalProjectUpdate
DEPENDS ExternalProjectUpdateSetup )
diff --git a/Tests/CSharpLinkFromCxx/.gitattributes b/Tests/CSharpLinkFromCxx/.gitattributes
new file mode 100644
index 0000000..57a39049
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/.gitattributes
@@ -0,0 +1 @@
+UsefulManagedCppClass.* -format.clang-format
diff --git a/Tests/CSharpLinkFromCxx/CMakeLists.txt b/Tests/CSharpLinkFromCxx/CMakeLists.txt
new file mode 100644
index 0000000..9a1a993
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/CMakeLists.txt
@@ -0,0 +1,19 @@
+# Take a C# shared library and link it to a managed C++ shared library
+cmake_minimum_required(VERSION 3.10)
+project (CSharpLinkFromCxx CXX CSharp)
+
+add_library(CSharpLibrary SHARED UsefulCSharpClass.cs)
+
+# we have to change the default flags for the
+# managed C++ project to build
+string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
+
+# The C# project is a dependency of the C++/CLI project
+add_library(ManagedCppLibrary SHARED UsefulManagedCppClass.cpp UsefulManagedCppClass.hpp)
+target_compile_options(ManagedCppLibrary PRIVATE "/clr")
+target_link_libraries(ManagedCppLibrary PUBLIC CSharpLibrary)
+
+# Main executable for the test framework
+add_executable(CSharpLinkFromCxx CSharpLinkFromCxx.cs)
+target_link_libraries(CSharpLinkFromCxx PRIVATE ManagedCppLibrary)
diff --git a/Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs b/Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs
new file mode 100644
index 0000000..31a74eb
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/CSharpLinkFromCxx.cs
@@ -0,0 +1,16 @@
+using System;
+using CSharpLibrary;
+
+namespace CSharpLinkFromCxx
+{
+ internal class CSharpLinkFromCxx
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Starting test for CSharpLinkFromCxx");
+
+ var useful = new UsefulManagedCppClass();
+ useful.RunTest();
+ }
+ }
+}
diff --git a/Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs b/Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs
new file mode 100644
index 0000000..749e57d
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/UsefulCSharpClass.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace CSharpLibrary
+{
+ public class UsefulCSharpClass
+ {
+ public string GetSomethingUseful()
+ {
+ return "Something Useful";
+ }
+ }
+}
diff --git a/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp
new file mode 100644
index 0000000..9468812
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.cpp
@@ -0,0 +1,15 @@
+#include "UsefulManagedCppClass.hpp"
+
+namespace CSharpLibrary
+{
+ UsefulManagedCppClass::UsefulManagedCppClass()
+ {
+ auto useful = gcnew UsefulCSharpClass();
+ m_usefulString = useful->GetSomethingUseful();
+ }
+
+ void UsefulManagedCppClass::RunTest()
+ {
+ Console::WriteLine("Printing from Managed CPP Class: " + m_usefulString);
+ }
+}
diff --git a/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp
new file mode 100644
index 0000000..def7cea
--- /dev/null
+++ b/Tests/CSharpLinkFromCxx/UsefulManagedCppClass.hpp
@@ -0,0 +1,16 @@
+using namespace System;
+
+namespace CSharpLibrary
+{
+ public ref class UsefulManagedCppClass
+ {
+ public:
+
+ UsefulManagedCppClass();
+ void RunTest();
+
+ private:
+
+ String^ m_usefulString;
+ };
+}
diff --git a/Tests/CTestTest/test.cmake.in b/Tests/CTestTest/test.cmake.in
index 589bd44..23166a7 100644
--- a/Tests/CTestTest/test.cmake.in
+++ b/Tests/CTestTest/test.cmake.in
@@ -62,7 +62,7 @@ COVERAGE_COMMAND:FILEPATH=@COVERAGE_COMMAND@
set (CTEST_DASHBOARD_ROOT "@CMAKE_CURRENT_BINARY_DIR@/Tests/CTestTest")
-# set any extra environment varibles here
+# set any extra environment variables here
set (CTEST_ENVIRONMENT
)
diff --git a/Tests/CommandLength/CMakeLists.txt b/Tests/CommandLength/CMakeLists.txt
new file mode 100644
index 0000000..6836051
--- /dev/null
+++ b/Tests/CommandLength/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.10)
+project(CommandLength C)
+
+add_executable(CommandLength test.c)
+add_custom_command(TARGET CommandLength POST_BUILD VERBATIM
+ COMMAND ${CMAKE_COMMAND} -E make_directory log)
+
+set(msg "xxxx $$$$ yyyy")
+set(msg "${msg} ${msg}")
+set(msg "${msg} ${msg}")
+set(msg "${msg} ${msg}")
+set(msg "${msg} ${msg}")
+foreach(i RANGE 1 1000)
+ add_custom_command(TARGET CommandLength POST_BUILD VERBATIM
+ COMMAND ${CMAKE_COMMAND} -E echo "${i} ${msg}" > log/${i}
+ )
+endforeach()
diff --git a/Tests/CommandLength/test.c b/Tests/CommandLength/test.c
new file mode 100644
index 0000000..f8b643a
--- /dev/null
+++ b/Tests/CommandLength/test.c
@@ -0,0 +1,4 @@
+int main()
+{
+ return 0;
+}
diff --git a/Tests/CompileOptions/CMakeLists.txt b/Tests/CompileOptions/CMakeLists.txt
index 692e0de..c9f1710 100644
--- a/Tests/CompileOptions/CMakeLists.txt
+++ b/Tests/CompileOptions/CMakeLists.txt
@@ -18,9 +18,21 @@ set_property(TARGET CompileOptions PROPERTY COMPILE_OPTIONS
"-DTEST_DEFINE"
"-DNEEDS_ESCAPE=\"E$CAPE\""
"$<$<CXX_COMPILER_ID:GNU>:-DTEST_DEFINE_GNU>"
+ "SHELL:" # produces no options
${c_tests}
${cxx_tests}
)
+if(BORLAND OR WATCOM)
+ # these compilers do not support separate -D flags
+ target_compile_definitions(CompileOptions PRIVATE NO_DEF_TESTS)
+else()
+ set_property(TARGET CompileOptions APPEND PROPERTY COMPILE_OPTIONS
+ "SHELL:-D DEF_A"
+ "$<1:SHELL:-D DEF_B>"
+ "SHELL:-D 'DEF_C' -D \"DEF_D\""
+ [[SHELL:-D "DEF_STR=\"string with spaces\""]]
+ )
+endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|Borland|Embarcadero")
set_property(TARGET CompileOptions APPEND PROPERTY COMPILE_OPTIONS
diff --git a/Tests/CompileOptions/main.cpp b/Tests/CompileOptions/main.cpp
index 63a0480..4779b88 100644
--- a/Tests/CompileOptions/main.cpp
+++ b/Tests/CompileOptions/main.cpp
@@ -12,6 +12,28 @@
#endif
#endif
+#ifndef NO_DEF_TESTS
+#ifndef DEF_A
+#error Expected definition DEF_A
+#endif
+
+#ifndef DEF_B
+#error Expected definition DEF_B
+#endif
+
+#ifndef DEF_C
+#error Expected definition DEF_C
+#endif
+
+#ifndef DEF_D
+#error Expected definition DEF_D
+#endif
+
+#ifndef DEF_STR
+#error Expected definition DEF_STR
+#endif
+#endif
+
#include <string.h>
int main()
@@ -20,6 +42,9 @@ int main()
#ifdef TEST_OCTOTHORPE
&& strcmp(TEST_OCTOTHORPE, "#") == 0
#endif
+#ifndef NO_DEF_TESTS
+ && strcmp(DEF_STR, "string with spaces") == 0
+#endif
&&
strcmp(EXPECTED_C_COMPILER_VERSION, TEST_C_COMPILER_VERSION) == 0 &&
strcmp(EXPECTED_CXX_COMPILER_VERSION, TEST_CXX_COMPILER_VERSION) ==
diff --git a/Tests/Complex/Cache/CMakeCache.txt b/Tests/Complex/Cache/CMakeCache.txt
index 17c55aa..727faa2 100644
--- a/Tests/Complex/Cache/CMakeCache.txt
+++ b/Tests/Complex/Cache/CMakeCache.txt
@@ -5,7 +5,7 @@
# If you do want to change a value, simply edit, save, and exit the editor.
# The syntax for the file is as follows:
# KEY:TYPE=VALUE
-# KEY is the name of a varible in the cache.
+# KEY is the name of a variable in the cache.
# TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!.
# VALUE is the current value for the KEY.
diff --git a/Tests/ComplexOneConfig/Cache/CMakeCache.txt b/Tests/ComplexOneConfig/Cache/CMakeCache.txt
index 17c55aa..727faa2 100644
--- a/Tests/ComplexOneConfig/Cache/CMakeCache.txt
+++ b/Tests/ComplexOneConfig/Cache/CMakeCache.txt
@@ -5,7 +5,7 @@
# If you do want to change a value, simply edit, save, and exit the editor.
# The syntax for the file is as follows:
# KEY:TYPE=VALUE
-# KEY is the name of a varible in the cache.
+# KEY is the name of a variable in the cache.
# TYPE is a hint to GUI's for the type of VALUE, DO NOT EDIT TYPE!.
# VALUE is the current value for the KEY.
diff --git a/Tests/Contracts/PLplot/CMakeLists.txt b/Tests/Contracts/PLplot/CMakeLists.txt
index b87b4c3..7051d62 100644
--- a/Tests/Contracts/PLplot/CMakeLists.txt
+++ b/Tests/Contracts/PLplot/CMakeLists.txt
@@ -9,7 +9,7 @@ if(NOT PLplot_GIT_TAG)
set(PLplot_GIT_TAG "plplot-5.13.0")
endif()
ExternalProject_Add(PLplot
- GIT_REPOSITORY "https://git.code.sf.net/p/plplot/plplot.git"
+ GIT_REPOSITORY "git://git.code.sf.net/p/plplot/plplot"
GIT_TAG "${PLplot_GIT_TAG}"
PREFIX "${PLplot_PREFIX}"
CMAKE_ARGS
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index eeae3f0..0f1a556 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -83,11 +83,23 @@ set_property(TARGET testLib7 PROPERTY OUTPUT_NAME testLib7-$<CONFIG>)
add_library(testLib8 OBJECT testLib8A.c testLib8B.c sub/testLib8C.c)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
- set(maybe_testLib8 testLib8)
+ set(maybe_OBJECTS_DESTINATION OBJECTS DESTINATION $<1:lib>)
else()
- set(maybe_testLib8 "")
+ set(maybe_OBJECTS_DESTINATION "")
endif()
+cmake_policy(PUSH)
+cmake_policy(SET CMP0022 NEW)
+add_library(testLib9ObjPub OBJECT testLib9ObjPub.c)
+target_compile_definitions(testLib9ObjPub INTERFACE testLib9ObjPub_USED)
+add_library(testLib9ObjPriv OBJECT testLib9ObjPriv.c)
+target_compile_definitions(testLib9ObjPriv INTERFACE testLib9ObjPriv_USED)
+add_library(testLib9ObjIface OBJECT testLib9ObjIface.c)
+target_compile_definitions(testLib9ObjIface INTERFACE testLib9ObjIface_USED)
+add_library(testLib9 STATIC testLib9.c)
+target_link_libraries(testLib9 INTERFACE testLib9ObjIface PUBLIC testLib9ObjPub PRIVATE testLib9ObjPriv)
+cmake_policy(POP)
+
# Test using the target_link_libraries command to set the
# LINK_INTERFACE_LIBRARIES* properties. We construct two libraries
# providing the same two symbols. In each library one of the symbols
@@ -344,6 +356,14 @@ install(FILES
set_property(TARGET testLib2 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USING_TESTLIB2)
set_property(TARGET testLib3 APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USING_TESTLIB3)
+set_target_properties(testLib3 PROPERTIES
+ EXPORT_PROPERTIES "EXPORTED_PROPERTY1"
+ EXPORTED_PROPERTY1 "EXPORTING_TESTLIB3")
+set_target_properties(testLib4 PROPERTIES
+ EXPORTED_PROPERTY2 "EXPORTING_TESTLIB4_1"
+ EXPORTED_PROPERTY3 "EXPORTING_TESTLIB4_2")
+set_property(TARGET testLib4 PROPERTY
+ EXPORT_PROPERTIES EXPORTED_PROPERTY2 EXPORTED_PROPERTY3)
set_property(TARGET cmp0022NEW APPEND PROPERTY INTERFACE_LINK_LIBRARIES testLib2)
# set_property(TARGET cmp0022NEW APPEND PROPERTY LINK_INTERFACE_LIBRARIES testLibIncludeRequired2) # TODO: Test for error
@@ -483,7 +503,8 @@ install(
TARGETS
testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3 testExe4
testExe2lib testLib4lib testLib4libdbg testLib4libopt
- testLib6 testLib7 ${maybe_testLib8}
+ testLib6 testLib7 testLib8
+ testLib9
testLibCycleA testLibCycleB
testLibNoSONAME
cmp0022NEW cmp0022OLD
@@ -492,10 +513,15 @@ install(
RUNTIME DESTINATION $<1:bin>
LIBRARY DESTINATION $<1:lib> NAMELINK_SKIP
ARCHIVE DESTINATION $<1:lib>
- OBJECTS DESTINATION $<1:lib>
+ ${maybe_OBJECTS_DESTINATION}
FRAMEWORK DESTINATION Frameworks
BUNDLE DESTINATION Applications
)
+install(
+ TARGETS
+ testLib9ObjPub testLib9ObjPriv testLib9ObjIface
+ EXPORT exp
+ )
if (APPLE)
file(COPY testLib4.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/testLib4.framework/Headers)
file(COPY testLib4.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/Debug/testLib4.framework/Headers)
@@ -545,7 +571,8 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3
FILE ExportBuildTree.cmake
)
export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 testExe2lib
- ${maybe_testLib8}
+ testLib8
+ testLib9 testLib9ObjPub testLib9ObjPriv testLib9ObjIface
testLib4lib testLib4libdbg testLib4libopt
testLibCycleA testLibCycleB
testLibNoSONAME
diff --git a/Tests/ExportImport/Export/testLib9.c b/Tests/ExportImport/Export/testLib9.c
new file mode 100644
index 0000000..fe8610b
--- /dev/null
+++ b/Tests/ExportImport/Export/testLib9.c
@@ -0,0 +1,15 @@
+#ifndef testLib9ObjPub_USED
+#error "testLib9ObjPub_USED not defined!"
+#endif
+#ifndef testLib9ObjPriv_USED
+#error "testLib9ObjPriv_USED not defined!"
+#endif
+#ifdef testLib9ObjIface_USED
+#error "testLib9ObjIface_USED defined but should not be!"
+#endif
+int testLib9ObjPub(void);
+int testLib9ObjPriv(void);
+int testLib9(void)
+{
+ return (testLib9ObjPub() + testLib9ObjPriv());
+}
diff --git a/Tests/ExportImport/Export/testLib9ObjIface.c b/Tests/ExportImport/Export/testLib9ObjIface.c
new file mode 100644
index 0000000..e75440a
--- /dev/null
+++ b/Tests/ExportImport/Export/testLib9ObjIface.c
@@ -0,0 +1,11 @@
+/* Duplicate symbols from other sources to verify that this source
+ is not included when the object library is used. */
+int testLib9ObjMissing(void);
+int testLib9ObjPub(void)
+{
+ return testLib9ObjMissing();
+}
+int testLib9ObjPriv(void)
+{
+ return testLib9ObjMissing();
+}
diff --git a/Tests/ExportImport/Export/testLib9ObjPriv.c b/Tests/ExportImport/Export/testLib9ObjPriv.c
new file mode 100644
index 0000000..6fa63cc
--- /dev/null
+++ b/Tests/ExportImport/Export/testLib9ObjPriv.c
@@ -0,0 +1,4 @@
+int testLib9ObjPriv(void)
+{
+ return 0;
+}
diff --git a/Tests/ExportImport/Export/testLib9ObjPub.c b/Tests/ExportImport/Export/testLib9ObjPub.c
new file mode 100644
index 0000000..66e2624
--- /dev/null
+++ b/Tests/ExportImport/Export/testLib9ObjPub.c
@@ -0,0 +1,4 @@
+int testLib9ObjPub(void)
+{
+ return 0;
+}
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 01960ea..39a89dc 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -32,6 +32,20 @@ add_executable(imp_testExe1
${Import_BINARY_DIR}/exp_generated4.c
)
+function(checkForProperty _TARGET _PROP _EXPECTED)
+ get_target_property(EXPORTED_PROPERTY ${_TARGET} "${_PROP}")
+ if (NOT EXPORTED_PROPERTY STREQUAL "${_EXPECTED}")
+ message(SEND_ERROR "${_TARGET} was expected to export \"${_PROP}\" with value \"${_EXPECTED}\" but got \"${EXPORTED_PROPERTY}\"")
+ endif()
+endfunction()
+
+checkForProperty(bld_testLib3 "EXPORTED_PROPERTY1" "EXPORTING_TESTLIB3")
+checkForProperty(exp_testLib3 "EXPORTED_PROPERTY1" "EXPORTING_TESTLIB3")
+checkForProperty(bld_testLib4 "EXPORTED_PROPERTY2" "EXPORTING_TESTLIB4_1")
+checkForProperty(exp_testLib4 "EXPORTED_PROPERTY2" "EXPORTING_TESTLIB4_1")
+checkForProperty(bld_testLib4 "EXPORTED_PROPERTY3" "EXPORTING_TESTLIB4_2")
+checkForProperty(exp_testLib4 "EXPORTED_PROPERTY3" "EXPORTING_TESTLIB4_2")
+
# Try linking to a library imported from the install tree.
target_link_libraries(imp_testExe1
exp_testLib2
@@ -229,15 +243,44 @@ add_library(imp_lib1b STATIC imp_lib1.c)
target_link_libraries(imp_lib1b bld_testLib2)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
- # Create a executable that is using objects imported from the install tree
- add_executable(imp_testLib8 imp_testLib8.c $<TARGET_OBJECTS:exp_testLib8>)
+ set(bld_objlib_type OBJECT_LIBRARY)
+
+ # Create executables using objects imported from the install tree
+ add_executable(imp_testLib8_src imp_testLib8.c $<TARGET_OBJECTS:exp_testLib8>)
+ add_executable(imp_testLib8_link imp_testLib8.c)
+ target_link_libraries(imp_testLib8_link exp_testLib8)
if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT XCODE_VERSION VERSION_LESS 5)
- # Create a executable that is using objects imported from the build tree
- add_executable(imp_testLib8b imp_testLib8.c $<TARGET_OBJECTS:bld_testLib8>)
+ # Create executables using objects imported from the build tree
+ add_executable(imp_testLib8b_src imp_testLib8.c $<TARGET_OBJECTS:bld_testLib8>)
+ add_executable(imp_testLib8b_link imp_testLib8.c)
+ target_link_libraries(imp_testLib8b_link bld_testLib8)
endif()
+else()
+ set(bld_objlib_type INTERFACE_LIBRARY)
endif()
+# Create an executable that uses a library imported from the install tree
+# that itself was built using an object library. Verify we get the usage
+# requirements.
+add_executable(imp_testLib9 imp_testLib9.c)
+target_link_libraries(imp_testLib9 exp_testLib9)
+# Similarly for importing from the build tree.
+add_executable(imp_testLib9b imp_testLib9.c)
+target_link_libraries(imp_testLib9b bld_testLib9)
+
+# Check that object libraries were transformed on export as expected.
+foreach(vis Pub Priv Iface)
+ get_property(type TARGET exp_testLib9Obj${vis} PROPERTY TYPE)
+ if(NOT type STREQUAL INTERFACE_LIBRARY)
+ message(FATAL_ERROR "exp_testLib9Obj${vis} type is '${type}', not 'INTERFACE_LIBRARY'")
+ endif()
+ get_property(type TARGET bld_testLib9Obj${vis} PROPERTY TYPE)
+ if(NOT type STREQUAL "${bld_objlib_type}")
+ message(FATAL_ERROR "bld_testLib9Obj${vis} type is '${type}', not '${bld_objlib_type}'")
+ endif()
+endforeach()
+
#-----------------------------------------------------------------------------
# Test that handling imported targets, including transitive dependencies,
# works in CheckFunctionExists (...and hopefully all other try_compile() checks
diff --git a/Tests/ExportImport/Import/A/imp_testLib9.c b/Tests/ExportImport/Import/A/imp_testLib9.c
new file mode 100644
index 0000000..f9c05fd
--- /dev/null
+++ b/Tests/ExportImport/Import/A/imp_testLib9.c
@@ -0,0 +1,16 @@
+#ifndef testLib9ObjPub_USED
+#error "testLib9ObjPub_USED not defined!"
+#endif
+#ifdef testLib9ObjPriv_USED
+#error "testLib9ObjPriv_USED defined but should not be!"
+#endif
+#ifndef testLib9ObjIface_USED
+#error "testLib9ObjIface_USED not defined!"
+#endif
+
+int testLib9(void);
+
+int main()
+{
+ return testLib9();
+}
diff --git a/Tests/FindCURL/CMakeLists.txt b/Tests/FindCURL/CMakeLists.txt
new file mode 100644
index 0000000..0cfd629
--- /dev/null
+++ b/Tests/FindCURL/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindCURL.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindCURL/Test"
+ "${CMake_BINARY_DIR}/Tests/FindCURL/Test"
+ ${build_generator_args}
+ --build-project TestFindCURL
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindCURL/Test/CMakeLists.txt b/Tests/FindCURL/Test/CMakeLists.txt
new file mode 100644
index 0000000..f0e5568
--- /dev/null
+++ b/Tests/FindCURL/Test/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.10)
+project(TestFindCURL C)
+include(CTest)
+
+find_package(CURL REQUIRED)
+
+add_definitions(-DCMAKE_EXPECTED_CURL_VERSION="${CURL_VERSION_STRING}")
+
+add_executable(test_tgt main.c)
+target_link_libraries(test_tgt CURL::CURL)
+add_test(NAME test_tgt COMMAND test_tgt)
+
+add_executable(test_var main.c)
+target_include_directories(test_var PRIVATE ${CURL_INCLUDE_DIRS})
+target_link_libraries(test_var PRIVATE ${CURL_LIBRARIES})
+add_test(NAME test_var COMMAND test_var)
diff --git a/Tests/FindCURL/Test/main.c b/Tests/FindCURL/Test/main.c
new file mode 100644
index 0000000..263775f
--- /dev/null
+++ b/Tests/FindCURL/Test/main.c
@@ -0,0 +1,17 @@
+#include <curl/curl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main()
+{
+ struct curl_slist* slist;
+
+ curl_global_init(0);
+
+ slist = curl_slist_append(NULL, "CMake");
+ curl_slist_free_all(slist);
+
+ curl_global_cleanup();
+
+ return 0;
+}
diff --git a/Tests/FindLibXml2/CMakeLists.txt b/Tests/FindLibXml2/CMakeLists.txt
new file mode 100644
index 0000000..6c2464f
--- /dev/null
+++ b/Tests/FindLibXml2/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindLibXml2.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindLibXml2/Test"
+ "${CMake_BINARY_DIR}/Tests/FindLibXml2/Test"
+ ${build_generator_args}
+ --build-project TestFindLibXml2
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindLibXml2/Test/CMakeLists.txt b/Tests/FindLibXml2/Test/CMakeLists.txt
new file mode 100644
index 0000000..df5d8c3
--- /dev/null
+++ b/Tests/FindLibXml2/Test/CMakeLists.txt
@@ -0,0 +1,16 @@
+cmake_minimum_required(VERSION 3.4)
+project(TestFindLibXml2 C)
+include(CTest)
+
+find_package(LibXml2 REQUIRED)
+
+add_definitions(-DCMAKE_EXPECTED_LibXml2_VERSION="${LIBXML2_VERSION_STRING}")
+
+add_executable(test_tgt main.c)
+target_link_libraries(test_tgt LibXml2::LibXml2)
+add_test(NAME test_tgt COMMAND test_tgt)
+
+add_executable(test_var main.c)
+target_include_directories(test_var PRIVATE ${LIBXML2_INCLUDE_DIRS})
+target_link_libraries(test_var PRIVATE ${LIBXML2_LIBRARIES})
+add_test(NAME test_var COMMAND test_var)
diff --git a/Tests/FindLibXml2/Test/main.c b/Tests/FindLibXml2/Test/main.c
new file mode 100644
index 0000000..264f07d
--- /dev/null
+++ b/Tests/FindLibXml2/Test/main.c
@@ -0,0 +1,19 @@
+#include <assert.h>
+#include <libxml/tree.h>
+#include <string.h>
+
+int main()
+{
+ xmlDoc* doc;
+
+ xmlInitParser();
+
+ doc = xmlNewDoc(BAD_CAST "1.0");
+ xmlFreeDoc(doc);
+
+ assert(strstr(CMAKE_EXPECTED_LibXml2_VERSION, LIBXML_DOTTED_VERSION));
+
+ xmlCleanupParser();
+
+ return 0;
+}
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index 19d12e5..3d08704 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -57,6 +57,11 @@ add_custom_target(check-part1 ALL
-Dtest_strequal_angle_r_comma=$<STREQUAL:$<ANGLE-R>,$<COMMA>>
-Dtest_strequal_both_empty=$<STREQUAL:,>
-Dtest_strequal_one_empty=$<STREQUAL:something,>
+ -Dtest_inlist_true=$<IN_LIST:a,a$<SEMICOLON>b>
+ -Dtest_inlist_false=$<IN_LIST:c,a$<SEMICOLON>b>
+ -Dtest_inlist_empty_1=$<IN_LIST:a,>
+ -Dtest_inlist_empty_2=$<IN_LIST:,a>
+ -Dtest_inlist_empty_3=$<IN_LIST:,>
-Dtest_angle_r=$<ANGLE-R>
-Dtest_comma=$<COMMA>
-Dtest_semicolon=$<SEMICOLON>
diff --git a/Tests/GeneratorExpression/check-part1.cmake b/Tests/GeneratorExpression/check-part1.cmake
index 60b193f..41bcd6d 100644
--- a/Tests/GeneratorExpression/check-part1.cmake
+++ b/Tests/GeneratorExpression/check-part1.cmake
@@ -49,6 +49,11 @@ check(test_strequal_semicolon "1")
check(test_strequal_angle_r_comma "0")
check(test_strequal_both_empty "1")
check(test_strequal_one_empty "0")
+check(test_inlist_true "1")
+check(test_inlist_false "0")
+check(test_inlist_empty_1 "0")
+check(test_inlist_empty_2 "0")
+check(test_inlist_empty_3 "0")
check(test_angle_r ">")
check(test_comma ",")
check(test_semicolon ";")
diff --git a/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt b/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt
index 2e6a5bd..f9c52b7 100644
--- a/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt
+++ b/Tests/QtAutogen/RerunRccDepends/CMakeLists.txt
@@ -45,8 +45,7 @@ file(TIMESTAMP "${rccDepBinGen}" rdGenBefore "${timeformat}")
# - Change a resource files listed in the .qrc file
# - Rebuild
execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
-execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resPlain/input.txt")
-execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resGen/input.txt")
+file(TOUCH "${rccDepBD}/resPlain/input.txt" "${rccDepBD}/resGen/input.txt")
execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${rccDepBD}" RESULT_VARIABLE result)
if (result)
message(SEND_ERROR "Second build of rccDepends failed.")
@@ -97,8 +96,7 @@ file(TIMESTAMP "${rccDepBinGen}" rdGenBefore "${timeformat}")
# - Change a newly added resource files listed in the .qrc file
# - Rebuild
execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
-execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resPlain/inputAdded.txt")
-execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${rccDepBD}/resGen/inputAdded.txt")
+file(TOUCH "${rccDepBD}/resPlain/inputAdded.txt" "${rccDepBD}/resGen/inputAdded.txt")
execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${rccDepBD}" RESULT_VARIABLE result)
if (result)
message(SEND_ERROR "Fourth build of rccDepends failed.")
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index d5bd297..ce80c13 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -188,6 +188,7 @@ if (QT4_FOUND)
endif()
add_RunCMake_test(CompatibleInterface)
add_RunCMake_test(Syntax)
+add_RunCMake_test(WorkingDirectory)
add_RunCMake_test(add_custom_command)
add_RunCMake_test(add_custom_target)
@@ -339,6 +340,9 @@ add_RunCMake_test(CPackConfig)
add_RunCMake_test(CPackInstallProperties)
add_RunCMake_test(ExternalProject)
add_RunCMake_test(FetchContent)
+if(NOT CMake_TEST_EXTERNAL_CMAKE)
+ set(CTestCommandLine_ARGS -DTEST_AFFINITY=$<TARGET_FILE:testAffinity>)
+endif()
add_RunCMake_test(CTestCommandLine)
add_RunCMake_test(CacheNewline)
# Only run this test on unix platforms that support
@@ -358,6 +362,11 @@ if(CMake_TEST_FindMatlab)
add_RunCMake_test(FindMatlab)
endif()
+# UseSWIG related tests
+if(CMake_TEST_UseSWIG)
+ add_RunCMake_test(UseSWIG)
+endif()
+
add_executable(pseudo_emulator pseudo_emulator.c)
add_executable(pseudo_emulator_custom_command pseudo_emulator_custom_command.c)
add_RunCMake_test(CrosscompilingEmulator
diff --git a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
index 0fafea5..3033c9c 100644
--- a/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CTestCommandLine/RunCMakeTest.cmake
@@ -141,3 +141,23 @@ function(run_TestOutputSize)
)
endfunction()
run_TestOutputSize()
+
+function(run_TestAffinity)
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/TestAffinity)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ # Create a test with affinity enabled. The default PROCESSORS
+ # value is 1, so our expected output checks that this is the
+ # number of processors in the mask.
+ file(WRITE "${RunCMake_TEST_BINARY_DIR}/CTestTestfile.cmake" "
+ add_test(Affinity \"${TEST_AFFINITY}\")
+ set_tests_properties(Affinity PROPERTIES PROCESSOR_AFFINITY ON)
+")
+ # Run ctest with a large parallel level so that the value is
+ # not responsible for capping the number of processors available.
+ run_cmake_command(TestAffinity ${CMAKE_CTEST_COMMAND} -V -j 64)
+endfunction()
+if(TEST_AFFINITY)
+ run_TestAffinity()
+endif()
diff --git a/Tests/RunCMake/CTestCommandLine/TestAffinity-stdout.txt b/Tests/RunCMake/CTestCommandLine/TestAffinity-stdout.txt
new file mode 100644
index 0000000..e23d30b
--- /dev/null
+++ b/Tests/RunCMake/CTestCommandLine/TestAffinity-stdout.txt
@@ -0,0 +1 @@
+1: CPU affinity (mask count is '1'|not supported on this platform)\.
diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
index 2486259..f9a5cae 100644
--- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
@@ -34,6 +34,10 @@ run_cmake(OUTPUT_NAME-recursion)
run_cmake(TARGET_PROPERTY-LOCATION)
run_cmake(TARGET_PROPERTY-SOURCES)
run_cmake(LINK_ONLY-not-linking)
+run_cmake(TARGET_EXISTS-no-arg)
+run_cmake(TARGET_EXISTS-empty-arg)
+run_cmake(TARGET_EXISTS)
+run_cmake(TARGET_EXISTS-not-a-target)
run_cmake(ImportedTarget-TARGET_BUNDLE_DIR)
run_cmake(ImportedTarget-TARGET_BUNDLE_CONTENT_DIR)
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-check.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-check.cmake
new file mode 100644
index 0000000..c4c3a51
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-check.cmake
@@ -0,0 +1,6 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_EXISTS-generated.txt" content)
+
+set(expected "1")
+if(NOT content STREQUAL expected)
+ set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
+endif()
diff --git a/Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-result.txt b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-result.txt
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg-result.txt
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg-stderr.txt b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg-stderr.txt
new file mode 100644
index 0000000..1df6e28
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at TARGET_EXISTS-empty-arg.cmake:2 \(file\):
+ Error evaluating generator expression:
+
+ \$<TARGET_EXISTS:>
+
+ \$<TARGET_EXISTS:tgt> expression requires a non-empty valid target name.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg.cmake
new file mode 100644
index 0000000..e387abc
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-empty-arg.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_EXISTS-generated.txt CONTENT "$<TARGET_EXISTS:${empty}>")
diff --git a/Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/ObjectLibrary/ObjWithObj-result.txt
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg-result.txt
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg-stderr.txt b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg-stderr.txt
new file mode 100644
index 0000000..69e6130
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error at TARGET_EXISTS-no-arg.cmake:2 \(file\):
+ Error evaluating generator expression:
+
+ \$<TARGET_EXISTS>
+
+ \$<TARGET_EXISTS> expression requires exactly one parameter.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg.cmake
new file mode 100644
index 0000000..0a5ce32
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-no-arg.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_EXISTS-generated.txt CONTENT "$<TARGET_EXISTS>")
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-not-a-target-check.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-not-a-target-check.cmake
new file mode 100644
index 0000000..35ba267
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-not-a-target-check.cmake
@@ -0,0 +1,6 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/TARGET_EXISTS-not-a-target-generated.txt" content)
+
+set(expected "0")
+if(NOT content STREQUAL expected)
+ set(RunCMake_TEST_FAILED "actual content:\n [[${content}]]\nbut expected:\n [[${expected}]]")
+endif()
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-not-a-target.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-not-a-target.cmake
new file mode 100644
index 0000000..d8a8d3e
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS-not-a-target.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0070 NEW)
+file(GENERATE OUTPUT TARGET_EXISTS-not-a-target-generated.txt CONTENT "$<TARGET_EXISTS:just-random-string>")
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS.cmake
new file mode 100644
index 0000000..9a83b34
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_EXISTS.cmake
@@ -0,0 +1,3 @@
+cmake_policy(SET CMP0070 NEW)
+add_custom_target(foo)
+file(GENERATE OUTPUT TARGET_EXISTS-generated.txt CONTENT "$<TARGET_EXISTS:foo>")
diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt
deleted file mode 100644
index b91ffd0..0000000
--- a/Tests/RunCMake/ObjectLibrary/BadObjSource2-stderr.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-CMake Error at BadObjSource2.cmake:1 \(add_library\):
- OBJECT library "A" contains:
-
- bad.obj
-
- but may contain only sources that compile, header files, and other files
- that would not affect linking of a normal library.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/CMakeLists.txt b/Tests/RunCMake/ObjectLibrary/CMakeLists.txt
index a17c8cd..d1b0d2c 100644
--- a/Tests/RunCMake/ObjectLibrary/CMakeLists.txt
+++ b/Tests/RunCMake/ObjectLibrary/CMakeLists.txt
@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8.4)
+cmake_minimum_required(VERSION 3.10)
project(${RunCMake_TEST} C)
include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt b/Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt
deleted file mode 100644
index 5420159..0000000
--- a/Tests/RunCMake/ObjectLibrary/ExportNotSupported-stderr.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-CMake Error at ExportNotSupported.cmake:[0-9]+ \(export\):
- export given OBJECT library "A" which may not be exported under Xcode with
- multiple architectures.
-Call Stack \(most recent call first\):
- CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake b/Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake
deleted file mode 100644
index a3f104e..0000000
--- a/Tests/RunCMake/ObjectLibrary/ExportNotSupported.cmake
+++ /dev/null
@@ -1,2 +0,0 @@
-add_library(A OBJECT a.c)
-export(TARGETS A FILE AExport.cmake)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt b/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-result.txt
+++ b/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-result.txt
diff --git a/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-stderr.txt b/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-stderr.txt
new file mode 100644
index 0000000..f2f0f94
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1-stderr.txt
@@ -0,0 +1 @@
+CMake Error: install\(EXPORT "exp" ...\) includes target "UseA" which requires target "A" that is not in the export set.
diff --git a/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1.cmake b/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1.cmake
new file mode 100644
index 0000000..9e24609
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/InstallLinkedObj1.cmake
@@ -0,0 +1,6 @@
+add_library(A OBJECT a.c)
+add_library(UseA STATIC)
+target_link_libraries(UseA PUBLIC A)
+
+install(TARGETS UseA EXPORT exp ARCHIVE DESTINATION lib)
+install(EXPORT exp DESTINATION lib/cmake/exp)
diff --git a/Tests/RunCMake/ObjectLibrary/InstallLinkedObj2.cmake b/Tests/RunCMake/ObjectLibrary/InstallLinkedObj2.cmake
new file mode 100644
index 0000000..cdda962
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/InstallLinkedObj2.cmake
@@ -0,0 +1,6 @@
+add_library(A OBJECT a.c)
+add_library(UseA STATIC)
+target_link_libraries(UseA PUBLIC A)
+
+install(TARGETS UseA A EXPORT exp ARCHIVE DESTINATION lib)
+install(EXPORT exp DESTINATION lib/cmake/exp)
diff --git a/Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt b/Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt
index 35a0e4f..a7004c1 100644
--- a/Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt
+++ b/Tests/RunCMake/ObjectLibrary/InstallNotSupported-stderr.txt
@@ -1,5 +1,5 @@
CMake Error at InstallNotSupported.cmake:[0-9]+ \(install\):
- install TARGETS given OBJECT library "A" which may not be installed under
- Xcode with multiple architectures.
+ install TARGETS given OBJECT library "A" whose objects may not be installed
+ under Xcode with multiple architectures.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt b/Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt
deleted file mode 100644
index 90e828b..0000000
--- a/Tests/RunCMake/ObjectLibrary/LinkObjLHS-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-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
deleted file mode 100644
index 5d7831a..0000000
--- a/Tests/RunCMake/ObjectLibrary/LinkObjLHS.cmake
+++ /dev/null
@@ -1,2 +0,0 @@
-add_library(AnObjLib OBJECT a.c)
-target_link_libraries(AnObjLib OtherLib)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake
new file mode 100644
index 0000000..4aa7bba
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHSShared.cmake
@@ -0,0 +1,7 @@
+project(LinkObjLHSShared C)
+
+add_library(OtherLib SHARED a.c)
+target_compile_definitions(OtherLib INTERFACE REQUIRED)
+
+add_library(AnObjLib OBJECT requires.c)
+target_link_libraries(AnObjLib OtherLib)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHSStatic.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjLHSStatic.cmake
new file mode 100644
index 0000000..261bee7
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjLHSStatic.cmake
@@ -0,0 +1,7 @@
+project(LinkObjLHSStatic C)
+
+add_library(OtherLib STATIC a.c)
+target_compile_definitions(OtherLib INTERFACE REQUIRED)
+
+add_library(AnObjLib OBJECT requires.c)
+target_link_libraries(AnObjLib OtherLib)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt
deleted file mode 100644
index d5ee4f9..0000000
--- a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-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 INTERFACE, 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
deleted file mode 100644
index 113d6a8..0000000
--- a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-add_library(A STATIC a.c)
-add_library(AnObjLib OBJECT a.c)
-target_link_libraries(A AnObjLib)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt
deleted file mode 100644
index 3295fca..0000000
--- a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2-stderr.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-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
deleted file mode 100644
index 6163729..0000000
--- a/Tests/RunCMake/ObjectLibrary/LinkObjRHS2.cmake
+++ /dev/null
@@ -1,3 +0,0 @@
-add_library(A SHARED a.c)
-target_link_libraries(A AnObjLib)
-add_library(AnObjLib OBJECT a.c)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject-build-result.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject-build-result.txt
new file mode 100644
index 0000000..e27f06b
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject-build-result.txt
@@ -0,0 +1 @@
+[1-9][0-9]*
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject-build-stdout.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject-build-stdout.txt
new file mode 100644
index 0000000..4eeb096
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject-build-stdout.txt
@@ -0,0 +1 @@
+REQUIRED needs to be defined
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject.cmake
new file mode 100644
index 0000000..db571a3
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject.cmake
@@ -0,0 +1,12 @@
+cmake_policy(SET CMP0022 NEW)
+
+enable_language(C)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+
+add_library(AnotherObjLib OBJECT b.c)
+target_link_libraries(AnotherObjLib PRIVATE AnObjLib)
+
+add_executable(exe exe.c)
+target_link_libraries(exe AnotherObjLib)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject2-build-result.txt b/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject2-build-result.txt
new file mode 100644
index 0000000..e27f06b
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject2-build-result.txt
@@ -0,0 +1 @@
+[1-9][0-9]*
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject2.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject2.cmake
new file mode 100644
index 0000000..6bb8d5e
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHSObject2.cmake
@@ -0,0 +1,12 @@
+cmake_policy(SET CMP0022 NEW)
+
+enable_language(C)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+
+add_library(AnotherObjLib OBJECT b.c)
+target_link_libraries(AnotherObjLib PUBLIC AnObjLib)
+
+add_executable(exe exe.c)
+target_link_libraries(exe AnotherObjLib)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHSShared.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjRHSShared.cmake
new file mode 100644
index 0000000..b9030b3
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHSShared.cmake
@@ -0,0 +1,13 @@
+enable_language(C)
+
+add_definitions(-DCOMPILE_FOR_SHARED_LIB)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+set_target_properties(AnObjLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
+
+add_library(A SHARED b.c $<TARGET_OBJECTS:AnObjLib>)
+target_link_libraries(A PUBLIC AnObjLib)
+
+add_executable(exe exe.c)
+target_link_libraries(exe A)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHSShared2.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjRHSShared2.cmake
new file mode 100644
index 0000000..e2e5fa2
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHSShared2.cmake
@@ -0,0 +1,14 @@
+enable_language(C)
+
+add_definitions(-DCOMPILE_FOR_SHARED_LIB)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+set_target_properties(AnObjLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
+
+add_library(A SHARED b.c)
+target_link_libraries(A PRIVATE AnObjLib)
+target_compile_definitions(A INTERFACE $<TARGET_PROPERTY:AnObjLib,INTERFACE_COMPILE_DEFINITIONS>)
+
+add_executable(exe exe.c)
+target_link_libraries(exe A)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHSStatic.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjRHSStatic.cmake
new file mode 100644
index 0000000..73fad06
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHSStatic.cmake
@@ -0,0 +1,10 @@
+enable_language(C)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+
+add_library(A STATIC b.c $<TARGET_OBJECTS:AnObjLib>)
+target_link_libraries(A PUBLIC AnObjLib)
+
+add_executable(exe exe.c)
+target_link_libraries(exe A)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHSStatic2.cmake b/Tests/RunCMake/ObjectLibrary/LinkObjRHSStatic2.cmake
new file mode 100644
index 0000000..9e1ab6d
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/LinkObjRHSStatic2.cmake
@@ -0,0 +1,11 @@
+enable_language(C)
+
+add_library(AnObjLib OBJECT a.c)
+target_compile_definitions(AnObjLib INTERFACE REQUIRED)
+
+add_library(A STATIC b.c)
+target_link_libraries(A PRIVATE AnObjLib)
+target_compile_definitions(A INTERFACE $<TARGET_PROPERTY:AnObjLib,INTERFACE_COMPILE_DEFINITIONS>)
+
+add_executable(exe exe.c)
+target_link_libraries(exe A)
diff --git a/Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt b/Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt
deleted file mode 100644
index d67b4ae..0000000
--- a/Tests/RunCMake/ObjectLibrary/ObjWithObj-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-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/RunCMakeTest.cmake b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
index b8eed73..c73732f 100644
--- a/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
+++ b/Tests/RunCMake/ObjectLibrary/RunCMakeTest.cmake
@@ -6,17 +6,46 @@ run_cmake(BadSourceExpression3)
run_cmake(BadObjSource1)
run_cmake(BadObjSource2)
if(RunCMake_GENERATOR STREQUAL "Xcode" AND "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]")
- run_cmake(ExportNotSupported)
run_cmake(ImportNotSupported)
run_cmake(InstallNotSupported)
else()
- run_cmake(Export)
run_cmake(Import)
run_cmake(Install)
+ run_cmake(InstallLinkedObj1)
+ run_cmake(InstallLinkedObj2)
endif()
-run_cmake(LinkObjLHS)
-run_cmake(LinkObjRHS1)
-run_cmake(LinkObjRHS2)
+run_cmake(Export)
+
+function (run_object_lib_build name)
+ # Use a single build tree for a few tests without cleaning.
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(${name})
+ run_cmake_command(${name}-build ${CMAKE_COMMAND} --build .)
+endfunction ()
+
+function (run_object_lib_build2 name)
+ # Use a single build tree for a few tests without cleaning.
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(${name})
+ set(RunCMake_TEST_OUTPUT_MERGE 1)
+ run_cmake_command(${name}-build ${CMAKE_COMMAND} --build .)
+endfunction ()
+
+run_object_lib_build(LinkObjLHSShared)
+run_object_lib_build(LinkObjLHSStatic)
+run_object_lib_build(LinkObjRHSShared)
+run_object_lib_build(LinkObjRHSStatic)
+run_object_lib_build2(LinkObjRHSObject)
+run_object_lib_build(LinkObjRHSShared2)
+run_object_lib_build(LinkObjRHSStatic2)
+run_object_lib_build2(LinkObjRHSObject2)
+
run_cmake(MissingSource)
run_cmake(ObjWithObj)
run_cmake(OwnSources)
diff --git a/Tests/RunCMake/ObjectLibrary/a.c b/Tests/RunCMake/ObjectLibrary/a.c
index 1636303..5beb3f1 100644
--- a/Tests/RunCMake/ObjectLibrary/a.c
+++ b/Tests/RunCMake/ObjectLibrary/a.c
@@ -1,4 +1,10 @@
-int a(void)
+#if defined(_WIN32) && defined(COMPILE_FOR_SHARED_LIB)
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT
+#endif
+
+EXPORT int a(void)
{
return 0;
}
diff --git a/Tests/RunCMake/ObjectLibrary/b.c b/Tests/RunCMake/ObjectLibrary/b.c
index 6751907..7549abf 100644
--- a/Tests/RunCMake/ObjectLibrary/b.c
+++ b/Tests/RunCMake/ObjectLibrary/b.c
@@ -1,4 +1,14 @@
-int b(void)
+#if defined(_WIN32) && defined(COMPILE_FOR_SHARED_LIB)
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT
+#endif
+
+extern int a(void);
+EXPORT int b()
{
- return 0;
+ return a();
}
+#ifndef REQUIRED
+#error "REQUIRED needs to be defined"
+#endif
diff --git a/Tests/RunCMake/ObjectLibrary/exe.c b/Tests/RunCMake/ObjectLibrary/exe.c
new file mode 100644
index 0000000..6efdae7
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/exe.c
@@ -0,0 +1,14 @@
+#if defined(_WIN32) && defined(COMPILE_FOR_SHARED_LIB)
+#define IMPORT __declspec(dllimport)
+#else
+#define IMPORT
+#endif
+
+extern IMPORT int b(void);
+int main()
+{
+ return b();
+}
+#ifndef REQUIRED
+#error "REQUIRED needs to be defined"
+#endif
diff --git a/Tests/RunCMake/ObjectLibrary/requires.c b/Tests/RunCMake/ObjectLibrary/requires.c
new file mode 100644
index 0000000..d524952
--- /dev/null
+++ b/Tests/RunCMake/ObjectLibrary/requires.c
@@ -0,0 +1,8 @@
+#ifdef REQUIRED
+int required()
+{
+ return 0;
+}
+#else
+#error "REQUIRED not defined"
+#endif
diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index e688830..36a122f 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -112,6 +112,8 @@ function(run_cmake test)
"|clang[^:]*: warning: the object size sanitizer has no effect at -O0, but is explicitly enabled:"
"|Error kstat returned"
"|Hit xcodebuild bug"
+ "|ld: 0711-224 WARNING: Duplicate symbol: .__init_aix_libgcc_cxa_atexit"
+ "|ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information"
"|[^\n]*is a member of multiple groups"
"|[^\n]*from Time Machine by path"
"|[^\n]*Bullseye Testing Technology"
diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
index 8d5139d..5af6fcd 100644
--- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
+++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt
@@ -23,6 +23,7 @@
\* CMP0065
\* CMP0068
\* CMP0069
+ \* CMP0073
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/UseSWIG/BasicConfiguration.cmake b/Tests/RunCMake/UseSWIG/BasicConfiguration.cmake
new file mode 100644
index 0000000..94d8dd3
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/BasicConfiguration.cmake
@@ -0,0 +1,68 @@
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+unset(SWIG_LANG_TYPE)
+unset(SWIG_LANG_INCLUDE_DIRECTORIES)
+unset(SWIG_LANG_DEFINITIONS)
+unset(SWIG_LANG_OPTIONS)
+unset(SWIG_LANG_LIBRARIES)
+
+if(${language} MATCHES python)
+ find_package(PythonInterp REQUIRED)
+ find_package(PythonLibs REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_PATH})
+ set(SWIG_LANG_LIBRARIES ${PYTHON_LIBRARIES})
+endif()
+if(${language} MATCHES perl)
+ find_package(Perl REQUIRED)
+ find_package(PerlLibs REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${PERL_INCLUDE_PATH})
+ separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}")
+ set(SWIG_LANG_OPTIONS ${c_flags})
+ set(SWIG_LANG_LIBRARIES ${PERL_LIBRARY})
+endif()
+if(${language} MATCHES tcl)
+ find_package(TCL REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${TCL_INCLUDE_PATH})
+ set(SWIG_LANG_LIBRARIES ${TCL_LIBRARY})
+endif()
+if(${language} MATCHES ruby)
+ find_package(Ruby REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${RUBY_INCLUDE_PATH})
+ set(SWIG_LANG_LIBRARIES ${RUBY_LIBRARY})
+endif()
+if(${language} MATCHES php4)
+ find_package(PHP4 REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${PHP4_INCLUDE_PATH})
+ set(SWIG_LANG_LIBRARIES ${PHP4_LIBRARY})
+endif()
+if(${language} MATCHES pike)
+ find_package(Pike REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${PIKE_INCLUDE_PATH})
+ set(SWIG_LANG_LIBRARIES ${PIKE_LIBRARY})
+endif()
+if(${language} MATCHES lua)
+ find_package(Lua REQUIRED)
+ set(SWIG_LANG_INCLUDE_DIRECTORIES ${LUA_INCLUDE_DIR})
+ set(SWIG_LANG_TYPE TYPE SHARED)
+ set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES})
+endif()
+
+unset(CMAKE_SWIG_FLAGS)
+
+set (CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set_property(SOURCE example.i PROPERTY CPLUSPLUS ON)
+set_property(SOURCE example.i PROPERTY COMPILE_OPTIONS -includeall)
+
+set_property(SOURCE example.i PROPERTY GENERATED_INCLUDE_DIRECTORIES ${SWIG_LANG_INCLUDE_DIRECTORIES})
+set_property(SOURCE example.i PROPERTY GENERATED_COMPILE_DEFINITIONS ${SWIG_LANG_DEFINITIONS})
+set_property(SOURCE example.i PROPERTY GENERATED_COMPILE_OPTIONS ${SWIG_LANG_OPTIONS})
+
+
+SWIG_ADD_LIBRARY(example
+ LANGUAGE "${language}"
+ ${SWIG_LANG_TYPE}
+ SOURCES example.i example.cxx)
+TARGET_LINK_LIBRARIES(example PRIVATE ${SWIG_LANG_LIBRARIES})
diff --git a/Tests/RunCMake/UseSWIG/BasicPerl.cmake b/Tests/RunCMake/UseSWIG/BasicPerl.cmake
new file mode 100644
index 0000000..67ad6bc
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/BasicPerl.cmake
@@ -0,0 +1,18 @@
+
+set(language "perl")
+
+include (BasicConfiguration.cmake)
+
+if (WIN32)
+ file (TO_CMAKE_PATH "$ENV{PATH}" perl_path)
+ string (REPLACE ";" "$<SEMICOLON>" perl_path "${perl_path}")
+ set (perl_env "PATH=$<TARGET_FILE_DIR:example>$<SEMICOLON>${perl_path}")
+else()
+ set (perl_env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:example>")
+endif()
+
+add_custom_target (RunTest
+ COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}"
+ "${PERL_EXECUTABLE}" "-I$<TARGET_FILE_DIR:example>"
+ "${CMAKE_CURRENT_SOURCE_DIR}/runme.pl"
+ DEPENDS example)
diff --git a/Tests/RunCMake/UseSWIG/BasicPython.cmake b/Tests/RunCMake/UseSWIG/BasicPython.cmake
new file mode 100644
index 0000000..0d8c824
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/BasicPython.cmake
@@ -0,0 +1,9 @@
+
+set(language "python")
+
+include (BasicConfiguration.cmake)
+
+add_custom_target (RunTest
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:example>"
+ "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runme.py"
+ DEPENDS example)
diff --git a/Tests/RunCMake/UseSWIG/CMakeLists.txt b/Tests/RunCMake/UseSWIG/CMakeLists.txt
new file mode 100644
index 0000000..f452db1
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8.4)
+project(${RunCMake_TEST} CXX)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/SwigTest/CMakeLists.txt b/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake
index 65f5c93..3ce0790 100644
--- a/Tests/SwigTest/CMakeLists.txt
+++ b/Tests/RunCMake/UseSWIG/LegacyConfiguration.cmake
@@ -1,54 +1,55 @@
-set(language "python")
-cmake_minimum_required (VERSION 2.6)
-
-project(example_${language}_class)
+# Prevent deprecated warnings from new UseSWIG module
+set (CMAKE_WARN_DEPRECATED FALSE)
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})
unset(SWIG_LANG_TYPE)
if(${language} MATCHES python)
- find_package(PythonLibs)
+ find_package(PythonInterp REQUIRED)
+ find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_PATH})
set(SWIG_LANG_LIBRARIES ${PYTHON_LIBRARIES})
endif()
if(${language} MATCHES perl)
- find_package(PerlLibs)
+ find_package(Perl REQUIRED)
+ find_package(PerlLibs REQUIRED)
include_directories(${PERL_INCLUDE_PATH})
- add_definitions(${PERL_EXTRA_C_FLAGS})
+ separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}")
+ add_compile_options(${c_flags})
set(SWIG_LANG_LIBRARIES ${PERL_LIBRARY})
endif()
if(${language} MATCHES tcl)
- find_package(TCL)
+ find_package(TCL REQUIRED)
include_directories(${TCL_INCLUDE_PATH})
set(SWIG_LANG_LIBRARIES ${TCL_LIBRARY})
endif()
if(${language} MATCHES ruby)
- find_package(Ruby)
+ find_package(Ruby REQUIRED)
include_directories(${RUBY_INCLUDE_PATH})
set(SWIG_LANG_LIBRARIES ${RUBY_LIBRARY})
endif()
if(${language} MATCHES php4)
- find_package(PHP4)
+ find_package(PHP4 REQUIRED)
include_directories(${PHP4_INCLUDE_PATH})
set(SWIG_LANG_LIBRARIES ${PHP4_LIBRARY})
endif()
if(${language} MATCHES pike)
- find_package(Pike)
+ find_package(Pike REQUIRED)
include_directories(${PIKE_INCLUDE_PATH})
set(SWIG_LANG_LIBRARIES ${PIKE_LIBRARY})
endif()
if(${language} MATCHES lua)
- find_package(Lua)
+ find_package(Lua REQUIRED)
include_directories(${LUA_INCLUDE_DIR})
set(SWIG_LANG_TYPE TYPE SHARED)
set(SWIG_LANG_LIBRARIES ${LUA_LIBRARIES})
endif()
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+unset(CMAKE_SWIG_FLAGS)
-set(CMAKE_SWIG_FLAGS "")
+include_directories(${CMAKE_CURRENT_LIST_DIR})
set_source_files_properties(example.i PROPERTIES CPLUSPLUS ON)
set_source_files_properties(example.i PROPERTIES SWIG_FLAGS "-includeall")
diff --git a/Tests/RunCMake/UseSWIG/LegacyPerl.cmake b/Tests/RunCMake/UseSWIG/LegacyPerl.cmake
new file mode 100644
index 0000000..3428c46
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/LegacyPerl.cmake
@@ -0,0 +1,18 @@
+
+set(language "perl")
+
+include (LegacyConfiguration.cmake)
+
+if (WIN32)
+ file (TO_CMAKE_PATH "$ENV{PATH}" perl_path)
+ string (REPLACE ";" "$<SEMICOLON>" perl_path "${perl_path}")
+ set (perl_env "PATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>$<SEMICOLON>${perl_path}")
+else()
+ set (perl_env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>")
+endif()
+
+add_custom_target (RunTest
+ COMMAND "${CMAKE_COMMAND}" -E env "${perl_env}"
+ "${PERL_EXECUTABLE}" "-I$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>"
+ "${CMAKE_CURRENT_SOURCE_DIR}/runme.pl"
+ DEPENDS ${SWIG_MODULE_example_REAL_NAME})
diff --git a/Tests/RunCMake/UseSWIG/LegacyPython.cmake b/Tests/RunCMake/UseSWIG/LegacyPython.cmake
new file mode 100644
index 0000000..8b47aa2
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/LegacyPython.cmake
@@ -0,0 +1,9 @@
+
+set(language "python")
+
+include (LegacyConfiguration.cmake)
+
+add_custom_target (RunTest
+ COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:${SWIG_MODULE_example_REAL_NAME}>"
+ "${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/runme.py"
+ DEPENDS ${SWIG_MODULE_example_REAL_NAME})
diff --git a/Tests/RunCMake/UseSWIG/MultipleModules.cmake b/Tests/RunCMake/UseSWIG/MultipleModules.cmake
new file mode 100644
index 0000000..e3d579f
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/MultipleModules.cmake
@@ -0,0 +1,30 @@
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+find_package(PythonLibs REQUIRED)
+find_package(PerlLibs REQUIRED)
+
+unset(CMAKE_SWIG_FLAGS)
+
+set (CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set_property(SOURCE example.i PROPERTY CPLUSPLUS ON)
+set_property(SOURCE example.i PROPERTY COMPILE_OPTIONS -includeall)
+
+set_property(SOURCE example.i PROPERTY GENERATED_INCLUDE_DIRECTORIES ${PYTHON_INCLUDE_PATH})
+
+swig_add_library(example1
+ LANGUAGE python
+ SOURCES example.i example.cxx)
+target_link_libraries(example1 PRIVATE ${PYTHON_LIBRARIES})
+
+# re-use sample interface file for another plugin
+set_property(SOURCE example.i PROPERTY GENERATED_INCLUDE_DIRECTORIES ${PERL_INCLUDE_PATH})
+separate_arguments(c_flags UNIX_COMMAND "${PERL_EXTRA_C_FLAGS}")
+set_property(SOURCE example.i PROPERTY GENERATED_COMPILE_OPTIONS ${c_flags})
+
+swig_add_library(example2
+ LANGUAGE perl
+ SOURCES example.i example.cxx)
+target_link_libraries(example2 PRIVATE ${PERL_LIBRARY})
diff --git a/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake
new file mode 100644
index 0000000..c63ff2e
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/RunCMakeTest.cmake
@@ -0,0 +1,23 @@
+include(RunCMake)
+
+function(run_SWIG test)
+ cmake_parse_arguments(_SWIG_TEST "" "TARGET" "" ${ARGN})
+ if (_SWIG_TEST_TARGET)
+ list (INSERT _SWIG_TEST_TARGET 0 --target)
+ endif()
+
+ set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
+ set(RunCMake_TEST_NO_CLEAN 1)
+ file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+ run_cmake(${test})
+ run_cmake_command(${test}-test ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} ${_SWIG_TEST_TARGET})
+endfunction()
+
+run_SWIG(LegacyPython TARGET RunTest)
+run_SWIG(LegacyPerl TARGET RunTest)
+
+run_SWIG(BasicPython TARGET RunTest)
+run_SWIG(BasicPerl TARGET RunTest)
+
+run_SWIG(MultipleModules)
diff --git a/Tests/SwigTest/example.cxx b/Tests/RunCMake/UseSWIG/example.cxx
index 961d6dd..961d6dd 100644
--- a/Tests/SwigTest/example.cxx
+++ b/Tests/RunCMake/UseSWIG/example.cxx
diff --git a/Tests/SwigTest/example.h b/Tests/RunCMake/UseSWIG/example.h
index 366deb0..366deb0 100644
--- a/Tests/SwigTest/example.h
+++ b/Tests/RunCMake/UseSWIG/example.h
diff --git a/Tests/SwigTest/example.i b/Tests/RunCMake/UseSWIG/example.i
index 75700b3..fbdf724 100644
--- a/Tests/SwigTest/example.i
+++ b/Tests/RunCMake/UseSWIG/example.i
@@ -7,4 +7,3 @@
/* Let's just grab the original header file here */
%include "example.h"
-
diff --git a/Tests/SwigTest/runme.php4 b/Tests/RunCMake/UseSWIG/runme.php4
index 653ced2..653ced2 100644
--- a/Tests/SwigTest/runme.php4
+++ b/Tests/RunCMake/UseSWIG/runme.php4
diff --git a/Tests/SwigTest/runme.pike b/Tests/RunCMake/UseSWIG/runme.pike
index ec28dd7..ec28dd7 100755..100644
--- a/Tests/SwigTest/runme.pike
+++ b/Tests/RunCMake/UseSWIG/runme.pike
diff --git a/Tests/SwigTest/runme.pl b/Tests/RunCMake/UseSWIG/runme.pl
index 5bfb3d8..965e063 100644
--- a/Tests/SwigTest/runme.pl
+++ b/Tests/RunCMake/UseSWIG/runme.pl
@@ -54,4 +54,3 @@ examplec::delete_Shape($s);
print $examplec::Shape_nshapes," shapes remain\n";
print "Goodbye\n";
-
diff --git a/Tests/RunCMake/UseSWIG/runme.py b/Tests/RunCMake/UseSWIG/runme.py
new file mode 100644
index 0000000..af5e07d
--- /dev/null
+++ b/Tests/RunCMake/UseSWIG/runme.py
@@ -0,0 +1,52 @@
+# file: runme.py
+
+# This file illustrates the shadow-class C++ interface generated
+# by SWIG.
+
+from __future__ import print_function
+
+import example
+
+# ----- Object creation -----
+
+print ("Creating some objects:")
+c = example.Circle(10)
+print (" Created circle", c)
+s = example.Square(10)
+print (" Created square", s)
+
+# ----- Access a static member -----
+
+print ("\nA total of", example.cvar.Shape_nshapes,"shapes were created")
+
+# ----- Member data access -----
+
+# Set the location of the object
+
+c.x = 20
+c.y = 30
+
+s.x = -10
+s.y = 5
+
+print ("\nHere is their current position:")
+print (" Circle = (%f, %f)" % (c.x,c.y))
+print (" Square = (%f, %f)" % (s.x,s.y))
+
+# ----- Call some methods -----
+
+print ("\nHere are some properties of the shapes:")
+for o in [c,s]:
+ print (" ", o)
+ print (" area = ", o.area())
+ print (" perimeter = ", o.perimeter())
+
+print ("\nGuess I'll clean up now")
+
+# Note: this invokes the virtual destructor
+del c
+del s
+
+s = 3
+print (example.cvar.Shape_nshapes,"shapes remain")
+print ("Goodbye")
diff --git a/Tests/SwigTest/runme.rb b/Tests/RunCMake/UseSWIG/runme.rb
index de73bcd..de73bcd 100644
--- a/Tests/SwigTest/runme.rb
+++ b/Tests/RunCMake/UseSWIG/runme.rb
diff --git a/Tests/SwigTest/runme.tcl b/Tests/RunCMake/UseSWIG/runme.tcl
index c7f4725..6055cf6 100644
--- a/Tests/SwigTest/runme.tcl
+++ b/Tests/RunCMake/UseSWIG/runme.tcl
@@ -47,4 +47,3 @@ rename s ""
puts "$Shape_nshapes shapes remain"
puts "Goodbye"
-
diff --git a/Tests/SwigTest/runme2.tcl b/Tests/RunCMake/UseSWIG/runme2.tcl
index 88ec2f6..d0b5c21 100644
--- a/Tests/SwigTest/runme2.tcl
+++ b/Tests/RunCMake/UseSWIG/runme2.tcl
@@ -67,4 +67,3 @@ delete_Shape $s
puts "$Shape_nshapes shapes remain"
puts "Goodbye"
-
diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
index 7100b31..afe9d6d 100644
--- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake
@@ -3,6 +3,7 @@ run_cmake(VsConfigurationType)
run_cmake(VsTargetsFileReferences)
run_cmake(VsCustomProps)
run_cmake(VsDebuggerWorkingDir)
+run_cmake(VsDebuggerCommand)
run_cmake(VsCSharpCustomTags)
run_cmake(VsCSharpReferenceProps)
run_cmake(VsCSharpWithoutSources)
diff --git a/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake b/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake
index 45766a0..96be54b 100644
--- a/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake
+++ b/Tests/RunCMake/VS10Project/VsCSharpCustomTags.cmake
@@ -16,8 +16,7 @@ set(fileNames)
foreach(e ${fileExtensions})
set(currentFile "${CMAKE_CURRENT_BINARY_DIR}/foo.${e}")
list(APPEND fileNames ${currentFile})
- execute_process(COMMAND ${CMAKE_COMMAND} -E touch
- "${currentFile}")
+ file(TOUCH "${currentFile}")
string(TOUPPER ${e} eUC)
set_source_files_properties("${currentFile}"
PROPERTIES
diff --git a/Tests/RunCMake/VS10Project/VsDebuggerCommand-check.cmake b/Tests/RunCMake/VS10Project/VsDebuggerCommand-check.cmake
new file mode 100644
index 0000000..0ded780
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsDebuggerCommand-check.cmake
@@ -0,0 +1,22 @@
+set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.vcxproj")
+if(NOT EXISTS "${vcProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${vcProjectFile} does not exist.")
+ return()
+endif()
+
+set(debuggerCommandSet FALSE)
+
+file(STRINGS "${vcProjectFile}" lines)
+foreach(line IN LISTS lines)
+ if(line MATCHES "^ *<LocalDebuggerCommand[^>]*>([^<>]+)</LocalDebuggerCommand>$")
+ if("${CMAKE_MATCH_1}" STREQUAL "my-debugger-command")
+ message(STATUS "foo.vcxproj has debugger command set")
+ set(debuggerCommandSet TRUE)
+ endif()
+ endif()
+endforeach()
+
+if(NOT debuggerCommandSet)
+ set(RunCMake_TEST_FAILED "LocalDebuggerCommand not found or not set correctly.")
+ return()
+endif()
diff --git a/Tests/RunCMake/VS10Project/VsDebuggerCommand.cmake b/Tests/RunCMake/VS10Project/VsDebuggerCommand.cmake
new file mode 100644
index 0000000..e29adc4
--- /dev/null
+++ b/Tests/RunCMake/VS10Project/VsDebuggerCommand.cmake
@@ -0,0 +1,5 @@
+enable_language(CXX)
+add_library(foo foo.cpp)
+
+set_target_properties(foo PROPERTIES
+ VS_DEBUGGER_COMMAND "my-debugger-command")
diff --git a/Tests/RunCMake/WorkingDirectory/CMakeLists.txt.in b/Tests/RunCMake/WorkingDirectory/CMakeLists.txt.in
new file mode 100644
index 0000000..46047b8
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/CMakeLists.txt.in
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.11)
+project(@CASE_NAME@ NONE)
+include("@RunCMake_SOURCE_DIR@/@CASE_NAME@.cmake")
diff --git a/Tests/RunCMake/WorkingDirectory/CTestConfig.cmake.in b/Tests/RunCMake/WorkingDirectory/CTestConfig.cmake.in
new file mode 100644
index 0000000..0226230
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/CTestConfig.cmake.in
@@ -0,0 +1 @@
+set(CTEST_PROJECT_NAME "CTestTestWorkingDir.@CASE_NAME@")
diff --git a/Tests/RunCMake/WorkingDirectory/RunCMakeTest.cmake b/Tests/RunCMake/WorkingDirectory/RunCMakeTest.cmake
new file mode 100644
index 0000000..a7685ae
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/RunCMakeTest.cmake
@@ -0,0 +1,9 @@
+include(RunCTest)
+
+run_ctest(dirNotExist)
+run_ctest(buildAndTestNoBuildDir
+ --build-and-test
+ ${RunCMake_BINARY_DIR}/buildAndTestNoBuildDir
+ ${RunCMake_BINARY_DIR}/buildAndTestNoBuildDir/CMakeLists.txt # Deliberately a file
+ --build-generator "${RunCMake_GENERATOR}"
+)
diff --git a/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-check.cmake b/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-check.cmake
new file mode 100644
index 0000000..fcfe461
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-check.cmake
@@ -0,0 +1,3 @@
+if(EXISTS ${RunCMake_TEST_BINARY_DIR}/CMakeCache.txt)
+ set(RunCMake_TEST_FAILED "Default build dir ${RunCMake_TEST_BINARY_DIR} was used, should not have been")
+endif()
diff --git a/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-result.txt b/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-result.txt
new file mode 100644
index 0000000..0617a38
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-result.txt
@@ -0,0 +1 @@
+^[^0][0-9]*$
diff --git a/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-stdout.txt b/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-stdout.txt
new file mode 100644
index 0000000..da89317
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir-stdout.txt
@@ -0,0 +1 @@
+Failed to change working directory to .*[/\\]buildAndTestNoBuildDir[/\\]CMakeLists.txt :
diff --git a/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir.cmake b/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir.cmake
new file mode 100644
index 0000000..ad795c4
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/buildAndTestNoBuildDir.cmake
@@ -0,0 +1,7 @@
+# We want a single test that always passes. We should never actually get to
+# configure with this file, so we use a successful configure-build-test
+# sequence to denote failure of the test case.
+include(CTest)
+add_test(NAME willPass
+ COMMAND ${CMAKE_COMMAND} -E touch someFile.txt
+)
diff --git a/Tests/RunCMake/WorkingDirectory/dirNotExist-result.txt b/Tests/RunCMake/WorkingDirectory/dirNotExist-result.txt
new file mode 100644
index 0000000..b57e2de
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/dirNotExist-result.txt
@@ -0,0 +1 @@
+(-1|255)
diff --git a/Tests/RunCMake/WorkingDirectory/dirNotExist-stderr.txt b/Tests/RunCMake/WorkingDirectory/dirNotExist-stderr.txt
new file mode 100644
index 0000000..3cea890
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/dirNotExist-stderr.txt
@@ -0,0 +1 @@
+Failed to change working directory to .*[/\\]dirNotExist-build[/\\]thisDirWillNotExist :
diff --git a/Tests/RunCMake/WorkingDirectory/dirNotExist-stdout.txt b/Tests/RunCMake/WorkingDirectory/dirNotExist-stdout.txt
new file mode 100644
index 0000000..58aa6e4
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/dirNotExist-stdout.txt
@@ -0,0 +1,10 @@
+Test project .*/Tests/RunCMake/WorkingDirectory/dirNotExist-build
+.* +Start 1: dirNotExist
+1/1 Test #1: dirNotExist +\.+\*\*\*Not Run +[0-9.]+ sec
++
+0% tests passed, 1 tests failed out of 1
++
+Total Test time \(real\) = +[0-9.]+ sec
++
+The following tests FAILED:
+.* +1 - dirNotExist \(Not Run\)$
diff --git a/Tests/RunCMake/WorkingDirectory/dirNotExist.cmake b/Tests/RunCMake/WorkingDirectory/dirNotExist.cmake
new file mode 100644
index 0000000..642386e
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/dirNotExist.cmake
@@ -0,0 +1,6 @@
+include(CTest)
+
+add_test(NAME dirNotExist
+ COMMAND ${CMAKE_COMMAND} -E touch someFile.txt
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/thisDirWillNotExist
+)
diff --git a/Tests/RunCMake/WorkingDirectory/test.cmake.in b/Tests/RunCMake/WorkingDirectory/test.cmake.in
new file mode 100644
index 0000000..8eccd79
--- /dev/null
+++ b/Tests/RunCMake/WorkingDirectory/test.cmake.in
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.11)
+
+set(CTEST_SITE "test-site")
+set(CTEST_BUILD_NAME "test-build-name")
+set(CTEST_SOURCE_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@")
+set(CTEST_BINARY_DIRECTORY "@RunCMake_BINARY_DIR@/@CASE_NAME@-build")
+set(CTEST_CMAKE_GENERATOR "@RunCMake_GENERATOR@")
+set(CTEST_CMAKE_GENERATOR_PLATFORM "@RunCMake_GENERATOR_PLATFORM@")
+set(CTEST_CMAKE_GENERATOR_TOOLSET "@RunCMake_GENERATOR_TOOLSET@")
+set(CTEST_BUILD_CONFIGURATION "$ENV{CMAKE_CONFIG_TYPE}")
+
+ctest_start(Experimental)
+ctest_configure()
+ctest_build()
+ctest_test()
diff --git a/Tests/RunCMake/add_library/CMP0073-stdout.txt b/Tests/RunCMake/add_library/CMP0073-stdout.txt
new file mode 100644
index 0000000..84645b8
--- /dev/null
+++ b/Tests/RunCMake/add_library/CMP0073-stdout.txt
@@ -0,0 +1,3 @@
+-- warn_LIB_DEPENDS='general;bar;'
+-- old_LIB_DEPENDS='general;bar;'
+-- new_LIB_DEPENDS=''
diff --git a/Tests/RunCMake/add_library/CMP0073.cmake b/Tests/RunCMake/add_library/CMP0073.cmake
new file mode 100644
index 0000000..b34f5dc
--- /dev/null
+++ b/Tests/RunCMake/add_library/CMP0073.cmake
@@ -0,0 +1,18 @@
+enable_language(C)
+
+add_library(warn empty.c)
+target_link_libraries(warn bar)
+message(STATUS "warn_LIB_DEPENDS='${warn_LIB_DEPENDS}'")
+
+cmake_policy(SET CMP0073 OLD)
+add_library(old empty.c)
+target_link_libraries(old bar)
+message(STATUS "old_LIB_DEPENDS='${old_LIB_DEPENDS}'")
+
+cmake_policy(SET CMP0073 NEW)
+add_library(new empty.c)
+target_link_libraries(new bar)
+message(STATUS "new_LIB_DEPENDS='${new_LIB_DEPENDS}'")
+if(DEFINED new_LIB_DEPENDS)
+ message(FATAL_ERROR "new_LIB_DEPENDS set but should not be")
+endif()
diff --git a/Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt b/Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt
index cd6f1e0..1bcc114 100644
--- a/Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt
+++ b/Tests/RunCMake/add_library/OBJECTwithNoSourcesButLinkObjects-stderr.txt
@@ -1,5 +1,4 @@
-^CMake Error at OBJECTwithNoSourcesButLinkObjects.cmake:[0-9]+ \(target_link_libraries\):
- Object library target \"TestObjectLibWithoutSources\" may not link to
- anything.
+^CMake Error at OBJECTwithNoSourcesButLinkObjects.cmake:[0-9]+ \(add_library\):
+ No SOURCES given to target: TestObjectLibWithoutSources
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-stderr.txt b/Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-stderr.txt
deleted file mode 100644
index 77a72f1..0000000
--- a/Tests/RunCMake/add_library/OBJECTwithOnlyObjectSources-stderr.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-^CMake Error at OBJECTwithOnlyObjectSources.cmake:[0-9]+ \(add_library\):
- OBJECT library \"TestObjectLibWithoutSources\" contains:
-
- [^
-]*test(\.cpp)?\.o(bj)?
-
- but may contain only sources that compile, header files, and other files
- that would not affect linking of a normal library.
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)
-
-
-CMake Error at OBJECTwithOnlyObjectSources.cmake:[0-9]+ \(add_library\):
- Only executables and non-OBJECT libraries may reference target objects.
-Call Stack \(most recent call first\):
- CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/add_library/RunCMakeTest.cmake b/Tests/RunCMake/add_library/RunCMakeTest.cmake
index 0ba6216..dfadb8f 100644
--- a/Tests/RunCMake/add_library/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_library/RunCMakeTest.cmake
@@ -1,5 +1,7 @@
include(RunCMake)
+run_cmake(CMP0073)
+
run_cmake(INTERFACEwithNoSources)
run_cmake(OBJECTwithNoSources)
run_cmake(STATICwithNoSources)
diff --git a/Tests/RunCMake/add_library/empty.c b/Tests/RunCMake/add_library/empty.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/add_library/empty.c
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt b/Tests/RunCMake/export/ForbiddenToExportImportedProperties-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/ObjectLibrary/LinkObjRHS1-result.txt
+++ b/Tests/RunCMake/export/ForbiddenToExportImportedProperties-result.txt
diff --git a/Tests/RunCMake/export/ForbiddenToExportImportedProperties-stderr.txt b/Tests/RunCMake/export/ForbiddenToExportImportedProperties-stderr.txt
new file mode 100644
index 0000000..ab03943
--- /dev/null
+++ b/Tests/RunCMake/export/ForbiddenToExportImportedProperties-stderr.txt
@@ -0,0 +1,3 @@
+CMake Error in CMakeLists.txt:
+ Target \"foo\" contains property \"IMPORTED_FOOBAR\" in EXPORT_PROPERTIES but
+ IMPORTED_\* and INTERFACE_\* properties are reserved.
diff --git a/Tests/RunCMake/export/ForbiddenToExportImportedProperties.cmake b/Tests/RunCMake/export/ForbiddenToExportImportedProperties.cmake
new file mode 100644
index 0000000..9c8653d
--- /dev/null
+++ b/Tests/RunCMake/export/ForbiddenToExportImportedProperties.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+add_library(foo empty.cpp)
+set_target_properties(foo PROPERTIES
+ IMPORTED_FOOBAR "Some other string"
+ EXPORT_PROPERTIES "IMPORTED_FOOBAR"
+)
+export(TARGETS foo FILE "${CMAKE_CURRENT_BINARY_DIR}/foo.cmake")
+install(TARGETS foo EXPORT fooExport
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+)
diff --git a/Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/ObjectLibrary/LinkObjLHS-result.txt
+++ b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-result.txt
diff --git a/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-stderr.txt b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-stderr.txt
new file mode 100644
index 0000000..577602b
--- /dev/null
+++ b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties-stderr.txt
@@ -0,0 +1,3 @@
+CMake Error in CMakeLists.txt:
+ Target \"foo\" contains property \"INTERFACE_FOOBAR\" in EXPORT_PROPERTIES but
+ IMPORTED_\* and INTERFACE_\* properties are reserved.
diff --git a/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties.cmake b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties.cmake
new file mode 100644
index 0000000..bab8de0
--- /dev/null
+++ b/Tests/RunCMake/export/ForbiddenToExportInterfaceProperties.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+add_library(foo empty.cpp)
+set_target_properties(foo PROPERTIES
+ INTERFACE_FOOBAR "Some string"
+ EXPORT_PROPERTIES "INTERFACE_FOOBAR"
+)
+export(TARGETS foo FILE "${CMAKE_CURRENT_BINARY_DIR}/foo.cmake")
+install(TARGETS foo EXPORT fooExport
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+)
diff --git a/Tests/RunCMake/ObjectLibrary/ExportNotSupported-result.txt b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/ObjectLibrary/ExportNotSupported-result.txt
+++ b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-result.txt
diff --git a/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-stderr.txt b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-stderr.txt
new file mode 100644
index 0000000..56488e6
--- /dev/null
+++ b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp-stderr.txt
@@ -0,0 +1,3 @@
+CMake Error in CMakeLists.txt:
+ Target \"foo\" contains property \"JUST_A_PROPERTY\" in EXPORT_PROPERTIES but
+ this property contains a generator expression. This is not allowed.
diff --git a/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp.cmake b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp.cmake
new file mode 100644
index 0000000..065cdbc
--- /dev/null
+++ b/Tests/RunCMake/export/ForbiddenToExportPropertyWithGenExp.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+add_library(foo empty.cpp)
+set_target_properties(foo PROPERTIES
+ JUST_A_PROPERTY "$<C_COMPILER_VERSION:0>"
+ EXPORT_PROPERTIES "JUST_A_PROPERTY"
+)
+export(TARGETS foo FILE "${CMAKE_CURRENT_BINARY_DIR}/foo.cmake")
+install(TARGETS foo EXPORT fooExport
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib
+)
diff --git a/Tests/RunCMake/export/RunCMakeTest.cmake b/Tests/RunCMake/export/RunCMakeTest.cmake
index 6d0b7ca..10ced90 100644
--- a/Tests/RunCMake/export/RunCMakeTest.cmake
+++ b/Tests/RunCMake/export/RunCMakeTest.cmake
@@ -5,3 +5,6 @@ run_cmake(TargetNotFound)
run_cmake(AppendExport)
run_cmake(OldIface)
run_cmake(NoExportSet)
+run_cmake(ForbiddenToExportInterfaceProperties)
+run_cmake(ForbiddenToExportImportedProperties)
+run_cmake(ForbiddenToExportPropertyWithGenExp)
diff --git a/Tests/RunCMake/export/empty.cpp b/Tests/RunCMake/export/empty.cpp
new file mode 100644
index 0000000..11ec041
--- /dev/null
+++ b/Tests/RunCMake/export/empty.cpp
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+ int empty()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt b/Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/ObjectLibrary/BadObjSource2-result.txt
+++ b/Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS-result.txt
diff --git a/Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS-stderr.txt b/Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS-stderr.txt
new file mode 100644
index 0000000..af3cb2e
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at GLOB-error-FOLLOW_SYMLINKS\.cmake:[0-9]+ \(file\):
+ file FOLLOW_SYMLINKS is not a valid parameter for GLOB\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS.cmake b/Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS.cmake
new file mode 100644
index 0000000..6d467a0
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-error-FOLLOW_SYMLINKS.cmake
@@ -0,0 +1 @@
+file(GLOB CONTENT_LIST FOLLOW_SYMLINKS)
diff --git a/Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg-result.txt b/Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg-stderr.txt b/Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg-stderr.txt
new file mode 100644
index 0000000..30cec89
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at GLOB-error-RELATIVE-no-arg\.cmake:[0-9]+ \(file\):
+ file GLOB requires a directory after the RELATIVE tag\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg.cmake b/Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg.cmake
new file mode 100644
index 0000000..a555881
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-error-RELATIVE-no-arg.cmake
@@ -0,0 +1 @@
+file(GLOB CONTENT_LIST RELATIVE)
diff --git a/Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES-result.txt b/Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES-stderr.txt b/Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES-stderr.txt
new file mode 100644
index 0000000..ee6cb0b
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-noexp-LIST_DIRECTORIES-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at GLOB-noexp-LIST_DIRECTORIES\.cmake:[0-9]+ \(file\):
+ file GLOB requires a glob expression after the bool\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/GLOB-noexp-RELATIVE-result.txt b/Tests/RunCMake/file/GLOB-noexp-RELATIVE-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-noexp-RELATIVE-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/GLOB-noexp-RELATIVE-stderr.txt b/Tests/RunCMake/file/GLOB-noexp-RELATIVE-stderr.txt
new file mode 100644
index 0000000..9c66631
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-noexp-RELATIVE-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at GLOB-noexp-RELATIVE\.cmake:[0-9]+ \(file\):
+ file GLOB requires a glob expression after the directory\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/GLOB-noexp-RELATIVE.cmake b/Tests/RunCMake/file/GLOB-noexp-RELATIVE.cmake
new file mode 100644
index 0000000..7b2d404
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-noexp-RELATIVE.cmake
@@ -0,0 +1 @@
+file(GLOB CONTENT_LIST RELATIVE "${CMAKE_CURRENT_BINARY_DIR}")
diff --git a/Tests/RunCMake/file/GLOB-sort-dedup-stderr.txt b/Tests/RunCMake/file/GLOB-sort-dedup-stderr.txt
new file mode 100644
index 0000000..d2565e4
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-sort-dedup-stderr.txt
@@ -0,0 +1,2 @@
+content: 7[ ]
+1aAb/\.hide;1aAb/1\.log;1aAb/1\.txt;1aAb/xkcd\.txt;a/1\.log;a/1\.txt;a/boot\.ini
diff --git a/Tests/RunCMake/file/GLOB-sort-dedup.cmake b/Tests/RunCMake/file/GLOB-sort-dedup.cmake
new file mode 100644
index 0000000..1e1c579
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB-sort-dedup.cmake
@@ -0,0 +1,21 @@
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/a")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/test/1aAb")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/a/1.log" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/a/1.txt" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/a/boot.ini" "")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/1aAb/.hide" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/1aAb/1.txt" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/1aAb/1.log" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test/1aAb/xkcd.txt" "")
+
+file(GLOB CONTENT_LIST
+ LIST_DIRECTORIES false
+ RELATIVE "${CMAKE_CURRENT_BINARY_DIR}/test"
+ "${CMAKE_CURRENT_BINARY_DIR}/test/a/*"
+ "${CMAKE_CURRENT_BINARY_DIR}/test/*/*"
+ )
+list(LENGTH CONTENT_LIST CONTENT_COUNT)
+message("content: ${CONTENT_COUNT} ")
+message("${CONTENT_LIST}")
diff --git a/Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS-result.txt b/Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS-stderr.txt b/Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS-stderr.txt
new file mode 100644
index 0000000..d0b2bff
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at GLOB_RECURSE-noexp-FOLLOW_SYMLINKS\.cmake:[0-9]+ \(file\):
+ file GLOB_RECURSE requires a glob expression after FOLLOW_SYMLINKS\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS.cmake b/Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS.cmake
new file mode 100644
index 0000000..5e5ce92
--- /dev/null
+++ b/Tests/RunCMake/file/GLOB_RECURSE-noexp-FOLLOW_SYMLINKS.cmake
@@ -0,0 +1 @@
+file(GLOB_RECURSE CONTENT_LIST FOLLOW_SYMLINKS)
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index 3be4fb7..4aab32d 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -5,6 +5,9 @@ run_cmake(DOWNLOAD-unused-argument)
run_cmake(DOWNLOAD-httpheader-not-set)
run_cmake(DOWNLOAD-netrc-bad)
run_cmake(DOWNLOAD-pass-not-set)
+run_cmake(TOUCH)
+run_cmake(TOUCH-error-in-source-directory)
+run_cmake(TOUCH-error-missing-directory)
run_cmake(UPLOAD-unused-argument)
run_cmake(UPLOAD-httpheader-not-set)
run_cmake(UPLOAD-netrc-bad)
@@ -32,11 +35,16 @@ run_cmake(LOCK-lowercase)
run_cmake(READ_ELF)
run_cmake(GLOB)
run_cmake(GLOB_RECURSE)
-# test is valid both for GLOB and GLOB_RECURSE
+run_cmake(GLOB_RECURSE-noexp-FOLLOW_SYMLINKS)
+
+# tests are valid both for GLOB and GLOB_RECURSE
+run_cmake(GLOB-sort-dedup)
+run_cmake(GLOB-error-FOLLOW_SYMLINKS)
run_cmake(GLOB-error-LIST_DIRECTORIES-not-boolean)
-# test is valid both for GLOB and GLOB_RECURSE
run_cmake(GLOB-error-LIST_DIRECTORIES-no-arg)
+run_cmake(GLOB-error-RELATIVE-no-arg)
run_cmake(GLOB-noexp-LIST_DIRECTORIES)
+run_cmake(GLOB-noexp-RELATIVE)
if(NOT WIN32 OR CYGWIN)
run_cmake(GLOB_RECURSE-cyclic-recursion)
diff --git a/Tests/RunCMake/file/TOUCH-error-in-source-directory-result.txt b/Tests/RunCMake/file/TOUCH-error-in-source-directory-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/TOUCH-error-in-source-directory-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/TOUCH-error-in-source-directory-stderr.txt b/Tests/RunCMake/file/TOUCH-error-in-source-directory-stderr.txt
new file mode 100644
index 0000000..f899c75
--- /dev/null
+++ b/Tests/RunCMake/file/TOUCH-error-in-source-directory-stderr.txt
@@ -0,0 +1 @@
+.*file attempted to touch a file:
diff --git a/Tests/RunCMake/file/TOUCH-error-in-source-directory.cmake b/Tests/RunCMake/file/TOUCH-error-in-source-directory.cmake
new file mode 100644
index 0000000..9aa7c56
--- /dev/null
+++ b/Tests/RunCMake/file/TOUCH-error-in-source-directory.cmake
@@ -0,0 +1,2 @@
+set(CMAKE_DISABLE_SOURCE_CHANGES ON)
+file(TOUCH "${CMAKE_CURRENT_SOURCE_DIR}/touch_test")
diff --git a/Tests/RunCMake/file/TOUCH-error-missing-directory-result.txt b/Tests/RunCMake/file/TOUCH-error-missing-directory-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/TOUCH-error-missing-directory-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/TOUCH-error-missing-directory-stderr.txt b/Tests/RunCMake/file/TOUCH-error-missing-directory-stderr.txt
new file mode 100644
index 0000000..f52e11a
--- /dev/null
+++ b/Tests/RunCMake/file/TOUCH-error-missing-directory-stderr.txt
@@ -0,0 +1 @@
+.*file problem touching file:
diff --git a/Tests/RunCMake/file/TOUCH-error-missing-directory.cmake b/Tests/RunCMake/file/TOUCH-error-missing-directory.cmake
new file mode 100644
index 0000000..0cfb8d9
--- /dev/null
+++ b/Tests/RunCMake/file/TOUCH-error-missing-directory.cmake
@@ -0,0 +1 @@
+file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/missing/directory/file.to-touch")
diff --git a/Tests/RunCMake/file/TOUCH-result.txt b/Tests/RunCMake/file/TOUCH-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/TOUCH-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/TOUCH-stderr.txt b/Tests/RunCMake/file/TOUCH-stderr.txt
new file mode 100644
index 0000000..9f31676
--- /dev/null
+++ b/Tests/RunCMake/file/TOUCH-stderr.txt
@@ -0,0 +1,9 @@
+^CMake Error at TOUCH\.cmake:[0-9]+ \(file\):
+ file must be called with at least two arguments\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
++
+CMake Error at TOUCH\.cmake:[0-9]+ \(file\):
+ file must be called with at least two arguments\.
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/file/TOUCH.cmake b/Tests/RunCMake/file/TOUCH.cmake
new file mode 100644
index 0000000..8931eb5
--- /dev/null
+++ b/Tests/RunCMake/file/TOUCH.cmake
@@ -0,0 +1,16 @@
+set(file "${CMAKE_CURRENT_BINARY_DIR}/file-to-touch")
+
+file(REMOVE "${file}")
+file(TOUCH_NOCREATE "${file}")
+if(EXISTS "${file}")
+ message(FATAL_ERROR "error: TOUCH_NOCREATE created a file!")
+endif()
+
+file(TOUCH "${file}")
+if(NOT EXISTS "${file}")
+ message(FATAL_ERROR "error: TOUCH did not create a file!")
+endif()
+file(REMOVE "${file}")
+
+file(TOUCH)
+file(TOUCH_NOCREATE)
diff --git a/Tests/RunCMake/find_package/CMP0074-OLD-stderr.txt b/Tests/RunCMake/find_package/CMP0074-OLD-stderr.txt
new file mode 100644
index 0000000..4c2e517
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0074-OLD-stderr.txt
@@ -0,0 +1,12 @@
+----------
+Foo_ROOT :<base>/foo/cmake_root
+ENV{Foo_ROOT} :<base>/foo/env_root
+
+find_package\(Foo\)
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_FILE_ZOT :FOO_TEST_FILE_ZOT-NOTFOUND
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PATH_ZOT :FOO_TEST_PATH_ZOT-NOTFOUND
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+
+----------
diff --git a/Tests/RunCMake/find_package/CMP0074-OLD.cmake b/Tests/RunCMake/find_package/CMP0074-OLD.cmake
new file mode 100644
index 0000000..4358317
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0074-OLD.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0074 OLD)
+include(CMP0074-common.cmake)
diff --git a/Tests/RunCMake/find_package/CMP0074-WARN-stderr.txt b/Tests/RunCMake/find_package/CMP0074-WARN-stderr.txt
new file mode 100644
index 0000000..c762d92
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0074-WARN-stderr.txt
@@ -0,0 +1,28 @@
+----------
+Foo_ROOT :<base>/foo/cmake_root
+ENV{Foo_ROOT} :<base>/foo/env_root
++
+CMake Warning \(dev\) at CMP0074-common.cmake:[0-9]+ \(find_package\):
+ Policy CMP0074 is not set: find_package uses PackageName_ROOT variables.
+ Run "cmake --help-policy CMP0074" for policy details. Use the cmake_policy
+ command to set the policy and suppress this warning.
+
+ CMake variable Foo_ROOT is set.
+
+ Environment variable Foo_ROOT is set.
+
+ For compatibility, CMake is ignoring the variable.
+Call Stack \(most recent call first\):
+ CMP0074-common.cmake:[0-9]+ \(RunPackageRootTest\)
+ CMP0074-WARN.cmake:[0-9]+ \(include\)
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
++
+find_package\(Foo\)
+FOO_TEST_FILE_FOO :FOO_TEST_FILE_FOO-NOTFOUND
+FOO_TEST_FILE_ZOT :FOO_TEST_FILE_ZOT-NOTFOUND
+FOO_TEST_PATH_FOO :FOO_TEST_PATH_FOO-NOTFOUND
+FOO_TEST_PATH_ZOT :FOO_TEST_PATH_ZOT-NOTFOUND
+FOO_TEST_PROG_FOO :FOO_TEST_PROG_FOO-NOTFOUND
+
+----------
diff --git a/Tests/RunCMake/find_package/CMP0074-WARN.cmake b/Tests/RunCMake/find_package/CMP0074-WARN.cmake
new file mode 100644
index 0000000..0d4ada7
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0074-WARN.cmake
@@ -0,0 +1,2 @@
+# (do not set CMP0074)
+include(CMP0074-common.cmake)
diff --git a/Tests/RunCMake/find_package/CMP0074-common.cmake b/Tests/RunCMake/find_package/CMP0074-common.cmake
new file mode 100644
index 0000000..bfacd82
--- /dev/null
+++ b/Tests/RunCMake/find_package/CMP0074-common.cmake
@@ -0,0 +1,46 @@
+# (includer selects CMP0074)
+cmake_policy(SET CMP0057 NEW)
+list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
+set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
+
+function(PrintPath label path)
+ string(REPLACE "${PackageRoot_BASE}" "<base>" out "${path}")
+ message("${label}${out}")
+endfunction()
+
+macro(CleanUpPackageRootTest)
+ unset(Foo_ROOT)
+ unset(ENV{Foo_ROOT})
+ unset(FOO_TEST_FILE_FOO)
+ unset(FOO_TEST_FILE_ZOT)
+ unset(FOO_TEST_PATH_FOO)
+ unset(FOO_TEST_PATH_ZOT)
+ unset(FOO_TEST_PROG_FOO)
+ unset(FOO_TEST_FILE_FOO CACHE)
+ unset(FOO_TEST_FILE_ZOT CACHE)
+ unset(FOO_TEST_PATH_FOO CACHE)
+ unset(FOO_TEST_PATH_ZOT CACHE)
+ unset(FOO_TEST_PROG_FOO CACHE)
+endmacro()
+
+macro(RunPackageRootTest)
+ message("----------")
+ PrintPath("Foo_ROOT :" "${Foo_ROOT}")
+ PrintPath("ENV{Foo_ROOT} :" "$ENV{Foo_ROOT}")
+ message("")
+
+ find_package(Foo)
+ message("find_package(Foo)")
+ PrintPath("FOO_TEST_FILE_FOO :" "${FOO_TEST_FILE_FOO}")
+ PrintPath("FOO_TEST_FILE_ZOT :" "${FOO_TEST_FILE_ZOT}")
+ PrintPath("FOO_TEST_PATH_FOO :" "${FOO_TEST_PATH_FOO}")
+ PrintPath("FOO_TEST_PATH_ZOT :" "${FOO_TEST_PATH_ZOT}")
+ PrintPath("FOO_TEST_PROG_FOO :" "${FOO_TEST_PROG_FOO}")
+ CleanUpPackageRootTest()
+ message("")
+endmacro()
+
+set(Foo_ROOT ${PackageRoot_BASE}/foo/cmake_root)
+set(ENV{Foo_ROOT} ${PackageRoot_BASE}/foo/env_root)
+RunPackageRootTest()
+message("----------")
diff --git a/Tests/RunCMake/find_package/PackageRoot.cmake b/Tests/RunCMake/find_package/PackageRoot.cmake
index 4c4f4c2..aa12e9b 100644
--- a/Tests/RunCMake/find_package/PackageRoot.cmake
+++ b/Tests/RunCMake/find_package/PackageRoot.cmake
@@ -1,5 +1,5 @@
-set(__UNDOCUMENTED_CMAKE_FIND_PACKAGE_ROOT 1)
cmake_policy(SET CMP0057 NEW)
+cmake_policy(SET CMP0074 NEW)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
diff --git a/Tests/RunCMake/find_package/PackageRootNestedConfig.cmake b/Tests/RunCMake/find_package/PackageRootNestedConfig.cmake
index ba06c09..1ef32cb 100644
--- a/Tests/RunCMake/find_package/PackageRootNestedConfig.cmake
+++ b/Tests/RunCMake/find_package/PackageRootNestedConfig.cmake
@@ -1,5 +1,5 @@
-set(__UNDOCUMENTED_CMAKE_FIND_PACKAGE_ROOT 1)
cmake_policy(SET CMP0057 NEW)
+cmake_policy(SET CMP0074 NEW)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
diff --git a/Tests/RunCMake/find_package/PackageRootNestedModule.cmake b/Tests/RunCMake/find_package/PackageRootNestedModule.cmake
index 2795cd4..017834c 100644
--- a/Tests/RunCMake/find_package/PackageRootNestedModule.cmake
+++ b/Tests/RunCMake/find_package/PackageRootNestedModule.cmake
@@ -1,5 +1,5 @@
-set(__UNDOCUMENTED_CMAKE_FIND_PACKAGE_ROOT 1)
cmake_policy(SET CMP0057 NEW)
+cmake_policy(SET CMP0074 NEW)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot)
diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake
index d548da0..c068402 100644
--- a/Tests/RunCMake/find_package/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake
@@ -1,5 +1,7 @@
include(RunCMake)
+run_cmake(CMP0074-WARN)
+run_cmake(CMP0074-OLD)
run_cmake(ComponentRequiredAndOptional)
run_cmake(MissingNormal)
run_cmake(MissingNormalRequired)
diff --git a/Tests/RunCMake/get_property/directory_properties-stderr.txt b/Tests/RunCMake/get_property/directory_properties-stderr.txt
index 6d5bcdb..89f5618 100644
--- a/Tests/RunCMake/get_property/directory_properties-stderr.txt
+++ b/Tests/RunCMake/get_property/directory_properties-stderr.txt
@@ -19,4 +19,12 @@ get_property: -->[^<;]*/Tests/RunCMake/get_property<--
get_directory_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build/directory_properties<--
get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties-build/directory_properties<--
get_directory_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<--
-get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<--$
+get_property: -->[^<;]*/Tests/RunCMake/get_property/directory_properties<--
+get_directory_property: --><--
+get_property: --><--
+get_directory_property: -->test1;test2<--
+get_property: -->test1;test2<--
+get_directory_property: -->test1;test2;test3<--
+get_property: -->test1;test2;test3<--
+get_directory_property: -->Sub/test1;Sub/test2<--
+get_property: -->Sub/test1;Sub/test2<--$
diff --git a/Tests/RunCMake/get_property/directory_properties.cmake b/Tests/RunCMake/get_property/directory_properties.cmake
index 4e68738..9b978fd 100644
--- a/Tests/RunCMake/get_property/directory_properties.cmake
+++ b/Tests/RunCMake/get_property/directory_properties.cmake
@@ -28,3 +28,12 @@ check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" BINARY_DIR)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" SOURCE_DIR)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" BINARY_DIR)
check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" SOURCE_DIR)
+
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS)
+add_test(NAME test1 COMMAND "${CMAKE_COMMAND}" -E echo "test1")
+add_test(NAME test2 COMMAND "${CMAKE_COMMAND}" -E echo "test2")
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS)
+add_test(NAME test3 COMMAND "${CMAKE_COMMAND}" -E echo "test3")
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}" TESTS)
+
+check_directory_property("${CMAKE_CURRENT_SOURCE_DIR}/directory_properties" TESTS)
diff --git a/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt b/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt
index 7318b97..95106ad 100644
--- a/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt
+++ b/Tests/RunCMake/get_property/directory_properties/CMakeLists.txt
@@ -4,3 +4,6 @@ subdirs(sub2)
add_custom_target(CustomSub)
add_library(InterfaceSub INTERFACE)
add_library(my::InterfaceSub ALIAS InterfaceSub)
+
+add_test(Sub/test1 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test1")
+add_test(Sub/test2 COMMAND "${CMAKE_COMMAND}" -E echo "Sub/test2")
diff --git a/Tests/RunCMake/project/LanguagesUnordered-stderr.txt b/Tests/RunCMake/project/LanguagesUnordered-stderr.txt
new file mode 100644
index 0000000..5108670
--- /dev/null
+++ b/Tests/RunCMake/project/LanguagesUnordered-stderr.txt
@@ -0,0 +1 @@
+ the following parameters must be specified after LANGUAGES keyword: C.
diff --git a/Tests/RunCMake/project/LanguagesUnordered.cmake b/Tests/RunCMake/project/LanguagesUnordered.cmake
new file mode 100644
index 0000000..cd3ba28
--- /dev/null
+++ b/Tests/RunCMake/project/LanguagesUnordered.cmake
@@ -0,0 +1 @@
+project(ProjectA C LANGUAGES CXX)
diff --git a/Tests/RunCMake/project/ProjectDescriptionNoArg-stderr.txt b/Tests/RunCMake/project/ProjectDescriptionNoArg-stderr.txt
new file mode 100644
index 0000000..910106f
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectDescriptionNoArg-stderr.txt
@@ -0,0 +1,2 @@
+ DESCRIPTION keyword not followed by a value or was followed by a value that
+ expanded to nothing.
diff --git a/Tests/RunCMake/project/ProjectDescriptionNoArg.cmake b/Tests/RunCMake/project/ProjectDescriptionNoArg.cmake
new file mode 100644
index 0000000..25acff8
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectDescriptionNoArg.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0048 NEW)
+project(ProjectDescriptionTest VERSION 1.0.0 LANGUAGES NONE DESCRIPTION)
diff --git a/Tests/RunCMake/project/ProjectDescriptionNoArg2-stderr.txt b/Tests/RunCMake/project/ProjectDescriptionNoArg2-stderr.txt
new file mode 100644
index 0000000..910106f
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectDescriptionNoArg2-stderr.txt
@@ -0,0 +1,2 @@
+ DESCRIPTION keyword not followed by a value or was followed by a value that
+ expanded to nothing.
diff --git a/Tests/RunCMake/project/ProjectDescriptionNoArg2.cmake b/Tests/RunCMake/project/ProjectDescriptionNoArg2.cmake
new file mode 100644
index 0000000..f50a2f6
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectDescriptionNoArg2.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0048 NEW)
+project(ProjectDescriptionTest VERSION 1.0.0 DESCRIPTION LANGUAGES NONE)
diff --git a/Tests/RunCMake/project/ProjectHomepage-stdout.txt b/Tests/RunCMake/project/ProjectHomepage-stdout.txt
new file mode 100644
index 0000000..253990f
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectHomepage-stdout.txt
@@ -0,0 +1,3 @@
+-- PROJECT_HOMEPAGE_URL=http://example.com
+-- CMAKE_PROJECT_HOMEPAGE_URL=http://example.com
+-- ProjectHomepageTest_HOMEPAGE_URL=http://example.com
diff --git a/Tests/RunCMake/project/ProjectHomepage.cmake b/Tests/RunCMake/project/ProjectHomepage.cmake
new file mode 100644
index 0000000..3307f1f
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectHomepage.cmake
@@ -0,0 +1,14 @@
+cmake_policy(SET CMP0048 NEW)
+project(ProjectHomepageTest VERSION 1.0.0 HOMEPAGE_URL "http://example.com" LANGUAGES)
+if(NOT PROJECT_HOMEPAGE_URL)
+ message(FATAL_ERROR "PROJECT_HOMEPAGE_URL expected to be set")
+endif()
+if(NOT CMAKE_PROJECT_HOMEPAGE_URL)
+ message(FATAL_ERROR "CMAKE_PROJECT_HOMEPAGE_URL expected to be set")
+endif()
+if(NOT ProjectHomepageTest_HOMEPAGE_URL)
+ message(FATAL_ERROR "ProjectHomepageTest_HOMEPAGE_URL expected to be set")
+endif()
+message(STATUS "PROJECT_HOMEPAGE_URL=${PROJECT_HOMEPAGE_URL}")
+message(STATUS "CMAKE_PROJECT_HOMEPAGE_URL=${CMAKE_PROJECT_HOMEPAGE_URL}")
+message(STATUS "ProjectHomepageTest_HOMEPAGE_URL=${ProjectHomepageTest_HOMEPAGE_URL}")
diff --git a/Tests/RunCMake/project/ProjectHomepage2-result.txt b/Tests/RunCMake/project/ProjectHomepage2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectHomepage2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/project/ProjectHomepage2-stderr.txt b/Tests/RunCMake/project/ProjectHomepage2-stderr.txt
new file mode 100644
index 0000000..4a0adc2
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectHomepage2-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at ProjectHomepage2.cmake:2 \(project\):
+ HOMEPAGE_URL may be specified at most once.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/project/ProjectHomepage2.cmake b/Tests/RunCMake/project/ProjectHomepage2.cmake
new file mode 100644
index 0000000..184c392
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectHomepage2.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0048 NEW)
+project(ProjectDescriptionTest VERSION 1.0.0 HOMEPAGE_URL "http://example.com" HOMEPAGE_URL "http://example.com" LANGUAGES)
diff --git a/Tests/RunCMake/project/ProjectHomepageNoArg-stderr.txt b/Tests/RunCMake/project/ProjectHomepageNoArg-stderr.txt
new file mode 100644
index 0000000..c9503b7
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectHomepageNoArg-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Warning at ProjectHomepageNoArg.cmake:2 \(project\):
+ HOMEPAGE_URL keyword not followed by a value or was followed by a value
+ that expanded to nothing.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/project/ProjectHomepageNoArg.cmake b/Tests/RunCMake/project/ProjectHomepageNoArg.cmake
new file mode 100644
index 0000000..4605541
--- /dev/null
+++ b/Tests/RunCMake/project/ProjectHomepageNoArg.cmake
@@ -0,0 +1,2 @@
+cmake_policy(SET CMP0048 NEW)
+project(ProjectDescriptionTest VERSION 1.0.0 LANGUAGES NONE HOMEPAGE_URL)
diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake
index 3d13e2e..e9fb929 100644
--- a/Tests/RunCMake/project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/project/RunCMakeTest.cmake
@@ -7,8 +7,14 @@ run_cmake(LanguagesImplicit)
run_cmake(LanguagesEmpty)
run_cmake(LanguagesNONE)
run_cmake(LanguagesTwice)
+run_cmake(LanguagesUnordered)
run_cmake(ProjectDescription)
run_cmake(ProjectDescription2)
+run_cmake(ProjectDescriptionNoArg)
+run_cmake(ProjectDescriptionNoArg2)
+run_cmake(ProjectHomepage)
+run_cmake(ProjectHomepage2)
+run_cmake(ProjectHomepageNoArg)
run_cmake(VersionAndLanguagesEmpty)
run_cmake(VersionEmpty)
run_cmake(VersionInvalid)
diff --git a/Tests/RunCMake/project/VersionMissingLanguages-stderr.txt b/Tests/RunCMake/project/VersionMissingLanguages-stderr.txt
index 52433bc..576ac69 100644
--- a/Tests/RunCMake/project/VersionMissingLanguages-stderr.txt
+++ b/Tests/RunCMake/project/VersionMissingLanguages-stderr.txt
@@ -1,4 +1,5 @@
CMake Error at VersionMissingLanguages.cmake:2 \(project\):
- project with VERSION must use LANGUAGES before language names.
+ project with VERSION, DESCRIPTION or HOMEPAGE_URL must use LANGUAGES before
+ language names.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)$
diff --git a/Tests/RunCMake/project/VersionMissingValueOkay-stderr.txt b/Tests/RunCMake/project/VersionMissingValueOkay-stderr.txt
new file mode 100644
index 0000000..3228df7
--- /dev/null
+++ b/Tests/RunCMake/project/VersionMissingValueOkay-stderr.txt
@@ -0,0 +1,2 @@
+ VERSION keyword not followed by a value or was followed by a value that
+ expanded to nothing.
diff --git a/Tests/RunCMake/string/Join.cmake b/Tests/RunCMake/string/Join.cmake
new file mode 100644
index 0000000..081f1e4
--- /dev/null
+++ b/Tests/RunCMake/string/Join.cmake
@@ -0,0 +1,16 @@
+string(JOIN % out)
+if(NOT out STREQUAL "")
+ message(FATAL_ERROR "\"string(JOIN % out)\" set out to \"${out}\"")
+endif()
+string(JOIN % out a)
+if(NOT out STREQUAL "a")
+ message(FATAL_ERROR "\"string(JOIN % out a)\" set out to \"${out}\"")
+endif()
+string(JOIN % out a "b")
+if(NOT out STREQUAL "a%b")
+ message(FATAL_ERROR "\"string(JOIN % out a \"b\")\" set out to \"${out}\"")
+endif()
+string(JOIN :: out a "b")
+if(NOT out STREQUAL "a::b")
+ message(FATAL_ERROR "\"string(JOIN :: out a \"b\")\" set out to \"${out}\"")
+endif()
diff --git a/Tests/RunCMake/string/JoinNoArgs-result.txt b/Tests/RunCMake/string/JoinNoArgs-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/string/JoinNoArgs-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/string/JoinNoArgs-stderr.txt b/Tests/RunCMake/string/JoinNoArgs-stderr.txt
new file mode 100644
index 0000000..d9dcec3
--- /dev/null
+++ b/Tests/RunCMake/string/JoinNoArgs-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at JoinNoArgs.cmake:1 \(string\):
+ string sub-command JOIN requires at least two arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/string/JoinNoArgs.cmake b/Tests/RunCMake/string/JoinNoArgs.cmake
new file mode 100644
index 0000000..35ba4d9
--- /dev/null
+++ b/Tests/RunCMake/string/JoinNoArgs.cmake
@@ -0,0 +1 @@
+string(JOIN)
diff --git a/Tests/RunCMake/string/JoinNoVar-result.txt b/Tests/RunCMake/string/JoinNoVar-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/string/JoinNoVar-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/string/JoinNoVar-stderr.txt b/Tests/RunCMake/string/JoinNoVar-stderr.txt
new file mode 100644
index 0000000..90701a9
--- /dev/null
+++ b/Tests/RunCMake/string/JoinNoVar-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at JoinNoVar.cmake:1 \(string\):
+ string sub-command JOIN requires at least two arguments.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/string/JoinNoVar.cmake b/Tests/RunCMake/string/JoinNoVar.cmake
new file mode 100644
index 0000000..35f7b92
--- /dev/null
+++ b/Tests/RunCMake/string/JoinNoVar.cmake
@@ -0,0 +1 @@
+string(JOIN ";")
diff --git a/Tests/RunCMake/string/RunCMakeTest.cmake b/Tests/RunCMake/string/RunCMakeTest.cmake
index 513d1e3..211337a 100644
--- a/Tests/RunCMake/string/RunCMakeTest.cmake
+++ b/Tests/RunCMake/string/RunCMakeTest.cmake
@@ -9,6 +9,10 @@ run_cmake(PrependNoArgs)
run_cmake(Concat)
run_cmake(ConcatNoArgs)
+run_cmake(Join)
+run_cmake(JoinNoArgs)
+run_cmake(JoinNoVar)
+
run_cmake(Timestamp)
run_cmake(TimestampEmpty)
run_cmake(TimestampInvalid)
diff --git a/Tests/SwigTest/runme.py b/Tests/SwigTest/runme.py
deleted file mode 100644
index ed3909e..0000000
--- a/Tests/SwigTest/runme.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# file: runme.py
-
-# This file illustrates the shadow-class C++ interface generated
-# by SWIG.
-
-import example
-
-# ----- Object creation -----
-
-print "Creating some objects:"
-c = example.Circle(10)
-print " Created circle", c
-s = example.Square(10)
-print " Created square", s
-
-# ----- Access a static member -----
-
-print "\nA total of", example.cvar.Shape_nshapes,"shapes were created"
-
-# ----- Member data access -----
-
-# Set the location of the object
-
-c.x = 20
-c.y = 30
-
-s.x = -10
-s.y = 5
-
-print "\nHere is their current position:"
-print " Circle = (%f, %f)" % (c.x,c.y)
-print " Square = (%f, %f)" % (s.x,s.y)
-
-# ----- Call some methods -----
-
-print "\nHere are some properties of the shapes:"
-for o in [c,s]:
- print " ", o
- print " area = ", o.area()
- print " perimeter = ", o.perimeter()
-
-print "\nGuess I'll clean up now"
-
-# Note: this invokes the virtual destructor
-del c
-del s
-
-s = 3
-print example.cvar.Shape_nshapes,"shapes remain"
-print "Goodbye"
-
diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h
index 328ce9e..875e30a 100644
--- a/Utilities/cmlibuv/include/uv.h
+++ b/Utilities/cmlibuv/include/uv.h
@@ -925,6 +925,19 @@ typedef struct uv_process_options_s {
*/
uv_uid_t uid;
uv_gid_t gid;
+ /*
+ Libuv can set the child process' CPU affinity mask. This happens when
+ `cpumask` is non-NULL. It must point to an array of char values
+ of length `cpumask_size`, whose value must be at least that returned by
+ uv_cpumask_size(). Each byte in the mask can be either zero (false)
+ or non-zero (true) to indicate whether the corresponding processor at
+ that index is included.
+
+ If enabled on an unsupported platform, uv_spawn() will fail with
+ UV_ENOTSUP.
+ */
+ char* cpumask;
+ size_t cpumask_size;
} uv_process_options_t;
/*
@@ -1094,6 +1107,7 @@ UV_EXTERN uv_pid_t uv_os_getppid(void);
UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count);
UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count);
+UV_EXTERN int uv_cpumask_size(void);
UV_EXTERN int uv_interface_addresses(uv_interface_address_t** addresses,
int* count);
diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c
index c7e431e..faaf697 100644
--- a/Utilities/cmlibuv/src/unix/core.c
+++ b/Utilities/cmlibuv/src/unix/core.c
@@ -40,6 +40,7 @@
#include <sys/uio.h> /* writev */
#include <sys/resource.h> /* getrusage */
#include <pwd.h>
+#include <sched.h>
#ifdef __sun
# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
@@ -63,6 +64,8 @@
# include <sys/sysctl.h>
# include <sys/filio.h>
# include <sys/wait.h>
+# include <sys/param.h>
+# include <sys/cpuset.h>
# define UV__O_CLOEXEC O_CLOEXEC
# if defined(__FreeBSD__) && __FreeBSD__ >= 10
# define uv__accept4 accept4
@@ -1340,6 +1343,15 @@ int uv_os_gethostname(char* buffer, size_t* size) {
}
+int uv_cpumask_size(void) {
+#if defined(__linux__) || defined(__FreeBSD__)
+ return CPU_SETSIZE;
+#else
+ return UV_ENOTSUP;
+#endif
+}
+
+
uv_os_fd_t uv_get_osfhandle(int fd) {
return fd;
}
diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c
index 9842710..47ab1dc 100644
--- a/Utilities/cmlibuv/src/unix/process.c
+++ b/Utilities/cmlibuv/src/unix/process.c
@@ -32,6 +32,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
+#include <sched.h>
#if defined(__APPLE__) && !TARGET_OS_IPHONE
# include <crt_externs.h>
@@ -44,6 +45,16 @@ extern char **environ;
# include <grp.h>
#endif
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__)
+# define uv__cpu_set_t cpu_set_t
+#elif defined(__FreeBSD__)
+# include <sys/param.h>
+# include <sys/cpuset.h>
+# include <pthread_np.h>
+# define uv__cpu_set_t cpuset_t
+#endif
+#endif
static void uv__chld(uv_signal_t* handle, int signum) {
uv_process_t* process;
@@ -285,6 +296,14 @@ static void uv__process_child_init(const uv_process_options_t* options,
int err;
int fd;
int n;
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ int r;
+ int i;
+ int cpumask_size;
+ uv__cpu_set_t cpuset;
+#endif
+#endif
if (options->flags & UV_PROCESS_DETACHED)
setsid();
@@ -375,6 +394,28 @@ static void uv__process_child_init(const uv_process_options_t* options,
_exit(127);
}
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ if (options->cpumask != NULL) {
+ cpumask_size = uv_cpumask_size();
+ assert(options->cpumask_size >= (size_t)cpumask_size);
+
+ CPU_ZERO(&cpuset);
+ for (i = 0; i < cpumask_size; ++i) {
+ if (options->cpumask[i]) {
+ CPU_SET(i, &cpuset);
+ }
+ }
+
+ r = -pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
+ if (r != 0) {
+ uv__write_int(error_fd, r);
+ _exit(127);
+ }
+ }
+#endif
+#endif
+
if (options->env != NULL) {
environ = options->env;
}
@@ -429,6 +470,20 @@ int uv_spawn(uv_loop_t* loop,
int i;
int status;
+ if (options->cpumask != NULL) {
+#ifndef CMAKE_BOOTSTRAP
+#if defined(__linux__) || defined(__FreeBSD__)
+ if (options->cpumask_size < (size_t)uv_cpumask_size()) {
+ return UV_EINVAL;
+ }
+#else
+ return UV_ENOTSUP;
+#endif
+#else
+ return UV_ENOTSUP;
+#endif
+ }
+
assert(options->file != NULL);
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c
index 9ed4e82..8d121b3 100644
--- a/Utilities/cmlibuv/src/win/core.c
+++ b/Utilities/cmlibuv/src/win/core.c
@@ -603,3 +603,7 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) {
return 0;
}
+
+int uv_cpumask_size(void) {
+ return (int)(sizeof(DWORD_PTR) * 8);
+}
diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c
index cc06d9e..f5f05af 100644
--- a/Utilities/cmlibuv/src/win/process.c
+++ b/Utilities/cmlibuv/src/win/process.c
@@ -954,6 +954,12 @@ int uv_spawn(uv_loop_t* loop,
return UV_EINVAL;
}
+ if (options->cpumask != NULL) {
+ if (options->cpumask_size < (size_t)uv_cpumask_size()) {
+ return UV_EINVAL;
+ }
+ }
+
assert(options->file != NULL);
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
UV_PROCESS_SETGID |
@@ -1084,6 +1090,12 @@ int uv_spawn(uv_loop_t* loop,
process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
}
+ if (options->cpumask != NULL) {
+ /* Create the child in a suspended state so we have a chance to set
+ its process affinity before it runs. */
+ process_flags |= CREATE_SUSPENDED;
+ }
+
if (!CreateProcessW(application_path,
arguments,
NULL,
@@ -1099,6 +1111,50 @@ int uv_spawn(uv_loop_t* loop,
goto done;
}
+ if (options->cpumask != NULL) {
+ /* The child is currently suspended. Set its process affinity
+ or terminate it if we can't. */
+ int i;
+ int cpumasksize;
+ DWORD_PTR sysmask;
+ DWORD_PTR oldmask;
+ DWORD_PTR newmask;
+
+ cpumasksize = uv_cpumask_size();
+
+ if (!GetProcessAffinityMask(info.hProcess, &oldmask, &sysmask)) {
+ err = GetLastError();
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+
+ newmask = 0;
+ for (i = 0; i < cpumasksize; i++) {
+ if (options->cpumask[i]) {
+ if (oldmask & (((DWORD_PTR)1) << i)) {
+ newmask |= ((DWORD_PTR)1) << i;
+ } else {
+ err = UV_EINVAL;
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+ }
+ }
+
+ if (!SetProcessAffinityMask(info.hProcess, newmask)) {
+ err = GetLastError();
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+
+ /* The process affinity of the child is set. Let it run. */
+ if (ResumeThread(info.hThread) == ((DWORD)-1)) {
+ err = GetLastError();
+ TerminateProcess(info.hProcess, 1);
+ goto done;
+ }
+ }
+
/* Spawn succeeded */
/* Beyond this point, failure is reported asynchronously. */
diff --git a/bootstrap b/bootstrap
index 0bee6c5..d152c34 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1116,8 +1116,10 @@ done
rm -f "${TMPFILE}.cxx"
if [ -z "${cmake_cxx_compiler}" ]; then
-cmake_error 7 "Cannot find a C++ compiler supporting C++11 on this system.
+cmake_error 7 "Cannot find a C++ compiler that supports both C++11 and the specified C++ flags.
Please specify one using environment variable CXX.
+The C++ flags are \"$cmake_cxx_flags\".
+They can be changed using the environment variable CXXFLAGS.
See cmake_bootstrap.log for compilers attempted."
fi
echo "C++ compiler on this system is: ${cmake_cxx_compiler} ${cmake_cxx_flags}"