mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
c++modules: Restore use of local target for import std
Restore use of a project-local `STATIC` library to provide the stdlib's
module initialization symbols, as CMake 4.2's experimental support did.
In commit fa10dc6c22 (Experimental/CXXModules: Implement EcoStd Module
Metadata parser, 2025-10-21, v4.3.0-rc1~483^2) we switched to an
imported target to provide the BMI under the assumption that stdlib
implementations provide the symbols themselves, but they don't yet.
While refactoring the module metadata parser's properties logic, also
fix a relative path issue for local arguments.
Fixes: #27426, #27626, #27635
This commit is contained in:
committed by
Brad King
parent
367abd8da0
commit
df6b1f2997
+102
-45
@@ -436,101 +436,142 @@ cmCxxModuleMetadata::SaveResult cmCxxModuleMetadata::SaveToFile(
|
||||
return st;
|
||||
}
|
||||
|
||||
void cmCxxModuleMetadata::PopulateTarget(
|
||||
cmTarget& target, cmCxxModuleMetadata const& meta,
|
||||
std::vector<std::string> const& configs)
|
||||
namespace {
|
||||
|
||||
struct MetaDataProperties
|
||||
{
|
||||
std::set<cm::string_view> allIncludeDirectories;
|
||||
std::set<cm::string_view> allCompileOptions;
|
||||
std::set<cm::string_view> allCompileFeatures;
|
||||
std::set<std::string> allCompileDefinitions;
|
||||
std::set<std::string> baseDirs;
|
||||
std::string MetadataDir;
|
||||
std::set<cm::string_view> AllCompileFeatures;
|
||||
std::set<cm::string_view> AllCompileOptions;
|
||||
std::set<cm::string_view> AllIncludeDirectories;
|
||||
std::set<std::string> AllCompileDefinitions;
|
||||
std::set<std::string> BaseDirs;
|
||||
std::set<std::string> Sources;
|
||||
|
||||
std::string metadataDir =
|
||||
cmSystemTools::GetFilenamePath(meta.MetadataFilePath);
|
||||
std::string NormalizePath(std::string const& in) const
|
||||
{
|
||||
std::string out = in;
|
||||
if (!cmSystemTools::FileIsFullPath(in)) {
|
||||
out = cmStrCat(MetadataDir, '/', in);
|
||||
}
|
||||
return cmSystemTools::CollapseFullPath(out);
|
||||
}
|
||||
};
|
||||
|
||||
auto fileSet =
|
||||
target.GetOrCreateFileSet(std::string{ cm::FileSetMetadata::CXX_MODULES },
|
||||
std::string{ cm::FileSetMetadata::CXX_MODULES },
|
||||
cm::FileSetMetadata::Visibility::Interface);
|
||||
MetaDataProperties CollectMetaProperties(cmCxxModuleMetadata const& meta)
|
||||
{
|
||||
MetaDataProperties props;
|
||||
|
||||
props.MetadataDir = cmSystemTools::GetFilenamePath(meta.MetadataFilePath);
|
||||
|
||||
for (auto const& module : meta.Modules) {
|
||||
std::string sourcePath = module.SourcePath;
|
||||
if (!cmSystemTools::FileIsFullPath(sourcePath)) {
|
||||
sourcePath = cmStrCat(metadataDir, '/', sourcePath);
|
||||
}
|
||||
|
||||
sourcePath = cmSystemTools::ToNormalizedPathOnDisk(std::move(sourcePath));
|
||||
std::string sourcePath = props.NormalizePath(module.SourcePath);
|
||||
props.Sources.insert(sourcePath);
|
||||
|
||||
// Module metadata files can reference files in different roots,
|
||||
// just use the immediate parent directory as a base directory
|
||||
baseDirs.insert(cmSystemTools::GetFilenamePath(sourcePath));
|
||||
|
||||
fileSet.first->AddFileEntry(sourcePath);
|
||||
props.BaseDirs.insert(cmSystemTools::GetFilenamePath(sourcePath));
|
||||
|
||||
if (module.LocalArguments) {
|
||||
for (auto const& incDir : module.LocalArguments->IncludeDirectories) {
|
||||
allIncludeDirectories.emplace(incDir);
|
||||
props.AllIncludeDirectories.emplace(incDir);
|
||||
}
|
||||
for (auto const& sysIncDir :
|
||||
module.LocalArguments->SystemIncludeDirectories) {
|
||||
allIncludeDirectories.emplace(sysIncDir);
|
||||
props.AllIncludeDirectories.emplace(sysIncDir);
|
||||
}
|
||||
for (auto const& opt : module.LocalArguments->CompileOptions) {
|
||||
allCompileOptions.emplace(opt);
|
||||
props.AllCompileOptions.emplace(opt);
|
||||
}
|
||||
for (auto const& opt : module.LocalArguments->CompileFeatures) {
|
||||
allCompileFeatures.emplace(opt);
|
||||
props.AllCompileFeatures.emplace(opt);
|
||||
}
|
||||
|
||||
for (auto const& def : module.LocalArguments->Definitions) {
|
||||
if (!def.Undef) {
|
||||
if (def.Value) {
|
||||
allCompileDefinitions.emplace(
|
||||
props.AllCompileDefinitions.emplace(
|
||||
cmStrCat(def.Name, "="_s, *def.Value));
|
||||
} else {
|
||||
allCompileDefinitions.emplace(def.Name);
|
||||
props.AllCompileDefinitions.emplace(def.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto const& baseDir : baseDirs) {
|
||||
return props;
|
||||
}
|
||||
|
||||
void PopulateFileSet(cmTarget& target, MetaDataProperties const& props)
|
||||
{
|
||||
auto fileSet =
|
||||
target.GetOrCreateFileSet(std::string{ cm::FileSetMetadata::CXX_MODULES },
|
||||
std::string{ cm::FileSetMetadata::CXX_MODULES },
|
||||
cm::FileSetMetadata::Visibility::Public);
|
||||
|
||||
for (auto const& source : props.Sources) {
|
||||
fileSet.first->AddFileEntry(source);
|
||||
}
|
||||
|
||||
for (auto const& baseDir : props.BaseDirs) {
|
||||
fileSet.first->AddDirectoryEntry(baseDir);
|
||||
}
|
||||
}
|
||||
|
||||
if (!allIncludeDirectories.empty()) {
|
||||
void PopulateLocalTarget(cmTarget& target, MetaDataProperties const& props)
|
||||
{
|
||||
if (!props.AllIncludeDirectories.empty()) {
|
||||
target.AppendProperty("INCLUDE_DIRECTORIES",
|
||||
cmJoin(props.AllIncludeDirectories, ";"));
|
||||
}
|
||||
|
||||
if (!props.AllCompileDefinitions.empty()) {
|
||||
target.AppendProperty("COMPILE_DEFINITIONS",
|
||||
cmJoin(props.AllCompileDefinitions, ";"));
|
||||
}
|
||||
|
||||
if (!props.AllCompileOptions.empty()) {
|
||||
target.AppendProperty("COMPILE_OPTIONS",
|
||||
cmJoin(props.AllCompileOptions, ";"));
|
||||
}
|
||||
|
||||
if (!props.AllCompileFeatures.empty()) {
|
||||
target.AppendProperty("COMPILE_FEATURES",
|
||||
cmJoin(props.AllCompileFeatures, ";"));
|
||||
}
|
||||
}
|
||||
|
||||
void PopulateImportedTarget(cmTarget& target, MetaDataProperties const& props,
|
||||
cmCxxModuleMetadata const& meta,
|
||||
std::vector<std::string> const& configs)
|
||||
{
|
||||
if (!props.AllIncludeDirectories.empty()) {
|
||||
target.SetProperty("IMPORTED_CXX_MODULES_INCLUDE_DIRECTORIES",
|
||||
cmJoin(allIncludeDirectories, ";"));
|
||||
cmJoin(props.AllIncludeDirectories, ";"));
|
||||
}
|
||||
|
||||
if (!allCompileDefinitions.empty()) {
|
||||
if (!props.AllCompileDefinitions.empty()) {
|
||||
target.SetProperty("IMPORTED_CXX_MODULES_COMPILE_DEFINITIONS",
|
||||
cmJoin(allCompileDefinitions, ";"));
|
||||
cmJoin(props.AllCompileDefinitions, ";"));
|
||||
}
|
||||
|
||||
if (!allCompileOptions.empty()) {
|
||||
if (!props.AllCompileOptions.empty()) {
|
||||
target.SetProperty("IMPORTED_CXX_MODULES_COMPILE_OPTIONS",
|
||||
cmJoin(allCompileOptions, ";"));
|
||||
cmJoin(props.AllCompileOptions, ";"));
|
||||
}
|
||||
|
||||
if (!allCompileFeatures.empty()) {
|
||||
if (!props.AllCompileFeatures.empty()) {
|
||||
target.SetProperty("IMPORTED_CXX_MODULES_COMPILE_FEATURES",
|
||||
cmJoin(allCompileFeatures, ";"));
|
||||
cmJoin(props.AllCompileFeatures, ";"));
|
||||
}
|
||||
|
||||
for (auto const& config : configs) {
|
||||
std::vector<std::string> moduleList;
|
||||
for (auto const& module : meta.Modules) {
|
||||
if (module.IsInterface) {
|
||||
std::string sourcePath = module.SourcePath;
|
||||
if (!cmSystemTools::FileIsFullPath(sourcePath)) {
|
||||
sourcePath = cmStrCat(metadataDir, '/', sourcePath);
|
||||
}
|
||||
sourcePath =
|
||||
cmSystemTools::ToNormalizedPathOnDisk(std::move(sourcePath));
|
||||
moduleList.push_back(cmStrCat(module.LogicalName, "="_s, sourcePath));
|
||||
moduleList.push_back(cmStrCat(module.LogicalName, "="_s,
|
||||
props.NormalizePath(module.SourcePath)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,3 +583,19 @@ void cmCxxModuleMetadata::PopulateTarget(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void cmCxxModuleMetadata::PopulateTarget(
|
||||
cmTarget& target, cmCxxModuleMetadata const& meta,
|
||||
std::vector<std::string> const& configs)
|
||||
{
|
||||
auto props = CollectMetaProperties(meta);
|
||||
PopulateFileSet(target, props);
|
||||
|
||||
if (target.IsImported()) {
|
||||
PopulateImportedTarget(target, props, meta, configs);
|
||||
} else {
|
||||
PopulateLocalTarget(target, props);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5198,13 +5198,20 @@ bool CreateCxxStdlibTarget(cmMakefile* makefile, cmLocalGenerator* lg,
|
||||
metadata = std::move(*parseResult.Meta);
|
||||
}
|
||||
|
||||
auto* stdlibTgt = makefile->AddImportedTarget(
|
||||
cxxTargetName, cmStateEnums::INTERFACE_LIBRARY, true);
|
||||
auto const localTargetName = cmStrCat("__cmake_cxx_std_", stdLevel);
|
||||
cmStandardLevelResolver standardResolver(makefile);
|
||||
auto* stdlibTgt = makefile->AddLibrary(
|
||||
localTargetName, cmStateEnums::STATIC_LIBRARY, {}, true);
|
||||
cmCxxModuleMetadata::PopulateTarget(*stdlibTgt, *metadata, configs);
|
||||
stdlibTgt->AppendProperty("IMPORTED_CXX_MODULES_COMPILE_FEATURES",
|
||||
cmStrCat("cxx_std_", stdLevel));
|
||||
standardResolver.AddRequiredTargetFeature(stdlibTgt,
|
||||
cmStrCat("cxx_std_", stdLevel));
|
||||
auto gt = cm::make_unique<cmGeneratorTarget>(stdlibTgt, lg);
|
||||
for (auto const& config : configs) {
|
||||
gt->ComputeCompileFeatures(config);
|
||||
}
|
||||
|
||||
lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(stdlibTgt, lg));
|
||||
lg->AddGeneratorTarget(std::move(gt));
|
||||
makefile->AddAlias(cxxTargetName, localTargetName);
|
||||
|
||||
#endif // CMAKE_BOOTSTRAP
|
||||
|
||||
@@ -5295,8 +5302,7 @@ bool cmGeneratorTarget::ApplyCXXStdTargets()
|
||||
standardResolver.GetLevelString("CXX", *explicitLevel);
|
||||
auto const cxxTargetName = cmStrCat("__CMAKE::CXX", stdLevel);
|
||||
|
||||
// Create the __CMAKE::CXX## IMPORTED interface target if it doesn't
|
||||
// already exist
|
||||
// Create the __CMAKE::CXX## target if it doesn't already exist
|
||||
if (!this->Makefile->FindTargetToUse(cxxTargetName) &&
|
||||
!CreateCxxStdlibTarget(this->Makefile, this->LocalGenerator,
|
||||
this->GetName(), cxxTargetName, stdLevel,
|
||||
|
||||
Reference in New Issue
Block a user