From 5bbd2c12dbef5aec8988b40d807037ae59fdb794 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 26 Mar 2024 13:44:15 -0400 Subject: Help/cmake-cxxmodules: describe the compilation strategy --- Help/manual/cmake-cxxmodules.7.rst | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Help/manual/cmake-cxxmodules.7.rst b/Help/manual/cmake-cxxmodules.7.rst index 3ee6645..8f62b5a 100644 --- a/Help/manual/cmake-cxxmodules.7.rst +++ b/Help/manual/cmake-cxxmodules.7.rst @@ -12,6 +12,49 @@ to scan source files for module dependencies during the build, collates scanning results to infer ordering constraints, and tells the build tool how to dynamically update the build graph. +Compilation Strategy +==================== + +With C++ modules, compiling a set of C++ sources is no longer embarrassingly +parallel. That is, any given source may first require the compilation of +another source file first in order to provide a "CMI" (compiled module +interface) or "BMI" (binary module interface) that C++ compilers use to +satisfy ``import`` statements in other sources. With headers, sources could +share their declarations so that any consumers could compile independently. +With modules, declarations are now generated into these BMI files by the +compiler during compilation based on the contents of the source file and its +``export`` statements. + +The order necessary for compilation requires build-time resolution of the +ordering because the order is controlled by the contents of the sources. This +means that the ordering needs extracted from the source during the build to +avoid regenerating the build graph via a configure and generate phase for +every source change to get a correct build. + +The general strategy is to use a "scanner" to extract the ordering dependency +information and update the build graph with new edges between existing edges +by taking the per-source scan results (represented by `P1689R5`_ files) and +"collating" the dependencies within a target and to modules produced by +targets visible to the target. The primary task is to generate "module map" +files to pass to each compile rule with the paths to the BMIs needed to +satisfy ``import`` statements. The collator also has tasks to use the +build-time information to fill out information including ``install`` rules for +the module interface units, their BMIs, and properties for any exported +targets with C++ modules. + +.. _`P1689R5`: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html + +.. note: + + CMake is focusing on correct builds before looking at performance + improvements. There are known tactics within the chosen strategy which may + offer build performance improvements. However, they are being deferred + until we have a working model against which to compare them. It is also + important to note that a tactic useful in one situation (e.g., clean + builds) may not be performant in a different situation (e.g., incremental + builds). Finding a balance and offering controls to select the tactics is + future work. + Scanning Control ================ -- cgit v0.12 From 3273b1897290731acbc3cdf9d5bc73f34a170772 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 2 Mar 2024 00:09:26 -0500 Subject: cmExportFileGenerator: support always exporting properties --- Source/cmExportFileGenerator.cxx | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 7867a8e..2d48f34 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -1388,6 +1388,12 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode( os << ")\n\n"; } +enum class ExportWhen +{ + Defined, + Always, +}; + enum class PropertyType { Strings, @@ -1409,6 +1415,12 @@ bool PropertyTypeIsForPaths(PropertyType pt) } } +struct ModuleTargetPropertyTable +{ + cm::static_string_view Name; + ExportWhen Cond; +}; + struct ModulePropertyTable { cm::static_string_view Name; @@ -1424,18 +1436,21 @@ bool cmExportFileGenerator::PopulateCxxModuleExportProperties( return true; } - const cm::static_string_view exportedDirectModuleProperties[] = { - "CXX_EXTENSIONS"_s, + const ModuleTargetPropertyTable exportedDirectModuleProperties[] = { + { "CXX_EXTENSIONS"_s, ExportWhen::Defined }, }; - for (auto const& propName : exportedDirectModuleProperties) { - auto const propNameStr = std::string(propName); - cmValue prop = gte->Target->GetComputedProperty( + for (auto const& prop : exportedDirectModuleProperties) { + auto const propNameStr = std::string(prop.Name); + cmValue propValue = gte->Target->GetComputedProperty( propNameStr, *gte->Target->GetMakefile()); - if (!prop) { - prop = gte->Target->GetProperty(propNameStr); + if (!propValue) { + propValue = gte->Target->GetProperty(propNameStr); } - if (prop) { - properties[propNameStr] = cmGeneratorExpression::Preprocess(*prop, ctx); + if (propValue) { + properties[propNameStr] = + cmGeneratorExpression::Preprocess(*propValue, ctx); + } else if (prop.Cond == ExportWhen::Always) { + properties[propNameStr] = ""; } } -- cgit v0.12 From bf0b457461f2892b480eb7b1790e75ff76fe2fc9 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 24 Feb 2024 17:30:41 -0500 Subject: Tests/CXXModules: add test case for `import std` support --- Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 6 ++++++ Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt | 12 ++++++++++++ Tests/RunCMake/CXXModules/examples/import-std/main.cxx | 10 ++++++++++ 3 files changed, 28 insertions(+) create mode 100644 Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std/main.cxx diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 14829a1..75e062e 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -175,6 +175,7 @@ endfunction () # - `partitions`: module partitions are supported # - `internal_partitions`: internal module partitions are supported # - `bmionly`: the compiler supports BMI-only builds +# - `import_std23`: the compiler supports `import std` for C++23 # # Generator-based: # - `compile_commands`: the generator supports `compile_commands.json` @@ -221,6 +222,11 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) run_cxx_module_test(same-src-name) run_cxx_module_test(scan_properties) run_cxx_module_test(target-objects) + + if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND + "import_std23" IN_LIST CMake_TEST_MODULE_COMPILATION) + run_cxx_module_test(import-std) + endif () endif () # Tests which require compile commands support. diff --git a/Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt new file mode 100644 index 0000000..4e894c7 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.29) +project(cxx_modules_import_std CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +set(CMAKE_CXX_MODULE_STD 1) + +add_executable(main + main.cxx) +target_compile_features(main PRIVATE cxx_std_23) + +add_test(NAME main COMMAND main) diff --git a/Tests/RunCMake/CXXModules/examples/import-std/main.cxx b/Tests/RunCMake/CXXModules/examples/import-std/main.cxx new file mode 100644 index 0000000..6dafd01 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std/main.cxx @@ -0,0 +1,10 @@ +import std; + +int main(int argc, char* argv[]) +{ + if (argc > 0 && argv[0]) { + std::string argv0 = argv[0]; + std::cout << "program: " << argv0 << std::endl; + } + return 0; +} -- cgit v0.12 From b8af090c78d706a11640bc4703eba6f7f56425be Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 26 Feb 2024 17:36:46 -0500 Subject: Tests/CXXModules: add a test for the `CXX_MODULE_STD` property --- Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 3 +++ .../examples/import-std-no-std-property-build-result.txt | 1 + .../examples/import-std-no-std-property-build-stdout.txt | 1 + .../examples/import-std-no-std-property/CMakeLists.txt | 10 ++++++++++ .../CXXModules/examples/import-std-no-std-property/main.cxx | 6 ++++++ 5 files changed, 21 insertions(+) create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-no-std-property-build-result.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-no-std-property-build-stdout.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-no-std-property/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-no-std-property/main.cxx diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 75e062e..f34d935 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -226,6 +226,9 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND "import_std23" IN_LIST CMake_TEST_MODULE_COMPILATION) run_cxx_module_test(import-std) + set(RunCMake_CXXModules_NO_TEST 1) + run_cxx_module_test(import-std-no-std-property) + unset(RunCMake_CXXModules_NO_TEST) endif () endif () diff --git a/Tests/RunCMake/CXXModules/examples/import-std-no-std-property-build-result.txt b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property-build-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property-build-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/examples/import-std-no-std-property-build-stdout.txt b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property-build-stdout.txt new file mode 100644 index 0000000..d473333 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property-build-stdout.txt @@ -0,0 +1 @@ +((Clang)?module 'std' not found|(MSVC)?could not find module 'std') diff --git a/Tests/RunCMake/CXXModules/examples/import-std-no-std-property/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property/CMakeLists.txt new file mode 100644 index 0000000..4ec4e36 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.29) +project(cxx_modules_import_std_no_std_property CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +set(CMAKE_CXX_MODULE_STD 0) + +add_executable(main + main.cxx) +target_compile_features(main PRIVATE cxx_std_23) diff --git a/Tests/RunCMake/CXXModules/examples/import-std-no-std-property/main.cxx b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property/main.cxx new file mode 100644 index 0000000..fee84f1 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property/main.cxx @@ -0,0 +1,6 @@ +import std; + +int main(int argc, char* argv[]) +{ + return 0; +} -- cgit v0.12 From a9ad29403ea9bcbf526146c0a9dea05e9af7c9d0 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 5 Mar 2024 13:44:24 -0500 Subject: Tests/CXXModules/vs-without-flags: use C++20 C++23 has complications with `import std` expectations. --- Tests/RunCMake/CXXModules/examples/vs-without-flags/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/RunCMake/CXXModules/examples/vs-without-flags/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/vs-without-flags/CMakeLists.txt index 0d18a66..c5958df 100644 --- a/Tests/RunCMake/CXXModules/examples/vs-without-flags/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/vs-without-flags/CMakeLists.txt @@ -3,7 +3,7 @@ project(cxx_modules_vs_without_flags CXX) include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") -set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_SCAN_FOR_MODULES ON) -- cgit v0.12 From b17e6a52f9ebfe518553b03249ac188152dac49d Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 5 Mar 2024 13:39:59 -0500 Subject: Tests/CXXModules: add tests for genex usage in `CXX_MODULE_STD` --- Tests/RunCMake/CXXModules/CXXImportStdConfig-result.txt | 1 + Tests/RunCMake/CXXModules/CXXImportStdConfig-stderr.txt | 3 +++ Tests/RunCMake/CXXModules/CXXImportStdConfig.cmake | 10 ++++++++++ Tests/RunCMake/CXXModules/CXXImportStdHeadTarget-result.txt | 1 + Tests/RunCMake/CXXModules/CXXImportStdHeadTarget-stderr.txt | 9 +++++++++ Tests/RunCMake/CXXModules/CXXImportStdHeadTarget.cmake | 10 ++++++++++ Tests/RunCMake/CXXModules/CXXImportStdInvalidGenex.cmake | 11 +++++++++++ Tests/RunCMake/CXXModules/CXXImportStdLinkLanguage-result.txt | 1 + Tests/RunCMake/CXXModules/CXXImportStdLinkLanguage-stderr.txt | 7 +++++++ Tests/RunCMake/CXXModules/CXXImportStdLinkLanguage.cmake | 10 ++++++++++ Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 7 +++++++ 11 files changed, 70 insertions(+) create mode 100644 Tests/RunCMake/CXXModules/CXXImportStdConfig-result.txt create mode 100644 Tests/RunCMake/CXXModules/CXXImportStdConfig-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/CXXImportStdConfig.cmake create mode 100644 Tests/RunCMake/CXXModules/CXXImportStdHeadTarget-result.txt create mode 100644 Tests/RunCMake/CXXModules/CXXImportStdHeadTarget-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/CXXImportStdHeadTarget.cmake create mode 100644 Tests/RunCMake/CXXModules/CXXImportStdInvalidGenex.cmake create mode 100644 Tests/RunCMake/CXXModules/CXXImportStdLinkLanguage-result.txt create mode 100644 Tests/RunCMake/CXXModules/CXXImportStdLinkLanguage-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/CXXImportStdLinkLanguage.cmake diff --git a/Tests/RunCMake/CXXModules/CXXImportStdConfig-result.txt b/Tests/RunCMake/CXXModules/CXXImportStdConfig-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/CXXImportStdConfig-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/CXXImportStdConfig-stderr.txt b/Tests/RunCMake/CXXModules/CXXImportStdConfig-stderr.txt new file mode 100644 index 0000000..268099f --- /dev/null +++ b/Tests/RunCMake/CXXModules/CXXImportStdConfig-stderr.txt @@ -0,0 +1,3 @@ +CMake Error in CMakeLists.txt: + The "CXX_MODULE_STD" property on the target "nocxx23target" contains a + context-sensitive condition that is not supported. diff --git a/Tests/RunCMake/CXXModules/CXXImportStdConfig.cmake b/Tests/RunCMake/CXXModules/CXXImportStdConfig.cmake new file mode 100644 index 0000000..0867082 --- /dev/null +++ b/Tests/RunCMake/CXXModules/CXXImportStdConfig.cmake @@ -0,0 +1,10 @@ +enable_language(CXX) + +set(CMAKE_CXX_MODULE_STD "$") + +add_library(nocxx23target) +target_sources(nocxx23target + PRIVATE + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(nocxx23target PRIVATE cxx_std_23) diff --git a/Tests/RunCMake/CXXModules/CXXImportStdHeadTarget-result.txt b/Tests/RunCMake/CXXModules/CXXImportStdHeadTarget-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/CXXImportStdHeadTarget-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/CXXImportStdHeadTarget-stderr.txt b/Tests/RunCMake/CXXModules/CXXImportStdHeadTarget-stderr.txt new file mode 100644 index 0000000..a2cdb63 --- /dev/null +++ b/Tests/RunCMake/CXXModules/CXXImportStdHeadTarget-stderr.txt @@ -0,0 +1,9 @@ +CMake Error: + Error evaluating generator expression: + + \$ + + \$ may only be used with binary targets. It may not + be used with add_custom_command or add_custom_target. Specify the target + to read a property from using the \$ signature + instead. diff --git a/Tests/RunCMake/CXXModules/CXXImportStdHeadTarget.cmake b/Tests/RunCMake/CXXModules/CXXImportStdHeadTarget.cmake new file mode 100644 index 0000000..3eb2c68 --- /dev/null +++ b/Tests/RunCMake/CXXModules/CXXImportStdHeadTarget.cmake @@ -0,0 +1,10 @@ +enable_language(CXX) + +set(CMAKE_CXX_MODULE_STD "$") + +add_library(nocxx23target) +target_sources(nocxx23target + PRIVATE + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(nocxx23target PRIVATE cxx_std_23) diff --git a/Tests/RunCMake/CXXModules/CXXImportStdInvalidGenex.cmake b/Tests/RunCMake/CXXModules/CXXImportStdInvalidGenex.cmake new file mode 100644 index 0000000..86230a4 --- /dev/null +++ b/Tests/RunCMake/CXXModules/CXXImportStdInvalidGenex.cmake @@ -0,0 +1,11 @@ +enable_language(CXX) +set(CMAKE_CXX_SCANDEP_SOURCE "echo") + +set(CMAKE_CXX_MODULE_STD "$ + + \$ may only be used with binary targets to specify link + libraries, link directories, link options and link depends. diff --git a/Tests/RunCMake/CXXModules/CXXImportStdLinkLanguage.cmake b/Tests/RunCMake/CXXModules/CXXImportStdLinkLanguage.cmake new file mode 100644 index 0000000..e9b20c7 --- /dev/null +++ b/Tests/RunCMake/CXXModules/CXXImportStdLinkLanguage.cmake @@ -0,0 +1,10 @@ +enable_language(CXX) + +set(CMAKE_CXX_MODULE_STD "$") + +add_library(nocxx23target) +target_sources(nocxx23target + PRIVATE + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(nocxx23target PRIVATE cxx_std_23) diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index f34d935..297860b 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -83,6 +83,13 @@ foreach (fileset_type IN LISTS fileset_types) run_cmake("NotCXXSource${fileset_type}") endforeach () +if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES) + run_cmake(CXXImportStdConfig) + run_cmake(CXXImportStdHeadTarget) + run_cmake(CXXImportStdLinkLanguage) + run_cmake(CXXImportStdInvalidGenex) +endif () + run_cmake(InstallBMI) run_cmake(InstallBMIGenericArgs) run_cmake(InstallBMIIgnore) -- cgit v0.12 From 16bf12d1e838263d753f082caeb7dc4222997ce2 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 5 Mar 2024 13:43:29 -0500 Subject: Tests/CXXModules; add tests for `CXX_MODULE_STD` behavior --- Tests/RunCMake/CXXModules/Inspect.cmake | 6 ++++++ Tests/RunCMake/CXXModules/NoCXX23TargetNotRequired.cmake | 11 +++++++++++ Tests/RunCMake/CXXModules/NoCXX23TargetRequired-result.txt | 1 + Tests/RunCMake/CXXModules/NoCXX23TargetRequired-stderr.txt | 4 ++++ Tests/RunCMake/CXXModules/NoCXX23TargetRequired.cmake | 11 +++++++++++ Tests/RunCMake/CXXModules/NoCXX23TargetUnset.cmake | 13 +++++++++++++ Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 7 +++++++ 7 files changed, 53 insertions(+) create mode 100644 Tests/RunCMake/CXXModules/NoCXX23TargetNotRequired.cmake create mode 100644 Tests/RunCMake/CXXModules/NoCXX23TargetRequired-result.txt create mode 100644 Tests/RunCMake/CXXModules/NoCXX23TargetRequired-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/NoCXX23TargetRequired.cmake create mode 100644 Tests/RunCMake/CXXModules/NoCXX23TargetUnset.cmake diff --git a/Tests/RunCMake/CXXModules/Inspect.cmake b/Tests/RunCMake/CXXModules/Inspect.cmake index 612b01b..1597bd8 100644 --- a/Tests/RunCMake/CXXModules/Inspect.cmake +++ b/Tests/RunCMake/CXXModules/Inspect.cmake @@ -15,11 +15,17 @@ if (CMAKE_CXX_FLAGS MATCHES "-std=") set(forced_cxx_standard 1) endif () +set(have_cxx23_import_std 0) +if (TARGET "__CMAKE::CXX23") + set(have_cxx23_import_std 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}\") +set(have_cxx23_import_std \"${have_cxx23_import_std}\") set(CMAKE_CXX_COMPILER_VERSION \"${CMAKE_CXX_COMPILER_VERSION}\") set(CMAKE_CXX_OUTPUT_EXTENSION \"${CMAKE_CXX_OUTPUT_EXTENSION}\") set(CXXModules_default_build_type \"${CMAKE_BUILD_TYPE}\") diff --git a/Tests/RunCMake/CXXModules/NoCXX23TargetNotRequired.cmake b/Tests/RunCMake/CXXModules/NoCXX23TargetNotRequired.cmake new file mode 100644 index 0000000..2d9bffa --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX23TargetNotRequired.cmake @@ -0,0 +1,11 @@ +enable_language(CXX) +set(CMAKE_CXX_SCANDEP_SOURCE "echo") + +set(CMAKE_CXX_MODULE_STD 0) + +add_library(nocxx23target) +target_sources(nocxx23target + PRIVATE + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(nocxx23target PRIVATE cxx_std_23) diff --git a/Tests/RunCMake/CXXModules/NoCXX23TargetRequired-result.txt b/Tests/RunCMake/CXXModules/NoCXX23TargetRequired-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX23TargetRequired-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/NoCXX23TargetRequired-stderr.txt b/Tests/RunCMake/CXXModules/NoCXX23TargetRequired-stderr.txt new file mode 100644 index 0000000..56468d0 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX23TargetRequired-stderr.txt @@ -0,0 +1,4 @@ +CMake Error in CMakeLists.txt: + The "CXX_MODULE_STD" property on the target "nocxx23target" requires that + the "__CMAKE::CXX23" target exist, but it was not provided by the + toolchain. diff --git a/Tests/RunCMake/CXXModules/NoCXX23TargetRequired.cmake b/Tests/RunCMake/CXXModules/NoCXX23TargetRequired.cmake new file mode 100644 index 0000000..fac05e2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX23TargetRequired.cmake @@ -0,0 +1,11 @@ +enable_language(CXX) +set(CMAKE_CXX_SCANDEP_SOURCE "echo") + +set(CMAKE_CXX_MODULE_STD 1) + +add_library(nocxx23target) +target_sources(nocxx23target + PRIVATE + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(nocxx23target PRIVATE cxx_std_23) diff --git a/Tests/RunCMake/CXXModules/NoCXX23TargetUnset.cmake b/Tests/RunCMake/CXXModules/NoCXX23TargetUnset.cmake new file mode 100644 index 0000000..8f6a656 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX23TargetUnset.cmake @@ -0,0 +1,13 @@ +enable_language(CXX) +set(CMAKE_CXX_SCANDEP_SOURCE "echo") + +# TODO(cxxmodules): Add instances of this test which test the policy +# of the property's unset behavior. +# set(CMAKE_CXX_MODULE_STD …) + +add_library(nocxx23target) +target_sources(nocxx23target + PRIVATE + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(nocxx23target PRIVATE cxx_std_23) diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 297860b..2fd4c46 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -90,6 +90,13 @@ if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES) run_cmake(CXXImportStdInvalidGenex) endif () +if ("cxx_std_23" IN_LIST CMAKE_CXX_COMPILE_FEATURES AND + NOT have_cxx23_import_std) + run_cmake(NoCXX23TargetUnset) + run_cmake(NoCXX23TargetNotRequired) + run_cmake(NoCXX23TargetRequired) +endif () + run_cmake(InstallBMI) run_cmake(InstallBMIGenericArgs) run_cmake(InstallBMIIgnore) -- cgit v0.12 From b8cc38f3a28190d39ef56f936f5d909688a8374e Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 26 Feb 2024 17:37:10 -0500 Subject: Tests/CXXModules: add tests that the C++ std targets don't get exported These targets are purely internal and should never be exported. --- Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 7 +++ .../import-std-not-in-export-build/CMakeLists.txt | 51 ++++++++++++++++++++ .../import-std-not-in-export-build/main.cxx | 6 +++ .../test/CMakeLists.txt | 45 ++++++++++++++++++ .../import-std-not-in-export-build/uses-std.cxx | 7 +++ .../CMakeLists.txt | 55 ++++++++++++++++++++++ .../import-std-not-in-export-install/main.cxx | 6 +++ .../test/CMakeLists.txt | 45 ++++++++++++++++++ .../import-std-not-in-export-install/uses-std.cxx | 7 +++ 9 files changed, 229 insertions(+) create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/main.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/test/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/uses-std.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/main.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/test/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/uses-std.cxx diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 2fd4c46..84e2085 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -243,6 +243,13 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) set(RunCMake_CXXModules_NO_TEST 1) run_cxx_module_test(import-std-no-std-property) unset(RunCMake_CXXModules_NO_TEST) + + if ("collation" IN_LIST CMake_TEST_MODULE_COMPILATION) + run_cxx_module_test(import-std-not-in-export-build) + + set(RunCMake_CXXModules_INSTALL 1) + run_cxx_module_test(import-std-not-in-export-install) + unset(RunCMake_CXXModules_INSTALL) endif () endif () diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/CMakeLists.txt new file mode 100644 index 0000000..b7ab279 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/CMakeLists.txt @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 3.29) +project(cxx_modules_import_std_not_in_export CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +set(CMAKE_CXX_MODULE_STD 1) + +add_library(import_std_not_in_export) +target_sources(import_std_not_in_export + PUBLIC + FILE_SET use_std TYPE CXX_MODULES FILES + uses-std.cxx) +target_compile_features(import_std_not_in_export PUBLIC cxx_std_23) + +add_executable(main + main.cxx) +target_link_libraries(main PRIVATE import_std_not_in_export) + +install(TARGETS import_std_not_in_export + EXPORT export + ARCHIVE DESTINATION "lib" + FILE_SET use_std DESTINATION "lib/cxx/miu") +export(EXPORT export + NAMESPACE CXXModules:: + FILE "${CMAKE_CURRENT_BINARY_DIR}/import_std_not_in_export-targets.cmake") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/import_std_not_in_export-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/import_std_not_in_export-targets.cmake\") +set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1) +") + +add_test(NAME main COMMAND main) + +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 import_std_not_in_export_build + COMMAND + "${CMAKE_COMMAND}" + "-Dexpected_dir=${CMAKE_CURRENT_SOURCE_DIR}" + "-Dimport_std_not_in_export_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/import-std-not-in-export-build/main.cxx b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/main.cxx new file mode 100644 index 0000000..a6dd8d8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/main.cxx @@ -0,0 +1,6 @@ +import uses_std; + +int main(int argc, char* argv[]) +{ + return f(); +} diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/test/CMakeLists.txt new file mode 100644 index 0000000..4e994d2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/test/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.29) +project(cxx_modules_library NONE) + +find_package(import_std_not_in_export REQUIRED) + +if (NOT TARGET CXXModules::import_std_not_in_export) + message(FATAL_ERROR + "Missing imported target") +endif () + +function (check_property expected property) + get_property(actual TARGET CXXModules::import_std_not_in_export + PROPERTY "${property}") + if (NOT DEFINED actual) + if (NOT expected STREQUAL "") + message(SEND_ERROR + "Mismatch for ${property}:\n expected: ${expected}\n actual: NOT-DEFINED") + endif () + elseif (NOT actual STREQUAL expected) + message(SEND_ERROR + "Mismatch for ${property}:\n expected: ${expected}\n actual: ${actual}") + endif () +endfunction () + +check_property("" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES") +check_property("" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS") +check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES") +check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES") +check_property("" "INTERFACE_LINK_LIBRARIES") +check_property("1" "CXX_MODULE_STD") + +# Extract the export-dependent targets from the export file. +file(STRINGS "${import_std_not_in_export_DIR}/import_std_not_in_export-targets.cmake" usage_dependent_targets + REGEX "foreach._target ") +# Rudimentary argument splitting. +string(REPLACE " " ";" usage_dependent_targets "${usage_dependent_targets}") +# Remove exported "target" names. +list(FILTER usage_dependent_targets EXCLUDE REGEX "CXXModules::") +# Strip quotes. +string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}") + +if ("__CMAKE::CXX23" IN_LIST usage_dependent_targets) + message(SEND_ERROR + "The main export requires the '__CMAKE::CXX23' target") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/uses-std.cxx b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/uses-std.cxx new file mode 100644 index 0000000..aa45dd1 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/uses-std.cxx @@ -0,0 +1,7 @@ +export module uses_std; +import std; + +export int f() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/CMakeLists.txt new file mode 100644 index 0000000..8b9295d --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/CMakeLists.txt @@ -0,0 +1,55 @@ +cmake_minimum_required(VERSION 3.29) +project(cxx_modules_import_std_not_in_export CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +set(CMAKE_CXX_MODULE_STD 1) + +add_library(import_std_not_in_export) +target_sources(import_std_not_in_export + PUBLIC + FILE_SET use_std TYPE CXX_MODULES FILES + uses-std.cxx) +target_compile_features(import_std_not_in_export PUBLIC cxx_std_23) + +add_executable(main + main.cxx) +target_link_libraries(main PRIVATE import_std_not_in_export) + +install(TARGETS import_std_not_in_export + EXPORT export + ARCHIVE DESTINATION "lib" + FILE_SET use_std DESTINATION "lib/cxx/miu") +install( + EXPORT export + NAMESPACE CXXModules:: + DESTINATION "lib/cmake/import_std_not_in_export" + FILE "import_std_not_in_export-targets.cmake") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/import_std_not_in_export-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/import_std_not_in_export-targets.cmake\") +set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1) +") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/import_std_not_in_export-config.cmake" + DESTINATION "lib/cmake/import_std_not_in_export") + +add_test(NAME main COMMAND main) + +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 import_std_not_in_export_build + COMMAND + "${CMAKE_COMMAND}" + "-Dexpected_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu" + "-Dimport_std_not_in_export_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/import_std_not_in_export" + ${generator} + -S "${CMAKE_CURRENT_SOURCE_DIR}/test" + -B "${CMAKE_CURRENT_BINARY_DIR}/test") diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/main.cxx b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/main.cxx new file mode 100644 index 0000000..a6dd8d8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/main.cxx @@ -0,0 +1,6 @@ +import uses_std; + +int main(int argc, char* argv[]) +{ + return f(); +} diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/test/CMakeLists.txt new file mode 100644 index 0000000..4e994d2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/test/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.29) +project(cxx_modules_library NONE) + +find_package(import_std_not_in_export REQUIRED) + +if (NOT TARGET CXXModules::import_std_not_in_export) + message(FATAL_ERROR + "Missing imported target") +endif () + +function (check_property expected property) + get_property(actual TARGET CXXModules::import_std_not_in_export + PROPERTY "${property}") + if (NOT DEFINED actual) + if (NOT expected STREQUAL "") + message(SEND_ERROR + "Mismatch for ${property}:\n expected: ${expected}\n actual: NOT-DEFINED") + endif () + elseif (NOT actual STREQUAL expected) + message(SEND_ERROR + "Mismatch for ${property}:\n expected: ${expected}\n actual: ${actual}") + endif () +endfunction () + +check_property("" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES") +check_property("" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS") +check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES") +check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES") +check_property("" "INTERFACE_LINK_LIBRARIES") +check_property("1" "CXX_MODULE_STD") + +# Extract the export-dependent targets from the export file. +file(STRINGS "${import_std_not_in_export_DIR}/import_std_not_in_export-targets.cmake" usage_dependent_targets + REGEX "foreach._target ") +# Rudimentary argument splitting. +string(REPLACE " " ";" usage_dependent_targets "${usage_dependent_targets}") +# Remove exported "target" names. +list(FILTER usage_dependent_targets EXCLUDE REGEX "CXXModules::") +# Strip quotes. +string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}") + +if ("__CMAKE::CXX23" IN_LIST usage_dependent_targets) + message(SEND_ERROR + "The main export requires the '__CMAKE::CXX23' target") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/uses-std.cxx b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/uses-std.cxx new file mode 100644 index 0000000..aa45dd1 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/uses-std.cxx @@ -0,0 +1,7 @@ +export module uses_std; +import std; + +export int f() +{ + return 0; +} -- cgit v0.12 From 85e1281e004cc7272b4d4342921065adf0e1cf82 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 1 Mar 2024 23:36:20 -0500 Subject: Tests/CXXModules: add tests for exporting `CXX_MODULE_STD` --- Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 4 ++ .../import-std-export-no-std-build/CMakeLists.txt | 56 +++++++++++++++++++++ .../impl-uses-std.cxx | 3 ++ .../import-std-export-no-std-build/main.cxx | 6 +++ .../test/CMakeLists.txt | 45 +++++++++++++++++ .../import-std-export-no-std-build/uses-std.cxx | 8 +++ .../CMakeLists.txt | 58 ++++++++++++++++++++++ .../impl-uses-std.cxx | 3 ++ .../import-std-export-no-std-install/main.cxx | 6 +++ .../test/CMakeLists.txt | 45 +++++++++++++++++ .../import-std-export-no-std-install/uses-std.cxx | 9 ++++ 11 files changed, 243 insertions(+) create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/impl-uses-std.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/main.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/test/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/uses-std.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/impl-uses-std.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/main.cxx create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/test/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/uses-std.cxx diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 84e2085..725ff2f 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -243,6 +243,10 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) set(RunCMake_CXXModules_NO_TEST 1) run_cxx_module_test(import-std-no-std-property) unset(RunCMake_CXXModules_NO_TEST) + run_cxx_module_test(import-std-export-no-std-build) + set(RunCMake_CXXModules_INSTALL 1) + run_cxx_module_test(import-std-export-no-std-install) + unset(RunCMake_CXXModules_INSTALL) if ("collation" IN_LIST CMake_TEST_MODULE_COMPILATION) run_cxx_module_test(import-std-not-in-export-build) diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/CMakeLists.txt new file mode 100644 index 0000000..0a4c41d --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required(VERSION 3.29) +project(cxx_modules_import_std_export_no_std CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +set(CMAKE_NO_STD 1) + +add_library(import_std_export_no_std) +target_sources(import_std_export_no_std + PRIVATE + uses-std.cxx + PUBLIC + FILE_SET use_std TYPE CXX_MODULES FILES + impl-uses-std.cxx) +target_compile_features(import_std_export_no_std PUBLIC cxx_std_23) +set_property(TARGET import_std_export_no_std + PROPERTY + CXX_MODULE_STD "$>") + +add_executable(main + main.cxx) +target_link_libraries(main PRIVATE import_std_export_no_std) + +install(TARGETS import_std_export_no_std + EXPORT export + ARCHIVE DESTINATION "lib" + FILE_SET use_std DESTINATION "lib/cxx/miu") +export(EXPORT export + NAMESPACE CXXModules:: + FILE "${CMAKE_CURRENT_BINARY_DIR}/import_std_export_no_std-targets.cmake") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/import_std_export_no_std-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/import_std_export_no_std-targets.cmake\") +set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1) +") + +add_test(NAME main COMMAND main) + +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 import_std_export_no_std_build + COMMAND + "${CMAKE_COMMAND}" + "-Dexpected_dir=${CMAKE_CURRENT_SOURCE_DIR}" + "-Dimport_std_export_no_std_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/import-std-export-no-std-build/impl-uses-std.cxx b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/impl-uses-std.cxx new file mode 100644 index 0000000..ee19332 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/impl-uses-std.cxx @@ -0,0 +1,3 @@ +export module uses_std; + +export int f(); diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/main.cxx b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/main.cxx new file mode 100644 index 0000000..a6dd8d8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/main.cxx @@ -0,0 +1,6 @@ +import uses_std; + +int main(int argc, char* argv[]) +{ + return f(); +} diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/test/CMakeLists.txt new file mode 100644 index 0000000..e37f174 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/test/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.29) +project(cxx_modules_library NONE) + +find_package(import_std_export_no_std REQUIRED) + +if (NOT TARGET CXXModules::import_std_export_no_std) + message(FATAL_ERROR + "Missing imported target") +endif () + +function (check_property expected property) + get_property(actual TARGET CXXModules::import_std_export_no_std + PROPERTY "${property}") + if (NOT DEFINED actual) + if (NOT expected STREQUAL "") + message(SEND_ERROR + "Mismatch for ${property}:\n expected: ${expected}\n actual: NOT-DEFINED") + endif () + elseif (NOT actual STREQUAL expected) + message(SEND_ERROR + "Mismatch for ${property}:\n expected: ${expected}\n actual: ${actual}") + endif () +endfunction () + +check_property("" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES") +check_property("" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS") +check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES") +check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES") +check_property("" "INTERFACE_LINK_LIBRARIES") +check_property("$" "CXX_MODULE_STD") + +# Extract the export-dependent targets from the export file. +file(STRINGS "${import_std_export_no_std_DIR}/import_std_export_no_std-targets.cmake" usage_dependent_targets + REGEX "foreach._target ") +# Rudimentary argument splitting. +string(REPLACE " " ";" usage_dependent_targets "${usage_dependent_targets}") +# Remove exported "target" names. +list(FILTER usage_dependent_targets EXCLUDE REGEX "CXXModules::") +# Strip quotes. +string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}") + +if ("__CMAKE::CXX23" IN_LIST usage_dependent_targets) + message(SEND_ERROR + "The main export requires the '__CMAKE::CXX23' target") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/uses-std.cxx b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/uses-std.cxx new file mode 100644 index 0000000..bd91093 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/uses-std.cxx @@ -0,0 +1,8 @@ +module uses_std; + +import std; + +int f() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/CMakeLists.txt new file mode 100644 index 0000000..69edbb5 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/CMakeLists.txt @@ -0,0 +1,58 @@ +cmake_minimum_required(VERSION 3.29) +project(cxx_modules_import_std_export_no_std CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(import_std_export_no_std) +target_sources(import_std_export_no_std + PRIVATE + uses-std.cxx + PUBLIC + FILE_SET use_std TYPE CXX_MODULES FILES + impl-uses-std.cxx) +target_compile_features(import_std_export_no_std PUBLIC cxx_std_23) +set_property(TARGET import_std_export_no_std + PROPERTY + CXX_MODULE_STD "$>") + +add_executable(main + main.cxx) +target_link_libraries(main PRIVATE import_std_export_no_std) + +install(TARGETS import_std_export_no_std + EXPORT export + ARCHIVE DESTINATION "lib" + FILE_SET use_std DESTINATION "lib/cxx/miu") +install( + EXPORT export + NAMESPACE CXXModules:: + DESTINATION "lib/cmake/import_std_export_no_std" + FILE "import_std_export_no_std-targets.cmake") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/import_std_export_no_std-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/import_std_export_no_std-targets.cmake\") +set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1) +") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/import_std_export_no_std-config.cmake" + DESTINATION "lib/cmake/import_std_export_no_std") + +add_test(NAME main COMMAND main) + +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 import_std_export_no_std_build + COMMAND + "${CMAKE_COMMAND}" + "-Dexpected_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu" + "-Dimport_std_export_no_std_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/import_std_export_no_std" + ${generator} + -S "${CMAKE_CURRENT_SOURCE_DIR}/test" + -B "${CMAKE_CURRENT_BINARY_DIR}/test") diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/impl-uses-std.cxx b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/impl-uses-std.cxx new file mode 100644 index 0000000..ee19332 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/impl-uses-std.cxx @@ -0,0 +1,3 @@ +export module uses_std; + +export int f(); diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/main.cxx b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/main.cxx new file mode 100644 index 0000000..a6dd8d8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/main.cxx @@ -0,0 +1,6 @@ +import uses_std; + +int main(int argc, char* argv[]) +{ + return f(); +} diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/test/CMakeLists.txt new file mode 100644 index 0000000..e37f174 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/test/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.29) +project(cxx_modules_library NONE) + +find_package(import_std_export_no_std REQUIRED) + +if (NOT TARGET CXXModules::import_std_export_no_std) + message(FATAL_ERROR + "Missing imported target") +endif () + +function (check_property expected property) + get_property(actual TARGET CXXModules::import_std_export_no_std + PROPERTY "${property}") + if (NOT DEFINED actual) + if (NOT expected STREQUAL "") + message(SEND_ERROR + "Mismatch for ${property}:\n expected: ${expected}\n actual: NOT-DEFINED") + endif () + elseif (NOT actual STREQUAL expected) + message(SEND_ERROR + "Mismatch for ${property}:\n expected: ${expected}\n actual: ${actual}") + endif () +endfunction () + +check_property("" "IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES") +check_property("" "IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS") +check_property("cxx_std_23" "IMPORTED_CXX_MODULES_COMPILE_FEATURES") +check_property("" "IMPORTED_CXX_MODULES_LINK_LIBRARIES") +check_property("" "INTERFACE_LINK_LIBRARIES") +check_property("$" "CXX_MODULE_STD") + +# Extract the export-dependent targets from the export file. +file(STRINGS "${import_std_export_no_std_DIR}/import_std_export_no_std-targets.cmake" usage_dependent_targets + REGEX "foreach._target ") +# Rudimentary argument splitting. +string(REPLACE " " ";" usage_dependent_targets "${usage_dependent_targets}") +# Remove exported "target" names. +list(FILTER usage_dependent_targets EXCLUDE REGEX "CXXModules::") +# Strip quotes. +string(REPLACE "\"" "" usage_dependent_targets "${usage_dependent_targets}") + +if ("__CMAKE::CXX23" IN_LIST usage_dependent_targets) + message(SEND_ERROR + "The main export requires the '__CMAKE::CXX23' target") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/uses-std.cxx b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/uses-std.cxx new file mode 100644 index 0000000..6b7e814 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/uses-std.cxx @@ -0,0 +1,9 @@ +module uses_std; +import std; + +int f() +{ + std::string str = "hello!"; + std::cout << "program: " << str << std::endl; + return 0; +} -- cgit v0.12 From 64548fef160f2daf4489caf17bc5cd79fdc802aa Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 26 Feb 2024 17:38:24 -0500 Subject: Tests/CXXModules: test using targets that import `std` --- Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 6 ++++++ .../examples/import-std-transitive/CMakeLists.txt | 25 ++++++++++++++++++++++ .../examples/import-std-transitive/main.cxx | 6 ++++++ 3 files changed, 37 insertions(+) create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-transitive/CMakeLists.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-transitive/main.cxx diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 725ff2f..94e380d 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -250,10 +250,16 @@ if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) if ("collation" IN_LIST CMake_TEST_MODULE_COMPILATION) run_cxx_module_test(import-std-not-in-export-build) + run_cxx_module_test(import-std-transitive import-std-transitive-not-in-export-build "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/examples/import-std-not-in-export-build-build") set(RunCMake_CXXModules_INSTALL 1) run_cxx_module_test(import-std-not-in-export-install) unset(RunCMake_CXXModules_INSTALL) + run_cxx_module_test(import-std-transitive import-std-transitive-not-in-export-install "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/examples/import-std-not-in-export-install-install") + + run_cxx_module_test(import-std-transitive import-std-transitive-export-no-std-build "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/examples/import-std-export-no-std-build-build" -DEXPORT_NO_STD=1) + run_cxx_module_test(import-std-transitive import-std-transitive-export-no-std-install "-DCMAKE_PREFIX_PATH=${RunCMake_BINARY_DIR}/examples/import-std-export-no-std-install-install" -DEXPORT_NO_STD=1) + endif () endif () endif () diff --git a/Tests/RunCMake/CXXModules/examples/import-std-transitive/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-transitive/CMakeLists.txt new file mode 100644 index 0000000..526298c --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-transitive/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.29) + +if (EXPORT_NO_STD) + # Block making C++ `import std` targets. + add_library(__CMAKE::CXX23 IMPORTED INTERFACE) +endif () + +project(cxx_modules_import_std_transitive CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +if (EXPORT_NO_STD) + set(package "import_std_export_no_std") +else () + set(package "import_std_not_in_export") +endif () +find_package("${package}" REQUIRED) + +set(CMAKE_CXX_MODULE_STD 0) + +add_executable(main + main.cxx) +target_link_libraries(main PRIVATE "CXXModules::${package}") + +add_test(NAME main COMMAND main) diff --git a/Tests/RunCMake/CXXModules/examples/import-std-transitive/main.cxx b/Tests/RunCMake/CXXModules/examples/import-std-transitive/main.cxx new file mode 100644 index 0000000..a6dd8d8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-transitive/main.cxx @@ -0,0 +1,6 @@ +import uses_std; + +int main(int argc, char* argv[]) +{ + return f(); +} -- cgit v0.12 From 7146cf92486a56014f858d6fe6032fbe1453fb7f Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 26 Feb 2024 17:57:07 -0500 Subject: cmTarget: support the `CXX_MODULE_STD` property --- Help/manual/cmake-properties.7.rst | 1 + Help/manual/cmake-variables.7.rst | 1 + Help/prop_tgt/CXX_MODULE_STD.rst | 36 +++++++++++++++++++++++ Help/release/dev/CXX_MODULE_STD-property.rst | 5 ++++ Help/variable/CMAKE_CXX_MODULE_STD.rst | 10 +++++++ Source/cmExportFileGenerator.cxx | 8 +++++ Source/cmTarget.cxx | 2 ++ Tests/RunCMake/property_init/CompileSources.cmake | 1 + 8 files changed, 64 insertions(+) create mode 100644 Help/prop_tgt/CXX_MODULE_STD.rst create mode 100644 Help/release/dev/CXX_MODULE_STD-property.rst create mode 100644 Help/variable/CMAKE_CXX_MODULE_STD.rst diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 8d2d202..6ccc23e 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -194,6 +194,7 @@ Properties on Targets /prop_tgt/CXX_MODULE_SET /prop_tgt/CXX_MODULE_SET_NAME /prop_tgt/CXX_MODULE_SETS + /prop_tgt/CXX_MODULE_STD /prop_tgt/CXX_SCAN_FOR_MODULES /prop_tgt/CXX_STANDARD /prop_tgt/CXX_STANDARD_REQUIRED diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 4bb0ec8..6ae7d1c 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -424,6 +424,7 @@ Variables that Control the Build /variable/CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS /variable/CMAKE_CUDA_RUNTIME_LIBRARY /variable/CMAKE_CUDA_SEPARABLE_COMPILATION + /variable/CMAKE_CXX_MODULE_STD /variable/CMAKE_CXX_SCAN_FOR_MODULES /variable/CMAKE_DEBUG_POSTFIX /variable/CMAKE_DEFAULT_BUILD_TYPE diff --git a/Help/prop_tgt/CXX_MODULE_STD.rst b/Help/prop_tgt/CXX_MODULE_STD.rst new file mode 100644 index 0000000..3ec7bb0 --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_STD.rst @@ -0,0 +1,36 @@ +CXX_MODULE_STD +-------------- + +.. versionadded:: 3.30 + +``CXX_MODULE_STD`` is a boolean specifying whether the target may use +``import std;`` its C++ sources or not. + +When this property is explicitly set to ``ON``, CMake will add a dependency to +a target which provides the C++ standard library's modules for the C++ +standard applied to the target. This target is only applicable within the +current build and will not appear in the exported interfaces of the targets. +When consumed, these targets will be reapplied as necessary. + +.. note: + + Similar to the introduction of :prop:`CXX_SCAN_FOR_MODULES`, this property + defaults to _not_ adding ``import std`` support to targets using + ``cxx_std_23`` without an explicit request in order to preserve existing + behavior for projects using C++23 without ``import std``. A future policy + to change the default behavior is expected once the feature sees wider + usage. + +This property's value is not relevant for targets which disable scanning (see +:prop_tgt:`CXX_SCAN_FOR_MODULES`). Additionally, this property only applies to +targets utilizing C++23 (``cxx_std_23``) or newer. + +The property supports +:manual:`generator expressions `, however +expressions that depend upon the configuration, the consuming target, or the +linker language are not allowed. Whether a target uses ``import std`` should +not depend upon such things as it is a static property of the target's source +code. + +Targets which are exported with C++ module sources will have this property's +resolved value exported. diff --git a/Help/release/dev/CXX_MODULE_STD-property.rst b/Help/release/dev/CXX_MODULE_STD-property.rst new file mode 100644 index 0000000..50febf4 --- /dev/null +++ b/Help/release/dev/CXX_MODULE_STD-property.rst @@ -0,0 +1,5 @@ +CXX_MODULE_STD-property +----------------------- + +* The :prop_tgt:`CXX_MODULE_STD` property may be used to control + ``import std;`` support for targets. diff --git a/Help/variable/CMAKE_CXX_MODULE_STD.rst b/Help/variable/CMAKE_CXX_MODULE_STD.rst new file mode 100644 index 0000000..b20e620 --- /dev/null +++ b/Help/variable/CMAKE_CXX_MODULE_STD.rst @@ -0,0 +1,10 @@ +CMAKE_CXX_MODULE_STD +-------------------- + +.. versionadded:: 3.30 + +Whether to add utility targets as dependencies to targets with at least +``cxx_std_23`` or not. + +This variable is used to initialize the :prop_tgt:`CXX_MODULE_STD` property on +all targets. See that target property for additional information. diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 2d48f34..9bd7f49 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -1438,6 +1438,14 @@ bool cmExportFileGenerator::PopulateCxxModuleExportProperties( const ModuleTargetPropertyTable exportedDirectModuleProperties[] = { { "CXX_EXTENSIONS"_s, ExportWhen::Defined }, + // Always define this property as it is an intrinsic property of the target + // and should not be inherited from the in-scope `CMAKE_CXX_MODULE_STD` + // variable. + // + // TODO(cxxmodules): A future policy may make this "ON" based on the target + // policies if unset. Add a new `ExportWhen` condition to handle it when + // this happens. + { "CXX_MODULE_STD"_s, ExportWhen::Always }, }; for (auto const& prop : exportedDirectModuleProperties) { auto const propNameStr = std::string(prop.Name); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 3f7e29b..1284130 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -412,6 +412,7 @@ TargetProperty const StaticTargetProperties[] = { COMMON_LANGUAGE_PROPERTIES(C), // ---- C++ COMMON_LANGUAGE_PROPERTIES(CXX), + { "CXX_MODULE_STD"_s, IC::CanCompileSources }, // ---- CSharp { "DOTNET_SDK"_s, IC::NonImportedTarget }, { "DOTNET_TARGET_FRAMEWORK"_s, IC::TargetWithCommands }, @@ -1842,6 +1843,7 @@ void cmTarget::CopyImportedCxxModulesProperties(cmTarget const* tgt) "CXX_STANDARD_REQUIRED", "CXX_EXTENSIONS", "CXX_VISIBILITY_PRESET", + "CXX_MODULE_STD", // Static analysis "CXX_CLANG_TIDY", diff --git a/Tests/RunCMake/property_init/CompileSources.cmake b/Tests/RunCMake/property_init/CompileSources.cmake index e8c5554..22b8f3f 100644 --- a/Tests/RunCMake/property_init/CompileSources.cmake +++ b/Tests/RunCMake/property_init/CompileSources.cmake @@ -100,6 +100,7 @@ set(properties "C_LINKER_LAUNCHER" "ccache" "" ### C++ "CXX_LINKER_LAUNCHER" "ccache" "" + "CXX_MODULE_STD" "ON" "" ### CUDA "CUDA_RESOLVE_DEVICE_SYMBOLS" "ON" "" "CUDA_RUNTIME_LIBRARY" "Static" "" -- cgit v0.12 From 7aa1e45e568783e89f7266ff9b8d6f3c538a560b Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 27 Feb 2024 11:53:49 -0500 Subject: cmStandardLevelResolver: offer an API to get the string of a level --- Source/cmStandardLevelResolver.cxx | 15 +++++++++++++++ Source/cmStandardLevelResolver.h | 3 +++ 2 files changed, 18 insertions(+) diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index c9ed380..44c4ae1 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -541,6 +541,21 @@ std::string cmStandardLevelResolver::GetEffectiveStandard( return mapping->second.GetEffectiveStandard(this->Makefile, target, config); } +std::string cmStandardLevelResolver::GetLevelString( + std::string const& lang, cmStandardLevel const& level) const +{ + auto mapping = StandardComputerMapping.find(lang); + if (mapping == StandardComputerMapping.end()) { + return {}; + } + + if (mapping->second.LevelsAsStrings.size() <= level.Index()) { + return {}; + } + + return mapping->second.LevelsAsStrings[level.Index()]; +} + bool cmStandardLevelResolver::AddRequiredTargetFeature( cmTarget* target, const std::string& feature, std::string* error) const { diff --git a/Source/cmStandardLevelResolver.h b/Source/cmStandardLevelResolver.h index 29cab55..523aa73 100644 --- a/Source/cmStandardLevelResolver.h +++ b/Source/cmStandardLevelResolver.h @@ -29,6 +29,9 @@ public: std::string const& lang, std::string const& config) const; + std::string GetLevelString(std::string const& lang, + cmStandardLevel const& level) const; + bool AddRequiredTargetFeature(cmTarget* target, const std::string& feature, std::string* error = nullptr) const; -- cgit v0.12 From d7e65b61781fdd3598c2115e10723449dde2f2e4 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 27 Feb 2024 11:54:35 -0500 Subject: Tests/CXXModules: mask C++23 std module targets These tests mess with the availability of C++ module support. Hide generation of the utility targets from any compiler detection. --- Tests/RunCMake/CXXModules/CMP0155-NEW.cmake | 3 +++ Tests/RunCMake/CXXModules/CMP0155-OLD.cmake | 3 +++ Tests/RunCMake/CXXModules/ImplicitCXX20.cmake | 3 +++ Tests/RunCMake/CXXModules/NoCXX20.cmake | 3 +++ Tests/RunCMake/CXXModules/NoScanningVariable.cmake | 3 +++ 5 files changed, 15 insertions(+) diff --git a/Tests/RunCMake/CXXModules/CMP0155-NEW.cmake b/Tests/RunCMake/CXXModules/CMP0155-NEW.cmake index d68775a..c754930 100644 --- a/Tests/RunCMake/CXXModules/CMP0155-NEW.cmake +++ b/Tests/RunCMake/CXXModules/CMP0155-NEW.cmake @@ -1,3 +1,6 @@ +# Block making C++ `import std` targets. +add_library(__CMAKE::CXX23 IMPORTED INTERFACE) + enable_language(CXX) unset(CMAKE_CXX_SCANDEP_SOURCE) diff --git a/Tests/RunCMake/CXXModules/CMP0155-OLD.cmake b/Tests/RunCMake/CXXModules/CMP0155-OLD.cmake index 201598e..a994266 100644 --- a/Tests/RunCMake/CXXModules/CMP0155-OLD.cmake +++ b/Tests/RunCMake/CXXModules/CMP0155-OLD.cmake @@ -1,3 +1,6 @@ +# Block making C++ `import std` targets. +add_library(__CMAKE::CXX23 IMPORTED INTERFACE) + enable_language(CXX) unset(CMAKE_CXX_SCANDEP_SOURCE) diff --git a/Tests/RunCMake/CXXModules/ImplicitCXX20.cmake b/Tests/RunCMake/CXXModules/ImplicitCXX20.cmake index cac1777..64d69f3 100644 --- a/Tests/RunCMake/CXXModules/ImplicitCXX20.cmake +++ b/Tests/RunCMake/CXXModules/ImplicitCXX20.cmake @@ -1,6 +1,9 @@ # Enable scanning by default for targets that explicitly use C++ 20. cmake_policy(SET CMP0155 NEW) +# Block making C++ `import std` targets. +add_library(__CMAKE::CXX23 IMPORTED INTERFACE) + # Force CMAKE_CXX_STANDARD_DEFAULT to be C++ 20. set(ENV{CXXFLAGS} "$ENV{CXXFLAGS} ${CMAKE_CXX20_STANDARD_COMPILE_OPTION}") enable_language(CXX) diff --git a/Tests/RunCMake/CXXModules/NoCXX20.cmake b/Tests/RunCMake/CXXModules/NoCXX20.cmake index b7372e8..9710728 100644 --- a/Tests/RunCMake/CXXModules/NoCXX20.cmake +++ b/Tests/RunCMake/CXXModules/NoCXX20.cmake @@ -1,3 +1,6 @@ +# Block making C++ `import std` targets. +add_library(__CMAKE::CXX23 IMPORTED INTERFACE) + enable_language(CXX) add_library(nocxx20) diff --git a/Tests/RunCMake/CXXModules/NoScanningVariable.cmake b/Tests/RunCMake/CXXModules/NoScanningVariable.cmake index 4bb6a70..950f1f3 100644 --- a/Tests/RunCMake/CXXModules/NoScanningVariable.cmake +++ b/Tests/RunCMake/CXXModules/NoScanningVariable.cmake @@ -1,6 +1,9 @@ # Enable scanning by default for targets that explicitly use C++ 20. cmake_policy(SET CMP0155 NEW) +# Block making C++ `import std` targets. +add_library(__CMAKE::CXX23 IMPORTED INTERFACE) + enable_language(CXX) # Hide any real scanning rule that may be available. -- cgit v0.12 From 15cd73d6c24a2ad888d5c324a64fc7ea4b760d91 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 1 Mar 2024 08:03:37 -0500 Subject: cmGlobalGenerator: compute target features before synthetic targets For `import std;` support, CMake needs to know the standard library involved in order to ensure that the right target is linked. Afterwards, the created synthetic targets need their target compile features computed. --- Source/cmGeneratorTarget.cxx | 12 ++++++++++++ Source/cmGlobalGenerator.cxx | 26 ++++++++++++++++---------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 2ec1a29..f0acb9c 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -8414,6 +8414,8 @@ void ComputeLinkImplTransitive(cmGeneratorTarget const* self, bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache, std::string const& config) { + std::vector allConfigs = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); cmOptionalLinkImplementation impl; this->ComputeLinkImplementationLibraries(config, impl, this, LinkInterfaceFor::Link); @@ -8488,9 +8490,19 @@ bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache, // Create the generator target and attach it to the local generator. auto gtp = cm::make_unique(tgt, lg); + synthDep = gtp.get(); cache.CxxModuleTargets[targetName] = synthDep; + + // See `localGen->ComputeTargetCompileFeatures()` call in + // `cmGlobalGenerator::Compute` for where non-synthetic targets resolve + // this. + for (auto const& innerConfig : allConfigs) { + gtp->ComputeCompileFeatures(innerConfig); + } + gtp->DiscoverSyntheticTargets(cache, config); + lg->AddGeneratorTarget(std::move(gtp)); } else { synthDep = cached->second; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 213142a..c0af34b 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1581,6 +1581,19 @@ bool cmGlobalGenerator::Compute() } #endif + // Perform up-front computation in order to handle errors (such as unknown + // features) at this point. While processing the compile features we also + // calculate and cache the language standard required by the compile + // features. + // + // Synthetic targets performed this inside of + // `cmLocalGenerator::DiscoverSyntheticTargets` + for (const auto& localGen : this->LocalGenerators) { + if (!localGen->ComputeTargetCompileFeatures()) { + return false; + } + } + // Iterate through all targets and set up C++20 module targets. // Create target templates for each imported target with C++20 modules. // INTERFACE library with BMI-generating rules and a collation step? @@ -1588,6 +1601,9 @@ bool cmGlobalGenerator::Compute() // Make `add_dependencies(imported_target // $<$:synth1> // $<$:synth2>)` + // + // Note that synthetic target creation performs the above marked + // steps on the created targets. if (!this->DiscoverSyntheticTargets()) { return false; } @@ -1597,16 +1613,6 @@ bool cmGlobalGenerator::Compute() localGen->AddHelperCommands(); } - // Perform up-front computation in order to handle errors (such as unknown - // features) at this point. While processing the compile features we also - // calculate and cache the language standard required by the compile - // features. - for (const auto& localGen : this->LocalGenerators) { - if (!localGen->ComputeTargetCompileFeatures()) { - return false; - } - } - // Add automatically generated sources (e.g. unity build). // Add unity sources after computing compile features. Unity sources do // not change the set of languages or features, but we need to know them -- cgit v0.12 From 2c8361f923317a784adfa6502e1a0c3a17c1dff9 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 27 Feb 2024 11:53:32 -0500 Subject: cxxmodules: link to `std`-providing targets when available --- Help/manual/cmake-cxxmodules.7.rst | 9 +++- Source/cmGeneratorTarget.cxx | 103 +++++++++++++++++++++++++++++++++++++ Source/cmGeneratorTarget.h | 1 + Source/cmGlobalGenerator.cxx | 23 +++++++++ Source/cmGlobalGenerator.h | 1 + 5 files changed, 136 insertions(+), 1 deletion(-) diff --git a/Help/manual/cmake-cxxmodules.7.rst b/Help/manual/cmake-cxxmodules.7.rst index 8f62b5a..0c9c46e 100644 --- a/Help/manual/cmake-cxxmodules.7.rst +++ b/Help/manual/cmake-cxxmodules.7.rst @@ -86,6 +86,12 @@ Compilers which CMake natively supports module dependency scanning include: * LLVM/Clang 16.0 and newer * GCC 14 (for the in-development branch, after 2023-09-20) and newer +``import std`` Support +====================== + +Support for ``import std`` is limited to the following toolchain and standard +library combinations: + Generator Support ================= @@ -116,6 +122,7 @@ For the :ref:`Visual Studio Generators`: - Only Visual Studio 2022 and MSVC toolsets 14.34 (Visual Studio 17.4) and newer. - No support for exporting or installing BMI or module information. -- No support for compiling BMIs from ``IMPORTED`` targets with C++ modules. +- No support for compiling BMIs from ``IMPORTED`` targets with C++ modules + (including ``import std``). - No diagnosis of using modules provided by ``PRIVATE`` sources from ``PUBLIC`` module sources. diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index f0acb9c..1dba976 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -8411,6 +8411,106 @@ void ComputeLinkImplTransitive(cmGeneratorTarget const* self, } } +bool cmGeneratorTarget::ApplyCXXStdTargets() +{ + cmStandardLevelResolver standardResolver(this->Makefile); + cmStandardLevel const cxxStd23 = + *standardResolver.LanguageStandardLevel("CXX", "23"); + std::vector const& configs = + this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); + auto std_prop = this->GetProperty("CXX_MODULE_STD"); + if (!std_prop) { + // TODO(cxxmodules): Add a target policy to flip the default here. Set + // `std_prop` based on it. + return true; + } + + std::string std_prop_value; + if (std_prop) { + // Evaluate generator expressions. + cmGeneratorExpression ge(*this->LocalGenerator->GetCMakeInstance()); + auto cge = ge.Parse(*std_prop); + if (!cge) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(R"(The "CXX_MODULE_STD" property on the target ")", + this->GetName(), "\" is not a valid generator expression.")); + return false; + } + // But do not allow context-sensitive queries. Whether a target uses + // `import std` should not depend on configuration or properties of the + // consumer (head target). The link language also shouldn't matter, so ban + // it as well. + if (cge->GetHadHeadSensitiveCondition()) { + // Not reachable; all target-sensitive genexes actually fail to parse. + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(R"(The "CXX_MODULE_STD" property on the target ")", + this->GetName(), + "\" contains a condition that queries the " + "consuming target which is not supported.")); + return false; + } + if (cge->GetHadLinkLanguageSensitiveCondition()) { + // Not reachable; all link language genexes actually fail to parse. + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(R"(The "CXX_MODULE_STD" property on the target ")", + this->GetName(), + "\" contains a condition that queries the " + "link language which is not supported.")); + return false; + } + std_prop_value = cge->Evaluate(this->LocalGenerator, ""); + if (cge->GetHadContextSensitiveCondition()) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(R"(The "CXX_MODULE_STD" property on the target ")", + this->GetName(), + "\" contains a context-sensitive condition " + "that is not supported.")); + return false; + } + } + auto use_std = cmIsOn(std_prop_value); + + // If we have a value and it is not true, there's nothing to do. + if (std_prop && !use_std) { + return true; + } + + for (auto const& config : configs) { + if (this->HaveCxxModuleSupport(config) != Cxx20SupportLevel::Supported) { + continue; + } + + cm::optional explicitLevel = + this->GetExplicitStandardLevel("CXX", config); + if (!explicitLevel || *explicitLevel < cxxStd23) { + continue; + } + + auto const targetName = cmStrCat( + "__CMAKE::CXX", standardResolver.GetLevelString("CXX", *explicitLevel)); + if (!this->Makefile->FindTargetToUse(targetName)) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + R"(The "CXX_MODULE_STD" property on the target ")", this->GetName(), + "\" requires that the \"", targetName, + "\" target exist, but it was not provided by the toolchain.")); + break; + } + + this->Target->AppendProperty( + "LINK_LIBRARIES", + cmStrCat("$:", targetName, + ">>")); + } + + return true; +} + bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache, std::string const& config) { @@ -8500,6 +8600,9 @@ bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache, for (auto const& innerConfig : allConfigs) { gtp->ComputeCompileFeatures(innerConfig); } + // See `cmGlobalGenerator::ApplyCXXStdTargets` in + // `cmGlobalGenerator::Compute` for non-synthetic target resolutions. + gtp->ApplyCXXStdTargets(); gtp->DiscoverSyntheticTargets(cache, config); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index fd4b2ec..28ad898 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -961,6 +961,7 @@ public: std::string GetImportedXcFrameworkPath(const std::string& config) const; + bool ApplyCXXStdTargets(); bool DiscoverSyntheticTargets(cmSyntheticTargetCache& cache, std::string const& config); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index c0af34b..e397fa2 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1594,6 +1594,16 @@ bool cmGlobalGenerator::Compute() } } + // We now have all targets set up and std levels constructed. Add + // `__CMAKE::CXX*` targets as link dependencies to all targets which need + // them. + // + // Synthetic targets performed this inside of + // `cmLocalGenerator::DiscoverSyntheticTargets` + if (!this->ApplyCXXStdTargets()) { + return false; + } + // Iterate through all targets and set up C++20 module targets. // Create target templates for each imported target with C++20 modules. // INTERFACE library with BMI-generating rules and a collation step? @@ -1830,6 +1840,19 @@ void cmGlobalGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt, entry->second = index++; } +bool cmGlobalGenerator::ApplyCXXStdTargets() +{ + for (auto const& gen : this->LocalGenerators) { + for (auto const& tgt : gen->GetGeneratorTargets()) { + if (!tgt->ApplyCXXStdTargets()) { + return false; + } + } + } + + return true; +} + bool cmGlobalGenerator::DiscoverSyntheticTargets() { cmSyntheticTargetCache cache; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index ba39768..1ca02d9 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -674,6 +674,7 @@ protected: virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const; + bool ApplyCXXStdTargets(); bool DiscoverSyntheticTargets(); bool AddHeaderSetVerification(); -- cgit v0.12 From 19341e258284ffcc66ca04da008cb49e7284ecf5 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 12 Mar 2024 11:56:40 -0400 Subject: ci: enable `import_std23` C++ module tests on MSVC --- .gitlab/ci/configure_windows_msvc_cxx_modules_common.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab/ci/configure_windows_msvc_cxx_modules_common.cmake b/.gitlab/ci/configure_windows_msvc_cxx_modules_common.cmake index e378d62..207f2a5 100644 --- a/.gitlab/ci/configure_windows_msvc_cxx_modules_common.cmake +++ b/.gitlab/ci/configure_windows_msvc_cxx_modules_common.cmake @@ -1 +1 @@ -set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,shared,export_bmi,install_bmi,bmionly" CACHE STRING "") +set(CMake_TEST_MODULE_COMPILATION "named,compile_commands,collation,partitions,internal_partitions,shared,export_bmi,install_bmi,bmionly,import_std23" CACHE STRING "") -- cgit v0.12 From f80c60df02854b9443a0f73770d2ef7a1bcd72d5 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 24 Feb 2024 16:30:48 -0500 Subject: CMakeDetermineCompilerSupport: construct C++ modules targets Compilers may implement this by implementing a `_cmake_cxx_import_std` function which takes the standard version as an argument (e.g., `23`) and creating a target named `CMake::CXX${std}` that represents how `import std;` should be represented within CMake. --- Modules/CMakeCXXCompiler.cmake.in | 2 ++ Modules/CMakeDetermineCompilerSupport.cmake | 14 ++++++++++ Modules/Compiler/CMakeCommonCompilerMacros.cmake | 35 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index d18e1c8..e0c5f8b 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/Modules/CMakeCXXCompiler.cmake.in @@ -91,3 +91,5 @@ set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_CXX_IMPLICIT_LINK_LIBRARIES@") set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES@") set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@") set(CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR "@CMAKE_CXX_COMPILER_CLANG_RESOURCE_DIR@") + +@CMAKE_CXX_IMPORT_STD@ diff --git a/Modules/CMakeDetermineCompilerSupport.cmake b/Modules/CMakeDetermineCompilerSupport.cmake index 746f04e..d561e7b 100644 --- a/Modules/CMakeDetermineCompilerSupport.cmake +++ b/Modules/CMakeDetermineCompilerSupport.cmake @@ -105,6 +105,19 @@ function(cmake_determine_compiler_support lang) ) endif() + # Create targets for use with `import std;` here. + set(CMAKE_CXX_IMPORT_STD "") + foreach (_cmake_import_std_version IN ITEMS 23 26) + if (CMAKE_CXX${_cmake_import_std_version}_COMPILE_FEATURES) + set(_cmake_cxx_import_std "") + cmake_create_cxx_import_std("${_cmake_import_std_version}" _cmake_cxx_import_std) + if (_cmake_cxx_import_std) + string(APPEND CMAKE_CXX_IMPORT_STD "### Imported target for C++${_cmake_import_std_version} standard library\n") + string(APPEND CMAKE_CXX_IMPORT_STD "${_cmake_cxx_import_std}\n\n") + endif () + endif () + endforeach () + set(CMAKE_CXX_COMPILE_FEATURES ${CMAKE_CXX_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_CXX98_COMPILE_FEATURES ${CMAKE_CXX98_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_CXX11_COMPILE_FEATURES ${CMAKE_CXX11_COMPILE_FEATURES} PARENT_SCOPE) @@ -113,6 +126,7 @@ function(cmake_determine_compiler_support lang) set(CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_CXX23_COMPILE_FEATURES ${CMAKE_CXX23_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_CXX26_COMPILE_FEATURES ${CMAKE_CXX26_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_CXX_IMPORT_STD ${CMAKE_CXX_IMPORT_STD} PARENT_SCOPE) message(CHECK_PASS "done") diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake index 02c2b18..3a91b30 100644 --- a/Modules/Compiler/CMakeCommonCompilerMacros.cmake +++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake @@ -201,3 +201,38 @@ macro(cmake_record_hip_compile_features) _has_compiler_features_hip(11) _has_compiler_features_hip(98) endmacro() + +function(cmake_create_cxx_import_std std variable) + set(_cmake_supported_import_std_features + # Compilers support `import std` in C++20 as an extension. Skip + # for now. + # 20 + 23 + 26) + list(FIND _cmake_supported_import_std_features "${std}" _cmake_supported_import_std_idx) + if (_cmake_supported_import_std_idx EQUAL "-1") + return () + endif () + # If the target exists, skip. A toolchain file may have provided it. + if (TARGET "__CMAKE::CXX${std}") + return () + endif () + # The generator must support imported C++ modules. + if (NOT CMAKE_GENERATOR MATCHES "Ninja") + return () + endif () + # Check if the compiler understands how to `import std;`. + include("${CMAKE_ROOT}/Modules/Compiler/${CMAKE_CXX_COMPILER_ID}-CXX-CXXImportStd.cmake" OPTIONAL RESULT_VARIABLE _cmake_import_std_res) + if (NOT _cmake_import_std_res) + return () + endif () + if (NOT COMMAND _cmake_cxx_import_std) + return () + endif () + _cmake_cxx_import_std("${std}" target_definition) + string(CONCAT guarded_target_definition + "if (NOT TARGET \"__CMAKE::CXX${std}\")\n" + "${target_definition}" + "endif ()\n") + set("${variable}" "${guarded_target_definition}" PARENT_SCOPE) +endfunction() -- cgit v0.12 From 15bbd1d9b890645f3786f1b24d0d7651cbc2e807 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 10 Apr 2024 09:12:24 -0400 Subject: Experimental: add an experimental feature gate for `import std` --- Help/dev/experimental.rst | 21 +++++++++++++++++++++ Help/manual/cmake-cxxmodules.7.rst | 6 ++++++ Help/prop_tgt/CXX_MODULE_STD.rst | 5 +++++ Help/variable/CMAKE_CXX_MODULE_STD.rst | 5 +++++ Modules/Compiler/CMakeCommonCompilerMacros.cmake | 11 +++++++++++ Source/cmExperimental.cxx | 9 +++++++++ Source/cmExperimental.h | 1 + Source/cmGeneratorTarget.cxx | 9 +++++++++ .../import-std-export-no-std-build-stderr.txt | 8 ++++++++ .../import-std-export-no-std-build/CMakeLists.txt | 3 +++ .../import-std-export-no-std-install-stderr.txt | 8 ++++++++ .../import-std-export-no-std-install/CMakeLists.txt | 3 +++ .../examples/import-std-no-std-property-stderr.txt | 8 ++++++++ .../import-std-no-std-property/CMakeLists.txt | 3 +++ .../import-std-not-in-export-build-stderr.txt | 8 ++++++++ .../import-std-not-in-export-build/CMakeLists.txt | 3 +++ .../import-std-not-in-export-install-stderr.txt | 8 ++++++++ .../import-std-not-in-export-install/CMakeLists.txt | 3 +++ .../CXXModules/examples/import-std-stderr.txt | 8 ++++++++ ...rt-std-transitive-not-in-export-build-stderr.txt | 8 ++++++++ ...-std-transitive-not-in-export-install-stderr.txt | 8 ++++++++ .../examples/import-std-transitive/CMakeLists.txt | 3 +++ .../CXXModules/examples/import-std/CMakeLists.txt | 3 +++ .../Experimental/CxxImportStd-set-stderr.txt | 6 ++++++ .../Experimental/CxxImportStd-set.cmake | 11 +++++++++++ .../Experimental/CxxImportStd-unset.cmake | 8 ++++++++ Tests/RunCMake/cmake_language/RunCMakeTest.cmake | 2 ++ 27 files changed, 179 insertions(+) create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-no-std-property-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-transitive-not-in-export-build-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/examples/import-std-transitive-not-in-export-install-stderr.txt create mode 100644 Tests/RunCMake/cmake_language/Experimental/CxxImportStd-set-stderr.txt create mode 100644 Tests/RunCMake/cmake_language/Experimental/CxxImportStd-set.cmake create mode 100644 Tests/RunCMake/cmake_language/Experimental/CxxImportStd-unset.cmake diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index fc4ac8b..93298c5 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst @@ -38,3 +38,24 @@ When activated, this experimental feature provides the following: * The package name associated with specific targets may be specified using the ``CMAKE_EXPORT_FIND_PACKAGE_NAME`` variable and/or ``EXPORT_FIND_PACKAGE_NAME`` target property. + +C++ ``import std`` support +========================== + +In order to activate support for ``import std`` in C++23 and newer targets, +set + +* variable ``CMAKE_EXPERIMENTAL_CXX_IMPORT_STD`` to +* value ``0e5b6991-d74f-4b3d-a41c-cf096e0b2508``. + +This UUID may change in future versions of CMake. Be sure to use the value +documented here by the source tree of the version of CMake with which you are +experimenting. + +When activated, this experimental feature provides the following: + +* The :prop_tgt:`CXX_MODULE_STD` target property and its initializing variable + :variable:`CMAKE_CXX_MODULE_STD`. + +* Targets with the property set to a true value and at least ``cxx_std_23`` + may use ``import std;`` in any scanned C++ source file. diff --git a/Help/manual/cmake-cxxmodules.7.rst b/Help/manual/cmake-cxxmodules.7.rst index 0c9c46e..12ea0a0 100644 --- a/Help/manual/cmake-cxxmodules.7.rst +++ b/Help/manual/cmake-cxxmodules.7.rst @@ -92,6 +92,12 @@ Compilers which CMake natively supports module dependency scanning include: Support for ``import std`` is limited to the following toolchain and standard library combinations: +.. note :: + + This support is provided only when experimental support for + ``import std;`` has been enabled by the + ``CMAKE_EXPERIMENTAL_CXX_IMPORT_STD`` gate. + Generator Support ================= diff --git a/Help/prop_tgt/CXX_MODULE_STD.rst b/Help/prop_tgt/CXX_MODULE_STD.rst index 3ec7bb0..d42699d 100644 --- a/Help/prop_tgt/CXX_MODULE_STD.rst +++ b/Help/prop_tgt/CXX_MODULE_STD.rst @@ -6,6 +6,11 @@ CXX_MODULE_STD ``CXX_MODULE_STD`` is a boolean specifying whether the target may use ``import std;`` its C++ sources or not. +.. note :: + + This setting is meaningful only when experimental support for ``import + std;`` has been enabled by the ``CMAKE_EXPERIMENTAL_CXX_IMPORT_STD`` gate. + When this property is explicitly set to ``ON``, CMake will add a dependency to a target which provides the C++ standard library's modules for the C++ standard applied to the target. This target is only applicable within the diff --git a/Help/variable/CMAKE_CXX_MODULE_STD.rst b/Help/variable/CMAKE_CXX_MODULE_STD.rst index b20e620..e2b27a0 100644 --- a/Help/variable/CMAKE_CXX_MODULE_STD.rst +++ b/Help/variable/CMAKE_CXX_MODULE_STD.rst @@ -6,5 +6,10 @@ CMAKE_CXX_MODULE_STD Whether to add utility targets as dependencies to targets with at least ``cxx_std_23`` or not. +.. note :: + + This setting is meaningful only when experimental support for ``import + std;`` has been enabled by the ``CMAKE_EXPERIMENTAL_CXX_IMPORT_STD`` gate. + This variable is used to initialize the :prop_tgt:`CXX_MODULE_STD` property on all targets. See that target property for additional information. diff --git a/Modules/Compiler/CMakeCommonCompilerMacros.cmake b/Modules/Compiler/CMakeCommonCompilerMacros.cmake index 3a91b30..0b5df0d 100644 --- a/Modules/Compiler/CMakeCommonCompilerMacros.cmake +++ b/Modules/Compiler/CMakeCommonCompilerMacros.cmake @@ -229,6 +229,17 @@ function(cmake_create_cxx_import_std std variable) if (NOT COMMAND _cmake_cxx_import_std) return () endif () + + # Check the experimental flag. Check it here to avoid triggering warnings in + # situations that don't support the feature anyways. + set(_cmake_supported_import_std_experimental "") + cmake_language(GET_EXPERIMENTAL_FEATURE_ENABLED + "CxxImportStd" + _cmake_supported_import_std_experimental) + if (NOT _cmake_supported_import_std_experimental) + return () + endif () + _cmake_cxx_import_std("${std}" target_definition) string(CONCAT guarded_target_definition "if (NOT TARGET \"__CMAKE::CXX${std}\")\n" diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx index 8adf4e2..a2e6e70 100644 --- a/Source/cmExperimental.cxx +++ b/Source/cmExperimental.cxx @@ -37,6 +37,15 @@ cmExperimental::FeatureData LookupTable[] = { {}, cmExperimental::TryCompileCondition::Always, false }, + // CxxImportStd + { "CxxImportStd", + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508", + "CMAKE_EXPERIMENTAL_CXX_IMPORT_STD", + "CMake's support for `import std;` in C++23 and newer is experimental. It " + "is meant only for experimentation and feedback to CMake developers.", + {}, + cmExperimental::TryCompileCondition::Always, + false }, }; static_assert(sizeof(LookupTable) / sizeof(LookupTable[0]) == static_cast(cmExperimental::Feature::Sentinel), diff --git a/Source/cmExperimental.h b/Source/cmExperimental.h index 1abfbc3..05764f9 100644 --- a/Source/cmExperimental.h +++ b/Source/cmExperimental.h @@ -19,6 +19,7 @@ public: { ExportPackageDependencies, WindowsKernelModeDriver, + CxxImportStd, Sentinel, }; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 1dba976..be82099 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -32,6 +32,7 @@ #include "cmCustomCommandGenerator.h" #include "cmCxxModuleUsageEffects.h" #include "cmEvaluatedTargetProperty.h" +#include "cmExperimental.h" #include "cmFileSet.h" #include "cmFileTimes.h" #include "cmGeneratedFileStream.h" @@ -8502,6 +8503,14 @@ bool cmGeneratorTarget::ApplyCXXStdTargets() break; } + // Check the experimental feature here as well. A toolchain may have + // provided the target and skipped the check in the toolchain preparation + // logic. + if (!cmExperimental::HasSupportEnabled( + *this->Makefile, cmExperimental::Feature::CxxImportStd)) { + break; + } + this->Target->AppendProperty( "LINK_LIBRARIES", cmStrCat("$:", targetName, diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build-stderr.txt new file mode 100644 index 0000000..3589448 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build-stderr.txt @@ -0,0 +1,8 @@ +CMake Warning \(dev\) at .*/Modules/Compiler/CMakeCommonCompilerMacros.cmake:[0-9]* \(cmake_language\): + CMake's support for `import std;` in C\+\+23 and newer is experimental. It + is meant only for experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + .*/Modules/CMakeDetermineCompilerSupport.cmake:[0-9]* \(cmake_create_cxx_import_std\) + .*/Modules/CMakeTestCXXCompiler.cmake:[0-9]* \(CMAKE_DETERMINE_COMPILER_SUPPORT\) + CMakeLists.txt:[0-9]* \(project\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/CMakeLists.txt index 0a4c41d..89350ef 100644 --- a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-build/CMakeLists.txt @@ -1,3 +1,6 @@ +set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") + cmake_minimum_required(VERSION 3.29) project(cxx_modules_import_std_export_no_std CXX) diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install-stderr.txt new file mode 100644 index 0000000..3589448 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install-stderr.txt @@ -0,0 +1,8 @@ +CMake Warning \(dev\) at .*/Modules/Compiler/CMakeCommonCompilerMacros.cmake:[0-9]* \(cmake_language\): + CMake's support for `import std;` in C\+\+23 and newer is experimental. It + is meant only for experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + .*/Modules/CMakeDetermineCompilerSupport.cmake:[0-9]* \(cmake_create_cxx_import_std\) + .*/Modules/CMakeTestCXXCompiler.cmake:[0-9]* \(CMAKE_DETERMINE_COMPILER_SUPPORT\) + CMakeLists.txt:[0-9]* \(project\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/CMakeLists.txt index 69edbb5..62d9d91 100644 --- a/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/import-std-export-no-std-install/CMakeLists.txt @@ -1,3 +1,6 @@ +set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") + cmake_minimum_required(VERSION 3.29) project(cxx_modules_import_std_export_no_std CXX) diff --git a/Tests/RunCMake/CXXModules/examples/import-std-no-std-property-stderr.txt b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property-stderr.txt new file mode 100644 index 0000000..3589448 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property-stderr.txt @@ -0,0 +1,8 @@ +CMake Warning \(dev\) at .*/Modules/Compiler/CMakeCommonCompilerMacros.cmake:[0-9]* \(cmake_language\): + CMake's support for `import std;` in C\+\+23 and newer is experimental. It + is meant only for experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + .*/Modules/CMakeDetermineCompilerSupport.cmake:[0-9]* \(cmake_create_cxx_import_std\) + .*/Modules/CMakeTestCXXCompiler.cmake:[0-9]* \(CMAKE_DETERMINE_COMPILER_SUPPORT\) + CMakeLists.txt:[0-9]* \(project\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/import-std-no-std-property/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property/CMakeLists.txt index 4ec4e36..a605e95 100644 --- a/Tests/RunCMake/CXXModules/examples/import-std-no-std-property/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/import-std-no-std-property/CMakeLists.txt @@ -1,3 +1,6 @@ +set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") + cmake_minimum_required(VERSION 3.29) project(cxx_modules_import_std_no_std_property CXX) diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build-stderr.txt new file mode 100644 index 0000000..3589448 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build-stderr.txt @@ -0,0 +1,8 @@ +CMake Warning \(dev\) at .*/Modules/Compiler/CMakeCommonCompilerMacros.cmake:[0-9]* \(cmake_language\): + CMake's support for `import std;` in C\+\+23 and newer is experimental. It + is meant only for experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + .*/Modules/CMakeDetermineCompilerSupport.cmake:[0-9]* \(cmake_create_cxx_import_std\) + .*/Modules/CMakeTestCXXCompiler.cmake:[0-9]* \(CMAKE_DETERMINE_COMPILER_SUPPORT\) + CMakeLists.txt:[0-9]* \(project\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/CMakeLists.txt index b7ab279..3112002 100644 --- a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-build/CMakeLists.txt @@ -1,3 +1,6 @@ +set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") + cmake_minimum_required(VERSION 3.29) project(cxx_modules_import_std_not_in_export CXX) diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install-stderr.txt new file mode 100644 index 0000000..3589448 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install-stderr.txt @@ -0,0 +1,8 @@ +CMake Warning \(dev\) at .*/Modules/Compiler/CMakeCommonCompilerMacros.cmake:[0-9]* \(cmake_language\): + CMake's support for `import std;` in C\+\+23 and newer is experimental. It + is meant only for experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + .*/Modules/CMakeDetermineCompilerSupport.cmake:[0-9]* \(cmake_create_cxx_import_std\) + .*/Modules/CMakeTestCXXCompiler.cmake:[0-9]* \(CMAKE_DETERMINE_COMPILER_SUPPORT\) + CMakeLists.txt:[0-9]* \(project\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/CMakeLists.txt index 8b9295d..788ea84 100644 --- a/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/import-std-not-in-export-install/CMakeLists.txt @@ -1,3 +1,6 @@ +set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") + cmake_minimum_required(VERSION 3.29) project(cxx_modules_import_std_not_in_export CXX) diff --git a/Tests/RunCMake/CXXModules/examples/import-std-stderr.txt b/Tests/RunCMake/CXXModules/examples/import-std-stderr.txt new file mode 100644 index 0000000..3589448 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-stderr.txt @@ -0,0 +1,8 @@ +CMake Warning \(dev\) at .*/Modules/Compiler/CMakeCommonCompilerMacros.cmake:[0-9]* \(cmake_language\): + CMake's support for `import std;` in C\+\+23 and newer is experimental. It + is meant only for experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + .*/Modules/CMakeDetermineCompilerSupport.cmake:[0-9]* \(cmake_create_cxx_import_std\) + .*/Modules/CMakeTestCXXCompiler.cmake:[0-9]* \(CMAKE_DETERMINE_COMPILER_SUPPORT\) + CMakeLists.txt:[0-9]* \(project\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/import-std-transitive-not-in-export-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/import-std-transitive-not-in-export-build-stderr.txt new file mode 100644 index 0000000..3589448 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-transitive-not-in-export-build-stderr.txt @@ -0,0 +1,8 @@ +CMake Warning \(dev\) at .*/Modules/Compiler/CMakeCommonCompilerMacros.cmake:[0-9]* \(cmake_language\): + CMake's support for `import std;` in C\+\+23 and newer is experimental. It + is meant only for experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + .*/Modules/CMakeDetermineCompilerSupport.cmake:[0-9]* \(cmake_create_cxx_import_std\) + .*/Modules/CMakeTestCXXCompiler.cmake:[0-9]* \(CMAKE_DETERMINE_COMPILER_SUPPORT\) + CMakeLists.txt:[0-9]* \(project\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/import-std-transitive-not-in-export-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/import-std-transitive-not-in-export-install-stderr.txt new file mode 100644 index 0000000..3589448 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/import-std-transitive-not-in-export-install-stderr.txt @@ -0,0 +1,8 @@ +CMake Warning \(dev\) at .*/Modules/Compiler/CMakeCommonCompilerMacros.cmake:[0-9]* \(cmake_language\): + CMake's support for `import std;` in C\+\+23 and newer is experimental. It + is meant only for experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + .*/Modules/CMakeDetermineCompilerSupport.cmake:[0-9]* \(cmake_create_cxx_import_std\) + .*/Modules/CMakeTestCXXCompiler.cmake:[0-9]* \(CMAKE_DETERMINE_COMPILER_SUPPORT\) + CMakeLists.txt:[0-9]* \(project\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/import-std-transitive/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std-transitive/CMakeLists.txt index 526298c..2894d67 100644 --- a/Tests/RunCMake/CXXModules/examples/import-std-transitive/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/import-std-transitive/CMakeLists.txt @@ -1,3 +1,6 @@ +set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") + cmake_minimum_required(VERSION 3.29) if (EXPORT_NO_STD) diff --git a/Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt index 4e894c7..bffcd66 100644 --- a/Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt +++ b/Tests/RunCMake/CXXModules/examples/import-std/CMakeLists.txt @@ -1,3 +1,6 @@ +set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") + cmake_minimum_required(VERSION 3.29) project(cxx_modules_import_std CXX) diff --git a/Tests/RunCMake/cmake_language/Experimental/CxxImportStd-set-stderr.txt b/Tests/RunCMake/cmake_language/Experimental/CxxImportStd-set-stderr.txt new file mode 100644 index 0000000..bddd3ab --- /dev/null +++ b/Tests/RunCMake/cmake_language/Experimental/CxxImportStd-set-stderr.txt @@ -0,0 +1,6 @@ +CMake Warning \(dev\) at Experimental/CxxImportStd-set.cmake:4 \(cmake_language\): + CMake's support for `import std;` in C\+\+23 and newer 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. diff --git a/Tests/RunCMake/cmake_language/Experimental/CxxImportStd-set.cmake b/Tests/RunCMake/cmake_language/Experimental/CxxImportStd-set.cmake new file mode 100644 index 0000000..a002297 --- /dev/null +++ b/Tests/RunCMake/cmake_language/Experimental/CxxImportStd-set.cmake @@ -0,0 +1,11 @@ +set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD + "0e5b6991-d74f-4b3d-a41c-cf096e0b2508") + +cmake_language(GET_EXPERIMENTAL_FEATURE_ENABLED + "CxxImportStd" + feature_present) + +if (NOT feature_present STREQUAL "TRUE") + message(FATAL_ERROR + "Expected the `CxxImportStd` feature to be enabled.") +endif () diff --git a/Tests/RunCMake/cmake_language/Experimental/CxxImportStd-unset.cmake b/Tests/RunCMake/cmake_language/Experimental/CxxImportStd-unset.cmake new file mode 100644 index 0000000..be758c2 --- /dev/null +++ b/Tests/RunCMake/cmake_language/Experimental/CxxImportStd-unset.cmake @@ -0,0 +1,8 @@ +cmake_language(GET_EXPERIMENTAL_FEATURE_ENABLED + "CxxImportStd" + feature_present) + +if (NOT feature_present STREQUAL "FALSE") + message(FATAL_ERROR + "Expected the `CxxImportStd` feature to be disabled.") +endif () diff --git a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake index 7c47b06..fe3da79 100644 --- a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake @@ -157,6 +157,8 @@ run_cmake_command( -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake ) +run_cmake(Experimental/CxxImportStd-set) +run_cmake(Experimental/CxxImportStd-unset) run_cmake(Experimental/ExportPackageDependencies-set) run_cmake(Experimental/ExportPackageDependencies-unset) run_cmake(Experimental/WindowsKernelModeDriver-set) -- cgit v0.12 From ffe74289b3f93219f12e5c3567640eb6f0403cd9 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 1 Mar 2024 08:01:28 -0500 Subject: CMakeDetermineCompilerId: extract C++ standard library impl This is needed for C++ modules because `import std` support may differ based on the standard library implementation. Extract the information as necessary. --- Modules/CMakeDetermineCompilerId.cmake | 24 ++++++++++++++++++++++++ Modules/CXX-DetectStdlib.h | 10 ++++++++++ 2 files changed, 34 insertions(+) create mode 100644 Modules/CXX-DetectStdlib.h diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index e75018b..7fcfbdc 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -312,6 +312,29 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) endif () endif () + set(CMAKE_${lang}_STANDARD_LIBRARY "") + if ("x${lang}" STREQUAL "xCXX" AND + EXISTS "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${lang}-DetectStdlib.h" AND + "x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xClang" AND + "x${CMAKE_${lang}_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") + # See #20851 for a proper abstraction for this. + execute_process( + COMMAND "${CMAKE_${lang}_COMPILER}" + ${CMAKE_${lang}_COMPILER_ID_ARG1} + ${CMAKE_CXX_COMPILER_ID_FLAGS_LIST} + -E + -x c++-header + "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${lang}-DetectStdlib.h" + -o - # Write to stdout. + OUTPUT_VARIABLE _lang_stdlib_out + ERROR_VARIABLE _lang_stdlib_err + RESULT_VARIABLE _lang_stdlib_res + ERROR_STRIP_TRAILING_WHITESPACE) + if (_lang_stdlib_res EQUAL 0) + string(REGEX REPLACE ".*CMAKE-STDLIB-DETECT: (.+)\n.*" "\\1" "CMAKE_${lang}_STANDARD_LIBRARY" "${_lang_stdlib_out}") + endif () + endif () + # Display the final identification result. if(CMAKE_${lang}_COMPILER_ID) if(CMAKE_${lang}_COMPILER_VERSION) @@ -355,6 +378,7 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src) set(CMAKE_${lang}_COMPILER_PRODUCED_OUTPUT "${COMPILER_${lang}_PRODUCED_OUTPUT}" PARENT_SCOPE) set(CMAKE_${lang}_COMPILER_PRODUCED_FILES "${COMPILER_${lang}_PRODUCED_FILES}" PARENT_SCOPE) set(CMAKE_${lang}_COMPILER_CLANG_RESOURCE_DIR "${CMAKE_${lang}_COMPILER_CLANG_RESOURCE_DIR}" PARENT_SCOPE) + set(CMAKE_${lang}_STANDARD_LIBRARY "${CMAKE_${lang}_STANDARD_LIBRARY}" PARENT_SCOPE) endfunction() include(CMakeCompilerIdDetection) diff --git a/Modules/CXX-DetectStdlib.h b/Modules/CXX-DetectStdlib.h new file mode 100644 index 0000000..0214dee --- /dev/null +++ b/Modules/CXX-DetectStdlib.h @@ -0,0 +1,10 @@ +#include +// clang-format off +#if defined(_LIBCPP_VERSION) +CMAKE-STDLIB-DETECT: libc++ +#elif defined(__GLIBCXX__) +CMAKE-STDLIB-DETECT: libstdc++ +#else +CMAKE-STDLIB-DETECT: UNKNOWN +#endif + // clang-format on -- cgit v0.12 From 442086c1dc49e8537beb360f82ea0864c5b124e0 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 8 Apr 2024 18:00:28 -0400 Subject: fileapi: ignore `__cmake_`-prefixed targets These targets are internal to CMake's C++ `import std` implementation and should not appear. --- Source/cmFileAPICodemodel.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index e9302da..869b94a 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -685,6 +685,11 @@ Json::Value CodemodelConfig::DumpTargets() continue; } + // Ignore targets starting with `__cmake_` as they are internal. + if (cmHasLiteralPrefix(gt->GetName(), "__cmake_")) { + continue; + } + targets.append(this->DumpTarget(gt, targets.size())); } -- cgit v0.12 From 62a71047bb0fb0f99c86d7312da83ec5bd0a322c Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 8 Apr 2024 18:03:00 -0400 Subject: cmGraphVizWriter: ignore `__cmake_`-prefixed targets These targets are internal to CMake's C++ `import std` implementation and should not appear. --- Source/cmGraphVizWriter.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index a8a7abb..6c3afef 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -284,7 +284,8 @@ void cmGraphVizWriter::Write() // Reserved targets have inconsistent names across platforms (e.g. 'all' // vs. 'ALL_BUILD'), which can disrupt the traversal ordering. // We don't need or want them anyway. - if (!cmGlobalGenerator::IsReservedTarget(gt->GetName())) { + if (!cmGlobalGenerator::IsReservedTarget(gt->GetName()) && + !cmHasLiteralPrefix(gt->GetName(), "__cmake_")) { sortedGeneratorTargets.insert(gt.get()); } } -- cgit v0.12 From 4617f272b47e5d2910647d2f6054d574abbb3d2a Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 26 Feb 2024 09:45:47 -0500 Subject: MSVC: support `import std` --- Help/manual/cmake-cxxmodules.7.rst | 3 + Modules/Compiler/MSVC-CXX-CXXImportStd.cmake | 102 +++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 Modules/Compiler/MSVC-CXX-CXXImportStd.cmake diff --git a/Help/manual/cmake-cxxmodules.7.rst b/Help/manual/cmake-cxxmodules.7.rst index 12ea0a0..9ffb529 100644 --- a/Help/manual/cmake-cxxmodules.7.rst +++ b/Help/manual/cmake-cxxmodules.7.rst @@ -92,6 +92,9 @@ Compilers which CMake natively supports module dependency scanning include: Support for ``import std`` is limited to the following toolchain and standard library combinations: +* MSVC toolset 14.36 and newer (provided with Visual Studio 17.6 Preview 2 and + newer) + .. note :: This support is provided only when experimental support for diff --git a/Modules/Compiler/MSVC-CXX-CXXImportStd.cmake b/Modules/Compiler/MSVC-CXX-CXXImportStd.cmake new file mode 100644 index 0000000..9966b9b --- /dev/null +++ b/Modules/Compiler/MSVC-CXX-CXXImportStd.cmake @@ -0,0 +1,102 @@ +function (_cmake_cxx_import_std std variable) + find_file(_msvc_modules_json_file + NAME modules.json + HINTS + "$ENV{VCToolsInstallDir}/modules" + PATHS + "$ENV{INCLUDE}" + "${CMAKE_CXX_COMPILER}/../../.." + PATH_SUFFIXES + ../modules + NO_CACHE) + # Without this file, we do not have modules installed. + if (NOT EXISTS "${_msvc_modules_json_file}") + return () + endif () + + file(READ "${_msvc_modules_json_file}" _msvc_modules_json) + string(JSON _msvc_json_version GET "${_msvc_modules_json}" "version") + string(JSON _msvc_json_revision GET "${_msvc_modules_json}" "revision") + # Require version 1. + if (NOT _msvc_json_version EQUAL "1") + return () + endif () + + string(JSON _msvc_json_library GET "${_msvc_modules_json}" "library") + # Bail if we don't understand the library. + if (NOT _msvc_json_library STREQUAL "microsoft/STL") + return () + endif () + + string(JSON _msvc_json_nmodules LENGTH "${_msvc_modules_json}" "module-sources") + # Don't declare the target without any modules. + if (NOT _msvc_json_nmodules) + return () + endif () + + # Declare the target. + set(_msvc_std_target "") + string(APPEND _msvc_std_target + "add_library(__cmake_cxx${std} STATIC)\n") + string(APPEND _msvc_std_target + "target_sources(__cmake_cxx${std} INTERFACE \"$<$,STATIC_LIBRARY>:$>\")\n") + string(APPEND _msvc_std_target + "set_property(TARGET __cmake_cxx${std} PROPERTY EXCLUDE_FROM_ALL 1)\n") + string(APPEND _msvc_std_target + "set_property(TARGET __cmake_cxx${std} PROPERTY CXX_SCAN_FOR_MODULES 1)\n") + string(APPEND _msvc_std_target + "set_property(TARGET __cmake_cxx${std} PROPERTY CXX_MODULE_STD 0)\n") + string(APPEND _msvc_std_target + "target_compile_features(__cmake_cxx${std} PUBLIC cxx_std_${std})\n") + + set(_msvc_modules_module_paths "") + get_filename_component(_msvc_modules_dir "${_msvc_modules_json_file}" DIRECTORY) + + # Add module sources. + math(EXPR _msvc_modules_json_nmodules_range "${_msvc_json_nmodules} - 1") + foreach (_msvc_modules_json_modules_idx RANGE 0 "${_msvc_modules_json_nmodules_range}") + string(JSON _msvc_modules_json_module_source GET "${_msvc_modules_json}" "module-sources" "${_msvc_modules_json_modules_idx}") + + if (NOT IS_ABSOLUTE "${_msvc_modules_json_module_source}") + string(PREPEND _msvc_modules_json_module_source "${_msvc_modules_dir}/") + endif () + list(APPEND _msvc_modules_module_paths + "${_msvc_modules_json_module_source}") + endforeach () + + # Split the paths into basedirs and module paths. + set(_msvc_modules_base_dirs_list "") + set(_msvc_modules_files "") + foreach (_msvc_modules_module_path IN LISTS _msvc_modules_module_paths) + get_filename_component(_msvc_module_dir "${_msvc_modules_module_path}" DIRECTORY) + + list(APPEND _msvc_modules_base_dirs_list + "${_msvc_module_dir}") + string(APPEND _msvc_modules_files + " \"${_msvc_modules_module_path}\"") + endforeach () + list(REMOVE_DUPLICATES _msvc_modules_base_dirs_list) + set(_msvc_modules_base_dirs "") + foreach (_msvc_modules_base_dir IN LISTS _msvc_modules_base_dirs_list) + string(APPEND _msvc_modules_base_dirs + " \"${_msvc_modules_base_dir}\"") + endforeach () + + # Create the file set for the modules. + string(APPEND _msvc_std_target + "target_sources(__cmake_cxx${std} + PUBLIC + FILE_SET std TYPE CXX_MODULES + BASE_DIRS ${_msvc_modules_base_dirs} + FILES ${_msvc_modules_files})\n") + + # Wrap the `__cmake_cxx${std}` target in a check. + string(PREPEND _msvc_std_target + "if (NOT TARGET \"__cmake_cxx${std}\")\n") + string(APPEND _msvc_std_target + "endif ()\n") + string(APPEND _msvc_std_target + "add_library(__CMAKE::CXX${std} ALIAS __cmake_cxx${std})\n") + + set("${variable}" "${_msvc_std_target}" PARENT_SCOPE) +endfunction () -- cgit v0.12 From 429902ebad620c877b869068583d2a32bb6197b4 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Sat, 24 Feb 2024 17:23:50 -0500 Subject: Clang: support creating a target for imported modules --- Help/manual/cmake-cxxmodules.7.rst | 1 + Modules/Compiler/Clang-CXX-CXXImportStd.cmake | 153 ++++++++++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 Modules/Compiler/Clang-CXX-CXXImportStd.cmake diff --git a/Help/manual/cmake-cxxmodules.7.rst b/Help/manual/cmake-cxxmodules.7.rst index 9ffb529..8f4ff44 100644 --- a/Help/manual/cmake-cxxmodules.7.rst +++ b/Help/manual/cmake-cxxmodules.7.rst @@ -92,6 +92,7 @@ Compilers which CMake natively supports module dependency scanning include: Support for ``import std`` is limited to the following toolchain and standard library combinations: +* Clang 18.1.2 and newer with ``-stdlib=libc++`` * MSVC toolset 14.36 and newer (provided with Visual Studio 17.6 Preview 2 and newer) diff --git a/Modules/Compiler/Clang-CXX-CXXImportStd.cmake b/Modules/Compiler/Clang-CXX-CXXImportStd.cmake new file mode 100644 index 0000000..3934db9 --- /dev/null +++ b/Modules/Compiler/Clang-CXX-CXXImportStd.cmake @@ -0,0 +1,153 @@ +function (_cmake_cxx_import_std std variable) + if (NOT CMAKE_CXX_STANDARD_LIBRARY STREQUAL "libc++") + return () + endif () + + execute_process( + COMMAND + "${CMAKE_CXX_COMPILER}" + ${CMAKE_CXX_COMPILER_ID_ARG1} + -print-file-name=libc++.modules.json + OUTPUT_VARIABLE _clang_libcxx_modules_json_file + ERROR_VARIABLE _clang_libcxx_modules_json_file_err + RESULT_VARIABLE _clang_libcxx_modules_json_file_res + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE) + if (_clang_libcxx_modules_json_file_res) + return () + endif () + + # Without this file, we do not have modules installed. + if (NOT EXISTS "${_clang_libcxx_modules_json_file}") + return () + endif () + + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "18.1.2") + # The original PR had a key spelling mismatch internally. Do not support it + # and instead require a release known to have the fix. + # https://github.com/llvm/llvm-project/pull/83036 + return () + endif () + + file(READ "${_clang_libcxx_modules_json_file}" _clang_libcxx_modules_json) + string(JSON _clang_modules_json_version GET "${_clang_libcxx_modules_json}" "version") + string(JSON _clang_modules_json_revision GET "${_clang_libcxx_modules_json}" "revision") + # Require version 1. + if (NOT _clang_modules_json_version EQUAL "1") + return () + endif () + + string(JSON _clang_modules_json_nmodules LENGTH "${_clang_libcxx_modules_json}" "modules") + # Don't declare the target without any modules. + if (NOT _clang_modules_json_nmodules) + return () + endif () + + # Declare the target. + set(_clang_libcxx_target "") + # Clang 18 does not provide the module initializer for the `std` modules. + # Create a static library to hold these. Hope that Clang 19 can provide this, + # but never run the code. + string(APPEND _clang_libcxx_target + "add_library(__cmake_cxx${std} STATIC)\n") + string(APPEND _clang_libcxx_target + "target_sources(__cmake_cxx${std} INTERFACE \"$<$,STATIC_LIBRARY>:$>\")\n") + string(APPEND _clang_libcxx_target + "set_property(TARGET __cmake_cxx${std} PROPERTY EXCLUDE_FROM_ALL 1)\n") + string(APPEND _clang_libcxx_target + "set_property(TARGET __cmake_cxx${std} PROPERTY CXX_SCAN_FOR_MODULES 1)\n") + string(APPEND _clang_libcxx_target + "set_property(TARGET __cmake_cxx${std} PROPERTY CXX_MODULE_STD 0)\n") + string(APPEND _clang_libcxx_target + "target_compile_features(__cmake_cxx${std} PUBLIC cxx_std_${std})\n") + + set(_clang_modules_is_stdlib 0) + set(_clang_modules_include_dirs_list "") + set(_clang_modules_module_paths "") + get_filename_component(_clang_modules_dir "${_clang_libcxx_modules_json_file}" DIRECTORY) + + # Add module sources. + math(EXPR _clang_modules_json_nmodules_range "${_clang_modules_json_nmodules} - 1") + foreach (_clang_modules_json_modules_idx RANGE 0 "${_clang_modules_json_nmodules_range}") + string(JSON _clang_modules_json_module GET "${_clang_libcxx_modules_json}" "modules" "${_clang_modules_json_modules_idx}") + + string(JSON _clang_modules_json_module_source GET "${_clang_modules_json_module}" "source-path") + string(JSON _clang_modules_json_module_is_stdlib GET "${_clang_modules_json_module}" "is-std-library") + string(JSON _clang_modules_json_module_local_arguments GET "${_clang_modules_json_module}" "local-arguments") + string(JSON _clang_modules_json_module_nsystem_include_directories LENGTH "${_clang_modules_json_module_local_arguments}" "system-include-directories") + + if (NOT IS_ABSOLUTE "${_clang_modules_json_module_source}") + string(PREPEND _clang_modules_json_module_source "${_clang_modules_dir}/") + endif () + list(APPEND _clang_modules_module_paths + "${_clang_modules_json_module_source}") + + if (_clang_modules_json_module_is_stdlib) + set(_clang_modules_is_stdlib 1) + endif () + + math(EXPR _clang_modules_json_module_nsystem_include_directories_range "${_clang_modules_json_module_nsystem_include_directories} - 1") + foreach (_clang_modules_json_modules_system_include_directories_idx RANGE 0 "${_clang_modules_json_module_nsystem_include_directories_range}") + string(JSON _clang_modules_json_module_system_include_directory GET "${_clang_modules_json_module_local_arguments}" "system-include-directories" "${_clang_modules_json_modules_system_include_directories_idx}") + + if (NOT IS_ABSOLUTE "${_clang_modules_json_module_system_include_directory}") + string(PREPEND _clang_modules_json_module_system_include_directory "${_clang_modules_dir}/") + endif () + list(APPEND _clang_modules_include_dirs_list + "${_clang_modules_json_module_system_include_directory}") + endforeach () + endforeach () + + # Split the paths into basedirs and module paths. + set(_clang_modules_base_dirs_list "") + set(_clang_modules_files "") + foreach (_clang_modules_module_path IN LISTS _clang_modules_module_paths) + get_filename_component(_clang_module_dir "${_clang_modules_module_path}" DIRECTORY) + + list(APPEND _clang_modules_base_dirs_list + "${_clang_module_dir}") + string(APPEND _clang_modules_files + " \"${_clang_modules_module_path}\"") + endforeach () + list(REMOVE_DUPLICATES _clang_modules_base_dirs_list) + set(_clang_modules_base_dirs "") + foreach (_clang_modules_base_dir IN LISTS _clang_modules_base_dirs_list) + string(APPEND _clang_modules_base_dirs + " \"${_clang_modules_base_dir}\"") + endforeach () + + # If we have a standard library module, suppress warnings about reserved + # module names. + if (_clang_modules_is_stdlib) + string(APPEND _clang_libcxx_target + "target_compile_options(__cmake_cxx${std} PRIVATE -Wno-reserved-module-identifier)\n") + endif () + + # Set up include directories. + list(REMOVE_DUPLICATES _clang_modules_include_dirs_list) + set(_clang_modules_include_dirs "") + foreach (_clang_modules_include_dir IN LISTS _clang_modules_include_dirs_list) + string(APPEND _clang_modules_include_dirs + " \"${_clang_modules_include_dir}\"") + endforeach () + string(APPEND _clang_libcxx_target + "target_include_directories(__cmake_cxx${std} PRIVATE ${_clang_modules_include_dirs})\n") + + # Create the file set for the modules. + string(APPEND _clang_libcxx_target + "target_sources(__cmake_cxx${std} + PUBLIC + FILE_SET std TYPE CXX_MODULES + BASE_DIRS ${_clang_modules_base_dirs} + FILES ${_clang_modules_files})\n") + + # Wrap the `__cmake_cxx${std}` target in a check. + string(PREPEND _clang_libcxx_target + "if (NOT TARGET \"__cmake_cxx${std}\")\n") + string(APPEND _clang_libcxx_target + "endif ()\n") + string(APPEND _clang_libcxx_target + "add_library(__CMAKE::CXX${std} ALIAS __cmake_cxx${std})\n") + + set("${variable}" "${_clang_libcxx_target}" PARENT_SCOPE) +endfunction () -- cgit v0.12