cxxmodules: make export trampoline script files unique

Include the name of the `EXPORT` in the filename when generating export
information for C++ modules. This allows the same directory to be used
for multiple sets of C++ module-using targets.

For `export(TARGETS)` uses, generate a name based on the hash of the
concatenation of the target names involved with the `export()` call.

Fixes: #25609
This commit is contained in:
Ben Boeckel
2024-01-18 13:19:17 -05:00
committed by Brad King
parent 2352dcc830
commit d791f3a180
13 changed files with 128 additions and 38 deletions

View File

@@ -3,6 +3,7 @@
#include "cmExportBuildFileGenerator.h"
#include <algorithm>
#include <cstddef>
#include <map>
#include <memory>
#include <set>
@@ -13,6 +14,7 @@
#include <cmext/algorithm>
#include <cmext/string_view>
#include "cmCryptoHash.h"
#include "cmExportSet.h"
#include "cmFileSet.h"
#include "cmGeneratedFileStream.h"
@@ -156,7 +158,19 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->GenerateTargetFileSets(gte, os);
}
this->GenerateCxxModuleInformation(os);
std::string cxx_modules_name;
if (this->ExportSet) {
cxx_modules_name = this->ExportSet->GetName();
} else {
cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_512);
constexpr std::size_t HASH_TRUNCATION = 12;
for (auto const& target : this->Targets) {
hasher.Append(target);
}
cxx_modules_name = hasher.FinalizeHex().substr(0, HASH_TRUNCATION);
}
this->GenerateCxxModuleInformation(cxx_modules_name, os);
// Generate import file content for each configuration.
for (std::string const& c : this->Configurations) {
@@ -165,7 +179,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
// Generate import file content for each configuration.
for (std::string const& c : this->Configurations) {
this->GenerateImportCxxModuleConfigTargetInclusion(c);
this->GenerateImportCxxModuleConfigTargetInclusion(cxx_modules_name, c);
}
this->GenerateMissingTargetsCheckCode(os);
@@ -506,7 +520,7 @@ std::string cmExportBuildFileGenerator::GetCxxModulesDirectory() const
}
void cmExportBuildFileGenerator::GenerateCxxModuleConfigInformation(
std::ostream& os) const
std::string const& name, std::ostream& os) const
{
const char* opt = "";
if (this->Configurations.size() > 1) {
@@ -519,13 +533,13 @@ void cmExportBuildFileGenerator::GenerateCxxModuleConfigInformation(
if (c.empty()) {
c = "noconfig";
}
os << "include(\"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << c << ".cmake\""
<< opt << ")\n";
os << "include(\"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << name << '-'
<< c << ".cmake\"" << opt << ")\n";
}
}
bool cmExportBuildFileGenerator::GenerateImportCxxModuleConfigTargetInclusion(
std::string config) const
std::string const& name, std::string config) const
{
auto cxx_modules_dirname = this->GetCxxModulesDirectory();
if (cxx_modules_dirname.empty()) {
@@ -536,8 +550,9 @@ bool cmExportBuildFileGenerator::GenerateImportCxxModuleConfigTargetInclusion(
config = "noconfig";
}
std::string fileName = cmStrCat(this->FileDir, '/', cxx_modules_dirname,
"/cxx-modules-", config, ".cmake");
std::string fileName =
cmStrCat(this->FileDir, '/', cxx_modules_dirname, "/cxx-modules-", name,
'-', config, ".cmake");
cmGeneratedFileStream os(fileName, true);
if (!os) {

View File

@@ -92,8 +92,10 @@ protected:
cmTargetExport* te) override;
std::string GetCxxModulesDirectory() const override;
void GenerateCxxModuleConfigInformation(std::ostream&) const override;
bool GenerateImportCxxModuleConfigTargetInclusion(std::string) const;
void GenerateCxxModuleConfigInformation(std::string const&,
std::ostream&) const override;
bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&,
std::string) const;
std::pair<std::vector<std::string>, std::string> FindBuildExportInfo(
cmGlobalGenerator* gg, const std::string& name);

View File

@@ -1461,7 +1461,8 @@ void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte,
}
}
void cmExportFileGenerator::GenerateCxxModuleInformation(std::ostream& os)
void cmExportFileGenerator::GenerateCxxModuleInformation(
std::string const& name, std::ostream& os)
{
auto const cxx_module_dirname = this->GetCxxModulesDirectory();
if (cxx_module_dirname.empty()) {
@@ -1471,17 +1472,17 @@ void cmExportFileGenerator::GenerateCxxModuleInformation(std::ostream& os)
// Write the include.
os << "# Include C++ module properties\n"
<< "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname
<< "/cxx-modules.cmake\")\n\n";
<< "/cxx-modules-" << name << ".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");
cmStrCat(path, '/', cxx_module_dirname, "/cxx-modules-", name, ".cmake");
// Include all configuration-specific include files.
cmGeneratedFileStream ap(trampoline_path, true);
ap.SetCopyIfDifferent(true);
this->GenerateCxxModuleConfigInformation(ap);
this->GenerateCxxModuleConfigInformation(name, ap);
}

View File

@@ -187,7 +187,7 @@ protected:
void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os,
cmTargetExport* te = nullptr);
void GenerateCxxModuleInformation(std::ostream& os);
void GenerateCxxModuleInformation(std::string const& name, std::ostream& os);
virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte,
cmFileSet* fileSet,
@@ -235,5 +235,6 @@ private:
const std::string& config) = 0;
virtual std::string GetCxxModulesDirectory() const = 0;
virtual void GenerateCxxModuleConfigInformation(std::ostream& os) const = 0;
virtual void GenerateCxxModuleConfigInformation(std::string const&,
std::ostream& os) const = 0;
};

View File

@@ -181,10 +181,12 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
bool result = true;
this->GenerateCxxModuleInformation(os);
std::string cxx_modules_name = this->IEGen->GetExportSet()->GetName();
this->GenerateCxxModuleInformation(cxx_modules_name, os);
if (requiresConfigFiles) {
for (std::string const& c : this->Configurations) {
if (!this->GenerateImportCxxModuleConfigTargetInclusion(c)) {
if (!this->GenerateImportCxxModuleConfigTargetInclusion(cxx_modules_name,
c)) {
result = false;
}
}
@@ -718,12 +720,12 @@ std::string cmExportInstallFileGenerator::GetCxxModulesDirectory() const
}
void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation(
std::ostream& os) const
std::string const& name, 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"
"file(GLOB _cmake_cxx_module_includes \"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << name << "-*.cmake\")\n"
"foreach(_cmake_cxx_module_include IN LISTS _cmake_cxx_module_includes)\n"
" include(\"${_cmake_cxx_module_include}\")\n"
"endforeach()\n"
@@ -733,7 +735,8 @@ void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation(
}
bool cmExportInstallFileGenerator::
GenerateImportCxxModuleConfigTargetInclusion(std::string const& config)
GenerateImportCxxModuleConfigTargetInclusion(std::string const& name,
std::string const& config)
{
auto cxx_modules_dirname = this->GetCxxModulesDirectory();
if (cxx_modules_dirname.empty()) {
@@ -748,7 +751,7 @@ bool cmExportInstallFileGenerator::
std::string const dest =
cmStrCat(this->FileDir, '/', cxx_modules_dirname, '/');
std::string fileName =
cmStrCat(dest, "cxx-modules-", filename_config, ".cmake");
cmStrCat(dest, "cxx-modules-", name, '-', filename_config, ".cmake");
cmGeneratedFileStream os(fileName, true);
if (!os) {

View File

@@ -118,8 +118,10 @@ protected:
cmTargetExport* te) override;
std::string GetCxxModulesDirectory() const override;
void GenerateCxxModuleConfigInformation(std::ostream&) const override;
bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&);
void GenerateCxxModuleConfigInformation(std::string const&,
std::ostream&) const override;
bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&,
std::string const&);
cmInstallExportGenerator* IEGen;

View File

@@ -56,7 +56,10 @@ protected:
cmTargetExport* te) override;
std::string GetCxxModulesDirectory() const override { return {}; }
void GenerateCxxModuleConfigInformation(std::ostream&) const override {}
void GenerateCxxModuleConfigInformation(std::string const&,
std::ostream&) const override
{
}
private:
std::string FindTargets(const std::string& prop,

View File

@@ -158,10 +158,11 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
// 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 installedFile = cmStrCat(installedDir, "/cxx-modules-",
this->ExportSet->GetName(), ".cmake");
std::string toInstallFile =
cmStrCat(cmSystemTools::GetFilenamePath(config_file_example),
"/cxx-modules.cmake");
"/cxx-modules-", this->ExportSet->GetName(), ".cmake");
os << indent << "if(EXISTS \"" << installedFile << "\")\n";
Indent indentN = indent.Next();
Indent indentNN = indentN.Next();

View File

@@ -1,19 +1,19 @@
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"\)]])
if (NOT export_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules/cxx-modules-exp\.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)
file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-exp.cmake" trampoline_script)
if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-[^.]*\.cmake" OPTIONAL\)]])
if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-exp-[^.]*\.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"\)]])
if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-exp-[^.]*\.cmake"\)]])
list(APPEND RunCMake_TEST_FAILED
"Could not find C++ module property per-config script inclusion(s)")
endif ()
@@ -21,12 +21,12 @@ 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")
if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-exp-${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)
file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-exp-${config}.cmake" config_script)
if (NOT config_script MATCHES "include\\(\"\\\${CMAKE_CURRENT_LIST_DIR}/target-export-name-${config}\\.cmake\"\\)")
list(APPEND RunCMake_TEST_FAILED

View File

@@ -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-7eb8e1b4d8a1\.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-7eb8e1b4d8a1.cmake" trampoline_script)
if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-7eb8e1b4d8a1-[^.]*\.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-7eb8e1b4d8a1-[^.]*\.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-7eb8e1b4d8a1-${config}.cmake")
continue ()
endif ()
set(any_exists 1)
file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-7eb8e1b4d8a1-${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 ()

View File

@@ -0,0 +1,21 @@
enable_language(CXX)
set(CMAKE_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(TARGETS export-modules
FILE "${CMAKE_BINARY_DIR}/lib/cmake/export-modules/export-modules-targets.cmake"
CXX_MODULES_DIRECTORY "cxx-modules")

View File

@@ -1,25 +1,25 @@
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"\)]])
if (NOT export_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules/cxx-modules-exp\.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)
file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-exp.cmake" trampoline_script)
if (NOT trampoline_script MATCHES [[file\(GLOB _cmake_cxx_module_includes "\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-\*\.cmake"\)]])
if (NOT trampoline_script MATCHES [[file\(GLOB _cmake_cxx_module_includes "\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-exp-\*\.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")
if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-exp-${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)
file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-exp-${config}.cmake" config_script)
if (NOT config_script MATCHES "include\\(\"\\\${CMAKE_CURRENT_LIST_DIR}/target-export-name-${config}\\.cmake\"\\)")
list(APPEND RunCMake_TEST_FAILED

View File

@@ -88,6 +88,7 @@ run_cmake(InstallBMIGenericArgs)
run_cmake(InstallBMIIgnore)
run_cmake(ExportBuildCxxModules)
run_cmake(ExportBuildCxxModulesTargets)
run_cmake(ExportInstallCxxModules)
# Generator-specific tests.