summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml20
-rw-r--r--.gitlab/ci/configure_debian10_aarch64_ninja.cmake1
-rw-r--r--.gitlab/ci/configure_debian10_ninja.cmake1
-rw-r--r--.gitlab/ci/configure_fedora36_makefiles.cmake1
-rw-r--r--.gitlab/ci/configure_linux_gcc_cxx_modules_ninja.cmake4
-rw-r--r--.gitlab/ci/configure_linux_gcc_cxx_modules_ninja_multi.cmake4
-rw-r--r--.gitlab/ci/cxx_modules_rules_gcc.cmake10
-rw-r--r--.gitlab/ci/docker/gcc_cxx_modules/Dockerfile9
-rwxr-xr-x.gitlab/ci/docker/gcc_cxx_modules/install_deps.sh7
-rwxr-xr-x.gitlab/ci/docker/gcc_cxx_modules/install_gcc.sh26
-rw-r--r--.gitlab/os-linux.yml24
-rw-r--r--Auxiliary/cmake-mode.el38
-rw-r--r--Auxiliary/vim/syntax/cmake.vim2
-rw-r--r--CMakeLists.txt2
-rw-r--r--CompileFlags.cmake9
-rw-r--r--Help/command/FIND_XXX.txt21
-rw-r--r--Help/command/cmake_language.rst26
-rw-r--r--Help/command/enable_language.rst9
-rw-r--r--Help/command/export.rst16
-rw-r--r--Help/command/foreach.rst8
-rw-r--r--Help/command/function.rst6
-rw-r--r--Help/command/if.rst7
-rw-r--r--Help/command/install.rst43
-rw-r--r--Help/command/target_sources.rst77
-rw-r--r--Help/command/try_run.rst13
-rw-r--r--Help/command/while.rst8
-rw-r--r--Help/cpack_gen/freebsd.rst12
-rw-r--r--Help/dev/experimental.rst22
-rw-r--r--Help/guide/tutorial/A Basic Starting Point.rst26
-rw-r--r--Help/guide/tutorial/Adding Support for a Testing Dashboard.rst20
-rw-r--r--Help/guide/tutorial/Adding System Introspection.rst10
-rw-r--r--Help/guide/tutorial/Adding a Custom Command and Generated File.rst12
-rw-r--r--Help/guide/tutorial/Packaging an Installer.rst4
-rw-r--r--Help/guide/tutorial/Step5/CTestConfig.cmake7
-rw-r--r--Help/guide/tutorial/Step6/CMakeLists.txt2
-rw-r--r--Help/guide/tutorial/Step6/CTestConfig.cmake7
-rw-r--r--Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt23
-rw-r--r--Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx25
-rw-r--r--Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx8
-rw-r--r--Help/guide/tutorial/Step7/CMakeLists.txt2
-rw-r--r--Help/guide/tutorial/Step7/CTestConfig.cmake7
-rw-r--r--Help/guide/tutorial/Step7/License.txt2
-rw-r--r--Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt43
-rw-r--r--Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx17
-rw-r--r--Help/guide/tutorial/Step8/CMakeLists.txt10
-rw-r--r--Help/guide/tutorial/Step9/CMakeLists.txt1
-rw-r--r--Help/guide/tutorial/index.rst2
-rw-r--r--Help/manual/cmake-properties.7.rst15
-rw-r--r--Help/manual/cmake-variables.7.rst1
-rw-r--r--Help/manual/cmake.1.rst5
-rw-r--r--Help/prop_tgt/CXX_MODULE_DIRS.rst17
-rw-r--r--Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst17
-rw-r--r--Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst17
-rw-r--r--Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst19
-rw-r--r--Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst18
-rw-r--r--Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst18
-rw-r--r--Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst19
-rw-r--r--Help/prop_tgt/CXX_MODULE_SET.rst18
-rw-r--r--Help/prop_tgt/CXX_MODULE_SETS.rst16
-rw-r--r--Help/prop_tgt/CXX_MODULE_SET_NAME.rst18
-rw-r--r--Help/prop_tgt/EXPORT_NO_SYSTEM.rst11
-rw-r--r--Help/prop_tgt/IMPORTED_NO_SYSTEM.rst12
-rw-r--r--Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst16
-rw-r--r--Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst16
-rw-r--r--Help/prop_tgt/SYSTEM.rst16
-rw-r--r--Help/prop_tgt/XCODE_GENERATE_SCHEME.rst1
-rw-r--r--Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst22
-rw-r--r--Help/release/dev/0-sample-topic.rst7
-rw-r--r--Help/release/dev/FindVulkan-dxc.rst5
-rw-r--r--Help/release/dev/cmake_language_GET_MESSAGE_LOG_LEVEL.rst6
-rw-r--r--Help/release/dev/find_item-VALIDATOR.rst6
-rw-r--r--Help/release/dev/finddoxygen-better-version-checking.rst11
-rw-r--r--Help/release/dev/findopenal-add-import-library.rst4
-rw-r--r--Help/release/dev/findvulkan-volk.rst5
-rw-r--r--Help/release/dev/system.rst15
-rw-r--r--Help/release/dev/try_run_split_output.rst6
-rw-r--r--Help/release/dev/xcode-launch-mode.rst7
-rw-r--r--Help/release/index.rst2
-rw-r--r--Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst5
-rw-r--r--Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst13
-rw-r--r--Modules/Compiler/NVIDIA-CUDA.cmake16
-rw-r--r--Modules/FindBLAS.cmake11
-rw-r--r--Modules/FindCUDA.cmake4
-rw-r--r--Modules/FindCURL.cmake2
-rw-r--r--Modules/FindDoxygen.cmake46
-rw-r--r--Modules/FindGLEW.cmake27
-rw-r--r--Modules/FindICU.cmake12
-rw-r--r--Modules/FindLAPACK.cmake12
-rw-r--r--Modules/FindOpenACC.cmake10
-rw-r--r--Modules/FindOpenAL.cmake26
-rw-r--r--Modules/FindOpenMP.cmake54
-rw-r--r--Modules/FindOpenSSL.cmake22
-rw-r--r--Modules/FindPython/Support.cmake274
-rw-r--r--Modules/FindRuby.cmake53
-rw-r--r--Modules/FindVulkan.cmake116
-rw-r--r--Modules/Platform/AIX-GNU.cmake4
-rw-r--r--Modules/Platform/AIX-XL.cmake4
-rwxr-xr-xModules/Platform/AIX/ExportImportList46
-rw-r--r--Modules/Platform/SerenityOS-Clang-ASM.cmake2
-rw-r--r--Modules/Platform/SerenityOS-Clang-C.cmake2
-rw-r--r--Modules/Platform/SerenityOS-Clang-CXX.cmake2
-rw-r--r--Modules/Platform/SerenityOS-GNU-ASM.cmake2
-rw-r--r--Modules/Platform/SerenityOS-GNU-C.cmake2
-rw-r--r--Modules/Platform/SerenityOS-GNU-CXX.cmake2
-rw-r--r--Modules/Platform/SerenityOS-GNU.cmake24
-rw-r--r--Modules/Platform/SerenityOS.cmake12
-rw-r--r--Source/CMakeLists.txt6
-rw-r--r--Source/CMakeVersion.cmake4
-rw-r--r--Source/CPack/cmCPackFreeBSDGenerator.cxx54
-rw-r--r--Source/CTest/cmCTestCoverageCommand.cxx12
-rw-r--r--Source/CTest/cmCTestCoverageCommand.h6
-rw-r--r--Source/CTest/cmCTestHandlerCommand.cxx10
-rw-r--r--Source/CTest/cmCTestHandlerCommand.h2
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx65
-rw-r--r--Source/CTest/cmCTestSubmitCommand.h13
-rw-r--r--Source/CTest/cmCTestUploadCommand.cxx2
-rw-r--r--Source/CTest/cmCTestUploadCommand.h5
-rw-r--r--Source/CursesDialog/cmCursesLongMessageForm.cxx2
-rw-r--r--Source/CursesDialog/form/.gitattributes1
-rw-r--r--Source/CursesDialog/form/fty_int.c2
-rw-r--r--Source/CursesDialog/form/fty_num.c2
-rw-r--r--Source/cmArgumentParser.cxx28
-rw-r--r--Source/cmArgumentParser.h48
-rw-r--r--Source/cmArgumentParserTypes.h24
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.cxx2
-rw-r--r--Source/cmCMakeLanguageCommand.cxx30
-rw-r--r--Source/cmCMakePathCommand.cxx12
-rw-r--r--Source/cmCommonTargetGenerator.cxx4
-rw-r--r--Source/cmConfigure.cmake.h.in4
-rw-r--r--Source/cmCoreTryCompile.cxx14
-rw-r--r--Source/cmCxxModuleMapper.cxx76
-rw-r--r--Source/cmCxxModuleMapper.h48
-rw-r--r--Source/cmDefinePropertyCommand.cxx5
-rw-r--r--Source/cmExecuteProcessCommand.cxx6
-rw-r--r--Source/cmExperimental.cxx63
-rw-r--r--Source/cmExperimental.h21
-rw-r--r--Source/cmExportBuildFileGenerator.cxx98
-rw-r--r--Source/cmExportBuildFileGenerator.h16
-rw-r--r--Source/cmExportCommand.cxx23
-rw-r--r--Source/cmExportFileGenerator.cxx33
-rw-r--r--Source/cmExportFileGenerator.h5
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.cxx3
-rw-r--r--Source/cmExportInstallFileGenerator.cxx108
-rw-r--r--Source/cmExportInstallFileGenerator.h25
-rw-r--r--Source/cmExportTryCompileFileGenerator.h3
-rw-r--r--Source/cmFileAPICodemodel.cxx16
-rw-r--r--Source/cmFileCommand.cxx272
-rw-r--r--Source/cmFindBase.cxx62
-rw-r--r--Source/cmFindBase.h7
-rw-r--r--Source/cmFindLibraryCommand.cxx33
-rw-r--r--Source/cmFindPackageCommand.cxx8
-rw-r--r--Source/cmFindPathCommand.cxx6
-rw-r--r--Source/cmFindProgramCommand.cxx12
-rw-r--r--Source/cmGeneratorTarget.cxx101
-rw-r--r--Source/cmGeneratorTarget.h30
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx448
-rw-r--r--Source/cmGlobalNinjaGenerator.h4
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx15
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h2
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx28
-rw-r--r--Source/cmInstallCommand.cxx155
-rw-r--r--Source/cmInstallCommandArguments.h5
-rw-r--r--Source/cmInstallCxxModuleBmiGenerator.cxx75
-rw-r--r--Source/cmInstallCxxModuleBmiGenerator.h52
-rw-r--r--Source/cmInstallExportGenerator.cxx73
-rw-r--r--Source/cmInstallExportGenerator.h8
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx37
-rw-r--r--Source/cmMakefile.cxx73
-rw-r--r--Source/cmMakefile.h1
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx10
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx12
-rw-r--r--Source/cmMakefileTargetGenerator.cxx130
-rw-r--r--Source/cmMakefileTargetGenerator.h20
-rw-r--r--Source/cmMessageCommand.cxx65
-rw-r--r--Source/cmMessageType.h16
-rw-r--r--Source/cmNinjaTargetGenerator.cxx321
-rw-r--r--Source/cmParseArgumentsCommand.cxx8
-rw-r--r--Source/cmScriptGenerator.cxx2
-rw-r--r--Source/cmStringCommand.cxx3
-rw-r--r--Source/cmSystemTools.cxx5
-rw-r--r--Source/cmTarget.cxx84
-rw-r--r--Source/cmTarget.h4
-rw-r--r--Source/cmTargetExport.h2
-rw-r--r--Source/cmTargetSourcesCommand.cxx38
-rw-r--r--Source/cmTryRunCommand.cxx171
-rw-r--r--Source/cmTryRunCommand.h10
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx43
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx71
-rw-r--r--Source/cmXCodeScheme.cxx10
-rw-r--r--Source/cmake.cxx54
-rw-r--r--Source/cmake.h22
-rw-r--r--Source/kwsys/SystemTools.cxx40
-rw-r--r--Templates/MSBuild/FlagTables/v10_Cuda.json112
-rw-r--r--Tests/Assembler/CMakeLists.txt6
-rw-r--r--Tests/CMakeLib/testArgumentParser.cxx72
-rw-r--r--Tests/CMakeLists.txt117
-rw-r--r--Tests/CMakeOnly/AllFindModules/CMakeLists.txt13
-rw-r--r--Tests/CTestTestFdSetSize/sleep.c14
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt11
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt14
-rw-r--r--Tests/ExternalProject/CMakeLists.txt6
-rw-r--r--Tests/FindOpenAL/CMakeLists.txt10
-rw-r--r--Tests/FindOpenAL/Test/CMakeLists.txt14
-rw-r--r--Tests/FindOpenAL/Test/main.cxx13
-rw-r--r--Tests/FindVulkan/Test/CMakeLists.txt20
-rw-r--r--Tests/FindVulkan/Test/Run-dxc_exe.cmake20
-rw-r--r--Tests/FindVulkan/Test/main-dxc_lib.cxx23
-rw-r--r--Tests/FindVulkan/Test/main-volk.cxx14
-rw-r--r--Tests/IncludeDirectories/CMakeLists.txt54
-rw-r--r--Tests/LoadCommand/CMakeCommands/cmTestCommand.c17
-rw-r--r--Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c17
-rw-r--r--Tests/RunCMake/AutoExportDll/AutoExport.cmake4
-rw-r--r--Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt10
-rw-r--r--Tests/RunCMake/CMakeLists.txt5
-rw-r--r--Tests/RunCMake/CTestTimeout/TestTimeout.c1
-rw-r--r--Tests/RunCMake/CXXModules/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake40
-rw-r--r--Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake22
-rw-r--r--Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake35
-rw-r--r--Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake22
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt12
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt6
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake13
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake13
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt12
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt6
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake12
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake12
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMI-check.cmake24
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMI-stderr.txt6
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMI.cmake23
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt6
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake9
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake13
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt6
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake9
-rw-r--r--Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake8
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake34
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake76
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake34
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake85
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake34
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt11
-rw-r--r--Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake59
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX-stderr.txt20
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX.cmake9
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20-stderr.txt20
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20.cmake11
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt20
-rw-r--r--Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake10
-rw-r--r--Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt30
-rw-r--r--Tests/RunCMake/CXXModules/NoDyndepSupport.cmake16
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt22
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake15
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt17
-rw-r--r--Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake13
-rw-r--r--Tests/RunCMake/CXXModules/RunCMakeTest.cmake169
-rw-r--r--Tests/RunCMake/CXXModules/check-json.cmake160
-rw-r--r--Tests/RunCMake/CXXModules/compiler_introspection.cmake25
-rw-r--r--Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake22
-rw-r--r--Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake27
-rw-r--r--Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake18
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt56
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt32
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt59
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt32
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt53
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt32
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt56
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt32
-rw-r--r--Tests/RunCMake/CXXModules/examples/generated-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt23
-rw-r--r--Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in5
-rw-r--r--Tests/RunCMake/CXXModules/examples/generated/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt27
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake7
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt25
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake4
-rw-r--r--Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt31
-rw-r--r--Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx9
-rw-r--r--Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/library-static-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt30
-rw-r--r--Tests/RunCMake/CXXModules/examples/library/importable.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/library/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/partitions-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt31
-rw-r--r--Tests/RunCMake/CXXModules/examples/partitions/importable.cxx9
-rw-r--r--Tests/RunCMake/CXXModules/examples/partitions/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/partitions/partition.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt1
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt1
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt22
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx8
-rw-r--r--Tests/RunCMake/CXXModules/examples/simple-stderr.txt9
-rw-r--r--Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt18
-rw-r--r--Tests/RunCMake/CXXModules/examples/simple/importable.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/examples/simple/main.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json45
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json45
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json73
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json73
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json40
-rw-r--r--Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json40
-rw-r--r--Tests/RunCMake/CXXModules/sources/c-anchor.c4
-rw-r--r--Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx4
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-header.h9
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-impl.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx11
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-internal-part.cxx3
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-part-impl.cxx13
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-part.cxx3
-rw-r--r--Tests/RunCMake/CXXModules/sources/module-use.cxx6
-rw-r--r--Tests/RunCMake/CXXModules/sources/module.cxx5
-rw-r--r--Tests/RunCMake/CommandLine/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/CommandLine/cmake_depends-stdout.txt2
-rw-r--r--Tests/RunCMake/FileAPI/codemodel-v2-check.py10
-rw-r--r--Tests/RunCMake/File_Archive/RunCMakeTest.cmake3
-rw-r--r--Tests/RunCMake/File_Archive/create-missing-args-result.txt1
-rw-r--r--Tests/RunCMake/File_Archive/create-missing-args-stderr.txt9
-rw-r--r--Tests/RunCMake/File_Archive/create-missing-args.cmake8
-rw-r--r--Tests/RunCMake/File_Archive/extract-missing-args-result.txt1
-rw-r--r--Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt7
-rw-r--r--Tests/RunCMake/File_Archive/extract-missing-args.cmake5
-rw-r--r--Tests/RunCMake/File_Configure/BadArgContent-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/NoArgContent-result.txt1
-rw-r--r--Tests/RunCMake/File_Configure/NoArgContent-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/NoArgContent.cmake1
-rw-r--r--Tests/RunCMake/File_Configure/NoArgOutput-result.txt1
-rw-r--r--Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Configure/NoArgOutput.cmake1
-rw-r--r--Tests/RunCMake/File_Configure/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Generate/InputAndContent-check.cmake8
-rw-r--r--Tests/RunCMake/File_Generate/InputAndContent-input.txt1
-rw-r--r--Tests/RunCMake/File_Generate/InputAndContent.cmake10
-rw-r--r--Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt4
-rw-r--r--Tests/RunCMake/File_Generate/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake25
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake28
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake3
-rw-r--r--Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake9
-rw-r--r--Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake64
-rw-r--r--Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake19
-rw-r--r--Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake2
-rw-r--r--Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake2
-rw-r--r--Tests/RunCMake/cmake_language/RunCMakeTest.cmake58
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level.cmake5
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt1
-rw-r--r--Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt1
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/file/TIMESTAMP-stdout.txt1
-rw-r--r--Tests/RunCMake/file/TIMESTAMP.cmake2
-rw-r--r--Tests/RunCMake/find_file/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt1
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-no-function.cmake2
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt1
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt4
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake5
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-stderr.txt3
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-stdout.txt3
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt1
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake2
-rw-r--r--Tests/RunCMake/find_file/VALIDATOR.cmake39
-rw-r--r--Tests/RunCMake/find_library/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt1
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-no-function.cmake2
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt1
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt4
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake5
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-stderr.txt3
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-stdout.txt3
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt1
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake2
-rw-r--r--Tests/RunCMake/find_library/VALIDATOR.cmake41
-rw-r--r--Tests/RunCMake/find_path/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt1
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-no-function.cmake2
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt1
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt4
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake5
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-stderr.txt3
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-stdout.txt3
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt1
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake2
-rw-r--r--Tests/RunCMake/find_path/VALIDATOR.cmake39
-rw-r--r--Tests/RunCMake/find_program/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt1
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-no-function.cmake2
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt1
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt4
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake5
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-stderr.txt3
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-stdout.txt3
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt1
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt4
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake2
-rw-r--r--Tests/RunCMake/find_program/VALIDATOR.cmake39
-rw-r--r--Tests/RunCMake/project/LanguagesDuplicate-check.cmake10
-rw-r--r--Tests/RunCMake/project/LanguagesDuplicate.cmake11
-rw-r--r--Tests/RunCMake/project/RunCMakeTest.cmake5
-rw-r--r--Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt10
-rw-r--r--Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt1
-rw-r--r--Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt12
-rw-r--r--Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake6
-rw-r--r--Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt1
-rw-r--r--Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt12
-rw-r--r--Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake6
-rw-r--r--Tests/RunCMake/target_sources/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/try_compile/CxxStandard-stderr.txt15
-rw-r--r--Tests/RunCMake/try_run/BadStdErrVariable-result.txt1
-rw-r--r--Tests/RunCMake/try_run/BadStdErrVariable-stderr.txt5
-rw-r--r--Tests/RunCMake/try_run/BadStdErrVariable.cmake5
-rw-r--r--Tests/RunCMake/try_run/BadStdOutVariable-result.txt1
-rw-r--r--Tests/RunCMake/try_run/BadStdOutVariable-stderr.txt5
-rw-r--r--Tests/RunCMake/try_run/BadStdOutVariable.cmake5
-rw-r--r--Tests/RunCMake/try_run/RunCMakeTest.cmake3
-rw-r--r--Tests/SwiftOnly/CMakeLists.txt1
-rw-r--r--Tests/SwiftOnly/main.swift6
-rw-r--r--Tests/TryCompile/CMakeLists.txt23
-rw-r--r--Tests/TryCompile/stdout_and_stderr.c8
-rw-r--r--Utilities/Doxygen/CMakeLists.txt2
-rw-r--r--Utilities/Sphinx/CMakeLists.txt2
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c24
-rwxr-xr-xbootstrap3
486 files changed, 8106 insertions, 1330 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8f26508..f321d33 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -275,6 +275,26 @@ t:hip4.2-radeon:
variables:
CMAKE_CI_NO_MR: "true"
+t:linux-gcc-cxx-modules-ninja:
+ extends:
+ - .gcc_cxx_modules_ninja
+ - .cmake_test_linux_release
+ - .linux_builder_tags
+ - .run_dependent
+ - .needs_centos6_x86_64
+ variables:
+ CMAKE_CI_JOB_NIGHTLY: "true"
+
+t:linux-gcc-cxx-modules-ninja-multi:
+ extends:
+ - .gcc_cxx_modules_ninja_multi
+ - .cmake_test_linux_release
+ - .linux_builder_tags
+ - .run_dependent
+ - .needs_centos6_x86_64
+ variables:
+ CMAKE_CI_JOB_NIGHTLY: "true"
+
b:fedora36-ninja:
extends:
- .fedora36_ninja
diff --git a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake
index bbccbcf..08c1a1a 100644
--- a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake
+++ b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake
@@ -44,6 +44,7 @@ set(CMake_TEST_FindMPI_Fortran "ON" CACHE BOOL "")
set(CMake_TEST_FindMPI "ON" CACHE BOOL "")
set(CMake_TEST_FindODBC "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenACC "ON" CACHE BOOL "")
+set(CMake_TEST_FindOpenAL "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenGL "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenMP_C "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenMP_CXX "ON" CACHE BOOL "")
diff --git a/.gitlab/ci/configure_debian10_ninja.cmake b/.gitlab/ci/configure_debian10_ninja.cmake
index 2fcff7a..12564fa 100644
--- a/.gitlab/ci/configure_debian10_ninja.cmake
+++ b/.gitlab/ci/configure_debian10_ninja.cmake
@@ -48,6 +48,7 @@ set(CMake_TEST_FindMPI_Fortran "ON" CACHE BOOL "")
set(CMake_TEST_FindMPI "ON" CACHE BOOL "")
set(CMake_TEST_FindODBC "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenACC "ON" CACHE BOOL "")
+set(CMake_TEST_FindOpenAL "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenGL "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenMP_C "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenMP_CXX "ON" CACHE BOOL "")
diff --git a/.gitlab/ci/configure_fedora36_makefiles.cmake b/.gitlab/ci/configure_fedora36_makefiles.cmake
index c5b5190..7abc269 100644
--- a/.gitlab/ci/configure_fedora36_makefiles.cmake
+++ b/.gitlab/ci/configure_fedora36_makefiles.cmake
@@ -47,6 +47,7 @@ set(CMake_TEST_FindMPI_Fortran "ON" CACHE BOOL "")
set(CMake_TEST_FindMPI "ON" CACHE BOOL "")
set(CMake_TEST_FindODBC "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenACC "ON" CACHE BOOL "")
+set(CMake_TEST_FindOpenAL "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenGL "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenMP_C "ON" CACHE BOOL "")
set(CMake_TEST_FindOpenMP_CXX "ON" CACHE BOOL "")
diff --git a/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja.cmake b/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja.cmake
new file mode 100644
index 0000000..bf990c8
--- /dev/null
+++ b/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja.cmake
@@ -0,0 +1,4 @@
+set(CMake_TEST_MODULE_COMPILATION "named,partitions,internal_partitions" CACHE STRING "")
+set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_gcc.cmake" CACHE STRING "")
+
+include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
diff --git a/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja_multi.cmake b/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja_multi.cmake
new file mode 100644
index 0000000..bf990c8
--- /dev/null
+++ b/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja_multi.cmake
@@ -0,0 +1,4 @@
+set(CMake_TEST_MODULE_COMPILATION "named,partitions,internal_partitions" CACHE STRING "")
+set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_gcc.cmake" CACHE STRING "")
+
+include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake")
diff --git a/.gitlab/ci/cxx_modules_rules_gcc.cmake b/.gitlab/ci/cxx_modules_rules_gcc.cmake
new file mode 100644
index 0000000..d800099
--- /dev/null
+++ b/.gitlab/ci/cxx_modules_rules_gcc.cmake
@@ -0,0 +1,10 @@
+set(CMake_TEST_CXXModules_UUID "a246741c-d067-4019-a8fb-3d16b0c9d1d3")
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE
+ "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E -x c++ <SOURCE>"
+ " -MT <DYNDEP_FILE> -MD -MF <DEP_FILE>"
+ " -fmodules-ts -fdep-file=<DYNDEP_FILE> -fdep-output=<OBJECT> -fdep-format=trtbd"
+ " -o <PREPROCESSED_SOURCE>")
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "gcc")
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "-fmodules-ts -fmodule-mapper=<MODULE_MAP_FILE> -fdep-format=trtbd -x c++")
diff --git a/.gitlab/ci/docker/gcc_cxx_modules/Dockerfile b/.gitlab/ci/docker/gcc_cxx_modules/Dockerfile
new file mode 100644
index 0000000..e0af0b9
--- /dev/null
+++ b/.gitlab/ci/docker/gcc_cxx_modules/Dockerfile
@@ -0,0 +1,9 @@
+FROM fedora:36
+MAINTAINER Ben Boeckel <ben.boeckel@kitware.com>
+
+# Install build dependencies for packages.
+COPY install_deps.sh /root/install_deps.sh
+RUN sh /root/install_deps.sh
+
+COPY install_gcc.sh /root/install_gcc.sh
+RUN sh /root/install_gcc.sh
diff --git a/.gitlab/ci/docker/gcc_cxx_modules/install_deps.sh b/.gitlab/ci/docker/gcc_cxx_modules/install_deps.sh
new file mode 100755
index 0000000..b8b706b
--- /dev/null
+++ b/.gitlab/ci/docker/gcc_cxx_modules/install_deps.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+set -e
+
+dnf install -y --setopt=install_weak_deps=False \
+ gcc-c++ mpfr-devel libmpc-devel isl-devel flex bison file findutils diffutils git-core
+dnf clean all
diff --git a/.gitlab/ci/docker/gcc_cxx_modules/install_gcc.sh b/.gitlab/ci/docker/gcc_cxx_modules/install_gcc.sh
new file mode 100755
index 0000000..20ea35f
--- /dev/null
+++ b/.gitlab/ci/docker/gcc_cxx_modules/install_gcc.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+set -e
+
+readonly revision="p1689r5-cmake-ci-20220614" # 3075e510e3d29583f8886b95aff044c0474c84a5
+readonly tarball="https://github.com/mathstuf/gcc/archive/$revision.tar.gz"
+
+readonly workdir="$HOME/gcc"
+readonly srcdir="$workdir/gcc"
+readonly builddir="$workdir/build"
+readonly njobs="$( nproc )"
+
+mkdir -p "$workdir"
+cd "$workdir"
+curl -L "$tarball" > "gcc-$revision.tar.gz"
+tar xf "gcc-$revision.tar.gz"
+mv "gcc-$revision" "$srcdir"
+mkdir -p "$builddir"
+cd "$builddir"
+"$srcdir/configure" \
+ --disable-multilib \
+ --enable-languages=c,c++ \
+ --prefix="/opt/gcc-p1689"
+make "-j$njobs"
+make "-j$njobs" install-strip
+rm -rf "$workdir"
diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml
index 12fbc1e..25d5365 100644
--- a/.gitlab/os-linux.yml
+++ b/.gitlab/os-linux.yml
@@ -299,6 +299,30 @@
CMAKE_CONFIGURATION: hip4.2_radeon
CMAKE_GENERATOR: "Ninja Multi-Config"
+### C++ modules
+
+.gcc_cxx_modules_x86_64:
+ image: "kitware/cmake:ci-gcc_cxx_modules-x86_64-2022-06-21"
+
+ variables:
+ GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci"
+ CMAKE_ARCH: x86_64
+ CC: "/opt/gcc-p1689/bin/gcc"
+ CXX: "/opt/gcc-p1689/bin/g++"
+
+.gcc_cxx_modules_ninja:
+ extends: .gcc_cxx_modules_x86_64
+
+ variables:
+ CMAKE_CONFIGURATION: linux_gcc_cxx_modules_ninja
+
+.gcc_cxx_modules_ninja_multi:
+ extends: .gcc_cxx_modules_x86_64
+
+ variables:
+ CMAKE_CONFIGURATION: linux_gcc_cxx_modules_ninja_multi
+ CMAKE_GENERATOR: "Ninja Multi-Config"
+
## Tags
.linux_builder_tags:
diff --git a/Auxiliary/cmake-mode.el b/Auxiliary/cmake-mode.el
index 8224d9e..2de9b98 100644
--- a/Auxiliary/cmake-mode.el
+++ b/Auxiliary/cmake-mode.el
@@ -288,6 +288,39 @@ This puts the mark at the end, and point at the beginning."
;------------------------------------------------------------------------------
+(defun cmake--syntax-propertize-until-bracket-close (syntax)
+ ;; This function assumes that a previous search has matched the
+ ;; beginning of a bracket_comment or bracket_argument and that the
+ ;; second capture group has matched the equal signs between the two
+ ;; opening brackets
+ (let* ((mb (match-beginning 2))
+ (me (match-end 2))
+ (cb (format "]%s]" (buffer-substring mb me))))
+ (save-match-data
+ (if (search-forward cb end 'move)
+ (progn
+ (setq me (match-end 0))
+ (put-text-property
+ (1- me)
+ me
+ 'syntax-table
+ (string-to-syntax syntax)))
+ (setq me end)))
+ (put-text-property
+ (match-beginning 1)
+ me
+ 'syntax-multiline
+ t)))
+
+(defconst cmake--syntax-propertize-function
+ (syntax-propertize-rules
+ ("\\(#\\)\\[\\(=*\\)\\["
+ (1
+ (prog1 "!" (cmake--syntax-propertize-until-bracket-close "!"))))
+ ("\\(\\[\\)\\(=*\\)\\["
+ (1
+ (prog1 "|" (cmake--syntax-propertize-until-bracket-close "|"))))))
+
;; Syntax table for this mode.
(defvar cmake-mode-syntax-table nil
"Syntax table for CMake mode.")
@@ -318,7 +351,10 @@ This puts the mark at the end, and point at the beginning."
; Setup indentation function.
(set (make-local-variable 'indent-line-function) 'cmake-indent)
; Setup comment syntax.
- (set (make-local-variable 'comment-start) "#"))
+ (set (make-local-variable 'comment-start) "#")
+ ;; Setup syntax propertization
+ (set (make-local-variable 'syntax-propertize-function) cmake--syntax-propertize-function)
+ (add-hook 'syntax-propertize-extend-region-functions #'syntax-propertize-multiline nil t))
;; Default cmake-mode key bindings
(define-key cmake-mode-map "\e\C-a" #'cmake-beginning-of-defun)
diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim
index e1a2885..1273c00 100644
--- a/Auxiliary/vim/syntax/cmake.vim
+++ b/Auxiliary/vim/syntax/cmake.vim
@@ -436,6 +436,7 @@ syn keyword cmakeProperty contained
\ XCODE_SCHEME_ENVIRONMENT
\ XCODE_SCHEME_EXECUTABLE
\ XCODE_SCHEME_GUARD_MALLOC
+ \ XCODE_SCHEME_LAUNCH_MODE
\ XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
\ XCODE_SCHEME_MALLOC_GUARD_EDGES
\ XCODE_SCHEME_MALLOC_SCRIBBLE
@@ -1537,6 +1538,7 @@ syn keyword cmakeVariable contained
\ CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
\ CMAKE_XCODE_SCHEME_ENVIRONMENT
\ CMAKE_XCODE_SCHEME_GUARD_MALLOC
+ \ CMAKE_XCODE_SCHEME_LAUNCH_MODE
\ CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
\ CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES
\ CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9de5338..4d9d3ca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
-cmake_minimum_required(VERSION 3.13...3.22 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.13...3.23 FATAL_ERROR)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideC.cmake)
set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideCXX.cmake)
diff --git a/CompileFlags.cmake b/CompileFlags.cmake
index e6fb20b..5641de4 100644
--- a/CompileFlags.cmake
+++ b/CompileFlags.cmake
@@ -136,3 +136,12 @@ OFF to disable /MP completely." )
endif()
endif()
endif()
+
+# Get rid of excess -Wunused-but-set-variable on release builds with LCC >= 1.26
+foreach(l C CXX)
+ if(CMAKE_${l}_COMPILER_ID STREQUAL "LCC" AND NOT CMAKE_${l}_COMPILER_VERSION VERSION_LESS 1.26)
+ foreach(c MINSIZEREL RELEASE RELWITHDEBINFO)
+ string(APPEND "CMAKE_${l}_FLAGS_${c}" " -Wno-unused-but-set-variable")
+ endforeach()
+ endif()
+endforeach()
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt
index 6683edb..e5e7496 100644
--- a/Help/command/FIND_XXX.txt
+++ b/Help/command/FIND_XXX.txt
@@ -15,6 +15,7 @@ The general signature is:
[PATHS [path | ENV var]... ]
[REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)]
[PATH_SUFFIXES suffix1 [suffix2 ...]]
+ [VALIDATOR function]
[DOC "cache documentation string"]
[NO_CACHE]
[REQUIRED]
@@ -66,6 +67,26 @@ Options include:
Specify additional subdirectories to check below each directory
location otherwise considered.
+``VALIDATOR``
+ .. versionadded:: 3.25
+
+ Specify a :command:`function` (a :command:`macro` is not an acceptable
+ choice) which will be called for each found item. The search ends when
+ the validation function returns a successful status.
+
+ The validation function expects two arguments: output variable name and item
+ value. By default, the output variable name already holds a ``TRUE`` value.
+
+ .. parsed-literal::
+
+ function (MY_CHECK output_status item)
+ if (NOT item MATCHES ...)
+ set(${output_status} FALSE PARENT_SCOPE)
+ endif()
+ endfunction()
+
+ |FIND_XXX| (result NAMES ... VALIDATOR my_check)
+
``DOC``
Specify the documentation string for the ``<VAR>`` cache entry.
diff --git a/Help/command/cmake_language.rst b/Help/command/cmake_language.rst
index cb8d60b..377e42d 100644
--- a/Help/command/cmake_language.rst
+++ b/Help/command/cmake_language.rst
@@ -14,6 +14,7 @@ Synopsis
cmake_language(`EVAL`_ CODE <code>...)
cmake_language(`DEFER`_ <options>... CALL <command> [<arg>...])
cmake_language(`SET_DEPENDENCY_PROVIDER`_ <command> SUPPORTED_METHODS <methods>...)
+ cmake_language(`GET_MESSAGE_LOG_LEVEL`_ <out-var>)
Introduction
^^^^^^^^^^^^
@@ -491,3 +492,28 @@ calling the provider command recursively for the same dependency.
SET_DEPENDENCY_PROVIDER mycomp_provide_dependency
SUPPORTED_METHODS FIND_PACKAGE
)
+
+Getting current message log level
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.25
+
+.. _GET_MESSAGE_LOG_LEVEL:
+.. _query_message_log_level:
+
+.. code-block:: cmake
+
+ cmake_language(GET_MESSAGE_LOG_LEVEL <output_variable>)
+
+Writes the current :command:`message` logging level
+into the given ``<output_variable>``.
+
+See :command:`message` for the possible logging levels.
+
+The current message logging level can be set either using the ``--log-level``
+command line option of the :manual:`cmake(1)` program or using
+the :variable:`CMAKE_MESSAGE_LOG_LEVEL` variable.
+
+If both the command line option and the variable are set, the command line
+option takes precedence. If neither are set, the default logging level
+is returned.
diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst
index d2acbc8..d9103b8 100644
--- a/Help/command/enable_language.rst
+++ b/Help/command/enable_language.rst
@@ -1,13 +1,14 @@
enable_language
---------------
-Enable a language (CXX/C/OBJC/OBJCXX/Fortran/etc)
+
+Enable languages (CXX/C/OBJC/OBJCXX/Fortran/etc)
.. code-block:: cmake
- enable_language(<lang> [OPTIONAL] )
+ enable_language(<lang>... [OPTIONAL])
-Enables support for the named language in CMake. This is
-the same as the :command:`project` command but does not create any of the extra
+Enables support for the named languages in CMake. This is the same as
+the :command:`project` command but does not create any of the extra
variables that are created by the project command. Example languages
are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``OBJCXX``, ``Fortran``,
``HIP``, ``ISPC``, and ``ASM``.
diff --git a/Help/command/export.rst b/Help/command/export.rst
index dc69645..6785b05 100644
--- a/Help/command/export.rst
+++ b/Help/command/export.rst
@@ -25,7 +25,8 @@ Exporting Targets
.. code-block:: cmake
export(TARGETS <target>... [NAMESPACE <namespace>]
- [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES])
+ [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES]
+ [CXX_MODULES_DIRECTORY <directory>])
Creates a file ``<filename>`` that may be included by outside projects to
import targets named by ``<target>...`` from the current project's build tree.
@@ -52,6 +53,16 @@ The options are:
in the export, even when policy :policy:`CMP0022` is NEW. This is useful
to support consumers using CMake versions older than 2.8.12.
+``CXX_MODULES_DIRECTORY <directory>``
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+ Export C++ module properties to files under the given directory. Each file
+ will be named according to the target's export name (without any namespace).
+ These files will automatically be included from the export file.
+
This signature requires all targets to be listed explicitly. If a library
target is included in the export, but a target to which it links is not
included, the behavior is unspecified. See the `export(EXPORT)`_ signature
@@ -95,7 +106,8 @@ Exporting Targets matching install(EXPORT)
.. code-block:: cmake
- export(EXPORT <export-name> [NAMESPACE <namespace>] [FILE <filename>])
+ export(EXPORT <export-name> [NAMESPACE <namespace>] [FILE <filename>]
+ [CXX_MODULES_DIRECTORY <directory>])
Creates a file ``<filename>`` that may be included by outside projects to
import targets from the current project's build tree. This is the same
diff --git a/Help/command/foreach.rst b/Help/command/foreach.rst
index d9f54ca..ddf8dfa 100644
--- a/Help/command/foreach.rst
+++ b/Help/command/foreach.rst
@@ -130,3 +130,11 @@ yields
-- en=two, ba=dua
-- en=three, ba=tiga
-- en=four, ba=
+
+See Also
+^^^^^^^^
+
+* :command:`break`
+* :command:`continue`
+* :command:`endforeach`
+* :command:`while`
diff --git a/Help/command/function.rst b/Help/command/function.rst
index 3d25aa4..fc55c03 100644
--- a/Help/command/function.rst
+++ b/Help/command/function.rst
@@ -73,3 +73,9 @@ argument. Referencing to ``ARGV#`` arguments beyond ``ARGC`` have
undefined behavior. Checking that ``ARGC`` is greater than ``#`` is
the only way to ensure that ``ARGV#`` was passed to the function as an
extra argument.
+
+See Also
+^^^^^^^^
+
+* :command:`endfunction`
+* :command:`return`
diff --git a/Help/command/if.rst b/Help/command/if.rst
index c096725..3908a8c 100644
--- a/Help/command/if.rst
+++ b/Help/command/if.rst
@@ -419,3 +419,10 @@ There is no automatic evaluation for environment or cache
:ref:`Variable References`. Their values must be referenced as
``$ENV{<name>}`` or ``$CACHE{<name>}`` wherever the above-documented
condition syntax accepts ``<variable|string>``.
+
+See also
+^^^^^^^^
+
+ * :command:`else`
+ * :command:`elseif`
+ * :command:`endif`
diff --git a/Help/command/install.rst b/Help/command/install.rst
index 973aa31..5aa3a4b 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -132,7 +132,7 @@ Installing Targets
install(TARGETS targets... [EXPORT <export-name>]
[RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>]
[[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
- PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>]
+ PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>|CXX_MODULES_BMI]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
@@ -215,11 +215,21 @@ that may be installed:
``/blah/include/myproj/here.h`` with a base directory ``/blah/include``
would be installed to ``myproj/here.h`` below the destination.
+``CXX_MODULES_BMI``
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+ Any module files from C++ modules from ``PUBLIC`` sources in a file set of
+ type ``CXX_MODULES`` will be installed to the given ``DESTINATION``. All
+ modules are placed directly in the destination as no directory structure is
+ derived from the names of the modules. An empty ``DESTINATION`` may be used
+ to suppress installing these files (for use in generic code).
+
For each of these arguments given, the arguments following them only apply
to the target or file type specified in the argument. If none is given, the
-installation properties apply to all target types. If only one is given then
-only targets of that type will be installed (which can be used to install
-just a DLL or just an import library.)
+installation properties apply to all target types.
For regular executables, static libraries and shared libraries, the
``DESTINATION`` argument is not required. For these target types, when
@@ -233,6 +243,14 @@ Apple bundles and frameworks. A destination can be omitted for interface and
object libraries, but they are handled differently (see the discussion of this
topic toward the end of this section).
+For shared libraries on DLL platforms, if neither ``RUNTIME`` nor ``ARCHIVE``
+destinations are specified, both the ``RUNTIME`` and ``ARCHIVE`` components are
+installed to their default destinations. If either a ``RUNTIME`` or ``ARCHIVE``
+destination is specified, the component is installed to that destination, and
+the other component is not installed. If both ``RUNTIME`` and ``ARCHIVE``
+destinations are specified, then both components are installed to their
+respective destinations.
+
The following table shows the target types with their associated variables and
built-in defaults that apply when no destination is given:
@@ -778,9 +796,10 @@ Installing Exports
.. code-block:: cmake
install(EXPORT <export-name> DESTINATION <dir>
- [NAMESPACE <namespace>] [[FILE <name>.cmake]|
+ [NAMESPACE <namespace>] [FILE <name>.cmake]
[PERMISSIONS permissions...]
- [CONFIGURATIONS [Debug|Release|...]]
+ [CONFIGURATIONS [Debug|Release|...]
+ [CXX_MODULES_DIRECTORY <directory>]
[EXPORT_LINK_INTERFACE_LIBRARIES]
[COMPONENT <component>]
[EXCLUDE_FROM_ALL])
@@ -836,6 +855,18 @@ library is always installed if the headers and CMake export file are present.
to an ndk build system complete with transitive dependencies, include flags
and defines required to use the libraries.
+``CXX_MODULES_DIRECTORY``
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+ Specify a subdirectory to store C++ module information for targets in the
+ export set. This directory will be populated with files which add the
+ necessary target property information to the relevant targets. Note that
+ without this information, none of the C++ modules which are part of the
+ targets in the export set will support being imported in consuming targets.
+
The ``EXPORT`` form is useful to help outside projects use targets built
and installed by the current project. For example, the code
diff --git a/Help/command/target_sources.rst b/Help/command/target_sources.rst
index 72119f6..a079307 100644
--- a/Help/command/target_sources.rst
+++ b/Help/command/target_sources.rst
@@ -75,9 +75,33 @@ File Sets
Adds a file set to a target, or adds files to an existing file set. Targets
have zero or more named file sets. Each file set has a name, a type, a scope of
``INTERFACE``, ``PUBLIC``, or ``PRIVATE``, one or more base directories, and
-files within those directories. The only acceptable type is ``HEADERS``. The
-optional default file sets are named after their type. The target may not be a
-custom target or :prop_tgt:`FRAMEWORK` target.
+files within those directories. The acceptable types include:
+
+``HEADERS``
+
+ Sources intended to be used via a language's ``#include`` mechanism.
+
+``CXX_MODULES``
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+ Sources which contain C++ interface module or partition units (i.e., those
+ using the ``export`` keyword). This file set type may not have an
+ ``INTERFACE`` scope except on ``IMPORTED`` targets.
+
+``CXX_MODULE_HEADER_UNITS``
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+ C++ header sources which may be imported by other C++ source code. This file
+ set type may not have an ``INTERFACE`` scope except on ``IMPORTED`` targets.
+
+The optional default file sets are named after their type. The target may not
+be a custom target or :prop_tgt:`FRAMEWORK` target.
Files in a ``PRIVATE`` or ``PUBLIC`` file set are marked as source files for
the purposes of IDE integration. Additionally, files in ``HEADERS`` file sets
@@ -93,16 +117,17 @@ Each ``target_sources(FILE_SET)`` entry starts with ``INTERFACE``, ``PUBLIC``, o
The name of the file set to create or add to. It must contain only letters,
numbers and underscores. Names starting with a capital letter are reserved
- for built-in file sets predefined by CMake. The only predefined set name is
- ``HEADERS``. All other set names must not start with a capital letter or
+ for built-in file sets predefined by CMake. The only predefined set names
+ are those matching the acceptable types. All other set names must not start
+ with a capital letter or
underscore.
``TYPE <type>``
- Every file set is associated with a particular type of file. ``HEADERS``
- is currently the only defined type and it is an error to specify anything
- else. As a special case, if the name of the file set is ``HEADERS``, the
- type does not need to be specified and the ``TYPE <type>`` arguments can be
+ Every file set is associated with a particular type of file. Only types
+ specified above may be used and it is an error to specify anything else. As
+ a special case, if the name of the file set is one of the types, the type
+ does not need to be specified and the ``TYPE <type>`` arguments can be
omitted. For all other file set names, ``TYPE`` is required.
``BASE_DIRS <dirs>...``
@@ -134,6 +159,8 @@ Each ``target_sources(FILE_SET)`` entry starts with ``INTERFACE``, ``PUBLIC``, o
The following target properties are set by ``target_sources(FILE_SET)``,
but they should not generally be manipulated directly:
+For file sets of type ``HEADERS``:
+
* :prop_tgt:`HEADER_SETS`
* :prop_tgt:`INTERFACE_HEADER_SETS`
* :prop_tgt:`HEADER_SET`
@@ -141,17 +168,37 @@ but they should not generally be manipulated directly:
* :prop_tgt:`HEADER_DIRS`
* :prop_tgt:`HEADER_DIRS_<NAME>`
+For file sets of type ``CXX_MODULES``:
+
+* :prop_tgt:`CXX_MODULE_SETS`
+* :prop_tgt:`INTERFACE_CXX_MODULE_SETS`
+* :prop_tgt:`CXX_MODULE_SET`
+* :prop_tgt:`CXX_MODULE_SET_<NAME>`
+* :prop_tgt:`CXX_MODULE_DIRS`
+* :prop_tgt:`CXX_MODULE_DIRS_<NAME>`
+
+For file sets of type ``CXX_MODULE_HEADER_UNITS``:
+
+* :prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS`
+* :prop_tgt:`INTERFACE_CXX_MODULE_HEADER_UNIT_SETS`
+* :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET`
+* :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET_<NAME>`
+* :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS`
+* :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS_<NAME>`
+
Target properties related to include directories are also modified by
``target_sources(FILE_SET)`` as follows:
:prop_tgt:`INCLUDE_DIRECTORIES`
- If the ``TYPE`` is ``HEADERS``, and the scope of the file set is ``PRIVATE``
- or ``PUBLIC``, all of the ``BASE_DIRS`` of the file set are wrapped in
- :genex:`$<BUILD_INTERFACE>` and appended to this property.
+ If the ``TYPE`` is ``HEADERS`` or ``CXX_MODULE_HEADER_UNITS``, and the scope
+ of the file set is ``PRIVATE`` or ``PUBLIC``, all of the ``BASE_DIRS`` of
+ the file set are wrapped in :genex:`$<BUILD_INTERFACE>` and appended to this
+ property.
:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`
- If the ``TYPE`` is ``HEADERS``, and the scope of the file set is
- ``INTERFACE`` or ``PUBLIC``, all of the ``BASE_DIRS`` of the file set are
- wrapped in :genex:`$<BUILD_INTERFACE>` and appended to this property.
+ If the ``TYPE`` is ``HEADERS`` or ``CXX_MODULE_HEADER_UNITS``, and the scope
+ of the file set is ``INTERFACE`` or ``PUBLIC``, all of the ``BASE_DIRS`` of
+ the file set are wrapped in :genex:`$<BUILD_INTERFACE>` and appended to this
+ property.
diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst
index fc41cdd..125b0ac 100644
--- a/Help/command/try_run.rst
+++ b/Help/command/try_run.rst
@@ -19,6 +19,8 @@ Try Compiling and Running Source Files
[LINK_LIBRARIES <libs>...]
[COMPILE_OUTPUT_VARIABLE <var>]
[RUN_OUTPUT_VARIABLE <var>]
+ [RUN_OUTPUT_STDOUT_VARIABLE <var>]
+ [RUN_OUTPUT_STDERR_VARIABLE <var>]
[OUTPUT_VARIABLE <var>]
[WORKING_DIRECTORY <var>]
[ARGS <args>...])
@@ -70,6 +72,16 @@ The options are:
``RUN_OUTPUT_VARIABLE <var>``
Report the output from running the executable in a given variable.
+``RUN_OUTPUT_STDOUT_VARIABLE <var>``
+ .. versionadded:: 3.25
+
+ Report the output of stdout from running the executable in a given variable.
+
+``RUN_OUTPUT_STDERR_VARIABLE <var>``
+ .. versionadded:: 3.25
+
+ Report the output of stderr from running the executable in a given variable.
+
``WORKING_DIRECTORY <var>``
.. versionadded:: 3.20
@@ -110,6 +122,7 @@ These cache entries are:
In order to make cross compiling your project easier, use ``try_run``
only if really required. If you use ``try_run``, use the
+``RUN_OUTPUT_STDOUT_VARIABLE``, ``RUN_OUTPUT_STDERR_VARIABLE``,
``RUN_OUTPUT_VARIABLE`` or ``OUTPUT_VARIABLE`` options only if really
required. Using them will require that when cross-compiling, the cache
variables will have to be set manually to the output of the executable.
diff --git a/Help/command/while.rst b/Help/command/while.rst
index a4957c1..0bafae5 100644
--- a/Help/command/while.rst
+++ b/Help/command/while.rst
@@ -23,3 +23,11 @@ Per legacy, the :command:`endwhile` command admits
an optional ``<condition>`` argument.
If used, it must be a verbatim repeat of the argument of the opening
``while`` command.
+
+See Also
+^^^^^^^^
+
+ * :command:`break`
+ * :command:`continue`
+ * :command:`foreach`
+ * :command:`endwhile`
diff --git a/Help/cpack_gen/freebsd.rst b/Help/cpack_gen/freebsd.rst
index f429bc5..faf8c74 100644
--- a/Help/cpack_gen/freebsd.rst
+++ b/Help/cpack_gen/freebsd.rst
@@ -62,8 +62,6 @@ the RPM information (e.g. package license).
- :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` (this is always set
by CPack itself, if nothing else sets it explicitly).
- - :variable:`PROJECT_DESCRIPTION` (this can be set with the DESCRIPTION
- parameter for :command:`project`).
.. variable:: CPACK_FREEBSD_PACKAGE_DESCRIPTION
@@ -75,6 +73,10 @@ the RPM information (e.g. package license).
- :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` (this may be set already
for Debian packaging, so it is used as a fallback).
+ - :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` (this is always set
+ by CPack itself, if nothing else sets it explicitly).
+ - :variable:`PROJECT_DESCRIPTION` (this can be set with the DESCRIPTION
+ parameter for :command:`project`).
.. variable:: CPACK_FREEBSD_PACKAGE_WWW
@@ -85,12 +87,12 @@ the RPM information (e.g. package license).
* Mandatory: YES
* Default:
- - :variable:`CMAKE_PROJECT_HOMEPAGE_URL`, or if that is not set,
- :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
+ - :variable:`CPACK_PACKAGE_HOMEPAGE_URL`, or if that is not set,
+ - :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already
for Debian packaging, so it is used as a fallback).
.. versionadded:: 3.12
- The ``CMAKE_PROJECT_HOMEPAGE_URL`` variable.
+ The ``CPACK_PACKAGE_HOMEPAGE_URL`` variable.
.. variable:: CPACK_FREEBSD_PACKAGE_LICENSE
diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst
index 7638d22..b8d681c 100644
--- a/Help/dev/experimental.rst
+++ b/Help/dev/experimental.rst
@@ -7,6 +7,23 @@ See documentation on `CMake Development`_ for more information.
.. _`CMake Development`: README.rst
+Features are gated behind ``CMAKE_EXPERIMENTAL_`` variables which must be set
+to specific values in order to enable their gated behaviors. Note that the
+specific values will change over time to reinforce their experimental nature.
+When used, a warning will be generated to indicate that an experimental
+feature is in use and that the affected behavior in the project is not part of
+CMake's stability guarantees.
+
+C++20 Module APIs
+=================
+
+Variable: ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+Value: ``3c375311-a3c9-4396-a187-3227ef642046``
+
+In order to support C++20 modules, there are a number of behaviors that have
+CMake APIs to provide the required features to build and export them from a
+project.
+
C++20 Module Dependencies
=========================
@@ -40,11 +57,6 @@ dependencies to the file specified by the ``<DYNDEP_FILE>`` placeholder. The
``CMAKE_EXPERIMENTAL_CXX_SCANDEP_DEPFILE_FORMAT`` file may be set to ``msvc``
for scandep rules which use ``msvc``-style dependency reporting.
-For tools which need to know the file set the source belongs to, the
-``CMAKE_EXPERIMENTAL_CXX_MODULE_SOURCE_TYPE_FLAG_<FILE_SET_TYPE>`` flag may
-be provided so that different source types can be distinguished prior to
-scanning.
-
The module dependencies should be written in the format described
by the `P1689r4`_ paper.
diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst
index cf1ec01..d57cc35 100644
--- a/Help/guide/tutorial/A Basic Starting Point.rst
+++ b/Help/guide/tutorial/A Basic Starting Point.rst
@@ -19,8 +19,19 @@ required. This will be the starting point for our tutorial. Create a
add_executable(Tutorial tutorial.cxx)
-Note that this example uses lower case commands in the ``CMakeLists.txt`` file.
-Upper, lower, and mixed case commands are supported by CMake. The source
+Any project's top most ``CMakeLists.txt`` must start by specifying
+a minimum CMake version using :command:`cmake_minimum_required`. This ensures
+that the later CMake functions are run with a compatible version of CMake.
+
+To start a project, we use :command:`project` to set the project name. This
+call is required with every project and should be called soon after
+:command:`cmake_minimum_required`.
+
+Lastly, we use :command:`add_executable` to specify we want an executable
+named Tutorial generated using ``tutorial.cxx`` as the source.
+
+Note that this example uses lower case commands in the ``CMakeLists.txt``
+file. Upper, lower, and mixed case commands are supported by CMake. The source
code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be
used to compute the square root of a number.
@@ -79,7 +90,7 @@ to set the project name and version number.
:language: cmake
:end-before: # specify the C++ standard
-Then, configure a header file to pass the version number to the source
+Then use :command:`configure_file` to pass the version number to the source
code:
.. literalinclude:: Step2/CMakeLists.txt
@@ -91,7 +102,8 @@ code:
Since the configured file will be written into the binary tree, we
must add that directory to the list of paths to search for include
-files. Add the following lines to the end of the ``CMakeLists.txt`` file:
+files. Use :command:`target_include_directories` to add the following lines to
+the end of the ``CMakeLists.txt`` file:
.. literalinclude:: Step2/CMakeLists.txt
:caption: CMakeLists.txt
@@ -107,9 +119,9 @@ directory with the following contents:
:name: TutorialConfig.h.in
:language: c++
-When CMake configures this header file the values for
+When CMake configures this header file, the values for
``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be
-replaced.
+replaced with the corresponding version numbers from the project.
Next modify ``tutorial.cxx`` to include the configured header file,
``TutorialConfig.h``.
@@ -141,7 +153,7 @@ Next let's add some C++11 features to our project by replacing ``atof`` with
We will need to explicitly state in the CMake code that it should use the
correct flags. The easiest way to enable support for a specific C++ standard
in CMake is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this
-tutorial, set the :variable:`CMAKE_CXX_STANDARD` variable in the
+tutorial, :command:`set` the :variable:`CMAKE_CXX_STANDARD` variable in the
``CMakeLists.txt`` file to ``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`
to ``True``. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the
call to ``add_executable``.
diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
index c6e0fd0..9ec195c 100644
--- a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
+++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst
@@ -1,4 +1,4 @@
-Step 8: Adding Support for a Testing Dashboard
+Step 5: Adding Support for a Testing Dashboard
==============================================
Adding support for submitting our test results to a dashboard is simple. We
@@ -9,21 +9,21 @@ we include the :module:`CTest` module in our top-level ``CMakeLists.txt``.
Replace:
-.. code-block:: cmake
+.. literalinclude:: Step5/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-enable_testing-remove
-
- # enable testing
- enable_testing()
+ :language: cmake
+ :start-after: # enable testing
+ :end-before: # does the application run
With:
-.. code-block:: cmake
+.. literalinclude:: Step6/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-include-CTest
-
- # enable dashboard scripting
- include(CTest)
+ :language: cmake
+ :start-after: # enable testing
+ :end-before: # does the application run
The :module:`CTest` module will automatically call ``enable_testing()``, so we
can remove it from our CMake files.
@@ -46,7 +46,7 @@ downloaded from the ``Settings`` page of the project on the CDash
instance that will host and display the test results. Once downloaded from
CDash, the file should not be modified locally.
-.. literalinclude:: Step9/CTestConfig.cmake
+.. literalinclude:: Step6/CTestConfig.cmake
:caption: CTestConfig.cmake
:name: CTestConfig.cmake
:language: cmake
diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst
index 8db0cb8..710e979 100644
--- a/Help/guide/tutorial/Adding System Introspection.rst
+++ b/Help/guide/tutorial/Adding System Introspection.rst
@@ -1,4 +1,4 @@
-Step 5: Adding System Introspection
+Step 6: Adding System Introspection
===================================
Let us consider adding some code to our project that depends on features the
@@ -15,7 +15,7 @@ these functions using the :module:`CheckCXXSourceCompiles` module in
Add the checks for ``log`` and ``exp`` to ``MathFunctions/CMakeLists.txt``,
after the call to :command:`target_include_directories`:
-.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-check_cxx_source_compiles
:language: cmake
@@ -25,7 +25,7 @@ after the call to :command:`target_include_directories`:
If available, use :command:`target_compile_definitions` to specify
``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions.
-.. literalinclude:: Step6/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-target_compile_definitions
:language: cmake
@@ -37,7 +37,7 @@ compute the square root in the ``mysqrt`` function. Add the following code to
the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the
``#endif`` before returning the result!):
-.. literalinclude:: Step6/MathFunctions/mysqrt.cxx
+.. literalinclude:: Step7/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-ifdef
:language: c++
@@ -46,7 +46,7 @@ the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the
We will also need to modify ``mysqrt.cxx`` to include ``cmath``.
-.. literalinclude:: Step6/MathFunctions/mysqrt.cxx
+.. literalinclude:: Step7/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx-include-cmath
:language: c++
diff --git a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst
index 70c6695..6dc4761 100644
--- a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst
+++ b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst
@@ -1,4 +1,4 @@
-Step 6: Adding a Custom Command and Generated File
+Step 7: Adding a Custom Command and Generated File
==================================================
Suppose, for the purpose of this tutorial, we decide that we never want to use
@@ -26,7 +26,7 @@ accomplish this.
First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for
``MakeTable`` is added as any other executable would be added.
-.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step8/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-add_executable-MakeTable
:language: cmake
@@ -36,7 +36,7 @@ First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for
Then we add a custom command that specifies how to produce ``Table.h``
by running MakeTable.
-.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step8/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-add_custom_command-Table.h
:language: cmake
@@ -47,7 +47,7 @@ Next we have to let CMake know that ``mysqrt.cxx`` depends on the generated
file ``Table.h``. This is done by adding the generated ``Table.h`` to the list
of sources for the library MathFunctions.
-.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step8/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-add_library-Table.h
:language: cmake
@@ -57,7 +57,7 @@ of sources for the library MathFunctions.
We also have to add the current binary directory to the list of include
directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``.
-.. literalinclude:: Step7/MathFunctions/CMakeLists.txt
+.. literalinclude:: Step8/MathFunctions/CMakeLists.txt
:caption: MathFunctions/CMakeLists.txt
:name: MathFunctions/CMakeLists.txt-target_include_directories-Table.h
:language: cmake
@@ -67,7 +67,7 @@ directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``.
Now let's use the generated table. First, modify ``mysqrt.cxx`` to include
``Table.h``. Next, we can rewrite the ``mysqrt`` function to use the table:
-.. literalinclude:: Step7/MathFunctions/mysqrt.cxx
+.. literalinclude:: Step8/MathFunctions/mysqrt.cxx
:caption: MathFunctions/mysqrt.cxx
:name: MathFunctions/mysqrt.cxx
:language: c++
diff --git a/Help/guide/tutorial/Packaging an Installer.rst b/Help/guide/tutorial/Packaging an Installer.rst
index 0ee5db2..5f0b27a 100644
--- a/Help/guide/tutorial/Packaging an Installer.rst
+++ b/Help/guide/tutorial/Packaging an Installer.rst
@@ -1,4 +1,4 @@
-Step 7: Packaging an Installer
+Step 8: Packaging an Installer
==============================
Next suppose that we want to distribute our project to other people so that
@@ -11,7 +11,7 @@ installations and package management features. To accomplish this we will use
CPack to create platform specific installers. Specifically we need to add a
few lines to the bottom of our top-level ``CMakeLists.txt`` file.
-.. literalinclude:: Step8/CMakeLists.txt
+.. literalinclude:: Step9/CMakeLists.txt
:caption: CMakeLists.txt
:name: CMakeLists.txt-include-CPack
:language: cmake
diff --git a/Help/guide/tutorial/Step5/CTestConfig.cmake b/Help/guide/tutorial/Step5/CTestConfig.cmake
new file mode 100644
index 0000000..73efdb1
--- /dev/null
+++ b/Help/guide/tutorial/Step5/CTestConfig.cmake
@@ -0,0 +1,7 @@
+set(CTEST_PROJECT_NAME "CMakeTutorial")
+set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
+
+set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_SITE "my.cdash.org")
+set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
+set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/Help/guide/tutorial/Step6/CMakeLists.txt b/Help/guide/tutorial/Step6/CMakeLists.txt
index 82d00c8..3ac5cd6 100644
--- a/Help/guide/tutorial/Step6/CMakeLists.txt
+++ b/Help/guide/tutorial/Step6/CMakeLists.txt
@@ -37,7 +37,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# enable testing
-enable_testing()
+include(CTest)
# does the application run
add_test(NAME Runs COMMAND Tutorial 25)
diff --git a/Help/guide/tutorial/Step6/CTestConfig.cmake b/Help/guide/tutorial/Step6/CTestConfig.cmake
new file mode 100644
index 0000000..73efdb1
--- /dev/null
+++ b/Help/guide/tutorial/Step6/CTestConfig.cmake
@@ -0,0 +1,7 @@
+set(CTEST_PROJECT_NAME "CMakeTutorial")
+set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
+
+set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_SITE "my.cdash.org")
+set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
+set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt
index 42e098a..b12f27d 100644
--- a/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt
@@ -6,29 +6,6 @@ target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
-# does this system provide the log and exp functions?
-include(CheckCXXSourceCompiles)
-check_cxx_source_compiles("
- #include <cmath>
- int main() {
- std::log(1.0);
- return 0;
- }
-" HAVE_LOG)
-check_cxx_source_compiles("
- #include <cmath>
- int main() {
- std::exp(1.0);
- return 0;
- }
-" HAVE_EXP)
-
-# add compile definitions
-if(HAVE_LOG AND HAVE_EXP)
- target_compile_definitions(MathFunctions
- PRIVATE "HAVE_LOG" "HAVE_EXP")
-endif()
-
# install rules
install(TARGETS MathFunctions DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx
deleted file mode 100644
index ee58556..0000000
--- a/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx
+++ /dev/null
@@ -1,25 +0,0 @@
-// A simple program that builds a sqrt table
-#include <cmath>
-#include <fstream>
-#include <iostream>
-
-int main(int argc, char* argv[])
-{
- // make sure we have enough arguments
- if (argc < 2) {
- return 1;
- }
-
- std::ofstream fout(argv[1], std::ios_base::out);
- const bool fileOpen = fout.is_open();
- if (fileOpen) {
- fout << "double sqrtTable[] = {" << std::endl;
- for (int i = 0; i < 10; ++i) {
- fout << sqrt(static_cast<double>(i)) << "," << std::endl;
- }
- // close the table with a zero
- fout << "0};" << std::endl;
- fout.close();
- }
- return fileOpen ? 0 : 1; // return 0 if wrote the file
-}
diff --git a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx
index 7eecd26..abe767d 100644
--- a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx
+++ b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx
@@ -1,4 +1,3 @@
-#include <cmath>
#include <iostream>
#include "MathFunctions.h"
@@ -10,12 +9,6 @@ double mysqrt(double x)
return 0;
}
- // if we have both log and exp then use them
-#if defined(HAVE_LOG) && defined(HAVE_EXP)
- double result = std::exp(std::log(x) * 0.5);
- std::cout << "Computing sqrt of " << x << " to be " << result
- << " using log and exp" << std::endl;
-#else
double result = x;
// do ten iterations
@@ -27,6 +20,5 @@ double mysqrt(double x)
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
-#endif
return result;
}
diff --git a/Help/guide/tutorial/Step7/CMakeLists.txt b/Help/guide/tutorial/Step7/CMakeLists.txt
index 82d00c8..3ac5cd6 100644
--- a/Help/guide/tutorial/Step7/CMakeLists.txt
+++ b/Help/guide/tutorial/Step7/CMakeLists.txt
@@ -37,7 +37,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# enable testing
-enable_testing()
+include(CTest)
# does the application run
add_test(NAME Runs COMMAND Tutorial 25)
diff --git a/Help/guide/tutorial/Step7/CTestConfig.cmake b/Help/guide/tutorial/Step7/CTestConfig.cmake
new file mode 100644
index 0000000..73efdb1
--- /dev/null
+++ b/Help/guide/tutorial/Step7/CTestConfig.cmake
@@ -0,0 +1,7 @@
+set(CTEST_PROJECT_NAME "CMakeTutorial")
+set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
+
+set(CTEST_DROP_METHOD "http")
+set(CTEST_DROP_SITE "my.cdash.org")
+set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
+set(CTEST_DROP_SITE_CDASH TRUE)
diff --git a/Help/guide/tutorial/Step7/License.txt b/Help/guide/tutorial/Step7/License.txt
deleted file mode 100644
index c62d00b..0000000
--- a/Help/guide/tutorial/Step7/License.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-This is the open source License.txt file introduced in
-CMake/Tutorial/Step7...
diff --git a/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt
index 9ede4b3..42e098a 100644
--- a/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt
+++ b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt
@@ -1,29 +1,34 @@
-# first we add the executable that generates the table
-add_executable(MakeTable MakeTable.cxx)
-
-# add the command to generate the source code
-add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- DEPENDS MakeTable
- )
-
-# add the main library
-add_library(MathFunctions
- mysqrt.cxx
- ${CMAKE_CURRENT_BINARY_DIR}/Table.h
- )
+add_library(MathFunctions mysqrt.cxx)
# state that anybody linking to us needs to include the current source dir
# to find MathFunctions.h, while we don't.
-# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the
-# TutorialConfig.h include is an implementation detail
-# state that we depend on our binary dir to find Table.h
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
- PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
)
+# does this system provide the log and exp functions?
+include(CheckCXXSourceCompiles)
+check_cxx_source_compiles("
+ #include <cmath>
+ int main() {
+ std::log(1.0);
+ return 0;
+ }
+" HAVE_LOG)
+check_cxx_source_compiles("
+ #include <cmath>
+ int main() {
+ std::exp(1.0);
+ return 0;
+ }
+" HAVE_EXP)
+
+# add compile definitions
+if(HAVE_LOG AND HAVE_EXP)
+ target_compile_definitions(MathFunctions
+ PRIVATE "HAVE_LOG" "HAVE_EXP")
+endif()
+
# install rules
install(TARGETS MathFunctions DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)
diff --git a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx
index 7d80ee9..7eecd26 100644
--- a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx
+++ b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx
@@ -1,10 +1,8 @@
+#include <cmath>
#include <iostream>
#include "MathFunctions.h"
-// include the generated table
-#include "Table.h"
-
// a hack square root calculation using simple operations
double mysqrt(double x)
{
@@ -12,12 +10,13 @@ double mysqrt(double x)
return 0;
}
- // use the table to help find an initial value
+ // if we have both log and exp then use them
+#if defined(HAVE_LOG) && defined(HAVE_EXP)
+ double result = std::exp(std::log(x) * 0.5);
+ std::cout << "Computing sqrt of " << x << " to be " << result
+ << " using log and exp" << std::endl;
+#else
double result = x;
- if (x >= 1 && x < 10) {
- std::cout << "Use the table to help find an initial value " << std::endl;
- result = sqrtTable[static_cast<int>(x)];
- }
// do ten iterations
for (int i = 0; i < 10; ++i) {
@@ -28,6 +27,6 @@ double mysqrt(double x)
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
-
+#endif
return result;
}
diff --git a/Help/guide/tutorial/Step8/CMakeLists.txt b/Help/guide/tutorial/Step8/CMakeLists.txt
index 4c78b94..3ac5cd6 100644
--- a/Help/guide/tutorial/Step8/CMakeLists.txt
+++ b/Help/guide/tutorial/Step8/CMakeLists.txt
@@ -37,7 +37,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
)
# enable testing
-enable_testing()
+include(CTest)
# does the application run
add_test(NAME Runs COMMAND Tutorial 25)
@@ -64,11 +64,3 @@ do_test(Tutorial 7 "7 is 2.645")
do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
-
-# setup installer
-include(InstallRequiredSystemLibraries)
-set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
-set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
-set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
-set(CPACK_SOURCE_GENERATOR "TGZ")
-include(CPack)
diff --git a/Help/guide/tutorial/Step9/CMakeLists.txt b/Help/guide/tutorial/Step9/CMakeLists.txt
index 6bae26e..b13a662 100644
--- a/Help/guide/tutorial/Step9/CMakeLists.txt
+++ b/Help/guide/tutorial/Step9/CMakeLists.txt
@@ -65,6 +65,7 @@ do_test(Tutorial 25 "25 is 5")
do_test(Tutorial -25 "-25 is (-nan|nan|0)")
do_test(Tutorial 0.0001 "0.0001 is 0.01")
+# setup installer
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst
index 09553cb..65d4829 100644
--- a/Help/guide/tutorial/index.rst
+++ b/Help/guide/tutorial/index.rst
@@ -25,10 +25,10 @@ provides the complete solution for the previous step.
Adding a Library
Adding Usage Requirements for a Library
Installing and Testing
+ Adding Support for a Testing Dashboard
Adding System Introspection
Adding a Custom Command and Generated File
Packaging an Installer
- Adding Support for a Testing Dashboard
Selecting Static or Shared Libraries
Adding Generator Expressions
Adding Export Configuration
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index d88322c..9fb46be 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -184,6 +184,16 @@ Properties on Targets
/prop_tgt/CUDA_STANDARD
/prop_tgt/CUDA_STANDARD_REQUIRED
/prop_tgt/CXX_EXTENSIONS
+ /prop_tgt/CXX_MODULE_DIRS
+ /prop_tgt/CXX_MODULE_DIRS_NAME
+ /prop_tgt/CXX_MODULE_SET
+ /prop_tgt/CXX_MODULE_SET_NAME
+ /prop_tgt/CXX_MODULE_SETS
+ /prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS
+ /prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME
+ /prop_tgt/CXX_MODULE_HEADER_UNIT_SET
+ /prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME
+ /prop_tgt/CXX_MODULE_HEADER_UNIT_SETS
/prop_tgt/CXX_STANDARD
/prop_tgt/CXX_STANDARD_REQUIRED
/prop_tgt/DEBUG_POSTFIX
@@ -202,6 +212,7 @@ Properties on Targets
/prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD_CONFIG
/prop_tgt/EXPORT_COMPILE_COMMANDS
/prop_tgt/EXPORT_NAME
+ /prop_tgt/EXPORT_NO_SYSTEM
/prop_tgt/EXPORT_PROPERTIES
/prop_tgt/FOLDER
/prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES
@@ -262,6 +273,8 @@ Properties on Targets
/prop_tgt/INTERFACE_COMPILE_DEFINITIONS
/prop_tgt/INTERFACE_COMPILE_FEATURES
/prop_tgt/INTERFACE_COMPILE_OPTIONS
+ /prop_tgt/INTERFACE_CXX_MODULE_SETS
+ /prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS
/prop_tgt/INTERFACE_HEADER_SETS
/prop_tgt/INTERFACE_HEADER_SETS_TO_VERIFY
/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES
@@ -375,6 +388,7 @@ Properties on Targets
/prop_tgt/Swift_LANGUAGE_VERSION
/prop_tgt/Swift_MODULE_DIRECTORY
/prop_tgt/Swift_MODULE_NAME
+ /prop_tgt/SYSTEM
/prop_tgt/TYPE
/prop_tgt/UNITY_BUILD
/prop_tgt/UNITY_BUILD_BATCH_SIZE
@@ -451,6 +465,7 @@ Properties on Targets
/prop_tgt/XCODE_SCHEME_ENVIRONMENT
/prop_tgt/XCODE_SCHEME_EXECUTABLE
/prop_tgt/XCODE_SCHEME_GUARD_MALLOC
+ /prop_tgt/XCODE_SCHEME_LAUNCH_MODE
/prop_tgt/XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
/prop_tgt/XCODE_SCHEME_MALLOC_GUARD_EDGES
/prop_tgt/XCODE_SCHEME_MALLOC_SCRIBBLE
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index 7c8a7fa..ce65aee 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -278,6 +278,7 @@ Variables that Change Behavior
/variable/CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
/variable/CMAKE_XCODE_SCHEME_ENVIRONMENT
/variable/CMAKE_XCODE_SCHEME_GUARD_MALLOC
+ /variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE
/variable/CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
/variable/CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES
/variable/CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 38105dd..2726f13 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -249,6 +249,11 @@ Options
For backward compatibility reasons, ``--loglevel`` is also accepted as a
synonym for this option.
+ .. versionadded:: 3.25
+ See the :command:`cmake_language`
+ :ref:`cmake_language <query_message_log_level>` command for a way to query
+ the current message logging level.
+
``--log-context``
Enable the :command:`message` command outputting context attached to each
message.
diff --git a/Help/prop_tgt/CXX_MODULE_DIRS.rst b/Help/prop_tgt/CXX_MODULE_DIRS.rst
new file mode 100644
index 0000000..fdf3831
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_DIRS.rst
@@ -0,0 +1,17 @@
+CXX_MODULE_DIRS
+---------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of base directories of the target's default
+C++ module set (i.e. the file set with name and type ``CXX_MODULES``). The
+property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_DIRS_<NAME>` for the list of base directories in
+other C++ module sets.
diff --git a/Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst b/Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst
new file mode 100644
index 0000000..8c27d45
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst
@@ -0,0 +1,17 @@
+CXX_MODULE_DIRS_<NAME>
+----------------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of base directories of the target's ``<NAME>`` C++
+module set, which has the set type ``CXX_MODULES``. The property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_DIRS` for the list of base directories in the
+default C++ module set. See :prop_tgt:`CXX_MODULE_SETS` for the file set names
+of all C++ module sets.
diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst
new file mode 100644
index 0000000..17e5cf0
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst
@@ -0,0 +1,17 @@
+CXX_MODULE_HEADER_UNIT_DIRS
+---------------------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of base directories of the target's default C++
+module header set (i.e. the file set with name and type
+``CXX_MODULE_HEADER_UNITS``). The property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS_<NAME>` for the list of base directories
+in other C++ module header sets.
diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst
new file mode 100644
index 0000000..ca30f23
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst
@@ -0,0 +1,19 @@
+CXX_MODULE_HEADER_UNIT_DIRS_<NAME>
+----------------------------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of base directories of the target's ``<NAME>`` C++
+module header set, which has the set type ``CXX_MODULE_HEADER_UNITS``. The
+property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS` for the list of base directories
+in the default C++ module header set. See
+:prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS` for the file set names of all C++
+module header sets.
diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst
new file mode 100644
index 0000000..f67a848
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst
@@ -0,0 +1,18 @@
+CXX_MODULE_HEADER_UNIT_SET
+--------------------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of files in the target's default C++ module header
+set, (i.e. the file set with name and type ``CXX_MODULE_HEADER_UNITS``). If
+any of the paths are relative, they are computed relative to the target's
+source directory. The property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET_<NAME>` for the list of files in
+other C++ module header sets.
diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst
new file mode 100644
index 0000000..7b4bd3f
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst
@@ -0,0 +1,18 @@
+CXX_MODULE_HEADER_UNIT_SETS
+---------------------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` C++ module header
+sets (i.e. all file sets with the type ``CXX_MODULE_HEADER_UNITS``). Files
+listed in these file sets are treated as source files for the purpose of IDE
+integration.
+
+C++ module header sets may be defined using the :command:`target_sources`
+command ``FILE_SET`` option with type ``CXX_MODULE_HEADER_UNITS``.
+
+See also :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET_<NAME>`,
+:prop_tgt:`CXX_MODULE_HEADER_UNIT_SET` and
+:prop_tgt:`INTERFACE_CXX_MODULE_HEADER_UNIT_SETS`.
diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst
new file mode 100644
index 0000000..d328950
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst
@@ -0,0 +1,19 @@
+CXX_MODULE_HEADER_UNIT_SET_<NAME>
+---------------------------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of files in the target's ``<NAME>`` C++ module header
+set, which has the set type ``CXX_MODULE_HEADER_UNITS``. If any of the paths
+are relative, they are computed relative to the target's source directory. The
+property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET` for the list of files in the
+default C++ module header set. See :prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS` for
+the file set names of all C++ module header sets.
diff --git a/Help/prop_tgt/CXX_MODULE_SET.rst b/Help/prop_tgt/CXX_MODULE_SET.rst
new file mode 100644
index 0000000..ae9000e
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_SET.rst
@@ -0,0 +1,18 @@
+CXX_MODULE_SET
+--------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of files in the target's default C++ module set,
+(i.e. the file set with name and type ``CXX_MODULES``). If any of the paths
+are relative, they are computed relative to the target's source directory. The
+property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_SET_<NAME>` for the list of files in other C++
+module sets.
diff --git a/Help/prop_tgt/CXX_MODULE_SETS.rst b/Help/prop_tgt/CXX_MODULE_SETS.rst
new file mode 100644
index 0000000..c03df39
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_SETS.rst
@@ -0,0 +1,16 @@
+CXX_MODULE_SETS
+---------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` C++ module sets (i.e.
+all file sets with the type ``CXX_MODULES``). Files listed in these file sets are
+treated as source files for the purpose of IDE integration.
+
+C++ module sets may be defined using the :command:`target_sources` command
+``FILE_SET`` option with type ``CXX_MODULES``.
+
+See also :prop_tgt:`CXX_MODULE_SET_<NAME>`, :prop_tgt:`CXX_MODULE_SET` and
+:prop_tgt:`INTERFACE_CXX_MODULE_SETS`.
diff --git a/Help/prop_tgt/CXX_MODULE_SET_NAME.rst b/Help/prop_tgt/CXX_MODULE_SET_NAME.rst
new file mode 100644
index 0000000..27c88f3
--- /dev/null
+++ b/Help/prop_tgt/CXX_MODULE_SET_NAME.rst
@@ -0,0 +1,18 @@
+CXX_MODULE_SET_<NAME>
+---------------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Semicolon-separated list of files in the target's ``<NAME>`` C++ module set,
+which has the set type ``CXX_MODULES``. If any of the paths are relative, they
+are computed relative to the target's source directory. The property supports
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+
+This property is normally only set by :command:`target_sources(FILE_SET)`
+rather than being manipulated directly.
+
+See :prop_tgt:`CXX_MODULE_SET` for the list of files in the default C++ module
+set. See :prop_tgt:`CXX_MODULE_SETS` for the file set names of all C++ module
+sets.
diff --git a/Help/prop_tgt/EXPORT_NO_SYSTEM.rst b/Help/prop_tgt/EXPORT_NO_SYSTEM.rst
new file mode 100644
index 0000000..c93d1a5
--- /dev/null
+++ b/Help/prop_tgt/EXPORT_NO_SYSTEM.rst
@@ -0,0 +1,11 @@
+EXPORT_NO_SYSTEM
+----------------
+
+.. versionadded:: 3.25
+
+Specifies that :command:`install(EXPORT)` and :command:`export` commands will
+generate a imported target with :prop_tgt:`SYSTEM` property `OFF`.
+
+See the :prop_tgt:`NO_SYSTEM_FROM_IMPORTED` target property to set this
+behavior on the target consuming the include directories rather than
+providing them.
diff --git a/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst b/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst
index ee22d6f..913d9f2 100644
--- a/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst
+++ b/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst
@@ -3,11 +3,21 @@ IMPORTED_NO_SYSTEM
.. versionadded:: 3.23
+.. deprecated:: 3.25
+
+ ``IMPORTED_NO_SYSTEM`` is deprecated. Set :prop_tgt:`SYSTEM` to `OFF`
+ instead if you don't want target's include directories to be ``SYSTEM``
+ when compiling consumers. Set :prop_tgt:`EXPORT_NO_SYSTEM` to `ON` instead
+ if you don't want the include directories of the imported target generated
+ by :command:`install(EXPORT)` and :command:`export` commands to be
+ ``SYSTEM`` when compiling consumers.
+
Specifies that an :ref:`Imported Target <Imported Targets>` is not
a ``SYSTEM`` library. This has the following effects:
* Entries of :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` are not treated
- as ``SYSTEM`` include directories when compiling consumers, as they
+ as ``SYSTEM`` include directories when compiling consumers (regardless of
+ the value of the consumed target's :prop_tgt:`SYSTEM` property), as they
would be by default. Entries of
:prop_tgt:`INTERFACE_SYSTEM_INCLUDE_DIRECTORIES` are not affected,
and will always be treated as ``SYSTEM`` include directories.
diff --git a/Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst b/Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst
new file mode 100644
index 0000000..eb3a9ff
--- /dev/null
+++ b/Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst
@@ -0,0 +1,16 @@
+INTERFACE_CXX_MODULE_HEADER_UNIT_SETS
+-------------------------------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Read-only list of the target's ``PUBLIC`` C++ module header sets (i.e. all
+file sets with the type ``CXX_MODULE_HEADER_UNITS``). Files listed in these
+C++ module header sets can be installed with :command:`install(TARGETS)` and
+exported with :command:`install(EXPORT)` and :command:`export`.
+
+C++ module header sets may be defined using the :command:`target_sources`
+command ``FILE_SET`` option with type ``CXX_MODULE_HEADER_UNITS``.
+
+See also :prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS`.
diff --git a/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst b/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst
new file mode 100644
index 0000000..cc30386
--- /dev/null
+++ b/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst
@@ -0,0 +1,16 @@
+INTERFACE_CXX_MODULE_SETS
+-------------------------
+
+.. note ::
+
+ Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API``
+
+Read-only list of the target's ``PUBLIC`` C++ module sets (i.e. all file sets
+with the type ``CXX_MODULES``). Files listed in these C++ module sets can be
+installed with :command:`install(TARGETS)` and exported with
+:command:`install(EXPORT)` and :command:`export`.
+
+C++ module sets may be defined using the :command:`target_sources` command
+``FILE_SET`` option with type ``CXX_MODULES``.
+
+See also :prop_tgt:`CXX_MODULE_SETS`.
diff --git a/Help/prop_tgt/SYSTEM.rst b/Help/prop_tgt/SYSTEM.rst
new file mode 100644
index 0000000..2db6aed
--- /dev/null
+++ b/Help/prop_tgt/SYSTEM.rst
@@ -0,0 +1,16 @@
+SYSTEM
+------
+
+.. versionadded:: 3.25
+
+Specifies that a target is a ``SYSTEM`` library. This has the following effects:
+
+* Entries of :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` are treated as ``SYSTEM``
+ include directories when compiling consumers.
+ Entries of :prop_tgt:`INTERFACE_SYSTEM_INCLUDE_DIRECTORIES` are not affected,
+ and will always be treated as ``SYSTEM`` include directories.
+
+For imported targets, this property has a default value `ON`, which means that their
+`INTERFACE_INCLUDE_DIRECTORIES` are treated as ``SYSTEM`` by default. If their
+`SYSTEM` property is `OFF`, then their `INTERFACE_INCLUDE_DIRECTORIES` will not be
+treated as ``SYSTEM``, regardless of the value of `IMPORTED_NO_SYSTEM` property.
diff --git a/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst b/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst
index 8f46d2f..eceddc1 100644
--- a/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst
+++ b/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst
@@ -41,4 +41,5 @@ The following target properties will be applied on the
- :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE`
- :prop_tgt:`XCODE_SCHEME_ENVIRONMENT`
- :prop_tgt:`XCODE_SCHEME_EXECUTABLE`
+- :prop_tgt:`XCODE_SCHEME_LAUNCH_MODE`
- :prop_tgt:`XCODE_SCHEME_WORKING_DIRECTORY`
diff --git a/Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst b/Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst
new file mode 100644
index 0000000..df5ae07
--- /dev/null
+++ b/Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst
@@ -0,0 +1,22 @@
+XCODE_SCHEME_LAUNCH_MODE
+------------------------
+
+.. versionadded:: 3.25
+
+Property value for ``Launch`` in the Info section of the generated Xcode
+scheme.
+
+Possible values are:
+
+``AUTO``
+ Launch automatically. This is the default.
+
+``WAIT``
+ Wait for the executable to be launched.
+
+This property is initialized by the value of the variable
+:variable:`CMAKE_XCODE_SCHEME_LAUNCH_MODE` if it is set when a target is
+created.
+
+Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property
+documentation to see all Xcode schema related properties.
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/FindVulkan-dxc.rst b/Help/release/dev/FindVulkan-dxc.rst
new file mode 100644
index 0000000..e22f016
--- /dev/null
+++ b/Help/release/dev/FindVulkan-dxc.rst
@@ -0,0 +1,5 @@
+FindVulkan-dxc
+--------------
+
+* The :module:`FindVulkan` module gained support for a DirectX Shader Compiler
+ component, ``dxc``.
diff --git a/Help/release/dev/cmake_language_GET_MESSAGE_LOG_LEVEL.rst b/Help/release/dev/cmake_language_GET_MESSAGE_LOG_LEVEL.rst
new file mode 100644
index 0000000..6e99a05
--- /dev/null
+++ b/Help/release/dev/cmake_language_GET_MESSAGE_LOG_LEVEL.rst
@@ -0,0 +1,6 @@
+cmake-language_GET_MESSAGE_LOG_LEVEL
+------------------------------------
+
+* The :command:`cmake_language` command gained a new
+ ``GET_MESSAGE_LOG_LEVEL`` sub-command. It can be used to
+ query the current message logging level.
diff --git a/Help/release/dev/find_item-VALIDATOR.rst b/Help/release/dev/find_item-VALIDATOR.rst
new file mode 100644
index 0000000..2cda421
--- /dev/null
+++ b/Help/release/dev/find_item-VALIDATOR.rst
@@ -0,0 +1,6 @@
+find_item-VALIDATOR
+-------------------
+
+* :command:`find_file`, :command:`find_path`, :command:`find_library`, and
+ :command:`find_program` commands gain the capability to specify a function
+ which will be called for each found item to validate it.
diff --git a/Help/release/dev/finddoxygen-better-version-checking.rst b/Help/release/dev/finddoxygen-better-version-checking.rst
new file mode 100644
index 0000000..3c2215d
--- /dev/null
+++ b/Help/release/dev/finddoxygen-better-version-checking.rst
@@ -0,0 +1,11 @@
+finddoxygen-better-version-checking
+-----------------------------------
+
+* The :module:`FindDoxygen` module now evaluates as many candidate
+ Doxygen installs as are necessary to satisfy version constraints,
+ with the package considered to be not found if none are available.
+
+* The :module:`FindDoxygen` module now handles version ranges.
+
+* The :module:`FindDoxygen` module now ignores non-semantic portions
+ of the output from Doxygen's `--version` option.
diff --git a/Help/release/dev/findopenal-add-import-library.rst b/Help/release/dev/findopenal-add-import-library.rst
new file mode 100644
index 0000000..6c9c93f
--- /dev/null
+++ b/Help/release/dev/findopenal-add-import-library.rst
@@ -0,0 +1,4 @@
+findopenal-add-import-library
+-----------------------------
+
+* The :module:`FindOpenAL` module now provides an imported target.
diff --git a/Help/release/dev/findvulkan-volk.rst b/Help/release/dev/findvulkan-volk.rst
new file mode 100644
index 0000000..cb77078
--- /dev/null
+++ b/Help/release/dev/findvulkan-volk.rst
@@ -0,0 +1,5 @@
+findvulkan-volk
+---------------
+
+* The :module:`FindVulkan` module now includes a ``volk`` component
+ for the Volk open source vulkan meta-loader.
diff --git a/Help/release/dev/system.rst b/Help/release/dev/system.rst
new file mode 100644
index 0000000..7cc841e
--- /dev/null
+++ b/Help/release/dev/system.rst
@@ -0,0 +1,15 @@
+system
+------
+
+* The :prop_tgt:`SYSTEM` target property was added to specify
+ that a target should be treated as a system library (i.e.
+ its include directories are automatically ``SYSTEM`` when
+ compiling consumers).
+
+* The :prop_tgt:`EXPORT_NO_SYSTEM` target property was added to
+ specify that :command:`install(EXPORT)` and :command:`export`
+ commands will generate a imported target with
+ :prop_tgt:`SYSTEM` property `OFF`.
+
+* The :prop_tgt:`IMPORTED_NO_SYSTEM` target property was deprecated
+ in favor of :prop_tgt:`SYSTEM` and :prop_tgt:`EXPORT_NO_SYSTEM`.
diff --git a/Help/release/dev/try_run_split_output.rst b/Help/release/dev/try_run_split_output.rst
new file mode 100644
index 0000000..98aedd6
--- /dev/null
+++ b/Help/release/dev/try_run_split_output.rst
@@ -0,0 +1,6 @@
+try_run_split_output
+--------------------
+
+* The :command:`try_run` command gained ``RUN_OUTPUT_STDOUT_VARIABLE``
+ and ``RUN_OUTPUT_STDERR_VARIABLE`` options to capture stdout and stderr
+ separately from the output of the compiled program.
diff --git a/Help/release/dev/xcode-launch-mode.rst b/Help/release/dev/xcode-launch-mode.rst
new file mode 100644
index 0000000..32b9ee6
--- /dev/null
+++ b/Help/release/dev/xcode-launch-mode.rst
@@ -0,0 +1,7 @@
+xcode-launch-mode
+-----------------
+
+* The :variable:`CMAKE_XCODE_SCHEME_LAUNCH_MODE` variable and corresponding
+ :prop_tgt:`XCODE_SCHEME_LAUNCH_MODE` target property were added to tell
+ the :generator:`Xcode` generator what to put in the scheme's "Launch"
+ mode setting.
diff --git a/Help/release/index.rst b/Help/release/index.rst
index 4dfac8a..11d5a11 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_MESSAGE_LOG_LEVEL.rst b/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst
index 3b45d1d..54ea6a4 100644
--- a/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst
+++ b/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst
@@ -15,3 +15,8 @@ subsequent CMake runs will continue to use the chosen log level.
Projects should not set this variable, it is intended for users so that
they may control the log level according to their own needs.
+
+.. versionadded:: 3.25
+ See the :command:`cmake_language`
+ :ref:`cmake_language <query_message_log_level>` command for a way to query
+ the current message logging level.
diff --git a/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst b/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst
new file mode 100644
index 0000000..c15b1ea
--- /dev/null
+++ b/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst
@@ -0,0 +1,13 @@
+CMAKE_XCODE_SCHEME_LAUNCH_MODE
+------------------------------
+
+.. versionadded:: 3.25
+
+Property value for ``Launch`` in the Info section of the generated Xcode
+scheme.
+
+This variable initializes the :prop_tgt:`XCODE_SCHEME_LAUNCH_MODE` property on
+all targets.
+
+Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property
+documentation to see all Xcode schema related properties.
diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake
index 2e3ae2c..33509ac 100644
--- a/Modules/Compiler/NVIDIA-CUDA.cmake
+++ b/Modules/Compiler/NVIDIA-CUDA.cmake
@@ -132,15 +132,19 @@ else()
endif()
-# FIXME: investigate use of --options-file.
-# Tell Makefile generator that nvcc does not support @<rspfile> syntax.
-set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0)
-set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
-set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0)
-
if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "9.0")
set(CMAKE_CUDA_RESPONSE_FILE_DEVICE_LINK_FLAG "--options-file ")
set(CMAKE_CUDA_RESPONSE_FILE_FLAG "--options-file ")
endif()
+if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0")
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 1)
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 1)
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 1)
+else()
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0)
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
+ set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0)
+endif()
+
__compiler_check_default_language_standard(CUDA 6.0 03)
diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake
index 7a381af..d02c589 100644
--- a/Modules/FindBLAS.cmake
+++ b/Modules/FindBLAS.cmake
@@ -35,6 +35,12 @@ The following variables may be set to influence this module's behavior:
if set ``pkg-config`` will be used to search for a BLAS library first
and if one is found that is preferred
+``BLA_PKGCONFIG_BLAS``
+ .. versionadded:: 3.25
+
+ If set, the ``pkg-config`` method will look for this module name instead of
+ just ``blas``.
+
``BLA_SIZEOF_INTEGER``
.. versionadded:: 3.22
@@ -273,8 +279,11 @@ endif()
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
if(BLA_PREFER_PKGCONFIG)
+ if(NOT BLA_PKGCONFIG_BLAS)
+ set(BLA_PKGCONFIG_BLAS "blas")
+ endif()
find_package(PkgConfig QUIET)
- pkg_check_modules(PKGC_BLAS QUIET blas)
+ pkg_check_modules(PKGC_BLAS QUIET ${BLA_PKGCONFIG_BLAS})
if(PKGC_BLAS_FOUND)
set(BLAS_FOUND ${PKGC_BLAS_FOUND})
set(BLAS_LIBRARIES "${PKGC_BLAS_LINK_LIBRARIES}")
diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake
index af5f798..470111f 100644
--- a/Modules/FindCUDA.cmake
+++ b/Modules/FindCUDA.cmake
@@ -799,7 +799,9 @@ if(NOT "${CUDA_TOOLKIT_ROOT_DIR}" STREQUAL "${CUDA_TOOLKIT_ROOT_DIR_INTERNAL}")
unset(CUDA_VERSION CACHE)
endif()
-if(NOT "${CUDA_TOOLKIT_TARGET_DIR}" STREQUAL "${CUDA_TOOLKIT_TARGET_DIR_INTERNAL}")
+# If CUDA_TOOLKIT_TARGET_DIR exists, check if it has changed.
+if(DEFINED CUDA_TOOLKIT_TARGET_DIR
+ AND NOT "${CUDA_TOOLKIT_TARGET_DIR}" STREQUAL "${CUDA_TOOLKIT_TARGET_DIR_INTERNAL}")
cuda_unset_include_and_libraries()
endif()
diff --git a/Modules/FindCURL.cmake b/Modules/FindCURL.cmake
index e37d225..279e263 100644
--- a/Modules/FindCURL.cmake
+++ b/Modules/FindCURL.cmake
@@ -72,6 +72,8 @@ if(NOT CURL_NO_CURL_CMAKE)
# can print what we found and return.
if(CURL_FOUND)
find_package_handle_standard_args(CURL HANDLE_COMPONENTS CONFIG_MODE)
+ # The upstream curl package sets CURL_VERSION, not CURL_VERSION_STRING.
+ set(CURL_VERSION_STRING "${CURL_VERSION}")
return()
endif()
endif()
diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake
index 4a16e31..23b7107 100644
--- a/Modules/FindDoxygen.cmake
+++ b/Modules/FindDoxygen.cmake
@@ -432,9 +432,44 @@ endif()
# or use something like homebrew.
# ============== End OSX stuff ================
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+
#
# Find Doxygen...
#
+function(_Doxygen_get_version doxy_version result_var doxy_path)
+ execute_process(
+ COMMAND "${doxy_path}" --version
+ OUTPUT_VARIABLE full_doxygen_version
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE version_result
+ )
+
+ # Ignore any commit hashes, etc.
+ string(REGEX MATCH [[^[0-9]+\.[0-9]+\.[0-9]+]] sem_doxygen_version "${full_doxygen_version}")
+
+ set(${result_var} ${version_result} PARENT_SCOPE)
+ set(${doxy_version} ${sem_doxygen_version} PARENT_SCOPE)
+endfunction()
+
+function(_Doxygen_version_validator version_match doxy_path)
+ if(NOT DEFINED Doxygen_FIND_VERSION)
+ set(${is_valid_version} TRUE PARENT_SCOPE)
+ else()
+ _Doxygen_get_version(candidate_version version_result "${doxy_path}")
+
+ if(version_result)
+ message(DEBUG "Unable to determine candidate doxygen version at ${doxy_path}: ${version_result}")
+ endif()
+
+ find_package_check_version("${candidate_version}" valid_doxy_version
+ HANDLE_VERSION_RANGE
+ )
+
+ set(${version_match} "${valid_doxy_version}" PARENT_SCOPE)
+ endif()
+endfunction()
+
macro(_Doxygen_find_doxygen)
find_program(
DOXYGEN_EXECUTABLE
@@ -446,16 +481,13 @@ macro(_Doxygen_find_doxygen)
/Applications/Utilities/Doxygen.app/Contents/Resources
/Applications/Utilities/Doxygen.app/Contents/MacOS
DOC "Doxygen documentation generation tool (http://www.doxygen.org)"
+ VALIDATOR _Doxygen_version_validator
)
mark_as_advanced(DOXYGEN_EXECUTABLE)
if(DOXYGEN_EXECUTABLE)
- execute_process(
- COMMAND "${DOXYGEN_EXECUTABLE}" --version
- OUTPUT_VARIABLE DOXYGEN_VERSION
- OUTPUT_STRIP_TRAILING_WHITESPACE
- RESULT_VARIABLE _Doxygen_version_result
- )
+ _Doxygen_get_version(DOXYGEN_VERSION _Doxygen_version_result "${DOXYGEN_EXECUTABLE}")
+
if(_Doxygen_version_result)
message(WARNING "Unable to determine doxygen version: ${_Doxygen_version_result}")
endif()
@@ -642,11 +674,11 @@ endforeach()
unset(_comp)
# Verify find results
-include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
find_package_handle_standard_args(
Doxygen
REQUIRED_VARS DOXYGEN_EXECUTABLE
VERSION_VAR DOXYGEN_VERSION
+ HANDLE_VERSION_RANGE
HANDLE_COMPONENTS
)
diff --git a/Modules/FindGLEW.cmake b/Modules/FindGLEW.cmake
index b9ebe08..bfde40b 100644
--- a/Modules/FindGLEW.cmake
+++ b/Modules/FindGLEW.cmake
@@ -63,11 +63,36 @@ This module defines the following variables:
#]=======================================================================]
include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
find_package(GLEW CONFIG QUIET)
if(GLEW_FOUND)
find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_CONFIG)
+ get_target_property(GLEW_INCLUDE_DIRS GLEW::GLEW INTERFACE_INCLUDE_DIRECTORIES)
+ set(GLEW_INCLUDE_DIR ${GLEW_INCLUDE_DIRS})
+ get_target_property(_GLEW_DEFS GLEW::GLEW INTERFACE_COMPILE_DEFINITIONS)
+ if("${_GLEW_DEFS}" MATCHES "GLEW_STATIC")
+ get_target_property(GLEW_LIBRARY_DEBUG GLEW::GLEW IMPORTED_LOCATION_DEBUG)
+ get_target_property(GLEW_LIBRARY_RELEASE GLEW::GLEW IMPORTED_LOCATION_RELEASE)
+ else()
+ get_target_property(GLEW_LIBRARY_DEBUG GLEW::GLEW IMPORTED_IMPLIB_DEBUG)
+ get_target_property(GLEW_LIBRARY_RELEASE GLEW::GLEW IMPORTED_IMPLIB_RELEASE)
+ endif()
+ get_target_property(_GLEW_LINK_INTERFACE GLEW::GLEW IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE) # same for debug and release
+ list(APPEND GLEW_LIBRARIES ${_GLEW_LINK_INTERFACE})
+ list(APPEND GLEW_LIBRARY ${_GLEW_LINK_INTERFACE})
+ select_library_configurations(GLEW)
+ if("${_GLEW_DEFS}" MATCHES "GLEW_STATIC")
+ set(GLEW_STATIC_LIBRARIES ${GLEW_LIBRARIES})
+ else()
+ set(GLEW_SHARED_LIBRARIES ${GLEW_LIBRARIES})
+ endif()
+ unset(_GLEW_DEFS)
+ unset(_GLEW_LINK_INTERFACE)
+ unset(GLEW_LIBRARY)
+ unset(GLEW_LIBRARY_DEBUG)
+ unset(GLEW_LIBRARY_RELEASE)
return()
endif()
@@ -171,8 +196,6 @@ find_library(GLEW_STATIC_LIBRARY_DEBUG
set(CMAKE_FIND_LIBRARY_SUFFIXES ${__GLEW_CURRENT_FIND_LIBRARY_SUFFIXES})
unset(__GLEW_CURRENT_FIND_LIBRARY_SUFFIXES)
-include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake)
-
select_library_configurations(GLEW_SHARED)
select_library_configurations(GLEW_STATIC)
diff --git a/Modules/FindICU.cmake b/Modules/FindICU.cmake
index 91dcba5..b4f4d71 100644
--- a/Modules/FindICU.cmake
+++ b/Modules/FindICU.cmake
@@ -254,13 +254,6 @@ function(_ICU_FIND)
set("${component_found}" ON)
set("${component_found_compat}" ON)
list(APPEND ICU_LIBRARY "${${component_cache}}")
- endif()
- mark_as_advanced("${component_found}")
- mark_as_advanced("${component_found_compat}")
- set("${component_cache}" "${${component_cache}}" PARENT_SCOPE)
- set("${component_found}" "${${component_found}}" PARENT_SCOPE)
- set("${component_found_compat}" "${${component_found_compat}}" PARENT_SCOPE)
- if(component_found OR component_found_compat)
if (ICU_FIND_REQUIRED_${component})
list(APPEND ICU_LIBS_FOUND "${component} (required): ${${component_cache}}")
else()
@@ -274,6 +267,11 @@ function(_ICU_FIND)
list(APPEND ICU_LIBS_NOTFOUND "${component} (optional)")
endif()
endif()
+ mark_as_advanced("${component_found}")
+ mark_as_advanced("${component_found_compat}")
+ set("${component_cache}" "${${component_cache}}" PARENT_SCOPE)
+ set("${component_found}" "${${component_found}}" PARENT_SCOPE)
+ set("${component_found_compat}" "${${component_found_compat}}" PARENT_SCOPE)
endforeach()
set(_ICU_REQUIRED_LIBS_FOUND "${ICU_REQUIRED_LIBS_FOUND}" PARENT_SCOPE)
set(ICU_LIBRARY "${ICU_LIBRARY}" PARENT_SCOPE)
diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake
index b08b359..4151116 100644
--- a/Modules/FindLAPACK.cmake
+++ b/Modules/FindLAPACK.cmake
@@ -35,6 +35,13 @@ The following variables may be set to influence this module's behavior:
if set ``pkg-config`` will be used to search for a LAPACK library first
and if one is found that is preferred
+``BLA_PKGCONFIG_LAPACK``
+ .. versionadded:: 3.25
+
+ If set, the ``pkg-config`` method will look for this module name instead of
+ just ``lapack``.
+
+
``BLA_SIZEOF_INTEGER``
.. versionadded:: 3.22
@@ -278,8 +285,11 @@ endif()
# Search with pkg-config if specified
if(BLA_PREFER_PKGCONFIG)
+ if(NOT BLA_PKGCONFIG_LAPACK)
+ set(BLA_PKGCONFIG_LAPACK "lapack")
+ endif()
find_package(PkgConfig QUIET)
- pkg_check_modules(PKGC_LAPACK QUIET lapack)
+ pkg_check_modules(PKGC_LAPACK QUIET ${BLA_PKGCONFIG_LAPACK})
if(PKGC_LAPACK_FOUND)
set(LAPACK_FOUND TRUE)
set(LAPACK_LIBRARIES "${PKGC_LAPACK_LINK_LIBRARIES}")
diff --git a/Modules/FindOpenACC.cmake b/Modules/FindOpenACC.cmake
index cf58f3b..71bd84f 100644
--- a/Modules/FindOpenACC.cmake
+++ b/Modules/FindOpenACC.cmake
@@ -27,6 +27,13 @@ The module provides :prop_tgt:`IMPORTED` targets:
Variables
^^^^^^^^^
+The module defines the following variables:
+
+``OpenACC_FOUND``
+ .. versionadded:: 3.25
+
+ Variable indicating that OpenACC flags for at least one languages have been found.
+
This module will set the following variables per language in your
project, where ``<lang>`` is one of C, CXX, or Fortran:
@@ -270,6 +277,9 @@ foreach (LANG IN ITEMS C CXX Fortran)
REQUIRED_VARS OpenACC_${LANG}_FLAGS
VERSION_VAR OpenACC_${LANG}_VERSION
)
+ if(OpenACC_${LANG}_FOUND)
+ set(OpenACC_FOUND TRUE)
+ endif()
endif()
endforeach()
diff --git a/Modules/FindOpenAL.cmake b/Modules/FindOpenAL.cmake
index b5b92c5..53aafdc 100644
--- a/Modules/FindOpenAL.cmake
+++ b/Modules/FindOpenAL.cmake
@@ -29,6 +29,16 @@ OpenAL is searched in the following order:
5. Manually compiled framework: ``/Library/Frameworks``.
6. Add-on package: ``/opt``.
+IMPORTED Targets
+^^^^^^^^^^^^^^^^
+
+.. versionadded:: 3.25
+
+This module defines the :prop_tgt:`IMPORTED` target:
+
+``OpenAL::OpenAL``
+ The OpenAL library, if found.
+
Result Variables
^^^^^^^^^^^^^^^^
@@ -94,3 +104,19 @@ find_package_handle_standard_args(
)
mark_as_advanced(OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
+
+if(OPENAL_INCLUDE_DIR AND OPENAL_LIBRARY)
+ if(NOT TARGET OpenAL::OpenAL)
+ if(EXISTS "${OPENAL_LIBRARY}")
+ add_library(OpenAL::OpenAL UNKNOWN IMPORTED)
+ set_target_properties(OpenAL::OpenAL PROPERTIES
+ IMPORTED_LOCATION "${OPENAL_LIBRARY}")
+ else()
+ add_library(OpenAL::OpenAL INTERFACE IMPORTED)
+ set_target_properties(OpenAL::OpenAL PROPERTIES
+ IMPORTED_LIBNAME "${OPENAL_LIBRARY}")
+ endif()
+ set_target_properties(OpenAL::OpenAL PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${OPENAL_INCLUDE_DIR}")
+ endif()
+endif()
diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake
index ecfb7f9..0590a28 100644
--- a/Modules/FindOpenMP.cmake
+++ b/Modules/FindOpenMP.cmake
@@ -243,6 +243,23 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR)
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n")
+ # For LCC we should additionally alanyze -print-search-dirs output
+ # to check for additional implicit_dirs.
+ # Note: This won't work if CMP0129 policy is set to OLD!
+ if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "LCC")
+ execute_process(
+ COMMAND ${CMAKE_${LANG}_COMPILER} -print-search-dirs
+ OUTPUT_VARIABLE output_lines
+ COMMAND_ERROR_IS_FATAL ANY
+ ERROR_QUIET)
+ if("${output_lines}" MATCHES ".*\nlibraries:[ \t]+(.*:)\n.*")
+ string(REPLACE ":" ";" implicit_dirs_addon "${CMAKE_MATCH_1}")
+ list(PREPEND OpenMP_${LANG}_IMPLICIT_LINK_DIRS ${implicit_dirs_addon})
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ " Extended OpenMP library search paths: [${implicit_dirs}]\n")
+ endif()
+ endif()
+
unset(_OPENMP_LIB_NAMES)
foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES)
get_filename_component(_OPENMP_IMPLICIT_LIB_DIR "${_OPENMP_IMPLICIT_LIB}" DIRECTORY)
@@ -460,10 +477,14 @@ foreach(LANG IN ITEMS C CXX)
if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND"
OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
_OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK)
- set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
- CACHE STRING "${LANG} compiler flags for OpenMP parallelization" FORCE)
- set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
- CACHE STRING "${LANG} compiler libraries for OpenMP parallelization" FORCE)
+ if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND")
+ set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}"
+ CACHE STRING "${LANG} compiler flags for OpenMP parallelization" FORCE)
+ endif()
+ if(NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND")
+ set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}"
+ CACHE STRING "${LANG} compiler libraries for OpenMP parallelization" FORCE)
+ endif()
mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES)
endif()
endif()
@@ -479,10 +500,14 @@ if(CMAKE_Fortran_COMPILER_LOADED)
set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "")
endif()
- set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
- CACHE STRING "Fortran compiler flags for OpenMP parallelization")
- set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
- CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
+ if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND")
+ set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
+ CACHE STRING "Fortran compiler flags for OpenMP parallelization" FORCE)
+ endif()
+ if(NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND")
+ set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
+ CACHE STRING "Fortran compiler libraries for OpenMP parallelization" FORCE)
+ endif()
mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES)
endif()
@@ -495,11 +520,14 @@ if(CMAKE_Fortran_COMPILER_LOADED)
set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "")
endif()
- set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
- CACHE STRING "Fortran compiler flags for OpenMP parallelization")
-
- set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}"
- CACHE STRING "Fortran compiler libraries for OpenMP parallelization")
+ if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND")
+ set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}"
+ CACHE STRING "Fortran compiler flags for OpenMP parallelization" FORCE)
+ endif()
+ if(NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND")
+ set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}"
+ CACHE STRING "Fortran compiler libraries for OpenMP parallelization" FORCE)
+ endif()
endif()
if(OpenMP_Fortran_HAVE_OMPLIB_MODULE)
diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake
index 9278566..352c4cc 100644
--- a/Modules/FindOpenSSL.cmake
+++ b/Modules/FindOpenSSL.cmake
@@ -90,13 +90,25 @@ This module will set the following variables in your project:
Hints
^^^^^
-Set ``OPENSSL_ROOT_DIR`` to the root directory of an OpenSSL installation.
+The following variables may be set to control search behavior:
-.. versionadded:: 3.4
- Set ``OPENSSL_USE_STATIC_LIBS`` to ``TRUE`` to look for static libraries.
+``OPENSSL_ROOT_DIR``
+ Set to the root directory of an OpenSSL installation.
+
+``OPENSSL_USE_STATIC_LIBS``
+ .. versionadded:: 3.4
+
+ Set to ``TRUE`` to look for static libraries.
+
+``OPENSSL_MSVC_STATIC_RT``
+ .. versionadded:: 3.5
+
+ Set to ``TRUE`` to choose the MT version of the lib.
-.. versionadded:: 3.5
- Set ``OPENSSL_MSVC_STATIC_RT`` set ``TRUE`` to choose the MT version of the lib.
+``ENV{PKG_CONFIG_PATH}``
+ On UNIX-like systems, ``pkg-config`` is used to locate the system OpenSSL.
+ Set the ``PKG_CONFIG_PATH`` environment varialbe to look in alternate
+ locations. Useful on multi-lib systems.
#]=======================================================================]
macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library)
diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake
index c4fae6b..7a127e4 100644
--- a/Modules/FindPython/Support.cmake
+++ b/Modules/FindPython/Support.cmake
@@ -14,6 +14,8 @@ cmake_policy(PUSH)
cmake_policy (SET CMP0012 NEW)
# IN_LIST operator
cmake_policy (SET CMP0057 NEW)
+# registry view behavior
+cmake_policy (SET CMP0134 NEW)
if (NOT DEFINED _PYTHON_PREFIX)
message (FATAL_ERROR "FindPython: INTERNAL ERROR")
@@ -175,30 +177,31 @@ function (_PYTHON_GET_REGISTRIES _PYTHON_PGR_REGISTRY_PATHS)
foreach (version IN LISTS _PGR_VERSION)
string (REPLACE "." "" version_no_dots ${version})
list (APPEND registries
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath])
+ [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
+ [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath])
if (version VERSION_GREATER_EQUAL "3.5")
+ # cmake_host_system_information is not usable in bootstrap
get_filename_component (arch "[HKEY_CURRENT_USER\\Software\\Python\\PythonCore\\${version};SysArchitecture]" NAME)
if (arch MATCHES "(${_${_PYTHON_PREFIX}_ARCH}|${_${_PYTHON_PREFIX}_ARCH2})bit")
list (APPEND registries
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath])
+ [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath])
endif()
else()
list (APPEND registries
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath])
+ [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath])
endif()
list (APPEND registries
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
- [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath])
+ [HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
+ [HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath]
+ [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
+ [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath]
+ [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}/InstallPath]
+ [HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath]
+ [HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath])
endforeach()
elseif (implementation STREQUAL "IronPython")
foreach (version IN LISTS _PGR_VERSION)
- list (APPEND registries [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${version}\\InstallPath])
+ list (APPEND registries [HKEY_LOCAL_MACHINE/SOFTWARE/IronPython/${version}/InstallPath])
endforeach()
endif()
endforeach()
@@ -711,7 +714,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
if (_PVI_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_EXECUTABLE}")
# interpreter does not exist anymore
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
endif()
@@ -732,7 +735,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
endif()
if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
# incompatible ABI
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
endif()
@@ -748,7 +751,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
OUTPUT_STRIP_TRAILING_WHITESPACE)
if (result)
# interpreter is not usable
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
endif()
@@ -773,7 +776,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
if (_PVI_EXACT AND NOT version VERSION_EQUAL _PVI_VERSION)
# interpreter has wrong version
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
else()
@@ -782,7 +785,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" expected_major_version "${_PVI_VERSION}")
if (NOT major_version VERSION_EQUAL expected_major_version
OR NOT version VERSION_GREATER_EQUAL _PVI_VERSION)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
endif()
@@ -794,7 +797,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
find_package_check_version ("${version}" in_range HANDLE_VERSION_RANGE)
if (NOT in_range)
# interpreter has invalid version
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
endif()
@@ -813,9 +816,9 @@ function (_PYTHON_VALIDATE_INTERPRETER)
if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
# interpreter not usable or has wrong major version
if (result)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
else()
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
endif()
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
@@ -836,9 +839,9 @@ function (_PYTHON_VALIDATE_INTERPRETER)
if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P)
# interpreter not usable or has wrong architecture
if (result)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
else()
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
endif()
set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
return()
@@ -846,6 +849,14 @@ function (_PYTHON_VALIDATE_INTERPRETER)
endif()
endfunction()
+function(_python_validate_find_interpreter status interpreter)
+ set(_${_PYTHON_PREFIX}_EXECUTABLE "${interpreter}" CACHE FILEPATH "" FORCE)
+ _python_validate_interpreter (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ if (NOT _${_PYTHON_PREFIX}_EXECUTABLE)
+ set (${status} FALSE PARENT_SCOPE)
+ endif()
+endfunction()
+
function (_PYTHON_VALIDATE_COMPILER)
if (NOT _${_PYTHON_PREFIX}_COMPILER)
@@ -856,7 +867,7 @@ function (_PYTHON_VALIDATE_COMPILER)
if (_PVC_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_COMPILER}")
# Compiler does not exist anymore
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot find the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Cannot find the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
endif()
@@ -883,7 +894,7 @@ function (_PYTHON_VALIDATE_COMPILER)
file (REMOVE_RECURSE "${working_dir}")
if (result)
# compiler is not usable
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot use the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Cannot use the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
endif()
@@ -909,7 +920,7 @@ function (_PYTHON_VALIDATE_COMPILER)
if (_PVC_EXACT AND NOT version VERSION_EQUAL _PVC_VERSION)
# interpreter has wrong version
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
else()
@@ -918,7 +929,7 @@ function (_PYTHON_VALIDATE_COMPILER)
string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" expected_major_version "${_PVC_VERSION}")
if (NOT major_version VERSION_EQUAL expected_major_version
OR NOT version VERSION_GREATER_EQUAL _PVC_VERSION)
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
endif()
@@ -930,7 +941,7 @@ function (_PYTHON_VALIDATE_COMPILER)
find_package_check_version ("${version}" in_range HANDLE_VERSION_RANGE)
if (NOT in_range)
# interpreter has invalid version
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
endif()
@@ -939,13 +950,21 @@ function (_PYTHON_VALIDATE_COMPILER)
string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" major_version "${version}")
if (NOT major_version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
# Compiler has wrong major version
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong major version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong major version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
return()
endif()
endif()
endfunction()
+function(_python_validate_find_compiler status compiler)
+ set(_${_PYTHON_PREFIX}_COMPILER "${compiler}" CACHE FILEPATH "" FORCE)
+ _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ if (NOT _${_PYTHON_PREFIX}_COMPILER)
+ set (${status} FALSE PARENT_SCOPE)
+ endif()
+endfunction()
+
function (_PYTHON_VALIDATE_LIBRARY)
if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
@@ -957,7 +976,7 @@ function (_PYTHON_VALIDATE_LIBRARY)
if (_PVL_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
# library does not exist anymore
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
if (WIN32)
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND")
@@ -971,7 +990,7 @@ function (_PYTHON_VALIDATE_LIBRARY)
if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT lib_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
# incompatible ABI
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
else()
if (_PVL_VERSION OR _PVL_IN_RANGE)
@@ -980,7 +999,7 @@ function (_PYTHON_VALIDATE_LIBRARY)
string (REGEX MATCH "[0-9](\\.[0-9]+)?" version "${_PVL_VERSION}")
if ((_PVL_EXACT AND NOT lib_VERSION VERSION_EQUAL version) OR (lib_VERSION VERSION_LESS version))
# library has wrong version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
endif()
endif()
@@ -990,14 +1009,14 @@ function (_PYTHON_VALIDATE_LIBRARY)
find_package_check_version ("${lib_VERSION}" in_range HANDLE_VERSION_RANGE)
if (NOT in_range)
# library has wrong version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
endif()
endif()
else()
if (NOT lib_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
# library has wrong major version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong major version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
endif()
endif()
@@ -1023,7 +1042,7 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR)
if (_PVID_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
# include file does not exist anymore
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
return()
endif()
@@ -1033,14 +1052,14 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR)
if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT inc_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
# incompatible ABI
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
else()
if (_PVID_VERSION OR _PVID_IN_RANGE)
if (_PVID_VERSION)
if ((_PVID_EXACT AND NOT inc_VERSION VERSION_EQUAL expected_version) OR (inc_VERSION VERSION_LESS expected_version))
# include dir has wrong version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
endif()
endif()
@@ -1050,14 +1069,14 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR)
find_package_check_version ("${inc_VERSION}" in_range HANDLE_VERSION_RANGE)
if (NOT in_range)
# include dir has wrong version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
endif()
endif()
else()
if (NOT inc_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
# include dir has wrong major version
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong major version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
endif()
endif()
@@ -1247,12 +1266,14 @@ if (DEFINED ${_PYTHON_PREFIX}_FIND_STRATEGY)
endif()
# Python and Anaconda distributions: define which architectures can be used
+unset (_${_PYTHON_PREFIX}_REGISTRY_VIEW)
if (CMAKE_SIZEOF_VOID_P)
math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
if ("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
OR "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
# In this case, search only for 64bit or 32bit
set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH})
+ set (_${_PYTHON_PREFIX}_REGISTRY_VIEW REGISTRY_VIEW ${_${_PYTHON_PREFIX}_ARCH})
else()
if (_${_PYTHON_PREFIX}_ARCH EQUAL "32")
set (_${_PYTHON_PREFIX}_ARCH2 64)
@@ -1506,9 +1527,13 @@ endfunction()
unset (_${_PYTHON_PREFIX}_REQUIRED_VARS)
unset (_${_PYTHON_PREFIX}_CACHED_VARS)
unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE)
+set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE CACHE INTERNAL "Interpreter reason failure")
unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE)
+set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE CACHE INTERNAL "Compiler reason failure")
unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE)
+set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE CACHE INTERNAL "Development reason failure")
unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE)
+set (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE CACHE INTERNAL "NumPy reason failure")
# preamble
@@ -1590,9 +1615,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
-
- _python_validate_interpreter (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1612,8 +1636,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1626,9 +1650,10 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_HINTS}
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1641,8 +1666,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_HINTS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1650,8 +1675,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
find_program (_${_PYTHON_PREFIX}_EXECUTABLE
NAMES ${_${_PYTHON_PREFIX}_NAMES}
NAMES_PER_DIR
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES})
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1663,8 +1688,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1676,8 +1701,9 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1687,9 +1713,9 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
endwhile()
else()
# look-up for various versions and locations
- set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS EXACT)
+ set (_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS EXACT)
if (${_PYTHON_PREFIX}_FIND_VERSION_RANGE)
- list (APPEND _${_PYTHON_PREFIX}_VALIDATE_OPTIONS IN_RANGE)
+ list (APPEND _${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS IN_RANGE)
endif()
foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
@@ -1698,6 +1724,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
_python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS VERSION ${_${_PYTHON_PREFIX}_VERSION})
_python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS VERSION ${_${_PYTHON_PREFIX}_VERSION})
+ set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS})
# Virtual environments handling
if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
@@ -1710,8 +1737,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1731,7 +1758,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
endif()
# Windows registry
@@ -1742,11 +1770,12 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_HINTS}
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
endif()
- _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1758,21 +1787,18 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_HINTS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
+
# try using standard paths.
- # NAMES_PER_DIR is not defined on purpose to have a chance to find
- # expected version.
- # For example, typical systems have 'python' for version 2.* and 'python3'
- # for version 3.*. So looking for names per dir will find, potentially,
- # systematically 'python' (i.e. version 2) even if version 3 is searched.
find_program (_${_PYTHON_PREFIX}_EXECUTABLE
NAMES ${_${_PYTHON_PREFIX}_NAMES}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES})
- _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NAMES_PER_DIR
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ VALIDATOR _python_validate_find_interpreter)
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1784,7 +1810,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_interpreter)
endif()
# Windows registry
@@ -1794,10 +1821,11 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_interpreter)
endif()
- _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
if (_${_PYTHON_PREFIX}_EXECUTABLE)
break()
endif()
@@ -1806,15 +1834,12 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
if (NOT _${_PYTHON_PREFIX}_EXECUTABLE AND
NOT _${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY")
# No specific version found. Retry with generic names and standard paths.
- # NAMES_PER_DIR is not defined on purpose to have a chance to find
- # expected version.
- # For example, typical systems have 'python' for version 2.* and 'python3'
- # for version 3.*. So looking for names per dir will find, potentially,
- # systematically 'python' (i.e. version 2) even if version 3 is searched.
_python_get_names (_${_PYTHON_PREFIX}_NAMES POSIX INTERPRETER)
+ unset (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS)
find_program (_${_PYTHON_PREFIX}_EXECUTABLE
- NAMES ${_${_PYTHON_PREFIX}_NAMES})
- _python_validate_interpreter ()
+ NAMES ${_${_PYTHON_PREFIX}_NAMES}
+ NAMES_PER_DIR
+ VALIDATOR _python_validate_find_interpreter)
endif()
endif()
endif()
@@ -1836,7 +1861,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
# Interpreter is not usable
set (_${_PYTHON_PREFIX}_EXECUTABLE_USABLE FALSE)
unset (${_PYTHON_PREFIX}_VERSION)
- set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot run the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
+ set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot run the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"")
endif()
endif()
@@ -1884,7 +1909,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
endif()
if (${_PYTHON_PREFIX}_Interpreter_FOUND)
- unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE)
+ unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE CACHE)
# compute and save interpreter signature
string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_EXECUTABLE}")
@@ -2058,8 +2083,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2072,9 +2097,10 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2087,8 +2113,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2097,8 +2123,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
find_program (_${_PYTHON_PREFIX}_COMPILER
NAMES ${_${_PYTHON_PREFIX}_COMPILER_NAMES}
NAMES_PER_DIR
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES})
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2110,12 +2136,13 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
endif()
+
# Windows registry
if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST")
find_program (_${_PYTHON_PREFIX}_COMPILER
@@ -2123,8 +2150,9 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2134,9 +2162,9 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
endwhile()
else()
# try using root dir and registry
- set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS EXACT)
+ set (_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS EXACT)
if (${_PYTHON_PREFIX}_FIND_VERSION_RANGE)
- list (APPEND _${_PYTHON_PREFIX}_VALIDATE_OPTIONS IN_RANGE)
+ list (APPEND _${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS IN_RANGE)
endif()
foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
@@ -2157,6 +2185,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
IMPLEMENTATIONS IronPython
VERSION ${_${_PYTHON_PREFIX}_VERSION})
+ set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS})
+
# Apple frameworks handling
if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
find_program (_${_PYTHON_PREFIX}_COMPILER
@@ -2168,8 +2198,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NO_CMAKE_PATH
NO_CMAKE_ENVIRONMENT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2182,9 +2212,10 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2197,8 +2228,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_SYSTEM_PATH)
- _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_CMAKE_SYSTEM_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2210,8 +2241,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2223,8 +2254,9 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
NAMES_PER_DIR
PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS}
PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
- NO_DEFAULT_PATH)
- _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS})
+ ${_${_PYTHON_PREFIX}_REGISTRY_VIEW}
+ NO_DEFAULT_PATH
+ VALIDATOR _python_validate_find_compiler)
if (_${_PYTHON_PREFIX}_COMPILER)
break()
endif()
@@ -2240,11 +2272,13 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
IMPLEMENTATIONS IronPython
VERSION ${_${_PYTHON_PREFIX}_FIND_VERSIONS}
COMPILER)
+ unset (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS)
find_program (_${_PYTHON_PREFIX}_COMPILER
NAMES ${_${_PYTHON_PREFIX}_COMPILER_NAMES}
+ NAMES_PER_DIR
HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
- PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES})
- _python_validate_compiler ()
+ PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}
+ VALIDATOR _python_validate_find_compiler)
endif()
endif()
@@ -2285,7 +2319,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
else()
# compiler not usable
set (_${_PYTHON_PREFIX}_COMPILER_USABLE FALSE)
- set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot run the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
+ set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Cannot run the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"")
endif()
file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}")
endif()
@@ -2304,7 +2338,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
endif()
if (${_PYTHON_PREFIX}_Compiler_FOUND)
- unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE)
+ unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE CACHE)
# compute and save compiler signature
string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_COMPILER}")
@@ -2786,7 +2820,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
set (${_PYTHON_PREFIX}_LIBRARY_RELEASE "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"")
set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
endif()
@@ -2837,7 +2871,15 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS)
while (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
- if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS
+ set (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED TRUE)
+ foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Module Embed)
+ string (TOUPPER "${_${_PYTHON_PREFIX}_COMPONENT}" _${_PYTHON_PREFIX}_ID)
+ if ("Development.${_${_PYTHON_PREFIX}_COMPONENT}" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+ AND NOT "LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${_${_PYTHON_PREFIX}_ID}_ARTIFACTS)
+ set (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED FALSE)
+ endif()
+ endforeach()
+ if (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED
AND NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
# Don't search for include dir if no library was founded
break()
@@ -2939,7 +2981,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
if (_${_PYTHON_PREFIX}_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
- set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
+ set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
endif()
@@ -3033,7 +3075,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
AND ${_PYTHON_PREFIX}_Development.Embed_FOUND)
OR (NOT "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
AND ${_PYTHON_PREFIX}_Development.Module_FOUND))
- unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE)
+ unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE CACHE)
endif()
if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
@@ -3144,7 +3186,7 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte
set (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
if(_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
- set (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}\"")
+ set_property (CACHE _${_PYTHON_PREFIX}_NumPy_REASON_FAILURE PROPERTY VALUE "Cannot find the directory \"${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}\"")
set_property (CACHE _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR-NOTFOUND")
endif()
@@ -3166,7 +3208,7 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte
endif()
if (${_PYTHON_PREFIX}_NumPy_FOUND)
- unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE)
+ unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE CACHE)
# compute and save numpy signature
string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_MODULE_SIGNATURE}:${${_PYTHON_PREFIX}_NumPyINCLUDE_DIR}")
@@ -3196,7 +3238,7 @@ unset (_${_PYTHON_PREFIX}_REASON_FAILURE)
foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Interpreter Compiler Development NumPy)
if (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE)
string (APPEND _${_PYTHON_PREFIX}_REASON_FAILURE "\n ${_${_PYTHON_PREFIX}_COMPONENT}: ${_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE}")
- unset (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE)
+ unset (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE CACHE)
endif()
endforeach()
diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake
index a80758d..b14349f 100644
--- a/Modules/FindRuby.cmake
+++ b/Modules/FindRuby.cmake
@@ -369,56 +369,17 @@ if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR)
set(Ruby_VERSION_MAJOR 1)
set(Ruby_VERSION_MINOR 9)
endif()
- # check whether we found 2.0.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?0")
+ # check whether we found 2.[0-7].x
+ if(${Ruby_EXECUTABLE} MATCHES "ruby2")
set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 0)
+ string(REGEX_REPLACE ${Ruby_EXECUTABLE} "ruby2\\.?([0-7])" "\\1" Ruby_VERSION_MINOR)
endif()
- # check whether we found 2.1.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?1")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 1)
- endif()
- # check whether we found 2.2.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?2")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 2)
- endif()
- # check whether we found 2.3.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?3")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 3)
- endif()
- # check whether we found 2.4.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?4")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 4)
- endif()
- # check whether we found 2.5.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?5")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 5)
- endif()
- # check whether we found 2.6.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?6")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 6)
- endif()
- # check whether we found 2.7.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?7")
- set(Ruby_VERSION_MAJOR 2)
- set(Ruby_VERSION_MINOR 7)
- endif()
- # check whether we found 3.0.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby3\\.?0")
- set(Ruby_VERSION_MAJOR 3)
- set(Ruby_VERSION_MINOR 0)
- endif()
- # check whether we found 3.1.x
- if(${Ruby_EXECUTABLE} MATCHES "ruby3\\.?1")
+ # check whether we found 3.[0-1].x
+ if(${Ruby_EXECUTABLE} MATCHES "ruby3")
set(Ruby_VERSION_MAJOR 3)
- set(Ruby_VERSION_MINOR 1)
+ string(REGEX_REPLACE ${Ruby_EXECUTABLE} "ruby3\\.?([0-1])" "\\1" Ruby_VERSION_MINOR)
endif()
+
endif()
if(Ruby_VERSION_MAJOR)
diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake
index 8b322ed..0dcdb31 100644
--- a/Modules/FindVulkan.cmake
+++ b/Modules/FindVulkan.cmake
@@ -20,6 +20,10 @@ This module respects several optional COMPONENTS: ``glslc``,
On macOS, an additional component ``MoltenVK`` is available.
There are corresponding import targets for each of these flags.
+.. versionadded:: 3.25
+
+Added optional COMPONENT ``dxc`` with corresponding targets.
+
IMPORTED Targets
^^^^^^^^^^^^^^^^
@@ -70,6 +74,21 @@ This module defines :prop_tgt:`IMPORTED` targets if Vulkan has been found:
Defined if SDK has the Khronos library which implement a subset of Vulkan API
over Apple Metal graphics framework. (MoltenVK).
+``Vulkan::volk``
+ .. versionadded:: 3.25
+
+ Defined if SDK has the Vulkan meta-loader (volk).
+
+``Vulkan::dxc_lib``
+ .. versionadded:: 3.25
+
+ Defined if SDK has the DirectX shader compiler library.
+
+``Vulkan::dxc_exe``
+ .. versionadded:: 3.25
+
+ Defined if SDK has the DirectX shader compiler CLI tool.
+
Result Variables
^^^^^^^^^^^^^^^^
@@ -109,6 +128,21 @@ This module defines the following variables:
.. versionadded:: 3.24
True, if the SDK has the MoltenVK library.
+``Vulkan_volk_FOUND``
+ .. versionadded:: 3.25
+
+ True, if the SDK has the volk library.
+
+``Vulkan_dxc_lib_FOUND``
+ .. versionadded:: 3.25
+
+ True, if the SDK has the DirectX shader compiler library.
+
+``Vulkan_dxc_exe_FOUND``
+ .. versionadded:: 3.25
+
+ True, if the SDK has the DirectX shader compiler CLI tool.
+
The module will also defines these cache variables:
@@ -137,6 +171,21 @@ The module will also defines these cache variables:
Path to the MoltenVK library.
+``Vulkan_volk_LIBRARY``
+ .. versionadded:: 3.25
+
+ Path to the volk library.
+
+``Vulkan_dxc_LIBRARY``
+ .. versionadded:: 3.25
+
+ Path to the DirectX shader compiler library.
+
+``Vulkan_dxc_EXECUTABLE``
+ .. versionadded:: 3.25
+
+ Path to the DirectX shader compiler CLI tool.
+
Hints
^^^^^
@@ -374,6 +423,27 @@ if(MoltenVK IN_LIST Vulkan_FIND_COMPONENTS)
)
mark_as_advanced(Vulkan_MoltenVK_INCLUDE_DIR)
endif()
+if(volk IN_LIST Vulkan_FIND_COMPONENTS)
+ find_library(Vulkan_volk_LIBRARY
+ NAMES volk
+ HINTS
+ ${_Vulkan_hint_library_search_paths})
+ mark_as_advanced(Vulkan_Volk_LIBRARY)
+endif()
+
+if (dxc IN_LIST Vulkan_FIND_COMPONENTS)
+ find_library(Vulkan_dxc_LIBRARY
+ NAMES dxcompiler
+ HINTS
+ ${_Vulkan_hint_library_search_paths})
+ mark_as_advanced(Vulkan_dxc_LIBRARY)
+
+ find_program(Vulkan_dxc_EXECUTABLE
+ NAMES dxc
+ HINTS
+ ${_Vulkan_hint_executable_search_paths})
+ mark_as_advanced(Vulkan_dxc_EXECUTABLE)
+endif()
if(Vulkan_GLSLC_EXECUTABLE)
set(Vulkan_glslc_FOUND TRUE)
@@ -387,6 +457,12 @@ else()
set(Vulkan_glslangValidator_FOUND FALSE)
endif()
+if (Vulkan_dxc_EXECUTABLE)
+ set(Vulkan_dxc_exe_FOUND TRUE)
+else()
+ set(Vulkan_dxc_exe_FOUND FALSE)
+endif()
+
function(_Vulkan_set_library_component_found component)
cmake_parse_arguments(PARSE_ARGV 1 _ARG
"NO_WARNING"
@@ -437,6 +513,8 @@ _Vulkan_set_library_component_found(glslang
glslang-genericcodegen)
_Vulkan_set_library_component_found(shaderc_combined)
_Vulkan_set_library_component_found(SPIRV-Tools)
+_Vulkan_set_library_component_found(volk)
+_Vulkan_set_library_component_found(dxc)
if(Vulkan_MoltenVK_INCLUDE_DIR AND Vulkan_MoltenVK_LIBRARY)
set(Vulkan_MoltenVK_FOUND TRUE)
@@ -723,6 +801,44 @@ if(Vulkan_FOUND)
IMPORTED_LOCATION_DEBUG "${Vulkan_SPIRV-Tools_DEBUG_LIBRARY}")
endif()
endif()
+
+ if(Vulkan_volk_LIBRARY AND NOT TARGET Vulkan::volk)
+ add_library(Vulkan::volk STATIC IMPORTED)
+ set_property(TARGET Vulkan::volk
+ PROPERTY
+ INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}")
+ set_property(TARGET Vulkan::volk APPEND
+ PROPERTY
+ IMPORTED_CONFIGURATIONS Release)
+ set_property(TARGET Vulkan::volk APPEND
+ PROPERTY
+ IMPORTED_LOCATION_RELEASE "${Vulkan_volk_LIBRARY}")
+
+ if (NOT WIN32)
+ set_property(TARGET Vulkan::volk APPEND
+ PROPERTY
+ IMPORTED_LINK_INTERFACE_LIBRARIES dl)
+ endif()
+ endif()
+
+ if (Vulkan_dxc_LIBRARY AND NOT TARGET Vulkan::dxc_lib)
+ add_library(Vulkan::dxc_lib STATIC IMPORTED)
+ set_property(TARGET Vulkan::dxc_lib
+ PROPERTY
+ INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}")
+ set_property(TARGET Vulkan::dxc_lib APPEND
+ PROPERTY
+ IMPORTED_CONFIGURATIONS Release)
+ set_property(TARGET Vulkan::dxc_lib APPEND
+ PROPERTY
+ IMPORTED_LOCATION_RELEASE "${Vulkan_dxc_LIBRARY}")
+ endif()
+
+ if(Vulkan_dxc_EXECUTABLE AND NOT TARGET Vulkan::dxc_exe)
+ add_executable(Vulkan::dxc_exe IMPORTED)
+ set_property(TARGET Vulkan::dxc_exe PROPERTY IMPORTED_LOCATION "${Vulkan_dxc_EXECUTABLE}")
+ endif()
+
endif()
if(Vulkan_MoltenVK_FOUND)
diff --git a/Modules/Platform/AIX-GNU.cmake b/Modules/Platform/AIX-GNU.cmake
index 5a532c7..a9aa8e0 100644
--- a/Modules/Platform/AIX-GNU.cmake
+++ b/Modules/Platform/AIX-GNU.cmake
@@ -23,11 +23,11 @@ macro(__aix_compiler_gnu lang)
# Construct the export list ourselves to pass only the object files so
# that we export only the symbols actually provided by the sources.
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <AIX_EXPORTS> <OBJECTS>"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp -c <CMAKE_${lang}_COMPILER> <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/exports.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
)
set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <AIX_EXPORTS> <OBJECTS>"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -c <CMAKE_${lang}_COMPILER> -l . <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endmacro()
diff --git a/Modules/Platform/AIX-XL.cmake b/Modules/Platform/AIX-XL.cmake
index 2a8c159..902cbb3 100644
--- a/Modules/Platform/AIX-XL.cmake
+++ b/Modules/Platform/AIX-XL.cmake
@@ -29,12 +29,12 @@ macro(__aix_compiler_xl lang)
# Construct the export list ourselves to pass only the object files so
# that we export only the symbols actually provided by the sources.
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <AIX_EXPORTS>${_OBJECTS}"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp -c <CMAKE_${lang}_COMPILER> <AIX_EXPORTS>${_OBJECTS}"
"<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/exports.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
)
set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS
- "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <AIX_EXPORTS> <OBJECTS>"
+ "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -c <CMAKE_${lang}_COMPILER> -l . <AIX_EXPORTS> <OBJECTS>"
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
unset(_OBJECTS)
diff --git a/Modules/Platform/AIX/ExportImportList b/Modules/Platform/AIX/ExportImportList
index 891bce7..5e16fcb 100755
--- a/Modules/Platform/AIX/ExportImportList
+++ b/Modules/Platform/AIX/ExportImportList
@@ -5,7 +5,7 @@
# This script is internal to CMake and meant only to be
# invoked by CMake-generated build systems on AIX.
-usage='usage: ExportImportList -o <out-file> [-l <lib>] [-n] [--] <objects>...'
+usage='usage: ExportImportList -o <out-file> -c <compiler> [-l <lib>] [-n] [--] <objects>...'
die() {
echo "$@" 1>&2; exit 1
@@ -15,11 +15,13 @@ die() {
out=''
lib=''
no_objects=''
+compiler=''
while test "$#" != 0; do
case "$1" in
-l) shift; lib="$1" ;;
-o) shift; out="$1" ;;
-n) no_objects='1' ;;
+ -c) shift; compiler="$1" ;;
--) shift; break ;;
-*) die "$usage" ;;
*) break ;;
@@ -27,27 +29,47 @@ while test "$#" != 0; do
shift
done
test -n "$out" || die "$usage"
+# We need the compiler executable to resolve where the ibm-llvm-nm executable is
+test -n "$compiler" || die "$usage"
# Build a temporary file that atomically replaces the output later.
out_tmp="$out.tmp$$"
trap 'rm -f "$out_tmp"' EXIT INT TERM
> "$out_tmp"
+# If IPA was enabled and a compiler from the IBMClang family is used, then
+# the object files contain LLVM bitcode[0] rather than XCOFF objects and so
+# need to be handled differently.
+#
+# [0]: https://www.ibm.com/docs/en/openxl-c-and-cpp-aix/17.1.0?topic=compatibility-link-time-optimization-lto
+NM="$(dirname "$compiler")/../libexec/ibm-llvm-nm"
+
+function IsBitcode {
+ # N4 = first 4 bytes, -tx = output in hexadecimal, -An = don't display offset
+ # cut: trim off the preceding whitespace where the offset would be
+ # 4243code is the hexadecimal magic number for LLVM bitcode
+ [ "$(od -N4 -tx -An $1 | cut -d ' ' -f 2)" == "4243c0de" ];
+}
+
# Collect symbols exported from all object files.
if test -z "$no_objects"; then
for f in "$@"; do
- dump -tov -X 32_64 "$f" |
- awk '
- BEGIN {
- V["EXPORTED"]=" export"
- V["PROTECTED"]=" protected"
- }
- /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / {
- if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) {
- print $NF V[$(NF-1)]
+ if IsBitcode "$f"; then
+ "$NM" "$f" --defined-only --extern-only --just-symbol-name 2>/dev/null
+ else
+ dump -tov -X 32_64 "$f" |
+ awk '
+ BEGIN {
+ V["EXPORTED"]=" export"
+ V["PROTECTED"]=" protected"
+ }
+ /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / {
+ if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) {
+ print $NF V[$(NF-1)]
+ }
}
- }
- '
+ '
+ fi
done >> "$out_tmp"
fi
diff --git a/Modules/Platform/SerenityOS-Clang-ASM.cmake b/Modules/Platform/SerenityOS-Clang-ASM.cmake
new file mode 100644
index 0000000..ba1e18c
--- /dev/null
+++ b/Modules/Platform/SerenityOS-Clang-ASM.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(ASM)
diff --git a/Modules/Platform/SerenityOS-Clang-C.cmake b/Modules/Platform/SerenityOS-Clang-C.cmake
new file mode 100644
index 0000000..791a197
--- /dev/null
+++ b/Modules/Platform/SerenityOS-Clang-C.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(C)
diff --git a/Modules/Platform/SerenityOS-Clang-CXX.cmake b/Modules/Platform/SerenityOS-Clang-CXX.cmake
new file mode 100644
index 0000000..084e319
--- /dev/null
+++ b/Modules/Platform/SerenityOS-Clang-CXX.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(CXX)
diff --git a/Modules/Platform/SerenityOS-GNU-ASM.cmake b/Modules/Platform/SerenityOS-GNU-ASM.cmake
new file mode 100644
index 0000000..ba1e18c
--- /dev/null
+++ b/Modules/Platform/SerenityOS-GNU-ASM.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(ASM)
diff --git a/Modules/Platform/SerenityOS-GNU-C.cmake b/Modules/Platform/SerenityOS-GNU-C.cmake
new file mode 100644
index 0000000..791a197
--- /dev/null
+++ b/Modules/Platform/SerenityOS-GNU-C.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(C)
diff --git a/Modules/Platform/SerenityOS-GNU-CXX.cmake b/Modules/Platform/SerenityOS-GNU-CXX.cmake
new file mode 100644
index 0000000..084e319
--- /dev/null
+++ b/Modules/Platform/SerenityOS-GNU-CXX.cmake
@@ -0,0 +1,2 @@
+include(Platform/SerenityOS-GNU)
+__serenity_compiler_gnu(CXX)
diff --git a/Modules/Platform/SerenityOS-GNU.cmake b/Modules/Platform/SerenityOS-GNU.cmake
new file mode 100644
index 0000000..ed39477
--- /dev/null
+++ b/Modules/Platform/SerenityOS-GNU.cmake
@@ -0,0 +1,24 @@
+# This module is shared by multiple languages; use include blocker.
+include_guard()
+
+set(CMAKE_EXE_LINKER_FLAGS_INIT "-Wl,--hash-style=gnu,-z,relro,-z,now,-z,noexecstack,-z,separate-code,-z,max-page-size=0x1000")
+
+macro(__serenity_compiler_gnu lang)
+ set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-rpath,")
+ set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":")
+ set(CMAKE_SHARED_LIBRARY_RPATH_LINK_${lang}_FLAG "-Wl,-rpath-link,")
+ set(CMAKE_SHARED_LIBRARY_SONAME_${lang}_FLAG "-Wl,-soname,")
+ set(CMAKE_EXE_EXPORTS_${lang}_FLAG "-Wl,--export-dynamic")
+
+ set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared -Wl,--hash-style=gnu,-z,relro,-z,now,-z,noexecstack,-z,separate-code")
+
+ # Initialize link type selection flags. These flags are used when
+ # building a shared library, shared module, or executable that links
+ # to other libraries to select whether to use the static or shared
+ # versions of the libraries.
+ foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
+ set(CMAKE_${type}_LINK_STATIC_${lang}_FLAGS "-Wl,-Bstatic")
+ set(CMAKE_${type}_LINK_DYNAMIC_${lang}_FLAGS "-Wl,-Bdynamic")
+ endforeach()
+
+endmacro()
diff --git a/Modules/Platform/SerenityOS.cmake b/Modules/Platform/SerenityOS.cmake
new file mode 100644
index 0000000..541620c
--- /dev/null
+++ b/Modules/Platform/SerenityOS.cmake
@@ -0,0 +1,12 @@
+
+set(SERENITYOS 1)
+
+set(CMAKE_DL_LIBS "-ldl")
+set(CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN "\$ORIGIN")
+set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
+
+# Shared libraries with no builtin soname may not be linked safely by
+# specifying the file path.
+set(CMAKE_PLATFORM_USES_PATH_WHEN_NO_SONAME 1)
+
+include(Platform/UnixPaths)
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 95b07cb..fe92716 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -197,6 +197,8 @@ set(SRCS
cmCustomCommandLines.cxx
cmCustomCommandLines.h
cmCustomCommandTypes.h
+ cmCxxModuleMapper.cxx
+ cmCxxModuleMapper.h
cmDefinitions.cxx
cmDefinitions.h
cmDependencyProvider.h
@@ -543,6 +545,8 @@ set(SRCS
cmExecuteProcessCommand.h
cmExpandedCommandArgument.cxx
cmExpandedCommandArgument.h
+ cmExperimental.cxx
+ cmExperimental.h
cmExportCommand.cxx
cmExportCommand.h
cmExportLibraryDependenciesCommand.cxx
@@ -603,6 +607,8 @@ set(SRCS
cmInstallCommand.h
cmInstallCommandArguments.cxx
cmInstallCommandArguments.h
+ cmInstallCxxModuleBmiGenerator.cxx
+ cmInstallCxxModuleBmiGenerator.h
cmInstallFilesCommand.cxx
cmInstallFilesCommand.h
cmInstallProgramsCommand.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index f6e25ed..c5024a5 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,8 +1,8 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 24)
-set(CMake_VERSION_PATCH 0)
-set(CMake_VERSION_RC 4)
+set(CMake_VERSION_PATCH 20220725)
+#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
# Start with the full version number used in tags. It has no dev info.
diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx
index 607d797..162dfc7 100644
--- a/Source/CPack/cmCPackFreeBSDGenerator.cxx
+++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx
@@ -23,8 +23,6 @@
// Suffix used to tell libpkg what compression to use
static const char FreeBSDPackageCompression[] = "txz";
-// Resulting package file-suffix, for < 1.17 and >= 1.17 versions of libpkg
-static const char FreeBSDPackageSuffix_10[] = ".txz";
static const char FreeBSDPackageSuffix_17[] = ".pkg";
cmCPackFreeBSDGenerator::cmCPackFreeBSDGenerator()
@@ -83,6 +81,14 @@ public:
{
if (!isValid())
return false;
+ // The API in the FreeBSD sources (the header has no documentation),
+ // is as follows:
+ //
+ // int pkg_create(struct pkg_create *pc, const char *metadata, const char
+ // *plist, bool hash)
+ //
+ // We let the plist be determined from what is installed, and all
+ // the rest comes from the manifest data.
int r = pkg_create(d, manifest.c_str(), nullptr, false);
return r == 0;
}
@@ -402,7 +408,8 @@ int cmCPackFreeBSDGenerator::PackageFiles()
return 0;
}
- std::string output_dir = cmSystemTools::CollapseFullPath("../", toplevel);
+ const std::string output_dir =
+ cmSystemTools::CollapseFullPath("../", toplevel);
PkgCreate package(output_dir, toplevel, manifestname);
if (package.isValid()) {
if (!package.Create()) {
@@ -416,40 +423,33 @@ int cmCPackFreeBSDGenerator::PackageFiles()
return 0;
}
- // Specifically looking for packages suffixed with the TAG, either extension
- std::string broken_suffix_10 =
- cmStrCat('-', var_lookup("CPACK_TOPLEVEL_TAG"), FreeBSDPackageSuffix_10);
+ // Specifically looking for packages suffixed with the TAG
std::string broken_suffix_17 =
cmStrCat('-', var_lookup("CPACK_TOPLEVEL_TAG"), FreeBSDPackageSuffix_17);
for (std::string& name : packageFileNames) {
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Packagefile " << name << std::endl);
- if (cmHasSuffix(name, broken_suffix_10)) {
- name.replace(name.size() - broken_suffix_10.size(), std::string::npos,
- FreeBSDPackageSuffix_10);
- break;
- }
if (cmHasSuffix(name, broken_suffix_17)) {
name.replace(name.size() - broken_suffix_17.size(), std::string::npos,
FreeBSDPackageSuffix_17);
break;
}
}
- // If the name uses a *new* style name, which doesn't exist, but there
- // is an *old* style name, then use that instead. This indicates we used
- // an older libpkg, which still creates .txz instead of .pkg files.
- for (std::string& name : packageFileNames) {
- if (cmHasSuffix(name, FreeBSDPackageSuffix_17) &&
- !cmSystemTools::FileExists(name)) {
- const std::string badSuffix(FreeBSDPackageSuffix_17);
- const std::string goodSuffix(FreeBSDPackageSuffix_10);
- std::string repairedName(name);
- repairedName.replace(repairedName.size() - badSuffix.size(),
- std::string::npos, goodSuffix);
- if (cmSystemTools::FileExists(repairedName)) {
- name = repairedName;
- cmCPackLogger(cmCPackLog::LOG_DEBUG,
- "Repaired packagefile " << name << std::endl);
- }
+
+ const std::string packageFileName =
+ var_lookup("CPACK_PACKAGE_FILE_NAME") + FreeBSDPackageSuffix_17;
+ if (packageFileNames.size() == 1 && !packageFileName.empty() &&
+ packageFileNames[0] != packageFileName) {
+ // Since libpkg always writes <name>-<version>.<suffix>,
+ // if there is a CPACK_PACKAGE_FILE_NAME set, we need to
+ // rename, and then re-set the name.
+ const std::string sourceFile = packageFileNames[0];
+ const std::string packageSubDirectory =
+ cmSystemTools::GetParentDirectory(sourceFile);
+ const std::string targetFileName =
+ packageSubDirectory + '/' + packageFileName;
+ if (cmSystemTools::RenameFile(sourceFile, targetFileName)) {
+ this->packageFileNames.clear();
+ this->packageFileNames.emplace_back(targetFileName);
}
}
diff --git a/Source/CTest/cmCTestCoverageCommand.cxx b/Source/CTest/cmCTestCoverageCommand.cxx
index 7432d08..97b0a89 100644
--- a/Source/CTest/cmCTestCoverageCommand.cxx
+++ b/Source/CTest/cmCTestCoverageCommand.cxx
@@ -4,7 +4,6 @@
#include <set>
-#include <cmext/algorithm>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -18,13 +17,6 @@ void cmCTestCoverageCommand::BindArguments()
this->Bind("LABELS"_s, this->Labels);
}
-void cmCTestCoverageCommand::CheckArguments(
- std::vector<std::string> const& keywords)
-{
- this->LabelsMentioned =
- !this->Labels.empty() || cm::contains(keywords, "LABELS");
-}
-
cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
{
this->CTest->SetCTestConfigurationFromCMakeVariable(
@@ -36,9 +28,9 @@ cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler()
handler->Initialize();
// If a LABELS option was given, select only files with the labels.
- if (this->LabelsMentioned) {
+ if (this->Labels) {
handler->SetLabelFilter(
- std::set<std::string>(this->Labels.begin(), this->Labels.end()));
+ std::set<std::string>(this->Labels->begin(), this->Labels->end()));
}
handler->SetQuiet(this->Quiet);
diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h
index 9344852..55c68b2 100644
--- a/Source/CTest/cmCTestCoverageCommand.h
+++ b/Source/CTest/cmCTestCoverageCommand.h
@@ -9,7 +9,9 @@
#include <vector>
#include <cm/memory>
+#include <cm/optional>
+#include "cmArgumentParserTypes.h" // IWYU pragma: keep
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
@@ -41,9 +43,7 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const& keywords) override;
cmCTestGenericHandler* InitializeHandler() override;
- bool LabelsMentioned;
- std::vector<std::string> Labels;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Labels;
};
diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx
index 5494d20..af365ad 100644
--- a/Source/CTest/cmCTestHandlerCommand.cxx
+++ b/Source/CTest/cmCTestHandlerCommand.cxx
@@ -7,6 +7,7 @@
#include <cstring>
#include <sstream>
+#include <cm/string_view>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -81,11 +82,10 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args,
// Process input arguments.
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
- std::vector<std::string> parsedKeywords;
- this->Parse(args, &unparsedArguments, &keywordsMissingValue,
+ std::vector<cm::string_view> parsedKeywords;
+ this->Parse(args, &unparsedArguments, /*keywordsMissingValue=*/nullptr,
&parsedKeywords);
- this->CheckArguments(keywordsMissingValue);
+ this->CheckArguments();
std::sort(parsedKeywords.begin(), parsedKeywords.end());
auto it = std::adjacent_find(parsedKeywords.begin(), parsedKeywords.end());
@@ -242,6 +242,6 @@ void cmCTestHandlerCommand::BindArguments()
this->Bind("SUBMIT_INDEX"_s, this->SubmitIndex);
}
-void cmCTestHandlerCommand::CheckArguments(std::vector<std::string> const&)
+void cmCTestHandlerCommand::CheckArguments()
{
}
diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h
index 756952d..31942c8 100644
--- a/Source/CTest/cmCTestHandlerCommand.h
+++ b/Source/CTest/cmCTestHandlerCommand.h
@@ -42,7 +42,7 @@ protected:
// Command argument handling.
virtual void BindArguments();
- virtual void CheckArguments(std::vector<std::string> const& keywords);
+ virtual void CheckArguments();
bool Append = false;
bool Quiet = false;
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index a2dc615..a1933cc 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -8,7 +8,6 @@
#include <cm/memory>
#include <cm/vector>
-#include <cmext/algorithm>
#include <cmext/string_view>
#include "cmCTest.h"
@@ -87,7 +86,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// If FILES are given, but not PARTS, only the FILES are submitted
// and *no* PARTS are submitted.
// (This is why we select the empty "noParts" set in the
- // FilesMentioned block below...)
+ // if(this->Files) block below...)
//
// If PARTS are given, only the selected PARTS are submitted.
//
@@ -96,7 +95,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
// If given explicit FILES to submit, pass them to the handler.
//
- if (this->FilesMentioned) {
+ if (this->Files) {
// Intentionally select *no* PARTS. (Pass an empty set.) If PARTS
// were also explicitly mentioned, they will be selected below...
// But FILES with no PARTS mentioned should just submit the FILES
@@ -104,14 +103,14 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler()
//
handler->SelectParts(std::set<cmCTest::Part>());
handler->SelectFiles(
- std::set<std::string>(this->Files.begin(), this->Files.end()));
+ std::set<std::string>(this->Files->begin(), this->Files->end()));
}
// If a PARTS option was given, select only the named parts for submission.
//
- if (this->PartsMentioned) {
+ if (this->Parts) {
auto parts =
- cmMakeRange(this->Parts).transform([this](std::string const& arg) {
+ cmMakeRange(*(this->Parts)).transform([this](std::string const& arg) {
return this->CTest->GetPartFromName(arg);
});
handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end()));
@@ -172,33 +171,31 @@ void cmCTestSubmitCommand::BindArguments()
this->cmCTestHandlerCommand::BindArguments();
}
-void cmCTestSubmitCommand::CheckArguments(
- std::vector<std::string> const& keywords)
+void cmCTestSubmitCommand::CheckArguments()
{
- this->PartsMentioned =
- !this->Parts.empty() || cm::contains(keywords, "PARTS");
- this->FilesMentioned =
- !this->Files.empty() || cm::contains(keywords, "FILES");
-
- cm::erase_if(this->Parts, [this](std::string const& arg) -> bool {
- cmCTest::Part p = this->CTest->GetPartFromName(arg);
- if (p == cmCTest::PartCount) {
- std::ostringstream e;
- e << "Part name \"" << arg << "\" is invalid.";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return true;
- }
- return false;
- });
-
- cm::erase_if(this->Files, [this](std::string const& arg) -> bool {
- if (!cmSystemTools::FileExists(arg)) {
- std::ostringstream e;
- e << "File \"" << arg << "\" does not exist. Cannot submit "
- << "a non-existent file.";
- this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
- return true;
- }
- return false;
- });
+ if (this->Parts) {
+ cm::erase_if(*(this->Parts), [this](std::string const& arg) -> bool {
+ cmCTest::Part p = this->CTest->GetPartFromName(arg);
+ if (p == cmCTest::PartCount) {
+ std::ostringstream e;
+ e << "Part name \"" << arg << "\" is invalid.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return true;
+ }
+ return false;
+ });
+ }
+
+ if (this->Files) {
+ cm::erase_if(*(this->Files), [this](std::string const& arg) -> bool {
+ if (!cmSystemTools::FileExists(arg)) {
+ std::ostringstream e;
+ e << "File \"" << arg << "\" does not exist. Cannot submit "
+ << "a non-existent file.";
+ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return true;
+ }
+ return false;
+ });
+ }
}
diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h
index c5d11df..b67f182 100644
--- a/Source/CTest/cmCTestSubmitCommand.h
+++ b/Source/CTest/cmCTestSubmitCommand.h
@@ -8,6 +8,9 @@
#include <string>
#include <vector>
+#include <cm/optional>
+
+#include "cmArgumentParserTypes.h"
#include "cmCTestHandlerCommand.h"
class cmCommand;
@@ -35,13 +38,11 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const& keywords) override;
+ void CheckArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
bool CDashUpload = false;
- bool FilesMentioned = false;
bool InternalTest = false;
- bool PartsMentioned = false;
std::string BuildID;
std::string CDashUploadFile;
@@ -50,7 +51,7 @@ protected:
std::string RetryDelay;
std::string SubmitURL;
- std::vector<std::string> Files;
- std::vector<std::string> HttpHeaders;
- std::vector<std::string> Parts;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Files;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> HttpHeaders;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Parts;
};
diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx
index f86ee0d..2ed671c 100644
--- a/Source/CTest/cmCTestUploadCommand.cxx
+++ b/Source/CTest/cmCTestUploadCommand.cxx
@@ -21,7 +21,7 @@ void cmCTestUploadCommand::BindArguments()
this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError);
}
-void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&)
+void cmCTestUploadCommand::CheckArguments()
{
cm::erase_if(this->Files, [this](std::string const& arg) -> bool {
if (!cmSystemTools::FileExists(arg)) {
diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h
index fe155f6..a9d1dd2 100644
--- a/Source/CTest/cmCTestUploadCommand.h
+++ b/Source/CTest/cmCTestUploadCommand.h
@@ -10,6 +10,7 @@
#include <cm/memory>
+#include "cmArgumentParserTypes.h"
#include "cmCTestHandlerCommand.h"
#include "cmCommand.h"
@@ -42,8 +43,8 @@ public:
protected:
void BindArguments() override;
- void CheckArguments(std::vector<std::string> const&) override;
+ void CheckArguments() override;
cmCTestGenericHandler* InitializeHandler() override;
- std::vector<std::string> Files;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Files;
};
diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx
index b14a751..6e6f0d6 100644
--- a/Source/CursesDialog/cmCursesLongMessageForm.cxx
+++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx
@@ -85,7 +85,7 @@ void cmCursesLongMessageForm::UpdateStatusBar()
for (size_t i = 0; i < sideSpace; i++) {
version[i] = ' ';
}
- sprintf(version + sideSpace, "%s", vertmp);
+ snprintf(version + sideSpace, sizeof(version) - sideSpace, "%s", vertmp);
version[width] = '\0';
char fmt_s[] = "%s";
diff --git a/Source/CursesDialog/form/.gitattributes b/Source/CursesDialog/form/.gitattributes
index 12ede74..6dfa627 100644
--- a/Source/CursesDialog/form/.gitattributes
+++ b/Source/CursesDialog/form/.gitattributes
@@ -1 +1,2 @@
+* -whitespace
* -format.clang-format-6.0
diff --git a/Source/CursesDialog/form/fty_int.c b/Source/CursesDialog/form/fty_int.c
index 7107fcc..7aeb4b8 100644
--- a/Source/CursesDialog/form/fty_int.c
+++ b/Source/CursesDialog/form/fty_int.c
@@ -117,7 +117,7 @@ static bool Check_Integer_Field(FIELD * field, const void * argp)
{
if (val<low || val>high) return FALSE;
}
- sprintf(buf,"%.*ld",(prec>0?prec:0),val);
+ snprintf(buf,sizeof(buf),"%.*ld",(prec>0?prec:0),val);
set_field_buffer(field,0,buf);
return TRUE;
}
diff --git a/Source/CursesDialog/form/fty_num.c b/Source/CursesDialog/form/fty_num.c
index 7809599..4109b6f 100644
--- a/Source/CursesDialog/form/fty_num.c
+++ b/Source/CursesDialog/form/fty_num.c
@@ -140,7 +140,7 @@ static bool Check_Numeric_Field(FIELD * field, const void * argp)
{
if (val<low || val>high) return FALSE;
}
- sprintf(buf,"%.*f",(prec>0?prec:0),val);
+ snprintf(buf,sizeof(buf),"%.*f",(prec>0?prec:0),val);
set_field_buffer(field,0,buf);
return TRUE;
}
diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx
index 4624f1c..f0c4cfc 100644
--- a/Source/cmArgumentParser.cxx
+++ b/Source/cmArgumentParser.cxx
@@ -4,6 +4,8 @@
#include <algorithm>
+#include "cmArgumentParserTypes.h"
+
namespace ArgumentParser {
auto ActionMap::Emplace(cm::string_view name, Action action)
@@ -44,14 +46,28 @@ void Instance::Bind(std::string& val)
this->ExpectValue = true;
}
-void Instance::Bind(StringList& val)
+void Instance::Bind(Maybe<std::string>& val)
+{
+ this->CurrentString = &val;
+ this->CurrentList = nullptr;
+ this->ExpectValue = false;
+}
+
+void Instance::Bind(MaybeEmpty<std::vector<std::string>>& val)
+{
+ this->CurrentString = nullptr;
+ this->CurrentList = &val;
+ this->ExpectValue = false;
+}
+
+void Instance::Bind(NonEmpty<std::vector<std::string>>& val)
{
this->CurrentString = nullptr;
this->CurrentList = &val;
this->ExpectValue = true;
}
-void Instance::Bind(MultiStringList& val)
+void Instance::Bind(std::vector<std::vector<std::string>>& val)
{
this->CurrentString = nullptr;
this->CurrentList = (static_cast<void>(val.emplace_back()), &val.back());
@@ -60,17 +76,17 @@ void Instance::Bind(MultiStringList& val)
void Instance::Consume(cm::string_view arg, void* result,
std::vector<std::string>* unparsedArguments,
- std::vector<std::string>* keywordsMissingValue,
- std::vector<std::string>* parsedKeywords)
+ std::vector<cm::string_view>* keywordsMissingValue,
+ std::vector<cm::string_view>* parsedKeywords)
{
auto const it = this->Bindings.Find(arg);
if (it != this->Bindings.end()) {
if (parsedKeywords != nullptr) {
- parsedKeywords->emplace_back(arg);
+ parsedKeywords->emplace_back(it->first);
}
it->second(*this, result);
if (this->ExpectValue && keywordsMissingValue != nullptr) {
- keywordsMissingValue->emplace_back(arg);
+ keywordsMissingValue->emplace_back(it->first);
}
return;
}
diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h
index 71ed844..26148d9 100644
--- a/Source/cmArgumentParser.h
+++ b/Source/cmArgumentParser.h
@@ -10,13 +10,13 @@
#include <utility>
#include <vector>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
-namespace ArgumentParser {
+#include "cmArgumentParserTypes.h" // IWYU pragma: keep
-using StringList = std::vector<std::string>;
-using MultiStringList = std::vector<StringList>;
+namespace ArgumentParser {
class Instance;
using Action = std::function<void(Instance&, void*)>;
@@ -39,18 +39,30 @@ public:
void Bind(bool& val);
void Bind(std::string& val);
- void Bind(StringList& val);
- void Bind(MultiStringList& val);
+ void Bind(Maybe<std::string>& val);
+ void Bind(MaybeEmpty<std::vector<std::string>>& val);
+ void Bind(NonEmpty<std::vector<std::string>>& val);
+ void Bind(std::vector<std::vector<std::string>>& val);
+
+ // cm::optional<> records the presence the keyword to which it binds.
+ template <typename T>
+ void Bind(cm::optional<T>& optVal)
+ {
+ if (!optVal) {
+ optVal.emplace();
+ }
+ this->Bind(*optVal);
+ }
void Consume(cm::string_view arg, void* result,
std::vector<std::string>* unparsedArguments,
- std::vector<std::string>* keywordsMissingValue,
- std::vector<std::string>* parsedKeywords);
+ std::vector<cm::string_view>* keywordsMissingValue,
+ std::vector<cm::string_view>* parsedKeywords);
private:
ActionMap const& Bindings;
std::string* CurrentString = nullptr;
- StringList* CurrentList = nullptr;
+ std::vector<std::string>* CurrentList = nullptr;
bool ExpectValue = false;
};
@@ -78,9 +90,9 @@ public:
template <typename Range>
void Parse(Result& result, Range const& args,
- std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ std::vector<std::string>* unparsedArguments,
+ std::vector<cm::string_view>* keywordsMissingValue = nullptr,
+ std::vector<cm::string_view>* parsedKeywords = nullptr) const
{
ArgumentParser::Instance instance(this->Bindings);
for (cm::string_view arg : args) {
@@ -90,10 +102,9 @@ public:
}
template <typename Range>
- Result Parse(Range const& args,
- std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ Result Parse(Range const& args, std::vector<std::string>* unparsedArguments,
+ std::vector<cm::string_view>* keywordsMissingValue = nullptr,
+ std::vector<cm::string_view>* parsedKeywords = nullptr) const
{
Result result;
this->Parse(result, args, unparsedArguments, keywordsMissingValue,
@@ -118,10 +129,9 @@ public:
}
template <typename Range>
- void Parse(Range const& args,
- std::vector<std::string>* unparsedArguments = nullptr,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ void Parse(Range const& args, std::vector<std::string>* unparsedArguments,
+ std::vector<cm::string_view>* keywordsMissingValue = nullptr,
+ std::vector<cm::string_view>* parsedKeywords = nullptr) const
{
ArgumentParser::Instance instance(this->Bindings);
for (cm::string_view arg : args) {
diff --git a/Source/cmArgumentParserTypes.h b/Source/cmArgumentParserTypes.h
new file mode 100644
index 0000000..9afa5c7
--- /dev/null
+++ b/Source/cmArgumentParserTypes.h
@@ -0,0 +1,24 @@
+/* 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
+
+namespace ArgumentParser {
+
+template <typename T>
+struct Maybe : public T
+{
+};
+
+template <typename T>
+struct MaybeEmpty : public T
+{
+};
+
+template <typename T>
+struct NonEmpty : public T
+{
+};
+
+} // namespace ArgumentParser
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 0750eea..033dd6d 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -491,7 +491,7 @@ bool QueryWindowsRegistry(Range args, cmExecutionStatus& status,
.Bind("SEPARATOR"_s, &Arguments::Separator)
.Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable);
std::vector<std::string> invalidArgs;
- std::vector<std::string> keywordsMissingValue;
+ std::vector<cm::string_view> keywordsMissingValue;
Arguments const arguments =
parser.Parse(args.advance(1), &invalidArgs, &keywordsMissingValue);
diff --git a/Source/cmCMakeLanguageCommand.cxx b/Source/cmCMakeLanguageCommand.cxx
index a2aaa2a..76561c3 100644
--- a/Source/cmCMakeLanguageCommand.cxx
+++ b/Source/cmCMakeLanguageCommand.cxx
@@ -14,15 +14,18 @@
#include <cmext/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmDependencyProvider.h"
#include "cmExecutionStatus.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmake.h"
namespace {
@@ -235,7 +238,7 @@ bool cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER(
struct SetProviderArgs
{
std::string Command;
- std::vector<std::string> Methods;
+ ArgumentParser::NonEmpty<std::vector<std::string>> Methods;
};
auto const ArgsParser =
@@ -303,6 +306,27 @@ bool cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER(
return true;
}
+
+bool cmCMakeLanguageCommandGET_MESSAGE_LOG_LEVEL(
+ std::vector<cmListFileArgument> const& args, cmExecutionStatus& status)
+{
+ cmMakefile& makefile = status.GetMakefile();
+ std::vector<std::string> expandedArgs;
+ makefile.ExpandArguments(args, expandedArgs);
+
+ if (args.size() < 2 || expandedArgs.size() > 2) {
+ return FatalError(
+ status,
+ "sub-command GET_MESSAGE_LOG_LEVEL expects exactly one argument");
+ }
+
+ Message::LogLevel logLevel = makefile.GetCurrentLogLevel();
+ std::string outputValue = cmake::LogLevelToString(logLevel);
+
+ const std::string& outputVariable = expandedArgs[1];
+ makefile.AddDefinition(outputVariable, outputValue);
+ return true;
+}
}
bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
@@ -451,5 +475,9 @@ bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args,
return cmCMakeLanguageCommandEVAL(args, status);
}
+ if (expArgs[expArg] == "GET_MESSAGE_LOG_LEVEL") {
+ return cmCMakeLanguageCommandGET_MESSAGE_LOG_LEVEL(args, status);
+ }
+
return FatalError(status, "called with unknown meta-operation");
}
diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx
index bf94c2d..adcffa9 100644
--- a/Source/cmCMakePathCommand.cxx
+++ b/Source/cmCMakePathCommand.cxx
@@ -44,8 +44,8 @@ public:
template <int Advance = 2>
Result Parse(std::vector<std::string> const& args,
- std::vector<std::string>* keywordsMissingValue = nullptr,
- std::vector<std::string>* parsedKeywords = nullptr) const
+ std::vector<cm::string_view>* keywordsMissingValue = nullptr,
+ std::vector<cm::string_view>* parsedKeywords = nullptr) const
{
this->Inputs.clear();
@@ -89,11 +89,11 @@ public:
args, &this->KeywordsMissingValue, &this->ParsedKeywords);
}
- const std::vector<std::string>& GetKeywordsMissingValue() const
+ const std::vector<cm::string_view>& GetKeywordsMissingValue() const
{
return this->KeywordsMissingValue;
}
- const std::vector<std::string>& GetParsedKeywords() const
+ const std::vector<cm::string_view>& GetParsedKeywords() const
{
return this->ParsedKeywords;
}
@@ -121,8 +121,8 @@ public:
}
private:
- mutable std::vector<std::string> KeywordsMissingValue;
- mutable std::vector<std::string> ParsedKeywords;
+ mutable std::vector<cm::string_view> KeywordsMissingValue;
+ mutable std::vector<cm::string_view> ParsedKeywords;
};
struct OutputVariable
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index ba95168..5fe6756 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -9,6 +9,7 @@
#include "cmComputeLinkInformation.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
+#include "cmGlobalGenerator.h"
#include "cmLocalCommonGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
@@ -175,6 +176,9 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories(
cmLocalGenerator* lg = linkee->GetLocalGenerator();
std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
lg->GetTargetDirectory(linkee));
+ if (lg->GetGlobalGenerator()->IsMultiConfig()) {
+ di = cmStrCat(di, '/', config);
+ }
dirs.push_back(std::move(di));
}
}
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 6a419f6..31d03da 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -14,6 +14,10 @@
#pragma warning(disable : 1572) /* floating-point equality test */
#endif
+#if defined(__LCC__) && defined(__EDG__) && (__LCC__ == 123)
+#pragma diag_suppress 2910 /* excess -Wunused-function in 1.23.x */
+#endif
+
#cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE
#cmakedefine HAVE_UNSETENV
#cmakedefine CMake_USE_MACH_PARSER
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 5418e7c..45afdd1 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -605,6 +605,15 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
// does not include any system headers anyway.
fprintf(fout,
"set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES \"\")\n");
+
+ // The link and compile lines for ABI detection step need to not use
+ // response files so we can extract implicit includes given to
+ // the underlying host compiler
+ if (testLangs.find("CUDA") != testLangs.end()) {
+ fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES OFF)\n");
+ fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES OFF)\n");
+ fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS OFF)\n");
+ }
}
fprintf(fout, "set(CMAKE_VERBOSE_MAKEFILE 1)\n");
for (std::string const& li : testLangs) {
@@ -1117,7 +1126,8 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
searchDirs.emplace_back(std::move(tmp));
}
searchDirs.emplace_back("/Debug");
-#if defined(__APPLE__)
+
+ // handle app-bundles (for targeting apple-platforms)
std::string app = "/" + targetName + ".app";
if (cmNonempty(config)) {
std::string tmp = cmStrCat('/', *config, app);
@@ -1126,7 +1136,7 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
std::string tmp = "/Debug" + app;
searchDirs.emplace_back(std::move(tmp));
searchDirs.emplace_back(std::move(app));
-#endif
+
searchDirs.emplace_back("/Development");
for (std::string const& sdir : searchDirs) {
diff --git a/Source/cmCxxModuleMapper.cxx b/Source/cmCxxModuleMapper.cxx
new file mode 100644
index 0000000..94ad721
--- /dev/null
+++ b/Source/cmCxxModuleMapper.cxx
@@ -0,0 +1,76 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCxxModuleMapper.h"
+
+#include <cassert>
+#include <sstream>
+#include <vector>
+
+#include "cmScanDepFormat.h"
+
+cm::optional<std::string> CxxModuleLocations::BmiGeneratorPathForModule(
+ std::string const& logical_name) const
+{
+ if (auto l = this->BmiLocationForModule(logical_name)) {
+ return this->PathForGenerator(*l);
+ }
+ return {};
+}
+
+namespace {
+
+std::string CxxModuleMapContentGcc(CxxModuleLocations const& loc,
+ cmScanDepInfo const& obj)
+{
+ std::stringstream mm;
+
+ // Documented in GCC's documentation. The format is a series of
+ // lines with a module name and the associated filename separated
+ // by spaces. The first line may use `$root` as the module name
+ // to specify a "repository root". That is used to anchor any
+ // relative paths present in the file (CMake should never
+ // generate any).
+
+ // Write the root directory to use for module paths.
+ mm << "$root " << loc.RootDirectory << "\n";
+
+ for (auto const& p : obj.Provides) {
+ if (auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName)) {
+ mm << p.LogicalName << ' ' << *bmi_loc << '\n';
+ }
+ }
+ for (auto const& r : obj.Requires) {
+ if (auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName)) {
+ mm << r.LogicalName << ' ' << *bmi_loc << '\n';
+ }
+ }
+
+ return mm.str();
+}
+}
+
+cm::static_string_view CxxModuleMapExtension(
+ cm::optional<CxxModuleMapFormat> format)
+{
+ if (format) {
+ switch (*format) {
+ case CxxModuleMapFormat::Gcc:
+ return ".gcm"_s;
+ }
+ }
+
+ return ".bmi"_s;
+}
+
+std::string CxxModuleMapContent(CxxModuleMapFormat format,
+ CxxModuleLocations const& loc,
+ cmScanDepInfo const& obj)
+{
+ switch (format) {
+ case CxxModuleMapFormat::Gcc:
+ return CxxModuleMapContentGcc(loc, obj);
+ }
+
+ assert(false);
+ return {};
+}
diff --git a/Source/cmCxxModuleMapper.h b/Source/cmCxxModuleMapper.h
new file mode 100644
index 0000000..99384c9
--- /dev/null
+++ b/Source/cmCxxModuleMapper.h
@@ -0,0 +1,48 @@
+/* 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 <functional>
+#include <string>
+
+#include <cm/optional>
+#include <cmext/string_view>
+
+struct cmScanDepInfo;
+
+enum class CxxModuleMapFormat
+{
+ Gcc,
+};
+
+struct CxxModuleLocations
+{
+ // The path from which all relative paths should be computed. If
+ // this is relative, it is relative to the compiler's working
+ // directory.
+ std::string RootDirectory;
+
+ // A function to convert a full path to a path for the generator.
+ std::function<std::string(std::string const&)> PathForGenerator;
+
+ // Lookup the BMI location of a logical module name.
+ std::function<cm::optional<std::string>(std::string const&)>
+ BmiLocationForModule;
+
+ // Returns the generator path (if known) for the BMI given a
+ // logical module name.
+ cm::optional<std::string> BmiGeneratorPathForModule(
+ std::string const& logical_name) const;
+};
+
+// Return the extension to use for a given modulemap format.
+cm::static_string_view CxxModuleMapExtension(
+ cm::optional<CxxModuleMapFormat> format);
+
+// Return the contents of the module map in the given format for the
+// object file.
+std::string CxxModuleMapContent(CxxModuleMapFormat format,
+ CxxModuleLocations const& loc,
+ cmScanDepInfo const& obj);
diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx
index faefcb8..31ee665 100644
--- a/Source/cmDefinePropertyCommand.cxx
+++ b/Source/cmDefinePropertyCommand.cxx
@@ -8,6 +8,7 @@
#include <cmext/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmProperty.h"
@@ -51,8 +52,8 @@ bool cmDefinePropertyCommand(std::vector<std::string> const& args,
// Parse remaining arguments.
bool inherited = false;
std::string PropertyName;
- std::vector<std::string> BriefDocs;
- std::vector<std::string> FullDocs;
+ ArgumentParser::NonEmpty<std::vector<std::string>> BriefDocs;
+ ArgumentParser::NonEmpty<std::vector<std::string>> FullDocs;
std::string initializeFromVariable;
cmArgumentParser<void> parser;
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 222ea80..af56e2d 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -95,13 +95,13 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args,
.Bind("COMMAND_ERROR_IS_FATAL"_s, &Arguments::CommandErrorIsFatal);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
+ std::vector<cm::string_view> keywordsMissingValue;
Arguments const arguments =
parser.Parse(args, &unparsedArguments, &keywordsMissingValue);
if (!keywordsMissingValue.empty()) {
- status.SetError(" called with no value for " +
- keywordsMissingValue.front() + ".");
+ status.SetError(cmStrCat(" called with no value for ",
+ keywordsMissingValue.front(), "."));
return false;
}
if (!unparsedArguments.empty()) {
diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx
new file mode 100644
index 0000000..922b53f
--- /dev/null
+++ b/Source/cmExperimental.cxx
@@ -0,0 +1,63 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmExperimental.h"
+
+#include <cassert>
+#include <cstddef>
+#include <string>
+
+#include "cmMakefile.h"
+#include "cmMessageType.h"
+#include "cmValue.h"
+
+namespace {
+
+/*
+ * The `Uuid` fields of these objects should change periodically.
+ * Search for other instances to keep the documentation and test suite
+ * up-to-date.
+ */
+
+struct FeatureData
+{
+ std::string const Uuid;
+ std::string const Variable;
+ std::string const Description;
+ bool Warned;
+} LookupTable[] = {
+ // CxxModuleCMakeApi
+ { "3c375311-a3c9-4396-a187-3227ef642046",
+ "CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API",
+ "CMake's C++ module support is experimental. It is meant only for "
+ "experimentation and feedback to CMake developers.",
+ false },
+};
+static_assert(sizeof(LookupTable) / sizeof(LookupTable[0]) ==
+ static_cast<size_t>(cmExperimental::Feature::Sentinel),
+ "Experimental feature lookup table mismatch");
+
+FeatureData& DataForFeature(cmExperimental::Feature f)
+{
+ assert(f != cmExperimental::Feature::Sentinel);
+ return LookupTable[static_cast<size_t>(f)];
+}
+}
+
+bool cmExperimental::HasSupportEnabled(cmMakefile const& mf, Feature f)
+{
+ bool enabled = false;
+ auto& data = DataForFeature(f);
+
+ auto value = mf.GetDefinition(data.Variable);
+ if (value == data.Uuid) {
+ enabled = true;
+ }
+
+ if (enabled && !data.Warned) {
+ mf.IssueMessage(MessageType::AUTHOR_WARNING, data.Description);
+ data.Warned = true;
+ }
+
+ return enabled;
+}
diff --git a/Source/cmExperimental.h b/Source/cmExperimental.h
new file mode 100644
index 0000000..26e0d17
--- /dev/null
+++ b/Source/cmExperimental.h
@@ -0,0 +1,21 @@
+/* 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
+
+class cmMakefile;
+
+class cmExperimental
+{
+public:
+ enum class Feature
+ {
+ CxxModuleCMakeApi,
+
+ Sentinel,
+ };
+
+ static bool HasSupportEnabled(cmMakefile const& mf, Feature f);
+};
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 6ce0c98..ed199ea 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -9,10 +9,13 @@
#include <sstream>
#include <utility>
+#include <cm/string_view>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmExportSet.h"
#include "cmFileSet.h"
+#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
@@ -23,6 +26,7 @@
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmValue.h"
@@ -139,11 +143,18 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->GenerateTargetFileSets(gte, os);
}
+ this->GenerateCxxModuleInformation(os);
+
// Generate import file content for each configuration.
for (std::string const& c : this->Configurations) {
this->GenerateImportConfig(os, c);
}
+ // Generate import file content for each configuration.
+ for (std::string const& c : this->Configurations) {
+ this->GenerateImportCxxModuleConfigTargetInclusion(c);
+ }
+
this->GenerateMissingTargetsCheckCode(os);
return true;
@@ -382,6 +393,21 @@ std::string cmExportBuildFileGenerator::GetFileSetDirectories(
std::any_of(directoryEntries.begin(), directoryEntries.end(),
EntryIsContextSensitive);
+ auto const& type = fileSet->GetType();
+ // C++ modules do not support interface file sets which are dependent upon
+ // the configuration.
+ if (contextSensitive &&
+ (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) {
+ auto* mf = this->LG->GetMakefile();
+ std::ostringstream e;
+ e << "The \"" << gte->GetName() << "\" target's interface file set \""
+ << fileSet->GetName() << "\" of type \"" << type
+ << "\" contains context-sensitive base directory entries which is not "
+ "supported.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return std::string{};
+ }
+
for (auto const& directory : directories) {
auto dest = cmOutputConverter::EscapeForCMake(
directory, cmOutputConverter::WrapQuotes::NoWrap);
@@ -427,6 +453,21 @@ std::string cmExportBuildFileGenerator::GetFileSetFiles(cmGeneratorTarget* gte,
std::any_of(fileEntries.begin(), fileEntries.end(),
EntryIsContextSensitive);
+ auto const& type = fileSet->GetType();
+ // C++ modules do not support interface file sets which are dependent upon
+ // the configuration.
+ if (contextSensitive &&
+ (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) {
+ auto* mf = this->LG->GetMakefile();
+ std::ostringstream e;
+ e << "The \"" << gte->GetName() << "\" target's interface file set \""
+ << fileSet->GetName() << "\" of type \"" << type
+ << "\" contains context-sensitive file entries which is not "
+ "supported.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return std::string{};
+ }
+
for (auto const& it : files) {
for (auto const& filename : it.second) {
auto escapedFile = cmOutputConverter::EscapeForCMake(
@@ -447,3 +488,60 @@ std::string cmExportBuildFileGenerator::GetFileSetFiles(cmGeneratorTarget* gte,
return cmJoin(resultVector, " ");
}
+
+std::string cmExportBuildFileGenerator::GetCxxModulesDirectory() const
+{
+ return this->CxxModulesDirectory;
+}
+
+void cmExportBuildFileGenerator::GenerateCxxModuleConfigInformation(
+ std::ostream& os) const
+{
+ const char* opt = "";
+ if (this->Configurations.size() > 1) {
+ // With more than one configuration, each individual file is optional.
+ opt = " OPTIONAL";
+ }
+
+ // Generate import file content for each configuration.
+ for (std::string c : this->Configurations) {
+ if (c.empty()) {
+ c = "noconfig";
+ }
+ os << "include(\"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << c << ".cmake\""
+ << opt << ")\n";
+ }
+}
+
+bool cmExportBuildFileGenerator::GenerateImportCxxModuleConfigTargetInclusion(
+ std::string config) const
+{
+ auto cxx_modules_dirname = this->GetCxxModulesDirectory();
+ if (cxx_modules_dirname.empty()) {
+ return true;
+ }
+
+ if (config.empty()) {
+ config = "noconfig";
+ }
+
+ std::string fileName = cmStrCat(this->FileDir, '/', cxx_modules_dirname,
+ "/cxx-modules-", config, ".cmake");
+
+ cmGeneratedFileStream os(fileName, true);
+ if (!os) {
+ std::string se = cmSystemTools::GetLastSystemError();
+ std::ostringstream e;
+ e << "cannot write to file \"" << fileName << "\": " << se;
+ cmSystemTools::Error(e.str());
+ return false;
+ }
+ os.SetCopyIfDifferent(true);
+
+ for (auto const* tgt : this->ExportedTargets) {
+ os << "include(\"${CMAKE_CURRENT_LIST_DIR}/target-" << tgt->GetExportName()
+ << '-' << config << ".cmake\")\n";
+ }
+
+ return true;
+}
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 5681e8f..4636196 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -47,6 +47,16 @@ public:
}
void SetExportSet(cmExportSet*);
+ /** Set the name of the C++ module directory. */
+ void SetCxxModuleDirectory(std::string cxx_module_dir)
+ {
+ this->CxxModulesDirectory = std::move(cxx_module_dir);
+ }
+ const std::string& GetCxxModuleDirectory() const
+ {
+ return this->CxxModulesDirectory;
+ }
+
/** Set whether to append generated code to the output file. */
void SetAppendMode(bool append) { this->AppendMode = append; }
@@ -81,6 +91,10 @@ protected:
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
cmTargetExport* te) override;
+ std::string GetCxxModulesDirectory() const override;
+ void GenerateCxxModuleConfigInformation(std::ostream&) const override;
+ bool GenerateImportCxxModuleConfigTargetInclusion(std::string) const;
+
std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
cmGlobalGenerator* gg, const std::string& name);
@@ -88,4 +102,6 @@ protected:
cmExportSet* ExportSet;
std::vector<cmGeneratorTarget*> Exports;
cmLocalGenerator* LG;
+ // The directory for C++ module information.
+ std::string CxxModulesDirectory;
};
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 63440a3..a58f2b7 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -7,13 +7,15 @@
#include <utility>
#include <cm/memory>
-#include <cmext/algorithm>
+#include <cm/optional>
#include <cmext/string_view>
#include "cmsys/RegularExpression.hxx"
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
+#include "cmExperimental.h"
#include "cmExportBuildAndroidMKGenerator.h"
#include "cmExportBuildFileGenerator.h"
#include "cmExportSet.h"
@@ -57,10 +59,11 @@ bool cmExportCommand(std::vector<std::string> const& args,
struct Arguments
{
std::string ExportSetName;
- std::vector<std::string> Targets;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Targets;
std::string Namespace;
std::string Filename;
std::string AndroidMKFile;
+ std::string CxxModulesDirectory;
bool Append = false;
bool ExportOld = false;
};
@@ -69,6 +72,12 @@ bool cmExportCommand(std::vector<std::string> const& args,
.Bind("NAMESPACE"_s, &Arguments::Namespace)
.Bind("FILE"_s, &Arguments::Filename);
+ bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled(
+ status.GetMakefile(), cmExperimental::Feature::CxxModuleCMakeApi);
+ if (supportCxx20FileSetTypes) {
+ parser.Bind("CXX_MODULES_DIRECTORY"_s, &Arguments::CxxModulesDirectory);
+ }
+
if (args[0] == "EXPORT") {
parser.Bind("EXPORT"_s, &Arguments::ExportSetName);
} else {
@@ -79,9 +88,7 @@ bool cmExportCommand(std::vector<std::string> const& args,
}
std::vector<std::string> unknownArgs;
- std::vector<std::string> keywordsMissingValue;
- Arguments const arguments =
- parser.Parse(args, &unknownArgs, &keywordsMissingValue);
+ Arguments const arguments = parser.Parse(args, &unknownArgs);
if (!unknownArgs.empty()) {
status.SetError("Unknown argument: \"" + unknownArgs.front() + "\".");
@@ -145,9 +152,8 @@ bool cmExportCommand(std::vector<std::string> const& args,
return false;
}
exportSet = &it->second;
- } else if (!arguments.Targets.empty() ||
- cm::contains(keywordsMissingValue, "TARGETS")) {
- for (std::string const& currentTarget : arguments.Targets) {
+ } else if (arguments.Targets) {
+ for (std::string const& currentTarget : *arguments.Targets) {
if (mf.IsAlias(currentTarget)) {
std::ostringstream e;
e << "given ALIAS target \"" << currentTarget
@@ -214,6 +220,7 @@ bool cmExportCommand(std::vector<std::string> const& args,
}
ebfg->SetExportFile(fname.c_str());
ebfg->SetNamespace(arguments.Namespace);
+ ebfg->SetCxxModuleDirectory(arguments.CxxModulesDirectory);
ebfg->SetAppendMode(arguments.Append);
if (exportSet != nullptr) {
ebfg->SetExportSet(exportSet);
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 452eb99..23b5690 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -932,13 +932,13 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
// Isolate the file policy level.
// Support CMake versions as far back as 2.6 but also support using NEW
- // policy settings for up to CMake 3.22 (this upper limit may be reviewed
+ // policy settings for up to CMake 3.23 (this upper limit may be reviewed
// and increased from time to time). This reduces the opportunity for CMake
// warnings when an older export file is later used with newer CMake
// versions.
/* clang-format off */
os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION 2.8.3...3.22)\n";
+ << "cmake_policy(VERSION 2.8.3...3.23)\n";
/* clang-format on */
}
@@ -1088,6 +1088,10 @@ void cmExportFileGenerator::GenerateImportTargetCode(
<< " PROPERTY IMPORTED_NO_SYSTEM 1)\n";
}
+ if (target->GetPropertyAsBool("EXPORT_NO_SYSTEM")) {
+ os << "set_property(TARGET " << targetName << " PROPERTY SYSTEM 0)\n";
+ }
+
os << "\n";
}
@@ -1301,3 +1305,28 @@ void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte,
os << " )\nendif()\n\n";
}
}
+
+void cmExportFileGenerator::GenerateCxxModuleInformation(std::ostream& os)
+{
+ auto const cxx_module_dirname = this->GetCxxModulesDirectory();
+ if (cxx_module_dirname.empty()) {
+ return;
+ }
+
+ // Write the include.
+ os << "# Include C++ module properties\n"
+ << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname
+ << "/cxx-modules.cmake\")\n\n";
+
+ // Get the path to the file we're going to write.
+ std::string path = this->MainImportFile;
+ path = cmSystemTools::GetFilenamePath(path);
+ auto trampoline_path =
+ cmStrCat(path, '/', cxx_module_dirname, "/cxx-modules.cmake");
+
+ // Include all configuration-specific include files.
+ cmGeneratedFileStream ap(trampoline_path, true);
+ ap.SetCopyIfDifferent(true);
+
+ this->GenerateCxxModuleConfigInformation(ap);
+}
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index d27a555..fdda878 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -182,6 +182,8 @@ protected:
void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
cmTargetExport* te = nullptr);
+ void GenerateCxxModuleInformation(std::ostream& os);
+
virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
cmFileSet* fileSet,
cmTargetExport* te) = 0;
@@ -226,4 +228,7 @@ private:
virtual std::string InstallNameDir(cmGeneratorTarget const* target,
const std::string& config) = 0;
+
+ virtual std::string GetCxxModulesDirectory() const = 0;
+ virtual void GenerateCxxModuleConfigInformation(std::ostream& os) const = 0;
};
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
index 4e4f8a1..d53254d 100644
--- a/Source/cmExportInstallAndroidMKGenerator.cxx
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -35,8 +35,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode(
for (size_t n = 0; n < numDotDot; n++) {
path += "/..";
}
- os << "_IMPORT_PREFIX := "
- << "$(LOCAL_PATH)" << path << "\n\n";
+ os << "_IMPORT_PREFIX := $(LOCAL_PATH)" << path << "\n\n";
for (std::unique_ptr<cmTargetExport> const& te :
this->IEGen->GetExportSet()->GetTargetExports()) {
// Collect import properties for this target.
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index adccdfe..7d8572d 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -7,6 +7,9 @@
#include <sstream>
#include <utility>
+#include <cm/string_view>
+#include <cmext/string_view>
+
#include "cmExportSet.h"
#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
@@ -18,6 +21,7 @@
#include "cmInstallTargetGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
@@ -162,10 +166,20 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->LoadConfigFiles(os);
+ bool result = true;
+
+ this->GenerateCxxModuleInformation(os);
+ if (requiresConfigFiles) {
+ for (std::string const& c : this->Configurations) {
+ if (!this->GenerateImportCxxModuleConfigTargetInclusion(c)) {
+ result = false;
+ }
+ }
+ }
+
this->CleanupTemporaryVariables(os);
this->GenerateImportedFileCheckLoop(os);
- bool result = true;
// Generate an import file for each configuration.
// Don't do this if we only export INTERFACE_LIBRARY targets.
if (requiresConfigFiles) {
@@ -562,6 +576,21 @@ std::string cmExportInstallFileGenerator::GetFileSetDirectories(
cge->Evaluate(gte->LocalGenerator, config, gte),
cmOutputConverter::WrapQuotes::NoWrap));
+ auto const& type = fileSet->GetType();
+ // C++ modules do not support interface file sets which are dependent upon
+ // the configuration.
+ if (cge->GetHadContextSensitiveCondition() &&
+ (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) {
+ auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
+ std::ostringstream e;
+ e << "The \"" << gte->GetName() << "\" target's interface file set \""
+ << fileSet->GetName() << "\" of type \"" << type
+ << "\" contains context-sensitive base file entries which is not "
+ "supported.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return std::string{};
+ }
+
if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) {
resultVector.push_back(
cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\""));
@@ -610,6 +639,21 @@ std::string cmExportInstallFileGenerator::GetFileSetFiles(
std::any_of(fileEntries.begin(), fileEntries.end(),
EntryIsContextSensitive);
+ auto const& type = fileSet->GetType();
+ // C++ modules do not support interface file sets which are dependent upon
+ // the configuration.
+ if (contextSensitive &&
+ (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) {
+ auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile();
+ std::ostringstream e;
+ e << "The \"" << gte->GetName() << "\" target's interface file set \""
+ << fileSet->GetName() << "\" of type \"" << type
+ << "\" contains context-sensitive base file entries which is not "
+ "supported.";
+ mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ return std::string{};
+ }
+
for (auto const& it : files) {
auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/');
for (auto const& filename : it.second) {
@@ -635,3 +679,65 @@ std::string cmExportInstallFileGenerator::GetFileSetFiles(
return cmJoin(resultVector, " ");
}
+
+std::string cmExportInstallFileGenerator::GetCxxModulesDirectory() const
+{
+ return IEGen->GetCxxModuleDirectory();
+}
+
+void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation(
+ std::ostream& os) const
+{
+ // Now load per-configuration properties for them.
+ /* clang-format off */
+ os << "# Load information for each installed configuration.\n"
+ "file(GLOB _cmake_cxx_module_includes \"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-*.cmake\")\n"
+ "foreach(_cmake_cxx_module_include IN LISTS _cmake_cxx_module_includes)\n"
+ " include(\"${_cmake_cxx_module_include}\")\n"
+ "endforeach()\n"
+ "unset(_cmake_cxx_module_include)\n"
+ "unset(_cmake_cxx_module_includes)\n";
+ /* clang-format on */
+}
+
+bool cmExportInstallFileGenerator::
+ GenerateImportCxxModuleConfigTargetInclusion(std::string const& config)
+{
+ auto cxx_modules_dirname = this->GetCxxModulesDirectory();
+ if (cxx_modules_dirname.empty()) {
+ return true;
+ }
+
+ std::string filename_config = config;
+ if (filename_config.empty()) {
+ filename_config = "noconfig";
+ }
+
+ std::string const dest =
+ cmStrCat(this->FileDir, '/', cxx_modules_dirname, '/');
+ std::string fileName =
+ cmStrCat(dest, "cxx-modules-", filename_config, ".cmake");
+
+ cmGeneratedFileStream os(fileName, true);
+ if (!os) {
+ std::string se = cmSystemTools::GetLastSystemError();
+ std::ostringstream e;
+ e << "cannot write to file \"" << fileName << "\": " << se;
+ cmSystemTools::Error(e.str());
+ return false;
+ }
+ os.SetCopyIfDifferent(true);
+
+ // Record this per-config import file.
+ this->ConfigCxxModuleFiles[config] = fileName;
+
+ auto& prop_files = this->ConfigCxxModuleTargetFiles[config];
+ for (auto const* tgt : this->ExportedTargets) {
+ auto prop_filename = cmStrCat("target-", tgt->GetExportName(), '-',
+ filename_config, ".cmake");
+ prop_files.emplace_back(cmStrCat(dest, prop_filename));
+ os << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << prop_filename << "\")\n";
+ }
+
+ return true;
+}
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index 86fb505..e073a31 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -50,6 +50,23 @@ public:
return this->ConfigImportFiles;
}
+ /** Get the per-config C++ module file generated for each configuration.
+ This maps from the configuration name to the file temporary location
+ for installation. */
+ std::map<std::string, std::string> const& GetConfigCxxModuleFiles()
+ {
+ return this->ConfigCxxModuleFiles;
+ }
+
+ /** Get the per-config C++ module file generated for each configuration.
+ This maps from the configuration name to the file temporary location
+ for installation for each target in the export set. */
+ std::map<std::string, std::vector<std::string>> const&
+ GetConfigCxxModuleTargetFiles()
+ {
+ return this->ConfigCxxModuleTargetFiles;
+ }
+
/** Compute the globbing expression used to load per-config import
files from the main file. */
std::string GetConfigImportFileGlob();
@@ -100,8 +117,16 @@ protected:
std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet,
cmTargetExport* te) override;
+ std::string GetCxxModulesDirectory() const override;
+ void GenerateCxxModuleConfigInformation(std::ostream&) const override;
+ bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&);
+
cmInstallExportGenerator* IEGen;
// The import file generated for each configuration.
std::map<std::string, std::string> ConfigImportFiles;
+ // The C++ module property file generated for each configuration.
+ std::map<std::string, std::string> ConfigCxxModuleFiles;
+ // The C++ module property target files generated for each configuration.
+ std::map<std::string, std::vector<std::string>> ConfigCxxModuleTargetFiles;
};
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 1dd8a20..5c34fad 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -55,6 +55,9 @@ protected:
std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet,
cmTargetExport* te) override;
+ std::string GetCxxModulesDirectory() const override { return {}; }
+ void GenerateCxxModuleConfigInformation(std::ostream&) const override {}
+
private:
std::string FindTargets(const std::string& prop,
const cmGeneratorTarget* tgt,
diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx
index dd0540c..0581802 100644
--- a/Source/cmFileAPICodemodel.cxx
+++ b/Source/cmFileAPICodemodel.cxx
@@ -27,6 +27,7 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmInstallCxxModuleBmiGenerator.h"
#include "cmInstallDirectoryGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
@@ -1092,6 +1093,21 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen)
if (installFileSet->GetOptional()) {
installer["isOptional"] = true;
}
+ } else if (auto* cxxModuleBmi =
+ dynamic_cast<cmInstallCxxModuleBmiGenerator*>(gen)) {
+ installer["type"] = "cxxModuleBmi";
+ installer["destination"] = cxxModuleBmi->GetDestination(this->Config);
+
+ auto const* target = cxxModuleBmi->GetTarget();
+ installer["cxxModuleBmiTarget"] = Json::objectValue;
+ installer["cxxModuleBmiTarget"]["id"] = TargetId(target, this->TopBuild);
+ installer["cxxModuleBmiTarget"]["index"] = this->TargetIndexMap[target];
+
+ // FIXME: Parse FilePermissions.
+ // FIXME: Parse MessageLevel.
+ if (cxxModuleBmi->GetOptional()) {
+ installer["isOptional"] = true;
+ }
}
// Add fields common to all install generators.
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 7d05347..d2aa63c 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -28,8 +28,8 @@
#include "cm_sys_stat.h"
-#include "cmAlgorithms.h"
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmCMakePath.h"
#include "cmCryptoHash.h"
#include "cmELF.h"
@@ -172,7 +172,8 @@ bool HandleReadCommand(std::vector<std::string> const& args,
.Bind("LIMIT"_s, &Arguments::Limit)
.Bind("HEX"_s, &Arguments::Hex);
- Arguments const arguments = parser.Parse(cmMakeRange(args).advance(3));
+ Arguments const arguments = parser.Parse(cmMakeRange(args).advance(3),
+ /*unparsedArguments=*/nullptr);
std::string fileName = fileNameArg;
if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
@@ -958,8 +959,8 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args,
bool removeEnvironmentRPath = false;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
- std::vector<std::string> parsedArgs;
+ std::vector<cm::string_view> missingArgs;
+ std::vector<cm::string_view> parsedArgs;
parser.Bind("FILE"_s, file)
.Bind("OLD_RPATH"_s, oldRPath)
.Bind("NEW_RPATH"_s, newRPath)
@@ -1028,8 +1029,8 @@ bool HandleRPathSetCommand(std::vector<std::string> const& args,
std::string newRPath;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
- std::vector<std::string> parsedArgs;
+ std::vector<cm::string_view> missingArgs;
+ std::vector<cm::string_view> parsedArgs;
parser.Bind("FILE"_s, file).Bind("NEW_RPATH"_s, newRPath);
parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs,
&parsedArgs);
@@ -1087,7 +1088,7 @@ bool HandleRPathRemoveCommand(std::vector<std::string> const& args,
std::string file;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
+ std::vector<cm::string_view> missingArgs;
parser.Bind("FILE"_s, file);
parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs);
if (!unknownArgs.empty()) {
@@ -1138,8 +1139,8 @@ bool HandleRPathCheckCommand(std::vector<std::string> const& args,
std::string rpath;
cmArgumentParser<void> parser;
std::vector<std::string> unknownArgs;
- std::vector<std::string> missingArgs;
- std::vector<std::string> parsedArgs;
+ std::vector<cm::string_view> missingArgs;
+ std::vector<cm::string_view> parsedArgs;
parser.Bind("FILE"_s, file).Bind("RPATH"_s, rpath);
parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs,
&parsedArgs);
@@ -1197,7 +1198,8 @@ bool HandleReadElfCommand(std::vector<std::string> const& args,
.Bind("RPATH"_s, &Arguments::RPath)
.Bind("RUNPATH"_s, &Arguments::RunPath)
.Bind("CAPTURE_ERROR"_s, &Arguments::Error);
- Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2));
+ Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2),
+ /*unparsedArguments=*/nullptr);
if (!cmSystemTools::FileExists(fileNameArg, true)) {
status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg,
@@ -1252,7 +1254,7 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
struct Arguments
{
- std::string BaseDirectory;
+ cm::optional<std::string> BaseDirectory;
bool ExpandTilde = false;
};
static auto const parser =
@@ -1261,11 +1263,9 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
.Bind("EXPAND_TILDE"_s, &Arguments::ExpandTilde);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
- std::vector<std::string> parsedKeywords;
- auto arguments =
- parser.Parse(cmMakeRange(args).advance(3), &unparsedArguments,
- &keywordsMissingValue, &parsedKeywords);
+ std::vector<cm::string_view> keywordsMissingValue;
+ auto arguments = parser.Parse(cmMakeRange(args).advance(3),
+ &unparsedArguments, &keywordsMissingValue);
if (!unparsedArguments.empty()) {
status.SetError("REAL_PATH called with unexpected arguments");
@@ -1276,7 +1276,7 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
return false;
}
- if (parsedKeywords.empty()) {
+ if (!arguments.BaseDirectory) {
arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory();
}
@@ -1295,7 +1295,7 @@ bool HandleRealPathCommand(std::vector<std::string> const& args,
}
cmCMakePath path(input, cmCMakePath::auto_format);
- path = path.Absolute(arguments.BaseDirectory).Normal();
+ path = path.Absolute(*arguments.BaseDirectory).Normal();
auto realPath = cmSystemTools::GetRealPath(path.GenericString());
status.GetMakefile().AddDefinition(args[2], realPath);
@@ -2497,15 +2497,15 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
struct Arguments
{
- std::string Output;
- std::string Input;
- std::string Content;
- std::string Condition;
- std::string Target;
- std::string NewLineStyle;
+ cm::optional<std::string> Output;
+ cm::optional<std::string> Input;
+ cm::optional<std::string> Content;
+ cm::optional<std::string> Condition;
+ cm::optional<std::string> Target;
+ cm::optional<std::string> NewLineStyle;
bool NoSourcePermissions = false;
bool UseSourcePermissions = false;
- std::vector<std::string> FilePermissions;
+ ArgumentParser::NonEmpty<std::vector<std::string>> FilePermissions;
};
static auto const parser =
@@ -2521,14 +2521,16 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
.Bind("NEWLINE_STYLE"_s, &Arguments::NewLineStyle);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValues;
- std::vector<std::string> parsedKeywords;
+ std::vector<cm::string_view> keywordsMissingValues;
+ std::vector<cm::string_view> parsedKeywords;
Arguments const arguments =
parser.Parse(cmMakeRange(args).advance(1), &unparsedArguments,
&keywordsMissingValues, &parsedKeywords);
if (!keywordsMissingValues.empty()) {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
+ status.SetError(
+ cmStrCat("GENERATE keywords missing values:\n ",
+ cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
return false;
}
@@ -2537,56 +2539,41 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
return false;
}
- bool mandatoryOptionsSpecified = false;
- if (parsedKeywords.size() > 1) {
- const bool outputOprionSpecified = parsedKeywords[0] == "OUTPUT"_s;
- const bool inputOrContentSpecified =
- parsedKeywords[1] == "INPUT"_s || parsedKeywords[1] == "CONTENT"_s;
- if (outputOprionSpecified && inputOrContentSpecified) {
- mandatoryOptionsSpecified = true;
- }
+ if (!arguments.Output || parsedKeywords[0] != "OUTPUT"_s) {
+ status.SetError("GENERATE requires OUTPUT as first option.");
+ return false;
}
- if (!mandatoryOptionsSpecified) {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
+ std::string const& output = *arguments.Output;
+
+ if (!arguments.Input && !arguments.Content) {
+ status.SetError("GENERATE requires INPUT or CONTENT option.");
return false;
}
+ const bool inputIsContent = parsedKeywords[1] == "CONTENT"_s;
+ if (!inputIsContent && parsedKeywords[1] == "INPUT") {
+ status.SetError("Unknown argument to GENERATE subcommand.");
+ }
+ std::string const& input =
+ inputIsContent ? *arguments.Content : *arguments.Input;
- const bool conditionOptionSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), "CONDITION"_s) !=
- parsedKeywords.end();
- if (conditionOptionSpecified && arguments.Condition.empty()) {
+ if (arguments.Condition && arguments.Condition->empty()) {
status.SetError("CONDITION of sub-command GENERATE must not be empty "
"if specified.");
return false;
}
+ std::string const& condition =
+ arguments.Condition ? *arguments.Condition : std::string();
- const bool targetOptionSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), "TARGET"_s) !=
- parsedKeywords.end();
- if (targetOptionSpecified && arguments.Target.empty()) {
+ if (arguments.Target && arguments.Target->empty()) {
status.SetError("TARGET of sub-command GENERATE must not be empty "
"if specified.");
return false;
}
+ std::string const& target =
+ arguments.Target ? *arguments.Target : std::string();
- const bool outputOptionSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), "OUTPUT"_s) !=
- parsedKeywords.end();
- if (outputOptionSpecified && parsedKeywords[0] != "OUTPUT"_s) {
- status.SetError("Incorrect arguments to GENERATE subcommand.");
- return false;
- }
-
- const bool inputIsContent = parsedKeywords[1] != "INPUT"_s;
- if (inputIsContent && parsedKeywords[1] != "CONTENT") {
- status.SetError("Unknown argument to GENERATE subcommand.");
- }
-
- const bool newLineStyleSpecified =
- std::find(parsedKeywords.begin(), parsedKeywords.end(),
- "NEWLINE_STYLE"_s) != parsedKeywords.end();
cmNewLineStyle newLineStyle;
- if (newLineStyleSpecified) {
+ if (arguments.NewLineStyle) {
std::string errorMessage;
if (!newLineStyle.ReadFromArguments(args, errorMessage)) {
status.SetError(cmStrCat("GENERATE ", errorMessage));
@@ -2594,11 +2581,6 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
}
}
- std::string input = arguments.Input;
- if (inputIsContent) {
- input = arguments.Content;
- }
-
if (arguments.NoSourcePermissions && arguments.UseSourcePermissions) {
status.SetError("given both NO_SOURCE_PERMISSIONS and "
"USE_SOURCE_PERMISSIONS. Only one option allowed.");
@@ -2656,8 +2638,7 @@ bool HandleGenerateCommand(std::vector<std::string> const& args,
}
}
- AddEvaluationFile(input, arguments.Target, arguments.Output,
- arguments.Condition, inputIsContent,
+ AddEvaluationFile(input, target, output, condition, inputIsContent,
newLineStyle.GetCharacters(), permissions, status);
return true;
}
@@ -2836,7 +2817,11 @@ bool HandleTimestampCommand(std::vector<std::string> const& args,
unsigned int argsIndex = 1;
- const std::string& filename = args[argsIndex++];
+ std::string filename = args[argsIndex++];
+ if (!cmsys::SystemTools::FileIsFullPath(filename)) {
+ filename = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/',
+ filename);
+ }
const std::string& outputVariable = args[argsIndex++];
@@ -3067,17 +3052,18 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
std::string ConflictingDependenciesPrefix;
std::string RPathPrefix;
std::string BundleExecutable;
- std::vector<std::string> Executables;
- std::vector<std::string> Libraries;
- std::vector<std::string> Directories;
- std::vector<std::string> Modules;
- std::vector<std::string> PreIncludeRegexes;
- std::vector<std::string> PreExcludeRegexes;
- std::vector<std::string> PostIncludeRegexes;
- std::vector<std::string> PostExcludeRegexes;
- std::vector<std::string> PostIncludeFiles;
- std::vector<std::string> PostExcludeFiles;
- std::vector<std::string> PostExcludeFilesStrict;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Executables;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Libraries;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Directories;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Modules;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PreIncludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PreExcludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeFiles;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeFiles;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>>
+ PostExcludeFilesStrict;
};
static auto const parser =
@@ -3102,7 +3088,7 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
.Bind("POST_EXCLUDE_FILES_STRICT"_s, &Arguments::PostExcludeFilesStrict);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
&keywordsMissingValues);
@@ -3113,24 +3099,10 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
return false;
}
- const std::vector<std::string> LIST_ARGS = {
- "DIRECTORIES",
- "EXECUTABLES",
- "LIBRARIES",
- "MODULES",
- "POST_EXCLUDE_FILES",
- "POST_EXCLUDE_FILES_STRICT",
- "POST_EXCLUDE_REGEXES",
- "POST_INCLUDE_FILES",
- "POST_INCLUDE_REGEXES",
- "PRE_EXCLUDE_REGEXES",
- "PRE_INCLUDE_REGEXES",
- };
- auto kwbegin = keywordsMissingValues.cbegin();
- auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
- if (kwend != kwbegin) {
- status.SetError(cmStrCat("Keywords missing values:\n ",
- cmJoin(cmMakeRange(kwbegin, kwend), "\n ")));
+ if (!keywordsMissingValues.empty()) {
+ status.SetError(
+ cmStrCat("Keywords missing values:\n ",
+ cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
cmSystemTools::SetFatalErrorOccurred();
return false;
}
@@ -3234,11 +3206,12 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
{
struct Arguments
{
- std::string Output;
- std::string Content;
+ cm::optional<std::string> Output;
+ cm::optional<std::string> Content;
bool EscapeQuotes = false;
bool AtOnly = false;
- std::string NewlineStyle;
+ // "NEWLINE_STYLE" requires one value, but we use a custom check below.
+ ArgumentParser::Maybe<std::string> NewlineStyle;
};
static auto const parser =
@@ -3250,11 +3223,10 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
.Bind("NEWLINE_STYLE"_s, &Arguments::NewlineStyle);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingArguments;
- std::vector<std::string> parsedKeywords;
+ std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
- &keywordsMissingArguments, &parsedKeywords);
+ &keywordsMissingValues);
auto argIt = unrecognizedArguments.begin();
if (argIt != unrecognizedArguments.end()) {
@@ -3264,28 +3236,23 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
return false;
}
- std::vector<std::string> mandatoryOptions{ "OUTPUT", "CONTENT" };
- for (auto const& e : mandatoryOptions) {
- const bool optionHasNoValue =
- std::find(keywordsMissingArguments.begin(),
- keywordsMissingArguments.end(),
- e) != keywordsMissingArguments.end();
- if (optionHasNoValue) {
- status.SetError(cmStrCat("CONFIGURE ", e, " option needs a value."));
- cmSystemTools::SetFatalErrorOccurred();
- return false;
- }
+ if (!keywordsMissingValues.empty()) {
+ status.SetError(
+ cmStrCat("CONFIGURE keywords missing values:\n ",
+ cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
}
- for (auto const& e : mandatoryOptions) {
- const bool optionGiven =
- std::find(parsedKeywords.begin(), parsedKeywords.end(), e) !=
- parsedKeywords.end();
- if (!optionGiven) {
- status.SetError(cmStrCat("CONFIGURE ", e, " option is mandatory."));
- cmSystemTools::SetFatalErrorOccurred();
- return false;
- }
+ if (!parsedArgs.Output) {
+ status.SetError("CONFIGURE OUTPUT option is mandatory.");
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
+ }
+ if (!parsedArgs.Content) {
+ status.SetError("CONFIGURE CONTENT option is mandatory.");
+ cmSystemTools::SetFatalErrorOccurred();
+ return false;
}
std::string errorMessage;
@@ -3297,7 +3264,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
// Check for generator expressions
std::string outputFile = cmSystemTools::CollapseFullPath(
- parsedArgs.Output, status.GetMakefile().GetCurrentBinaryDirectory());
+ *parsedArgs.Output, status.GetMakefile().GetCurrentBinaryDirectory());
std::string::size_type pos = outputFile.find_first_of("<>");
if (pos != std::string::npos) {
@@ -3346,7 +3313,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args,
fout.SetCopyIfDifferent(true);
// copy input to output and expand variables from input at the same time
- std::stringstream sin(parsedArgs.Content, std::ios::in);
+ std::stringstream sin(*parsedArgs.Content, std::ios::in);
std::string inLine;
std::string outLine;
bool hasNewLine = false;
@@ -3375,9 +3342,13 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
std::string Format;
std::string Compression;
std::string CompressionLevel;
- std::string MTime;
+ // "MTIME" should require one value, but it has long been accidentally
+ // accepted without one and treated as if an empty value were given.
+ // Fixing this would require a policy.
+ ArgumentParser::Maybe<std::string> MTime;
bool Verbose = false;
- std::vector<std::string> Paths;
+ // "PATHS" requires at least one value, but use a custom check below.
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Paths;
};
static auto const parser =
@@ -3391,7 +3362,7 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
.Bind("PATHS"_s, &Arguments::Paths);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
&keywordsMissingValues);
@@ -3402,14 +3373,10 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args,
return false;
}
- const std::vector<std::string> LIST_ARGS = {
- "OUTPUT", "FORMAT", "COMPRESSION", "COMPRESSION_LEVEL", "MTIME", "PATHS"
- };
- auto kwbegin = keywordsMissingValues.cbegin();
- auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
- if (kwend != kwbegin) {
- status.SetError(cmStrCat("Keywords missing values:\n ",
- cmJoin(cmMakeRange(kwbegin, kwend), "\n ")));
+ if (!keywordsMissingValues.empty()) {
+ status.SetError(
+ cmStrCat("Keywords missing values:\n ",
+ cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
cmSystemTools::SetFatalErrorOccurred();
return false;
}
@@ -3506,7 +3473,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
bool Verbose = false;
bool ListOnly = false;
std::string Destination;
- std::vector<std::string> Patterns;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Patterns;
bool Touch = false;
};
@@ -3519,7 +3486,7 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
.Bind("TOUCH"_s, &Arguments::Touch);
std::vector<std::string> unrecognizedArguments;
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
auto parsedArgs =
parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments,
&keywordsMissingValues);
@@ -3530,13 +3497,10 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args,
return false;
}
- const std::vector<std::string> LIST_ARGS = { "INPUT", "DESTINATION",
- "PATTERNS" };
- auto kwbegin = keywordsMissingValues.cbegin();
- auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS);
- if (kwend != kwbegin) {
- status.SetError(cmStrCat("Keywords missing values:\n ",
- cmJoin(cmMakeRange(kwbegin, kwend), "\n ")));
+ if (!keywordsMissingValues.empty()) {
+ status.SetError(
+ cmStrCat("Keywords missing values:\n ",
+ cmJoin(cmMakeRange(keywordsMissingValues), "\n ")));
cmSystemTools::SetFatalErrorOccurred();
return false;
}
@@ -3630,9 +3594,9 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,
struct Arguments
{
- std::vector<std::string> Permissions;
- std::vector<std::string> FilePermissions;
- std::vector<std::string> DirectoryPermissions;
+ ArgumentParser::NonEmpty<std::vector<std::string>> Permissions;
+ ArgumentParser::NonEmpty<std::vector<std::string>> FilePermissions;
+ ArgumentParser::NonEmpty<std::vector<std::string>> DirectoryPermissions;
};
static auto const parser =
@@ -3642,7 +3606,7 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,
.Bind("DIRECTORY_PERMISSIONS"_s, &Arguments::DirectoryPermissions);
std::vector<std::string> pathEntries;
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
Arguments parsedArgs = parser.Parse(cmMakeRange(args).advance(1),
&pathEntries, &keywordsMissingValues);
@@ -3666,7 +3630,7 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse,
if (!keywordsMissingValues.empty()) {
for (const auto& i : keywordsMissingValues) {
- status.SetError(i + " is not given any arguments");
+ status.SetError(cmStrCat(i, " is not given any arguments"));
cmSystemTools::SetFatalErrorOccurred();
}
return false;
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 4dfbef9..91efc66 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -2,15 +2,20 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmFindBase.h"
+#include <algorithm>
#include <cstddef>
#include <deque>
+#include <functional>
#include <map>
#include <utility>
#include <cm/optional>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmCMakePath.h"
+#include "cmExecutionStatus.h"
+#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
@@ -24,8 +29,6 @@
#include "cmWindowsRegistry.h"
#include "cmake.h"
-class cmExecutionStatus;
-
cmFindBase::cmFindBase(std::string findCommandName, cmExecutionStatus& status)
: cmFindCommon(status)
, FindCommandName(std::move(findCommandName))
@@ -138,6 +141,31 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
cmStrCat("given invalid value for \"REGISTRY_VIEW\": ", args[j]));
return false;
}
+ } else if (args[j] == "VALIDATOR") {
+ if (++j == args.size()) {
+ this->SetError("missing required argument for \"VALIDATOR\"");
+ return false;
+ }
+ auto command = this->Makefile->GetState()->GetCommand(args[j]);
+ if (command == nullptr) {
+ this->SetError(cmStrCat(
+ "command specified for \"VALIDATOR\" is undefined: ", args[j], '.'));
+ return false;
+ }
+ // ensure a macro is not specified as validator
+ const auto& validatorName = args[j];
+ auto macros = cmExpandedList(this->Makefile->GetProperty("MACROS"));
+ if (std::find_if(macros.begin(), macros.end(),
+ [&validatorName](const std::string& item) {
+ return cmSystemTools::Strucmp(validatorName.c_str(),
+ item.c_str()) == 0;
+ }) != macros.end()) {
+ this->SetError(cmStrCat(
+ "command specified for \"VALIDATOR\" is not a function: ", args[j],
+ '.'));
+ return false;
+ }
+ this->ValidatorName = args[j];
} else if (this->CheckCommonArgument(args[j])) {
doing = DoingNone;
} else {
@@ -188,6 +216,36 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn)
return true;
}
+bool cmFindBase::Validate(const std::string& path) const
+{
+ if (this->ValidatorName.empty()) {
+ return true;
+ }
+
+ // The validator command will be executed in an isolated scope.
+ cmMakefile::ScopePushPop varScope(this->Makefile);
+ cmMakefile::PolicyPushPop polScope(this->Makefile);
+ static_cast<void>(varScope);
+ static_cast<void>(polScope);
+
+ auto resultName =
+ cmStrCat("CMAKE_"_s, cmSystemTools::UpperCase(this->FindCommandName),
+ "_VALIDATOR_STATUS"_s);
+
+ this->Makefile->AddDefinitionBool(resultName, true);
+
+ cmListFileFunction validator(
+ this->ValidatorName, 0, 0,
+ { cmListFileArgument(resultName, cmListFileArgument::Unquoted, 0),
+ cmListFileArgument(path, cmListFileArgument::Quoted, 0) });
+ cmExecutionStatus status(*this->Makefile);
+
+ if (this->Makefile->ExecuteCommand(validator, status)) {
+ return this->Makefile->GetDefinition(resultName).IsOn();
+ }
+ return false;
+}
+
void cmFindBase::ExpandPaths()
{
if (!this->NoDefaultPath) {
diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h
index d197424..75d9a6d 100644
--- a/Source/cmFindBase.h
+++ b/Source/cmFindBase.h
@@ -31,6 +31,11 @@ public:
*/
virtual bool ParseArguments(std::vector<std::string> const& args);
+ /**
+ * To check validity of a found path using user's validator, if any
+ */
+ bool Validate(const std::string& path) const;
+
protected:
friend class cmFindBaseDebugState;
void ExpandPaths();
@@ -63,6 +68,8 @@ protected:
bool Required = false;
+ std::string ValidatorName;
+
private:
// Add pieces of the search.
void FillPackageRootPath();
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index 1c4039b..6296a60 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -192,6 +192,7 @@ struct cmFindLibraryHelper
// Context information.
cmMakefile* Makefile;
+ cmFindBase const* FindBase;
cmGlobalGenerator* GG;
// List of valid prefixes and suffixes.
@@ -239,6 +240,11 @@ struct cmFindLibraryHelper
bool CheckDirectory(std::string const& path);
bool CheckDirectoryForName(std::string const& path, Name& name);
+ bool Validate(const std::string& path) const
+ {
+ return this->FindBase->Validate(path);
+ }
+
cmFindBaseDebugState DebugSearches;
void DebugLibraryFailed(std::string const& name, std::string const& path)
@@ -291,6 +297,7 @@ std::string const& get_suffixes(cmMakefile* mf)
cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf,
cmFindBase const* base)
: Makefile(mf)
+ , FindBase(base)
, DebugMode(base->DebugModeEnabled())
, DebugSearches(std::move(debugName), base)
{
@@ -416,10 +423,13 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
if (!exists) {
this->DebugLibraryFailed(name.Raw, path);
} else {
- this->DebugLibraryFound(name.Raw, path);
- this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
- cmSystemTools::ConvertToUnixSlashes(this->BestPath);
- return true;
+ auto testPath = cmSystemTools::CollapseFullPath(this->TestPath);
+ if (this->Validate(testPath)) {
+ this->DebugLibraryFound(name.Raw, path);
+ this->BestPath = testPath;
+ return true;
+ }
+ this->DebugLibraryFailed(name.Raw, path);
}
}
@@ -443,8 +453,11 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
this->TestPath = cmStrCat(path, origName);
// Make sure the path is readable and is not a directory.
if (cmSystemTools::FileExists(this->TestPath, true)) {
- this->DebugLibraryFound(name.Raw, dir);
+ if (!this->Validate(cmSystemTools::CollapseFullPath(this->TestPath))) {
+ continue;
+ }
+ this->DebugLibraryFound(name.Raw, dir);
// This is a matching file. Check if it is better than the
// best name found so far. Earlier prefixes are preferred,
// followed by earlier suffixes. For OpenBSD, shared library
@@ -541,7 +554,10 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir()
for (std::string const& n : this->Names) {
fwPath = cmStrCat(d, n, ".framework");
if (cmSystemTools::FileIsDirectory(fwPath)) {
- return cmSystemTools::CollapseFullPath(fwPath);
+ auto finalPath = cmSystemTools::CollapseFullPath(fwPath);
+ if (this->Validate(finalPath)) {
+ return finalPath;
+ }
}
}
}
@@ -558,7 +574,10 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName()
for (std::string const& d : this->SearchPaths) {
fwPath = cmStrCat(d, n, ".framework");
if (cmSystemTools::FileIsDirectory(fwPath)) {
- return cmSystemTools::CollapseFullPath(fwPath);
+ auto finalPath = cmSystemTools::CollapseFullPath(fwPath);
+ if (this->Validate(finalPath)) {
+ return finalPath;
+ }
}
}
}
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 8c6a0aa..4ad9124 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -822,13 +822,13 @@ void cmFindPackageCommand::SetVersionVariables(
char buf[64];
snprintf(buf, sizeof(buf), "%u", major);
addDefinition(prefix + "_MAJOR", buf);
- sprintf(buf, "%u", minor);
+ snprintf(buf, sizeof(buf), "%u", minor);
addDefinition(prefix + "_MINOR", buf);
- sprintf(buf, "%u", patch);
+ snprintf(buf, sizeof(buf), "%u", patch);
addDefinition(prefix + "_PATCH", buf);
- sprintf(buf, "%u", tweak);
+ snprintf(buf, sizeof(buf), "%u", tweak);
addDefinition(prefix + "_TWEAK", buf);
- sprintf(buf, "%u", count);
+ snprintf(buf, sizeof(buf), "%u", count);
addDefinition(prefix + "_COUNT", buf);
}
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index 27074ff..74a69d8 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -88,7 +88,8 @@ std::string cmFindPathCommand::FindHeaderInFramework(
if (!frameWorkName.empty()) {
std::string fpath = cmStrCat(dir, frameWorkName, ".framework");
std::string intPath = cmStrCat(fpath, "/Headers/", fileName);
- if (cmSystemTools::FileExists(intPath)) {
+ if (cmSystemTools::FileExists(intPath) &&
+ this->Validate(this->IncludeFileInPath ? intPath : fpath)) {
debug.FoundAt(intPath);
if (this->IncludeFileInPath) {
return intPath;
@@ -124,7 +125,8 @@ std::string cmFindPathCommand::FindNormalHeader(cmFindBaseDebugState& debug)
for (std::string const& n : this->Names) {
for (std::string const& sp : this->SearchPaths) {
tryPath = cmStrCat(sp, n);
- if (cmSystemTools::FileExists(tryPath)) {
+ if (cmSystemTools::FileExists(tryPath) &&
+ this->Validate(this->IncludeFileInPath ? tryPath : sp)) {
debug.FoundAt(tryPath);
if (this->IncludeFileInPath) {
return tryPath;
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index a64e0e4..8a2a69e 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -27,6 +27,7 @@ struct cmFindProgramHelper
cmFindBase const* base)
: DebugSearches(std::move(debugName), base)
, Makefile(makefile)
+ , FindBase(base)
, PolicyCMP0109(makefile->GetPolicyStatus(cmPolicies::CMP0109))
{
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
@@ -56,6 +57,7 @@ struct cmFindProgramHelper
// Debug state
cmFindBaseDebugState DebugSearches;
cmMakefile* Makefile;
+ cmFindBase const* FindBase;
cmPolicies::PolicyStatus PolicyCMP0109;
@@ -94,7 +96,7 @@ struct cmFindProgramHelper
this->TestNameExt = cmStrCat(name, ext);
this->TestPath = cmSystemTools::CollapseFullPath(
this->TestNameExt, path);
- bool exists = this->FileIsExecutable(this->TestPath);
+ bool exists = this->FileIsValid(this->TestPath);
exists ? this->DebugSearches.FoundAt(this->TestPath)
: this->DebugSearches.FailedAt(this->TestPath);
if (exists) {
@@ -104,12 +106,12 @@ struct cmFindProgramHelper
return false;
});
}
- bool FileIsExecutable(std::string const& file) const
+ bool FileIsValid(std::string const& file) const
{
-#ifdef _WIN32
if (!this->FileIsExecutableCMP0109(file)) {
return false;
}
+#ifdef _WIN32
// Pretend the Windows "python" app installer alias does not exist.
if (cmSystemTools::LowerCase(file).find("/windowsapps/python") !=
std::string::npos) {
@@ -119,10 +121,8 @@ struct cmFindProgramHelper
return false;
}
}
- return true;
-#else
- return this->FileIsExecutableCMP0109(file);
#endif
+ return this->FindBase->Validate(file);
}
bool FileIsExecutableCMP0109(std::string const& file) const
{
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 8a7215b..433c1d5 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -807,11 +807,16 @@ void handleSystemIncludesDep(cmLocalGenerator* lg,
dagChecker, depTgt, language),
result);
}
- if (!depTgt->IsImported() || excludeImported) {
+ if (!depTgt->GetPropertyAsBool("SYSTEM")) {
return;
}
- if (depTgt->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) {
- return;
+ if (depTgt->IsImported()) {
+ if (excludeImported) {
+ return;
+ }
+ if (depTgt->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) {
+ return;
+ }
}
if (cmValue dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) {
@@ -1707,7 +1712,8 @@ void addFileSetEntry(cmGeneratorTarget const* headTarget,
}
}
if (!found) {
- if (fileSet->GetType() == "HEADERS"_s) {
+ if (fileSet->GetType() == "HEADERS"_s ||
+ fileSet->GetType() == "CXX_MODULE_HEADER_UNITS"_s) {
headTarget->Makefile->GetOrCreateSourceGroup("Header Files")
->AddGroupFile(path);
}
@@ -1728,6 +1734,20 @@ void AddFileSetEntries(cmGeneratorTarget const* headTarget,
addFileSetEntry(headTarget, config, dagChecker, headerSet, entries);
}
}
+ for (auto const& entry : headTarget->Target->GetCxxModuleSetsEntries()) {
+ for (auto const& name : cmExpandedList(entry.Value)) {
+ auto const* cxxModuleSet = headTarget->Target->GetFileSet(name);
+ addFileSetEntry(headTarget, config, dagChecker, cxxModuleSet, entries);
+ }
+ }
+ for (auto const& entry :
+ headTarget->Target->GetCxxModuleHeaderSetsEntries()) {
+ for (auto const& name : cmExpandedList(entry.Value)) {
+ auto const* cxxModuleHeaderSet = headTarget->Target->GetFileSet(name);
+ addFileSetEntry(headTarget, config, dagChecker, cxxModuleHeaderSet,
+ entries);
+ }
+ }
}
bool processSources(cmGeneratorTarget const* tgt,
@@ -8700,3 +8720,76 @@ std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile(
return filename;
}
+
+bool cmGeneratorTarget::HaveCxx20ModuleSources() const
+{
+ auto const& fs_names = this->Target->GetAllFileSetNames();
+ return std::any_of(fs_names.begin(), fs_names.end(),
+ [this](std::string const& name) -> bool {
+ auto const* file_set = this->Target->GetFileSet(name);
+ if (!file_set) {
+ this->Makefile->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", this->Target->GetName(),
+ "\" is tracked to have file set \"", name,
+ "\", but it was not found."));
+ return false;
+ }
+
+ auto const& fs_type = file_set->GetType();
+ return fs_type == "CXX_MODULES"_s ||
+ fs_type == "CXX_MODULE_HEADER_UNITS"_s;
+ });
+}
+
+cmGeneratorTarget::Cxx20SupportLevel cmGeneratorTarget::HaveCxxModuleSupport(
+ std::string const& config) const
+{
+ auto const* state = this->Makefile->GetState();
+ if (!state->GetLanguageEnabled("CXX")) {
+ return Cxx20SupportLevel::MissingCxx;
+ }
+ cmStandardLevelResolver standardResolver(this->Makefile);
+ if (!standardResolver.HaveStandardAvailable(this, "CXX", config,
+ "cxx_std_20")) {
+ return Cxx20SupportLevel::NoCxx20;
+ }
+ if (!this->Makefile->IsOn("CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP")) {
+ return Cxx20SupportLevel::MissingExperimentalFlag;
+ }
+ return Cxx20SupportLevel::Supported;
+}
+
+void cmGeneratorTarget::CheckCxxModuleStatus(std::string const& config) const
+{
+ // Check for `CXX_MODULE*` file sets and a lack of support.
+ if (this->HaveCxx20ModuleSources()) {
+ switch (this->HaveCxxModuleSupport(config)) {
+ case cmGeneratorTarget::Cxx20SupportLevel::MissingCxx:
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", this->GetName(),
+ "\" target has C++ module sources but the \"CXX\" language "
+ "has not been enabled"));
+ break;
+ case cmGeneratorTarget::Cxx20SupportLevel::MissingExperimentalFlag:
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", this->GetName(),
+ "\" target has C++ module sources but its experimental "
+ "support has not been requested"));
+ break;
+ case cmGeneratorTarget::Cxx20SupportLevel::NoCxx20:
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ "The \"", this->GetName(),
+ "\" target has C++ module sources but is not using at least "
+ "\"cxx_std_20\""));
+ break;
+ case cmGeneratorTarget::Cxx20SupportLevel::Supported:
+ // All is well.
+ break;
+ }
+ }
+}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 6bce7d2..349afa7 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -1196,4 +1196,34 @@ public:
bool operator()(cmGeneratorTarget const* t1,
cmGeneratorTarget const* t2) const;
};
+
+ // C++20 module support queries.
+
+ /**
+ * Query whether the target expects C++20 module support.
+ *
+ * This will inspect the target itself to see if C++20 module
+ * support is expected to work based on its sources.
+ */
+ bool HaveCxx20ModuleSources() const;
+
+ enum class Cxx20SupportLevel
+ {
+ // C++ is not available.
+ MissingCxx,
+ // The experimental feature is not available.
+ MissingExperimentalFlag,
+ // The target does not require at least C++20.
+ NoCxx20,
+ // C++20 modules are available and working.
+ Supported,
+ };
+ /**
+ * Query whether the target has C++20 module support available (regardless of
+ * whether it is required or not).
+ */
+ Cxx20SupportLevel HaveCxxModuleSupport(std::string const& config) const;
+
+ // Check C++ module status for the target.
+ void CheckCxxModuleStatus(std::string const& config) const;
};
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index acaed36..b4d5746 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -5,6 +5,7 @@
#include <algorithm>
#include <cctype>
#include <cstdio>
+#include <functional>
#include <sstream>
#include <utility>
@@ -14,6 +15,7 @@
#include <cm/string_view>
#include <cmext/algorithm>
#include <cmext/memory>
+#include <cmext/string_view>
#include <cm3p/json/reader.h>
#include <cm3p/json/value.h>
@@ -21,7 +23,9 @@
#include "cmsys/FStream.hxx"
+#include "cmCxxModuleMapper.h"
#include "cmDocumentationEntry.h"
+#include "cmFileSet.h"
#include "cmFortranParser.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpressionEvaluationFile.h"
@@ -2480,13 +2484,53 @@ cm::optional<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
}
}
+struct CxxModuleFileSet
+{
+ std::string Name;
+ std::string RelativeDirectory;
+ std::string SourcePath;
+ std::string Type;
+ cmFileSetVisibility Visibility;
+ cm::optional<std::string> Destination;
+};
+
+struct CxxModuleBmiInstall
+{
+ std::string Component;
+ std::string Destination;
+ bool ExcludeFromAll;
+ bool Optional;
+ std::string Permissions;
+ std::string MessageLevel;
+ std::string ScriptLocation;
+};
+
+struct CxxModuleExport
+{
+ std::string Name;
+ std::string Destination;
+ std::string Prefix;
+ std::string CxxModuleInfoDir;
+ std::string Namespace;
+ bool Install;
+};
+
+struct cmGlobalNinjaGenerator::CxxModuleExportInfo
+{
+ std::map<std::string, CxxModuleFileSet> ObjectToFileSet;
+ cm::optional<CxxModuleBmiInstall> BmiInstallation;
+ std::vector<CxxModuleExport> Exports;
+ std::string Config;
+};
+
bool cmGlobalNinjaGenerator::WriteDyndepFile(
std::string const& dir_top_src, std::string const& dir_top_bld,
std::string const& dir_cur_src, std::string const& dir_cur_bld,
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
std::string const& module_dir,
std::vector<std::string> const& linked_target_dirs,
- std::string const& arg_lang, std::string const& arg_modmapfmt)
+ std::string const& arg_lang, std::string const& arg_modmapfmt,
+ CxxModuleExportInfo const& export_info)
{
// Setup path conversions.
{
@@ -2517,7 +2561,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
// Populate the module map with those provided by linked targets first.
for (std::string const& linked_target_dir : linked_target_dirs) {
std::string const ltmn =
- cmStrCat(linked_target_dir, "/", arg_lang, "Modules.json");
+ cmStrCat(linked_target_dir, '/', arg_lang, "Modules.json");
Json::Value ltm;
cmsys::ifstream ltmf(ltmn.c_str(), std::ios::in | std::ios::binary);
Json::Reader reader;
@@ -2534,11 +2578,20 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
}
}
- const char* module_ext = "";
- if (arg_modmapfmt == "gcc") {
- module_ext = ".gcm";
+ cm::optional<CxxModuleMapFormat> modmap_fmt;
+ if (arg_modmapfmt.empty()) {
+ // nothing to do.
+ } else if (arg_modmapfmt == "gcc") {
+ modmap_fmt = CxxModuleMapFormat::Gcc;
+ } else {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep does not understand the ", arg_modmapfmt,
+ " module map format"));
+ return false;
}
+ auto module_ext = CxxModuleMapExtension(modmap_fmt);
+
// Extend the module map with those provided by this target.
// We do this after loading the modules provided by linked targets
// in case we have one of the same name that must be preferred.
@@ -2555,7 +2608,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
}
} else {
// Assume the module file path matches the logical module name.
- std::string safe_logical_name = p.LogicalName;
+ std::string safe_logical_name =
+ p.LogicalName; // TODO: needs fixing for header units
cmSystemTools::ReplaceString(safe_logical_name, ":", "-");
mod = cmStrCat(module_dir, safe_logical_name, module_ext);
}
@@ -2568,6 +2622,20 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
ddf << "ninja_dyndep_version = 1.0\n";
{
+ CxxModuleLocations locs;
+ locs.RootDirectory = ".";
+ locs.PathForGenerator = [this](std::string const& path) -> std::string {
+ return this->ConvertToNinjaPath(path);
+ };
+ locs.BmiLocationForModule =
+ [&mod_files](std::string const& logical) -> cm::optional<std::string> {
+ auto m = mod_files.find(logical);
+ if (m != mod_files.end()) {
+ return m->second;
+ }
+ return {};
+ };
+
cmNinjaBuild build("dyndep");
build.Outputs.emplace_back("");
for (cmScanDepInfo const& object : objects) {
@@ -2589,46 +2657,14 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
build.Variables.emplace("restat", "1");
}
- if (arg_modmapfmt.empty()) {
- // nothing to do.
- } else {
- std::stringstream mm;
- if (arg_modmapfmt == "gcc") {
- // Documented in GCC's documentation. The format is a series of lines
- // with a module name and the associated filename separated by
- // spaces. The first line may use `$root` as the module name to
- // specify a "repository root". That is used to anchor any relative
- // paths present in the file (CMake should never generate any).
-
- // Write the root directory to use for module paths.
- mm << "$root .\n";
-
- for (auto const& l : object.Provides) {
- auto m = mod_files.find(l.LogicalName);
- if (m != mod_files.end()) {
- mm << l.LogicalName << " " << this->ConvertToNinjaPath(m->second)
- << "\n";
- }
- }
- for (auto const& r : object.Requires) {
- auto m = mod_files.find(r.LogicalName);
- if (m != mod_files.end()) {
- mm << r.LogicalName << " " << this->ConvertToNinjaPath(m->second)
- << "\n";
- }
- }
- } else {
- cmSystemTools::Error(
- cmStrCat("-E cmake_ninja_dyndep does not understand the ",
- arg_modmapfmt, " module map format"));
- return false;
- }
+ if (modmap_fmt) {
+ auto mm = CxxModuleMapContent(*modmap_fmt, locs, object);
// XXX(modmap): If changing this path construction, change
// `cmNinjaTargetGenerator::WriteObjectBuildStatements` to generate the
// corresponding file path.
cmGeneratedFileStream mmf(cmStrCat(object.PrimaryOutput, ".modmap"));
- mmf << mm.str();
+ mmf << mm;
}
this->WriteBuild(ddf, build);
@@ -2642,7 +2678,279 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
cmGeneratedFileStream tmf(target_mods_file);
tmf << tm;
- return true;
+ bool result = true;
+
+ // Fortran doesn't support any of the file-set or BMI installation considered
+ // below.
+ if (arg_lang != "Fortran"_s) {
+ // Prepare the export information blocks.
+ std::string const config_upper =
+ cmSystemTools::UpperCase(export_info.Config);
+ std::vector<std::pair<std::unique_ptr<cmGeneratedFileStream>,
+ CxxModuleExport const*>>
+ exports;
+ for (auto const& exp : export_info.Exports) {
+ std::unique_ptr<cmGeneratedFileStream> properties;
+
+ std::string const export_dir =
+ cmStrCat(exp.Prefix, '/', exp.CxxModuleInfoDir, '/');
+ std::string const property_file_path = cmStrCat(
+ export_dir, "target-", exp.Name, '-', export_info.Config, ".cmake");
+ properties = cm::make_unique<cmGeneratedFileStream>(property_file_path);
+
+ // Set up the preamble.
+ *properties << "set_property(TARGET \"" << exp.Namespace << exp.Name
+ << "\"\n"
+ << " PROPERTY IMPORTED_CXX_MODULES_" << config_upper
+ << '\n';
+
+ exports.emplace_back(std::move(properties), &exp);
+ }
+
+ std::unique_ptr<cmGeneratedFileStream> bmi_install_script;
+ if (export_info.BmiInstallation) {
+ bmi_install_script = cm::make_unique<cmGeneratedFileStream>(
+ export_info.BmiInstallation->ScriptLocation);
+ }
+
+ auto cmEscape = [](cm::string_view str) {
+ return cmOutputConverter::EscapeForCMake(
+ str, cmOutputConverter::WrapQuotes::NoWrap);
+ };
+ auto install_destination =
+ [&cmEscape](std::string const& dest) -> std::pair<bool, std::string> {
+ if (cmSystemTools::FileIsFullPath(dest)) {
+ return std::make_pair(true, cmEscape(dest));
+ }
+ return std::make_pair(false,
+ cmStrCat("${_IMPORT_PREFIX}/", cmEscape(dest)));
+ };
+
+ // public/private requirement tracking.
+ std::set<std::string> private_modules;
+ std::map<std::string, std::set<std::string>> public_source_requires;
+
+ for (cmScanDepInfo const& object : objects) {
+ // Convert to forward slashes.
+ auto output_path = object.PrimaryOutput;
+# ifdef _WIN32
+ cmSystemTools::ConvertToUnixSlashes(output_path);
+# endif
+ // Find the fileset for this object.
+ auto fileset_info_itr = export_info.ObjectToFileSet.find(output_path);
+ bool const has_provides = !object.Provides.empty();
+ if (fileset_info_itr == export_info.ObjectToFileSet.end()) {
+ // If it provides anything, it should have a `CXX_MODULES` or
+ // `CXX_MODULE_INTERNAL_PARTITIONS` type and be present.
+ if (has_provides) {
+ // Take the first module provided to provide context.
+ auto const& provides = object.Provides[0];
+ char const* ok_types = "`CXX_MODULES`";
+ if (provides.LogicalName.find(':') != std::string::npos) {
+ ok_types = "`CXX_MODULES` (or `CXX_MODULE_INTERNAL_PARTITIONS` if "
+ "it is not `export`ed)";
+ }
+ cmSystemTools::Error(
+ cmStrCat("Output ", object.PrimaryOutput, " provides the `",
+ provides.LogicalName,
+ "` module but it is not found in a `FILE_SET` of type ",
+ ok_types));
+ result = false;
+ }
+
+ // This object file does not provide anything, so nothing more needs to
+ // be done.
+ continue;
+ }
+
+ auto const& file_set = fileset_info_itr->second;
+
+ // Verify the fileset type for the object.
+ if (file_set.Type == "CXX_MODULES"_s) {
+ if (!has_provides) {
+ cmSystemTools::Error(cmStrCat(
+ "Output ", object.PrimaryOutput,
+ " is of type `CXX_MODULES` but does not provide a module"));
+ result = false;
+ continue;
+ }
+ } else if (file_set.Type == "CXX_MODULE_INTERNAL_PARTITIONS"_s) {
+ if (!has_provides) {
+ cmSystemTools::Error(cmStrCat(
+ "Source ", file_set.SourcePath,
+ " is of type `CXX_MODULE_INTERNAL_PARTITIONS` but does not "
+ "provide a module"));
+ result = false;
+ continue;
+ }
+ auto const& provides = object.Provides[0];
+ if (provides.LogicalName.find(':') == std::string::npos) {
+ cmSystemTools::Error(cmStrCat(
+ "Source ", file_set.SourcePath,
+ " is of type `CXX_MODULE_INTERNAL_PARTITIONS` but does not "
+ "provide a module partition"));
+ result = false;
+ continue;
+ }
+ } else if (file_set.Type == "CXX_MODULE_HEADERS"_s) {
+ // TODO.
+ } else {
+ if (has_provides) {
+ auto const& provides = object.Provides[0];
+ char const* ok_types = "`CXX_MODULES`";
+ if (provides.LogicalName.find(':') != std::string::npos) {
+ ok_types = "`CXX_MODULES` (or `CXX_MODULE_INTERNAL_PARTITIONS` if "
+ "it is not `export`ed)";
+ }
+ cmSystemTools::Error(cmStrCat(
+ "Source ", file_set.SourcePath, " provides the `",
+ provides.LogicalName, "` C++ module but is of type `",
+ file_set.Type, "` module but must be of type ", ok_types));
+ result = false;
+ }
+
+ // Not a C++ module; ignore.
+ continue;
+ }
+
+ if (!cmFileSetVisibilityIsForInterface(file_set.Visibility)) {
+ // Nothing needs to be conveyed about non-`PUBLIC` modules.
+ for (auto const& p : object.Provides) {
+ private_modules.insert(p.LogicalName);
+ }
+ continue;
+ }
+
+ // The module is public. Record what it directly requires.
+ {
+ auto& reqs = public_source_requires[file_set.SourcePath];
+ for (auto const& r : object.Requires) {
+ reqs.insert(r.LogicalName);
+ }
+ }
+
+ // Write out properties and install rules for any exports.
+ for (auto const& p : object.Provides) {
+ bool bmi_dest_is_abs = false;
+ std::string bmi_destination;
+ if (export_info.BmiInstallation) {
+ auto dest =
+ install_destination(export_info.BmiInstallation->Destination);
+ bmi_dest_is_abs = dest.first;
+ bmi_destination = cmStrCat(dest.second, '/');
+ }
+
+ std::string install_bmi_path;
+ std::string build_bmi_path;
+ auto m = mod_files.find(p.LogicalName);
+ if (m != mod_files.end()) {
+ install_bmi_path =
+ cmStrCat(bmi_destination,
+ cmEscape(cmSystemTools::GetFilenameName(m->second)));
+ build_bmi_path = cmEscape(m->second);
+ }
+
+ for (auto const& exp : exports) {
+ std::string iface_source;
+ if (exp.second->Install && file_set.Destination) {
+ auto dest = install_destination(*file_set.Destination);
+ iface_source = cmStrCat(
+ dest.second, '/', cmEscape(file_set.RelativeDirectory),
+ cmEscape(cmSystemTools::GetFilenameName(file_set.SourcePath)));
+ } else {
+ iface_source = cmEscape(file_set.SourcePath);
+ }
+
+ std::string bmi_path;
+ if (exp.second->Install && export_info.BmiInstallation) {
+ bmi_path = install_bmi_path;
+ } else if (!exp.second->Install) {
+ bmi_path = build_bmi_path;
+ }
+
+ if (iface_source.empty()) {
+ // No destination for the C++ module source; ignore this property
+ // value.
+ continue;
+ }
+
+ *exp.first << " \"" << cmEscape(p.LogicalName) << '='
+ << iface_source;
+ if (!bmi_path.empty()) {
+ *exp.first << ',' << bmi_path;
+ }
+ *exp.first << "\"\n";
+ }
+
+ if (bmi_install_script) {
+ auto const& bmi_install = *export_info.BmiInstallation;
+
+ *bmi_install_script << "if (CMAKE_INSTALL_COMPONENT STREQUAL \""
+ << cmEscape(bmi_install.Component) << '\"';
+ if (!bmi_install.ExcludeFromAll) {
+ *bmi_install_script << " OR NOT CMAKE_INSTALL_COMPONENT";
+ }
+ *bmi_install_script << ")\n";
+ *bmi_install_script << " file(INSTALL\n"
+ " DESTINATION \"";
+ if (!bmi_dest_is_abs) {
+ *bmi_install_script << "${CMAKE_INSTALL_PREFIX}/";
+ }
+ *bmi_install_script << cmEscape(bmi_install.Destination)
+ << "\"\n"
+ " TYPE FILE\n";
+ if (bmi_install.Optional) {
+ *bmi_install_script << " OPTIONAL\n";
+ }
+ if (!bmi_install.MessageLevel.empty()) {
+ *bmi_install_script << " " << bmi_install.MessageLevel << "\n";
+ }
+ if (!bmi_install.Permissions.empty()) {
+ *bmi_install_script << " PERMISSIONS" << bmi_install.Permissions
+ << "\n";
+ }
+ *bmi_install_script << " FILES \"" << m->second << "\")\n";
+ if (bmi_dest_is_abs) {
+ *bmi_install_script
+ << " list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n"
+ " \""
+ << cmEscape(cmSystemTools::GetFilenameName(m->second))
+ << "\")\n"
+ " if (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n"
+ " message(WARNING\n"
+ " \"ABSOLUTE path INSTALL DESTINATION : "
+ "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"
+ " endif ()\n"
+ " if (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n"
+ " message(FATAL_ERROR\n"
+ " \"ABSOLUTE path INSTALL DESTINATION forbidden (by "
+ "caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n"
+ " endif ()\n";
+ }
+ *bmi_install_script << "endif ()\n";
+ }
+ }
+ }
+
+ // Add trailing parenthesis for the `set_property` call.
+ for (auto const& exp : exports) {
+ *exp.first << ")\n";
+ }
+
+ // Check that public sources only require public modules.
+ for (auto const& pub_reqs : public_source_requires) {
+ for (auto const& req : pub_reqs.second) {
+ if (private_modules.count(req)) {
+ cmSystemTools::Error(cmStrCat(
+ "Public C++ module source `", pub_reqs.first, "` requires the `",
+ req, "` C++ module which is provided by a private source"));
+ result = false;
+ }
+ }
+ }
+ }
+
+ return result;
}
int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
@@ -2716,6 +3024,59 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
}
}
+ cmGlobalNinjaGenerator::CxxModuleExportInfo export_info;
+ export_info.Config = tdi["config"].asString();
+ if (export_info.Config.empty()) {
+ export_info.Config = "noconfig";
+ }
+ Json::Value const& tdi_exports = tdi["exports"];
+ if (tdi_exports.isArray()) {
+ for (auto const& tdi_export : tdi_exports) {
+ CxxModuleExport exp;
+ exp.Install = tdi_export["install"].asBool();
+ exp.Name = tdi_export["export-name"].asString();
+ exp.Destination = tdi_export["destination"].asString();
+ exp.Prefix = tdi_export["export-prefix"].asString();
+ exp.CxxModuleInfoDir = tdi_export["cxx-module-info-dir"].asString();
+ exp.Namespace = tdi_export["namespace"].asString();
+
+ export_info.Exports.push_back(exp);
+ }
+ }
+ auto const& bmi_installation = tdi["bmi-installation"];
+ if (bmi_installation.isObject()) {
+ CxxModuleBmiInstall bmi_install;
+
+ bmi_install.Component = bmi_installation["component"].asString();
+ bmi_install.Destination = bmi_installation["destination"].asString();
+ bmi_install.ExcludeFromAll = bmi_installation["exclude-from-all"].asBool();
+ bmi_install.Optional = bmi_installation["optional"].asBool();
+ bmi_install.Permissions = bmi_installation["permissions"].asString();
+ bmi_install.MessageLevel = bmi_installation["message-level"].asString();
+ bmi_install.ScriptLocation =
+ bmi_installation["script-location"].asString();
+
+ export_info.BmiInstallation = bmi_install;
+ }
+ Json::Value const& tdi_cxx_modules = tdi["cxx-modules"];
+ if (tdi_cxx_modules.isObject()) {
+ for (auto i = tdi_cxx_modules.begin(); i != tdi_cxx_modules.end(); ++i) {
+ CxxModuleFileSet& fsi = export_info.ObjectToFileSet[i.key().asString()];
+ auto const& tdi_cxx_module_info = *i;
+ fsi.Name = tdi_cxx_module_info["name"].asString();
+ fsi.RelativeDirectory =
+ tdi_cxx_module_info["relative-directory"].asString();
+ fsi.SourcePath = tdi_cxx_module_info["source"].asString();
+ fsi.Type = tdi_cxx_module_info["type"].asString();
+ fsi.Visibility = cmFileSetVisibilityFromName(
+ tdi_cxx_module_info["visibility"].asString(), nullptr);
+ auto const& tdi_fs_dest = tdi_cxx_module_info["destination"];
+ if (tdi_fs_dest.isString()) {
+ fsi.Destination = tdi_fs_dest.asString();
+ }
+ }
+ }
+
cmake cm(cmake::RoleInternal, cmState::Unknown);
cm.SetHomeDirectory(dir_top_src);
cm.SetHomeOutputDirectory(dir_top_bld);
@@ -2723,7 +3084,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
if (!ggd ||
!cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd).WriteDyndepFile(
dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis,
- module_dir, linked_target_dirs, arg_lang, arg_modmapfmt)) {
+ module_dir, linked_target_dirs, arg_lang, arg_modmapfmt,
+ export_info)) {
return 1;
}
return 0;
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index aa2df4d..dc4f444 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -417,13 +417,15 @@ public:
bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }
void StripNinjaOutputPathPrefixAsSuffix(std::string& path);
+ struct CxxModuleExportInfo;
bool WriteDyndepFile(
std::string const& dir_top_src, std::string const& dir_top_bld,
std::string const& dir_cur_src, std::string const& dir_cur_bld,
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
std::string const& module_dir,
std::vector<std::string> const& linked_target_dirs,
- std::string const& arg_lang, std::string const& arg_modmapfmt);
+ std::string const& arg_lang, std::string const& arg_modmapfmt,
+ CxxModuleExportInfo const& export_info);
virtual std::string BuildAlias(const std::string& alias,
const std::string& /*config*/) const
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index f7f7317..e53ae8e 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -395,12 +395,27 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
{
VisualStudioFolders.clear();
+ std::vector<std::string> configs =
+ root->GetMakefile()->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig);
+
for (cmGeneratorTarget const* target : projectTargets) {
if (!this->IsInSolution(target)) {
continue;
}
bool written = false;
+ for (auto const& c : configs) {
+ target->CheckCxxModuleStatus(c);
+ }
+
+ if (target->HaveCxx20ModuleSources() && !this->SupportsCxxModuleDyndep()) {
+ root->GetMakefile()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", target->GetName(),
+ "\" target contains C++ module sources which are not "
+ "supported by the generator"));
+ }
+
// handle external vc project files
cmValue expath = target->GetProperty("EXTERNAL_MSPROJECT");
if (expath) {
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index a55cf45..288069c 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -157,6 +157,8 @@ protected:
cmValue typeGuid,
const std::set<BT<std::pair<std::string, bool>>>& dependencies) = 0;
+ virtual bool SupportsCxxModuleDyndep() const { return false; }
+
std::string ConvertToSolutionPath(const std::string& path);
std::set<std::string> IsPartOfDefaultBuild(
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index d5783ef..456f5bc 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -468,6 +468,10 @@ bool cmGlobalXCodeGenerator::Open(const std::string& bindir,
}
CFRelease(cfStr);
}
+#else
+ (void)bindir;
+ (void)projectName;
+ (void)dryRun;
#endif
return ret;
@@ -1372,6 +1376,18 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget(
return true;
}
+ for (std::string const& configName : this->CurrentConfigurationTypes) {
+ gtgt->CheckCxxModuleStatus(configName);
+ }
+
+ if (gtgt->HaveCxx20ModuleSources()) {
+ gtgt->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", gtgt->GetName(),
+ "\" target contains C++ module sources which are not "
+ "supported by the generator"));
+ }
+
auto& gtgt_visited = this->CommandsVisited[gtgt];
auto& deps = this->GetTargetDirectDepends(gtgt);
for (auto& d : deps) {
@@ -2407,6 +2423,18 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
this->AppendDefines(ppDefs, targetDefines);
buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS",
ppDefs.CreateList());
+ if (languages.count("Swift")) {
+ if (this->XcodeVersion < 80) {
+ std::string defineString;
+ std::set<std::string> defines(targetDefines.begin(),
+ targetDefines.end());
+ this->CurrentLocalGenerator->JoinDefines(defines, defineString, "Swift");
+ cflags["Swift"] += " " + defineString;
+ } else {
+ buildSettings->AddAttribute("SWIFT_ACTIVE_COMPILATION_CONDITIONS",
+ ppDefs.CreateList());
+ }
+ }
std::string extraLinkOptionsVar;
std::string extraLinkOptions;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 7ca5b23..b1044a8 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -12,18 +12,22 @@
#include <utility>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
#include "cmsys/Glob.hxx"
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
+#include "cmExperimental.h"
#include "cmExportSet.h"
#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmInstallCommandArguments.h"
+#include "cmInstallCxxModuleBmiGenerator.h"
#include "cmInstallDirectoryGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallFileSetGenerator.h"
@@ -54,13 +58,13 @@ namespace {
struct RuntimeDependenciesArgs
{
- std::vector<std::string> Directories;
- std::vector<std::string> PreIncludeRegexes;
- std::vector<std::string> PreExcludeRegexes;
- std::vector<std::string> PostIncludeRegexes;
- std::vector<std::string> PostExcludeRegexes;
- std::vector<std::string> PostIncludeFiles;
- std::vector<std::string> PostExcludeFiles;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Directories;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PreIncludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PreExcludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeRegexes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeFiles;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeFiles;
};
auto const RuntimeDependenciesArgHelper =
@@ -109,6 +113,8 @@ public:
const cmInstallCommandArguments* args) const;
std::string GetLibraryDestination(
const cmInstallCommandArguments* args) const;
+ std::string GetCxxModulesBmiDestination(
+ const cmInstallCommandArguments* args) const;
std::string GetIncludeDestination(
const cmInstallCommandArguments* args) const;
std::string GetSysconfDestination(
@@ -401,16 +407,17 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
struct ArgVectors
{
- std::vector<std::string> Archive;
- std::vector<std::string> Library;
- std::vector<std::string> Runtime;
- std::vector<std::string> Object;
- std::vector<std::string> Framework;
- std::vector<std::string> Bundle;
- std::vector<std::string> Includes;
- std::vector<std::string> PrivateHeader;
- std::vector<std::string> PublicHeader;
- std::vector<std::string> Resource;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Archive;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Library;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Runtime;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Object;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Framework;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Bundle;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Includes;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PrivateHeader;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> PublicHeader;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Resource;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> CxxModulesBmi;
std::vector<std::vector<std::string>> FileSets;
};
@@ -426,7 +433,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
.Bind("PRIVATE_HEADER"_s, &ArgVectors::PrivateHeader)
.Bind("PUBLIC_HEADER"_s, &ArgVectors::PublicHeader)
.Bind("RESOURCE"_s, &ArgVectors::Resource)
- .Bind("FILE_SET"_s, &ArgVectors::FileSets);
+ .Bind("FILE_SET"_s, &ArgVectors::FileSets)
+ .Bind("CXX_MODULES_BMI"_s, &ArgVectors::CxxModulesBmi);
std::vector<std::string> genericArgVector;
ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector);
@@ -434,26 +442,25 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// now parse the generic args (i.e. the ones not specialized on LIBRARY/
// ARCHIVE, RUNTIME etc. (see above)
// These generic args also contain the targets and the export stuff
- std::vector<std::string> targetList;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> targetList;
std::string exports;
- std::vector<std::string> runtimeDependenciesArgVector;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>>
+ runtimeDependenciesArgVector;
std::string runtimeDependencySetArg;
std::vector<std::string> unknownArgs;
- std::vector<std::string> parsedArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
genericArgs.Bind("TARGETS"_s, targetList);
genericArgs.Bind("EXPORT"_s, exports);
genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector);
genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
- genericArgs.Parse(genericArgVector, &unknownArgs, nullptr, &parsedArgs);
+ genericArgs.Parse(genericArgVector, &unknownArgs);
bool success = genericArgs.Finalize();
- bool withRuntimeDependencies =
- std::find(parsedArgs.begin(), parsedArgs.end(), "RUNTIME_DEPENDENCIES") !=
- parsedArgs.end();
RuntimeDependenciesArgs runtimeDependenciesArgs =
- RuntimeDependenciesArgHelper.Parse(runtimeDependenciesArgVector,
- &unknownArgs);
+ runtimeDependenciesArgVector
+ ? RuntimeDependenciesArgHelper.Parse(*runtimeDependenciesArgVector,
+ &unknownArgs)
+ : RuntimeDependenciesArgs();
cmInstallCommandArguments archiveArgs(helper.DefaultComponentName);
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
@@ -467,6 +474,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
cmInstallCommandIncludesArgument includesArgs;
std::vector<cmInstallCommandFileSetArguments> fileSetArgs(
argVectors.FileSets.size(), { helper.DefaultComponentName });
+ cmInstallCommandArguments cxxModuleBmiArgs(helper.DefaultComponentName);
// now parse the args for specific parts of the target (e.g. LIBRARY,
// RUNTIME, ARCHIVE etc.
@@ -490,6 +498,15 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
fileSetArgs[i] = std::move(fileSetArg);
}
+ bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled(
+ *helper.Makefile, cmExperimental::Feature::CxxModuleCMakeApi);
+ if (!supportCxx20FileSetTypes) {
+ std::copy(argVectors.CxxModulesBmi.begin(), argVectors.CxxModulesBmi.end(),
+ std::back_inserter(unknownArgs));
+ } else {
+ cxxModuleBmiArgs.Parse(argVectors.CxxModulesBmi, &unknownArgs);
+ }
+
if (!unknownArgs.empty()) {
// Unknown argument.
status.SetError(
@@ -510,6 +527,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
for (auto& fileSetArg : fileSetArgs) {
fileSetArg.SetGenericArguments(&genericArgs);
}
+ cxxModuleBmiArgs.SetGenericArguments(&genericArgs);
success = success && archiveArgs.Finalize();
success = success && libraryArgs.Finalize();
@@ -523,6 +541,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
for (auto& fileSetArg : fileSetArgs) {
success = success && fileSetArg.Finalize();
}
+ if (supportCxx20FileSetTypes) {
+ success = success && cxxModuleBmiArgs.Finalize();
+ }
if (!success) {
return false;
@@ -536,7 +557,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly() ||
std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
[](const cmInstallCommandFileSetArguments& fileSetArg)
- -> bool { return fileSetArg.GetNamelinkOnly(); })) {
+ -> bool { return fileSetArg.GetNamelinkOnly(); }) ||
+ cxxModuleBmiArgs.GetNamelinkOnly()) {
status.SetError(
"TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
"The NAMELINK_ONLY option may be specified only following LIBRARY.");
@@ -548,7 +570,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip() ||
std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
[](const cmInstallCommandFileSetArguments& fileSetArg)
- -> bool { return fileSetArg.GetNamelinkSkip(); })) {
+ -> bool { return fileSetArg.GetNamelinkSkip(); }) ||
+ cxxModuleBmiArgs.GetNamelinkSkip()) {
status.SetError(
"TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
"The NAMELINK_SKIP option may be specified only following LIBRARY.");
@@ -564,7 +587,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
resourceArgs.HasNamelinkComponent() ||
std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
[](const cmInstallCommandFileSetArguments& fileSetArg)
- -> bool { return fileSetArg.HasNamelinkComponent(); })) {
+ -> bool { return fileSetArg.HasNamelinkComponent(); }) ||
+ cxxModuleBmiArgs.HasNamelinkComponent()) {
status.SetError(
"TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. "
"The NAMELINK_COMPONENT option may be specified only following "
@@ -583,7 +607,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
!publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty() ||
std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
[](const cmInstallCommandFileSetArguments& fileSetArg)
- -> bool { return !fileSetArg.GetType().empty(); })) {
+ -> bool { return !fileSetArg.GetType().empty(); }) ||
+ !cxxModuleBmiArgs.GetType().empty()) {
status.SetError(
"TARGETS given TYPE option. The TYPE option may only be specified in "
" install(FILES) and install(DIRECTORIES).");
@@ -597,7 +622,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
- if (withRuntimeDependencies) {
+ if (runtimeDependenciesArgVector) {
if (!runtimeDependencySetArg.empty()) {
status.SetError("TARGETS cannot have both RUNTIME_DEPENDENCIES and "
"RUNTIME_DEPENDENCY_SET.");
@@ -706,6 +731,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
bool installsPublicHeader = false;
bool installsResource = false;
std::vector<bool> installsFileSet(fileSetArgs.size(), false);
+ bool installsCxxModuleBmi = false;
// Generate install script code to install the given targets.
for (cmTarget* ti : targets) {
@@ -722,6 +748,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
std::unique_ptr<cmInstallFilesGenerator> publicHeaderGenerator;
std::unique_ptr<cmInstallFilesGenerator> resourceGenerator;
std::vector<std::unique_ptr<cmInstallFileSetGenerator>> fileSetGenerators;
+ std::unique_ptr<cmInstallCxxModuleBmiGenerator> cxxModuleBmiGenerator;
// Avoid selecting default destinations for PUBLIC_HEADER and
// PRIVATE_HEADER if any artifacts are specified.
@@ -760,6 +787,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
for (auto const& gen : fileSetGenerators) {
te->FileSetGenerators[gen->GetFileSet()] = gen.get();
}
+ te->CxxModuleBmiGenerator = cxxModuleBmiGenerator.get();
target.AddInstallIncludeDirectories(
*te, cmMakeRange(includesArgs.GetIncludeDirs()));
te->NamelinkOnly = namelinkOnly;
@@ -1105,6 +1133,19 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
}
+ if (supportCxx20FileSetTypes &&
+ !cxxModuleBmiArgs.GetDestination().empty()) {
+ cxxModuleBmiGenerator = cm::make_unique<cmInstallCxxModuleBmiGenerator>(
+ target.GetName(),
+ helper.GetCxxModulesBmiDestination(&cxxModuleBmiArgs),
+ cxxModuleBmiArgs.GetPermissions(),
+ cxxModuleBmiArgs.GetConfigurations(), cxxModuleBmiArgs.GetComponent(),
+ cmInstallGenerator::SelectMessageLevel(target.GetMakefile()),
+ cxxModuleBmiArgs.GetExcludeFromAll(), cxxModuleBmiArgs.GetOptional(),
+ helper.Makefile->GetBacktrace());
+ target.SetHaveInstallRule(true);
+ }
+
// Add this install rule to an export if one was specified.
if (!addTargetExport()) {
return false;
@@ -1121,6 +1162,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
installsPrivateHeader = installsPrivateHeader || privateHeaderGenerator;
installsPublicHeader = installsPublicHeader || publicHeaderGenerator;
installsResource = installsResource || resourceGenerator;
+ installsCxxModuleBmi = installsCxxModuleBmi || cxxModuleBmiGenerator;
helper.Makefile->AddInstallGenerator(std::move(archiveGenerator));
helper.Makefile->AddInstallGenerator(std::move(libraryGenerator));
@@ -1135,9 +1177,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
for (auto& gen : fileSetGenerators) {
helper.Makefile->AddInstallGenerator(std::move(gen));
}
+ helper.Makefile->AddInstallGenerator(std::move(cxxModuleBmiGenerator));
}
- if (withRuntimeDependencies && !runtimeDependencySet->Empty()) {
+ if (runtimeDependenciesArgVector && !runtimeDependencySet->Empty()) {
AddInstallRuntimeDependenciesGenerator(
helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs,
std::move(runtimeDependenciesArgs), installsRuntime, installsLibrary,
@@ -1192,6 +1235,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
fileSetArgs[i].GetComponent());
}
}
+ if (installsCxxModuleBmi) {
+ helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
+ cxxModuleBmiArgs.GetComponent());
+ }
return true;
}
@@ -1206,10 +1253,10 @@ bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
struct ArgVectors
{
- std::vector<std::string> Library;
- std::vector<std::string> Runtime;
- std::vector<std::string> Framework;
- std::vector<std::string> Bundle;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Library;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Runtime;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Framework;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Bundle;
};
static auto const argHelper = cmArgumentParser<ArgVectors>{}
@@ -1223,7 +1270,7 @@ bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args,
// now parse the generic args (i.e. the ones not specialized on LIBRARY,
// RUNTIME etc. (see above)
- std::vector<std::string> targetList;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> targetList;
std::string runtimeDependencySetArg;
std::vector<std::string> unknownArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
@@ -1464,7 +1511,7 @@ bool HandleFilesMode(std::vector<std::string> const& args,
// This is the FILES mode.
bool programs = (args[0] == "PROGRAMS");
cmInstallCommandArguments ica(helper.DefaultComponentName);
- std::vector<std::string> files;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> files;
ica.Bind(programs ? "PROGRAMS"_s : "FILES"_s, files);
std::vector<std::string> unknownArgs;
ica.Parse(args, &unknownArgs);
@@ -1950,7 +1997,7 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args,
cm::make_unique<cmInstallExportGenerator>(
&exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message,
- ica.GetExcludeFromAll(), fname, name_space, exportOld, true,
+ ica.GetExcludeFromAll(), fname, name_space, "", exportOld, true,
helper.Makefile->GetBacktrace()));
return true;
@@ -1973,12 +2020,19 @@ bool HandleExportMode(std::vector<std::string> const& args,
std::string name_space;
bool exportOld = false;
std::string filename;
+ std::string cxx_modules_directory;
ica.Bind("EXPORT"_s, exp);
ica.Bind("NAMESPACE"_s, name_space);
ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld);
ica.Bind("FILE"_s, filename);
+ bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled(
+ *helper.Makefile, cmExperimental::Feature::CxxModuleCMakeApi);
+ if (supportCxx20FileSetTypes) {
+ ica.Bind("CXX_MODULES_DIRECTORY"_s, cxx_modules_directory);
+ }
+
std::vector<std::string> unknownArgs;
ica.Parse(args, &unknownArgs);
@@ -2064,8 +2118,8 @@ bool HandleExportMode(std::vector<std::string> const& args,
cm::make_unique<cmInstallExportGenerator>(
&exportSet, ica.GetDestination(), ica.GetPermissions(),
ica.GetConfigurations(), ica.GetComponent(), message,
- ica.GetExcludeFromAll(), fname, name_space, exportOld, false,
- helper.Makefile->GetBacktrace()));
+ ica.GetExcludeFromAll(), fname, name_space, cxx_modules_directory,
+ exportOld, false, helper.Makefile->GetBacktrace()));
return true;
}
@@ -2088,9 +2142,9 @@ bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args,
struct ArgVectors
{
- std::vector<std::string> Library;
- std::vector<std::string> Runtime;
- std::vector<std::string> Framework;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Library;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Runtime;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Framework;
};
static auto const argHelper = cmArgumentParser<ArgVectors>{}
@@ -2106,7 +2160,7 @@ bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args,
// These generic args also contain the runtime dependency set
std::string runtimeDependencySetArg;
std::vector<std::string> runtimeDependencyArgVector;
- std::vector<std::string> parsedArgs;
+ std::vector<cm::string_view> parsedArgs;
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg);
genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector, nullptr,
@@ -2280,6 +2334,15 @@ std::string Helper::GetLibraryDestination(
return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib");
}
+std::string Helper::GetCxxModulesBmiDestination(
+ const cmInstallCommandArguments* args) const
+{
+ if (args) {
+ return args->GetDestination();
+ }
+ return {};
+}
+
std::string Helper::GetIncludeDestination(
const cmInstallCommandArguments* args) const
{
diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h
index 79bd945..6e46aac 100644
--- a/Source/cmInstallCommandArguments.h
+++ b/Source/cmInstallCommandArguments.h
@@ -8,6 +8,7 @@
#include <vector>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
class cmInstallCommandArguments : public cmArgumentParser<void>
{
@@ -44,8 +45,8 @@ private:
std::string NamelinkComponent;
bool ExcludeFromAll = false;
std::string Rename;
- std::vector<std::string> Permissions;
- std::vector<std::string> Configurations;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Permissions;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Configurations;
bool Optional = false;
bool NamelinkOnly = false;
bool NamelinkSkip = false;
diff --git a/Source/cmInstallCxxModuleBmiGenerator.cxx b/Source/cmInstallCxxModuleBmiGenerator.cxx
new file mode 100644
index 0000000..1ef1eaa
--- /dev/null
+++ b/Source/cmInstallCxxModuleBmiGenerator.cxx
@@ -0,0 +1,75 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmInstallCxxModuleBmiGenerator.h"
+
+#include <ostream>
+#include <utility>
+
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmOutputConverter.h"
+#include "cmStringAlgorithms.h"
+
+cmInstallCxxModuleBmiGenerator::cmInstallCxxModuleBmiGenerator(
+ std::string target, std::string const& dest, std::string file_permissions,
+ std::vector<std::string> const& configurations, std::string const& component,
+ MessageLevel message, bool exclude_from_all, bool optional,
+ cmListFileBacktrace backtrace)
+ : cmInstallGenerator(dest, configurations, component, message,
+ exclude_from_all, false, std::move(backtrace))
+ , TargetName(std::move(target))
+ , FilePermissions(std::move(file_permissions))
+ , Optional(optional)
+{
+ this->ActionsPerConfig = true;
+}
+
+cmInstallCxxModuleBmiGenerator::~cmInstallCxxModuleBmiGenerator() = default;
+
+bool cmInstallCxxModuleBmiGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+
+ this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
+ if (!this->Target) {
+ // If no local target has been found, find it in the global scope.
+ this->Target =
+ lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
+ }
+
+ return true;
+}
+
+std::string cmInstallCxxModuleBmiGenerator::GetScriptLocation(
+ std::string const& config) const
+{
+ char const* config_name = config.c_str();
+ if (config.empty()) {
+ config_name = "noconfig";
+ }
+ return cmStrCat(this->Target->GetSupportDirectory(),
+ "/install-cxx-module-bmi-", config_name, ".cmake");
+}
+
+std::string cmInstallCxxModuleBmiGenerator::GetDestination(
+ std::string const& config) const
+{
+ return cmGeneratorExpression::Evaluate(this->Destination,
+ this->LocalGenerator, config);
+}
+
+void cmInstallCxxModuleBmiGenerator::GenerateScriptForConfig(
+ std::ostream& os, const std::string& config, Indent indent)
+{
+ auto const& loc = this->GetScriptLocation(config);
+ if (loc.empty()) {
+ return;
+ }
+ os << indent << "include(\""
+ << cmOutputConverter::EscapeForCMake(
+ loc, cmOutputConverter::WrapQuotes::NoWrap)
+ << "\" OPTIONAL)\n";
+}
diff --git a/Source/cmInstallCxxModuleBmiGenerator.h b/Source/cmInstallCxxModuleBmiGenerator.h
new file mode 100644
index 0000000..21edb2e
--- /dev/null
+++ b/Source/cmInstallCxxModuleBmiGenerator.h
@@ -0,0 +1,52 @@
+/* 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 <iosfwd>
+#include <string>
+#include <vector>
+
+#include "cmInstallGenerator.h"
+#include "cmScriptGenerator.h"
+
+class cmGeneratorTarget;
+class cmListFileBacktrace;
+class cmLocalGenerator;
+
+/** \class cmInstallCxxModuleBmiGenerator
+ * \brief Generate C++ module BMI installation rules.
+ */
+class cmInstallCxxModuleBmiGenerator : public cmInstallGenerator
+{
+public:
+ cmInstallCxxModuleBmiGenerator(
+ std::string target, std::string const& dest, std::string file_permissions,
+ std::vector<std::string> const& configurations,
+ std::string const& component, MessageLevel message, bool exclude_from_all,
+ bool optional, cmListFileBacktrace backtrace);
+ ~cmInstallCxxModuleBmiGenerator() override;
+
+ bool Compute(cmLocalGenerator* lg) override;
+
+ std::string const& GetFilePermissions() const
+ {
+ return this->FilePermissions;
+ }
+ std::string GetDestination(std::string const& config) const;
+ std::string GetScriptLocation(std::string const& config) const;
+ cmGeneratorTarget const* GetTarget() const { return this->Target; }
+ bool GetOptional() const { return this->Optional; }
+ MessageLevel GetMessageLevel() const { return this->Message; }
+
+protected:
+ void GenerateScriptForConfig(std::ostream& os, const std::string& config,
+ Indent indent) override;
+
+ std::string const TargetName;
+ cmGeneratorTarget const* Target = nullptr;
+ cmLocalGenerator* LocalGenerator = nullptr;
+ std::string const FilePermissions;
+ bool const Optional;
+};
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index b80437d..1d81b0b 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -23,7 +23,8 @@ cmInstallExportGenerator::cmInstallExportGenerator(
cmExportSet* exportSet, std::string const& destination,
std::string file_permissions, std::vector<std::string> const& configurations,
std::string const& component, MessageLevel message, bool exclude_from_all,
- std::string filename, std::string name_space, bool exportOld, bool android,
+ std::string filename, std::string name_space,
+ std::string cxx_modules_directory, bool exportOld, bool android,
cmListFileBacktrace backtrace)
: cmInstallGenerator(destination, configurations, component, message,
exclude_from_all, false, std::move(backtrace))
@@ -31,6 +32,7 @@ cmInstallExportGenerator::cmInstallExportGenerator(
, FilePermissions(std::move(file_permissions))
, FileName(std::move(filename))
, Namespace(std::move(name_space))
+ , CxxModulesDirectory(std::move(cxx_modules_directory))
, ExportOld(exportOld)
{
if (android) {
@@ -141,6 +143,75 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
os << indent << "endif()\n";
files.clear();
}
+
+ // Now create a configuration-specific install rule for the C++ module import
+ // property file of each configuration.
+ auto cxx_module_dest =
+ cmStrCat(this->Destination, '/', this->CxxModulesDirectory);
+ std::string config_file_example;
+ for (auto const& i : this->EFGen->GetConfigCxxModuleFiles()) {
+ config_file_example = i.second;
+ break;
+ }
+ if (!config_file_example.empty()) {
+ // Remove old per-configuration export files if the main changes.
+ std::string installedDir = cmStrCat(
+ "$ENV{DESTDIR}", ConvertToAbsoluteDestination(cxx_module_dest), '/');
+ std::string installedFile = cmStrCat(installedDir, "/cxx-modules.cmake");
+ std::string toInstallFile =
+ cmStrCat(cmSystemTools::GetFilenamePath(config_file_example),
+ "/cxx-modules.cmake");
+ os << indent << "if(EXISTS \"" << installedFile << "\")\n";
+ Indent indentN = indent.Next();
+ Indent indentNN = indentN.Next();
+ Indent indentNNN = indentNN.Next();
+ /* clang-format off */
+ os << indentN << "file(DIFFERENT _cmake_export_file_changed FILES\n"
+ << indentN << " \"" << installedFile << "\"\n"
+ << indentN << " \"" << toInstallFile << "\")\n";
+ os << indentN << "if(_cmake_export_file_changed)\n";
+ os << indentNN << "file(GLOB _cmake_old_config_files \"" << installedDir
+ << this->EFGen->GetConfigImportFileGlob() << "\")\n";
+ os << indentNN << "if(_cmake_old_config_files)\n";
+ os << indentNNN << "string(REPLACE \";\" \", \" _cmake_old_config_files_text \"${_cmake_old_config_files}\")\n";
+ os << indentNNN << R"(message(STATUS "Old C++ module export file \")" << installedFile
+ << "\\\" will be replaced. Removing files [${_cmake_old_config_files_text}].\")\n";
+ os << indentNNN << "unset(_cmake_old_config_files_text)\n";
+ os << indentNNN << "file(REMOVE ${_cmake_old_config_files})\n";
+ os << indentNN << "endif()\n";
+ os << indentNN << "unset(_cmake_old_config_files)\n";
+ os << indentN << "endif()\n";
+ os << indentN << "unset(_cmake_export_file_changed)\n";
+ os << indent << "endif()\n";
+ /* clang-format on */
+
+ // All of these files are siblings; get its location to know where the
+ // "anchor" file is.
+ files.push_back(toInstallFile);
+ this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files,
+ false, this->FilePermissions.c_str(), nullptr,
+ nullptr, nullptr, indent);
+ files.clear();
+ }
+ for (auto const& i : this->EFGen->GetConfigCxxModuleFiles()) {
+ files.push_back(i.second);
+ std::string config_test = this->CreateConfigTest(i.first);
+ os << indent << "if(" << config_test << ")\n";
+ this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files,
+ false, this->FilePermissions.c_str(), nullptr,
+ nullptr, nullptr, indent.Next());
+ os << indent << "endif()\n";
+ files.clear();
+ }
+ for (auto const& i : this->EFGen->GetConfigCxxModuleTargetFiles()) {
+ std::string config_test = this->CreateConfigTest(i.first);
+ os << indent << "if(" << config_test << ")\n";
+ this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, i.second,
+ false, this->FilePermissions.c_str(), nullptr,
+ nullptr, nullptr, indent.Next());
+ os << indent << "endif()\n";
+ files.clear();
+ }
}
void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index 02fe1fa..346ca67 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -28,7 +28,8 @@ public:
const std::vector<std::string>& configurations,
std::string const& component, MessageLevel message,
bool exclude_from_all, std::string filename,
- std::string name_space, bool exportOld,
+ std::string name_space,
+ std::string cxx_modules_directory, bool exportOld,
bool android, cmListFileBacktrace backtrace);
cmInstallExportGenerator(const cmInstallExportGenerator&) = delete;
~cmInstallExportGenerator() override;
@@ -50,6 +51,10 @@ public:
std::string GetDestinationFile() const;
std::string GetFileName() const { return this->FileName; }
std::string GetTempDir() const;
+ std::string GetCxxModuleDirectory() const
+ {
+ return this->CxxModulesDirectory;
+ }
protected:
void GenerateScript(std::ostream& os) override;
@@ -64,6 +69,7 @@ protected:
std::string const FilePermissions;
std::string const FileName;
std::string const Namespace;
+ std::string const CxxModulesDirectory;
bool const ExportOld;
cmLocalGenerator* LocalGenerator = nullptr;
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index e125470..de1d3cd 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1412,13 +1412,16 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) {
// The dependencies must be regenerated.
- std::string targetName = cmSystemTools::GetFilenameName(targetDir);
- targetName = targetName.substr(0, targetName.length() - 4);
- std::string message =
- cmStrCat("Scanning dependencies of target ", targetName);
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
- cmsysTerminal_Color_ForegroundBold,
- message.c_str(), true, color);
+ if (verbose) {
+ std::string targetName = cmSystemTools::GetFilenameName(targetDir);
+ targetName = targetName.substr(0, targetName.length() - 4);
+ std::string message =
+ cmStrCat("Scanning dependencies of target ", targetName);
+ cmSystemTools::MakefileColorEcho(
+ cmsysTerminal_Color_ForegroundMagenta |
+ cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, color);
+ }
status = this->ScanDependencies(targetDir, dependFile,
internalDependFile, validDependencies);
@@ -1447,13 +1450,19 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
this->GetBinaryDirectory())
: std::function<bool(const std::string&)>())) {
// regenerate dependencies files
- std::string targetName =
- cmCMakePath(targetDir).GetFileName().RemoveExtension().GenericString();
- auto message = cmStrCat(
- "Consolidate compiler generated dependencies of target ", targetName);
- cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
- cmsysTerminal_Color_ForegroundBold,
- message.c_str(), true, color);
+ if (verbose) {
+ std::string targetName = cmCMakePath(targetDir)
+ .GetFileName()
+ .RemoveExtension()
+ .GenericString();
+ auto message =
+ cmStrCat("Consolidate compiler generated dependencies of target ",
+ targetName);
+ cmSystemTools::MakefileColorEcho(
+ cmsysTerminal_Color_ForegroundMagenta |
+ cmsysTerminal_Color_ForegroundBold,
+ message.c_str(), true, color);
+ }
// Open the make depends file. This should be copy-if-different
// because the make tool may try to reload it needlessly otherwise.
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 628eb1d..208d907 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -149,6 +149,29 @@ void cmMakefile::IssueMessage(MessageType t, std::string const& text) const
this->GetCMakeInstance()->IssueMessage(t, text, this->Backtrace);
}
+Message::LogLevel cmMakefile::GetCurrentLogLevel() const
+{
+ const cmake* cmakeInstance = this->GetCMakeInstance();
+
+ const Message::LogLevel logLevelCliOrDefault = cmakeInstance->GetLogLevel();
+ assert("Expected a valid log level here" &&
+ logLevelCliOrDefault != Message::LogLevel::LOG_UNDEFINED);
+
+ Message::LogLevel result = logLevelCliOrDefault;
+
+ // If the log-level was set via the command line option, it takes precedence
+ // over the CMAKE_MESSAGE_LOG_LEVEL variable.
+ if (!cmakeInstance->WasLogLevelSetViaCLI()) {
+ const Message::LogLevel logLevelFromVar = cmake::StringToLogLevel(
+ this->GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL"));
+ if (logLevelFromVar != Message::LogLevel::LOG_UNDEFINED) {
+ result = logLevelFromVar;
+ }
+ }
+
+ return result;
+}
+
bool cmMakefile::CheckCMP0037(std::string const& targetName,
cmStateEnums::TargetType targetType) const
{
@@ -3456,7 +3479,7 @@ void cmMakefile::AddTargetObject(std::string const& tgtName,
#endif
}
-void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
+void cmMakefile::EnableLanguage(std::vector<std::string> const& languages,
bool optional)
{
if (this->DeferRunning) {
@@ -3468,24 +3491,48 @@ void cmMakefile::EnableLanguage(std::vector<std::string> const& lang,
if (const char* def = this->GetGlobalGenerator()->GetCMakeCFGIntDir()) {
this->AddDefinition("CMAKE_CFG_INTDIR", def);
}
+
+ std::vector<std::string> unique_languages;
+ {
+ std::vector<std::string> duplicate_languages;
+ for (std::string const& language : languages) {
+ if (!cm::contains(unique_languages, language)) {
+ unique_languages.push_back(language);
+ } else if (!cm::contains(duplicate_languages, language)) {
+ duplicate_languages.push_back(language);
+ }
+ }
+ if (!duplicate_languages.empty()) {
+ auto quantity = duplicate_languages.size() == 1 ? std::string(" has")
+ : std::string("s have");
+ this->IssueMessage(MessageType::AUTHOR_WARNING,
+ "Languages to be enabled may not be specified more "
+ "than once at the same time. The following language" +
+ quantity + " been specified multiple times: " +
+ cmJoin(duplicate_languages, ", "));
+ }
+ }
+
// If RC is explicitly listed we need to do it after other languages.
// On some platforms we enable RC implicitly while enabling others.
// Do not let that look like recursive enable_language(RC).
- std::vector<std::string> langs;
- std::vector<std::string> langsRC;
- langs.reserve(lang.size());
- for (std::string const& i : lang) {
- if (i == "RC") {
- langsRC.push_back(i);
+ std::vector<std::string> languages_without_RC;
+ std::vector<std::string> languages_for_RC;
+ languages_without_RC.reserve(unique_languages.size());
+ for (std::string const& language : unique_languages) {
+ if (language == "RC") {
+ languages_for_RC.push_back(language);
} else {
- langs.push_back(i);
+ languages_without_RC.push_back(language);
}
}
- if (!langs.empty()) {
- this->GetGlobalGenerator()->EnableLanguage(langs, this, optional);
+ if (!languages_without_RC.empty()) {
+ this->GetGlobalGenerator()->EnableLanguage(languages_without_RC, this,
+ optional);
}
- if (!langsRC.empty()) {
- this->GetGlobalGenerator()->EnableLanguage(langsRC, this, optional);
+ if (!languages_for_RC.empty()) {
+ this->GetGlobalGenerator()->EnableLanguage(languages_for_RC, this,
+ optional);
}
}
@@ -4431,7 +4478,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
}
// Deprecate old policies.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0097 &&
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0102 &&
!(this->GetCMakeInstance()->GetIsInTryCompile() &&
(
// Policies set by cmCoreTryCompile::TryCompileCode.
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index e7b9716..df40c82 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -925,6 +925,7 @@ public:
};
void IssueMessage(MessageType t, std::string const& text) const;
+ Message::LogLevel GetCurrentLogLevel() const;
/** Set whether or not to report a CMP0000 violation. */
void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; }
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 3849c6f..74574f7 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -182,14 +182,16 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule(
// Collect up flags to link in needed libraries.
std::string linkLibs;
- this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
- useResponseFileForLibs, depends);
+ this->CreateLinkLibs(
+ linkLineComputer.get(), linkLibs, useResponseFileForLibs, depends,
+ cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
// Construct object file lists that may be needed to expand the
// rule.
std::string buildObjs;
- this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects,
- buildObjs, depends, false);
+ this->CreateObjectLists(
+ useLinkScript, false, useResponseFileForObjects, buildObjs, depends,
+ false, cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
cmRulePlaceholderExpander::RuleVariables vars;
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index f30ec27..3f7d87d 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -322,15 +322,17 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules(
linkLineComputer->SetForResponse(useResponseFileForLibs);
linkLineComputer->SetRelink(relink);
- this->CreateLinkLibs(linkLineComputer.get(), linkLibs,
- useResponseFileForLibs, depends);
+ this->CreateLinkLibs(
+ linkLineComputer.get(), linkLibs, useResponseFileForLibs, depends,
+ cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
// Construct object file lists that may be needed to expand the
// rule.
std::string buildObjs;
- this->CreateObjectLists(useLinkScript, false, // useArchiveRules
- useResponseFileForObjects, buildObjs, depends,
- false);
+ this->CreateObjectLists(
+ useLinkScript, false, // useArchiveRules
+ useResponseFileForObjects, buildObjs, depends, false,
+ cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink);
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
objectDir = this->LocalGenerator->ConvertToOutputFormat(
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index aec6577..1e1df79 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -21,6 +21,7 @@
#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
+#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
@@ -46,6 +47,7 @@
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
+#include "cmTarget.h"
#include "cmValue.h"
#include "cmake.h"
@@ -107,7 +109,7 @@ std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New(
return result;
}
-std::string cmMakefileTargetGenerator::GetConfigName()
+std::string cmMakefileTargetGenerator::GetConfigName() const
{
auto const& configNames = this->LocalGenerator->GetConfigNames();
assert(configNames.size() == 1);
@@ -190,6 +192,16 @@ void cmMakefileTargetGenerator::CreateRuleFile()
void cmMakefileTargetGenerator::WriteTargetBuildRules()
{
+ this->GeneratorTarget->CheckCxxModuleStatus(this->GetConfigName());
+
+ if (this->GeneratorTarget->HaveCxx20ModuleSources()) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", this->GeneratorTarget->GetName(),
+ "\" target contains C++ module sources which are not supported "
+ "by the generator"));
+ }
+
// -- Write the custom commands for this target
// Evaluates generator expressions and expands prop_value
@@ -302,6 +314,40 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
}
}
+ std::map<std::string, std::string> file_set_map;
+
+ auto const* tgt = this->GeneratorTarget->Target;
+ for (auto const& name : tgt->GetAllFileSetNames()) {
+ auto const* file_set = tgt->GetFileSet(name);
+ if (!file_set) {
+ this->Makefile->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(),
+ "\" is tracked to have file set \"", name,
+ "\", but it was not found."));
+ continue;
+ }
+
+ auto fileEntries = file_set->CompileFileEntries();
+ auto directoryEntries = file_set->CompileDirectoryEntries();
+ auto directories = file_set->EvaluateDirectoryEntries(
+ directoryEntries, this->LocalGenerator, this->GetConfigName(),
+ this->GeneratorTarget);
+
+ std::map<std::string, std::vector<std::string>> files;
+ for (auto const& entry : fileEntries) {
+ file_set->EvaluateFileEntry(directories, files, entry,
+ this->LocalGenerator, this->GetConfigName(),
+ this->GeneratorTarget);
+ }
+
+ for (auto const& it : files) {
+ for (auto const& filename : it.second) {
+ file_set_map[filename] = file_set->GetType();
+ }
+ }
+ }
+
std::vector<cmSourceFile const*> objectSources;
this->GeneratorTarget->GetObjectSources(objectSources,
this->GetConfigName());
@@ -314,6 +360,25 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
this->WriteObjectRuleFiles(*sf);
}
}
+
+ for (cmSourceFile const* sf : objectSources) {
+ auto const& path = sf->GetFullPath();
+ auto const it = file_set_map.find(path);
+ if (it != file_set_map.end()) {
+ auto const& file_set_type = it->second;
+ if (file_set_type == "CXX_MODULES"_s ||
+ file_set_type == "CXX_MODULE_HEADER_UNITS"_s) {
+ if (sf->GetLanguage() != "CXX"_s) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ "Target \"", tgt->GetName(), "\" contains the source\n ", path,
+ "\nin a file set of type \"", file_set_type,
+ R"(" but the source is not classified as a "CXX" source.)"));
+ }
+ }
+ }
+ }
}
void cmMakefileTargetGenerator::WriteCommonCodeRules()
@@ -2080,7 +2145,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries(
}
std::string cmMakefileTargetGenerator::CreateResponseFile(
- const char* name, std::string const& options,
+ const std::string& name, std::string const& options,
std::vector<std::string>& makefile_depends)
{
// FIXME: Find a better way to determine the response file encoding,
@@ -2126,7 +2191,8 @@ cmMakefileTargetGenerator::CreateLinkLineComputer(
void cmMakefileTargetGenerator::CreateLinkLibs(
cmLinkLineComputer* linkLineComputer, std::string& linkLibs,
- bool useResponseFile, std::vector<std::string>& makefile_depends)
+ bool useResponseFile, std::vector<std::string>& makefile_depends,
+ ResponseFlagFor responseMode)
{
std::string frameworkPath;
std::string linkPath;
@@ -2139,20 +2205,13 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
if (useResponseFile &&
linkLibs.find_first_not_of(' ') != std::string::npos) {
// Lookup the response file reference flag.
- std::string responseFlagVar =
- cmStrCat("CMAKE_",
- this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
- "_RESPONSE_FILE_LINK_FLAG");
- std::string responseFlag;
- if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
- responseFlag = *p;
- } else {
- responseFlag = "@";
- }
+ std::string responseFlag = this->GetResponseFlag(responseMode);
// Create this response file.
+ std::string responseFileName =
+ (responseMode == Link) ? "linkLibs.rsp" : "deviceLinkLibs.rsp";
std::string link_rsp =
- this->CreateResponseFile("linklibs.rsp", linkLibs, makefile_depends);
+ this->CreateResponseFile(responseFileName, linkLibs, makefile_depends);
// Reference the response file.
linkLibs = cmStrCat(responseFlag,
@@ -2164,7 +2223,7 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
void cmMakefileTargetGenerator::CreateObjectLists(
bool useLinkScript, bool useArchiveRules, bool useResponseFile,
std::string& buildObjs, std::vector<std::string>& makefile_depends,
- bool useWatcomQuote)
+ bool useWatcomQuote, ResponseFlagFor responseMode)
{
std::string variableName;
std::string variableNameExternal;
@@ -2179,27 +2238,19 @@ void cmMakefileTargetGenerator::CreateObjectLists(
this->WriteObjectsStrings(object_strings, responseFileLimit);
// Lookup the response file reference flag.
- std::string responseFlagVar =
- cmStrCat("CMAKE_",
- this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()),
- "_RESPONSE_FILE_LINK_FLAG");
- std::string responseFlag;
- if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
- responseFlag = *p;
- } else {
- responseFlag = "@";
- }
+ std::string responseFlag = this->GetResponseFlag(responseMode);
// Write a response file for each string.
const char* sep = "";
for (unsigned int i = 0; i < object_strings.size(); ++i) {
// Number the response files.
- char rsp[32];
- snprintf(rsp, sizeof(rsp), "objects%u.rsp", i + 1);
+ std::string responseFileName =
+ (responseMode == Link) ? "objects" : "deviceObjects";
+ responseFileName += std::to_string(i + 1);
// Create this response file.
- std::string objects_rsp =
- this->CreateResponseFile(rsp, object_strings[i], makefile_depends);
+ std::string objects_rsp = this->CreateResponseFile(
+ responseFileName, object_strings[i], makefile_depends);
// Separate from previous response file references.
buildObjs += sep;
@@ -2251,7 +2302,7 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
}
std::string name = cmStrCat("includes_", lang, ".rsp");
std::string arg = std::move(responseFlag) +
- this->CreateResponseFile(name.c_str(), includeFlags,
+ this->CreateResponseFile(name, includeFlags,
this->FlagFileDepends[lang]);
this->LocalGenerator->AppendFlags(flags, arg);
} else {
@@ -2304,3 +2355,22 @@ void cmMakefileTargetGenerator::GenDefFile(
fout << src->GetFullPath() << "\n";
}
}
+
+std::string cmMakefileTargetGenerator::GetResponseFlag(
+ ResponseFlagFor mode) const
+{
+ std::string responseFlag = "@";
+ std::string responseFlagVar;
+
+ auto lang = this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName());
+ if (mode == cmMakefileTargetGenerator::ResponseFlagFor::Link) {
+ responseFlagVar = cmStrCat("CMAKE_", lang, "_RESPONSE_FILE_LINK_FLAG");
+ } else if (mode == cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink) {
+ responseFlagVar = "CMAKE_CUDA_RESPONSE_FILE_DEVICE_LINK_FLAG";
+ }
+
+ if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) {
+ responseFlag = *p;
+ }
+ return responseFlag;
+}
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index cb804e0..dafa650 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -56,7 +56,7 @@ public:
cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
- std::string GetConfigName();
+ std::string GetConfigName() const;
protected:
void GetDeviceLinkFlags(std::string& linkFlags,
@@ -157,22 +157,31 @@ protected:
/** Create a response file with the given set of options. Returns
the relative path from the target build working directory to the
response file name. */
- std::string CreateResponseFile(const char* name, std::string const& options,
+ std::string CreateResponseFile(const std::string& name,
+ std::string const& options,
std::vector<std::string>& makefile_depends);
bool CheckUseResponseFileForObjects(std::string const& l) const;
bool CheckUseResponseFileForLibraries(std::string const& l) const;
+ enum ResponseFlagFor
+ {
+ Link,
+ DeviceLink
+ };
+
/** Create list of flags for link libraries. */
void CreateLinkLibs(cmLinkLineComputer* linkLineComputer,
std::string& linkLibs, bool useResponseFile,
- std::vector<std::string>& makefile_depends);
+ std::vector<std::string>& makefile_depends,
+ ResponseFlagFor responseMode = ResponseFlagFor::Link);
/** Create lists of object files for linking and cleaning. */
void CreateObjectLists(bool useLinkScript, bool useArchiveRules,
bool useResponseFile, std::string& buildObjs,
std::vector<std::string>& makefile_depends,
- bool useWatcomQuote);
+ bool useWatcomQuote,
+ ResponseFlagFor responseMode = ResponseFlagFor::Link);
/** Add commands for generate def files */
void GenDefFile(std::vector<std::string>& real_link_commands);
@@ -180,6 +189,9 @@ protected:
void AddIncludeFlags(std::string& flags, const std::string& lang,
const std::string& config) override;
+ /** Return the response flag for the given configuration */
+ std::string GetResponseFlag(ResponseFlagFor mode) const;
+
virtual void CloseFileStreams();
cmLocalUnixMakefileGenerator3* LocalGenerator;
cmGlobalUnixMakefileGenerator3* GlobalGenerator;
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index cd57600..fa29ec9 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -81,94 +81,83 @@ bool cmMessageCommand(std::vector<std::string> const& args,
auto type = MessageType::MESSAGE;
auto fatal = false;
- auto level = cmake::LogLevel::LOG_UNDEFINED;
+ auto level = Message::LogLevel::LOG_UNDEFINED;
auto checkingType = CheckingType::UNDEFINED;
if (*i == "SEND_ERROR") {
type = MessageType::FATAL_ERROR;
- level = cmake::LogLevel::LOG_ERROR;
+ level = Message::LogLevel::LOG_ERROR;
++i;
} else if (*i == "FATAL_ERROR") {
fatal = true;
type = MessageType::FATAL_ERROR;
- level = cmake::LogLevel::LOG_ERROR;
+ level = Message::LogLevel::LOG_ERROR;
++i;
} else if (*i == "WARNING") {
type = MessageType::WARNING;
- level = cmake::LogLevel::LOG_WARNING;
+ level = Message::LogLevel::LOG_WARNING;
++i;
} else if (*i == "AUTHOR_WARNING") {
if (mf.IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") &&
!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) {
fatal = true;
type = MessageType::AUTHOR_ERROR;
- level = cmake::LogLevel::LOG_ERROR;
+ level = Message::LogLevel::LOG_ERROR;
} else if (!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) {
type = MessageType::AUTHOR_WARNING;
- level = cmake::LogLevel::LOG_WARNING;
+ level = Message::LogLevel::LOG_WARNING;
} else {
return true;
}
++i;
} else if (*i == "CHECK_START") {
- level = cmake::LogLevel::LOG_STATUS;
+ level = Message::LogLevel::LOG_STATUS;
checkingType = CheckingType::CHECK_START;
++i;
} else if (*i == "CHECK_PASS") {
- level = cmake::LogLevel::LOG_STATUS;
+ level = Message::LogLevel::LOG_STATUS;
checkingType = CheckingType::CHECK_PASS;
++i;
} else if (*i == "CHECK_FAIL") {
- level = cmake::LogLevel::LOG_STATUS;
+ level = Message::LogLevel::LOG_STATUS;
checkingType = CheckingType::CHECK_FAIL;
++i;
} else if (*i == "STATUS") {
- level = cmake::LogLevel::LOG_STATUS;
+ level = Message::LogLevel::LOG_STATUS;
++i;
} else if (*i == "VERBOSE") {
- level = cmake::LogLevel::LOG_VERBOSE;
+ level = Message::LogLevel::LOG_VERBOSE;
++i;
} else if (*i == "DEBUG") {
- level = cmake::LogLevel::LOG_DEBUG;
+ level = Message::LogLevel::LOG_DEBUG;
++i;
} else if (*i == "TRACE") {
- level = cmake::LogLevel::LOG_TRACE;
+ level = Message::LogLevel::LOG_TRACE;
++i;
} else if (*i == "DEPRECATION") {
if (mf.IsOn("CMAKE_ERROR_DEPRECATED")) {
fatal = true;
type = MessageType::DEPRECATION_ERROR;
- level = cmake::LogLevel::LOG_ERROR;
+ level = Message::LogLevel::LOG_ERROR;
} else if (!mf.IsSet("CMAKE_WARN_DEPRECATED") ||
mf.IsOn("CMAKE_WARN_DEPRECATED")) {
type = MessageType::DEPRECATION_WARNING;
- level = cmake::LogLevel::LOG_WARNING;
+ level = Message::LogLevel::LOG_WARNING;
} else {
return true;
}
++i;
} else if (*i == "NOTICE") {
// `NOTICE` message type is going to be output to stderr
- level = cmake::LogLevel::LOG_NOTICE;
+ level = Message::LogLevel::LOG_NOTICE;
++i;
} else {
// Messages w/o any type are `NOTICE`s
- level = cmake::LogLevel::LOG_NOTICE;
+ level = Message::LogLevel::LOG_NOTICE;
}
assert("Message log level expected to be set" &&
- level != cmake::LogLevel::LOG_UNDEFINED);
-
- auto desiredLevel = mf.GetCMakeInstance()->GetLogLevel();
- assert("Expected a valid log level here" &&
- desiredLevel != cmake::LogLevel::LOG_UNDEFINED);
-
- // Command line option takes precedence over the cache variable
- if (!mf.GetCMakeInstance()->WasLogLevelSetViaCLI()) {
- const auto desiredLevelFromCache =
- cmake::StringToLogLevel(mf.GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL"));
- if (desiredLevelFromCache != cmake::LogLevel::LOG_UNDEFINED) {
- desiredLevel = desiredLevelFromCache;
- }
- }
+ level != Message::LogLevel::LOG_UNDEFINED);
+
+ Message::LogLevel desiredLevel = mf.GetCurrentLogLevel();
if (desiredLevel < level) {
// Suppress the message
@@ -178,17 +167,17 @@ bool cmMessageCommand(std::vector<std::string> const& args,
auto message = cmJoin(cmMakeRange(i, args.cend()), "");
switch (level) {
- case cmake::LogLevel::LOG_ERROR:
- case cmake::LogLevel::LOG_WARNING:
+ case Message::LogLevel::LOG_ERROR:
+ case Message::LogLevel::LOG_WARNING:
// we've overridden the message type, above, so display it directly
mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace());
break;
- case cmake::LogLevel::LOG_NOTICE:
+ case Message::LogLevel::LOG_NOTICE:
cmSystemTools::Message(IndentText(message, mf));
break;
- case cmake::LogLevel::LOG_STATUS:
+ case Message::LogLevel::LOG_STATUS:
switch (checkingType) {
case CheckingType::CHECK_START:
mf.DisplayStatus(IndentText(message, mf), -1);
@@ -209,9 +198,9 @@ bool cmMessageCommand(std::vector<std::string> const& args,
}
break;
- case cmake::LogLevel::LOG_VERBOSE:
- case cmake::LogLevel::LOG_DEBUG:
- case cmake::LogLevel::LOG_TRACE:
+ case Message::LogLevel::LOG_VERBOSE:
+ case Message::LogLevel::LOG_DEBUG:
+ case Message::LogLevel::LOG_TRACE:
mf.DisplayStatus(IndentText(message, mf), -1);
break;
diff --git a/Source/cmMessageType.h b/Source/cmMessageType.h
index 44de429..decb4b3 100644
--- a/Source/cmMessageType.h
+++ b/Source/cmMessageType.h
@@ -16,3 +16,19 @@ enum class MessageType
DEPRECATION_ERROR,
DEPRECATION_WARNING
};
+
+namespace Message {
+
+/** \brief Define log level constants. */
+enum class LogLevel
+{
+ LOG_UNDEFINED,
+ LOG_ERROR,
+ LOG_WARNING,
+ LOG_NOTICE,
+ LOG_STATUS,
+ LOG_VERBOSE,
+ LOG_DEBUG,
+ LOG_TRACE
+};
+}
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 3fac7f5..a4080d8 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -21,11 +21,17 @@
#include "cmComputeLinkInformation.h"
#include "cmCustomCommandGenerator.h"
+#include "cmExportBuildFileGenerator.h"
+#include "cmExportSet.h"
#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
+#include "cmInstallCxxModuleBmiGenerator.h"
+#include "cmInstallExportGenerator.h"
+#include "cmInstallFileSetGenerator.h"
+#include "cmInstallGenerator.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
@@ -36,12 +42,12 @@
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
-#include "cmStandardLevelResolver.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmTargetExport.h"
#include "cmValue.h"
#include "cmake.h"
@@ -153,17 +159,12 @@ std::string cmNinjaTargetGenerator::LanguageDyndepRule(
bool cmNinjaTargetGenerator::NeedCxxModuleSupport(
std::string const& lang, std::string const& config) const
{
- if (lang != "CXX") {
+ if (lang != "CXX"_s) {
return false;
}
- if (!this->Makefile->IsOn("CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP")) {
- return false;
- }
- cmGeneratorTarget const* tgt = this->GetGeneratorTarget();
- cmStandardLevelResolver standardResolver(this->Makefile);
- bool const uses_cxx20 =
- standardResolver.HaveStandardAvailable(tgt, "CXX", config, "cxx_std_20");
- return uses_cxx20 && this->GetGlobalGenerator()->CheckCxxModuleSupport();
+ return this->GetGeneratorTarget()->HaveCxxModuleSupport(config) ==
+ cmGeneratorTarget::Cxx20SupportLevel::Supported &&
+ this->GetGlobalGenerator()->CheckCxxModuleSupport();
}
bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang,
@@ -255,51 +256,53 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
flags, genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS));
}
- if (this->NeedCxxModuleSupport(language, config)) {
- auto const& path = source->GetFullPath();
- auto const* tgt = this->GeneratorTarget->Target;
+ auto const& path = source->GetFullPath();
+ auto const* tgt = this->GeneratorTarget->Target;
- std::string file_set_type;
+ std::string file_set_type;
- for (auto const& name : tgt->GetAllFileSetNames()) {
- auto const* file_set = tgt->GetFileSet(name);
- if (!file_set) {
- this->GetMakefile()->IssueMessage(
- MessageType::INTERNAL_ERROR,
- cmStrCat("Target `", tgt->GetName(),
- "` is tracked to have file set `", name,
- "`, but it was not found."));
- continue;
- }
+ for (auto const& name : tgt->GetAllFileSetNames()) {
+ auto const* file_set = tgt->GetFileSet(name);
+ if (!file_set) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(),
+ "\" is tracked to have file set \"", name,
+ "\", but it was not found."));
+ continue;
+ }
- auto fileEntries = file_set->CompileFileEntries();
- auto directoryEntries = file_set->CompileDirectoryEntries();
- auto directories = file_set->EvaluateDirectoryEntries(
- directoryEntries, this->LocalGenerator, config, this->GeneratorTarget);
+ auto fileEntries = file_set->CompileFileEntries();
+ auto directoryEntries = file_set->CompileDirectoryEntries();
+ auto directories = file_set->EvaluateDirectoryEntries(
+ directoryEntries, this->LocalGenerator, config, this->GeneratorTarget);
- std::map<std::string, std::vector<std::string>> files;
- for (auto const& entry : fileEntries) {
- file_set->EvaluateFileEntry(directories, files, entry,
- this->LocalGenerator, config,
- this->GeneratorTarget);
- }
+ std::map<std::string, std::vector<std::string>> files;
+ for (auto const& entry : fileEntries) {
+ file_set->EvaluateFileEntry(directories, files, entry,
+ this->LocalGenerator, config,
+ this->GeneratorTarget);
+ }
- for (auto const& it : files) {
- for (auto const& filename : it.second) {
- if (filename == path) {
- file_set_type = file_set->GetType();
- break;
- }
+ for (auto const& it : files) {
+ for (auto const& filename : it.second) {
+ if (filename == path) {
+ file_set_type = file_set->GetType();
+ break;
}
}
+ }
- if (!file_set_type.empty()) {
- std::string source_type_var = cmStrCat(
- "CMAKE_EXPERIMENTAL_CXX_MODULE_SOURCE_TYPE_FLAG_", file_set_type);
- cmMakefile* mf = this->GetMakefile();
- if (cmValue source_type_flag = mf->GetDefinition(source_type_var)) {
- this->LocalGenerator->AppendFlags(flags, *source_type_flag);
- }
+ if (file_set_type == "CXX_MODULES"_s ||
+ file_set_type == "CXX_MODULE_HEADER_UNITS"_s) {
+ if (source->GetLanguage() != "CXX"_s) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat(
+ "Target \"", tgt->GetName(), "\" contains the source\n ", path,
+ "\nin a file set of type \"", file_set_type,
+ R"(" but the source is not classified as a "CXX" source.)"));
+ continue;
}
}
}
@@ -1038,6 +1041,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
const std::string& config, const std::string& fileConfig,
bool firstForConfig)
{
+ this->GeneratorTarget->CheckCxxModuleStatus(config);
+
// Write comments.
cmGlobalNinjaGenerator::WriteDivider(this->GetImplFileStream(fileConfig));
this->GetImplFileStream(fileConfig)
@@ -1338,9 +1343,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
}
- this->ExportObjectCompileCommand(
- language, sourceFilePath, objectDir, objectFileName, objectFileDir,
- vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config);
+ if (firstForConfig) {
+ this->ExportObjectCompileCommand(
+ language, sourceFilePath, objectDir, objectFileName, objectFileDir,
+ vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config);
+ }
objBuild.Outputs.push_back(objectFileName);
if (firstForConfig) {
@@ -1616,8 +1623,9 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
mod_dir = this->GeneratorTarget->GetFortranModuleDirectory(
this->Makefile->GetHomeOutputDirectory());
} else if (lang == "CXX") {
- mod_dir =
- cmSystemTools::CollapseFullPath(this->GeneratorTarget->ObjectDirectory);
+ mod_dir = this->GetGlobalGenerator()->ExpandCFGIntDir(
+ cmSystemTools::CollapseFullPath(this->GeneratorTarget->ObjectDirectory),
+ config);
}
if (mod_dir.empty()) {
mod_dir = this->Makefile->GetCurrentBinaryDirectory();
@@ -1654,6 +1662,215 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
tdi_linked_target_dirs.append(l);
}
+ cmTarget* tgt = this->GeneratorTarget->Target;
+ auto all_file_sets = tgt->GetAllFileSetNames();
+ Json::Value& tdi_cxx_module_info = tdi["cxx-modules"] = Json::objectValue;
+ for (auto const& file_set_name : all_file_sets) {
+ auto* file_set = tgt->GetFileSet(file_set_name);
+ if (!file_set) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(),
+ "\" is tracked to have file set \"", file_set_name,
+ "\", but it was not found."));
+ continue;
+ }
+ auto fs_type = file_set->GetType();
+ // We only care about C++ module sources here.
+ if (fs_type != "CXX_MODULES"_s) {
+ continue;
+ }
+
+ auto fileEntries = file_set->CompileFileEntries();
+ auto directoryEntries = file_set->CompileDirectoryEntries();
+
+ auto directories = file_set->EvaluateDirectoryEntries(
+ directoryEntries, this->GeneratorTarget->LocalGenerator, config,
+ this->GeneratorTarget);
+ std::map<std::string, std::vector<std::string>> files_per_dirs;
+ for (auto const& entry : fileEntries) {
+ file_set->EvaluateFileEntry(directories, files_per_dirs, entry,
+ this->GeneratorTarget->LocalGenerator,
+ config, this->GeneratorTarget);
+ }
+
+ std::map<std::string, cmSourceFile const*> sf_map;
+ {
+ std::vector<cmSourceFile const*> objectSources;
+ this->GeneratorTarget->GetObjectSources(objectSources, config);
+ for (auto const* sf : objectSources) {
+ auto full_path = sf->GetFullPath();
+ if (full_path.empty()) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(),
+ "\" has a full path-less source file."));
+ continue;
+ }
+ sf_map[full_path] = sf;
+ }
+ }
+
+ Json::Value fs_dest = Json::nullValue;
+ for (auto const& ig : this->GetMakefile()->GetInstallGenerators()) {
+ if (auto const* fsg =
+ dynamic_cast<cmInstallFileSetGenerator const*>(ig.get())) {
+ if (fsg->GetTarget() == this->GeneratorTarget &&
+ fsg->GetFileSet() == file_set) {
+ fs_dest = fsg->GetDestination(config);
+ continue;
+ }
+ }
+ }
+
+ for (auto const& files_per_dir : files_per_dirs) {
+ for (auto const& file : files_per_dir.second) {
+ auto lookup = sf_map.find(file);
+ if (lookup == sf_map.end()) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(), "\" has source file \"",
+ file,
+ R"(" which is not in any of its "FILE_SET BASE_DIRS".)"));
+ continue;
+ }
+
+ auto const* sf = lookup->second;
+
+ if (!sf) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::INTERNAL_ERROR,
+ cmStrCat("Target \"", tgt->GetName(), "\" has source file \"",
+ file, "\" which has not been tracked properly."));
+ continue;
+ }
+
+ auto obj_path = this->GetObjectFilePath(sf, config);
+ Json::Value& tdi_module_info = tdi_cxx_module_info[obj_path] =
+ Json::objectValue;
+
+ tdi_module_info["source"] = file;
+ tdi_module_info["relative-directory"] = files_per_dir.first;
+ tdi_module_info["name"] = file_set->GetName();
+ tdi_module_info["type"] = file_set->GetType();
+ tdi_module_info["visibility"] =
+ std::string(cmFileSetVisibilityToName(file_set->GetVisibility()));
+ tdi_module_info["destination"] = fs_dest;
+ }
+ }
+ }
+
+ tdi["config"] = config;
+
+ // Add information about the export sets that this target is a member of.
+ Json::Value& tdi_exports = tdi["exports"] = Json::arrayValue;
+ std::string export_name = this->GeneratorTarget->GetExportName();
+
+ cmInstallCxxModuleBmiGenerator const* bmi_gen = nullptr;
+ for (auto const& ig : this->GetMakefile()->GetInstallGenerators()) {
+ if (auto const* bmig =
+ dynamic_cast<cmInstallCxxModuleBmiGenerator const*>(ig.get())) {
+ if (bmig->GetTarget() == this->GeneratorTarget) {
+ bmi_gen = bmig;
+ continue;
+ }
+ }
+ }
+ if (bmi_gen) {
+ Json::Value tdi_bmi_info = Json::objectValue;
+
+ tdi_bmi_info["permissions"] = bmi_gen->GetFilePermissions();
+ tdi_bmi_info["destination"] = bmi_gen->GetDestination(config);
+ const char* msg_level = "";
+ switch (bmi_gen->GetMessageLevel()) {
+ case cmInstallGenerator::MessageDefault:
+ break;
+ case cmInstallGenerator::MessageAlways:
+ msg_level = "MESSAGE_ALWAYS";
+ break;
+ case cmInstallGenerator::MessageLazy:
+ msg_level = "MESSAGE_LAZY";
+ break;
+ case cmInstallGenerator::MessageNever:
+ msg_level = "MESSAGE_NEVER";
+ break;
+ }
+ tdi_bmi_info["message-level"] = msg_level;
+ tdi_bmi_info["script-location"] = bmi_gen->GetScriptLocation(config);
+
+ tdi["bmi-installation"] = tdi_bmi_info;
+ } else {
+ tdi["bmi-installation"] = Json::nullValue;
+ }
+
+ auto const& all_install_exports =
+ this->GetGlobalGenerator()->GetExportSets();
+ for (auto const& exp : all_install_exports) {
+ // Ignore exports sets which are not for this target.
+ auto const& targets = exp.second.GetTargetExports();
+ auto tgt_export =
+ std::find_if(targets.begin(), targets.end(),
+ [this](std::unique_ptr<cmTargetExport> const& te) {
+ return te->Target == this->GeneratorTarget;
+ });
+ if (tgt_export == targets.end()) {
+ continue;
+ }
+
+ auto const* installs = exp.second.GetInstallations();
+ for (auto const* install : *installs) {
+ Json::Value tdi_export_info = Json::objectValue;
+
+ auto const& ns = install->GetNamespace();
+ auto const& dest = install->GetDestination();
+ auto const& cxxm_dir = install->GetCxxModuleDirectory();
+ auto const& export_prefix = install->GetTempDir();
+
+ tdi_export_info["namespace"] = ns;
+ tdi_export_info["export-name"] = export_name;
+ tdi_export_info["destination"] = dest;
+ tdi_export_info["cxx-module-info-dir"] = cxxm_dir;
+ tdi_export_info["export-prefix"] = export_prefix;
+ tdi_export_info["install"] = true;
+
+ tdi_exports.append(tdi_export_info);
+ }
+ }
+
+ auto const& all_build_exports =
+ this->GetMakefile()->GetExportBuildFileGenerators();
+ for (auto const& exp : all_build_exports) {
+ std::vector<std::string> targets;
+ exp->GetTargets(targets);
+
+ // Ignore exports sets which are not for this target.
+ auto const& name = this->GeneratorTarget->GetName();
+ bool has_current_target =
+ std::any_of(targets.begin(), targets.end(),
+ [name](std::string const& tname) { return tname == name; });
+ if (!has_current_target) {
+ continue;
+ }
+
+ Json::Value tdi_export_info = Json::objectValue;
+
+ auto const& ns = exp->GetNamespace();
+ auto const& main_fn = exp->GetMainExportFileName();
+ auto const& cxxm_dir = exp->GetCxxModuleDirectory();
+ auto dest = cmsys::SystemTools::GetParentDirectory(main_fn);
+ auto const& export_prefix =
+ cmSystemTools::GetFilenamePath(exp->GetMainExportFileName());
+
+ tdi_export_info["namespace"] = ns;
+ tdi_export_info["export-name"] = export_name;
+ tdi_export_info["destination"] = dest;
+ tdi_export_info["cxx-module-info-dir"] = cxxm_dir;
+ tdi_export_info["export-prefix"] = export_prefix;
+ tdi_export_info["install"] = false;
+
+ tdi_exports.append(tdi_export_info);
+ }
+
std::string const tdin = this->GetTargetDependInfoPath(lang, config);
cmGeneratedFileStream tdif(tdin);
tdif << tdi;
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
index 95f3e7e..31538b6 100644
--- a/Source/cmParseArgumentsCommand.cxx
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -10,6 +10,7 @@
#include <cm/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
@@ -41,8 +42,9 @@ namespace {
using options_map = std::map<std::string, bool>;
using single_map = std::map<std::string, std::string>;
-using multi_map = std::map<std::string, std::vector<std::string>>;
-using options_set = std::set<std::string>;
+using multi_map =
+ std::map<std::string, ArgumentParser::NonEmpty<std::vector<std::string>>>;
+using options_set = std::set<cm::string_view>;
struct UserArgumentParser : public cmArgumentParser<void>
{
@@ -208,7 +210,7 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args,
}
}
- std::vector<std::string> keywordsMissingValues;
+ std::vector<cm::string_view> keywordsMissingValues;
parser.Parse(list, &unparsed, &keywordsMissingValues);
diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx
index 166ee56..32f9bec 100644
--- a/Source/cmScriptGenerator.cxx
+++ b/Source/cmScriptGenerator.cxx
@@ -133,7 +133,7 @@ void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os,
std::string config_test = this->CreateConfigTest(this->Configurations);
os << indent << "if(" << config_test << ")\n";
this->GenerateScriptActions(os, indent.Next());
- os << indent << "endif(" << config_test << ")\n";
+ os << indent << "endif()\n";
}
}
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index c3ee695..fe311d1 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -143,7 +143,8 @@ bool HandleHexCommand(std::vector<std::string> const& args,
std::string::size_type hexIndex = 0;
for (auto const& c : instr) {
- sprintf(&output[hexIndex], "%.2x", static_cast<unsigned char>(c) & 0xFF);
+ snprintf(&output[hexIndex], 3, "%.2x",
+ static_cast<unsigned char>(c) & 0xFF);
hexIndex += 2;
}
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 351386a..3de45bc 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1218,7 +1218,7 @@ std::string cmSystemTools::ComputeCertificateThumbprint(
certContext, CERT_HASH_PROP_ID, hashData, &hashLength)) {
for (DWORD i = 0; i < hashLength; i++) {
// Convert each byte to hexadecimal
- sprintf(pHashPrint, "%02X", hashData[i]);
+ snprintf(pHashPrint, 3, "%02X", hashData[i]);
pHashPrint += 2;
}
*pHashPrint = '\0';
@@ -1501,8 +1501,7 @@ std::string cmSystemTools::RelativeIfUnder(std::string const& top,
bool cmSystemTools::UnsetEnv(const char* value)
{
# if !defined(HAVE_UNSETENV)
- std::string var = cmStrCat(value, '=');
- return cmSystemTools::PutEnv(var);
+ return cmSystemTools::UnPutEnv(value);
# else
unsetenv(value);
return true;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index a8cd619..c76e2cb 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -272,6 +272,8 @@ public:
cmListFileBacktrace Backtrace;
FileSetType HeadersFileSets;
+ FileSetType CxxModulesFileSets;
+ FileSetType CxxModuleHeadersFileSets;
cmTargetInternals();
@@ -301,6 +303,19 @@ cmTargetInternals::cmTargetInternals()
"The default header set"_s, "Header set"_s,
FileSetEntries("HEADER_SETS"_s),
FileSetEntries("INTERFACE_HEADER_SETS"_s))
+ , CxxModulesFileSets("CXX_MODULES"_s, "CXX_MODULE_DIRS"_s,
+ "CXX_MODULE_SET"_s, "CXX_MODULE_DIRS_"_s,
+ "CXX_MODULE_SET_"_s, "C++ module"_s,
+ "The default C++ module set"_s, "C++ module set"_s,
+ FileSetEntries("CXX_MODULE_SETS"_s),
+ FileSetEntries("INTERFACE_CXX_MODULE_SETS"_s))
+ , CxxModuleHeadersFileSets(
+ "CXX_MODULE_HEADER_UNITS"_s, "CXX_MODULE_HEADER_UNIT_DIRS"_s,
+ "CXX_MODULE_HEADER_UNIT_SET"_s, "CXX_MODULE_HEADER_UNIT_DIRS_"_s,
+ "CXX_MODULE_HEADER_UNIT_SET_"_s, "C++ module header"_s,
+ "The default C++ module header set"_s, "C++ module header set"_s,
+ FileSetEntries("CXX_MODULE_HEADER_UNIT_SETS"_s),
+ FileSetEntries("INTERFACE_CXX_MODULE_HEADER_UNIT_SETS"_s))
{
}
@@ -611,6 +626,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("XCODE_SCHEME_MALLOC_SCRIBBLE");
initProp("XCODE_SCHEME_MALLOC_GUARD_EDGES");
initProp("XCODE_SCHEME_GUARD_MALLOC");
+ initProp("XCODE_SCHEME_LAUNCH_MODE");
initProp("XCODE_SCHEME_ZOMBIE_OBJECTS");
initProp("XCODE_SCHEME_MALLOC_STACK");
initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE");
@@ -760,6 +776,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
}
}
+ if (this->IsImported()) {
+ this->SetProperty("SYSTEM", "ON");
+ }
+
for (auto const& prop : mf->GetState()->GetPropertyDefinitions().GetMap()) {
if (prop.first.second == cmProperty::TARGET &&
!prop.second.GetInitializeFromVariable().empty()) {
@@ -1367,11 +1387,32 @@ cmBTStringRange cmTarget::GetHeaderSetsEntries() const
return cmMakeRange(this->impl->HeadersFileSets.SelfEntries.Entries);
}
+cmBTStringRange cmTarget::GetCxxModuleSetsEntries() const
+{
+ return cmMakeRange(this->impl->CxxModulesFileSets.SelfEntries.Entries);
+}
+
+cmBTStringRange cmTarget::GetCxxModuleHeaderSetsEntries() const
+{
+ return cmMakeRange(this->impl->CxxModuleHeadersFileSets.SelfEntries.Entries);
+}
+
cmBTStringRange cmTarget::GetInterfaceHeaderSetsEntries() const
{
return cmMakeRange(this->impl->HeadersFileSets.InterfaceEntries.Entries);
}
+cmBTStringRange cmTarget::GetInterfaceCxxModuleSetsEntries() const
+{
+ return cmMakeRange(this->impl->CxxModulesFileSets.InterfaceEntries.Entries);
+}
+
+cmBTStringRange cmTarget::GetInterfaceCxxModuleHeaderSetsEntries() const
+{
+ return cmMakeRange(
+ this->impl->CxxModuleHeadersFileSets.InterfaceEntries.Entries);
+}
+
namespace {
#define MAKE_PROP(PROP) const std::string prop##PROP = #PROP
MAKE_PROP(C_STANDARD);
@@ -1631,6 +1672,12 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value)
} else if (this->impl->HeadersFileSets.WriteProperties(
this, this->impl.get(), prop, value, true)) {
/* Handled in the `if` condition. */
+ } else if (this->impl->CxxModulesFileSets.WriteProperties(
+ this, this->impl.get(), prop, value, true)) {
+ /* Handled in the `if` condition. */
+ } else if (this->impl->CxxModuleHeadersFileSets.WriteProperties(
+ this, this->impl.get(), prop, value, true)) {
+ /* Handled in the `if` condition. */
} else {
this->impl->Properties.SetProperty(prop, value);
}
@@ -1742,6 +1789,13 @@ void cmTarget::AppendProperty(const std::string& prop,
this->impl->Makefile->IssueMessage(
MessageType::FATAL_ERROR, prop + " property may not be appended.");
} else if (this->impl->HeadersFileSets.WriteProperties(
+ this, this->impl.get(), prop, value,
+ false)) { // NOLINT(bugprone-branch-clone)
+ /* Handled in the `if` condition. */
+ } else if (this->impl->CxxModulesFileSets.WriteProperties(
+ this, this->impl.get(), prop, value, false)) {
+ /* Handled in the `if` condition. */
+ } else if (this->impl->CxxModuleHeadersFileSets.WriteProperties(
this, this->impl.get(), prop, value, false)) {
/* Handled in the `if` condition. */
} else {
@@ -2250,6 +2304,17 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
if (headers.first) {
return headers.second;
}
+ auto cxx_modules = this->impl->CxxModulesFileSets.ReadProperties(
+ this, this->impl.get(), prop);
+ if (cxx_modules.first) {
+ return cxx_modules.second;
+ }
+ auto cxx_module_headers =
+ this->impl->CxxModuleHeadersFileSets.ReadProperties(
+ this, this->impl.get(), prop);
+ if (cxx_module_headers.first) {
+ return cxx_module_headers.second;
+ }
}
cmValue retVal = this->impl->Properties.GetPropertyValue(prop);
@@ -2527,6 +2592,11 @@ std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet(
auto bt = this->impl->Makefile->GetBacktrace();
if (type == this->impl->HeadersFileSets.TypeName) {
this->impl->HeadersFileSets.AddFileSet(name, vis, std::move(bt));
+ } else if (type == this->impl->CxxModulesFileSets.TypeName) {
+ this->impl->CxxModulesFileSets.AddFileSet(name, vis, std::move(bt));
+ } else if (type == this->impl->CxxModuleHeadersFileSets.TypeName) {
+ this->impl->CxxModuleHeadersFileSets.AddFileSet(name, vis,
+ std::move(bt));
}
}
return std::make_pair(&result.first->second, result.second);
@@ -2537,6 +2607,12 @@ std::string cmTarget::GetFileSetsPropertyName(const std::string& type)
if (type == "HEADERS") {
return "HEADER_SETS";
}
+ if (type == "CXX_MODULES") {
+ return "CXX_MODULE_SETS";
+ }
+ if (type == "CXX_MODULE_HEADER_UNITS") {
+ return "CXX_MODULE_HEADER_UNIT_SETS";
+ }
return "";
}
@@ -2545,6 +2621,12 @@ std::string cmTarget::GetInterfaceFileSetsPropertyName(const std::string& type)
if (type == "HEADERS") {
return "INTERFACE_HEADER_SETS";
}
+ if (type == "CXX_MODULES") {
+ return "INTERFACE_CXX_MODULE_SETS";
+ }
+ if (type == "CXX_MODULE_HEADER_UNITS") {
+ return "INTERFACE_CXX_MODULE_HEADER_UNIT_SETS";
+ }
return "";
}
@@ -2572,6 +2654,8 @@ std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const
};
appendEntries(this->impl->HeadersFileSets.InterfaceEntries.Entries);
+ appendEntries(this->impl->CxxModulesFileSets.InterfaceEntries.Entries);
+ appendEntries(this->impl->CxxModuleHeadersFileSets.InterfaceEntries.Entries);
return result;
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 5ed018e..94d6688 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -275,8 +275,12 @@ public:
cmBTStringRange GetLinkInterfaceDirectExcludeEntries() const;
cmBTStringRange GetHeaderSetsEntries() const;
+ cmBTStringRange GetCxxModuleSetsEntries() const;
+ cmBTStringRange GetCxxModuleHeaderSetsEntries() const;
cmBTStringRange GetInterfaceHeaderSetsEntries() const;
+ cmBTStringRange GetInterfaceCxxModuleSetsEntries() const;
+ cmBTStringRange GetInterfaceCxxModuleHeaderSetsEntries() const;
std::string ImportedGetFullPath(const std::string& config,
cmStateEnums::ArtifactType artifact) const;
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
index 885ac74..1cef888 100644
--- a/Source/cmTargetExport.h
+++ b/Source/cmTargetExport.h
@@ -8,6 +8,7 @@
class cmFileSet;
class cmGeneratorTarget;
+class cmInstallCxxModuleBmiGenerator;
class cmInstallFileSetGenerator;
class cmInstallFilesGenerator;
class cmInstallTargetGenerator;
@@ -32,6 +33,7 @@ public:
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
std::map<cmFileSet*, cmInstallFileSetGenerator*> FileSetGenerators;
+ cmInstallCxxModuleBmiGenerator* CxxModuleBmiGenerator;
///@}
bool NamelinkOnly = false;
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index b1367e1..e2b0213 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -9,6 +9,8 @@
#include <cmext/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
+#include "cmExperimental.h"
#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmListFileCache.h"
@@ -27,8 +29,8 @@ struct FileSetArgs
{
std::string Type;
std::string FileSet;
- std::vector<std::string> BaseDirs;
- std::vector<std::string> Files;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> BaseDirs;
+ ArgumentParser::MaybeEmpty<std::vector<std::string>> Files;
};
auto const FileSetArgsParser = cmArgumentParser<FileSetArgs>()
@@ -196,7 +198,7 @@ std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent(
bool TargetSourcesImpl::HandleFileSetMode(
const std::string& scope, const std::vector<std::string>& content)
{
- auto args = FileSetsArgsParser.Parse(content);
+ auto args = FileSetsArgsParser.Parse(content, /*unparsedArguments=*/nullptr);
for (auto& argList : args.FileSets) {
argList.emplace(argList.begin(), "FILE_SET"_s);
@@ -256,9 +258,31 @@ bool TargetSourcesImpl::HandleOneFileSet(
this->SetError("Must specify a TYPE when creating file set");
return false;
}
- if (type != "HEADERS"_s) {
- this->SetError("File set TYPE may only be \"HEADERS\"");
- return false;
+ bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled(
+ *this->Makefile, cmExperimental::Feature::CxxModuleCMakeApi);
+
+ if (supportCxx20FileSetTypes) {
+ if (type != "HEADERS"_s && type != "CXX_MODULES"_s &&
+ type != "CXX_MODULE_HEADER_UNITS"_s) {
+ this->SetError(
+ R"(File set TYPE may only be "HEADERS", "CXX_MODULES", or "CXX_MODULE_HEADER_UNITS")");
+ return false;
+ }
+
+ if (cmFileSetVisibilityIsForInterface(visibility) &&
+ !cmFileSetVisibilityIsForSelf(visibility) &&
+ !this->Target->IsImported()) {
+ if (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s) {
+ this->SetError(
+ R"(File set TYPEs "CXX_MODULES" and "CXX_MODULE_HEADER_UNITS" may not have "INTERFACE" visibility)");
+ return false;
+ }
+ }
+ } else {
+ if (type != "HEADERS"_s) {
+ this->SetError("File set TYPE may only be \"HEADERS\"");
+ return false;
+ }
}
if (args.BaseDirs.empty()) {
@@ -294,7 +318,7 @@ bool TargetSourcesImpl::HandleOneFileSet(
if (!baseDirectories.empty()) {
fileSet.first->AddDirectoryEntry(
BT<std::string>(baseDirectories, this->Makefile->GetBacktrace()));
- if (type == "HEADERS"_s) {
+ if (type == "HEADERS"_s || type == "CXX_MODULE_HEADER_UNITS"_s) {
for (auto const& dir : cmExpandedList(baseDirectories)) {
auto interfaceDirectoriesGenex =
cmStrCat("$<BUILD_INTERFACE:", dir, ">");
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index c82ac64..4cd0adc 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -42,6 +42,8 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
this->RunResultVariable.clear();
this->OutputVariable.clear();
this->RunOutputVariable.clear();
+ this->RunOutputStdOutVariable.clear();
+ this->RunOutputStdErrVariable.clear();
this->CompileOutputVariable.clear();
std::string runArgs;
@@ -76,6 +78,22 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
}
i++;
this->RunOutputVariable = argv[i];
+ } else if (argv[i] == "RUN_OUTPUT_STDOUT_VARIABLE") {
+ if (argv.size() <= (i + 1)) {
+ cmSystemTools::Error(
+ "RUN_OUTPUT_STDOUT_VARIABLE specified but there is no variable");
+ return false;
+ }
+ i++;
+ this->RunOutputStdOutVariable = argv[i];
+ } else if (argv[i] == "RUN_OUTPUT_STDERR_VARIABLE") {
+ if (argv.size() <= (i + 1)) {
+ cmSystemTools::Error(
+ "RUN_OUTPUT_STDERR_VARIABLE specified but there is no variable");
+ return false;
+ }
+ i++;
+ this->RunOutputStdErrVariable = argv[i];
} else if (argv[i] == "COMPILE_OUTPUT_VARIABLE") {
if (argv.size() <= (i + 1)) {
cmSystemTools::Error(
@@ -102,11 +120,27 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
// using OUTPUT_VARIABLE makes crosscompiling harder
if (!this->OutputVariable.empty() &&
(!this->RunOutputVariable.empty() ||
- !this->CompileOutputVariable.empty())) {
+ !this->CompileOutputVariable.empty() ||
+ !this->RunOutputStdOutVariable.empty() ||
+ !this->RunOutputStdErrVariable.empty())) {
cmSystemTools::Error(
"You cannot use OUTPUT_VARIABLE together with COMPILE_OUTPUT_VARIABLE "
- "or RUN_OUTPUT_VARIABLE. Please use only COMPILE_OUTPUT_VARIABLE and/or "
- "RUN_OUTPUT_VARIABLE.");
+ ", RUN_OUTPUT_VARIABLE, RUN_OUTPUT_STDOUT_VARIABLE or "
+ "RUN_OUTPUT_STDERR_VARIABLE. "
+ "Please use only COMPILE_OUTPUT_VARIABLE, RUN_OUTPUT_VARIABLE, "
+ "RUN_OUTPUT_STDOUT_VARIABLE "
+ "and/or RUN_OUTPUT_STDERR_VARIABLE.");
+ return false;
+ }
+
+ if ((!this->RunOutputStdOutVariable.empty() ||
+ !RunOutputStdErrVariable.empty()) &&
+ !this->RunOutputVariable.empty()) {
+ cmSystemTools::Error(
+ "You cannot use RUN_OUTPUT_STDOUT_VARIABLE or "
+ "RUN_OUTPUT_STDERR_VARIABLE together "
+ "with RUN_OUTPUT_VARIABLE. Please use only COMPILE_OUTPUT_VARIABLE or "
+ "RUN_OUTPUT_STDOUT_VARIABLE and/or RUN_OUTPUT_STDERR_VARIABLE.");
return false;
}
@@ -119,6 +153,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
}
bool captureRunOutput = false;
+ bool captureRunOutputStdOutErr = false;
if (!this->OutputVariable.empty()) {
captureRunOutput = true;
tryCompile.emplace_back("OUTPUT_VARIABLE");
@@ -128,7 +163,10 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
tryCompile.emplace_back("OUTPUT_VARIABLE");
tryCompile.push_back(this->CompileOutputVariable);
}
- if (!this->RunOutputVariable.empty()) {
+ if (!this->RunOutputStdOutVariable.empty() ||
+ !RunOutputStdErrVariable.empty()) {
+ captureRunOutputStdOutErr = true;
+ } else if (!this->RunOutputVariable.empty()) {
captureRunOutput = true;
}
@@ -145,12 +183,27 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
} else {
// "run" it and capture the output
std::string runOutputContents;
+ std::string runOutputStdOutContents;
+ std::string runOutputStdErrContents;
if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING") &&
!this->Makefile->IsDefinitionSet("CMAKE_CROSSCOMPILING_EMULATOR")) {
this->DoNotRunExecutable(
- runArgs, argv[3], captureRunOutput ? &runOutputContents : nullptr);
+ runArgs, argv[3], captureRunOutput ? &runOutputContents : nullptr,
+ captureRunOutputStdOutErr && !RunOutputStdOutVariable.empty()
+ ? &runOutputStdOutContents
+ : nullptr,
+ captureRunOutputStdOutErr && !RunOutputStdErrVariable.empty()
+ ? &runOutputStdErrContents
+ : nullptr);
} else {
- this->RunExecutable(runArgs, &runOutputContents);
+ this->RunExecutable(
+ runArgs, captureRunOutput ? &runOutputContents : nullptr,
+ captureRunOutputStdOutErr && !RunOutputStdOutVariable.empty()
+ ? &runOutputStdOutContents
+ : nullptr,
+ captureRunOutputStdOutErr && !RunOutputStdErrVariable.empty()
+ ? &runOutputStdErrContents
+ : nullptr);
}
// now put the output into the variables
@@ -158,6 +211,14 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
this->Makefile->AddDefinition(this->RunOutputVariable,
runOutputContents);
}
+ if (!this->RunOutputStdOutVariable.empty()) {
+ this->Makefile->AddDefinition(this->RunOutputStdOutVariable,
+ runOutputStdOutContents);
+ }
+ if (!this->RunOutputStdErrVariable.empty()) {
+ this->Makefile->AddDefinition(this->RunOutputStdErrVariable,
+ runOutputStdErrContents);
+ }
if (!this->OutputVariable.empty()) {
// if the TryCompileCore saved output in this outputVariable then
@@ -180,7 +241,8 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
}
void cmTryRunCommand::RunExecutable(const std::string& runArgs,
- std::string* out)
+ std::string* out, std::string* stdOut,
+ std::string* stdErr)
{
int retVal = -1;
@@ -204,7 +266,8 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
finalCommand += runArgs;
}
bool worked = cmSystemTools::RunSingleCommand(
- finalCommand, out, out, &retVal,
+ finalCommand, stdOut || stdErr ? stdOut : out,
+ stdOut || stdErr ? stdErr : out, &retVal,
this->WorkingDirectory.empty() ? nullptr : this->WorkingDirectory.c_str(),
cmSystemTools::OUTPUT_NONE, cmDuration::zero());
// set the run var
@@ -227,7 +290,8 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
*/
void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
const std::string& srcFile,
- std::string* out)
+ std::string* out, std::string* stdOut,
+ std::string* stdErr)
{
// copy the executable out of the CMakeFiles/ directory, so it is not
// removed at the end of try_run() and the user can run it manually
@@ -246,6 +310,10 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
std::string internalRunOutputName =
this->RunResultVariable + "__TRYRUN_OUTPUT";
+ std::string internalRunOutputStdOutName =
+ this->RunResultVariable + "__TRYRUN_OUTPUT_STDOUT";
+ std::string internalRunOutputStdErrName =
+ this->RunResultVariable + "__TRYRUN_OUTPUT_STDERR";
bool error = false;
if (!this->Makefile->GetDefinition(this->RunResultVariable)) {
@@ -269,7 +337,51 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
}
// is the output from the executable used ?
- if (out) {
+ if (stdOut || stdErr) {
+ if (!this->Makefile->GetDefinition(internalRunOutputStdOutName)) {
+ // if the variables doesn't exist, create it with a helpful error text
+ // and mark it as advanced
+ std::string comment = cmStrCat(
+ "Output of try_run(), contains the text, which the executable "
+ "would have printed on stdout on its target platform.\n",
+ detailsString);
+
+ this->Makefile->AddCacheDefinition(
+ internalRunOutputStdOutName, "PLEASE_FILL_OUT-NOTFOUND",
+ comment.c_str(), cmStateEnums::STRING);
+ cmState* state = this->Makefile->GetState();
+ cmValue existing =
+ state->GetCacheEntryValue(internalRunOutputStdOutName);
+ if (existing) {
+ state->SetCacheEntryProperty(internalRunOutputStdOutName, "ADVANCED",
+ "1");
+ }
+
+ error = true;
+ }
+
+ if (!this->Makefile->GetDefinition(internalRunOutputStdErrName)) {
+ // if the variables doesn't exist, create it with a helpful error text
+ // and mark it as advanced
+ std::string comment = cmStrCat(
+ "Output of try_run(), contains the text, which the executable "
+ "would have printed on stderr on its target platform.\n",
+ detailsString);
+
+ this->Makefile->AddCacheDefinition(
+ internalRunOutputStdErrName, "PLEASE_FILL_OUT-NOTFOUND",
+ comment.c_str(), cmStateEnums::STRING);
+ cmState* state = this->Makefile->GetState();
+ cmValue existing =
+ state->GetCacheEntryValue(internalRunOutputStdErrName);
+ if (existing) {
+ state->SetCacheEntryProperty(internalRunOutputStdErrName, "ADVANCED",
+ "1");
+ }
+
+ error = true;
+ }
+ } else if (out) {
if (!this->Makefile->GetDefinition(internalRunOutputName)) {
// if the variables doesn't exist, create it with a helpful error text
// and mark it as advanced
@@ -317,7 +429,34 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
" to\n"
" the exit code (in many cases 0 for success), otherwise "
"enter \"FAILED_TO_RUN\".\n");
- if (out) {
+ if (stdOut || stdErr) {
+ if (stdOut) {
+ comment += internalRunOutputStdOutName;
+ comment +=
+ "\n contains the text the executable "
+ "would have printed on stdout.\n"
+ " If the executable would not have been able to run, set ";
+ comment += internalRunOutputStdOutName;
+ comment += " empty.\n"
+ " Otherwise check if the output is evaluated by the "
+ "calling CMake code. If so,\n"
+ " check what the source file would have printed when "
+ "called with the given arguments.\n";
+ }
+ if (stdErr) {
+ comment += internalRunOutputStdErrName;
+ comment +=
+ "\n contains the text the executable "
+ "would have printed on stderr.\n"
+ " If the executable would not have been able to run, set ";
+ comment += internalRunOutputStdErrName;
+ comment += " empty.\n"
+ " Otherwise check if the output is evaluated by the "
+ "calling CMake code. If so,\n"
+ " check what the source file would have printed when "
+ "called with the given arguments.\n";
+ }
+ } else if (out) {
comment += internalRunOutputName;
comment +=
"\n contains the text the executable "
@@ -330,6 +469,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
" check what the source file would have printed when "
"called with the given arguments.\n";
}
+
comment += "The ";
comment += this->CompileResultVariable;
comment += " variable holds the build result for this try_run().\n\n"
@@ -370,7 +510,14 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
return;
}
- if (out) {
+ if (stdOut || stdErr) {
+ if (stdOut) {
+ (*stdOut) = *this->Makefile->GetDefinition(internalRunOutputStdOutName);
+ }
+ if (stdErr) {
+ (*stdErr) = *this->Makefile->GetDefinition(internalRunOutputStdErrName);
+ }
+ } else if (out) {
(*out) = *this->Makefile->GetDefinition(internalRunOutputName);
}
}
diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h
index d45acd8..ccf678e 100644
--- a/Source/cmTryRunCommand.h
+++ b/Source/cmTryRunCommand.h
@@ -39,15 +39,21 @@ public:
private:
void RunExecutable(const std::string& runArgs,
- std::string* runOutputContents);
+ std::string* runOutputContents,
+ std::string* runOutputStdOutContents,
+ std::string* runOutputStdErrContents);
void DoNotRunExecutable(const std::string& runArgs,
const std::string& srcFile,
- std::string* runOutputContents);
+ std::string* runOutputContents,
+ std::string* runOutputStdOutContents,
+ std::string* runOutputStdErrContents);
std::string CompileResultVariable;
std::string RunResultVariable;
std::string OutputVariable;
std::string RunOutputVariable;
+ std::string RunOutputStdOutVariable;
+ std::string RunOutputStdErrVariable;
std::string CompileOutputVariable;
std::string WorkingDirectory;
};
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index c79331c..2356869 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -347,6 +347,18 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString(
void cmVisualStudio10TargetGenerator::Generate()
{
+ for (std::string const& config : this->Configurations) {
+ this->GeneratorTarget->CheckCxxModuleStatus(config);
+ }
+
+ if (this->GeneratorTarget->HaveCxx20ModuleSources()) {
+ this->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("The \"", this->GeneratorTarget->GetName(),
+ "\" target contains C++ module sources which are not supported "
+ "by the generator"));
+ }
+
this->ProjectType = this->ComputeProjectType(this->GeneratorTarget);
this->Managed = this->ProjectType == VsProjectType::csproj;
const std::string ProjectFileExtension =
@@ -952,6 +964,10 @@ void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile(
std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
ConvertToWindowsSlash(outDir);
e1.Element("OutputPath", outDir);
+
+ Options& o = *(this->ClOptions[config]);
+ OptionsHelper oh(o, e1);
+ oh.OutputFlagMap();
}
this->WriteDotNetDocumentationFile(e0);
@@ -2914,7 +2930,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
Elem& e0)
{
cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType();
- if (ttype > cmStateEnums::GLOBAL_TARGET) {
+ if (ttype > cmStateEnums::INTERFACE_LIBRARY) {
return;
}
if (this->ProjectType == VsProjectType::csproj) {
@@ -3852,21 +3868,28 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
this->GeneratorTarget->GetLinkOptions(linkOpts, configName, "CUDA");
// LINK_OPTIONS are escaped.
this->LocalGenerator->AppendCompileOptions(linkFlags, linkOpts);
+
+ cmComputeLinkInformation* pcli =
+ this->GeneratorTarget->GetLinkInformation(configName);
+ if (doDeviceLinking && pcli) {
+
+ cmLinkLineDeviceComputer computer(
+ this->LocalGenerator,
+ this->LocalGenerator->GetStateSnapshot().GetDirectory());
+ std::string ignored_;
+ this->LocalGenerator->GetDeviceLinkFlags(computer, configName, ignored_,
+ linkFlags, ignored_, ignored_,
+ this->GeneratorTarget);
+
+ this->LocalGenerator->AddLanguageFlagsForLinking(
+ linkFlags, this->GeneratorTarget, "CUDA", configName);
+ }
cudaLinkOptions.AppendFlagString("AdditionalOptions", linkFlags);
// For static libraries that have device linking enabled compute
// the libraries
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY &&
doDeviceLinking) {
- cmComputeLinkInformation* pcli =
- this->GeneratorTarget->GetLinkInformation(configName);
- if (!pcli) {
- cmSystemTools::Error(
- "CMake can not compute cmComputeLinkInformation for target: " +
- this->Name);
- return false;
- }
-
cmComputeLinkInformation& cli = *pcli;
cmLinkLineDeviceComputer computer(
this->LocalGenerator,
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 00c65ed..16584f5 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -161,71 +161,12 @@ bool cmVisualStudioGeneratorOptions::UsingSBCS() const
void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
{
- // Extract temporary values stored by our flag table.
- FlagValue arch = this->TakeFlag("cmake-temp-arch");
- FlagValue code = this->TakeFlag("cmake-temp-code");
- FlagValue gencode = this->TakeFlag("cmake-temp-gencode");
-
- // No -code allowed without -arch.
- if (arch.empty()) {
- code.clear();
- }
-
- // Create a CodeGeneration field with [arch],[code] syntax in each entry.
- // CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`.
- FlagValue& result = this->FlagMap["CodeGeneration"];
-
- // If there are no flags, leave the CodeGeneration field empty.
- if (arch.empty() && gencode.empty()) {
- return;
- }
-
- // First entries for the -arch=<arch> [-code=<code>,...] pair.
- if (!arch.empty()) {
- std::string arch_name = arch[0];
- if (arch_name == "all" || arch_name == "all-major" ||
- arch_name == "native") {
- AppendFlagString("AdditionalOptions", "-arch=" + arch_name);
- return;
- }
- std::vector<std::string> codes;
- if (!code.empty()) {
- codes = cmTokenize(code[0], ",");
- }
- if (codes.empty()) {
- codes.push_back(arch_name);
- // nvcc -arch=<arch> has a special case that allows a real
- // architecture to be specified instead of a virtual arch.
- // It translates to -arch=<virtual> -code=<real>.
- cmSystemTools::ReplaceString(arch_name, "sm_", "compute_");
- }
- for (std::string const& c : codes) {
- std::string entry = arch_name + "," + c;
- result.push_back(entry);
- }
- }
-
- // Now add entries for the following signatures:
- // -gencode=<arch>,<code>
- // -gencode=<arch>,[<code1>,<code2>]
- // -gencode=<arch>,"<code1>,<code2>"
- for (std::string const& e : gencode) {
- std::string entry = e;
- cmSystemTools::ReplaceString(entry, "arch=", "");
- cmSystemTools::ReplaceString(entry, "code=", "");
- cmSystemTools::ReplaceString(entry, "[", "");
- cmSystemTools::ReplaceString(entry, "]", "");
- cmSystemTools::ReplaceString(entry, "\"", "");
-
- std::vector<std::string> codes = cmTokenize(entry, ",");
- if (codes.size() >= 2) {
- auto gencode_arch = cm::cbegin(codes);
- for (auto ci = gencode_arch + 1; ci != cm::cend(codes); ++ci) {
- std::string code_entry = *gencode_arch + "," + *ci;
- result.push_back(code_entry);
- }
- }
- }
+ // Create an empty CodeGeneration field, and pass the the actual
+ // compile flags via additional options so that we have consistent
+ // behavior and avoid issues with MSBuild extensions injecting
+ // virtual code when we request real only.
+ FlagValue& code_gen_flag = this->FlagMap["CodeGeneration"];
+ code_gen_flag = "";
}
void cmVisualStudioGeneratorOptions::FixManifestUACFlags()
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
index adc500a..a62015f 100644
--- a/Source/cmXCodeScheme.cxx
+++ b/Source/cmXCodeScheme.cxx
@@ -147,7 +147,15 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
"Xcode.DebuggerFoundation.Debugger.LLDB");
xout.Attribute("selectedLauncherIdentifier",
"Xcode.DebuggerFoundation.Launcher.LLDB");
- xout.Attribute("launchStyle", "0");
+ {
+ cmValue launchMode =
+ this->Target->GetTarget()->GetProperty("XCODE_SCHEME_LAUNCH_MODE");
+ std::string value = "0"; // == 'AUTO'
+ if (launchMode && *launchMode == "WAIT") {
+ value = "1";
+ }
+ xout.Attribute("launchStyle", value);
+ }
WriteCustomWorkingDirectory(xout, configuration);
xout.Attribute("ignoresPersistentStateOnLaunch", "NO");
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index e6fa219..efb2520 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -3,6 +3,7 @@
#include "cmake.h"
#include <algorithm>
+#include <array>
#include <cstdio>
#include <cstdlib>
#include <cstring>
@@ -955,7 +956,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
CommandArgument::Values::One,
[](std::string const& value, cmake* state) -> bool {
const auto logLevel = StringToLogLevel(value);
- if (logLevel == LogLevel::LOG_UNDEFINED) {
+ if (logLevel == Message::LogLevel::LOG_UNDEFINED) {
cmSystemTools::Error(
"Invalid level specified for --log-level");
return false;
@@ -971,7 +972,7 @@ void cmake::SetArgs(const std::vector<std::string>& args)
CommandArgument::Values::One,
[](std::string const& value, cmake* state) -> bool {
const auto logLevel = StringToLogLevel(value);
- if (logLevel == LogLevel::LOG_UNDEFINED) {
+ if (logLevel == Message::LogLevel::LOG_UNDEFINED) {
cmSystemTools::Error(
"Invalid level specified for --loglevel");
return false;
@@ -1402,23 +1403,52 @@ void cmake::SetArgs(const std::vector<std::string>& args)
#endif
}
-cmake::LogLevel cmake::StringToLogLevel(const std::string& levelStr)
-{
- using LevelsPair = std::pair<std::string, LogLevel>;
- static const std::vector<LevelsPair> levels = {
- { "error", LogLevel::LOG_ERROR }, { "warning", LogLevel::LOG_WARNING },
- { "notice", LogLevel::LOG_NOTICE }, { "status", LogLevel::LOG_STATUS },
- { "verbose", LogLevel::LOG_VERBOSE }, { "debug", LogLevel::LOG_DEBUG },
- { "trace", LogLevel::LOG_TRACE }
+namespace {
+using LevelsPair = std::pair<cm::string_view, Message::LogLevel>;
+using LevelsPairArray = std::array<LevelsPair, 7>;
+const LevelsPairArray& getStringToLogLevelPairs()
+{
+ static const LevelsPairArray levels = {
+ { { "error", Message::LogLevel::LOG_ERROR },
+ { "warning", Message::LogLevel::LOG_WARNING },
+ { "notice", Message::LogLevel::LOG_NOTICE },
+ { "status", Message::LogLevel::LOG_STATUS },
+ { "verbose", Message::LogLevel::LOG_VERBOSE },
+ { "debug", Message::LogLevel::LOG_DEBUG },
+ { "trace", Message::LogLevel::LOG_TRACE } }
};
+ return levels;
+}
+} // namespace
+
+Message::LogLevel cmake::StringToLogLevel(cm::string_view levelStr)
+{
+ const LevelsPairArray& levels = getStringToLogLevelPairs();
- const auto levelStrLowCase = cmSystemTools::LowerCase(levelStr);
+ const auto levelStrLowCase =
+ cmSystemTools::LowerCase(std::string{ levelStr });
+ // NOLINTNEXTLINE(readability-qualified-auto)
const auto it = std::find_if(levels.cbegin(), levels.cend(),
[&levelStrLowCase](const LevelsPair& p) {
return p.first == levelStrLowCase;
});
- return (it != levels.cend()) ? it->second : LogLevel::LOG_UNDEFINED;
+ return (it != levels.cend()) ? it->second : Message::LogLevel::LOG_UNDEFINED;
+}
+
+std::string cmake::LogLevelToString(Message::LogLevel level)
+{
+ const LevelsPairArray& levels = getStringToLogLevelPairs();
+
+ // NOLINTNEXTLINE(readability-qualified-auto)
+ const auto it =
+ std::find_if(levels.cbegin(), levels.cend(),
+ [&level](const LevelsPair& p) { return p.second == level; });
+ const cm::string_view levelStrLowerCase =
+ (it != levels.cend()) ? it->first : "undefined";
+ std::string levelStrUpperCase =
+ cmSystemTools::UpperCase(std::string{ levelStrLowerCase });
+ return levelStrUpperCase;
}
cmake::TraceFormat cmake::StringToTraceFormat(const std::string& traceStr)
diff --git a/Source/cmake.h b/Source/cmake.h
index 3c6af17..a631647 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -119,19 +119,6 @@ public:
FIND_PACKAGE_MODE
};
- /** \brief Define log level constants. */
- enum LogLevel
- {
- LOG_UNDEFINED,
- LOG_ERROR,
- LOG_WARNING,
- LOG_NOTICE,
- LOG_STATUS,
- LOG_VERBOSE,
- LOG_DEBUG,
- LOG_TRACE
- };
-
/** \brief Define supported trace formats **/
enum TraceFormat
{
@@ -469,9 +456,10 @@ public:
bool WasLogLevelSetViaCLI() const { return this->LogLevelWasSetViaCLI; }
//! Get the selected log level for `message()` commands during the cmake run.
- LogLevel GetLogLevel() const { return this->MessageLogLevel; }
- void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; }
- static LogLevel StringToLogLevel(const std::string& levelStr);
+ Message::LogLevel GetLogLevel() const { return this->MessageLogLevel; }
+ void SetLogLevel(Message::LogLevel level) { this->MessageLogLevel = level; }
+ static Message::LogLevel StringToLogLevel(cm::string_view levelStr);
+ static std::string LogLevelToString(Message::LogLevel level);
static TraceFormat StringToTraceFormat(const std::string& levelStr);
bool HasCheckInProgress() const
@@ -732,7 +720,7 @@ private:
std::set<std::string> DebugFindPkgs;
std::set<std::string> DebugFindVars;
- LogLevel MessageLogLevel = LogLevel::LOG_STATUS;
+ Message::LogLevel MessageLogLevel = Message::LogLevel::LOG_STATUS;
bool LogLevelWasSetViaCLI = false;
bool LogContext = false;
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 5889a4b..89a3cc7 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -3067,17 +3067,14 @@ std::string SystemTools::GetRealPath(const std::string& path,
return ret;
}
-bool SystemTools::FileIsDirectory(const std::string& inName)
+// Remove any trailing slash from the name except in a root component.
+static const char* RemoveTrailingSlashes(
+ const std::string& inName, char (&local_buffer)[KWSYS_SYSTEMTOOLS_MAXPATH],
+ std::string& string_buffer)
{
- if (inName.empty()) {
- return false;
- }
size_t length = inName.size();
const char* name = inName.c_str();
- // Remove any trailing slash from the name except in a root component.
- char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
- std::string string_buffer;
size_t last = length - 1;
if (last > 0 && (name[last] == '/' || name[last] == '\\') &&
strcmp(name, "/") != 0 && name[last - 1] != ':') {
@@ -3091,6 +3088,19 @@ bool SystemTools::FileIsDirectory(const std::string& inName)
}
}
+ return name;
+}
+
+bool SystemTools::FileIsDirectory(const std::string& inName)
+{
+ if (inName.empty()) {
+ return false;
+ }
+
+ char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
+ std::string string_buffer;
+ const auto name = RemoveTrailingSlashes(inName, local_buffer, string_buffer);
+
// Now check the file node type.
#if defined(_WIN32)
DWORD attr =
@@ -3107,9 +3117,21 @@ bool SystemTools::FileIsDirectory(const std::string& inName)
}
}
-bool SystemTools::FileIsExecutable(const std::string& name)
+bool SystemTools::FileIsExecutable(const std::string& inName)
{
- return !FileIsDirectory(name) && TestFileAccess(name, TEST_FILE_EXECUTE);
+#ifdef _WIN32
+ char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
+ std::string string_buffer;
+ const auto name = RemoveTrailingSlashes(inName, local_buffer, string_buffer);
+ const auto attr =
+ GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str());
+
+ // On Windows any file that exists and is not a directory is considered
+ // readable and therefore also executable:
+ return attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY);
+#else
+ return !FileIsDirectory(inName) && TestFileAccess(inName, TEST_FILE_EXECUTE);
+#endif
}
#if defined(_WIN32)
diff --git a/Templates/MSBuild/FlagTables/v10_Cuda.json b/Templates/MSBuild/FlagTables/v10_Cuda.json
index b3230ac..b0765f5 100644
--- a/Templates/MSBuild/FlagTables/v10_Cuda.json
+++ b/Templates/MSBuild/FlagTables/v10_Cuda.json
@@ -70,118 +70,6 @@
]
},
{
- "name": "cmake-temp-gencode",
- "switch": "gencode=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue",
- "SemicolonAppendable"
- ]
- },
- {
- "name": "cmake-temp-gencode",
- "switch": "gencode",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing",
- "SemicolonAppendable"
- ]
- },
- {
- "name": "cmake-temp-gencode",
- "switch": "-generate-code=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue",
- "SemicolonAppendable"
- ]
- },
- {
- "name": "cmake-temp-gencode",
- "switch": "-generate-code",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing",
- "SemicolonAppendable"
- ]
- },
- {
- "name": "cmake-temp-code",
- "switch": "code=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
- "name": "cmake-temp-code",
- "switch": "code",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing"
- ]
- },
- {
- "name": "cmake-temp-code",
- "switch": "-gpu-code=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
- "name": "cmake-temp-code",
- "switch": "-gpu-code",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing"
- ]
- },
- {
- "name": "cmake-temp-arch",
- "switch": "arch=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
- "name": "cmake-temp-arch",
- "switch": "arch",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing"
- ]
- },
- {
- "name": "cmake-temp-arch",
- "switch": "-gpu-architecture=",
- "comment": "",
- "value": "",
- "flags": [
- "UserValue"
- ]
- },
- {
- "name": "cmake-temp-arch",
- "switch": "-gpu-architecture",
- "comment": "",
- "value": "",
- "flags": [
- "UserFollowing"
- ]
- },
- {
"name": "FastMath",
"switch": "use_fast_math",
"comment": "",
diff --git a/Tests/Assembler/CMakeLists.txt b/Tests/Assembler/CMakeLists.txt
index 1b7e57d..8f6b355 100644
--- a/Tests/Assembler/CMakeLists.txt
+++ b/Tests/Assembler/CMakeLists.txt
@@ -24,6 +24,12 @@ if("${CMAKE_GENERATOR}" MATCHES "Makefile|Xcode|Ninja" AND
elseif("${CMAKE_SYSTEM_NAME};${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "Darwin;arm64")
list(APPEND C_FLAGS -arch arm64)
endif()
+ if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ # Just in case the user is passing -flto, we need to pass -fno-lto to
+ # clang when generating the assembly file, or else clang will generate
+ # LLVM IR instead of assembly.
+ list(APPEND C_FLAGS -fno-lto)
+ endif()
# Clang on OS X, and perhaps other compilers, do not support -g
# for both generating and assembling, so drop it from generating.
list(REMOVE_ITEM C_FLAGS -g)
diff --git a/Tests/CMakeLib/testArgumentParser.cxx b/Tests/CMakeLib/testArgumentParser.cxx
index 965690c..ecfc5fc 100644
--- a/Tests/CMakeLib/testArgumentParser.cxx
+++ b/Tests/CMakeLib/testArgumentParser.cxx
@@ -6,10 +6,12 @@
#include <string>
#include <vector>
+#include <cm/optional>
#include <cm/string_view>
#include <cmext/string_view>
#include "cmArgumentParser.h"
+#include "cmArgumentParserTypes.h"
namespace {
@@ -19,39 +21,54 @@ struct Result
bool Option2 = false;
std::string String1;
- std::string String2;
+ cm::optional<std::string> String2;
+ cm::optional<std::string> String3;
+ ArgumentParser::Maybe<std::string> String4;
- std::vector<std::string> List1;
- std::vector<std::string> List2;
- std::vector<std::string> List3;
+ ArgumentParser::NonEmpty<std::vector<std::string>> List1;
+ ArgumentParser::NonEmpty<std::vector<std::string>> List2;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> List3;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> List4;
+ cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> List5;
+ cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> List6;
std::vector<std::vector<std::string>> Multi1;
std::vector<std::vector<std::string>> Multi2;
- std::vector<std::vector<std::string>> Multi3;
+ cm::optional<std::vector<std::vector<std::string>>> Multi3;
+ cm::optional<std::vector<std::vector<std::string>>> Multi4;
};
std::initializer_list<cm::string_view> const args = {
/* clang-format off */
"OPTION_1", // option
+ // "OPTION_2", // option that is not present
"STRING_1", // string arg missing value
- "STRING_2", "foo", "bar", // string arg + unparsed value
+ "STRING_2", "foo", "bar", // string arg + unparsed value, presence captured
+ // "STRING_3", // string arg that is not present
+ "STRING_4", // string arg allowed to be missing value
"LIST_1", // list arg missing values
"LIST_2", "foo", "bar", // list arg with 2 elems
"LIST_3", "bar", // list arg ...
"LIST_3", "foo", // ... with continuation
+ "LIST_4", // list arg missing values, presence captured
+ // "LIST_5", // list arg that is not present
+ "LIST_6", // list arg allowed to be empty
"MULTI_2", // multi list with 0 lists
"MULTI_3", "foo", "bar", // multi list with first list with two elems
"MULTI_3", "bar", "foo", // multi list with second list with two elems
+ // "MULTI_4", // multi list arg that is not present
/* clang-format on */
};
bool verifyResult(Result const& result,
std::vector<std::string> const& unparsedArguments,
- std::vector<std::string> const& keywordsMissingValue)
+ std::vector<cm::string_view> const& keywordsMissingValue)
{
static std::vector<std::string> const foobar = { "foo", "bar" };
static std::vector<std::string> const barfoo = { "bar", "foo" };
- static std::vector<std::string> const missing = { "STRING_1", "LIST_1" };
+ static std::vector<cm::string_view> const missing = { "STRING_1"_s,
+ "LIST_1"_s,
+ "LIST_4"_s };
#define ASSERT_TRUE(x) \
do { \
@@ -65,18 +82,29 @@ bool verifyResult(Result const& result,
ASSERT_TRUE(!result.Option2);
ASSERT_TRUE(result.String1.empty());
- ASSERT_TRUE(result.String2 == "foo");
+ ASSERT_TRUE(result.String2);
+ ASSERT_TRUE(*result.String2 == "foo");
+ ASSERT_TRUE(!result.String3);
+ ASSERT_TRUE(result.String4.empty());
ASSERT_TRUE(result.List1.empty());
ASSERT_TRUE(result.List2 == foobar);
- ASSERT_TRUE(result.List3 == barfoo);
+ ASSERT_TRUE(result.List3);
+ ASSERT_TRUE(*result.List3 == barfoo);
+ ASSERT_TRUE(result.List4);
+ ASSERT_TRUE(result.List4->empty());
+ ASSERT_TRUE(!result.List5);
+ ASSERT_TRUE(result.List6);
+ ASSERT_TRUE(result.List6->empty());
ASSERT_TRUE(result.Multi1.empty());
ASSERT_TRUE(result.Multi2.size() == 1);
ASSERT_TRUE(result.Multi2[0].empty());
- ASSERT_TRUE(result.Multi3.size() == 2);
- ASSERT_TRUE(result.Multi3[0] == foobar);
- ASSERT_TRUE(result.Multi3[1] == barfoo);
+ ASSERT_TRUE(result.Multi3);
+ ASSERT_TRUE((*result.Multi3).size() == 2);
+ ASSERT_TRUE((*result.Multi3)[0] == foobar);
+ ASSERT_TRUE((*result.Multi3)[1] == barfoo);
+ ASSERT_TRUE(!result.Multi4);
ASSERT_TRUE(unparsedArguments.size() == 1);
ASSERT_TRUE(unparsedArguments[0] == "bar");
@@ -89,19 +117,25 @@ bool testArgumentParserDynamic()
{
Result result;
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
+ std::vector<cm::string_view> keywordsMissingValue;
cmArgumentParser<void>{}
.Bind("OPTION_1"_s, result.Option1)
.Bind("OPTION_2"_s, result.Option2)
.Bind("STRING_1"_s, result.String1)
.Bind("STRING_2"_s, result.String2)
+ .Bind("STRING_3"_s, result.String3)
+ .Bind("STRING_4"_s, result.String4)
.Bind("LIST_1"_s, result.List1)
.Bind("LIST_2"_s, result.List2)
.Bind("LIST_3"_s, result.List3)
+ .Bind("LIST_4"_s, result.List4)
+ .Bind("LIST_5"_s, result.List5)
+ .Bind("LIST_6"_s, result.List6)
.Bind("MULTI_1"_s, result.Multi1)
.Bind("MULTI_2"_s, result.Multi2)
.Bind("MULTI_3"_s, result.Multi3)
+ .Bind("MULTI_4"_s, result.Multi4)
.Parse(args, &unparsedArguments, &keywordsMissingValue);
return verifyResult(result, unparsedArguments, keywordsMissingValue);
@@ -115,15 +149,21 @@ bool testArgumentParserStatic()
.Bind("OPTION_2"_s, &Result::Option2)
.Bind("STRING_1"_s, &Result::String1)
.Bind("STRING_2"_s, &Result::String2)
+ .Bind("STRING_3"_s, &Result::String3)
+ .Bind("STRING_4"_s, &Result::String4)
.Bind("LIST_1"_s, &Result::List1)
.Bind("LIST_2"_s, &Result::List2)
.Bind("LIST_3"_s, &Result::List3)
+ .Bind("LIST_4"_s, &Result::List4)
+ .Bind("LIST_5"_s, &Result::List5)
+ .Bind("LIST_6"_s, &Result::List6)
.Bind("MULTI_1"_s, &Result::Multi1)
.Bind("MULTI_2"_s, &Result::Multi2)
- .Bind("MULTI_3"_s, &Result::Multi3);
+ .Bind("MULTI_3"_s, &Result::Multi3)
+ .Bind("MULTI_4"_s, &Result::Multi4);
std::vector<std::string> unparsedArguments;
- std::vector<std::string> keywordsMissingValue;
+ std::vector<cm::string_view> keywordsMissingValue;
Result const result =
parser.Parse(args, &unparsedArguments, &keywordsMissingValue);
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 24e98f4..a54b6b5 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -431,7 +431,7 @@ if(BUILD_TESTING)
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])")
ADD_TEST_MACRO(CSharpOnly CSharpOnly)
- if(NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ if(NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx)
ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx)
endif()
@@ -1056,8 +1056,11 @@ if(BUILD_TESTING)
endif()
endif()
if(NSIS_MAKENSIS_EXECUTABLE)
- set(CPackComponents_BUILD_OPTIONS ${CPackComponents_BUILD_OPTIONS}
- -DCPACK_BINARY_NSIS:BOOL=ON)
+ execute_process(COMMAND ${NSIS_MAKENSIS_EXECUTABLE} "-VERSION" ERROR_QUIET OUTPUT_QUIET RESULT_VARIABLE NSIS_OK)
+ if("${NSIS_OK}" STREQUAL "0")
+ set(CPackComponents_BUILD_OPTIONS ${CPackComponents_BUILD_OPTIONS}
+ -DCPACK_BINARY_NSIS:BOOL=ON)
+ endif()
endif()
add_test(CPackComponents ${CMAKE_CTEST_COMMAND}
@@ -1153,7 +1156,6 @@ if(BUILD_TESTING)
"components-source"
"components-shlibdeps1"
"components-depend1"
- "components-depend2"
"compression")
# Run additional tests if dpkg-shlibdeps is available (and is new enough version)
find_program(SHLIBDEPS_EXECUTABLE NAMES dpkg-shlibdeps)
@@ -1173,6 +1175,11 @@ if(BUILD_TESTING)
list(APPEND DEB_CONFIGURATIONS_TO_TEST "shlibdeps-with-private-lib-failure"
"shlibdeps-with-private-lib-success")
endif()
+ # Check if distro has symbols or shlibs data
+ file(GLOB SHLIBS_FILES_EXIST "/var/lib/dpkg/info/*.shlibs" "/var/lib/dpkg/info/*.symbols")
+ if(SHLIBS_FILES_EXIST)
+ list(APPEND DEB_CONFIGURATIONS_TO_TEST "components-depend2")
+ endif()
endif()
set(CPackGen "DEB")
@@ -1460,6 +1467,7 @@ if(BUILD_TESTING)
LTTngUST
ODBC
OpenACC
+ OpenAL
OpenCL
OpenGL
OpenMP
@@ -1734,7 +1742,7 @@ if(BUILD_TESTING)
if(NOT CMake_TEST_EXTERNAL_CMAKE)
foreach(STP RANGE 2 12)
- if (STP EQUAL 6)
+ if (STP EQUAL 7)
set(pass_regex ".*using log and exp")
else()
set(pass_regex "The square root of 25 is 5")
@@ -2115,7 +2123,7 @@ if(BUILD_TESTING)
if(MSVC AND NOT MSVC_VERSION LESS 1310
AND (NOT CMAKE_GENERATOR MATCHES "Visual Studio 9 "
OR CMAKE_SIZEOF_VOID_P EQUAL 4)
- AND (NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ AND (NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
)
ADD_TEST_MACRO(VSMASM VSMASM)
endif()
@@ -2127,7 +2135,7 @@ if(BUILD_TESTING)
if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio 9 "
AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v90"
- AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx)
ADD_TEST_MACRO(VSManagedCustomCommand)
endif()
@@ -2665,7 +2673,10 @@ if(BUILD_TESTING)
endif()
if(NOT DEFINED CMake_TEST_CTestUpdate_HG AND HG_EXECUTABLE
AND (UNIX OR NOT "${HG_EXECUTABLE}" MATCHES "cygwin"))
- set(CMake_TEST_CTestUpdate_HG 1)
+ execute_process(COMMAND "${HG_EXECUTABLE}" --version OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE HG_RV)
+ if(HG_RV EQUAL 0)
+ set(CMake_TEST_CTestUpdate_HG 1)
+ endif()
endif()
if(CMake_TEST_CTestUpdate_HG)
if(NOT HG_EXECUTABLE)
@@ -3367,56 +3378,70 @@ if(BUILD_TESTING)
set(JavaExportImport_BUILD_OPTIONS -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM})
ADD_TEST_MACRO(JavaExportImport JavaExportImport)
- get_filename_component(JNIPATH ${Java_JAVAC_EXECUTABLE} PATH)
+ get_filename_component(JAVACPATH ${Java_JAVAC_EXECUTABLE} REALPATH)
+ get_filename_component(JNIPATH ${JAVACPATH} PATH)
find_file(JNI_H jni.h
"${JNIPATH}/../include"
"${JNIPATH}/../java/include")
if(JNI_H AND EXISTS "${JNI_H}") # in case jni.h is a broken symlink
file(READ "${JNI_H}" JNI_FILE)
if("${JNI_FILE}" MATCHES "JDK1_2")
- add_test(NAME Java.Jar COMMAND ${CMAKE_CTEST_COMMAND}
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/Java"
- "${CMake_BINARY_DIR}/Tests/JavaJar"
- ${build_generator_args}
- --build-project hello
- --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJar/"
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
- list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJar")
- # For next tests, java tool must have same architecture as toolchain
- math(EXPR _object_mode "${CMAKE_SIZEOF_VOID_P} * 8")
execute_process(
COMMAND "${Java_JAVA_EXECUTABLE}" -version
OUTPUT_VARIABLE _version ERROR_VARIABLE _version RESULT_VARIABLE _result
)
- if(_result EQUAL 0 AND _version MATCHES "${_object_mode}-Bit")
- ## next test is valid only if Java version is less than 1.10
- if ("${Java_VERSION}" VERSION_LESS 1.10)
- add_test(NAME Java.Javah COMMAND ${CMAKE_CTEST_COMMAND}
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/JavaJavah"
- "${CMake_BINARY_DIR}/Tests/JavaJavah"
- ${build_generator_args}
- --build-project helloJavah
- --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJavah/"
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
- list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJavah")
+
+ # E2K has broken Java RVM before 3.5.2
+ if (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "e2k" AND _result EQUAL 0)
+ string(REGEX MATCH "RVM ([0-9.]+)" RVMVER "${_version}")
+ # Consider empty match a broken version too
+ if("${CMAKE_MATCH_1}" VERSION_LESS "3.5.2")
+ set(BROKEN_RVM TRUE)
endif()
- ## next test is valid only if Java is, at least, version 1.8
- if (NOT "${Java_VERSION}" VERSION_LESS 1.8)
- add_test(NAME Java.NativeHeaders COMMAND ${CMAKE_CTEST_COMMAND}
- --build-and-test
- "${CMake_SOURCE_DIR}/Tests/JavaNativeHeaders"
- "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders"
- ${build_generator_args}
- --build-project helloJavaNativeHeaders
- --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/"
- --build-target install
- --build-options
- "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/Install"
- --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
- list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders")
+ endif()
+
+ if(NOT BROKEN_RVM)
+ add_test(NAME Java.Jar COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/Java"
+ "${CMake_BINARY_DIR}/Tests/JavaJar"
+ ${build_generator_args}
+ --build-project hello
+ --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJar/"
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJar")
+
+ # For next tests, java tool must have same architecture as toolchain
+ math(EXPR _object_mode "${CMAKE_SIZEOF_VOID_P} * 8")
+ if(_result EQUAL 0 AND _version MATCHES "${_object_mode}-Bit")
+ ## next test is valid only if Java version is less than 1.10
+ if ("${Java_VERSION}" VERSION_LESS 1.10)
+ add_test(NAME Java.Javah COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/JavaJavah"
+ "${CMake_BINARY_DIR}/Tests/JavaJavah"
+ ${build_generator_args}
+ --build-project helloJavah
+ --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJavah/"
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJavah")
+ endif()
+ ## next test is valid only if Java is, at least, version 1.8
+ if (NOT "${Java_VERSION}" VERSION_LESS 1.8)
+ add_test(NAME Java.NativeHeaders COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/JavaNativeHeaders"
+ "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders"
+ ${build_generator_args}
+ --build-project helloJavaNativeHeaders
+ --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/"
+ --build-target install
+ --build-options
+ "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/Install"
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>)
+ list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders")
+ endif()
endif()
endif()
endif()
diff --git a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
index 49a4041..0907d03 100644
--- a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
+++ b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt
@@ -56,6 +56,15 @@ macro(check_version_string MODULE_NAME VERSION_VAR)
if (NOT _exclude_pos EQUAL -1)
message(STATUS "excluding check of ${VERSION_VAR}='${${VERSION_VAR}}' due to local configuration")
elseif (${MODULE_NAME}_FOUND)
+
+ unset(SKIP_CHECK)
+ if(${MODULE_NAME} STREQUAL "HG")
+ execute_process(COMMAND "${HG_EXECUTABLE}" --version OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE HG_RV)
+ if(NOT HG_RV EQUAL 0)
+ message(WARNING "Broken HG executable detected, skipping")
+ set(SKIP_CHECK TRUE)
+ endif()
+ endif()
if (DEFINED ${VERSION_VAR})
message(STATUS "${VERSION_VAR}='${${VERSION_VAR}}'")
if (NOT ${VERSION_VAR} MATCHES "^[0-9]")
@@ -71,7 +80,9 @@ macro(check_version_string MODULE_NAME VERSION_VAR)
message(SEND_ERROR "unexpected: ${VERSION_VAR} is NOT VERSION_GREATER 0")
endif()
else()
- message(SEND_ERROR "${MODULE_NAME}_FOUND is set but version number variable ${VERSION_VAR} is NOT DEFINED")
+ if(NOT SKIP_CHECK)
+ message(SEND_ERROR "${MODULE_NAME}_FOUND is set but version number variable ${VERSION_VAR} is NOT DEFINED")
+ endif()
endif()
endif ()
endmacro()
diff --git a/Tests/CTestTestFdSetSize/sleep.c b/Tests/CTestTestFdSetSize/sleep.c
index 2fb6490..d55cec6 100644
--- a/Tests/CTestTestFdSetSize/sleep.c
+++ b/Tests/CTestTestFdSetSize/sleep.c
@@ -1,7 +1,11 @@
#if defined(_WIN32)
# include <windows.h>
-#else
+#elif _XOPEN_SOURCE >= 500 || defined(_ALL_SOURCE)
# include <unistd.h>
+#else
+# include <time.h>
+
+# include <sys/select.h>
#endif
/* sleeps for 0.1 second */
@@ -9,8 +13,14 @@ int main(int argc, char** argv)
{
#if defined(_WIN32)
Sleep(100);
-#else
+#elif _XOPEN_SOURCE >= 500 || defined(_ALL_SOURCE)
usleep(100 * 1000);
+#else
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+
+ select(0, NULL, NULL, NULL, &tv);
#endif
return 0;
}
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index c9e41f5..6f19c13 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -155,6 +155,15 @@ target_include_directories(testInterfaceIncludeUser
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/testInterfaceIncludeUser>"
)
set_property(TARGET testInterfaceIncludeUser PROPERTY IMPORTED_NO_SYSTEM 1)
+
+add_library(testInterfaceIncludeUser2 INTERFACE)
+target_include_directories(testInterfaceIncludeUser2
+ INTERFACE
+ "$<INSTALL_INTERFACE:include/testInterfaceIncludeUser>"
+ "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/testInterfaceIncludeUser>"
+)
+set_property(TARGET testInterfaceIncludeUser2 PROPERTY EXPORT_NO_SYSTEM 1)
+
install(
FILES
"${CMAKE_CURRENT_SOURCE_DIR}/include/testInterfaceIncludeUser/testInterfaceInclude.h"
@@ -562,6 +571,7 @@ install(
TopDirLib SubDirLinkA
systemlib
testInterfaceIncludeUser
+ testInterfaceIncludeUser2
EXPORT exp
RUNTIME DESTINATION $<1:bin>$<0:/wrong>
LIBRARY DESTINATION $<1:lib>$<0:/wrong> NAMELINK_SKIP
@@ -622,6 +632,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3
TopDirLib SubDirLinkA
systemlib
testInterfaceIncludeUser
+ testInterfaceIncludeUser2
NAMESPACE bld_
FILE ExportBuildTree.cmake
)
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 272c7a9..5bafdf8 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -75,6 +75,10 @@ add_library(imp_testInterfaceInclude1 STATIC imp_testInterfaceInclude1.c)
target_include_directories(imp_testInterfaceInclude1 SYSTEM PRIVATE testInterfaceIncludeSystem)
target_link_libraries(imp_testInterfaceInclude1 PRIVATE exp_testInterfaceIncludeUser)
+add_library(imp_testInterfaceInclude1b STATIC imp_testInterfaceInclude1.c)
+target_include_directories(imp_testInterfaceInclude1b SYSTEM PRIVATE testInterfaceIncludeSystem)
+target_link_libraries(imp_testInterfaceInclude1b PRIVATE exp_testInterfaceIncludeUser2)
+
add_executable(imp_UseSharedLibWithHelper1 ../../../InterfaceLinkLibrariesDirect/UseSharedLibWithHelper.c)
target_link_libraries(imp_UseSharedLibWithHelper1 PRIVATE exp_testSharedLibWithHelper testSharedLibHelperExclude)
@@ -122,9 +126,13 @@ target_link_libraries(imp_testExe1b
bld_testStaticLibWithPlugin
)
-add_library(imp_testInterfaceInclude1b STATIC imp_testInterfaceInclude1.c)
-target_include_directories(imp_testInterfaceInclude1b SYSTEM PRIVATE testInterfaceIncludeSystem)
-target_link_libraries(imp_testInterfaceInclude1b PRIVATE bld_testInterfaceIncludeUser)
+add_library(imp_testInterfaceInclude1c STATIC imp_testInterfaceInclude1.c)
+target_include_directories(imp_testInterfaceInclude1c SYSTEM PRIVATE testInterfaceIncludeSystem)
+target_link_libraries(imp_testInterfaceInclude1c PRIVATE bld_testInterfaceIncludeUser)
+
+add_library(imp_testInterfaceInclude1d STATIC imp_testInterfaceInclude1.c)
+target_include_directories(imp_testInterfaceInclude1d SYSTEM PRIVATE testInterfaceIncludeSystem)
+target_link_libraries(imp_testInterfaceInclude1d PRIVATE bld_testInterfaceIncludeUser2)
add_custom_target(check_testLib1_genex ALL
COMMAND ${CMAKE_COMMAND} -DtestLib1=$<TARGET_FILE:exp_testLib1>
diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt
index e4c6c66..81d31e7 100644
--- a/Tests/ExternalProject/CMakeLists.txt
+++ b/Tests/ExternalProject/CMakeLists.txt
@@ -45,7 +45,11 @@ if(NOT DEFINED EP_TEST_HG OR EP_TEST_HG)
find_package(Hg)
endif()
if(NOT DEFINED EP_TEST_HG AND Hg_FOUND)
- set(EP_TEST_HG 1)
+ # Check if hg executable is working
+ execute_process(COMMAND "${HG_EXECUTABLE}" --version OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE HG_RV)
+ if(HG_RV EQUAL 0)
+ set(EP_TEST_HG 1)
+ endif()
endif()
message(STATUS "EP_TEST_CVS='${EP_TEST_CVS}' CVS_EXECUTABLE='${CVS_EXECUTABLE}'")
diff --git a/Tests/FindOpenAL/CMakeLists.txt b/Tests/FindOpenAL/CMakeLists.txt
new file mode 100644
index 0000000..fc4803e
--- /dev/null
+++ b/Tests/FindOpenAL/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_test(NAME FindOpenAL.Test COMMAND
+ ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+ --build-and-test
+ "${CMake_SOURCE_DIR}/Tests/FindOpenAL/Test"
+ "${CMake_BINARY_DIR}/Tests/FindOpenAL/Test"
+ ${build_generator_args}
+ --build-project TestFindOpenAL
+ --build-options ${build_options}
+ --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+ )
diff --git a/Tests/FindOpenAL/Test/CMakeLists.txt b/Tests/FindOpenAL/Test/CMakeLists.txt
new file mode 100644
index 0000000..fa3e263
--- /dev/null
+++ b/Tests/FindOpenAL/Test/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.21)
+project(TestFindOpenAL CXX)
+include(CTest)
+
+find_package(OpenAL REQUIRED)
+
+add_executable(test_tgt main.cxx)
+target_link_libraries(test_tgt OpenAL::OpenAL)
+add_test(NAME test_tgt COMMAND test_tgt)
+
+add_executable(test_var main.cxx)
+target_include_directories(test_var PRIVATE ${OPENAL_INCLUDE_DIR})
+target_link_libraries(test_var PRIVATE ${OPENAL_LIBRARY})
+add_test(NAME test_var COMMAND test_var)
diff --git a/Tests/FindOpenAL/Test/main.cxx b/Tests/FindOpenAL/Test/main.cxx
new file mode 100644
index 0000000..bb45faf
--- /dev/null
+++ b/Tests/FindOpenAL/Test/main.cxx
@@ -0,0 +1,13 @@
+#include <AL/al.h>
+#include <AL/alc.h>
+#include <stdio.h>
+
+int main()
+{
+ /* Reference an AL symbol without requiring a context at runtime. */
+ printf("&alGetString = %p\n", &alGetString);
+
+ /* Reference an ALC symbol without requiring a context at runtime. */
+ printf("&alcGetString = %p\n", &alcGetString);
+ return 0;
+}
diff --git a/Tests/FindVulkan/Test/CMakeLists.txt b/Tests/FindVulkan/Test/CMakeLists.txt
index 42543ac..dfcfc15 100644
--- a/Tests/FindVulkan/Test/CMakeLists.txt
+++ b/Tests/FindVulkan/Test/CMakeLists.txt
@@ -7,7 +7,10 @@ set(components
glslang
shaderc_combined
SPIRV-Tools
+ volk
+ dxc
)
+
if(APPLE)
list(APPEND components MoltenVK)
endif()
@@ -75,6 +78,14 @@ if(APPLE)
add_test(NAME test_tgt_MoltenVK COMMAND test_tgt_MoltenVK)
endif()
+add_executable(test_tgt_volk main-volk.cxx)
+target_link_libraries(test_tgt_volk Vulkan::volk)
+add_test(NAME test_tgt_volk COMMAND test_tgt_volk)
+
+add_executable(test_tgt_dxc_lib main-dxc_lib.cxx)
+target_link_libraries(test_tgt_dxc_lib Vulkan::dxc_lib)
+add_test(NAME test_tgt_dxc_lib COMMAND test_tgt_dxc_lib)
+
if(Vulkan_GLSLC_EXECUTABLE)
add_test(NAME test_glslc
COMMAND ${CMAKE_COMMAND}
@@ -92,3 +103,12 @@ if(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE)
-P "${CMAKE_CURRENT_LIST_DIR}/Run-glslangValidator.cmake"
)
endif()
+
+if(Vulkan_dxc_EXECUTABLE)
+ add_test(NAME test_dxc_exe
+ COMMAND ${CMAKE_COMMAND}
+ "-DVULKAN_DXC_EXECUTABLE=${Vulkan_dxc_EXECUTABLE}"
+ "-DVULKAN_DXC_EXECUTABLE_TARGET=$<TARGET_FILE:Vulkan::dxc_exe>"
+ -P "${CMAKE_CURRENT_LIST_DIR}/Run-dxc_exe.cmake"
+ )
+endif()
diff --git a/Tests/FindVulkan/Test/Run-dxc_exe.cmake b/Tests/FindVulkan/Test/Run-dxc_exe.cmake
new file mode 100644
index 0000000..0d38855
--- /dev/null
+++ b/Tests/FindVulkan/Test/Run-dxc_exe.cmake
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.12)
+
+function(run_dxc_exe exe exe_display)
+ execute_process(COMMAND ${exe} --help
+ OUTPUT_VARIABLE output
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ RESULT_VARIABLE result
+ )
+
+ if(NOT result EQUAL 0)
+ message(SEND_ERROR "Result of ${exe_display} --help is ${result}, should be 0")
+ endif()
+
+ if(NOT output MATCHES "^OVERVIEW: HLSL Compiler for ")
+ message(SEND_ERROR "Output of ${exe_display} --help is \"${output}\", should begin with \"OVERVIEW: HLSL Compiler for \"")
+ endif()
+endfunction()
+
+run_dxc_exe("${VULKAN_DXC_EXECUTABLE}" "\${VULKAN_DXC_EXECUTABLE}")
+run_dxc_exe("${VULKAN_DXC_EXECUTABLE_TARGET}" "Vulkan::dxc_exe")
diff --git a/Tests/FindVulkan/Test/main-dxc_lib.cxx b/Tests/FindVulkan/Test/main-dxc_lib.cxx
new file mode 100644
index 0000000..6ccb0de
--- /dev/null
+++ b/Tests/FindVulkan/Test/main-dxc_lib.cxx
@@ -0,0 +1,23 @@
+#include <cstdio>
+
+#include "dxc/dxcapi.h"
+#include "printf.h"
+
+int main()
+{
+ IDxcCompiler3* compiler;
+ DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler));
+
+ assert(compiler);
+
+ IDxcVersionInfo* version;
+ compiler->QueryInterface(&version);
+
+ uint32_t major, minor;
+ version->GetVersion(&major, &minor);
+ printf("DirectX Shader Compiler: %u.%u\n", major, minor);
+ version->Release();
+ compiler->Release();
+
+ return 0;
+}
diff --git a/Tests/FindVulkan/Test/main-volk.cxx b/Tests/FindVulkan/Test/main-volk.cxx
new file mode 100644
index 0000000..2ec9fb4
--- /dev/null
+++ b/Tests/FindVulkan/Test/main-volk.cxx
@@ -0,0 +1,14 @@
+#include <iostream>
+
+#include <volk/volk.h>
+
+int main()
+{
+ if (volkInitialize() != VK_SUCCESS) {
+ std::cout << "volk initialization success!" << std::endl;
+ } else {
+ std::cout << "volk initialization failure!" << std::endl;
+ }
+
+ return 0;
+}
diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt
index bb4b92c..e82cea2 100644
--- a/Tests/IncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/CMakeLists.txt
@@ -121,12 +121,66 @@ add_library(ordertest ordertest.cpp)
target_include_directories(ordertest SYSTEM PUBLIC SystemIncludeDirectories/systemlib)
target_include_directories(ordertest PUBLIC SystemIncludeDirectories/userlib)
+# Test "IMPORTED_NO_SYSTEM" property and its interaction with "SYSTEM"
add_library(ordertest2 ordertest.cpp)
target_include_directories(ordertest2 SYSTEM PRIVATE SystemIncludeDirectories/systemlib)
target_link_libraries(ordertest2 PRIVATE ordertest2_userlib)
add_library(ordertest2_userlib INTERFACE IMPORTED)
target_include_directories(ordertest2_userlib INTERFACE SystemIncludeDirectories/userlib)
set_property(TARGET ordertest2_userlib PROPERTY IMPORTED_NO_SYSTEM 1)
+get_property(system_prop_value TARGET ordertest2_userlib PROPERTY SYSTEM)
+if (NOT system_prop_value)
+ message(SEND_ERROR "ordertest2_userlib SYSTEM property should be ON.")
+endif()
+
+# Test "SYSTEM" property of non-imported libraries
+add_library(ordertest3_systemlib INTERFACE)
+target_include_directories(ordertest3_systemlib INTERFACE SystemIncludeDirectories/systemlib)
+set_property(TARGET ordertest3_systemlib PROPERTY SYSTEM 1)
+add_library(ordertest3_userlib INTERFACE)
+target_include_directories(ordertest3_userlib INTERFACE SystemIncludeDirectories/userlib)
+add_library(ordertest3 ordertest.cpp)
+target_link_libraries(ordertest3 PRIVATE ordertest3_systemlib ordertest3_userlib)
+
+# Test "SYSTEM" property of imported libraries and its interaction with "IMPORTED_NO_SYSTEM"
+add_library(ordertest4 ordertest.cpp)
+target_include_directories(ordertest4 SYSTEM PRIVATE SystemIncludeDirectories/systemlib)
+target_link_libraries(ordertest4 PRIVATE ordertest4_userlib)
+add_library(ordertest4_userlib INTERFACE IMPORTED)
+target_include_directories(ordertest4_userlib INTERFACE SystemIncludeDirectories/userlib)
+set_property(TARGET ordertest4_userlib PROPERTY SYSTEM 0)
+get_property(imported_no_system_prop_value TARGET ordertest4_userlib PROPERTY IMPORTED_NO_SYSTEM)
+if (imported_no_system_prop_value)
+ message(SEND_ERROR "ordertest4_userlib IMPORTED_NO_SYSTEM property should be OFF.")
+endif()
+
+# Test the interaction between "SYSTEM" and "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES"
+add_library(ordertest5_systemlib INTERFACE)
+target_include_directories(ordertest5_systemlib SYSTEM INTERFACE SystemIncludeDirectories/systemlib)
+# The default value of `SYSTEM` is already `OFF`. Here we explicitly set it again.
+set_property(TARGET ordertest5_systemlib PROPERTY SYSTEM 0)
+add_library(ordertest5_userlib INTERFACE)
+target_include_directories(ordertest5_userlib INTERFACE SystemIncludeDirectories/userlib)
+add_library(ordertest5 ordertest.cpp)
+target_link_libraries(ordertest5 PRIVATE ordertest5_systemlib ordertest5_userlib)
+
+# Test that the include of imported executable is treated as system by default.
+add_executable(ordertest6_systemexe IMPORTED)
+target_include_directories(ordertest6_systemexe INTERFACE SystemIncludeDirectories/systemlib)
+set_property(TARGET ordertest6_systemexe PROPERTY ENABLE_EXPORTS 1)
+add_library(ordertest6_userlib INTERFACE)
+target_include_directories(ordertest6_userlib INTERFACE SystemIncludeDirectories/userlib)
+add_library(ordertest6 ordertest.cpp)
+target_link_libraries(ordertest6 PRIVATE ordertest6_systemexe ordertest6_userlib)
+
+# Test that the include of imported executable is not treated as system if "SYSTEM" property is OFF.
+add_library(ordertest7 ordertest.cpp)
+target_include_directories(ordertest7 SYSTEM PRIVATE SystemIncludeDirectories/systemlib)
+target_link_libraries(ordertest7 PRIVATE ordertest7_userexe)
+add_library(ordertest7_userexe INTERFACE IMPORTED)
+target_include_directories(ordertest7_userexe INTERFACE SystemIncludeDirectories/userlib)
+set_property(TARGET ordertest7_userexe PROPERTY ENABLE_EXPORTS 1)
+set_property(TARGET ordertest7_userexe PROPERTY SYSTEM 0)
add_subdirectory(StandardIncludeDirectories)
add_subdirectory(TargetIncludeDirectories)
diff --git a/Tests/LoadCommand/CMakeCommands/cmTestCommand.c b/Tests/LoadCommand/CMakeCommands/cmTestCommand.c
index af7b092..7176ebe 100644
--- a/Tests/LoadCommand/CMakeCommands/cmTestCommand.c
+++ b/Tests/LoadCommand/CMakeCommands/cmTestCommand.c
@@ -75,10 +75,10 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
info->CAPI->DisplaySatus(mf, info->CAPI->GetStartOutputDirectory(mf));
info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentDirectory(mf));
info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentOutputDirectory(mf));
- sprintf(buffer, "Cache version: %d.%d, CMake version: %d.%d",
- info->CAPI->GetCacheMajorVersion(mf),
- info->CAPI->GetCacheMinorVersion(mf),
- info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf));
+ snprintf(
+ buffer, sizeof(buffer), "Cache version: %d.%d, CMake version: %d.%d",
+ info->CAPI->GetCacheMajorVersion(mf), info->CAPI->GetCacheMinorVersion(mf),
+ info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf));
info->CAPI->DisplaySatus(mf, buffer);
if (info->CAPI->CommandExists(mf, "SET")) {
info->CAPI->DisplaySatus(mf, "Command SET exists");
@@ -91,10 +91,12 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
source_file = info->CAPI->CreateNewSourceFile(mf);
cstr = info->CAPI->SourceFileGetSourceName(source_file);
- sprintf(buffer, "Should be empty (source file name): [%s]", cstr);
+ snprintf(buffer, sizeof(buffer), "Should be empty (source file name): [%s]",
+ cstr);
info->CAPI->DisplaySatus(mf, buffer);
cstr = info->CAPI->SourceFileGetFullPath(source_file);
- sprintf(buffer, "Should be empty (source file full path): [%s]", cstr);
+ snprintf(buffer, sizeof(buffer),
+ "Should be empty (source file full path): [%s]", cstr);
info->CAPI->DisplaySatus(mf, buffer);
info->CAPI->DefineSourceFileProperty(mf, "SOME_PROPERTY", "unused old prop",
"This property is no longer used", 0);
@@ -106,7 +108,8 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
"This property is for testing.", 0);
info->CAPI->SourceFileSetProperty(source_file, "SOME_PROPERTY2", "HERE");
cstr = info->CAPI->SourceFileGetProperty(source_file, "ABSTRACT");
- sprintf(buffer, "Should be 0 (source file abstract property): [%p]", cstr);
+ snprintf(buffer, sizeof(buffer),
+ "Should be 0 (source file abstract property): [%p]", cstr);
info->CAPI->DisplaySatus(mf, buffer);
info->CAPI->DestroySourceFile(source_file);
diff --git a/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c b/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c
index af7b092..7176ebe 100644
--- a/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c
+++ b/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c
@@ -75,10 +75,10 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
info->CAPI->DisplaySatus(mf, info->CAPI->GetStartOutputDirectory(mf));
info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentDirectory(mf));
info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentOutputDirectory(mf));
- sprintf(buffer, "Cache version: %d.%d, CMake version: %d.%d",
- info->CAPI->GetCacheMajorVersion(mf),
- info->CAPI->GetCacheMinorVersion(mf),
- info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf));
+ snprintf(
+ buffer, sizeof(buffer), "Cache version: %d.%d, CMake version: %d.%d",
+ info->CAPI->GetCacheMajorVersion(mf), info->CAPI->GetCacheMinorVersion(mf),
+ info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf));
info->CAPI->DisplaySatus(mf, buffer);
if (info->CAPI->CommandExists(mf, "SET")) {
info->CAPI->DisplaySatus(mf, "Command SET exists");
@@ -91,10 +91,12 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
source_file = info->CAPI->CreateNewSourceFile(mf);
cstr = info->CAPI->SourceFileGetSourceName(source_file);
- sprintf(buffer, "Should be empty (source file name): [%s]", cstr);
+ snprintf(buffer, sizeof(buffer), "Should be empty (source file name): [%s]",
+ cstr);
info->CAPI->DisplaySatus(mf, buffer);
cstr = info->CAPI->SourceFileGetFullPath(source_file);
- sprintf(buffer, "Should be empty (source file full path): [%s]", cstr);
+ snprintf(buffer, sizeof(buffer),
+ "Should be empty (source file full path): [%s]", cstr);
info->CAPI->DisplaySatus(mf, buffer);
info->CAPI->DefineSourceFileProperty(mf, "SOME_PROPERTY", "unused old prop",
"This property is no longer used", 0);
@@ -106,7 +108,8 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[])
"This property is for testing.", 0);
info->CAPI->SourceFileSetProperty(source_file, "SOME_PROPERTY2", "HERE");
cstr = info->CAPI->SourceFileGetProperty(source_file, "ABSTRACT");
- sprintf(buffer, "Should be 0 (source file abstract property): [%p]", cstr);
+ snprintf(buffer, sizeof(buffer),
+ "Should be 0 (source file abstract property): [%p]", cstr);
info->CAPI->DisplaySatus(mf, buffer);
info->CAPI->DestroySourceFile(source_file);
diff --git a/Tests/RunCMake/AutoExportDll/AutoExport.cmake b/Tests/RunCMake/AutoExportDll/AutoExport.cmake
index dbcf4b8..fe57d56 100644
--- a/Tests/RunCMake/AutoExportDll/AutoExport.cmake
+++ b/Tests/RunCMake/AutoExportDll/AutoExport.cmake
@@ -7,7 +7,7 @@ set_property(TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1)
add_library(autoexport SHARED hello.cxx world.cxx foo.c $<TARGET_OBJECTS:objlib>)
add_library(autoexport3 SHARED cppCLI.cxx)
if(MSVC AND NOT MSVC_VERSION VERSION_LESS 1600
- AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
set_property(TARGET autoexport3 PROPERTY COMMON_LANGUAGE_RUNTIME "")
endif()
@@ -17,7 +17,7 @@ if(MSVC)
add_library(autoexport_for_exec SHARED hello2.c)
target_link_libraries(autoexport_for_exec say)
if(NOT MSVC_VERSION VERSION_LESS 1600 AND
- NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
enable_language(ASM_MASM)
target_sources(autoexport PRIVATE nop.asm)
set_property(SOURCE nop.asm PROPERTY COMPILE_FLAGS /safeseh)
diff --git a/Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt b/Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt
new file mode 100644
index 0000000..5d09fcf
--- /dev/null
+++ b/Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0102-OLD.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0102 will be removed from a future version
+ of CMake.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 69def6d..9549af9 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -565,6 +565,9 @@ if(CMake_TEST_CUDA)
endif()
add_RunCMake_test(DependencyGraph -DCMAKE_Fortran_COMPILER=${CMAKE_Fortran_COMPILER})
+# Add C++ Module tests.
+add_RunCMake_test(CXXModules -DCMake_TEST_MODULE_COMPILATION=${CMake_TEST_MODULE_COMPILATION} -DCMake_TEST_MODULE_COMPILATION_RULES=${CMake_TEST_MODULE_COMPILATION_RULES})
+
# ctresalloc links against CMakeLib and CTestLib, which means it can't be built
# if CMake_TEST_EXTERNAL_CMAKE is activated (the compiler might be different.)
# So, it has to be provided in the original build tree.
@@ -966,7 +969,7 @@ endif()
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|9[0-9])")
add_RunCMake_test(CSharpCustomCommand)
- if(NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
+ if(NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64")
add_RunCMake_test(CSharpReferenceImport)
endif()
endif()
diff --git a/Tests/RunCMake/CTestTimeout/TestTimeout.c b/Tests/RunCMake/CTestTimeout/TestTimeout.c
index 5a008a7..0d534fc 100644
--- a/Tests/RunCMake/CTestTimeout/TestTimeout.c
+++ b/Tests/RunCMake/CTestTimeout/TestTimeout.c
@@ -1,6 +1,7 @@
#if defined(_WIN32)
# include <windows.h>
#else
+# include <sched.h>
# include <unistd.h>
#endif
diff --git a/Tests/RunCMake/CXXModules/CMakeLists.txt b/Tests/RunCMake/CXXModules/CMakeLists.txt
new file mode 100644
index 0000000..708d92c
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.23)
+project(${RunCMake_TEST} NONE)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake
new file mode 100644
index 0000000..cb6f6bd
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake
@@ -0,0 +1,40 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/export-modules-targets.cmake" export_script)
+
+if (NOT export_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules/cxx-modules\.cmake"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module property script inclusion")
+endif ()
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules.cmake" trampoline_script)
+
+if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-[^.]*\.cmake" OPTIONAL\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module property per-config script inclusion(s)")
+ endif ()
+else ()
+ if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-[^.]*\.cmake"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module property per-config script inclusion(s)")
+ endif ()
+endif ()
+
+set(any_exists 0)
+foreach (config IN ITEMS noconfig Debug Release RelWithDebInfo MinSizeRel)
+ if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-${config}.cmake")
+ continue ()
+ endif ()
+ set(any_exists 1)
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-${config}.cmake" config_script)
+
+ if (NOT config_script MATCHES "include\\(\"\\\${CMAKE_CURRENT_LIST_DIR}/target-export-name-${config}\\.cmake\"\\)")
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module per-target property script inclusion")
+ endif ()
+endforeach ()
+
+if (NOT any_exists)
+ list(APPEND RunCMake_TEST_FAILED
+ "No per-configuration target files exist.")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt
new file mode 100644
index 0000000..c05b0b4
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at ExportBuildCxxModules.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake b/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake
new file mode 100644
index 0000000..850f8dc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake
@@ -0,0 +1,22 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(export-modules)
+target_sources(export-modules
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(export-modules
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET export-modules
+ PROPERTY EXPORT_NAME export-name)
+
+install(TARGETS export-modules
+ EXPORT exp
+ FILE_SET fs DESTINATION "include/cxx/export-modules")
+
+export(EXPORT exp
+ FILE "${CMAKE_BINARY_DIR}/lib/cmake/export-modules/export-modules-targets.cmake"
+ CXX_MODULES_DIRECTORY "cxx-modules")
diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake
new file mode 100644
index 0000000..9e83fd8
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake
@@ -0,0 +1,35 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/exp.cmake" export_script)
+
+if (NOT export_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules/cxx-modules\.cmake"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module property script inclusion")
+endif ()
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules.cmake" trampoline_script)
+
+if (NOT trampoline_script MATCHES [[file\(GLOB _cmake_cxx_module_includes "\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-\*\.cmake"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module property per-config script inclusion(s)")
+endif ()
+
+set(any_exists 0)
+foreach (config IN ITEMS noconfig Debug Release RelWithDebInfo MinSizeRel)
+ if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-${config}.cmake")
+ continue ()
+ endif ()
+ set(any_exists 1)
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-${config}.cmake" config_script)
+
+ if (NOT config_script MATCHES "include\\(\"\\\${CMAKE_CURRENT_LIST_DIR}/target-export-name-${config}\\.cmake\"\\)")
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find C++ module per-target property script inclusion")
+ endif ()
+endforeach ()
+
+if (NOT any_exists)
+ list(APPEND RunCMake_TEST_FAILED
+ "No per-configuration target files exist.")
+endif ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt
new file mode 100644
index 0000000..4fe27a9
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at ExportInstallCxxModules.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake b/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake
new file mode 100644
index 0000000..234a4b5
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake
@@ -0,0 +1,22 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(export-modules)
+target_sources(export-modules
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(export-modules
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET export-modules
+ PROPERTY EXPORT_NAME export-name)
+
+install(TARGETS export-modules
+ EXPORT exp
+ FILE_SET fs DESTINATION "include/cxx/export-modules")
+
+install(EXPORT exp
+ DESTINATION "lib/cmake/export-modules"
+ CXX_MODULES_DIRECTORY "cxx-modules")
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt
new file mode 100644
index 0000000..d573a02
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt
@@ -0,0 +1,12 @@
+CMake Warning \(dev\) at FileSetModuleHeaderUnitsInterface.cmake:2 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error at FileSetModuleHeaderUnitsInterface.cmake:2 \(target_sources\):
+ target_sources File set TYPEs "CXX_MODULES" and "CXX_MODULE_HEADER_UNITS"
+ may not have "INTERFACE" visibility
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake
new file mode 100644
index 0000000..03ca17e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake
@@ -0,0 +1,8 @@
+add_library(module-header)
+target_sources(module-header
+ INTERFACE
+ FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES
+ sources/module-header.h)
+target_compile_features(module-header
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt
new file mode 100644
index 0000000..1b4ba5d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning \(dev\) at FileSetModuleHeaderUnitsInterfaceImported.cmake:2 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake
new file mode 100644
index 0000000..9ff5606
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake
@@ -0,0 +1,8 @@
+add_library(module-header SHARED IMPORTED)
+target_sources(module-header
+ INTERFACE
+ FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES
+ sources/module-header.h)
+target_compile_features(module-header
+ INTERFACE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt
new file mode 100644
index 0000000..a7ac88e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at FileSetModuleHeaderUnitsPrivate.cmake:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake
new file mode 100644
index 0000000..ebf9853
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake
@@ -0,0 +1,13 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(module-header
+ sources/cxx-anchor.cxx)
+target_sources(module-header
+ PRIVATE
+ FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES
+ sources/module-header.h)
+target_compile_features(module-header
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt
new file mode 100644
index 0000000..a5b4ede
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at FileSetModuleHeaderUnitsPublic.cmake:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake
new file mode 100644
index 0000000..3dfccbb5
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake
@@ -0,0 +1,13 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(module-header
+ sources/cxx-anchor.cxx)
+target_sources(module-header
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES
+ sources/module-header.h)
+target_compile_features(module-header
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt
new file mode 100644
index 0000000..81a35e8
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt
@@ -0,0 +1,12 @@
+CMake Warning \(dev\) at FileSetModulesInterface.cmake:2 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error at FileSetModulesInterface.cmake:2 \(target_sources\):
+ target_sources File set TYPEs "CXX_MODULES" and "CXX_MODULE_HEADER_UNITS"
+ may not have "INTERFACE" visibility
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake b/Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake
new file mode 100644
index 0000000..24cec3e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake
@@ -0,0 +1,8 @@
+add_library(module)
+target_sources(module
+ INTERFACE
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(module
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt
new file mode 100644
index 0000000..4420bbc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning \(dev\) at FileSetModulesInterfaceImported.cmake:2 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake
new file mode 100644
index 0000000..6640ae9
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake
@@ -0,0 +1,8 @@
+add_library(module SHARED IMPORTED)
+target_sources(module
+ INTERFACE
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(module
+ INTERFACE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt
new file mode 100644
index 0000000..03e06cc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at FileSetModulesPrivate.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake b/Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake
new file mode 100644
index 0000000..ca18982
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(module)
+target_sources(module
+ PRIVATE
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(module
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt
new file mode 100644
index 0000000..0c110c3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at FileSetModulesPublic.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake b/Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake
new file mode 100644
index 0000000..58de174
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake
@@ -0,0 +1,12 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(module)
+target_sources(module
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(module
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/InstallBMI-check.cmake b/Tests/RunCMake/CXXModules/InstallBMI-check.cmake
new file mode 100644
index 0000000..f891c80
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMI-check.cmake
@@ -0,0 +1,24 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script)
+
+if (NOT install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi" OR NOT CMAKE_INSTALL_COMPONENT\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find BMI install script component for `bmi`")
+endif ()
+
+if (NOT install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find BMI install script inclusion")
+endif ()
+
+if (NOT install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi-optional"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find BMI install script component for `bmi-optional`")
+endif ()
+
+if (NOT install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi-only-debug" OR NOT CMAKE_INSTALL_COMPONENT\)
+ if\(CMAKE_INSTALL_CONFIG_NAME MATCHES "\^\(\[Dd\]\[Ee\]\[Bb\]\[Uu\]\[Gg\]\)\$"\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find BMI install script component for `bmi-only-debug`")
+endif ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
diff --git a/Tests/RunCMake/CXXModules/InstallBMI-stderr.txt b/Tests/RunCMake/CXXModules/InstallBMI-stderr.txt
new file mode 100644
index 0000000..fc3c7db
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMI-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning \(dev\) at InstallBMI.cmake:8 \(install\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/InstallBMI.cmake b/Tests/RunCMake/CXXModules/InstallBMI.cmake
new file mode 100644
index 0000000..f0947b4
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMI.cmake
@@ -0,0 +1,23 @@
+enable_language(CXX)
+
+add_library(install-bmi)
+target_sources(install-bmi
+ PRIVATE
+ sources/cxx-anchor.cxx)
+
+install(TARGETS install-bmi
+ CXX_MODULES_BMI
+ DESTINATION "lib/bmi"
+ COMPONENT "bmi")
+
+install(TARGETS install-bmi
+ CXX_MODULES_BMI
+ DESTINATION "lib/bmi"
+ EXCLUDE_FROM_ALL
+ COMPONENT "bmi-optional")
+
+install(TARGETS install-bmi
+ CXX_MODULES_BMI
+ DESTINATION "lib/bmi"
+ CONFIGURATIONS Debug
+ COMPONENT "bmi-only-debug")
diff --git a/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake
new file mode 100644
index 0000000..32a37ad
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake
@@ -0,0 +1,8 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script)
+
+if (NOT install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi-generic-args\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Could not find BMI install script inclusion")
+endif ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
diff --git a/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt
new file mode 100644
index 0000000..44c961f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning \(dev\) at InstallBMIGenericArgs.cmake:8 \(install\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake
new file mode 100644
index 0000000..8f17143
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake
@@ -0,0 +1,9 @@
+enable_language(CXX)
+
+add_library(install-bmi-generic-args)
+target_sources(install-bmi-generic-args
+ PRIVATE
+ sources/cxx-anchor.cxx)
+
+install(TARGETS install-bmi-generic-args
+ DESTINATION "bin")
diff --git a/Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake b/Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake
new file mode 100644
index 0000000..7d13ef0
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake
@@ -0,0 +1,13 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script)
+
+if (install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi" OR NOT CMAKE_INSTALL_COMPONENT\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Found BMI install script component for `bmi`")
+endif ()
+
+if (install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi-ignore\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Found BMI install script inclusion")
+endif ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
diff --git a/Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt b/Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt
new file mode 100644
index 0000000..d9d2c2d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt
@@ -0,0 +1,6 @@
+CMake Warning \(dev\) at InstallBMIIgnore.cmake:5 \(install\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake b/Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake
new file mode 100644
index 0000000..f339511
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake
@@ -0,0 +1,9 @@
+enable_language(CXX)
+
+add_library(install-bmi-ignore INTERFACE)
+
+install(TARGETS install-bmi-ignore
+ CXX_MODULES_BMI
+ # An empty destination ignores BMI installation.
+ DESTINATION ""
+ COMPONENT "bmi")
diff --git a/Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake b/Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake
new file mode 100644
index 0000000..412e260
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake
@@ -0,0 +1,8 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script)
+
+if (install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi-generic-args\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]])
+ list(APPEND RunCMake_TEST_FAILED
+ "Found BMI install script inclusion")
+endif ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake
new file mode 100644
index 0000000..0d08c44
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake
@@ -0,0 +1,34 @@
+include("${CMAKE_CURRENT_LIST_DIR}/check-json.cmake")
+
+if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(have_file 0)
+ foreach (config IN ITEMS Release Debug RelWithDebInfo MinSizeRel)
+ if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-public.dir/${config}/CXXDependInfo.json")
+ continue ()
+ endif ()
+ set(have_file 1)
+
+ set(CMAKE_BUILD_TYPE "${config}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-public.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-private.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+ endforeach ()
+
+ if (NOT have_file)
+ list(APPEND RunCMake_TEST_FAILED
+ "No recognized build configurations found.")
+ endif ()
+else ()
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-public.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-private.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt
new file mode 100644
index 0000000..ebf7be5
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at NinjaDependInfoBMIInstall.cmake:14 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake
new file mode 100644
index 0000000..32dc42d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake
@@ -0,0 +1,76 @@
+# Fake out that we have dyndep; we only need to generate, not actually build
+# here.
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+enable_language(CXX)
+
+if (NOT CMAKE_GENERATOR MATCHES "Ninja")
+ message(FATAL_ERROR
+ "This test requires a 'Ninja' generator to be used.")
+endif ()
+
+add_library(ninja-bmi-install-public)
+target_sources(ninja-bmi-install-public
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-bmi-install-public
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET ninja-bmi-install-public
+ PROPERTY EXPORT_NAME "with-public")
+
+install(TARGETS ninja-bmi-install-public
+ FILE_SET modules
+ DESTINATION "lib/cxx"
+ COMPONENT "modules"
+ FILE_SET internal_partitions
+ DESTINATION "lib/cxx/internals"
+ COMPONENT "modules-internal"
+ CXX_MODULES_BMI
+ DESTINATION "lib/cxx/modules/$<CONFIG>"
+ COMPONENT "bmi")
+
+add_library(ninja-bmi-install-private)
+target_sources(ninja-bmi-install-private
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PRIVATE
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-bmi-install-private
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET ninja-bmi-install-private
+ PROPERTY EXPORT_NAME "with-private")
+
+set(CMAKE_INSTALL_MESSAGE LAZY)
+install(TARGETS ninja-bmi-install-private
+ CXX_MODULES_BMI
+ DESTINATION "lib/cxx/modules/private/$<CONFIG>"
+ PERMISSIONS
+ OWNER_READ OWNER_WRITE
+ GROUP_READ
+ WORLD_READ
+ COMPONENT "bmi")
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake
new file mode 100644
index 0000000..7720257
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake
@@ -0,0 +1,34 @@
+include("${CMAKE_CURRENT_LIST_DIR}/check-json.cmake")
+
+if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(have_file 0)
+ foreach (config IN ITEMS Release Debug RelWithDebInfo MinSizeRel)
+ if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/${config}/CXXDependInfo.json")
+ continue ()
+ endif ()
+ set(have_file 1)
+
+ set(CMAKE_BUILD_TYPE "${config}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-private.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+ endforeach ()
+
+ if (NOT have_file)
+ list(APPEND RunCMake_TEST_FAILED
+ "No recognized build configurations found.")
+ endif ()
+else ()
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-private.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt
new file mode 100644
index 0000000..e328223
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at NinjaDependInfoExport.cmake:14 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake
new file mode 100644
index 0000000..05e7ef7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake
@@ -0,0 +1,85 @@
+# Fake out that we have dyndep; we only need to generate, not actually build
+# here.
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+enable_language(CXX)
+
+if (NOT CMAKE_GENERATOR MATCHES "Ninja")
+ message(FATAL_ERROR
+ "This test requires a 'Ninja' generator to be used.")
+endif ()
+
+add_library(ninja-exports-public)
+target_sources(ninja-exports-public
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-exports-public
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET ninja-exports-public
+ PROPERTY EXPORT_NAME "with-public")
+
+install(TARGETS ninja-exports-public
+ EXPORT exp
+ FILE_SET modules
+ DESTINATION "lib/cxx"
+ COMPONENT "modules"
+ FILE_SET internal_partitions
+ DESTINATION "lib/cxx/internals"
+ COMPONENT "modules-internal")
+
+add_library(ninja-exports-private)
+target_sources(ninja-exports-private
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PRIVATE
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-exports-private
+ PRIVATE
+ cxx_std_20)
+set_property(TARGET ninja-exports-private
+ PROPERTY EXPORT_NAME "with-private")
+
+install(TARGETS ninja-exports-private
+ EXPORT exp)
+
+# Test multiple build exports.
+export(EXPORT exp
+ FILE "${CMAKE_BINARY_DIR}/lib/cmake/export1/export1-targets.cmake"
+ NAMESPACE export1::
+ CXX_MODULES_DIRECTORY "cxx-modules")
+export(EXPORT exp
+ FILE "${CMAKE_BINARY_DIR}/lib/cmake/export2/export2-targets.cmake"
+ CXX_MODULES_DIRECTORY "cxx-modules")
+
+# Test multiple install exports.
+install(EXPORT exp
+ DESTINATION "lib/cmake/export1"
+ NAMESPACE export1::
+ CXX_MODULES_DIRECTORY "cxx-modules")
+install(EXPORT exp
+ DESTINATION "lib/cmake/export2"
+ CXX_MODULES_DIRECTORY "cxx-modules")
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake
new file mode 100644
index 0000000..b9a1315
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake
@@ -0,0 +1,34 @@
+include("${CMAKE_CURRENT_LIST_DIR}/check-json.cmake")
+
+if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(have_file 0)
+ foreach (config IN ITEMS Release Debug RelWithDebInfo MinSizeRel)
+ if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-public.dir/${config}/CXXDependInfo.json")
+ continue ()
+ endif ()
+ set(have_file 1)
+
+ set(CMAKE_BUILD_TYPE "${config}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-public.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-private.dir/${config}/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+ endforeach ()
+
+ if (NOT have_file)
+ list(APPEND RunCMake_TEST_FAILED
+ "No recognized build configurations found.")
+ endif ()
+else ()
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-public.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-public.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+
+ file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-private.dir/CXXDependInfo.json" actual_contents)
+ file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-private.json" expect_contents)
+ check_json("${actual_contents}" "${expect_contents}")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt
new file mode 100644
index 0000000..ca430cc
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt
@@ -0,0 +1,11 @@
+CMake Warning \(dev\) at NinjaDependInfoFileSet.cmake:14 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake
new file mode 100644
index 0000000..74e729e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake
@@ -0,0 +1,59 @@
+# Fake out that we have dyndep; we only need to generate, not actually build
+# here.
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+enable_language(CXX)
+
+if (NOT CMAKE_GENERATOR MATCHES "Ninja")
+ message(FATAL_ERROR
+ "This test requires a 'Ninja' generator to be used.")
+endif ()
+
+add_library(ninja-file-sets-public)
+target_sources(ninja-file-sets-public
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-file-sets-public
+ PRIVATE
+ cxx_std_20)
+
+install(TARGETS ninja-file-sets-public
+ FILE_SET modules
+ DESTINATION "lib/cxx"
+ COMPONENT "modules"
+ FILE_SET internal_partitions
+ DESTINATION "lib/cxx/internals"
+ COMPONENT "modules-internal")
+
+add_library(ninja-file-sets-private)
+target_sources(ninja-file-sets-private
+ PRIVATE
+ sources/module-impl.cxx
+ sources/module-internal-part-impl.cxx
+ sources/module-part-impl.cxx
+ sources/module-use.cxx
+ PRIVATE
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}/sources"
+ FILES
+ sources/module.cxx
+ sources/module-part.cxx
+ FILE_SET internal_partitions TYPE CXX_MODULES FILES
+ sources/module-internal-part.cxx)
+target_compile_features(ninja-file-sets-private
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/NoCXX-result.txt b/Tests/RunCMake/CXXModules/NoCXX-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NoCXX-stderr.txt b/Tests/RunCMake/CXXModules/NoCXX-stderr.txt
new file mode 100644
index 0000000..aa7f406
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX-stderr.txt
@@ -0,0 +1,20 @@
+CMake Warning \(dev\) at NoCXX.cmake:4 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ The "nocxx" target has C\+\+ module sources but the "CXX" language has not
+ been enabled
+
+(
+CMake Error in CMakeLists.txt:
+( The "nocxx" target has C\+\+ module sources but the "CXX" language has not
+ been enabled
+| The "nocxx" target contains C\+\+ module sources which are not supported by
+ the generator
+)
+)*
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NoCXX.cmake b/Tests/RunCMake/CXXModules/NoCXX.cmake
new file mode 100644
index 0000000..3c46f9d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX.cmake
@@ -0,0 +1,9 @@
+enable_language(C)
+
+add_library(nocxx)
+target_sources(nocxx
+ PRIVATE
+ sources/c-anchor.c
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
diff --git a/Tests/RunCMake/CXXModules/NoCXX20-result.txt b/Tests/RunCMake/CXXModules/NoCXX20-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NoCXX20-stderr.txt b/Tests/RunCMake/CXXModules/NoCXX20-stderr.txt
new file mode 100644
index 0000000..95d73b1
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20-stderr.txt
@@ -0,0 +1,20 @@
+CMake Warning \(dev\) at NoCXX20.cmake:4 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ The "nocxx20" target has C\+\+ module sources but is not using at least
+ "cxx_std_20"
+
+(
+CMake Error in CMakeLists.txt:
+( The "nocxx20" target has C\+\+ module sources but is not using at least
+ "cxx_std_20"
+| The "nocxx20" target contains C\+\+ module sources which are not supported by
+ the generator
+)
+)*
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NoCXX20.cmake b/Tests/RunCMake/CXXModules/NoCXX20.cmake
new file mode 100644
index 0000000..b7372e8
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20.cmake
@@ -0,0 +1,11 @@
+enable_language(CXX)
+
+add_library(nocxx20)
+target_sources(nocxx20
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+set_target_properties(nocxx20
+ PROPERTIES
+ CXX_STANDARD 17
+ CXX_STANDARD_REQUIRED ON)
diff --git a/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt
new file mode 100644
index 0000000..5f90ec8
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt
@@ -0,0 +1,20 @@
+CMake Warning \(dev\) at NoCXX20ModuleFlag.cmake:4 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ The "noexperimentalflag" target has C\+\+ module sources but its experimental
+ support has not been requested
+
+(
+CMake Error in CMakeLists.txt:
+( The "noexperimentalflag" target has C\+\+ module sources but its experimental
+ support has not been requested
+| The "noexperimentalflag" target contains C\+\+ module sources which are not
+ supported by the generator
+)
+)*
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake
new file mode 100644
index 0000000..5f896f9
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake
@@ -0,0 +1,10 @@
+enable_language(CXX)
+
+add_library(noexperimentalflag)
+target_sources(noexperimentalflag
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(noexperimentalflag
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt b/Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt b/Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt
new file mode 100644
index 0000000..52f781f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt
@@ -0,0 +1,30 @@
+CMake Warning \(dev\) at NoDyndepSupport.cmake:10 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+(CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error:
+ The Ninja generator does not support C\+\+20 modules using Ninja version
+
+ .*
+
+ due to lack of required features. Ninja 1.10 or higher is required.
+
+|CMake Error in CMakeLists.txt:
+ The "nodyndep" target contains C\+\+ module sources which are not supported
+ by the generator
+
+(
+CMake Error in CMakeLists.txt:
+ The "nodyndep" target contains C\+\+ module sources which are not supported
+ by the generator
+
+)*)
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NoDyndepSupport.cmake b/Tests/RunCMake/CXXModules/NoDyndepSupport.cmake
new file mode 100644
index 0000000..0954400
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NoDyndepSupport.cmake
@@ -0,0 +1,16 @@
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+if (NOT CMAKE_CXX_STANDARD_DEFAULT)
+ set(CMAKE_CXX_STANDARD_DEFAULT "11")
+endif ()
+
+add_library(nodyndep)
+target_sources(nodyndep
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/module.cxx)
+target_compile_features(nodyndep
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt
new file mode 100644
index 0000000..a93eb40
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt
@@ -0,0 +1,22 @@
+CMake Warning \(dev\) at NotCXXSourceModuleHeaderUnits.cmake:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ Target "not-cxx-source" contains the source
+
+ .*/Tests/RunCMake/CXXModules/sources/c-anchor.c
+
+ in a file set of type "CXX_MODULE_HEADER_UNITS" but the source is not
+ classified as a "CXX" source.
+
+
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake
new file mode 100644
index 0000000..af4ddac
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake
@@ -0,0 +1,15 @@
+enable_language(C)
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(not-cxx-source)
+target_sources(not-cxx-source
+ PRIVATE
+ sources/cxx-anchor.cxx
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES
+ sources/c-anchor.c)
+target_compile_features(not-cxx-source
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt
new file mode 100644
index 0000000..d341c1f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt
@@ -0,0 +1,17 @@
+CMake Warning \(dev\) at NotCXXSourceModules.cmake:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:6 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error in CMakeLists.txt:
+ Target "not-cxx-source" contains the source
+
+ .*/Tests/RunCMake/CXXModules/sources/c-anchor.c
+
+ in a file set of type "CXX_MODULES" but the source is not classified as a
+ "CXX" source.
+
+
+CMake Generate step failed. Build files cannot be regenerated correctly.
diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake b/Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake
new file mode 100644
index 0000000..f7a6060
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake
@@ -0,0 +1,13 @@
+enable_language(C)
+enable_language(CXX)
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
+set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "")
+
+add_library(not-cxx-source)
+target_sources(not-cxx-source
+ PUBLIC
+ FILE_SET fs TYPE CXX_MODULES FILES
+ sources/c-anchor.c)
+target_compile_features(not-cxx-source
+ PRIVATE
+ cxx_std_20)
diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake
new file mode 100644
index 0000000..ca1bc81
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake
@@ -0,0 +1,169 @@
+include(RunCMake)
+
+# For `if (IN_LIST)`
+cmake_policy(SET CMP0057 NEW)
+
+run_cmake(compiler_introspection)
+include("${RunCMake_BINARY_DIR}/compiler_introspection-build/info.cmake")
+
+# Test negative cases where C++20 modules do not work.
+run_cmake(NoCXX)
+if ("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
+ # This test requires that the compiler be told to compile in an older-than-20
+ # standard. If the compiler forces a standard to be used, skip it.
+ if (NOT forced_cxx_standard)
+ run_cmake(NoCXX20)
+ endif ()
+
+ # This test uses C++20, but another prerequisite is missing, so forced
+ # standards don't matter.
+ run_cmake(NoCXX20ModuleFlag)
+endif ()
+
+if (RunCMake_GENERATOR MATCHES "Ninja")
+ execute_process(
+ COMMAND "${CMAKE_MAKE_PROGRAM}" --version
+ RESULT_VARIABLE res
+ OUTPUT_VARIABLE ninja_version
+ ERROR_VARIABLE err
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_STRIP_TRAILING_WHITESPACE)
+
+ if (res)
+ message(WARNING
+ "Failed to determine `ninja` version: ${err}")
+ set(ninja_version "0")
+ endif ()
+endif ()
+
+# Test behavior when the generator does not support C++20 modules.
+if (NOT RunCMake_GENERATOR MATCHES "Ninja" OR
+ ninja_version VERSION_LESS "1.10" OR
+ NOT "cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
+ if ("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
+ run_cmake(NoDyndepSupport)
+ endif ()
+
+ # Bail; the remaining tests require the generator to successfully generate
+ # with C++20 modules in the source list.
+ return ()
+endif ()
+
+set(fileset_types
+ Modules
+ ModuleHeaderUnits)
+set(scopes
+ Interface
+ Private
+ Public)
+foreach (fileset_type IN LISTS fileset_types)
+ foreach (scope IN LISTS scopes)
+ run_cmake("FileSet${fileset_type}${scope}")
+ endforeach ()
+ run_cmake("FileSet${fileset_type}InterfaceImported")
+
+ # Test the error message when a non-C++ source file is found in the source
+ # list.
+ run_cmake("NotCXXSource${fileset_type}")
+endforeach ()
+
+run_cmake(InstallBMI)
+run_cmake(InstallBMIGenericArgs)
+run_cmake(InstallBMIIgnore)
+
+run_cmake(ExportBuildCxxModules)
+run_cmake(ExportInstallCxxModules)
+
+# Generator-specific tests.
+if (RunCMake_GENERATOR MATCHES "Ninja")
+ run_cmake(NinjaDependInfoFileSet)
+ run_cmake(NinjaDependInfoExport)
+ run_cmake(NinjaDependInfoBMIInstall)
+else ()
+ message(FATAL_ERROR
+ "Please add 'DependInfo' tests for the '${RunCMake_GENERATOR}' generator.")
+endif ()
+
+# Actual compilation tests.
+if (NOT CMake_TEST_MODULE_COMPILATION)
+ return ()
+endif ()
+
+function (run_cxx_module_test directory)
+ set(test_name "${directory}")
+ if (NOT ARGN STREQUAL "")
+ list(POP_FRONT ARGN test_name)
+ endif ()
+
+ set(RunCMake_TEST_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/examples/${directory}")
+ set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/examples/${test_name}-build")
+
+ if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ set(RunCMake_TEST_OPTIONS -DCMAKE_CONFIGURATION_TYPES=Debug)
+ else ()
+ set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+ endif ()
+
+ if (RunCMake_CXXModules_INSTALL)
+ set(prefix "${RunCMake_BINARY_DIR}/examples/${test_name}-install")
+ file(REMOVE_RECURSE "${prefix}")
+ list(APPEND RunCMake_TEST_OPTIONS
+ "-DCMAKE_INSTALL_PREFIX=${prefix}")
+ endif ()
+
+ list(APPEND RunCMake_TEST_OPTIONS
+ "-DCMake_TEST_MODULE_COMPILATION_RULES=${CMake_TEST_MODULE_COMPILATION_RULES}"
+ ${ARGN})
+ run_cmake("examples/${test_name}")
+ set(RunCMake_TEST_NO_CLEAN 1)
+ run_cmake_command("examples/${test_name}-build" "${CMAKE_COMMAND}" --build . --config Debug)
+ if (RunCMake_CXXModules_INSTALL)
+ run_cmake_command("examples/${test_name}-install" "${CMAKE_COMMAND}" --build . --target install --config Debug)
+ endif ()
+ run_cmake_command("examples/${test_name}-test" "${CMAKE_CTEST_COMMAND}" -C Debug --output-on-failure)
+endfunction ()
+
+string(REPLACE "," ";" CMake_TEST_MODULE_COMPILATION "${CMake_TEST_MODULE_COMPILATION}")
+
+# Tests which use named modules.
+if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(simple)
+ run_cxx_module_test(library library-static -DBUILD_SHARED_LIBS=OFF)
+ run_cxx_module_test(generated)
+ run_cxx_module_test(public-req-private)
+endif ()
+
+# Tests which use named modules in shared libraries.
+if ("shared" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(library library-shared -DBUILD_SHARED_LIBS=ON)
+endif ()
+
+# Tests which use partitions.
+if ("partitions" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(partitions)
+endif ()
+
+# Tests which use internal partitions.
+if ("internal_partitions" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(internal-partitions)
+endif ()
+
+# Tests which install BMIs
+if ("export_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(export-interface-build)
+ run_cxx_module_test(export-bmi-and-interface-build)
+endif ()
+
+# All of the following tests perform installation.
+set(RunCMake_CXXModules_INSTALL 1)
+
+# Tests which install BMIs
+if ("install_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(install-bmi)
+ run_cxx_module_test(install-bmi-and-interfaces)
+
+ if ("export_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION)
+ run_cxx_module_test(export-interface-install)
+ run_cxx_module_test(export-bmi-and-interface-install)
+ endif ()
+endif ()
diff --git a/Tests/RunCMake/CXXModules/check-json.cmake b/Tests/RunCMake/CXXModules/check-json.cmake
new file mode 100644
index 0000000..19d0c8a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/check-json.cmake
@@ -0,0 +1,160 @@
+cmake_policy(PUSH)
+cmake_policy(SET CMP0057 NEW)
+
+function (json_placeholders in out)
+ string(REPLACE "<CONFIG>" "${CMAKE_BUILD_TYPE}" in "${in}")
+ if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
+ string(REPLACE "<CONFIG_DIR>" "${CMAKE_BUILD_TYPE}/" in "${in}")
+ else ()
+ string(REPLACE "<CONFIG_DIR>" "" in "${in}")
+ endif ()
+ if (CMAKE_BUILD_TYPE)
+ string(REPLACE "<CONFIG_FORCE>" "${CMAKE_BUILD_TYPE}" in "${in}")
+ else ()
+ string(REPLACE "<CONFIG_FORCE>" "noconfig" in "${in}")
+ endif ()
+ string(REPLACE "<SOURCE_DIR>" "${RunCMake_SOURCE_DIR}" in "${in}")
+ string(REPLACE "<BINARY_DIR>" "${RunCMake_TEST_BINARY_DIR}" in "${in}")
+ set("${out}" "${in}" PARENT_SCOPE)
+endfunction ()
+
+function (check_json_value path actual_type expect_type actual_value expect_value)
+ if (NOT actual_type STREQUAL expect_type)
+ list(APPEND RunCMake_TEST_FAILED
+ "Type mismatch at ${path}: ${actual_type} vs. ${expect_type}")
+ return ()
+ endif ()
+
+ if (actual_type STREQUAL NULL)
+ # Nothing to check
+ elseif (actual_type STREQUAL BOOLEAN)
+ if (NOT actual_value STREQUAL expect_value)
+ list(APPEND RunCMake_TEST_FAILED
+ "Boolean mismatch at ${path}: ${actual_value} vs. ${expect_value}")
+ endif ()
+ elseif (actual_type STREQUAL NUMBER)
+ if (NOT actual_value EQUAL expect_value)
+ list(APPEND RunCMake_TEST_FAILED
+ "Number mismatch at ${path}: ${actual_value} vs. ${expect_value}")
+ endif ()
+ elseif (actual_type STREQUAL STRING)
+ # Allow some values to be ignored.
+ if (expect_value STREQUAL "<IGNORE>")
+ return ()
+ endif ()
+
+ json_placeholders("${expect_value}" expect_value_expanded)
+ if (NOT actual_value STREQUAL expect_value_expanded)
+ list(APPEND RunCMake_TEST_FAILED
+ "String mismatch at ${path}: ${actual_value} vs. ${expect_value_expanded}")
+ endif ()
+ elseif (actual_type STREQUAL ARRAY)
+ check_json_array("${path}" "${actual_value}" "${expect_value}")
+ elseif (actual_type STREQUAL OBJECT)
+ check_json_object("${path}" "${actual_value}" "${expect_value}")
+ endif ()
+endfunction ()
+
+# Check that two arrays are the same.
+function (check_json_array path actual expect)
+ string(JSON actual_len LENGTH "${actual}")
+ string(JSON expect_len LENGTH "${expect}")
+
+ set(iter_len "${actual_len}")
+ if (actual_len LESS expect_len)
+ list(APPEND RunCMake_TEST_FAILED
+ "Missing array items at ${path}")
+ elseif (expect_len LESS actual_len)
+ list(APPEND RunCMake_TEST_FAILED
+ "Extra array items at ${path}")
+ set(iter_len "${expect_len}")
+ endif ()
+
+ foreach (idx RANGE "${iter_len}")
+ if (idx EQUAL iter_len)
+ break ()
+ endif ()
+
+ set(new_path "${path}[${idx}]")
+ string(JSON actual_type TYPE "${actual}" "${idx}")
+ string(JSON expect_type TYPE "${expect}" "${idx}")
+ string(JSON actual_value GET "${actual}" "${idx}")
+ string(JSON expect_value GET "${expect}" "${idx}")
+ check_json_value("${new_path}" "${actual_type}" "${expect_type}" "${actual_value}" "${expect_value}")
+ endforeach ()
+endfunction ()
+
+# Check that two inner objects are the same.
+function (check_json_object path actual expect)
+ string(JSON actual_len LENGTH "${actual}")
+ string(JSON expect_len LENGTH "${expect}")
+
+ set(actual_keys "")
+ set(expect_keys "")
+ foreach (idx RANGE "${actual_len}")
+ if (idx EQUAL actual_len)
+ break ()
+ endif ()
+
+ string(JSON actual_key MEMBER "${actual}" "${idx}")
+ list(APPEND actual_keys "${actual_key}")
+ endforeach ()
+ foreach (idx RANGE "${expect_len}")
+ if (idx EQUAL expect_len)
+ break ()
+ endif ()
+
+ string(JSON expect_key MEMBER "${expect}" "${idx}")
+ list(APPEND expect_keys "${expect_key}")
+ endforeach ()
+
+ json_placeholders("${expect_keys}" expect_keys_expanded)
+
+ set(actual_keys_missed "${actual_keys}")
+ set(expect_keys_missed "${expect_keys}")
+
+ set(common_keys "")
+ set(expect_keys_stack "${expect_keys}")
+ while (expect_keys_stack)
+ list(POP_BACK expect_keys_stack expect_key)
+ json_placeholders("${expect_key}" expect_key_expanded)
+
+ if (expect_key_expanded IN_LIST actual_keys_missed AND
+ expect_key IN_LIST expect_keys_missed)
+ list(APPEND common_keys "${expect_key}")
+ endif ()
+
+ list(REMOVE_ITEM actual_keys_missed "${expect_key_expanded}")
+ list(REMOVE_ITEM expect_keys_missed "${expect_key}")
+ endwhile ()
+
+ if (actual_keys_missed)
+ string(REPLACE ";" ", " actual_keys_missed_text "${actual_keys_missed}")
+ list(APPEND RunCMake_TEST_FAILED
+ "Missing expected members at ${path}: ${actual_keys_missed_text}")
+ endif ()
+ if (expect_keys_missed)
+ string(REPLACE ";" ", " expect_keys_missed_text "${expect_keys_missed}")
+ list(APPEND RunCMake_TEST_FAILED
+ "Extra unexpected members at ${path}: ${expect_keys_missed_text}")
+ endif ()
+
+ foreach (key IN LISTS common_keys)
+ json_placeholders("${key}" key_expanded)
+ set(new_path "${path}.${key_expanded}")
+ string(JSON actual_type TYPE "${actual}" "${key_expanded}")
+ string(JSON expect_type TYPE "${expect}" "${key}")
+ string(JSON actual_value GET "${actual}" "${key_expanded}")
+ string(JSON expect_value GET "${expect}" "${key}")
+ check_json_value("${new_path}" "${actual_type}" "${expect_type}" "${actual_value}" "${expect_value}")
+ endforeach ()
+endfunction ()
+
+# Check that two JSON objects are the same.
+function (check_json actual expect)
+ check_json_object("" "${actual}" "${expect}")
+endfunction ()
+
+string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}")
+
+cmake_policy(POP)
diff --git a/Tests/RunCMake/CXXModules/compiler_introspection.cmake b/Tests/RunCMake/CXXModules/compiler_introspection.cmake
new file mode 100644
index 0000000..7a2df3d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/compiler_introspection.cmake
@@ -0,0 +1,25 @@
+enable_language(CXX)
+
+set(info "")
+
+# See `Modules/Compiler/MSVC-CXX.cmake` for this. If there is explicitly no
+# default, the feature list is populated to be everything.
+if (DEFINED CMAKE_CXX_STANDARD_DEFAULT AND
+ CMAKE_CXX_STANDARD_DEFAULT STREQUAL "")
+ set(CMAKE_CXX_COMPILE_FEATURES "")
+endif ()
+
+# Detect if the environment forces a C++ standard, let the test selection know.
+set(forced_cxx_standard 0)
+if (CMAKE_CXX_FLAGS MATCHES "-std=")
+ set(forced_cxx_standard 1)
+endif ()
+
+# Forward information about the C++ compile features.
+string(APPEND info "\
+set(CMAKE_CXX_COMPILE_FEATURES \"${CMAKE_CXX_COMPILE_FEATURES}\")
+set(CMAKE_MAKE_PROGRAM \"${CMAKE_MAKE_PROGRAM}\")
+set(forced_cxx_standard \"${forced_cxx_standard}\")
+")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}")
diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake
new file mode 100644
index 0000000..f99455b
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake
@@ -0,0 +1,22 @@
+function (check_for_bmi prefix destination name)
+ set(found 0)
+ foreach (ext IN ITEMS gcm)
+ if (EXISTS "${prefix}/${destination}/${name}.${ext}")
+ set(found 1)
+ break ()
+ endif ()
+ endforeach ()
+
+ if (NOT found)
+ message(SEND_ERROR
+ "Failed to find the ${name} BMI")
+ endif ()
+endfunction ()
+
+function (check_for_interface prefix destination subdir name)
+ set(found 0)
+ if (NOT EXISTS "${prefix}/${destination}/${subdir}/${name}")
+ message(SEND_ERROR
+ "Failed to find the ${name} module interface")
+ endif ()
+endfunction ()
diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake
new file mode 100644
index 0000000..8efe508
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake
@@ -0,0 +1,27 @@
+function (check_for_bmi prefix destination name)
+ set(found 0)
+ foreach (ext IN ITEMS gcm)
+ if (EXISTS "${prefix}/${destination}/${name}.${ext}")
+ set(found 1)
+ break ()
+ endif ()
+ endforeach ()
+
+ if (NOT found)
+ message(SEND_ERROR
+ "Failed to find the ${name} BMI")
+ endif ()
+endfunction ()
+
+function (check_for_interface prefix destination subdir name)
+ set(found 0)
+ if (NOT EXISTS "${prefix}/${destination}/${subdir}/${name}")
+ message(SEND_ERROR
+ "Failed to find the ${name} module interface")
+ endif ()
+endfunction ()
+
+function (report_dirs prefix destination)
+ message("prefix: ${prefix}")
+ message("destination: ${destination}")
+endfunction ()
diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake
new file mode 100644
index 0000000..381094e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake
@@ -0,0 +1,18 @@
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+if (NOT EXISTS "${CMake_TEST_MODULE_COMPILATION_RULES}")
+ message(FATAL_ERROR
+ "The `CMake_TEST_MODULE_COMPILATION_RULES` file must be specified "
+ "for these tests to operate.")
+endif ()
+
+include("${CMake_TEST_MODULE_COMPILATION_RULES}")
+
+if (NOT CMake_TEST_CXXModules_UUID STREQUAL "a246741c-d067-4019-a8fb-3d16b0c9d1d3")
+ message(FATAL_ERROR
+ "The compilation rule file needs updated for changes in the test "
+ "suite. Please see the history for what needs to be updated.")
+endif ()
+
+include(CTest)
+enable_testing()
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt
new file mode 100644
index 0000000..5e4392a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt
new file mode 100644
index 0000000..a450b7e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt
@@ -0,0 +1,56 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_export_bmi_and_interfaces CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(export_bmi_and_interfaces STATIC)
+target_sources(export_bmi_and_interfaces
+ PRIVATE
+ forward.cxx
+ PRIVATE
+ FILE_SET modules_private TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ private.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(export_bmi_and_interfaces PUBLIC cxx_std_20)
+
+install(TARGETS export_bmi_and_interfaces
+ EXPORT CXXModules
+ FILE_SET modules DESTINATION "lib/cxx/miu"
+ CXX_MODULES_BMI DESTINATION "lib/cxx/bmi")
+export(EXPORT CXXModules
+ NAMESPACE CXXModules::
+ FILE "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-targets.cmake"
+ CXX_MODULES_DIRECTORY "export_bmi_and_interfaces-cxx-modules")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-config.cmake"
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_bmi_and_interfaces-targets.cmake\")
+set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
+")
+
+set(generator
+ -G "${CMAKE_GENERATOR}")
+if (CMAKE_GENERATOR_TOOLSET)
+ list(APPEND generator
+ -T "${CMAKE_GENERATOR_TOOLSET}")
+endif ()
+if (CMAKE_GENERATOR_PLATFORM)
+ list(APPEND generator
+ -A "${CMAKE_GENERATOR_PLATFORM}")
+endif ()
+
+add_test(NAME export_bmi_and_interfaces_build
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dexpected_source_dir=${CMAKE_CURRENT_SOURCE_DIR}"
+ "-Dexpected_binary_dir=${CMAKE_CURRENT_BINARY_DIR}"
+ "-Dexport_bmi_and_interfaces_DIR=${CMAKE_CURRENT_BINARY_DIR}"
+ ${generator}
+ -S "${CMAKE_CURRENT_SOURCE_DIR}/test"
+ -B "${CMAKE_CURRENT_BINARY_DIR}/test")
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx
new file mode 100644
index 0000000..7f53271
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx
@@ -0,0 +1,6 @@
+import priv;
+
+int forwarding()
+{
+ return from_private();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx
new file mode 100644
index 0000000..e0b1872
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx
@@ -0,0 +1,8 @@
+export module importable;
+
+int forwarding();
+
+export int from_import()
+{
+ return forwarding();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx
new file mode 100644
index 0000000..c5b719a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx
@@ -0,0 +1,6 @@
+export module priv;
+
+export int from_private()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt
new file mode 100644
index 0000000..b814b3b
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_library NONE)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+find_package(export_bmi_and_interfaces REQUIRED)
+
+if (NOT TARGET CXXModules::export_bmi_and_interfaces)
+ message(FATAL_ERROR
+ "Missing imported target")
+endif ()
+
+get_property(file_sets TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY INTERFACE_CXX_MODULE_SETS)
+if (NOT file_sets STREQUAL "modules")
+ message(FATAL_ERROR
+ "Incorrect exported file sets in `CXXModules::export_bmi_and_interfaces`: `${file_sets}`")
+endif ()
+
+get_property(file_set_files TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY CXX_MODULE_SET_modules)
+if (NOT file_set_files STREQUAL "${expected_source_dir}/importable.cxx")
+ message(FATAL_ERROR
+ "Incorrect exported file set paths in CXXModules::export_bmi_and_interfaces`: `${file_set_files}`")
+endif ()
+
+get_property(imported_modules TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY IMPORTED_CXX_MODULES_DEBUG)
+if (NOT imported_modules MATCHES "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/CMakeFiles/export_bmi_and_interfaces.dir(/Debug)?/importable.(gcm|pcm|ifc)")
+ message(FATAL_ERROR
+ "Incorrect exported modules in CXXModules::export_bmi_and_interfaces`: `${imported_modules}`")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt
new file mode 100644
index 0000000..5e4392a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt
new file mode 100644
index 0000000..a5574fe
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt
@@ -0,0 +1,59 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_export_bmi_and_interfaces CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(export_bmi_and_interfaces STATIC)
+target_sources(export_bmi_and_interfaces
+ PRIVATE
+ forward.cxx
+ PRIVATE
+ FILE_SET modules_private TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ private.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(export_bmi_and_interfaces PUBLIC cxx_std_20)
+
+install(TARGETS export_bmi_and_interfaces
+ EXPORT CXXModules
+ FILE_SET modules DESTINATION "lib/cxx/miu"
+ CXX_MODULES_BMI DESTINATION "lib/cxx/bmi")
+install(EXPORT CXXModules
+ NAMESPACE CXXModules::
+ DESTINATION "lib/cmake/export_bmi_and_interfaces"
+ FILE "export_bmi_and_interfaces-targets.cmake"
+ CXX_MODULES_DIRECTORY "export_bmi_and_interfaces-cxx-modules")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-config.cmake"
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_bmi_and_interfaces-targets.cmake\")
+set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
+")
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-config.cmake"
+ DESTINATION "lib/cmake/export_bmi_and_interfaces")
+
+set(generator
+ -G "${CMAKE_GENERATOR}")
+if (CMAKE_GENERATOR_TOOLSET)
+ list(APPEND generator
+ -T "${CMAKE_GENERATOR_TOOLSET}")
+endif ()
+if (CMAKE_GENERATOR_PLATFORM)
+ list(APPEND generator
+ -A "${CMAKE_GENERATOR_PLATFORM}")
+endif ()
+
+add_test(NAME export_bmi_and_interfaces_build
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dexpected_source_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu"
+ "-Dexpected_binary_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/bmi"
+ "-Dexport_bmi_and_interfaces_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/export_bmi_and_interfaces"
+ ${generator}
+ -S "${CMAKE_CURRENT_SOURCE_DIR}/test"
+ -B "${CMAKE_CURRENT_BINARY_DIR}/test")
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx
new file mode 100644
index 0000000..7f53271
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx
@@ -0,0 +1,6 @@
+import priv;
+
+int forwarding()
+{
+ return from_private();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx
new file mode 100644
index 0000000..e0b1872
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx
@@ -0,0 +1,8 @@
+export module importable;
+
+int forwarding();
+
+export int from_import()
+{
+ return forwarding();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx
new file mode 100644
index 0000000..c5b719a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx
@@ -0,0 +1,6 @@
+export module priv;
+
+export int from_private()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt
new file mode 100644
index 0000000..db0484d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_library NONE)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+find_package(export_bmi_and_interfaces REQUIRED)
+
+if (NOT TARGET CXXModules::export_bmi_and_interfaces)
+ message(FATAL_ERROR
+ "Missing imported target")
+endif ()
+
+get_property(file_sets TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY INTERFACE_CXX_MODULE_SETS)
+if (NOT file_sets STREQUAL "modules")
+ message(FATAL_ERROR
+ "Incorrect exported file sets in `CXXModules::export_bmi_and_interfaces`: `${file_sets}`")
+endif ()
+
+get_property(file_set_files TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY CXX_MODULE_SET_modules)
+if (NOT file_set_files STREQUAL "${expected_source_dir}/importable.cxx")
+ message(FATAL_ERROR
+ "Incorrect exported file set paths in CXXModules::export_bmi_and_interfaces`: `${file_set_files}`")
+endif ()
+
+get_property(imported_modules TARGET CXXModules::export_bmi_and_interfaces
+ PROPERTY IMPORTED_CXX_MODULES_DEBUG)
+if (NOT imported_modules MATCHES "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/importable.(gcm|pcm|ifc)")
+ message(FATAL_ERROR
+ "Incorrect exported modules in CXXModules::export_bmi_and_interfaces`: `${imported_modules}`")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt
new file mode 100644
index 0000000..5e4392a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt
new file mode 100644
index 0000000..80ddaf8
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt
@@ -0,0 +1,53 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_export_interfaces CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(export_interfaces STATIC)
+target_sources(export_interfaces
+ PRIVATE
+ forward.cxx
+ PRIVATE
+ FILE_SET modules_private TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ private.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(export_interfaces PUBLIC cxx_std_20)
+
+install(TARGETS export_interfaces
+ EXPORT CXXModules
+ FILE_SET modules DESTINATION "lib/cxx/miu")
+export(EXPORT CXXModules
+ NAMESPACE CXXModules::
+ FILE "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-targets.cmake")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-config.cmake"
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_interfaces-targets.cmake\")
+set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
+")
+
+set(generator
+ -G "${CMAKE_GENERATOR}")
+if (CMAKE_GENERATOR_TOOLSET)
+ list(APPEND generator
+ -T "${CMAKE_GENERATOR_TOOLSET}")
+endif ()
+if (CMAKE_GENERATOR_PLATFORM)
+ list(APPEND generator
+ -A "${CMAKE_GENERATOR_PLATFORM}")
+endif ()
+
+add_test(NAME export_interfaces_build
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dexpected_dir=${CMAKE_CURRENT_SOURCE_DIR}"
+ "-Dexport_interfaces_DIR=${CMAKE_CURRENT_BINARY_DIR}"
+ ${generator}
+ -S "${CMAKE_CURRENT_SOURCE_DIR}/test"
+ -B "${CMAKE_CURRENT_BINARY_DIR}/test")
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx
new file mode 100644
index 0000000..7f53271
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx
@@ -0,0 +1,6 @@
+import priv;
+
+int forwarding()
+{
+ return from_private();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx
new file mode 100644
index 0000000..e0b1872
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx
@@ -0,0 +1,8 @@
+export module importable;
+
+int forwarding();
+
+export int from_import()
+{
+ return forwarding();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx
new file mode 100644
index 0000000..c5b719a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx
@@ -0,0 +1,6 @@
+export module priv;
+
+export int from_private()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt
new file mode 100644
index 0000000..6145210
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_library NONE)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+find_package(export_interfaces REQUIRED)
+
+if (NOT TARGET CXXModules::export_interfaces)
+ message(FATAL_ERROR
+ "Missing imported target")
+endif ()
+
+get_property(file_sets TARGET CXXModules::export_interfaces
+ PROPERTY INTERFACE_CXX_MODULE_SETS)
+if (NOT file_sets STREQUAL "modules")
+ message(FATAL_ERROR
+ "Incorrect exported file sets in `CXXModules::export_interfaces`: `${file_sets}`")
+endif ()
+
+get_property(file_set_files TARGET CXXModules::export_interfaces
+ PROPERTY CXX_MODULE_SET_modules)
+if (NOT file_set_files STREQUAL "${expected_dir}/importable.cxx")
+ message(FATAL_ERROR
+ "Incorrect exported file set paths in CXXModules::export_interfaces`: `${file_set_files}`")
+endif ()
+
+get_property(imported_modules_set TARGET CXXModules::export_interfaces
+ PROPERTY IMPORTED_CXX_MODULES_DEBUG SET)
+if (imported_modules_set)
+ message(FATAL_ERROR
+ "Unexpected C++ modules specified.")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt
new file mode 100644
index 0000000..5e4392a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt
new file mode 100644
index 0000000..1dfb6da
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt
@@ -0,0 +1,56 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_export_interfaces CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(export_interfaces STATIC)
+target_sources(export_interfaces
+ PRIVATE
+ forward.cxx
+ PRIVATE
+ FILE_SET modules_private TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ private.cxx
+ PUBLIC
+ FILE_SET modules TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(export_interfaces PUBLIC cxx_std_20)
+
+install(TARGETS export_interfaces
+ EXPORT CXXModules
+ FILE_SET modules DESTINATION "lib/cxx/miu")
+install(EXPORT CXXModules
+ NAMESPACE CXXModules::
+ DESTINATION "lib/cmake/export_interfaces"
+ FILE "export_interfaces-targets.cmake")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-config.cmake"
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_interfaces-targets.cmake\")
+set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1)
+")
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-config.cmake"
+ DESTINATION "lib/cmake/export_interfaces")
+
+set(generator
+ -G "${CMAKE_GENERATOR}")
+if (CMAKE_GENERATOR_TOOLSET)
+ list(APPEND generator
+ -T "${CMAKE_GENERATOR_TOOLSET}")
+endif ()
+if (CMAKE_GENERATOR_PLATFORM)
+ list(APPEND generator
+ -A "${CMAKE_GENERATOR_PLATFORM}")
+endif ()
+
+add_test(NAME export_interfaces_build
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dexpected_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu"
+ "-Dexport_interfaces_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/export_interfaces"
+ ${generator}
+ -S "${CMAKE_CURRENT_SOURCE_DIR}/test"
+ -B "${CMAKE_CURRENT_BINARY_DIR}/test")
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx
new file mode 100644
index 0000000..7f53271
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx
@@ -0,0 +1,6 @@
+import priv;
+
+int forwarding()
+{
+ return from_private();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx
new file mode 100644
index 0000000..e0b1872
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx
@@ -0,0 +1,8 @@
+export module importable;
+
+int forwarding();
+
+export int from_import()
+{
+ return forwarding();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx
new file mode 100644
index 0000000..c5b719a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx
@@ -0,0 +1,6 @@
+export module priv;
+
+export int from_private()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt
new file mode 100644
index 0000000..6145210
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_library NONE)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+find_package(export_interfaces REQUIRED)
+
+if (NOT TARGET CXXModules::export_interfaces)
+ message(FATAL_ERROR
+ "Missing imported target")
+endif ()
+
+get_property(file_sets TARGET CXXModules::export_interfaces
+ PROPERTY INTERFACE_CXX_MODULE_SETS)
+if (NOT file_sets STREQUAL "modules")
+ message(FATAL_ERROR
+ "Incorrect exported file sets in `CXXModules::export_interfaces`: `${file_sets}`")
+endif ()
+
+get_property(file_set_files TARGET CXXModules::export_interfaces
+ PROPERTY CXX_MODULE_SET_modules)
+if (NOT file_set_files STREQUAL "${expected_dir}/importable.cxx")
+ message(FATAL_ERROR
+ "Incorrect exported file set paths in CXXModules::export_interfaces`: `${file_set_files}`")
+endif ()
+
+get_property(imported_modules_set TARGET CXXModules::export_interfaces
+ PROPERTY IMPORTED_CXX_MODULES_DEBUG SET)
+if (imported_modules_set)
+ message(FATAL_ERROR
+ "Unexpected C++ modules specified.")
+endif ()
diff --git a/Tests/RunCMake/CXXModules/examples/generated-stderr.txt b/Tests/RunCMake/CXXModules/examples/generated-stderr.txt
new file mode 100644
index 0000000..b9bbf34
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/generated-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:12 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt
new file mode 100644
index 0000000..73f7ff7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_generated CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+configure_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/importable.cxx.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/importable.cxx"
+ COPYONLY)
+
+add_executable(generated)
+target_sources(generated
+ PRIVATE
+ main.cxx
+ PRIVATE
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/importable.cxx")
+target_compile_features(generated PUBLIC cxx_std_20)
+
+add_test(NAME generated COMMAND generated)
diff --git a/Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in b/Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in
new file mode 100644
index 0000000..a9287d7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in
@@ -0,0 +1,5 @@
+export module importable;
+
+export int from_import() {
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/generated/main.cxx b/Tests/RunCMake/CXXModules/examples/generated/main.cxx
new file mode 100644
index 0000000..feb38d2
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/generated/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt
new file mode 100644
index 0000000..5e4392a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt
new file mode 100644
index 0000000..efaca0e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt
@@ -0,0 +1,27 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_install_bmi_and_interfaces CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(install_bmi_and_interfaces STATIC)
+target_sources(install_bmi_and_interfaces
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(install_bmi_and_interfaces PUBLIC cxx_std_20)
+
+install(TARGETS install_bmi_and_interfaces
+ ARCHIVE DESTINATION "lib"
+ CXX_MODULES_BMI DESTINATION "lib/cxx/bmi"
+ FILE_SET CXX_MODULES DESTINATION "lib/cxx/miu")
+
+add_test(NAME check-for-bmi
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dprefix=${CMAKE_INSTALL_PREFIX}"
+ "-Dbmi_destination=lib/cxx/bmi"
+ "-Dfs_destination=lib/cxx/miu"
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/check-for-bmi.cmake")
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake
new file mode 100644
index 0000000..a8ff1ad
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake
@@ -0,0 +1,7 @@
+include("${CMAKE_CURRENT_LIST_DIR}/../cxx-modules-find-bmi.cmake")
+
+report_dirs("${prefix}" "${bmi_destination}")
+check_for_bmi("${prefix}" "${bmi_destination}" importable)
+
+report_dirs("${prefix}" "${fs_destination}")
+check_for_interface("${prefix}" "${fs_destination}" "" importable.cxx)
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx
new file mode 100644
index 0000000..607680a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx
@@ -0,0 +1,6 @@
+export module importable;
+
+export int from_import()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt b/Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt
new file mode 100644
index 0000000..5e4392a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt
new file mode 100644
index 0000000..4e039f9
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_install_bmi CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(install_bmi STATIC)
+target_sources(install_bmi
+ PUBLIC
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(install_bmi PUBLIC cxx_std_20)
+
+install(TARGETS install_bmi
+ ARCHIVE DESTINATION "lib"
+ CXX_MODULES_BMI DESTINATION "lib/cxx/bmi")
+
+add_test(NAME check-for-bmi
+ COMMAND
+ "${CMAKE_COMMAND}"
+ "-Dprefix=${CMAKE_INSTALL_PREFIX}"
+ "-Ddestination=lib/cxx/bmi"
+ -P "${CMAKE_CURRENT_SOURCE_DIR}/check-for-bmi.cmake")
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake b/Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake
new file mode 100644
index 0000000..ff84ed6
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake
@@ -0,0 +1,4 @@
+include("${CMAKE_CURRENT_LIST_DIR}/../cxx-modules-find-bmi.cmake")
+
+report_dirs("${prefix}" "${destination}")
+check_for_bmi("${prefix}" "${destination}" importable)
diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx b/Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx
new file mode 100644
index 0000000..607680a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx
@@ -0,0 +1,6 @@
+export module importable;
+
+export int from_import()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt b/Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt
new file mode 100644
index 0000000..4652aec
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt
new file mode 100644
index 0000000..f5e9d94
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_internal_partitions CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+include(GenerateExportHeader)
+
+add_library(internal-partitions)
+generate_export_header(internal-partitions)
+target_sources(internal-partitions
+ PUBLIC
+ FILE_SET HEADERS
+ BASE_DIRS
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/internal-partitions_export.h"
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx
+ partition.cxx)
+target_compile_features(internal-partitions PUBLIC cxx_std_20)
+
+add_executable(exe)
+target_link_libraries(exe PRIVATE internal-partitions)
+target_sources(exe
+ PRIVATE
+ main.cxx)
+
+add_test(NAME exe COMMAND exe)
diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx b/Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx
new file mode 100644
index 0000000..8be521b
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx
@@ -0,0 +1,9 @@
+export module importable;
+import importable : internal_partition;
+
+#include "internal-partitions_export.h"
+
+export INTERNAL_PARTITIONS_EXPORT int from_import()
+{
+ return from_partition();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx b/Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx
new file mode 100644
index 0000000..feb38d2
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx b/Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx
new file mode 100644
index 0000000..b15f53c
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx
@@ -0,0 +1,6 @@
+module importable : internal_partition;
+
+int from_partition()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt b/Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt
new file mode 100644
index 0000000..4652aec
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/library-static-stderr.txt b/Tests/RunCMake/CXXModules/examples/library-static-stderr.txt
new file mode 100644
index 0000000..4652aec
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/library-static-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt
new file mode 100644
index 0000000..27fd94f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_library CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+include(GenerateExportHeader)
+
+add_library(library)
+generate_export_header(library)
+target_sources(library
+ PUBLIC
+ FILE_SET HEADERS
+ BASE_DIRS
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/library_export.h"
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(library PUBLIC cxx_std_20)
+
+add_executable(exe)
+target_link_libraries(exe PRIVATE library)
+target_sources(exe
+ PRIVATE
+ main.cxx)
+
+add_test(NAME exe COMMAND exe)
diff --git a/Tests/RunCMake/CXXModules/examples/library/importable.cxx b/Tests/RunCMake/CXXModules/examples/library/importable.cxx
new file mode 100644
index 0000000..72ed0df
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/library/importable.cxx
@@ -0,0 +1,8 @@
+export module importable;
+
+#include "library_export.h"
+
+export LIBRARY_EXPORT int from_import()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/library/main.cxx b/Tests/RunCMake/CXXModules/examples/library/main.cxx
new file mode 100644
index 0000000..feb38d2
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/library/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/partitions-stderr.txt b/Tests/RunCMake/CXXModules/examples/partitions-stderr.txt
new file mode 100644
index 0000000..4652aec
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/partitions-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt
new file mode 100644
index 0000000..3a7b0d4
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_partitions CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+include(GenerateExportHeader)
+
+add_library(partitions)
+generate_export_header(partitions)
+target_sources(partitions
+ PUBLIC
+ FILE_SET HEADERS
+ BASE_DIRS
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/partitions_export.h"
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx
+ partition.cxx)
+target_compile_features(partitions PUBLIC cxx_std_20)
+
+add_executable(exe)
+target_link_libraries(exe PRIVATE partitions)
+target_sources(exe
+ PRIVATE
+ main.cxx)
+
+add_test(NAME exe COMMAND exe)
diff --git a/Tests/RunCMake/CXXModules/examples/partitions/importable.cxx b/Tests/RunCMake/CXXModules/examples/partitions/importable.cxx
new file mode 100644
index 0000000..1e81aaf
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/partitions/importable.cxx
@@ -0,0 +1,9 @@
+export module importable;
+export import importable : partition;
+
+#include "partitions_export.h"
+
+export PARTITIONS_EXPORT int from_import()
+{
+ return from_partition();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/partitions/main.cxx b/Tests/RunCMake/CXXModules/examples/partitions/main.cxx
new file mode 100644
index 0000000..c5b78c9
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/partitions/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import() + from_partition();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/partitions/partition.cxx b/Tests/RunCMake/CXXModules/examples/partitions/partition.cxx
new file mode 100644
index 0000000..a47a4fd
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/partitions/partition.cxx
@@ -0,0 +1,8 @@
+export module importable : partition;
+
+#include "partitions_export.h"
+
+export PARTITIONS_EXPORT int from_partition()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt b/Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt b/Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt
new file mode 100644
index 0000000..b5f1c55
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt
@@ -0,0 +1 @@
+CMake Error: Public C\+\+ module source `.*/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx` requires the `priv` C\+\+ module which is provided by a private source
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt b/Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt
new file mode 100644
index 0000000..5e4392a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt
new file mode 100644
index 0000000..600fec4
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_public_req_private CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_library(public_req_private)
+target_sources(public_req_private
+ PRIVATE
+ FILE_SET private TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ priv.cxx
+ PUBLIC
+ FILE_SET public TYPE CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ pub.cxx)
+target_compile_features(public_req_private PUBLIC cxx_std_20)
+
+add_test(NAME cmake-version COMMAND "${CMAKE_COMMAND}" --version)
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx b/Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx
new file mode 100644
index 0000000..7c000b7
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx
@@ -0,0 +1,6 @@
+export module priv;
+
+export int g()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx b/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx
new file mode 100644
index 0000000..6ff2d23
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx
@@ -0,0 +1,8 @@
+export module pub;
+
+import priv;
+
+export int f()
+{
+ return g();
+}
diff --git a/Tests/RunCMake/CXXModules/examples/simple-stderr.txt b/Tests/RunCMake/CXXModules/examples/simple-stderr.txt
new file mode 100644
index 0000000..5e4392a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/simple-stderr.txt
@@ -0,0 +1,9 @@
+CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Warning \(dev\):
+ C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is
+ experimental. It is meant only for compiler developers to try.
+This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt
new file mode 100644
index 0000000..442e425
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.24)
+project(cxx_modules_simple CXX)
+
+include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake")
+
+add_executable(simple)
+target_sources(simple
+ PRIVATE
+ main.cxx
+ PRIVATE
+ FILE_SET CXX_MODULES
+ BASE_DIRS
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ FILES
+ importable.cxx)
+target_compile_features(simple PUBLIC cxx_std_20)
+
+add_test(NAME simple COMMAND simple)
diff --git a/Tests/RunCMake/CXXModules/examples/simple/importable.cxx b/Tests/RunCMake/CXXModules/examples/simple/importable.cxx
new file mode 100644
index 0000000..607680a
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/simple/importable.cxx
@@ -0,0 +1,6 @@
+export module importable;
+
+export int from_import()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/examples/simple/main.cxx b/Tests/RunCMake/CXXModules/examples/simple/main.cxx
new file mode 100644
index 0000000..feb38d2
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/examples/simple/main.cxx
@@ -0,0 +1,6 @@
+import importable;
+
+int main(int argc, char* argv[])
+{
+ return from_import();
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json
new file mode 100644
index 0000000..65f0759
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json
@@ -0,0 +1,45 @@
+{
+ "bmi-installation": {
+ "destination": "lib/cxx/modules/private/<CONFIG>",
+ "message-level": "MESSAGE_LAZY",
+ "permissions": " OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ",
+ "script-location": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-private.dir/install-cxx-module-bmi-<CONFIG_FORCE>.cmake"
+ },
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-bmi-install-private.dir/sources/module-internal-part.cxx.o": {
+ "destination": null,
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-bmi-install-private.dir/sources/module-part.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-bmi-install-private.dir/sources/module.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-private.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json
new file mode 100644
index 0000000..9c8a895
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json
@@ -0,0 +1,45 @@
+{
+ "bmi-installation": {
+ "destination": "lib/cxx/modules/<CONFIG>",
+ "message-level": "",
+ "permissions": "",
+ "script-location": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-public.dir/install-cxx-module-bmi-noconfig.cmake"
+ },
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-bmi-install-public.dir/sources/module-internal-part.cxx.o": {
+ "destination": "lib/cxx/internals",
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-bmi-install-public.dir/sources/module-part.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-bmi-install-public.dir/sources/module.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-public.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json
new file mode 100644
index 0000000..0545981
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json
@@ -0,0 +1,73 @@
+{
+ "bmi-installation": null,
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-exports-private.dir/sources/module-internal-part.cxx.o": {
+ "destination": null,
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-exports-private.dir/sources/module-part.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-exports-private.dir/sources/module.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "lib/cmake/export1",
+ "export-name" : "with-private",
+ "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/d2e2673818fd2bd8c45c0e3ed0e38fcd",
+ "install" : true,
+ "namespace" : "export1::"
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "lib/cmake/export2",
+ "export-name" : "with-private",
+ "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/28cd47cb4c96ad5cadaa3fb1b0201ae8",
+ "install" : true,
+ "namespace" : ""
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "<BINARY_DIR>/lib/cmake/export1",
+ "export-name" : "with-private",
+ "export-prefix" : "<BINARY_DIR>/lib/cmake/export1",
+ "install" : false,
+ "namespace" : "export1::"
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "<BINARY_DIR>/lib/cmake/export2",
+ "export-name" : "with-private",
+ "export-prefix" : "<BINARY_DIR>/lib/cmake/export2",
+ "install" : false,
+ "namespace" : ""
+ }
+ ],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-private.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json
new file mode 100644
index 0000000..adc3ae3
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json
@@ -0,0 +1,73 @@
+{
+ "bmi-installation": null,
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-exports-public.dir/sources/module-internal-part.cxx.o": {
+ "destination": "lib/cxx/internals",
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-exports-public.dir/sources/module-part.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-exports-public.dir/sources/module.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "lib/cmake/export1",
+ "export-name" : "with-public",
+ "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/d2e2673818fd2bd8c45c0e3ed0e38fcd",
+ "install" : true,
+ "namespace" : "export1::"
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "lib/cmake/export2",
+ "export-name" : "with-public",
+ "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/28cd47cb4c96ad5cadaa3fb1b0201ae8",
+ "install" : true,
+ "namespace" : ""
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "<BINARY_DIR>/lib/cmake/export1",
+ "export-name" : "with-public",
+ "export-prefix" : "<BINARY_DIR>/lib/cmake/export1",
+ "install" : false,
+ "namespace" : "export1::"
+ },
+ {
+ "cxx-module-info-dir" : "cxx-modules",
+ "destination" : "<BINARY_DIR>/lib/cmake/export2",
+ "export-name" : "with-public",
+ "export-prefix" : "<BINARY_DIR>/lib/cmake/export2",
+ "install" : false,
+ "namespace" : ""
+ }
+ ],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-public.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json
new file mode 100644
index 0000000..9ba6568
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json
@@ -0,0 +1,40 @@
+{
+ "bmi-installation": null,
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-file-sets-private.dir/sources/module-internal-part.cxx.o": {
+ "destination": null,
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-file-sets-private.dir/sources/module-part.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ },
+ "CMakeFiles/ninja-file-sets-private.dir/sources/module.cxx.o": {
+ "destination": null,
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PRIVATE"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-file-sets-private.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json
new file mode 100644
index 0000000..46e2cbf
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json
@@ -0,0 +1,40 @@
+{
+ "bmi-installation": null,
+ "compiler-id": "<IGNORE>",
+ "config": "<CONFIG>",
+ "cxx-modules": {
+ "CMakeFiles/ninja-file-sets-public.dir/<CONFIG_DIR>sources/module-internal-part.cxx.o": {
+ "destination": "lib/cxx/internals",
+ "name": "internal_partitions",
+ "relative-directory": "sources",
+ "source": "<SOURCE_DIR>/sources/module-internal-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-file-sets-public.dir/<CONFIG_DIR>sources/module-part.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module-part.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ },
+ "CMakeFiles/ninja-file-sets-public.dir/<CONFIG_DIR>sources/module.cxx.o": {
+ "destination": "lib/cxx",
+ "name": "modules",
+ "relative-directory": "",
+ "source": "<SOURCE_DIR>/sources/module.cxx",
+ "type": "CXX_MODULES",
+ "visibility": "PUBLIC"
+ }
+ },
+ "dir-cur-bld": "<BINARY_DIR>",
+ "dir-cur-src": "<SOURCE_DIR>",
+ "dir-top-bld": "<BINARY_DIR>",
+ "dir-top-src": "<SOURCE_DIR>",
+ "exports": [],
+ "include-dirs": [],
+ "language": "CXX",
+ "linked-target-dirs": [],
+ "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-file-sets-public.dir"
+}
diff --git a/Tests/RunCMake/CXXModules/sources/c-anchor.c b/Tests/RunCMake/CXXModules/sources/c-anchor.c
new file mode 100644
index 0000000..c782188
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/c-anchor.c
@@ -0,0 +1,4 @@
+int c_anchor()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx b/Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx
new file mode 100644
index 0000000..9c94ec1
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx
@@ -0,0 +1,4 @@
+int cxx_anchor()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/sources/module-header.h b/Tests/RunCMake/CXXModules/sources/module-header.h
new file mode 100644
index 0000000..982617e
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-header.h
@@ -0,0 +1,9 @@
+#ifndef module_header_h
+#define module_header_h
+
+inline int h()
+{
+ return 0;
+}
+
+#endif
diff --git a/Tests/RunCMake/CXXModules/sources/module-impl.cxx b/Tests/RunCMake/CXXModules/sources/module-impl.cxx
new file mode 100644
index 0000000..4718999
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-impl.cxx
@@ -0,0 +1,6 @@
+module M;
+
+int f()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx b/Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx
new file mode 100644
index 0000000..be77b0d
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx
@@ -0,0 +1,11 @@
+#ifdef _MSC_VER
+// Only MSVC supports this pattern.
+module M : internal_part;
+#else
+module M;
+#endif
+
+int i()
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CXXModules/sources/module-internal-part.cxx b/Tests/RunCMake/CXXModules/sources/module-internal-part.cxx
new file mode 100644
index 0000000..fa82afb
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-internal-part.cxx
@@ -0,0 +1,3 @@
+module M : internal_part;
+
+int i();
diff --git a/Tests/RunCMake/CXXModules/sources/module-part-impl.cxx b/Tests/RunCMake/CXXModules/sources/module-part-impl.cxx
new file mode 100644
index 0000000..46d5d9f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-part-impl.cxx
@@ -0,0 +1,13 @@
+#ifdef _MSC_VER
+// Only MSVC supports this pattern.
+module M : part;
+#else
+module M;
+#endif
+
+import M : internal_part;
+
+int p()
+{
+ return i();
+}
diff --git a/Tests/RunCMake/CXXModules/sources/module-part.cxx b/Tests/RunCMake/CXXModules/sources/module-part.cxx
new file mode 100644
index 0000000..137c16f
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-part.cxx
@@ -0,0 +1,3 @@
+export module M : part;
+
+int p();
diff --git a/Tests/RunCMake/CXXModules/sources/module-use.cxx b/Tests/RunCMake/CXXModules/sources/module-use.cxx
new file mode 100644
index 0000000..2d060cd
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module-use.cxx
@@ -0,0 +1,6 @@
+import M;
+
+int main(int argc, char* argv[])
+{
+ return f() + p();
+}
diff --git a/Tests/RunCMake/CXXModules/sources/module.cxx b/Tests/RunCMake/CXXModules/sources/module.cxx
new file mode 100644
index 0000000..a631354
--- /dev/null
+++ b/Tests/RunCMake/CXXModules/sources/module.cxx
@@ -0,0 +1,5 @@
+export module M;
+export import M : part;
+import M : internal_part;
+
+int f();
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index c8234ec..80a7c69 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -940,8 +940,8 @@ set(CMAKE_DEPENDS_CHECK_C
set(CMAKE_RELATIVE_PATH_TOP_SOURCE \"${RunCMake_TEST_SOURCE_DIR}\")
set(CMAKE_RELATIVE_PATH_TOP_BINARY \"${RunCMake_TEST_BINARY_DIR}\")
")
- run_cmake_command(cmake_depends ${CMAKE_COMMAND} -E cmake_depends
- "Unix Makefiles"
+ run_cmake_command(cmake_depends ${CMAKE_COMMAND} -E env VERBOSE=1
+ ${CMAKE_COMMAND} -E cmake_depends "Unix Makefiles"
${RunCMake_TEST_SOURCE_DIR} ${RunCMake_TEST_SOURCE_DIR}
${RunCMake_TEST_BINARY_DIR} ${RunCMake_TEST_BINARY_DIR}
${RunCMake_TEST_BINARY_DIR}/CMakeFiles/DepTarget.dir/DependInfo.cmake
diff --git a/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt b/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt
index 8fe092b..cf972a8 100644
--- a/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt
+++ b/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt
@@ -1 +1 @@
-^Scanning dependencies of target DepTarget$
+Scanning dependencies of target DepTarget$
diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
index d5f596e..01a004c 100644
--- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py
+++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py
@@ -213,6 +213,16 @@ def check_directory(c):
assert is_int(at["index"])
assert c["targets"][at["index"]]["name"] == et["index"]
+ if e.get("cxxModuleBmiTarget", None) is not None:
+ expected_keys.append("cxxModuleBmiTarget")
+ et = e["cxxModuleBmiTarget"]
+ at = a["cxxModuleBmiTarget"]
+ assert is_dict(at)
+ assert sorted(at.keys()) == ["id", "index"]
+ assert matches(at["id"], et["id"])
+ assert is_int(at["index"])
+ assert c["targets"][at["index"]]["name"] == et["index"]
+
if e["backtrace"] is not None:
expected_keys.append("backtrace")
check_backtrace(d, a["backtrace"], e["backtrace"])
diff --git a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake
index 3908f42..dad0dd3 100644
--- a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake
@@ -13,6 +13,9 @@ run_cmake(zip)
# Extracting only selected files or directories
run_cmake(zip-filtered)
+run_cmake(create-missing-args)
+run_cmake(extract-missing-args)
+
run_cmake(unsupported-format)
run_cmake(zip-with-bad-compression)
run_cmake(7zip-with-bad-compression)
diff --git a/Tests/RunCMake/File_Archive/create-missing-args-result.txt b/Tests/RunCMake/File_Archive/create-missing-args-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/create-missing-args-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt b/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt
new file mode 100644
index 0000000..ecfe401
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt
@@ -0,0 +1,9 @@
+^CMake Error at create-missing-args.cmake:[0-9]+ \(file\):
+ file Keywords missing values:
+
+ OUTPUT
+ FORMAT
+ COMPRESSION
+ COMPRESSION_LEVEL
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Archive/create-missing-args.cmake b/Tests/RunCMake/File_Archive/create-missing-args.cmake
new file mode 100644
index 0000000..a0c84d2
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/create-missing-args.cmake
@@ -0,0 +1,8 @@
+file(ARCHIVE_CREATE
+ OUTPUT # missing output path
+ FORMAT # missing output format
+ COMPRESSION # missing compression type
+ COMPRESSION_LEVEL # missing compression level
+ MTIME # missing modification time
+ PATHS # no paths
+ )
diff --git a/Tests/RunCMake/File_Archive/extract-missing-args-result.txt b/Tests/RunCMake/File_Archive/extract-missing-args-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/extract-missing-args-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt b/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt
new file mode 100644
index 0000000..96c779f
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at extract-missing-args.cmake:[0-9]+ \(file\):
+ file Keywords missing values:
+
+ INPUT
+ DESTINATION
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Archive/extract-missing-args.cmake b/Tests/RunCMake/File_Archive/extract-missing-args.cmake
new file mode 100644
index 0000000..21c5d99
--- /dev/null
+++ b/Tests/RunCMake/File_Archive/extract-missing-args.cmake
@@ -0,0 +1,5 @@
+file(ARCHIVE_EXTRACT
+ INPUT # missing input
+ DESTINATION # missing destination
+ PATTERNS # no patterns
+ )
diff --git a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
index a6ea314..dd6a2e7 100644
--- a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
+++ b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt
@@ -1,4 +1,6 @@
CMake Error at BadArgContent.cmake:[0-9]+ \(file\):
- file CONFIGURE CONTENT option needs a value.
+ file CONFIGURE keywords missing values:
+
+ CONTENT
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
index b5a924c..e1bf7b4 100644
--- a/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
+++ b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt
@@ -1,4 +1,6 @@
CMake Error at BadArgOutput.cmake:[0-9]+ \(file\):
- file CONFIGURE OUTPUT option needs a value.
+ file CONFIGURE keywords missing values:
+
+ OUTPUT
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/File_Configure/NoArgContent-result.txt b/Tests/RunCMake/File_Configure/NoArgContent-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgContent-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt b/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt
new file mode 100644
index 0000000..2e8dd9a
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at NoArgContent.cmake:[0-9]+ \(file\):
+ file CONFIGURE CONTENT option is mandatory.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Configure/NoArgContent.cmake b/Tests/RunCMake/File_Configure/NoArgContent.cmake
new file mode 100644
index 0000000..cf52c46
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgContent.cmake
@@ -0,0 +1 @@
+file(CONFIGURE OUTPUT "")
diff --git a/Tests/RunCMake/File_Configure/NoArgOutput-result.txt b/Tests/RunCMake/File_Configure/NoArgOutput-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgOutput-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt b/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt
new file mode 100644
index 0000000..53de48b
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at NoArgOutput.cmake:[0-9]+ \(file\):
+ file CONFIGURE OUTPUT option is mandatory.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/File_Configure/NoArgOutput.cmake b/Tests/RunCMake/File_Configure/NoArgOutput.cmake
new file mode 100644
index 0000000..77e9cdc
--- /dev/null
+++ b/Tests/RunCMake/File_Configure/NoArgOutput.cmake
@@ -0,0 +1 @@
+file(CONFIGURE CONTENT "")
diff --git a/Tests/RunCMake/File_Configure/RunCMakeTest.cmake b/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
index 5022985..008ce67 100644
--- a/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Configure/RunCMakeTest.cmake
@@ -9,6 +9,8 @@ run_cmake(DirOutput)
run_cmake(NewLineStyle-NoArg)
run_cmake(NewLineStyle-ValidArg)
run_cmake(NewLineStyle-WrongArg)
+run_cmake(NoArgOutput)
+run_cmake(NoArgContent)
run_cmake(SubDir)
run_cmake(AtOnly)
run_cmake(EscapeQuotes)
diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
index e823b25..4278bce 100644
--- a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
+++ b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt
@@ -1,4 +1,6 @@
CMake Error at EmptyCondition1.cmake:2 \(file\):
- file Incorrect arguments to GENERATE subcommand.
+ file GENERATE keywords missing values:
+
+ CONDITION
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/InputAndContent-check.cmake b/Tests/RunCMake/File_Generate/InputAndContent-check.cmake
new file mode 100644
index 0000000..5c9b803
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/InputAndContent-check.cmake
@@ -0,0 +1,8 @@
+file(READ "${RunCMake_TEST_BINARY_DIR}/output-INPUT.txt" input)
+if(NOT input MATCHES "INPUT file")
+ string(APPEND RunCMake_TEST_FAILED "INPUT incorrectly overridden by CONTENT")
+endif()
+file(READ "${RunCMake_TEST_BINARY_DIR}/output-CONTENT.txt" content)
+if(NOT content MATCHES "CONTENT argument")
+ string(APPEND RunCMake_TEST_FAILED "CONTENT incorrectly overridden by INPUT")
+endif()
diff --git a/Tests/RunCMake/File_Generate/InputAndContent-input.txt b/Tests/RunCMake/File_Generate/InputAndContent-input.txt
new file mode 100644
index 0000000..73f162b
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/InputAndContent-input.txt
@@ -0,0 +1 @@
+INPUT file
diff --git a/Tests/RunCMake/File_Generate/InputAndContent.cmake b/Tests/RunCMake/File_Generate/InputAndContent.cmake
new file mode 100644
index 0000000..9c3977a
--- /dev/null
+++ b/Tests/RunCMake/File_Generate/InputAndContent.cmake
@@ -0,0 +1,10 @@
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-INPUT.txt"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/InputAndContent-input.txt"
+ CONTENT "CONTENT argument"
+)
+file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-CONTENT.txt"
+ CONTENT "CONTENT argument"
+ INPUT "${CMAKE_CURRENT_SOURCE_DIR}/InputAndContent-input.txt"
+)
diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
index bc71f2f..4059bf8 100644
--- a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
+++ b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt
@@ -1,4 +1,6 @@
CMake Error at NewLineStyle-NoArg.cmake:[0-9]+ \(file\):
- file Incorrect arguments to GENERATE subcommand.
+ file GENERATE keywords missing values:
+
+ NEWLINE_STYLE
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
index be3bf04..5a670ae 100644
--- a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
+++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake
@@ -17,6 +17,7 @@ run_cmake(EmptyCondition2)
run_cmake(BadCondition)
run_cmake(DebugEvaluate)
run_cmake(GenerateSource)
+run_cmake(InputAndContent)
run_cmake(OutputNameMatchesSources)
run_cmake(OutputNameMatchesObjects)
run_cmake(OutputNameMatchesOtherSources)
diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
index f479dcf..661ae3f 100644
--- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
@@ -24,6 +24,27 @@ endif()
# We need a real pkg-config to run the test for get_variable.
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
+ string(FIND "${CMAKE_CURRENT_BINARY_DIR}" " " IS_SPACES_IN_PATH)
+ if(IS_SPACES_IN_PATH GREATER -1)
+ string(REPLACE " " "\\ " ESCAPED_ROOT "${CMAKE_CURRENT_BINARY_DIR}")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_spaces.pc" "
+libdir=${ESCAPED_ROOT}
+Name: test_spaces.pc
+Version: 0.0
+Description: test spaces
+Libs: -L\${libdir}
+")
+ set(PKG_CONFIG_PATH_SAVED "$ENV{PKG_CONFIG_PATH}")
+ set(ENV{PKG_CONFIG_PATH} "${CMAKE_CURRENT_BINARY_DIR}")
+ execute_process(COMMAND "${PKG_CONFIG_EXECUTABLE}" --libs test_spaces
+ ERROR_QUIET COMMAND_ERROR_IS_FATAL ANY
+ OUTPUT_VARIABLE test_spaces_LIBS)
+ set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH_SAVED}")
+ string(STRIP "${test_spaces_LIBS}" test_spaces_LIBS_STRIPPED)
+ if(NOT "${test_spaces_LIBS_STRIPPED}" STREQUAL "-L${ESCAPED_ROOT}")
+ set(PKG_CONFIG_DONT_SUPPORT_SPACES_IN_PATH TRUE)
+ endif()
+ endif()
run_cmake(FindPkgConfig_GET_VARIABLE)
run_cmake(FindPkgConfig_GET_VARIABLE_PREFIX_PATH)
run_cmake(FindPkgConfig_GET_VARIABLE_PKGCONFIG_PATH)
@@ -32,5 +53,7 @@ if (PKG_CONFIG_FOUND)
run_cmake(FindPkgConfig_VERSION_OPERATORS)
run_cmake(FindPkgConfig_GET_MATCHING_MODULE_NAME)
run_cmake(FindPkgConfig_empty_target)
- run_cmake(FindPkgConfig_LIBRARY_PATH)
+ if(NOT PKG_CONFIG_DONT_SUPPORT_SPACES_IN_PATH)
+ run_cmake(FindPkgConfig_LIBRARY_PATH)
+ endif()
endif ()
diff --git a/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake
new file mode 100644
index 0000000..a1ae6ac
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake
@@ -0,0 +1,28 @@
+set(expected_compile_commands
+[==[^\[
+{
+ "directory": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/CompileCommands-build|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\CompileCommands-build)",
+ "command": "[^
+]*Debug[^
+]*",
+ "file": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/main\.c|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\main\.c)"
+},
+{
+ "directory": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/CompileCommands-build|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\CompileCommands-build)",
+ "command": "[^
+]*Release[^
+]*",
+ "file": "[^
+]*(/Tests/RunCMake/NinjaMultiConfig/main\.c|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\main\.c)"
+}
+]$]==])
+
+file(READ "${RunCMake_TEST_BINARY_DIR}/compile_commands.json" actual_compile_commands)
+if(NOT actual_compile_commands MATCHES "${expected_compile_commands}")
+ string(REPLACE "\n" "\n " expected_compile_commands_formatted "${expected_compile_commands}")
+ string(REPLACE "\n" "\n " actual_compile_commands_formatted "${actual_compile_commands}")
+ string(APPEND RunCMake_TEST_FAILED "Expected compile_commands.json to match:\n ${expected_compile_commands_formatted}\nActual compile_commands.json:\n ${actual_compile_commands_formatted}\n")
+endif()
diff --git a/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake b/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake
new file mode 100644
index 0000000..fc44d5a
--- /dev/null
+++ b/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+
+add_executable(exe main.c)
diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
index 738bc6c..c040e8f 100644
--- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
+++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake
@@ -453,6 +453,11 @@ run_cmake_command(NoUnusedVariables ${CMAKE_COMMAND} ${CMAKE_CURRENT_LIST_DIR}
"-DCMAKE_DEFAULT_BUILD_TYPE=Debug"
"-DCMAKE_DEFAULT_CONFIGS=all"
)
+unset(RunCMake_TEST_BINARY_DIR)
+
+set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release;-DCMAKE_CROSS_CONFIGS=all;-DCMAKE_EXPORT_COMPILE_COMMANDS=ON")
+run_cmake(CompileCommands)
+unset(RunCMake_TEST_OPTIONS)
# CudaSimple uses separable compilation, which is currently only supported on NVCC.
if(CMake_TEST_CUDA)
diff --git a/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake b/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
index bcdc101..1701a36 100644
--- a/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
+++ b/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake
@@ -5,6 +5,7 @@ if(NOT EXISTS "${vcProjectFile}")
endif()
set(found_iface_h 0)
+set(found_int_dir 0)
file(STRINGS "${vcProjectFile}" lines)
foreach(line IN LISTS lines)
if(line MATCHES "<([A-Za-z0-9_]+) +Include=.*iface\\.h")
@@ -19,7 +20,15 @@ foreach(line IN LISTS lines)
endif()
set(found_iface_h 1)
endif()
+ if(line MATCHES "^ *<IntDir [^<>]+>[^<>]+</IntDir>")
+ set(found_int_dir 1)
+ endif()
endforeach()
if(NOT found_iface_h)
set(RunCMake_TEST_FAILED "iface.h not referenced in\n ${vcProjectFile}")
+ return()
+endif()
+if(NOT found_int_dir)
+ set(RunCMake_TEST_FAILED "No references to IntDir in\n ${vcProjectFile}")
+ return()
endif()
diff --git a/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake b/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake
index 9c9074e..22e2bb3 100644
--- a/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake
+++ b/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake
@@ -4,6 +4,7 @@ include(RunCMake)
run_cmake(VsDotnetSdkCustomCommandsTarget)
run_cmake(VsDotnetSdkCustomCommandsSource)
run_cmake(VsDotnetSdkStartupObject)
+run_cmake(VsDotnetSdkDefines)
run_cmake(DotnetSdkVariables)
function(run_VsDotnetSdk)
diff --git a/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake
new file mode 100644
index 0000000..eaeba24
--- /dev/null
+++ b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake
@@ -0,0 +1,64 @@
+#
+# Check C# VS project for required elements.
+#
+set(csProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj")
+if(NOT EXISTS "${csProjectFile}")
+ set(RunCMake_TEST_FAILED "Project file ${csProjectFile} does not exist.")
+ return()
+endif()
+
+
+set(inDebug FALSE)
+set(inRelease FALSE)
+set(debugOK FALSE)
+set(releaseOK FALSE)
+
+
+file(STRINGS "${csProjectFile}" lines)
+foreach(line IN LISTS lines)
+ #message(STATUS ${line})
+ if(line MATCHES "^ *<PropertyGroup .*Debug.*")
+ set(inDebug TRUE)
+ elseif(line MATCHES "^ *<PropertyGroup .*Release.*")
+ set(inRelease TRUE)
+ elseif(line MATCHES "^ *</PropertyGroup> *$")
+ set(inRelease FALSE)
+ set(inDebug FALSE)
+ elseif(inDebug AND
+ (line MATCHES "^ *<DefineConstants>.*MY_FOO_DEFINE.*</DefineConstants> *$") AND
+ (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_DEBUG.*</DefineConstants> *$") AND
+ (NOT (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_RELEASE.*</DefineConstants> *$")) AND
+ (NOT (line MATCHES "^ *<DefineConstants>.*MY_BAR_ASSIGNMENT=bar.*</DefineConstants> *$"))
+ )
+ set(debugOK TRUE)
+ elseif(inRelease AND
+ (line MATCHES "^ *<DefineConstants>.*MY_FOO_DEFINE.*</DefineConstants> *$") AND
+ (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_RELEASE.*</DefineConstants> *$") AND
+ (NOT (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_DEBUG.*</DefineConstants> *$")) AND
+ (NOT (line MATCHES "^ *<DefineConstants>.*MY_BAR_ASSIGNMENT=bar.*</DefineConstants> *$"))
+ )
+ set(releaseOK TRUE)
+ endif()
+endforeach()
+
+function(print_csprojfile)
+ file(STRINGS "${csProjectFile}" lines)
+ foreach(line IN LISTS lines)
+ message(STATUS ${line})
+ endforeach()
+endfunction()
+
+
+if(NOT debugOK)
+ message(STATUS "Failed to set Debug configuration defines correctly.")
+ set(RunCMake_TEST_FAILED "Failed to set Debug configuration defines correctly.")
+ print_csprojfile()
+ return()
+endif()
+
+if(NOT releaseOK)
+ message(STATUS "Failed to set Release configuration defines correctly.")
+ set(RunCMake_TEST_FAILED "Failed to set Release configuration defines correctly.")
+ print_csprojfile()
+ return()
+endif()
diff --git a/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake
new file mode 100644
index 0000000..d89f19b
--- /dev/null
+++ b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake
@@ -0,0 +1,19 @@
+enable_language(CSharp)
+if(NOT CMAKE_CSharp_COMPILER)
+ return()
+endif()
+
+set(CMAKE_DOTNET_SDK "Microsoft.NET.Sdk")
+set(CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION "net5.0")
+
+add_executable(foo csharponly.cs lib1.cs)
+
+# Issue 23376
+target_compile_definitions(
+ foo
+ PUBLIC
+ MY_FOO_DEFINE
+ "MY_BAR_ASSIGNMENT=bar"
+ $<$<CONFIG:Debug>:DEFINE_ONLY_FOR_DEBUG>
+ $<$<CONFIG:Release>:DEFINE_ONLY_FOR_RELEASE>
+)
diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake
index be44ecd..efd70cf 100644
--- a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake
+++ b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake
@@ -43,6 +43,8 @@ check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED" "enableGPUFrameCaptureMo
check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_METAL" "enableGPUFrameCaptureMode=\"1\"")
check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED_MIXED_CASE" "enableGPUFrameCaptureMode=\"3\"")
check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_METAL_MIXED_CASE" "enableGPUFrameCaptureMode=\"1\"")
+check_property("LAUNCH_MODE_AUTO" "launchStyle=\"0\"")
+check_property("LAUNCH_MODE_WAIT" "launchStyle=\"1\"")
check_property("EXECUTABLE" "myExecutable")
check_property("ARGUMENTS" [=["--foo"]=])
diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake
index 126a9fc..5edbc89 100644
--- a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake
+++ b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake
@@ -38,6 +38,8 @@ create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED ENABLE_GPU_FRA
create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_METAL ENABLE_GPU_FRAME_CAPTURE_MODE Metal)
create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED_MIXED_CASE ENABLE_GPU_FRAME_CAPTURE_MODE DISAbled)
create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_METAL_MIXED_CASE ENABLE_GPU_FRAME_CAPTURE_MODE METal)
+create_scheme_for_property(LAUNCH_MODE_AUTO LAUNCH_MODE AUTO)
+create_scheme_for_property(LAUNCH_MODE_WAIT LAUNCH_MODE WAIT)
create_scheme_for_property(EXECUTABLE EXECUTABLE myExecutable)
create_scheme_for_property(ARGUMENTS ARGUMENTS "--foo;--bar=baz")
create_scheme_for_property(ENVIRONMENT ENVIRONMENT "FOO=foo;BAR=bar")
diff --git a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake
index 6480b2e..03a15fc 100644
--- a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake
+++ b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake
@@ -82,3 +82,61 @@ run_cmake(defer_get_call_id_var)
run_cmake(defer_missing_arg)
run_cmake(defer_missing_call)
run_cmake(defer_unknown_option)
+
+# Default log level
+run_cmake_command(
+ get_message_log_level_none
+ ${CMAKE_COMMAND}
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from cache
+run_cmake_command(
+ get_message_log_level_cache
+ ${CMAKE_COMMAND}
+ -DCMAKE_MESSAGE_LOG_LEVEL=TRACE
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from regular variable
+run_cmake_command(
+ get_message_log_level_var
+ ${CMAKE_COMMAND}
+ -DNEW_LOG_LEVEL=TRACE
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from command line
+run_cmake_command(
+ get_message_log_level_cli
+ ${CMAKE_COMMAND}
+ --log-level=DEBUG
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from command line, it has higher priority over a cache variable
+run_cmake_command(
+ get_message_log_level_cli_and_cache
+ ${CMAKE_COMMAND}
+ --log-level=DEBUG
+ -DCMAKE_MESSAGE_LOG_LEVEL=TRACE
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from command line, it has higher priority over a regular variable
+run_cmake_command(
+ get_message_log_level_cli_and_var
+ ${CMAKE_COMMAND}
+ --log-level=DEBUG
+ -DNEW_LOG_LEVEL=TRACE
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
+
+# Log level from variable, it has higher priority over a cache variable
+run_cmake_command(
+ get_message_log_level_var_and_cache
+ ${CMAKE_COMMAND}
+ -DNEW_LOG_LEVEL=DEBUG
+ -DCMAKE_MESSAGE_LOG_LEVEL=TRACE
+ -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake
+ )
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level.cmake b/Tests/RunCMake/cmake_language/get_message_log_level.cmake
new file mode 100644
index 0000000..1740c1f
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level.cmake
@@ -0,0 +1,5 @@
+if(NEW_LOG_LEVEL)
+ set(CMAKE_MESSAGE_LOG_LEVEL "${NEW_LOG_LEVEL}")
+endif()
+cmake_language(GET_MESSAGE_LOG_LEVEL log_level)
+message(STATUS "log level is: ${log_level}")
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt
new file mode 100644
index 0000000..cf1cd7b
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt
@@ -0,0 +1 @@
+log level is: TRACE
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt
new file mode 100644
index 0000000..4d6e1eb
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt
@@ -0,0 +1 @@
+log level is: DEBUG
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt
new file mode 100644
index 0000000..4d6e1eb
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt
@@ -0,0 +1 @@
+log level is: DEBUG
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt
new file mode 100644
index 0000000..4d6e1eb
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt
@@ -0,0 +1 @@
+log level is: DEBUG
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt
new file mode 100644
index 0000000..92ffd34
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt
@@ -0,0 +1 @@
+log level is: STATUS
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt
new file mode 100644
index 0000000..cf1cd7b
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt
@@ -0,0 +1 @@
+log level is: TRACE
diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt
new file mode 100644
index 0000000..4d6e1eb
--- /dev/null
+++ b/Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt
@@ -0,0 +1 @@
+log level is: DEBUG
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index aff4735..db88956 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -47,6 +47,7 @@ run_cmake(GLOB_RECURSE)
run_cmake(GLOB_RECURSE-noexp-FOLLOW_SYMLINKS)
run_cmake(SIZE)
run_cmake(SIZE-error-does-not-exist)
+run_cmake(TIMESTAMP)
run_cmake(REMOVE-empty)
diff --git a/Tests/RunCMake/file/TIMESTAMP-stdout.txt b/Tests/RunCMake/file/TIMESTAMP-stdout.txt
new file mode 100644
index 0000000..42be6ba
--- /dev/null
+++ b/Tests/RunCMake/file/TIMESTAMP-stdout.txt
@@ -0,0 +1 @@
+-- '[0-9]*-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-6][0-9]Z'
diff --git a/Tests/RunCMake/file/TIMESTAMP.cmake b/Tests/RunCMake/file/TIMESTAMP.cmake
new file mode 100644
index 0000000..2bd2577
--- /dev/null
+++ b/Tests/RunCMake/file/TIMESTAMP.cmake
@@ -0,0 +1,2 @@
+file(TIMESTAMP "TIMESTAMP.cmake" output UTC)
+message(STATUS "'${output}'")
diff --git a/Tests/RunCMake/find_file/RunCMakeTest.cmake b/Tests/RunCMake/find_file/RunCMakeTest.cmake
index 23765d4..296bb71 100644
--- a/Tests/RunCMake/find_file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_file/RunCMakeTest.cmake
@@ -7,6 +7,10 @@ run_cmake(Required)
run_cmake(NO_CACHE)
run_cmake(REGISTRY_VIEW-no-view)
run_cmake(REGISTRY_VIEW-wrong-view)
+run_cmake(VALIDATOR-no-function)
+run_cmake(VALIDATOR-undefined-function)
+run_cmake(VALIDATOR-specify-macro)
+run_cmake(VALIDATOR)
run_cmake_with_options(FromPATHEnvDebugVar --debug-find-var=PrefixInPATH_File)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt
new file mode 100644
index 0000000..4d49649
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_file\):
+ find_file missing required argument for "VALIDATOR"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_file/VALIDATOR-no-function.cmake
new file mode 100644
index 0000000..4800fe9
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-no-function.cmake
@@ -0,0 +1,2 @@
+
+find_file(result NAMES input.txt VALIDATOR)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt
new file mode 100644
index 0000000..7e0eda0
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_file\):
+ find_file command specified for "VALIDATOR" is not a function: check.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake
new file mode 100644
index 0000000..ec0ce9a
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake
@@ -0,0 +1,5 @@
+
+macro(CHECK result path)
+endmacro()
+
+find_file(result NAMES input.txt VALIDATOR check)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-stderr.txt
new file mode 100644
index 0000000..6c8159b
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-stderr.txt
@@ -0,0 +1,3 @@
+CHECK='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+CHECK='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+CHECK='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
diff --git a/Tests/RunCMake/find_file/VALIDATOR-stdout.txt b/Tests/RunCMake/find_file/VALIDATOR-stdout.txt
new file mode 100644
index 0000000..44fa77c
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-stdout.txt
@@ -0,0 +1,3 @@
+-- FILE='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- FILE='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h'
+-- FILE='FILE-NOTFOUND'
diff --git a/Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt
new file mode 100644
index 0000000..b4125e6
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_file\):
+ find_file command specified for "VALIDATOR" is undefined: undefined.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake
new file mode 100644
index 0000000..c465887
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake
@@ -0,0 +1,2 @@
+
+find_file(result NAMES input.txt VALIDATOR undefined)
diff --git a/Tests/RunCMake/find_file/VALIDATOR.cmake b/Tests/RunCMake/find_file/VALIDATOR.cmake
new file mode 100644
index 0000000..72dd8f9
--- /dev/null
+++ b/Tests/RunCMake/find_file/VALIDATOR.cmake
@@ -0,0 +1,39 @@
+
+function(CHECK_DEFAULT result filename)
+ message("CHECK='${filename}'")
+endfunction()
+
+function(CHECK_OK result filename)
+ message("CHECK='${filename}'")
+ set(${result} TRUE PARENT_SCOPE)
+endfunction()
+
+function(CHECK_KO result filename)
+ message("CHECK='${filename}'")
+ set(${result} FALSE PARENT_SCOPE)
+endfunction()
+
+
+find_file(FILE
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_default
+ )
+message(STATUS "FILE='${FILE}'")
+unset(FILE CACHE)
+
+find_file(FILE
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_ok
+ )
+message(STATUS "FILE='${FILE}'")
+unset(FILE CACHE)
+
+find_file(FILE
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_ko
+ )
+message(STATUS "FILE='${FILE}'")
+unset(FILE CACHE)
diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake
index de0ee14..cc005d0 100644
--- a/Tests/RunCMake/find_library/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake
@@ -13,6 +13,10 @@ run_cmake(Required)
run_cmake(NO_CACHE)
run_cmake(REGISTRY_VIEW-no-view)
run_cmake(REGISTRY_VIEW-wrong-view)
+run_cmake(VALIDATOR-no-function)
+run_cmake(VALIDATOR-undefined-function)
+run_cmake(VALIDATOR-specify-macro)
+run_cmake(VALIDATOR)
run_cmake_script(FromScriptMode "-DTEMP_DIR=${RunCMake_BINARY_DIR}/FromScriptMode-temp")
diff --git a/Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt
new file mode 100644
index 0000000..6c04aa4
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_library\):
+ find_library missing required argument for "VALIDATOR"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_library/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_library/VALIDATOR-no-function.cmake
new file mode 100644
index 0000000..516e54e
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-no-function.cmake
@@ -0,0 +1,2 @@
+
+find_library(result NAMES input.txt VALIDATOR)
diff --git a/Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt
new file mode 100644
index 0000000..03e7df9
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_library\):
+ find_library command specified for "VALIDATOR" is not a function: check.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake
new file mode 100644
index 0000000..fa90d72
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake
@@ -0,0 +1,5 @@
+
+macro(CHECK result path)
+endmacro()
+
+find_library(result NAMES input.txt VALIDATOR check)
diff --git a/Tests/RunCMake/find_library/VALIDATOR-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-stderr.txt
new file mode 100644
index 0000000..7211450
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-stderr.txt
@@ -0,0 +1,3 @@
+CHECK='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+CHECK='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+CHECK='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
diff --git a/Tests/RunCMake/find_library/VALIDATOR-stdout.txt b/Tests/RunCMake/find_library/VALIDATOR-stdout.txt
new file mode 100644
index 0000000..bd2549b
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-stdout.txt
@@ -0,0 +1,3 @@
+-- LIB='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- LIB='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a'
+-- LIB='LIB-NOTFOUND'
diff --git a/Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt
new file mode 100644
index 0000000..dc7ad9e
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_library\):
+ find_library command specified for "VALIDATOR" is undefined: undefined.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake
new file mode 100644
index 0000000..9ac7ee0
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake
@@ -0,0 +1,2 @@
+
+find_library(result NAMES input.txt VALIDATOR undefined)
diff --git a/Tests/RunCMake/find_library/VALIDATOR.cmake b/Tests/RunCMake/find_library/VALIDATOR.cmake
new file mode 100644
index 0000000..7593941
--- /dev/null
+++ b/Tests/RunCMake/find_library/VALIDATOR.cmake
@@ -0,0 +1,41 @@
+list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib)
+list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a)
+
+function(CHECK_DEFAULT result filename)
+ message("CHECK='${filename}'")
+endfunction()
+
+function(CHECK_OK result filename)
+ message("CHECK='${filename}'")
+ set(${result} TRUE PARENT_SCOPE)
+endfunction()
+
+function(CHECK_KO result filename)
+ message("CHECK='${filename}'")
+ set(${result} FALSE PARENT_SCOPE)
+endfunction()
+
+
+find_library(LIB
+ NAMES PrefixInPATH
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ VALIDATOR check_default
+ )
+message(STATUS "LIB='${LIB}'")
+unset(LIB CACHE)
+
+find_library(LIB
+ NAMES PrefixInPATH
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ VALIDATOR check_ok
+ )
+message(STATUS "LIB='${LIB}'")
+unset(LIB CACHE)
+
+find_library(LIB
+ NAMES PrefixInPATH
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/lib
+ VALIDATOR check_ko
+ )
+message(STATUS "LIB='${LIB}'")
+unset(LIB CACHE)
diff --git a/Tests/RunCMake/find_path/RunCMakeTest.cmake b/Tests/RunCMake/find_path/RunCMakeTest.cmake
index 63cadc2..9c76f2e 100644
--- a/Tests/RunCMake/find_path/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_path/RunCMakeTest.cmake
@@ -7,6 +7,10 @@ run_cmake(Required)
run_cmake(NO_CACHE)
run_cmake(REGISTRY_VIEW-no-view)
run_cmake(REGISTRY_VIEW-wrong-view)
+run_cmake(VALIDATOR-no-function)
+run_cmake(VALIDATOR-undefined-function)
+run_cmake(VALIDATOR-specify-macro)
+run_cmake(VALIDATOR)
if(APPLE)
run_cmake(FrameworksWithSubdirs)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt
new file mode 100644
index 0000000..1dfd064
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_path\):
+ find_path missing required argument for "VALIDATOR"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_path/VALIDATOR-no-function.cmake
new file mode 100644
index 0000000..bac2752
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-no-function.cmake
@@ -0,0 +1,2 @@
+
+find_path(result NAMES input.txt VALIDATOR)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt
new file mode 100644
index 0000000..92ee17e
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_path\):
+ find_path command specified for "VALIDATOR" is not a function: check.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake
new file mode 100644
index 0000000..62b44ed
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake
@@ -0,0 +1,5 @@
+
+macro(CHECK result path)
+endmacro()
+
+find_path(result NAMES input.txt VALIDATOR check)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-stderr.txt
new file mode 100644
index 0000000..851353d
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-stderr.txt
@@ -0,0 +1,3 @@
+CHECK='[^']+/Tests/RunCMake/find_path/include/'
+CHECK='[^']+/Tests/RunCMake/find_path/include/'
+CHECK='[^']+/Tests/RunCMake/find_path/include/'
diff --git a/Tests/RunCMake/find_path/VALIDATOR-stdout.txt b/Tests/RunCMake/find_path/VALIDATOR-stdout.txt
new file mode 100644
index 0000000..3fce030
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-stdout.txt
@@ -0,0 +1,3 @@
+-- DIR='[^']+/Tests/RunCMake/find_path/include'
+-- DIR='[^']+/Tests/RunCMake/find_path/include'
+-- DIR='DIR-NOTFOUND'
diff --git a/Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt
new file mode 100644
index 0000000..d3e0517
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_path\):
+ find_path command specified for "VALIDATOR" is undefined: undefined.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake
new file mode 100644
index 0000000..3fb55c5
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake
@@ -0,0 +1,2 @@
+
+find_path(result NAMES input.txt VALIDATOR undefined)
diff --git a/Tests/RunCMake/find_path/VALIDATOR.cmake b/Tests/RunCMake/find_path/VALIDATOR.cmake
new file mode 100644
index 0000000..1e01250
--- /dev/null
+++ b/Tests/RunCMake/find_path/VALIDATOR.cmake
@@ -0,0 +1,39 @@
+
+function(CHECK_DEFAULT result filename)
+ message("CHECK='${filename}'")
+endfunction()
+
+function(CHECK_OK result filename)
+ message("CHECK='${filename}'")
+ set(${result} TRUE PARENT_SCOPE)
+endfunction()
+
+function(CHECK_KO result filename)
+ message("CHECK='${filename}'")
+ set(${result} FALSE PARENT_SCOPE)
+endfunction()
+
+
+find_path(DIR
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_default
+ )
+message(STATUS "DIR='${DIR}'")
+unset(DIR CACHE)
+
+find_path(DIR
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_ok
+ )
+message(STATUS "DIR='${DIR}'")
+unset(DIR CACHE)
+
+find_path(DIR
+ NAMES PrefixInPATH.h
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include
+ VALIDATOR check_ko
+ )
+message(STATUS "DIR='${DIR}'")
+unset(DIR CACHE)
diff --git a/Tests/RunCMake/find_program/RunCMakeTest.cmake b/Tests/RunCMake/find_program/RunCMakeTest.cmake
index d0ce8fc..f8ecb8f 100644
--- a/Tests/RunCMake/find_program/RunCMakeTest.cmake
+++ b/Tests/RunCMake/find_program/RunCMakeTest.cmake
@@ -9,6 +9,10 @@ run_cmake(NO_CACHE)
run_cmake(IgnorePrefixPath)
run_cmake(REGISTRY_VIEW-no-view)
run_cmake(REGISTRY_VIEW-wrong-view)
+run_cmake(VALIDATOR-no-function)
+run_cmake(VALIDATOR-undefined-function)
+run_cmake(VALIDATOR-specify-macro)
+run_cmake(VALIDATOR)
if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN|MSYS)$")
run_cmake(WindowsCom)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt
new file mode 100644
index 0000000..b8868af
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_program\):
+ find_program missing required argument for "VALIDATOR"
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_program/VALIDATOR-no-function.cmake
new file mode 100644
index 0000000..0d6a74f
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-no-function.cmake
@@ -0,0 +1,2 @@
+
+find_program(result NAMES input.txt VALIDATOR)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt
new file mode 100644
index 0000000..1ae5148
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_program\):
+ find_program command specified for "VALIDATOR" is not a function: check.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake
new file mode 100644
index 0000000..43bb9ec
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake
@@ -0,0 +1,5 @@
+
+macro(CHECK result path)
+endmacro()
+
+find_program(result NAMES input.txt VALIDATOR check)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-stderr.txt
new file mode 100644
index 0000000..6704ed1
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-stderr.txt
@@ -0,0 +1,3 @@
+CHECK='[^']+/Tests/RunCMake/find_program/A/testA'
+CHECK='[^']+/Tests/RunCMake/find_program/A/testA'
+CHECK='[^']+/Tests/RunCMake/find_program/A/testA'
diff --git a/Tests/RunCMake/find_program/VALIDATOR-stdout.txt b/Tests/RunCMake/find_program/VALIDATOR-stdout.txt
new file mode 100644
index 0000000..d434742
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-stdout.txt
@@ -0,0 +1,3 @@
+-- PROG='[^']+/Tests/RunCMake/find_program/A/testA'
+-- PROG='[^']+/Tests/RunCMake/find_program/A/testA'
+-- PROG='PROG-NOTFOUND'
diff --git a/Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt
new file mode 100644
index 0000000..a89ffa0
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_program\):
+ find_program command specified for "VALIDATOR" is undefined: undefined.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
diff --git a/Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake
new file mode 100644
index 0000000..96be5fd
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake
@@ -0,0 +1,2 @@
+
+find_program(result NAMES input.txt VALIDATOR undefined)
diff --git a/Tests/RunCMake/find_program/VALIDATOR.cmake b/Tests/RunCMake/find_program/VALIDATOR.cmake
new file mode 100644
index 0000000..8be2b39
--- /dev/null
+++ b/Tests/RunCMake/find_program/VALIDATOR.cmake
@@ -0,0 +1,39 @@
+
+function(CHECK_DEFAULT result filename)
+ message("CHECK='${filename}'")
+endfunction()
+
+function(CHECK_OK result filename)
+ message("CHECK='${filename}'")
+ set(${result} TRUE PARENT_SCOPE)
+endfunction()
+
+function(CHECK_KO result filename)
+ message("CHECK='${filename}'")
+ set(${result} FALSE PARENT_SCOPE)
+endfunction()
+
+
+find_program(PROG
+ NAMES testA
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ VALIDATOR check_default
+ )
+message(STATUS "PROG='${PROG}'")
+unset(PROG CACHE)
+
+find_program(PROG
+ NAMES testA
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ VALIDATOR check_ok
+ )
+message(STATUS "PROG='${PROG}'")
+unset(PROG CACHE)
+
+find_program(PROG
+ NAMES testA
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A
+ VALIDATOR check_ko
+ )
+message(STATUS "PROG='${PROG}'")
+unset(PROG CACHE)
diff --git a/Tests/RunCMake/project/LanguagesDuplicate-check.cmake b/Tests/RunCMake/project/LanguagesDuplicate-check.cmake
new file mode 100644
index 0000000..31c7da3
--- /dev/null
+++ b/Tests/RunCMake/project/LanguagesDuplicate-check.cmake
@@ -0,0 +1,10 @@
+if(NOT actual_stderr MATCHES "The following language has been specified multiple times: C\n")
+ set(RunCMake_TEST_FAILED "'LANGUAGES C C C' should report only 'C' and only once.")
+endif()
+
+if(NOT actual_stderr MATCHES "The following languages have been specified multiple times: C, CXX\n")
+ if(RunCMake_TEST_FAILED)
+ string(APPEND RunCMake_TEST_FAILED "\n")
+ endif()
+ string(APPEND RunCMake_TEST_FAILED "'LANGUAGES C C CXX CXX' should report 'C' and 'CXX'.")
+endif()
diff --git a/Tests/RunCMake/project/LanguagesDuplicate.cmake b/Tests/RunCMake/project/LanguagesDuplicate.cmake
new file mode 100644
index 0000000..97a79d0
--- /dev/null
+++ b/Tests/RunCMake/project/LanguagesDuplicate.cmake
@@ -0,0 +1,11 @@
+cmake_policy(SET CMP0057 NEW)
+
+project(ProjectA C C C)
+project(ProjectB C C CXX CXX)
+
+get_property(langs GLOBAL PROPERTY ENABLED_LANGUAGES)
+foreach(lang C CXX)
+ if(NOT lang IN_LIST langs)
+ message(FATAL_ERROR "Expected language '${lang}' to be enabled.")
+ endif()
+endforeach()
diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake
index 945d9ed..6d9f52f 100644
--- a/Tests/RunCMake/project/RunCMakeTest.cmake
+++ b/Tests/RunCMake/project/RunCMakeTest.cmake
@@ -12,6 +12,11 @@ run_cmake_with_options(CodeInjection
if(CMake_TEST_RESOURCES)
run_cmake(ExplicitRC)
endif()
+
+set(RunCMake_DEFAULT_stderr .)
+run_cmake(LanguagesDuplicate)
+unset(RunCMake_DEFAULT_stderr)
+
run_cmake(LanguagesImplicit)
run_cmake(LanguagesEmpty)
run_cmake(LanguagesNONE)
diff --git a/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt
new file mode 100644
index 0000000..f04e43f
--- /dev/null
+++ b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt
@@ -0,0 +1,10 @@
+^CMake Deprecation Warning at CMP0101-BEFORE_keyword.cmake:[0-9]+ \(cmake_policy\):
+ The OLD behavior for policy CMP0101 will be removed from a future version
+ of CMake.
+
+ The cmake-policies\(7\) manual explains that the OLD behaviors of all
+ policies are deprecated and that a policy should be set to OLD only under
+ specific short-term circumstances. Projects should be ported to the NEW
+ behavior and not rely on setting a policy to OLD.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt
new file mode 100644
index 0000000..042d67d
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt
@@ -0,0 +1,12 @@
+^CMake Warning \(dev\) at FileSetDefaultWrongTypeExperimental.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error at FileSetDefaultWrongTypeExperimental\.cmake:[0-9]+ \(target_sources\):
+ target_sources File set TYPE may only be "HEADERS", "CXX_MODULES", or
+ "CXX_MODULE_HEADER_UNITS"
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake
new file mode 100644
index 0000000..5ade637
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake
@@ -0,0 +1,6 @@
+enable_language(C)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+add_library(lib1 STATIC empty.c)
+target_sources(lib1 PRIVATE FILE_SET UNKNOWN)
diff --git a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt
new file mode 100644
index 0000000..a1b784f
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt
@@ -0,0 +1,12 @@
+^CMake Warning \(dev\) at FileSetWrongTypeExperimental.cmake:6 \(target_sources\):
+ CMake's C\+\+ module support is experimental. It is meant only for
+ experimentation and feedback to CMake developers.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.
+
+CMake Error at FileSetWrongTypeExperimental\.cmake:[0-9]+ \(target_sources\):
+ target_sources File set TYPE may only be "HEADERS", "CXX_MODULES", or
+ "CXX_MODULE_HEADER_UNITS"
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake
new file mode 100644
index 0000000..332441c
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake
@@ -0,0 +1,6 @@
+enable_language(C)
+
+set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
+
+add_library(lib1 STATIC empty.c)
+target_sources(lib1 PRIVATE FILE_SET a TYPE UNKNOWN)
diff --git a/Tests/RunCMake/target_sources/RunCMakeTest.cmake b/Tests/RunCMake/target_sources/RunCMakeTest.cmake
index 6a3c7b9..7c67c3f 100644
--- a/Tests/RunCMake/target_sources/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_sources/RunCMakeTest.cmake
@@ -26,6 +26,8 @@ run_cmake(FileSetProperties)
run_cmake(FileSetNoType)
run_cmake(FileSetWrongType)
run_cmake(FileSetDefaultWrongType)
+run_cmake(FileSetWrongTypeExperimental)
+run_cmake(FileSetDefaultWrongTypeExperimental)
run_cmake(FileSetChangeScope)
run_cmake(FileSetChangeType)
run_cmake(FileSetWrongBaseDirs)
diff --git a/Tests/RunCMake/try_compile/CxxStandard-stderr.txt b/Tests/RunCMake/try_compile/CxxStandard-stderr.txt
index ec7245f..cee1b44 100644
--- a/Tests/RunCMake/try_compile/CxxStandard-stderr.txt
+++ b/Tests/RunCMake/try_compile/CxxStandard-stderr.txt
@@ -1,6 +1,17 @@
-^CMake Error at .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\):
+^(CMake Error in .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:
+ The CXX_STANDARD property on target "cmTC_[0-9a-f]*" contained an invalid
+ value: "3".
+
+
+)?CMake Error at .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\):
CXX_STANDARD is set to invalid value '3'
-+
+
+(
+CMake Error in .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:
+ The CXX_STANDARD property on target "cmTC_[0-9a-f]*" contained an invalid
+ value: "3".
+
+)?
CMake Error at CxxStandard.cmake:[0-9]+ \(try_compile\):
Failed to generate test project build system.
Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/try_run/BadStdErrVariable-result.txt b/Tests/RunCMake/try_run/BadStdErrVariable-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/try_run/BadStdErrVariable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/BadStdErrVariable-stderr.txt b/Tests/RunCMake/try_run/BadStdErrVariable-stderr.txt
new file mode 100644
index 0000000..5d7e5e9
--- /dev/null
+++ b/Tests/RunCMake/try_run/BadStdErrVariable-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error: RUN_OUTPUT_STDERR_VARIABLE specified but there is no variable
+CMake Error at BadStdErrVariable.cmake:1 \(try_run\):
+ try_run unknown error.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_run/BadStdErrVariable.cmake b/Tests/RunCMake/try_run/BadStdErrVariable.cmake
new file mode 100644
index 0000000..88c2a72
--- /dev/null
+++ b/Tests/RunCMake/try_run/BadStdErrVariable.cmake
@@ -0,0 +1,5 @@
+try_run(RUN_RESULT COMPILE_RESULT
+ ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp/workdir
+ RUN_OUTPUT_STDERR_VARIABLE
+ )
diff --git a/Tests/RunCMake/try_run/BadStdOutVariable-result.txt b/Tests/RunCMake/try_run/BadStdOutVariable-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/try_run/BadStdOutVariable-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/try_run/BadStdOutVariable-stderr.txt b/Tests/RunCMake/try_run/BadStdOutVariable-stderr.txt
new file mode 100644
index 0000000..df60658
--- /dev/null
+++ b/Tests/RunCMake/try_run/BadStdOutVariable-stderr.txt
@@ -0,0 +1,5 @@
+CMake Error: RUN_OUTPUT_STDOUT_VARIABLE specified but there is no variable
+CMake Error at BadStdOutVariable.cmake:1 \(try_run\):
+ try_run unknown error.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/try_run/BadStdOutVariable.cmake b/Tests/RunCMake/try_run/BadStdOutVariable.cmake
new file mode 100644
index 0000000..691e881
--- /dev/null
+++ b/Tests/RunCMake/try_run/BadStdOutVariable.cmake
@@ -0,0 +1,5 @@
+try_run(RUN_RESULT COMPILE_RESULT
+ ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp ${CMAKE_CURRENT_SOURCE_DIR}/src.c
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp/workdir
+ RUN_OUTPUT_STDOUT_VARIABLE
+ )
diff --git a/Tests/RunCMake/try_run/RunCMakeTest.cmake b/Tests/RunCMake/try_run/RunCMakeTest.cmake
index d74add0..5fa5b2f 100644
--- a/Tests/RunCMake/try_run/RunCMakeTest.cmake
+++ b/Tests/RunCMake/try_run/RunCMakeTest.cmake
@@ -10,3 +10,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND
endif()
run_cmake(WorkingDirArg)
+
+run_cmake(BadStdOutVariable)
+run_cmake(BadStdErrVariable)
diff --git a/Tests/SwiftOnly/CMakeLists.txt b/Tests/SwiftOnly/CMakeLists.txt
index 01c2222..e92e544 100644
--- a/Tests/SwiftOnly/CMakeLists.txt
+++ b/Tests/SwiftOnly/CMakeLists.txt
@@ -25,6 +25,7 @@ endif()
set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift)
add_executable(SwiftOnly main.swift)
+target_compile_definitions(SwiftOnly PRIVATE SWIFTONLY)
add_library(L L.swift)
diff --git a/Tests/SwiftOnly/main.swift b/Tests/SwiftOnly/main.swift
index 28560d0..a3f1a2c 100644
--- a/Tests/SwiftOnly/main.swift
+++ b/Tests/SwiftOnly/main.swift
@@ -1 +1,7 @@
dump("SwiftOnly")
+
+#if SWIFTONLY
+dump("SWIFTONLY defined")
+#else
+fatalError("SWIFTONLY NOT defined")
+#endif
diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt
index 000fd2c..7c6f970 100644
--- a/Tests/TryCompile/CMakeLists.txt
+++ b/Tests/TryCompile/CMakeLists.txt
@@ -259,11 +259,32 @@ endif()
if("${COMPILE_OUTPUT}" MATCHES "hello world")
message(SEND_ERROR " COMPILE_OUT contains the run output: \"${COMPILE_OUTPUT}\"")
endif()
-# check the run output, it should stdout
+# check the run output, it should contain stdout
if(NOT "${RUN_OUTPUT}" MATCHES "hello world")
message(SEND_ERROR " RUN_OUTPUT didn't contain \"hello world\": \"${RUN_OUTPUT}\"")
endif()
+# try to run a file and parse stdout and stderr separately
+try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE
+ ${TryCompile_BINARY_DIR}
+ ${TryCompile_SOURCE_DIR}/stdout_and_stderr.c
+ COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT
+ RUN_OUTPUT_STDOUT_VARIABLE RUN_OUTPUT_STDOUT
+ RUN_OUTPUT_STDERR_VARIABLE RUN_OUTPUT_STDERR)
+
+if(NOT SHOULD_COMPILE)
+ message(STATUS " exit_with_error failed compiling: ${COMPILE_OUTPUT}")
+endif()
+
+# check the run stdout output
+if(NOT "${RUN_OUTPUT_STDOUT}" MATCHES "hello world")
+ message(SEND_ERROR " RUN_OUTPUT_STDOUT didn't contain \"hello world\": \"${RUN_OUTPUT_STDOUT}\"")
+endif()
+# check the run stderr output
+if(NOT "${RUN_OUTPUT_STDERR}" MATCHES "error")
+ message(SEND_ERROR " RUN_OUTPUT_STDERR didn't contain \"error\": \"${RUN_OUTPUT_STDERR}\"")
+endif()
+
#######################################################################
#
# also test that the CHECK_C_SOURCE_COMPILES, CHECK_CXX_SOURCE_COMPILES
diff --git a/Tests/TryCompile/stdout_and_stderr.c b/Tests/TryCompile/stdout_and_stderr.c
new file mode 100644
index 0000000..84ded1f
--- /dev/null
+++ b/Tests/TryCompile/stdout_and_stderr.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int main()
+{
+ fputs("error\n", stderr);
+ puts("hello world\n");
+ return 0;
+}
diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt
index b712c27..bc16350 100644
--- a/Utilities/Doxygen/CMakeLists.txt
+++ b/Utilities/Doxygen/CMakeLists.txt
@@ -3,7 +3,7 @@
if(NOT CMake_SOURCE_DIR)
set(CMakeDeveloperReference_STANDALONE 1)
- cmake_minimum_required(VERSION 3.13...3.22 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.13...3.23 FATAL_ERROR)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt
index fbce1c8..58c0573 100644
--- a/Utilities/Sphinx/CMakeLists.txt
+++ b/Utilities/Sphinx/CMakeLists.txt
@@ -3,7 +3,7 @@
if(NOT CMake_SOURCE_DIR)
set(CMakeHelp_STANDALONE 1)
- cmake_minimum_required(VERSION 3.13...3.22 FATAL_ERROR)
+ cmake_minimum_required(VERSION 3.13...3.23 FATAL_ERROR)
get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH)
get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH)
include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake)
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 635e9c1..5d1203b 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -217,8 +217,10 @@
* BoringSSL: supported since 5fd1807d95f7 (committed 2016-09-30)
* LibreSSL: since 2.5.3 (April 12, 2017)
*/
-#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) || \
- defined(OPENSSL_IS_BORINGSSL)
+#if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) && \
+ !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20503000L)) || \
+ defined(OPENSSL_IS_BORINGSSL)
#define HAVE_SSL_CTX_SET_EC_CURVES
#endif
@@ -2282,6 +2284,14 @@ static void ossl_trace(int direction, int ssl_ver, int content_type,
# define HAS_NPN 1
#endif
+/* Check for OpenSSL 1.1.0 which has set_{min,max}_proto_version(). */
+#undef HAS_MODERN_SET_PROTO_VER
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L \
+ && !(defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER < 0x20600000L)
+# define HAS_MODERN_SET_PROTO_VER 1
+#endif
+
#ifdef HAS_NPN
/*
@@ -2340,7 +2350,7 @@ select_next_proto_cb(SSL *ssl,
}
#endif /* HAS_NPN */
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
+#ifdef HAS_MODERN_SET_PROTO_VER
static CURLcode
set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
{
@@ -2424,7 +2434,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn)
return CURLE_OK;
}
-#endif
+#endif /* HAS_MODERN_SET_PROTO_VER */
#ifdef OPENSSL_IS_BORINGSSL
typedef uint32_t ctx_option_t;
@@ -2434,7 +2444,7 @@ typedef uint64_t ctx_option_t;
typedef long ctx_option_t;
#endif
-#if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */
+#if !defined(HAS_MODERN_SET_PROTO_VER)
static CURLcode
set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
struct Curl_easy *data,
@@ -2509,7 +2519,7 @@ set_ssl_version_min_max_legacy(ctx_option_t *ctx_options,
}
return CURLE_OK;
}
-#endif
+#endif /* ! HAS_MODERN_SET_PROTO_VER */
/* The "new session" callback must return zero if the session can be removed
* or non-zero if the session has been put into the session cache.
@@ -2813,7 +2823,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data,
ctx_options |= SSL_OP_NO_SSLv2;
ctx_options |= SSL_OP_NO_SSLv3;
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */
+#if HAS_MODERN_SET_PROTO_VER /* 1.1.0 */
result = set_ssl_version_min_max(backend->ctx, conn);
#else
result = set_ssl_version_min_max_legacy(&ctx_options, data, conn,
diff --git a/bootstrap b/bootstrap
index 9a87413..01ff84f 100755
--- a/bootstrap
+++ b/bootstrap
@@ -328,6 +328,7 @@ CMAKE_CXX_SOURCES="\
cmCustomCommand \
cmCustomCommandGenerator \
cmCustomCommandLines \
+ cmCxxModuleMapper \
cmDefinePropertyCommand \
cmDefinitions \
cmDocumentationFormatter \
@@ -337,6 +338,7 @@ CMAKE_CXX_SOURCES="\
cmExecProgramCommand \
cmExecuteProcessCommand \
cmExpandedCommandArgument \
+ cmExperimental \
cmExportBuildFileGenerator \
cmExportFileGenerator \
cmExportInstallFileGenerator \
@@ -391,6 +393,7 @@ CMAKE_CXX_SOURCES="\
cmIncludeRegularExpressionCommand \
cmInstallCommand \
cmInstallCommandArguments \
+ cmInstallCxxModuleBmiGenerator \
cmInstallDirectoryGenerator \
cmInstallExportGenerator \
cmInstallFileSetGenerator \