From 3526b8c1232db2720c5d782ffde8acdc5cb2c191 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Fri, 22 Apr 2022 18:20:30 -0400 Subject: cmExport*FileGenerator: support exporting C++ module properties C++ module properties will be generated at build time, so generate code that includes the files actually responsible for the information. --- Source/cmExportBuildFileGenerator.cxx | 66 +++++++++++++++++++ Source/cmExportBuildFileGenerator.h | 4 ++ Source/cmExportFileGenerator.cxx | 25 ++++++++ Source/cmExportFileGenerator.h | 5 ++ Source/cmExportInstallFileGenerator.cxx | 74 +++++++++++++++++++++- Source/cmExportInstallFileGenerator.h | 25 ++++++++ Source/cmExportTryCompileFileGenerator.h | 3 + Source/cmInstallExportGenerator.cxx | 69 ++++++++++++++++++++ .../CXXModules/ExportBuildCxxModules-check.cmake | 40 ++++++++++++ .../CXXModules/ExportBuildCxxModules-stderr.txt | 11 ++++ .../CXXModules/ExportBuildCxxModules.cmake | 22 +++++++ .../CXXModules/ExportInstallCxxModules-check.cmake | 35 ++++++++++ .../CXXModules/ExportInstallCxxModules-stderr.txt | 11 ++++ .../CXXModules/ExportInstallCxxModules.cmake | 22 +++++++ Tests/RunCMake/CXXModules/RunCMakeTest.cmake | 3 + 15 files changed, 414 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake create mode 100644 Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake create mode 100644 Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake create mode 100644 Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt create mode 100644 Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index af33ada..ed199ea 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -15,6 +15,7 @@ #include "cmExportSet.h" #include "cmFileSet.h" +#include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -25,6 +26,7 @@ #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" +#include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" #include "cmValue.h" @@ -141,11 +143,18 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateTargetFileSets(gte, os); } + this->GenerateCxxModuleInformation(os); + // Generate import file content for each configuration. for (std::string const& c : this->Configurations) { this->GenerateImportConfig(os, c); } + // Generate import file content for each configuration. + for (std::string const& c : this->Configurations) { + this->GenerateImportCxxModuleConfigTargetInclusion(c); + } + this->GenerateMissingTargetsCheckCode(os); return true; @@ -479,3 +488,60 @@ std::string cmExportBuildFileGenerator::GetFileSetFiles(cmGeneratorTarget* gte, return cmJoin(resultVector, " "); } + +std::string cmExportBuildFileGenerator::GetCxxModulesDirectory() const +{ + return this->CxxModulesDirectory; +} + +void cmExportBuildFileGenerator::GenerateCxxModuleConfigInformation( + std::ostream& os) const +{ + const char* opt = ""; + if (this->Configurations.size() > 1) { + // With more than one configuration, each individual file is optional. + opt = " OPTIONAL"; + } + + // Generate import file content for each configuration. + for (std::string c : this->Configurations) { + if (c.empty()) { + c = "noconfig"; + } + os << "include(\"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << c << ".cmake\"" + << opt << ")\n"; + } +} + +bool cmExportBuildFileGenerator::GenerateImportCxxModuleConfigTargetInclusion( + std::string config) const +{ + auto cxx_modules_dirname = this->GetCxxModulesDirectory(); + if (cxx_modules_dirname.empty()) { + return true; + } + + if (config.empty()) { + config = "noconfig"; + } + + std::string fileName = cmStrCat(this->FileDir, '/', cxx_modules_dirname, + "/cxx-modules-", config, ".cmake"); + + cmGeneratedFileStream os(fileName, true); + if (!os) { + std::string se = cmSystemTools::GetLastSystemError(); + std::ostringstream e; + e << "cannot write to file \"" << fileName << "\": " << se; + cmSystemTools::Error(e.str()); + return false; + } + os.SetCopyIfDifferent(true); + + for (auto const* tgt : this->ExportedTargets) { + os << "include(\"${CMAKE_CURRENT_LIST_DIR}/target-" << tgt->GetExportName() + << '-' << config << ".cmake\")\n"; + } + + return true; +} diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 5f72046..4636196 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -91,6 +91,10 @@ protected: std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te) override; + std::string GetCxxModulesDirectory() const override; + void GenerateCxxModuleConfigInformation(std::ostream&) const override; + bool GenerateImportCxxModuleConfigTargetInclusion(std::string) const; + std::pair, std::string> FindBuildExportInfo( cmGlobalGenerator* gg, const std::string& name); diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 9837269..23b5690 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -1305,3 +1305,28 @@ void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte, os << " )\nendif()\n\n"; } } + +void cmExportFileGenerator::GenerateCxxModuleInformation(std::ostream& os) +{ + auto const cxx_module_dirname = this->GetCxxModulesDirectory(); + if (cxx_module_dirname.empty()) { + return; + } + + // Write the include. + os << "# Include C++ module properties\n" + << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname + << "/cxx-modules.cmake\")\n\n"; + + // Get the path to the file we're going to write. + std::string path = this->MainImportFile; + path = cmSystemTools::GetFilenamePath(path); + auto trampoline_path = + cmStrCat(path, '/', cxx_module_dirname, "/cxx-modules.cmake"); + + // Include all configuration-specific include files. + cmGeneratedFileStream ap(trampoline_path, true); + ap.SetCopyIfDifferent(true); + + this->GenerateCxxModuleConfigInformation(ap); +} diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index d27a555..fdda878 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -182,6 +182,8 @@ protected: void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os, cmTargetExport* te = nullptr); + void GenerateCxxModuleInformation(std::ostream& os); + virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te) = 0; @@ -226,4 +228,7 @@ private: virtual std::string InstallNameDir(cmGeneratorTarget const* target, const std::string& config) = 0; + + virtual std::string GetCxxModulesDirectory() const = 0; + virtual void GenerateCxxModuleConfigInformation(std::ostream& os) const = 0; }; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 3a06769..7d8572d 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -166,10 +166,20 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->LoadConfigFiles(os); + bool result = true; + + this->GenerateCxxModuleInformation(os); + if (requiresConfigFiles) { + for (std::string const& c : this->Configurations) { + if (!this->GenerateImportCxxModuleConfigTargetInclusion(c)) { + result = false; + } + } + } + this->CleanupTemporaryVariables(os); this->GenerateImportedFileCheckLoop(os); - bool result = true; // Generate an import file for each configuration. // Don't do this if we only export INTERFACE_LIBRARY targets. if (requiresConfigFiles) { @@ -669,3 +679,65 @@ std::string cmExportInstallFileGenerator::GetFileSetFiles( return cmJoin(resultVector, " "); } + +std::string cmExportInstallFileGenerator::GetCxxModulesDirectory() const +{ + return IEGen->GetCxxModuleDirectory(); +} + +void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation( + std::ostream& os) const +{ + // Now load per-configuration properties for them. + /* clang-format off */ + os << "# Load information for each installed configuration.\n" + "file(GLOB _cmake_cxx_module_includes \"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-*.cmake\")\n" + "foreach(_cmake_cxx_module_include IN LISTS _cmake_cxx_module_includes)\n" + " include(\"${_cmake_cxx_module_include}\")\n" + "endforeach()\n" + "unset(_cmake_cxx_module_include)\n" + "unset(_cmake_cxx_module_includes)\n"; + /* clang-format on */ +} + +bool cmExportInstallFileGenerator:: + GenerateImportCxxModuleConfigTargetInclusion(std::string const& config) +{ + auto cxx_modules_dirname = this->GetCxxModulesDirectory(); + if (cxx_modules_dirname.empty()) { + return true; + } + + std::string filename_config = config; + if (filename_config.empty()) { + filename_config = "noconfig"; + } + + std::string const dest = + cmStrCat(this->FileDir, '/', cxx_modules_dirname, '/'); + std::string fileName = + cmStrCat(dest, "cxx-modules-", filename_config, ".cmake"); + + cmGeneratedFileStream os(fileName, true); + if (!os) { + std::string se = cmSystemTools::GetLastSystemError(); + std::ostringstream e; + e << "cannot write to file \"" << fileName << "\": " << se; + cmSystemTools::Error(e.str()); + return false; + } + os.SetCopyIfDifferent(true); + + // Record this per-config import file. + this->ConfigCxxModuleFiles[config] = fileName; + + auto& prop_files = this->ConfigCxxModuleTargetFiles[config]; + for (auto const* tgt : this->ExportedTargets) { + auto prop_filename = cmStrCat("target-", tgt->GetExportName(), '-', + filename_config, ".cmake"); + prop_files.emplace_back(cmStrCat(dest, prop_filename)); + os << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << prop_filename << "\")\n"; + } + + return true; +} diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 86fb505..e073a31 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -50,6 +50,23 @@ public: return this->ConfigImportFiles; } + /** Get the per-config C++ module file generated for each configuration. + This maps from the configuration name to the file temporary location + for installation. */ + std::map const& GetConfigCxxModuleFiles() + { + return this->ConfigCxxModuleFiles; + } + + /** Get the per-config C++ module file generated for each configuration. + This maps from the configuration name to the file temporary location + for installation for each target in the export set. */ + std::map> const& + GetConfigCxxModuleTargetFiles() + { + return this->ConfigCxxModuleTargetFiles; + } + /** Compute the globbing expression used to load per-config import files from the main file. */ std::string GetConfigImportFileGlob(); @@ -100,8 +117,16 @@ protected: std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te) override; + std::string GetCxxModulesDirectory() const override; + void GenerateCxxModuleConfigInformation(std::ostream&) const override; + bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&); + cmInstallExportGenerator* IEGen; // The import file generated for each configuration. std::map ConfigImportFiles; + // The C++ module property file generated for each configuration. + std::map ConfigCxxModuleFiles; + // The C++ module property target files generated for each configuration. + std::map> ConfigCxxModuleTargetFiles; }; diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index 1dd8a20..5c34fad 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -55,6 +55,9 @@ protected: std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet, cmTargetExport* te) override; + std::string GetCxxModulesDirectory() const override { return {}; } + void GenerateCxxModuleConfigInformation(std::ostream&) const override {} + private: std::string FindTargets(const std::string& prop, const cmGeneratorTarget* tgt, diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 433e0c5..1d81b0b 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -143,6 +143,75 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os, os << indent << "endif()\n"; files.clear(); } + + // Now create a configuration-specific install rule for the C++ module import + // property file of each configuration. + auto cxx_module_dest = + cmStrCat(this->Destination, '/', this->CxxModulesDirectory); + std::string config_file_example; + for (auto const& i : this->EFGen->GetConfigCxxModuleFiles()) { + config_file_example = i.second; + break; + } + if (!config_file_example.empty()) { + // Remove old per-configuration export files if the main changes. + std::string installedDir = cmStrCat( + "$ENV{DESTDIR}", ConvertToAbsoluteDestination(cxx_module_dest), '/'); + std::string installedFile = cmStrCat(installedDir, "/cxx-modules.cmake"); + std::string toInstallFile = + cmStrCat(cmSystemTools::GetFilenamePath(config_file_example), + "/cxx-modules.cmake"); + os << indent << "if(EXISTS \"" << installedFile << "\")\n"; + Indent indentN = indent.Next(); + Indent indentNN = indentN.Next(); + Indent indentNNN = indentNN.Next(); + /* clang-format off */ + os << indentN << "file(DIFFERENT _cmake_export_file_changed FILES\n" + << indentN << " \"" << installedFile << "\"\n" + << indentN << " \"" << toInstallFile << "\")\n"; + os << indentN << "if(_cmake_export_file_changed)\n"; + os << indentNN << "file(GLOB _cmake_old_config_files \"" << installedDir + << this->EFGen->GetConfigImportFileGlob() << "\")\n"; + os << indentNN << "if(_cmake_old_config_files)\n"; + os << indentNNN << "string(REPLACE \";\" \", \" _cmake_old_config_files_text \"${_cmake_old_config_files}\")\n"; + os << indentNNN << R"(message(STATUS "Old C++ module export file \")" << installedFile + << "\\\" will be replaced. Removing files [${_cmake_old_config_files_text}].\")\n"; + os << indentNNN << "unset(_cmake_old_config_files_text)\n"; + os << indentNNN << "file(REMOVE ${_cmake_old_config_files})\n"; + os << indentNN << "endif()\n"; + os << indentNN << "unset(_cmake_old_config_files)\n"; + os << indentN << "endif()\n"; + os << indentN << "unset(_cmake_export_file_changed)\n"; + os << indent << "endif()\n"; + /* clang-format on */ + + // All of these files are siblings; get its location to know where the + // "anchor" file is. + files.push_back(toInstallFile); + this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files, + false, this->FilePermissions.c_str(), nullptr, + nullptr, nullptr, indent); + files.clear(); + } + for (auto const& i : this->EFGen->GetConfigCxxModuleFiles()) { + files.push_back(i.second); + std::string config_test = this->CreateConfigTest(i.first); + os << indent << "if(" << config_test << ")\n"; + this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files, + false, this->FilePermissions.c_str(), nullptr, + nullptr, nullptr, indent.Next()); + os << indent << "endif()\n"; + files.clear(); + } + for (auto const& i : this->EFGen->GetConfigCxxModuleTargetFiles()) { + std::string config_test = this->CreateConfigTest(i.first); + os << indent << "if(" << config_test << ")\n"; + this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, i.second, + false, this->FilePermissions.c_str(), nullptr, + nullptr, nullptr, indent.Next()); + os << indent << "endif()\n"; + files.clear(); + } } void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os, diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake new file mode 100644 index 0000000..cb6f6bd --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake @@ -0,0 +1,40 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/export-modules-targets.cmake" export_script) + +if (NOT export_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules/cxx-modules\.cmake"\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module property script inclusion") +endif () + +file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules.cmake" trampoline_script) + +if (RunCMake_GENERATOR_IS_MULTI_CONFIG) + if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-[^.]*\.cmake" OPTIONAL\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module property per-config script inclusion(s)") + endif () +else () + if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-[^.]*\.cmake"\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module property per-config script inclusion(s)") + endif () +endif () + +set(any_exists 0) +foreach (config IN ITEMS noconfig Debug Release RelWithDebInfo MinSizeRel) + if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-${config}.cmake") + continue () + endif () + set(any_exists 1) + + file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-${config}.cmake" config_script) + + if (NOT config_script MATCHES "include\\(\"\\\${CMAKE_CURRENT_LIST_DIR}/target-export-name-${config}\\.cmake\"\\)") + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module per-target property script inclusion") + endif () +endforeach () + +if (NOT any_exists) + list(APPEND RunCMake_TEST_FAILED + "No per-configuration target files exist.") +endif () diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt new file mode 100644 index 0000000..c05b0b4 --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at ExportBuildCxxModules.cmake:6 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake b/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake new file mode 100644 index 0000000..850f8dc --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake @@ -0,0 +1,22 @@ +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +add_library(export-modules) +target_sources(export-modules + PUBLIC + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(export-modules + PRIVATE + cxx_std_20) +set_property(TARGET export-modules + PROPERTY EXPORT_NAME export-name) + +install(TARGETS export-modules + EXPORT exp + FILE_SET fs DESTINATION "include/cxx/export-modules") + +export(EXPORT exp + FILE "${CMAKE_BINARY_DIR}/lib/cmake/export-modules/export-modules-targets.cmake" + CXX_MODULES_DIRECTORY "cxx-modules") diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake new file mode 100644 index 0000000..9e83fd8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake @@ -0,0 +1,35 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/exp.cmake" export_script) + +if (NOT export_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules/cxx-modules\.cmake"\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module property script inclusion") +endif () + +file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules.cmake" trampoline_script) + +if (NOT trampoline_script MATCHES [[file\(GLOB _cmake_cxx_module_includes "\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-\*\.cmake"\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module property per-config script inclusion(s)") +endif () + +set(any_exists 0) +foreach (config IN ITEMS noconfig Debug Release RelWithDebInfo MinSizeRel) + if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-${config}.cmake") + continue () + endif () + set(any_exists 1) + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-${config}.cmake" config_script) + + if (NOT config_script MATCHES "include\\(\"\\\${CMAKE_CURRENT_LIST_DIR}/target-export-name-${config}\\.cmake\"\\)") + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module per-target property script inclusion") + endif () +endforeach () + +if (NOT any_exists) + list(APPEND RunCMake_TEST_FAILED + "No per-configuration target files exist.") +endif () + +string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}") diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt new file mode 100644 index 0000000..4fe27a9 --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at ExportInstallCxxModules.cmake:6 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake b/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake new file mode 100644 index 0000000..234a4b5 --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake @@ -0,0 +1,22 @@ +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +add_library(export-modules) +target_sources(export-modules + PUBLIC + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(export-modules + PRIVATE + cxx_std_20) +set_property(TARGET export-modules + PROPERTY EXPORT_NAME export-name) + +install(TARGETS export-modules + EXPORT exp + FILE_SET fs DESTINATION "include/cxx/export-modules") + +install(EXPORT exp + DESTINATION "lib/cmake/export-modules" + CXX_MODULES_DIRECTORY "cxx-modules") diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake index 7c93100..a4b67fd 100644 --- a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -71,6 +71,9 @@ run_cmake(InstallBMI) run_cmake(InstallBMIGenericArgs) run_cmake(InstallBMIIgnore) +run_cmake(ExportBuildCxxModules) +run_cmake(ExportInstallCxxModules) + # Actual compilation tests. if (NOT CMake_TEST_MODULE_COMPILATION) return () -- cgit v0.12