diff --git a/Source/cmCxxModuleMetadata.cxx b/Source/cmCxxModuleMetadata.cxx index dfd7aab005..202a26099d 100644 --- a/Source/cmCxxModuleMetadata.cxx +++ b/Source/cmCxxModuleMetadata.cxx @@ -435,99 +435,140 @@ cmCxxModuleMetadata::SaveResult cmCxxModuleMetadata::SaveToFile( return st; } -void cmCxxModuleMetadata::PopulateTarget( - cmTarget& target, cmCxxModuleMetadata const& meta, - std::vector const& configs) +namespace { + +struct MetaDataProperties { - std::set allIncludeDirectories; - std::set allCompileOptions; - std::set allCompileFeatures; - std::set allCompileDefinitions; - std::set baseDirs; + std::string MetadataDir; + std::set AllCompileFeatures; + std::set AllCompileOptions; + std::set AllIncludeDirectories; + std::set AllCompileDefinitions; + std::set BaseDirs; + std::set 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("CXX_MODULES", "CXX_MODULES", - cmFileSetVisibility::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("CXX_MODULES", "CXX_MODULES", + cmFileSetVisibility::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 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 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))); } } @@ -539,3 +580,19 @@ void cmCxxModuleMetadata::PopulateTarget( } } } + +} // namespace + +void cmCxxModuleMetadata::PopulateTarget( + cmTarget& target, cmCxxModuleMetadata const& meta, + std::vector const& configs) +{ + auto props = CollectMetaProperties(meta); + PopulateFileSet(target, props); + + if (target.IsImported()) { + PopulateImportedTarget(target, props, meta, configs); + } else { + PopulateLocalTarget(target, props); + } +} diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 2bc13d9534..98049236af 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -5194,13 +5194,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(stdlibTgt, lg); + for (auto const& config : configs) { + gt->ComputeCompileFeatures(config); + } - lg->AddGeneratorTarget(cm::make_unique(stdlibTgt, lg)); + lg->AddGeneratorTarget(std::move(gt)); + makefile->AddAlias(cxxTargetName, localTargetName); #endif // CMAKE_BOOTSTRAP @@ -5291,8 +5298,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,