diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 29fc40d283..8d4a57aea7 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -268,6 +268,8 @@ add_library( cmFilePathChecksum.h cmFileSet.cxx cmFileSet.h + cmFileSetMetadata.cxx + cmFileSetMetadata.h cmFileTime.cxx cmFileTime.h cmFileTimeCache.cxx @@ -300,6 +302,10 @@ add_library( cmGeneratorExpressionParser.h cmGeneratorExpression.cxx cmGeneratorExpression.h + cmGeneratorFileSet.cxx + cmGeneratorFileSet.h + cmGeneratorFileSets.cxx + cmGeneratorFileSets.h cmGeneratorTarget.cxx cmGeneratorTarget.h cmGeneratorTarget_CompatibleInterface.cxx diff --git a/Source/cmBuildDatabase.cxx b/Source/cmBuildDatabase.cxx index e067caaad6..f5ddafaf80 100644 --- a/Source/cmBuildDatabase.cxx +++ b/Source/cmBuildDatabase.cxx @@ -17,8 +17,9 @@ #include "cmsys/FStream.hxx" #include "cmComputeLinkInformation.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGeneratedFileStream.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmListFileCache.h" @@ -449,9 +450,9 @@ cmBuildDatabase cmBuildDatabase::ForTarget(cmGeneratorTarget* gt, bool isPrivate = true; if (sf->GetLanguage() == "CXX"_s) { auto const* fs = gt->GetFileSetForSource(config, sf); - if (fs && fs->GetType() == cmFileSet::CXX_MODULES) { + if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) { isCXXModule = true; - isPrivate = !cmFileSet::VisibilityIsForInterface(fs->GetVisibility()); + isPrivate = !fs->IsForInterface(); } } diff --git a/Source/cmCxxModuleMetadata.cxx b/Source/cmCxxModuleMetadata.cxx index 68f3f55d6b..392095e9f5 100644 --- a/Source/cmCxxModuleMetadata.cxx +++ b/Source/cmCxxModuleMetadata.cxx @@ -16,6 +16,7 @@ #include "cmsys/FStream.hxx" #include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGeneratedFileStream.h" #include "cmJSONState.h" #include "cmListFileCache.h" @@ -448,9 +449,10 @@ void cmCxxModuleMetadata::PopulateTarget( std::string metadataDir = cmSystemTools::GetFilenamePath(meta.MetadataFilePath); - auto fileSet = target.GetOrCreateFileSet( - std::string{ cmFileSet::CXX_MODULES }, - std::string{ cmFileSet::CXX_MODULES }, cmFileSet::Visibility::Interface); + auto fileSet = + target.GetOrCreateFileSet(std::string{ cm::FileSetMetadata::CXX_MODULES }, + std::string{ cm::FileSetMetadata::CXX_MODULES }, + cm::FileSetMetadata::Visibility::Interface); for (auto const& module : meta.Modules) { std::string sourcePath = module.SourcePath; diff --git a/Source/cmDebuggerVariablesHelper.cxx b/Source/cmDebuggerVariablesHelper.cxx index 498b948239..9f8338fac7 100644 --- a/Source/cmDebuggerVariablesHelper.cxx +++ b/Source/cmDebuggerVariablesHelper.cxx @@ -16,6 +16,7 @@ #include "cmDebuggerStackFrame.h" #include "cmDebuggerVariables.h" #include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGlobalGenerator.h" #include "cmList.h" #include "cmListFileCache.h" @@ -195,18 +196,19 @@ std::shared_ptr cmDebuggerVariablesHelper::CreateIfAny( return {}; } - static auto visibilityString = [](cmFileSet::Visibility visibility) { - switch (visibility) { - case cmFileSet::Visibility::Private: - return "Private"; - case cmFileSet::Visibility::Public: - return "Public"; - case cmFileSet::Visibility::Interface: - return "Interface"; - default: - return "Unknown"; - } - }; + static auto visibilityString = + [](cm::FileSetMetadata::Visibility visibility) { + switch (visibility) { + case cm::FileSetMetadata::Visibility::Private: + return "Private"; + case cm::FileSetMetadata::Visibility::Public: + return "Public"; + case cm::FileSetMetadata::Visibility::Interface: + return "Interface"; + default: + return "Unknown"; + } + }; auto variables = std::make_shared( variablesManager, name, supportsVariableType, [=]() { @@ -305,15 +307,15 @@ std::shared_ptr cmDebuggerVariablesHelper::CreateIfAny( targetVariables->AddSubVariables( CreateIfAny(variablesManager, "CompileOptions", supportsVariableType, target->GetCompileOptionsEntries())); - targetVariables->AddSubVariables( - CreateIfAny(variablesManager, "CxxModuleSets", supportsVariableType, - target->GetFileSetsEntries(cmFileSet::CXX_MODULES))); + targetVariables->AddSubVariables(CreateIfAny( + variablesManager, "CxxModuleSets", supportsVariableType, + target->GetFileSetsEntries(cm::FileSetMetadata::CXX_MODULES))); targetVariables->AddSubVariables( CreateIfAny(variablesManager, "HeaderSets", supportsVariableType, - target->GetFileSetsEntries(cmFileSet::HEADERS))); + target->GetFileSetsEntries(cm::FileSetMetadata::HEADERS))); targetVariables->AddSubVariables(CreateIfAny( variablesManager, "InterfaceHeaderSets", supportsVariableType, - target->GetInterfaceFileSetsEntries(cmFileSet::HEADERS))); + target->GetInterfaceFileSetsEntries(cm::FileSetMetadata::HEADERS))); targetVariables->AddSubVariables( CreateIfAny(variablesManager, "LinkDirectories", supportsVariableType, target->GetLinkDirectoriesEntries())); diff --git a/Source/cmDyndepCollation.cxx b/Source/cmDyndepCollation.cxx index 969092542e..527fdbf3dc 100644 --- a/Source/cmDyndepCollation.cxx +++ b/Source/cmDyndepCollation.cxx @@ -20,10 +20,11 @@ #include "cmCxxModuleMetadata.h" #include "cmExportBuildFileGenerator.h" #include "cmExportSet.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGenExContext.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" // IWYU pragma: keep +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmInstallCxxModuleBmiGenerator.h" @@ -56,7 +57,6 @@ TdiSourceInfo CollationInformationSources(cmGeneratorTarget const* gt, cm::GenEx::Context const context(gt->LocalGenerator, config); TdiSourceInfo info; cmTarget const* tgt = gt->Target; - auto all_file_sets = tgt->GetAllFileSetNames(); Json::Value& tdi_sources = info.Sources = Json::objectValue; Json::Value& tdi_cxx_module_info = info.CxxModules = Json::objectValue; @@ -93,37 +93,20 @@ TdiSourceInfo CollationInformationSources(cmGeneratorTarget const* gt, } } - for (auto const& file_set_name : all_file_sets) { - auto const* file_set = tgt->GetFileSet(file_set_name); - if (!file_set) { - gt->Makefile->IssueMessage(MessageType::INTERNAL_ERROR, - cmStrCat("Target \"", tgt->GetName(), - "\" is tracked to have file set \"", - file_set_name, - "\", but it was not found.")); - continue; - } + for (auto const* file_set : gt->GetAllFileSets()) { auto fs_type = file_set->GetType(); // We only care about C++ module sources here. - if (fs_type != cmFileSet::CXX_MODULES) { + if (fs_type != cm::FileSetMetadata::CXX_MODULES) { continue; } // Synthetic (BMI-only) targets do not build private C++ modules. if (tgt->IsSynthetic() && - file_set->GetVisibility() == cmFileSet::Visibility::Private) { + file_set->GetVisibility() == + cm::FileSetMetadata::Visibility::Private) { continue; } - auto fileEntries = file_set->CompileFileEntries(); - auto directoryEntries = file_set->CompileDirectoryEntries(); - - auto directories = - file_set->EvaluateDirectoryEntries(directoryEntries, context, gt); - std::map> files_per_dirs; - for (auto const& entry : fileEntries) { - file_set->EvaluateFileEntry(directories, files_per_dirs, entry, context, - gt); - } + auto files_per_dirs = file_set->GetFiles(context, gt); Json::Value fs_dest = Json::nullValue; for (auto const& ig : gt->Makefile->GetInstallGenerators()) { @@ -139,7 +122,7 @@ TdiSourceInfo CollationInformationSources(cmGeneratorTarget const* gt, // Detect duplicate sources. std::set visited_sources; - for (auto const& files_per_dir : files_per_dirs) { + for (auto const& files_per_dir : files_per_dirs.first) { for (auto const& file : files_per_dir.second) { auto const full_file = cmSystemTools::CollapseFullPath(file); auto lookup = sf_map.find(full_file); @@ -149,16 +132,18 @@ TdiSourceInfo CollationInformationSources(cmGeneratorTarget const* gt, gt->Makefile->IssueMessage( MessageType::AUTHOR_WARNING, cmStrCat("Target \"", tgt->GetName(), "\" has source file\n ", - file, "\nin a \"FILE_SET TYPE ", cmFileSet::CXX_MODULES, + file, "\nin a \"FILE_SET TYPE ", + cm::FileSetMetadata::CXX_MODULES, "\" multiple times.")); continue; } - gt->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat("Target \"", tgt->GetName(), "\" has source file\n ", - file, "\nin a \"FILE_SET TYPE ", cmFileSet::CXX_MODULES, - "\" but it is not " - "scheduled for compilation.")); + gt->Makefile->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("Target \"", tgt->GetName(), + "\" has source file\n ", file, + "\nin a \"FILE_SET TYPE ", + cm::FileSetMetadata::CXX_MODULES, + "\" but it is not " + "scheduled for compilation.")); continue; } visited_sources.insert(full_file); @@ -211,8 +196,8 @@ TdiSourceInfo CollationInformationSources(cmGeneratorTarget const* gt, tdi_module_info["relative-directory"] = files_per_dir.first; tdi_module_info["name"] = file_set->GetName(); tdi_module_info["type"] = file_set->GetType(); - tdi_module_info["visibility"] = - std::string(cmFileSet::VisibilityToName(file_set->GetVisibility())); + tdi_module_info["visibility"] = std::string( + cm::FileSetMetadata::VisibilityToName(file_set->GetVisibility())); tdi_module_info["destination"] = fs_dest; } } @@ -403,7 +388,8 @@ struct CxxModuleFileSet std::string RelativeDirectory; std::string SourcePath; std::string Type; - cmFileSet::Visibility Visibility = cmFileSet::Visibility::Private; + cm::FileSetMetadata::Visibility Visibility = + cm::FileSetMetadata::Visibility::Private; cm::optional Destination; std::vector IncludeDirectories; std::vector Definitions; @@ -526,7 +512,7 @@ cmDyndepCollation::ParseExportInfo(Json::Value const& tdi) } fsi.SourcePath = tdi_cxx_module_info["source"].asString(); fsi.Type = tdi_cxx_module_info["type"].asString(); - fsi.Visibility = cmFileSet::VisibilityFromName( + fsi.Visibility = cm::FileSetMetadata::VisibilityFromName( tdi_cxx_module_info["visibility"].asString(), nullptr); auto const& tdi_fs_dest = tdi_cxx_module_info["destination"]; if (tdi_fs_dest.isString()) { @@ -677,7 +663,7 @@ bool cmDyndepCollation::WriteDyndepMetadata( cmStrCat("Output ", object.PrimaryOutput, " provides the `", provides.LogicalName, "` module but it is not found in a `FILE_SET` of type `", - cmFileSet::CXX_MODULES, '`')); + cm::FileSetMetadata::CXX_MODULES, '`')); result = false; } @@ -717,10 +703,11 @@ bool cmDyndepCollation::WriteDyndepMetadata( } // Verify the fileset type for the object. - if (file_set.Type == cmFileSet::CXX_MODULES) { + if (file_set.Type == cm::FileSetMetadata::CXX_MODULES) { if (!has_provides) { cmSystemTools::Error(cmStrCat("Output ", object.PrimaryOutput, - " is of type `", cmFileSet::CXX_MODULES, + " is of type `", + cm::FileSetMetadata::CXX_MODULES, "` but does not provide a module " "interface unit or partition")); result = false; @@ -731,10 +718,11 @@ bool cmDyndepCollation::WriteDyndepMetadata( } else { if (has_provides) { auto const& provides = object.Provides[0]; - cmSystemTools::Error(cmStrCat( - "Source ", file_set.SourcePath, " provides the `", - provides.LogicalName, "` C++ module but is of type `", file_set.Type, - "` module but must be of type `", cmFileSet::CXX_MODULES, '`')); + cmSystemTools::Error( + cmStrCat("Source ", file_set.SourcePath, " provides the `", + provides.LogicalName, "` C++ module but is of type `", + file_set.Type, "` module but must be of type `", + cm::FileSetMetadata::CXX_MODULES, '`')); result = false; } @@ -742,7 +730,7 @@ bool cmDyndepCollation::WriteDyndepMetadata( continue; } - if (!cmFileSet::VisibilityIsForInterface(file_set.Visibility)) { + if (!cm::FileSetMetadata::VisibilityIsForInterface(file_set.Visibility)) { // Nothing needs to be conveyed about non-`PUBLIC` modules. for (auto const& p : object.Provides) { private_modules.insert(p.LogicalName); @@ -926,7 +914,7 @@ bool cmDyndepCollation::IsObjectPrivate( return false; } auto const& file_set = fileset_info_itr->second; - return !cmFileSet::VisibilityIsForInterface(file_set.Visibility); + return !cm::FileSetMetadata::VisibilityIsForInterface(file_set.Visibility); } bool cmDyndepCollation::IsBmiOnly(cmCxxModuleExportInfo const& exportInfo, diff --git a/Source/cmEvaluatedTargetProperty.h b/Source/cmEvaluatedTargetProperty.h index 1ffbec46de..fa2bc8c131 100644 --- a/Source/cmEvaluatedTargetProperty.h +++ b/Source/cmEvaluatedTargetProperty.h @@ -10,6 +10,8 @@ #include "cmListFileCache.h" namespace cm { +class TargetPropertyEntry; + namespace GenEx { struct Context; } @@ -40,8 +42,7 @@ struct EvaluatedTargetPropertyEntry EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry( cmGeneratorTarget const* thisTarget, cm::GenEx::Context const& context, - cmGeneratorExpressionDAGChecker* dagChecker, - cmGeneratorTarget::TargetPropertyEntry& entry); + cmGeneratorExpressionDAGChecker* dagChecker, cm::TargetPropertyEntry& entry); struct EvaluatedTargetPropertyEntries { @@ -52,8 +53,7 @@ struct EvaluatedTargetPropertyEntries EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries( cmGeneratorTarget const* thisTarget, cm::GenEx::Context const& context, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector> const& - in); + std::vector> const& in); // IncludeRuntimeInterface is used to break the cycle in computing // the necessary transitive dependencies of targets that can occur diff --git a/Source/cmExportBuildCMakeConfigGenerator.cxx b/Source/cmExportBuildCMakeConfigGenerator.cxx index 057af999ee..d7ee97f3ed 100644 --- a/Source/cmExportBuildCMakeConfigGenerator.cxx +++ b/Source/cmExportBuildCMakeConfigGenerator.cxx @@ -2,25 +2,23 @@ file LICENSE.rst or https://cmake.org/licensing for details. */ #include "cmExportBuildCMakeConfigGenerator.h" -#include #include #include #include -#include +#include #include -#include #include #include #include -#include #include "cmCryptoHash.h" #include "cmExportSet.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGenExContext.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -160,47 +158,35 @@ void cmExportBuildCMakeConfigGenerator::GenerateImportTargetsConfig( } } -namespace { -bool EntryIsContextSensitive( - std::unique_ptr const& cge) -{ - return cge->GetHadContextSensitiveCondition(); -} -} - std::string cmExportBuildCMakeConfigGenerator::GetFileSetDirectories( - cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* /*te*/) + cmGeneratorTarget* gte, cmGeneratorFileSet const* fileSet, + cmTargetExport const* /*te*/) { std::vector resultVector; auto configs = gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); - auto directoryEntries = fileSet->CompileDirectoryEntries(); for (auto const& config : configs) { cm::GenEx::Context context(gte->LocalGenerator, config); - auto directories = - fileSet->EvaluateDirectoryEntries(directoryEntries, context, gte); - - bool const contextSensitive = - std::any_of(directoryEntries.begin(), directoryEntries.end(), - EntryIsContextSensitive); + auto directories = fileSet->GetDirectories(context, gte); + bool const contextSensitive = directories.second; auto const& type = fileSet->GetType(); // C++ modules do not support interface file sets which are dependent upon // the configuration. - if (contextSensitive && type == cmFileSet::CXX_MODULES) { + if (contextSensitive && type == cm::FileSetMetadata::CXX_MODULES) { auto* mf = this->LG->GetMakefile(); - std::ostringstream e; - e << "The \"" << gte->GetName() << "\" target's interface file set \"" - << fileSet->GetName() << "\" of type \"" << type - << "\" contains context-sensitive base directory entries which is not " - "supported."; - mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("The \"", gte->GetName(), + "\" target's interface file set \"", + fileSet->GetName(), "\" of type \"", type, + "\" contains context-sensitive base directory " + "entries which is not supported.")); return std::string{}; } - for (auto const& directory : directories) { + for (auto const& directory : directories.first) { auto dest = cmOutputConverter::EscapeForCMake( directory, cmOutputConverter::WrapQuotes::NoWrap); @@ -217,47 +203,35 @@ std::string cmExportBuildCMakeConfigGenerator::GetFileSetDirectories( } std::string cmExportBuildCMakeConfigGenerator::GetFileSetFiles( - cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* /*te*/) + cmGeneratorTarget* gte, cmGeneratorFileSet const* fileSet, + cmTargetExport const* /*te*/) { std::vector resultVector; auto configs = gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); - auto fileEntries = fileSet->CompileFileEntries(); - auto directoryEntries = fileSet->CompileDirectoryEntries(); - for (auto const& config : configs) { cm::GenEx::Context context(gte->LocalGenerator, config); - auto directories = - fileSet->EvaluateDirectoryEntries(directoryEntries, context, gte); - std::map> files; - for (auto const& entry : fileEntries) { - fileSet->EvaluateFileEntry(directories, files, entry, context, gte); - } - - bool const contextSensitive = - std::any_of(directoryEntries.begin(), directoryEntries.end(), - EntryIsContextSensitive) || - std::any_of(fileEntries.begin(), fileEntries.end(), - EntryIsContextSensitive); + auto files = fileSet->GetFiles(context, gte); + bool const contextSensitive = files.second; auto const& type = fileSet->GetType(); // C++ modules do not support interface file sets which are dependent upon // the configuration. - if (contextSensitive && type == cmFileSet::CXX_MODULES) { + if (contextSensitive && type == cm::FileSetMetadata::CXX_MODULES) { auto* mf = this->LG->GetMakefile(); - std::ostringstream e; - e << "The \"" << gte->GetName() << "\" target's interface file set \"" - << fileSet->GetName() << "\" of type \"" << type - << "\" contains context-sensitive file entries which is not " - "supported."; - mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("The \"", gte->GetName(), + "\" target's interface file set \"", + fileSet->GetName(), "\" of type \"", type, + "\" contains context-sensitive file entries " + "which is not supported.")); return std::string{}; } - for (auto const& it : files) { + for (auto const& it : files.first) { for (auto const& filename : it.second) { auto escapedFile = cmOutputConverter::EscapeForCMake( filename, cmOutputConverter::WrapQuotes::NoWrap); @@ -317,9 +291,8 @@ bool cmExportBuildCMakeConfigGenerator:: 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()); + cmSystemTools::Error( + cmStrCat("cannot write to file \"", fileName, "\": ", se)); return false; } os.SetCopyIfDifferent(true); diff --git a/Source/cmExportBuildCMakeConfigGenerator.h b/Source/cmExportBuildCMakeConfigGenerator.h index c6250323c6..29ecb235bb 100644 --- a/Source/cmExportBuildCMakeConfigGenerator.h +++ b/Source/cmExportBuildCMakeConfigGenerator.h @@ -36,9 +36,11 @@ protected: void GenerateImportTargetsConfig(std::ostream& os, std::string const& config, std::string const& suffix) override; - std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet, + std::string GetFileSetDirectories(cmGeneratorTarget* gte, + cmGeneratorFileSet const* fileSet, cmTargetExport const* te) override; - std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet, + std::string GetFileSetFiles(cmGeneratorTarget* gte, + cmGeneratorFileSet const* fileSet, cmTargetExport const* te) override; void GenerateCxxModuleConfigInformation(std::string const&, diff --git a/Source/cmExportCMakeConfigGenerator.cxx b/Source/cmExportCMakeConfigGenerator.cxx index 56d26ce158..5979081b9c 100644 --- a/Source/cmExportCMakeConfigGenerator.cxx +++ b/Source/cmExportCMakeConfigGenerator.cxx @@ -13,9 +13,10 @@ #include #include "cmExportSet.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmFindPackageStack.h" #include "cmGeneratedFileStream.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -607,7 +608,7 @@ void cmExportCMakeConfigGenerator::GenerateTargetFileSets( << targetName << '\n'; for (auto const& name : interfaceFileSets) { - auto* fileSet = gte->Target->GetFileSet(name); + auto const* fileSet = gte->GetFileSet(name); if (!fileSet) { gte->Makefile->IssueMessage( MessageType::FATAL_ERROR, @@ -629,7 +630,7 @@ void cmExportCMakeConfigGenerator::GenerateTargetFileSets( os << " )\nelse()\n set_property(TARGET " << targetName << "\n APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES"; for (auto const& name : interfaceFileSets) { - auto* fileSet = gte->Target->GetFileSet(name); + auto const* fileSet = gte->GetFileSet(name); if (!fileSet) { gte->Makefile->IssueMessage( MessageType::FATAL_ERROR, @@ -639,7 +640,7 @@ void cmExportCMakeConfigGenerator::GenerateTargetFileSets( return; } - if (fileSet->GetType() == cmFileSet::HEADERS) { + if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) { os << "\n " << this->GetFileSetDirectories(gte, fileSet, te); } } diff --git a/Source/cmExportCMakeConfigGenerator.h b/Source/cmExportCMakeConfigGenerator.h index f95676f550..a715280086 100644 --- a/Source/cmExportCMakeConfigGenerator.h +++ b/Source/cmExportCMakeConfigGenerator.h @@ -15,7 +15,7 @@ #include "cmGeneratorExpression.h" #include "cmStateTypes.h" -class cmFileSet; +class cmGeneratorFileSet; class cmGeneratorTarget; class cmTargetExport; @@ -91,10 +91,10 @@ protected: void GenerateCxxModuleInformation(std::string const& name, std::ostream& os); virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte, - cmFileSet* fileSet, + cmGeneratorFileSet const* fileSet, cmTargetExport const* te) = 0; virtual std::string GetFileSetFiles(cmGeneratorTarget* gte, - cmFileSet* fileSet, + cmGeneratorFileSet const* fileSet, cmTargetExport const* te) = 0; void SetRequiredCMakeVersion(unsigned int major, unsigned int minor, diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index fdf0dbdad0..8e6df039c5 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -674,9 +674,9 @@ bool PropertyTypeIsForPaths(PropertyType pt) bool cmExportFileGenerator::PopulateCxxModuleExportProperties( cmGeneratorTarget const* gte, ImportPropertyMap& properties, cmGeneratorExpression::PreprocessContext ctx, - std::string const& includesDestinationDirs, std::string& errorMessage) + std::string const& includesDestinationDirs, std::string&) { - if (!gte->HaveCxx20ModuleSources(&errorMessage)) { + if (!gte->HaveCxx20ModuleSources()) { return true; } diff --git a/Source/cmExportInstallCMakeConfigGenerator.cxx b/Source/cmExportInstallCMakeConfigGenerator.cxx index 80bf35059b..912ff39d71 100644 --- a/Source/cmExportInstallCMakeConfigGenerator.cxx +++ b/Source/cmExportInstallCMakeConfigGenerator.cxx @@ -2,7 +2,6 @@ file LICENSE.rst or https://cmake.org/licensing for details. */ #include "cmExportInstallCMakeConfigGenerator.h" -#include #include #include #include @@ -12,14 +11,14 @@ #include #include -#include #include "cmExportFileGenerator.h" #include "cmExportSet.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGenExContext.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmInstallExportGenerator.h" #include "cmInstallFileSetGenerator.h" @@ -271,16 +270,9 @@ void cmExportInstallCMakeConfigGenerator::GenerateImportTargetsConfig( } } -namespace { -bool EntryIsContextSensitive( - std::unique_ptr const& cge) -{ - return cge->GetHadContextSensitiveCondition(); -} -} - std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories( - cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* te) + cmGeneratorTarget* gte, cmGeneratorFileSet const* fileSet, + cmTargetExport const* te) { std::vector resultVector; @@ -303,7 +295,7 @@ std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories( // C++ modules do not support interface file sets which are dependent upon // the configuration. if (cge->GetHadContextSensitiveCondition() && - type == cmFileSet::CXX_MODULES) { + type == cm::FileSetMetadata::CXX_MODULES) { auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile(); std::ostringstream e; e << "The \"" << gte->GetName() << "\" target's interface file set \"" @@ -327,29 +319,22 @@ std::string cmExportInstallCMakeConfigGenerator::GetFileSetDirectories( } std::string cmExportInstallCMakeConfigGenerator::GetFileSetFiles( - cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport const* te) + cmGeneratorTarget* gte, cmGeneratorFileSet const* fileSet, + cmTargetExport const* te) { std::vector resultVector; auto configs = gte->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig); - auto fileEntries = fileSet->CompileFileEntries(); - auto directoryEntries = fileSet->CompileDirectoryEntries(); - cmGeneratorExpression destGe(*gte->Makefile->GetCMakeInstance()); auto destCge = destGe.Parse( te->FileSetGenerators.at(fileSet->GetName())->GetDestination()); for (auto const& config : configs) { cm::GenEx::Context context(gte->LocalGenerator, config); - auto directories = - fileSet->EvaluateDirectoryEntries(directoryEntries, context, gte); + auto files = fileSet->GetFiles(context, gte); - std::map> files; - for (auto const& entry : fileEntries) { - fileSet->EvaluateFileEntry(directories, files, entry, context, gte); - } auto unescapedDest = destCge->Evaluate(gte->LocalGenerator, config, gte); auto dest = cmStrCat(cmOutputConverter::EscapeForCMake( @@ -359,27 +344,23 @@ std::string cmExportInstallCMakeConfigGenerator::GetFileSetFiles( dest = cmStrCat("${_IMPORT_PREFIX}/", dest); } - bool const contextSensitive = destCge->GetHadContextSensitiveCondition() || - std::any_of(directoryEntries.begin(), directoryEntries.end(), - EntryIsContextSensitive) || - std::any_of(fileEntries.begin(), fileEntries.end(), - EntryIsContextSensitive); - + bool const contextSensitive = + destCge->GetHadContextSensitiveCondition() || files.second; auto const& type = fileSet->GetType(); // C++ modules do not support interface file sets which are dependent upon // the configuration. - if (contextSensitive && type == cmFileSet::CXX_MODULES) { + if (contextSensitive && type == cm::FileSetMetadata::CXX_MODULES) { auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile(); - std::ostringstream e; - e << "The \"" << gte->GetName() << "\" target's interface file set \"" - << fileSet->GetName() << "\" of type \"" << type - << "\" contains context-sensitive base file entries which is not " - "supported."; - mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + mf->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("The \"", gte->GetName(), + "\" target's interface file set \"", + fileSet->GetName(), "\" of type \"", type, + "\" contains context-sensitive base file " + "entries which is not supported.")); return std::string{}; } - for (auto const& it : files) { + for (auto const& it : files.first) { auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/'); for (auto const& filename : it.second) { auto relFile = diff --git a/Source/cmExportInstallCMakeConfigGenerator.h b/Source/cmExportInstallCMakeConfigGenerator.h index 480384d187..e4ebd2964e 100644 --- a/Source/cmExportInstallCMakeConfigGenerator.h +++ b/Source/cmExportInstallCMakeConfigGenerator.h @@ -59,9 +59,11 @@ protected: virtual void CleanupTemporaryVariables(std::ostream&); - std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet, + std::string GetFileSetDirectories(cmGeneratorTarget* gte, + cmGeneratorFileSet const* fileSet, cmTargetExport const* te) override; - std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet, + std::string GetFileSetFiles(cmGeneratorTarget* gte, + cmGeneratorFileSet const* fileSet, cmTargetExport const* te) override; std::string GetCxxModulesDirectory() const override; diff --git a/Source/cmExportInstallPackageInfoGenerator.cxx b/Source/cmExportInstallPackageInfoGenerator.cxx index 3b20c5928f..78eb146299 100644 --- a/Source/cmExportInstallPackageInfoGenerator.cxx +++ b/Source/cmExportInstallPackageInfoGenerator.cxx @@ -19,8 +19,9 @@ #include "cmAlgorithms.h" #include "cmExportSet.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmInstallExportGenerator.h" #include "cmInstallFileSetGenerator.h" @@ -220,8 +221,8 @@ std::string cmExportInstallPackageInfoGenerator::GetCxxModulesDirectory() const cm::optional cmExportInstallPackageInfoGenerator::GetFileSetDirectory( - cmGeneratorTarget* gte, cmTargetExport const* te, cmFileSet* fileSet, - cm::optional const& config) + cmGeneratorTarget* gte, cmTargetExport const* te, + cmGeneratorFileSet const* fileSet, cm::optional const& config) { cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance()); auto cge = @@ -240,7 +241,7 @@ cmExportInstallPackageInfoGenerator::GetFileSetDirectory( } std::string const& type = fileSet->GetType(); - if (config && (type == cmFileSet::CXX_MODULES)) { + if (config && (type == cm::FileSetMetadata::CXX_MODULES)) { // C++ modules do not support interface file sets which are dependent // upon the configuration. cmMakefile* mf = gte->LocalGenerator->GetMakefile(); @@ -270,7 +271,7 @@ bool cmExportInstallPackageInfoGenerator::GenerateFileSetProperties( bool hasModules = false; std::set seenIncludeDirectories; for (auto const& name : gte->Target->GetAllInterfaceFileSets()) { - cmFileSet* fileSet = gte->Target->GetFileSet(name); + cmGeneratorFileSet const* fileSet = gte->GetFileSet(name); if (!fileSet) { gte->Makefile->IssueMessage( @@ -284,13 +285,13 @@ bool cmExportInstallPackageInfoGenerator::GenerateFileSetProperties( cm::optional const& fileSetDirectory = this->GetFileSetDirectory(gte, te, fileSet, config); - if (fileSet->GetType() == cmFileSet::HEADERS) { + if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) { if (fileSetDirectory && !cm::contains(seenIncludeDirectories, *fileSetDirectory)) { component["includes"].append(*fileSetDirectory); seenIncludeDirectories.insert(*fileSetDirectory); } - } else if (fileSet->GetType() == cmFileSet::CXX_MODULES) { + } else if (fileSet->GetType() == cm::FileSetMetadata::CXX_MODULES) { hasModules = true; this->RequiresConfigFiles = true; } diff --git a/Source/cmExportInstallPackageInfoGenerator.h b/Source/cmExportInstallPackageInfoGenerator.h index 150123456d..da7f4e305b 100644 --- a/Source/cmExportInstallPackageInfoGenerator.h +++ b/Source/cmExportInstallPackageInfoGenerator.h @@ -12,7 +12,7 @@ #include "cmExportInstallFileGenerator.h" #include "cmExportPackageInfoGenerator.h" -class cmFileSet; +class cmGeneratorFileSet; class cmGeneratorTarget; class cmInstallExportGenerator; class cmPackageInfoArguments; @@ -71,7 +71,8 @@ protected: std::string GetCxxModulesDirectory() const override; cm::optional GetFileSetDirectory( - cmGeneratorTarget* gte, cmTargetExport const* te, cmFileSet* fileSet, + cmGeneratorTarget* gte, cmTargetExport const* te, + cmGeneratorFileSet const* fileSet, cm::optional const& config = {}); bool GenerateFileSetProperties(Json::Value& component, diff --git a/Source/cmExportInstallSbomGenerator.cxx b/Source/cmExportInstallSbomGenerator.cxx index c3b0826e91..d944383902 100644 --- a/Source/cmExportInstallSbomGenerator.cxx +++ b/Source/cmExportInstallSbomGenerator.cxx @@ -13,8 +13,9 @@ #include #include "cmExportSet.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmInstallExportGenerator.h" #include "cmInstallFileSetGenerator.h" @@ -212,8 +213,8 @@ std::string cmExportInstallSbomGenerator::GetCxxModuleFile( } cm::optional cmExportInstallSbomGenerator::GetFileSetDirectory( - cmGeneratorTarget* gte, cmTargetExport const* te, cmFileSet* fileSet, - cm::optional const& config) + cmGeneratorTarget* gte, cmTargetExport const* te, + cmGeneratorFileSet const* fileSet, cm::optional const& config) { cmGeneratorExpression ge(*gte->Makefile->GetCMakeInstance()); auto cge = @@ -228,7 +229,7 @@ cm::optional cmExportInstallSbomGenerator::GetFileSetDirectory( } std::string const& type = fileSet->GetType(); - if (config && (type == cmFileSet::CXX_MODULES)) { + if (config && (type == cm::FileSetMetadata::CXX_MODULES)) { cmMakefile* mf = gte->LocalGenerator->GetMakefile(); std::ostringstream e; e << "The \"" << gte->GetName() << "\" target's interface file set \"" diff --git a/Source/cmExportInstallSbomGenerator.h b/Source/cmExportInstallSbomGenerator.h index c7fb9b64f7..a6d4c5c636 100644 --- a/Source/cmExportInstallSbomGenerator.h +++ b/Source/cmExportInstallSbomGenerator.h @@ -13,7 +13,7 @@ #include "cmExportInstallFileGenerator.h" #include "cmExportSbomGenerator.h" -class cmFileSet; +class cmGeneratorFileSet; class cmGeneratorTarget; class cmInstallExportGenerator; class cmSbomArguments; @@ -63,6 +63,7 @@ protected: std::string GetCxxModulesDirectory() const override; cm::optional GetFileSetDirectory( - cmGeneratorTarget* gte, cmTargetExport const* te, cmFileSet* fileSet, + cmGeneratorTarget* gte, cmTargetExport const* te, + cmGeneratorFileSet const* fileSet, cm::optional const& config = {}); }; diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 886c639a00..3bb036907f 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -8,10 +8,10 @@ #include #include -#include "cmFileSet.h" #include "cmGenExContext.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionDAGChecker.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmList.h" @@ -176,14 +176,16 @@ std::string cmExportTryCompileFileGenerator::InstallNameDir( } std::string cmExportTryCompileFileGenerator::GetFileSetDirectories( - cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport const* /*te*/) + cmGeneratorTarget* /*gte*/, cmGeneratorFileSet const* fileSet, + cmTargetExport const* /*te*/) { return cmOutputConverter::EscapeForCMake( cmList::to_string(fileSet->GetDirectoryEntries())); } std::string cmExportTryCompileFileGenerator::GetFileSetFiles( - cmGeneratorTarget* /*gte*/, cmFileSet* fileSet, cmTargetExport const* /*te*/) + cmGeneratorTarget* /*gte*/, cmGeneratorFileSet const* fileSet, + cmTargetExport const* /*te*/) { return cmOutputConverter::EscapeForCMake( cmList::to_string(fileSet->GetFileEntries())); diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index 00231ba6ff..f877a17029 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -57,10 +57,11 @@ protected: std::string const& config) override; std::string GetFileSetDirectories(cmGeneratorTarget* target, - cmFileSet* fileSet, + cmGeneratorFileSet const* fileSet, cmTargetExport const* te) override; - std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet, + std::string GetFileSetFiles(cmGeneratorTarget* target, + cmGeneratorFileSet const* fileSet, cmTargetExport const* te) override; std::string GetCxxModulesDirectory() const override { return {}; } diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 9ce718fa7d..38ca4dd442 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -17,16 +17,16 @@ #include #include -#include #include #include "cmCryptoHash.h" #include "cmExportSet.h" #include "cmFileAPI.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGenExContext.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmInstallCxxModuleBmiGenerator.h" @@ -48,7 +48,6 @@ #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmMessageType.h" #include "cmRange.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" @@ -465,7 +464,7 @@ class Target using FileSetDatabase = std::map; - std::vector FileSetVisibilities; + std::vector FileSetVisibilities; template JBT ToJBT(BT const& bt) @@ -502,7 +501,7 @@ class Target Json::Value DumpLanguageStandard(JBTs const& standard); Json::Value DumpDefine(JBT const& def); std::pair DumpFileSets(); - Json::Value DumpFileSet(cmFileSet const* fs, + Json::Value DumpFileSet(cmGeneratorFileSet const* fs, std::vector const& directories); Json::Value DumpSources(FileSetDatabase const& fsdb); Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk, @@ -1148,18 +1147,11 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) auto* target = installFileSet->GetTarget(); cm::GenEx::Context context(target->LocalGenerator, this->Config); - - auto dirCges = fileSet->CompileDirectoryEntries(); - auto dirs = fileSet->EvaluateDirectoryEntries(dirCges, context, target); - - auto entryCges = fileSet->CompileFileEntries(); - std::map> entries; - for (auto const& entryCge : entryCges) { - fileSet->EvaluateFileEntry(dirs, entries, entryCge, context, target); - } + auto dirs = fileSet->GetDirectories(context, target); + auto entries = fileSet->GetFiles(context, target); Json::Value files = Json::arrayValue; - for (auto const& it : entries) { + for (auto const& it : entries.first) { auto dir = it.first; if (!dir.empty()) { dir += '/'; @@ -1174,7 +1166,7 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) installer["fileSetName"] = fileSet->GetName(); installer["fileSetType"] = fileSet->GetType(); installer["fileSetDirectories"] = Json::arrayValue; - for (auto const& dir : dirs) { + for (auto const& dir : dirs.first) { installer["fileSetDirectories"].append( RelativeIfUnder(this->TopSource, dir)); } @@ -1726,41 +1718,22 @@ std::pair Target::DumpFileSets() this->FileSetVisibilities.clear(); // Build the fileset database. - auto const* tgt = this->GT->Target; - auto const& fs_names = tgt->GetAllFileSetNames(); + auto const& fileSets = this->GT->GetAllFileSets(); - if (!fs_names.empty()) { + if (!fileSets.empty()) { fsJson = Json::arrayValue; size_t fsIndex = 0; - for (auto const& fs_name : fs_names) { - auto const* fs = tgt->GetFileSet(fs_name); - if (!fs) { - this->GT->Makefile->IssueMessage( - MessageType::INTERNAL_ERROR, - cmStrCat("Target \"", tgt->GetName(), - "\" is tracked to have file set \"", fs_name, - "\", but it was not found.")); - continue; - } - + for (auto const* fs : fileSets) { cm::GenEx::Context context(this->GT->LocalGenerator, this->Config); - auto fileEntries = fs->CompileFileEntries(); - auto directoryEntries = fs->CompileDirectoryEntries(); + auto directories = fs->GetDirectories(context, this->GT); - auto directories = - fs->EvaluateDirectoryEntries(directoryEntries, context, this->GT); - - fsJson.append(this->DumpFileSet(fs, directories)); + fsJson.append(this->DumpFileSet(fs, directories.first)); this->FileSetVisibilities.push_back(fs->GetVisibility()); - std::map> files_per_dirs; - for (auto const& entry : fileEntries) { - fs->EvaluateFileEntry(directories, files_per_dirs, entry, context, - this->GT); - } + auto files_per_dirs = fs->GetFiles(context, this->GT); - for (auto const& files_per_dir : files_per_dirs) { + for (auto const& files_per_dir : files_per_dirs.first) { auto const& dir = files_per_dir.first; for (auto const& file : files_per_dir.second) { std::string sf_path; @@ -1780,7 +1753,7 @@ std::pair Target::DumpFileSets() return std::make_pair(fsJson, fsdb); } -Json::Value Target::DumpFileSet(cmFileSet const* fs, +Json::Value Target::DumpFileSet(cmGeneratorFileSet const* fs, std::vector const& directories) { Json::Value fileSet = Json::objectValue; @@ -1788,7 +1761,7 @@ Json::Value Target::DumpFileSet(cmFileSet const* fs, fileSet["name"] = fs->GetName(); fileSet["type"] = fs->GetType(); fileSet["visibility"] = - std::string(cmFileSet::VisibilityToName(fs->GetVisibility())); + std::string(cm::FileSetMetadata::VisibilityToName(fs->GetVisibility())); Json::Value baseDirs = Json::arrayValue; for (auto const& directory : directories) { @@ -1888,7 +1861,8 @@ Json::Value Target::DumpInterfaceSources(FileSetDatabase const& fsdb) Json::ArrayIndex const index = fsIter.second; // FileSetVisibilities was populated by DumpFileSets() and will always // have the same size as the file sets array that index is indexing into - if (this->FileSetVisibilities[index] != cmFileSet::Visibility::Private) { + if (this->FileSetVisibilities[index] != + cm::FileSetMetadata::Visibility::Private) { dumpFile(fsIter.first); } } diff --git a/Source/cmFileSet.cxx b/Source/cmFileSet.cxx index 266edc9670..21d932bd69 100644 --- a/Source/cmFileSet.cxx +++ b/Source/cmFileSet.cxx @@ -2,113 +2,24 @@ file LICENSE.rst or https://cmake.org/licensing for details. */ #include "cmFileSet.h" -#include #include -#include #include #include -#include #include -#include -#include "cmsys/RegularExpression.hxx" - -#include "cmGenExContext.h" -#include "cmGeneratorExpression.h" #include "cmList.h" #include "cmListFileCache.h" -#include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmMessageType.h" -#include "cmStringAlgorithms.h" -#include "cmSystemTools.h" -#include "cmake.h" -cm::static_string_view cmFileSet::VisibilityToName(Visibility vis) -{ - switch (vis) { - case Visibility::Interface: - return "INTERFACE"_s; - case Visibility::Public: - return "PUBLIC"_s; - case Visibility::Private: - return "PRIVATE"_s; - } - return ""_s; -} - -cmFileSet::Visibility cmFileSet::VisibilityFromName(cm::string_view name, - cmMakefile* mf) -{ - if (name == "INTERFACE"_s) { - return Visibility::Interface; - } - if (name == "PUBLIC"_s) { - return Visibility::Public; - } - if (name == "PRIVATE"_s) { - return Visibility::Private; - } - auto msg = cmStrCat("File set visibility \"", name, "\" is not valid."); - if (mf) { - mf->IssueMessage(MessageType::FATAL_ERROR, msg); - } else { - cmSystemTools::Error(msg); - } - return Visibility::Private; -} - -bool cmFileSet::VisibilityIsForSelf(Visibility vis) -{ - switch (vis) { - case Visibility::Interface: - return false; - case Visibility::Public: - case Visibility::Private: - return true; - } - return false; -} - -bool cmFileSet::VisibilityIsForInterface(Visibility vis) -{ - switch (vis) { - case Visibility::Interface: - case Visibility::Public: - return true; - case Visibility::Private: - return false; - } - return false; -} -cm::static_string_view const cmFileSet::HEADERS = "HEADERS"_s; -cm::static_string_view const cmFileSet::CXX_MODULES = "CXX_MODULES"_s; - -bool cmFileSet::IsKnownType(std::string const& type) -{ - return cm::contains(GetKnownTypes(), type); -} - -bool cmFileSet::TypeCanBeIncluded(std::string const& type) -{ - return type == HEADERS; -} - -cmList const& cmFileSet::GetKnownTypes() -{ - return KnownTypes; -} - -cmList cmFileSet::KnownTypes{ std::string{ HEADERS }, - std::string{ CXX_MODULES } }; +namespace Metadata = cm::FileSetMetadata; cmFileSet::cmFileSet(cmMakefile* makefile, std::string name, std::string type, - Visibility visibility) + Metadata::Visibility visibility) : Makefile(makefile) , Name(std::move(name)) , Type(std::move(type)) - , FSVisibility(visibility) + , Visibility(visibility) { } @@ -138,147 +49,6 @@ void cmFileSet::AddFileEntry(BT files) this->FileEntries.push_back(std::move(files)); } -std::vector> -cmFileSet::CompileFileEntries() const -{ - std::vector> result; - - for (auto const& entry : this->FileEntries) { - for (auto const& ex : cmList{ entry.Value }) { - cmGeneratorExpression ge(*this->GetMakefile()->GetCMakeInstance(), - entry.Backtrace); - auto cge = ge.Parse(ex); - result.push_back(std::move(cge)); - } - } - - return result; -} - -std::vector> -cmFileSet::CompileDirectoryEntries() const -{ - std::vector> result; - - for (auto const& entry : this->DirectoryEntries) { - for (auto const& ex : cmList{ entry.Value }) { - cmGeneratorExpression ge(*this->GetMakefile()->GetCMakeInstance(), - entry.Backtrace); - auto cge = ge.Parse(ex); - result.push_back(std::move(cge)); - } - } - - return result; -} - -std::vector cmFileSet::EvaluateDirectoryEntries( - std::vector> const& cges, - cm::GenEx::Context const& context, cmGeneratorTarget const* target, - cmGeneratorExpressionDAGChecker* dagChecker) const -{ - struct DirCacheEntry - { - std::string collapsedDir; - cm::optional fileId; - }; - - std::unordered_map dirCache; - std::vector result; - for (auto const& cge : cges) { - auto entry = cge->Evaluate(context, dagChecker, target); - cmList dirs{ entry }; - for (std::string dir : dirs) { - if (!cmSystemTools::FileIsFullPath(dir)) { - dir = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', dir); - } - - auto dirCacheResult = dirCache.emplace(dir, DirCacheEntry()); - auto& dirCacheEntry = dirCacheResult.first->second; - auto const isNewCacheEntry = dirCacheResult.second; - - if (isNewCacheEntry) { - cmSystemTools::FileId fileId; - auto isFileIdValid = cmSystemTools::GetFileId(dir, fileId); - dirCacheEntry.collapsedDir = cmSystemTools::CollapseFullPath(dir); - dirCacheEntry.fileId = - isFileIdValid ? cm::optional(fileId) : cm::nullopt; - } - - for (auto const& priorDir : result) { - auto priorDirCacheEntry = dirCache.at(priorDir); - bool sameFile = dirCacheEntry.fileId.has_value() && - priorDirCacheEntry.fileId.has_value() && - (*dirCacheEntry.fileId == *priorDirCacheEntry.fileId); - if (!sameFile && - (cmSystemTools::IsSubDirectory(dirCacheEntry.collapsedDir, - priorDirCacheEntry.collapsedDir) || - cmSystemTools::IsSubDirectory(priorDirCacheEntry.collapsedDir, - dirCacheEntry.collapsedDir))) { - context.LG->GetCMakeInstance()->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat( - "Base directories in file set cannot be subdirectories of each " - "other:\n ", - priorDir, "\n ", dir), - cge->GetBacktrace()); - return {}; - } - } - result.push_back(dir); - } - } - return result; -} - -void cmFileSet::EvaluateFileEntry( - std::vector const& dirs, - std::map>& filesPerDir, - std::unique_ptr const& cge, - cm::GenEx::Context const& context, cmGeneratorTarget const* target, - cmGeneratorExpressionDAGChecker* dagChecker) const -{ - auto files = cge->Evaluate(context, dagChecker, target); - for (std::string file : cmList{ files }) { - if (!cmSystemTools::FileIsFullPath(file)) { - file = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', file); - } - auto collapsedFile = cmSystemTools::CollapseFullPath(file); - bool found = false; - std::string relDir; - for (auto const& dir : dirs) { - auto collapsedDir = cmSystemTools::CollapseFullPath(dir); - if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) { - found = true; - relDir = cmSystemTools::GetParentDirectory( - cmSystemTools::RelativePath(collapsedDir, collapsedFile)); - break; - } - } - if (!found) { - std::ostringstream e; - e << "File:\n " << file - << "\nmust be in one of the file set's base directories:"; - for (auto const& dir : dirs) { - e << "\n " << dir; - } - context.LG->GetCMakeInstance()->IssueMessage( - MessageType::FATAL_ERROR, e.str(), cge->GetBacktrace()); - return; - } - - filesPerDir[relDir].push_back(file); - } -} - -bool cmFileSet::IsValidName(std::string const& name) -{ - static cmsys::RegularExpression const regex("^[a-z0-9][a-zA-Z0-9_]*$"); - - cmsys::RegularExpressionMatch match; - return regex.find(name.c_str(), match); -} - std::string const cmFileSet::propCOMPILE_DEFINITIONS = "COMPILE_DEFINITIONS"; std::string const cmFileSet::propCOMPILE_OPTIONS = "COMPILE_OPTIONS"; std::string const cmFileSet::propINCLUDE_DIRECTORIES = "INCLUDE_DIRECTORIES"; diff --git a/Source/cmFileSet.h b/Source/cmFileSet.h index e4910a17f1..4b22b1f767 100644 --- a/Source/cmFileSet.h +++ b/Source/cmFileSet.h @@ -3,63 +3,47 @@ #pragma once #include -#include -#include #include #include #include -#include -#include "cmList.h" +#include "cmFileSetMetadata.h" #include "cmListFileCache.h" #include "cmPropertyMap.h" #include "cmValue.h" -namespace cm { -namespace GenEx { -struct Context; -} -} - -class cmCompiledGeneratorExpression; -struct cmGeneratorExpressionDAGChecker; -class cmGeneratorTarget; class cmMakefile; class cmFileSet { public: - enum class Visibility - { - Private, - Public, - Interface, - }; - static cm::static_string_view VisibilityToName(Visibility vis); - static Visibility VisibilityFromName(cm::string_view name, cmMakefile* mf); - - static bool VisibilityIsForSelf(Visibility vis); - static bool VisibilityIsForInterface(Visibility vis); - - static bool IsKnownType(std::string const& type); - static bool TypeCanBeIncluded(std::string const& type); - - // Pre-defined FileSet types - static cm::static_string_view const HEADERS; - static cm::static_string_view const CXX_MODULES; - - static cmList const& GetKnownTypes(); - cmFileSet(cmMakefile* makefile, std::string name, std::string type, - Visibility visibility); + cm::FileSetMetadata::Visibility visibility); std::string const& GetName() const { return this->Name; } std::string const& GetType() const { return this->Type; } - Visibility GetVisibility() const { return this->FSVisibility; } + cm::FileSetMetadata::Visibility GetVisibility() const + { + return this->Visibility; + } cmMakefile* GetMakefile() const { return this->Makefile; } + bool IsForSelf() const + { + return cm::FileSetMetadata::VisibilityIsForSelf(this->GetVisibility()); + } + bool IsForInterface() const + { + return cm::FileSetMetadata::VisibilityIsForInterface( + this->GetVisibility()); + } + bool CanBeIncluded() const + { + return this->Type == cm::FileSetMetadata::HEADERS; + } + void CopyEntries(cmFileSet const* fs); void ClearDirectoryEntries(); @@ -76,26 +60,6 @@ public: return this->FileEntries; } - std::vector> - CompileFileEntries() const; - - std::vector> - CompileDirectoryEntries() const; - - std::vector EvaluateDirectoryEntries( - std::vector> const& cges, - cm::GenEx::Context const& context, cmGeneratorTarget const* target, - cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; - - void EvaluateFileEntry( - std::vector const& dirs, - std::map>& filesPerDir, - std::unique_ptr const& cge, - cm::GenEx::Context const& context, cmGeneratorTarget const* target, - cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; - - static bool IsValidName(std::string const& name); - //! Set/Get a property of this file set void SetProperty(std::string const& prop, cmValue value); void SetProperty(std::string const& prop, std::nullptr_t) @@ -115,12 +79,10 @@ public: cmValue GetProperty(std::string const& prop) const; private: - static cmList KnownTypes; - cmMakefile* Makefile; std::string Name; std::string Type; - Visibility FSVisibility; + cm::FileSetMetadata::Visibility Visibility; std::vector> DirectoryEntries; std::vector> FileEntries; cmPropertyMap Properties; diff --git a/Source/cmFileSetMetadata.cxx b/Source/cmFileSetMetadata.cxx new file mode 100644 index 0000000000..d58c2a382f --- /dev/null +++ b/Source/cmFileSetMetadata.cxx @@ -0,0 +1,102 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#include "cmFileSetMetadata.h" + +#include + +#include +#include + +#include "cmsys/RegularExpression.hxx" + +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +namespace cm { +namespace FileSetMetadata { +cm::string_view VisibilityToName(Visibility vis) +{ + switch (vis) { + case Visibility::Interface: + return "INTERFACE"_s; + case Visibility::Public: + return "PUBLIC"_s; + case Visibility::Private: + return "PRIVATE"_s; + } + return ""_s; +} + +Visibility VisibilityFromName(cm::string_view name, cmMakefile* mf) +{ + if (name == "INTERFACE"_s) { + return Visibility::Interface; + } + if (name == "PUBLIC"_s) { + return Visibility::Public; + } + if (name == "PRIVATE"_s) { + return Visibility::Private; + } + auto msg = cmStrCat("File set visibility \"", name, "\" is not valid."); + if (mf) { + mf->IssueMessage(MessageType::FATAL_ERROR, msg); + } else { + cmSystemTools::Error(msg); + } + return Visibility::Private; +} + +bool VisibilityIsForSelf(Visibility vis) +{ + switch (vis) { + case Visibility::Interface: + return false; + case Visibility::Public: + case Visibility::Private: + return true; + } + return false; +} + +bool VisibilityIsForInterface(Visibility vis) +{ + switch (vis) { + case Visibility::Interface: + case Visibility::Public: + return true; + case Visibility::Private: + return false; + } + return false; +} + +cm::string_view const HEADERS = "HEADERS"_s; +cm::string_view const CXX_MODULES = "CXX_MODULES"_s; + +namespace { +std::vector KnownTypes{ HEADERS, CXX_MODULES }; + +cmsys::RegularExpression const ValidNameRegex("^[a-z0-9][a-zA-Z0-9_]*$"); +} + +std::vector const& GetKnownTypes() +{ + return KnownTypes; +} + +bool IsKnownType(cm::string_view type) +{ + return cm::contains(GetKnownTypes(), type); +} + +bool IsValidName(cm::string_view name) +{ + cmsys::RegularExpressionMatch match; + return ValidNameRegex.find(name.data(), match); +} + +} +} diff --git a/Source/cmFileSetMetadata.h b/Source/cmFileSetMetadata.h new file mode 100644 index 0000000000..042d379baf --- /dev/null +++ b/Source/cmFileSetMetadata.h @@ -0,0 +1,36 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#pragma once + +#include + +#include + +class cmMakefile; + +namespace cm { +namespace FileSetMetadata { +enum class Visibility +{ + Private, + Public, + Interface +}; + +cm::string_view VisibilityToName(Visibility vis); +Visibility VisibilityFromName(cm::string_view name, cmMakefile* mf); + +bool VisibilityIsForSelf(Visibility vis); +bool VisibilityIsForInterface(Visibility vis); + +// Pre-defined FileSet types +extern cm::string_view const HEADERS; +extern cm::string_view const CXX_MODULES; + +std::vector const& GetKnownTypes(); +bool IsKnownType(cm::string_view type); + +// check validity of a user's file set name +bool IsValidName(cm::string_view type); +} +} diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index b938329896..150e0d6adf 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -29,12 +29,12 @@ #include "cmCMakePath.h" #include "cmCMakeString.hxx" #include "cmComputeLinkInformation.h" -#include "cmFileSet.h" #include "cmGenExContext.h" #include "cmGenExEvaluation.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorExpressionEvaluator.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmLinkItem.h" @@ -3582,11 +3582,11 @@ static const struct DeviceLinkNode : public cmGeneratorExpressionNode namespace { bool GetFileSet(std::vector const& parameters, cm::GenEx::Evaluation* eval, - GeneratorExpressionContent const* content, cmFileSet*& fileSet) + GeneratorExpressionContent const* content, + cmGeneratorFileSet const*& fileSet) { auto const& fileSetName = parameters[0]; auto targetName = parameters[1]; - auto* makefile = eval->Context.LG->GetMakefile(); fileSet = nullptr; auto const TARGET = "TARGET:"_s; @@ -3598,7 +3598,11 @@ bool GetFileSet(std::vector const& parameters, cmStrCat("No value provided for the ", TARGET, " option.")); return false; } - auto* target = makefile->FindTargetToUse(targetName); + + cmLocalGenerator const* lg = eval->CurrentTarget + ? eval->CurrentTarget->GetLocalGenerator() + : eval->Context.LG; + auto const* target = lg->FindGeneratorTargetToUse(targetName); if (!target) { reportError(eval, content->GetOriginalExpression(), cmStrCat("Non-existent target: ", targetName)); @@ -3634,7 +3638,7 @@ static const struct FileSetExistsNode : public cmGeneratorExpressionNode return std::string{}; } - cmFileSet* fileSet = nullptr; + cmGeneratorFileSet const* fileSet = nullptr; if (!GetFileSet(parameters, eval, content, fileSet)) { return std::string{}; } @@ -3686,7 +3690,7 @@ static const struct FileSetPropertyNode : public cmGeneratorExpressionNode return std::string{}; } - cmFileSet* fileSet = nullptr; + cmGeneratorFileSet const* fileSet = nullptr; if (!GetFileSet(parameters, eval, content, fileSet)) { return std::string{}; } diff --git a/Source/cmGeneratorFileSet.cxx b/Source/cmGeneratorFileSet.cxx new file mode 100644 index 0000000000..76e041dd7b --- /dev/null +++ b/Source/cmGeneratorFileSet.cxx @@ -0,0 +1,337 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#include "cmGeneratorFileSet.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "cmFileSet.h" +#include "cmGenExContext.h" +#include "cmGeneratorExpression.h" +#include "cmList.h" +#include "cmListFileCache.h" +#include "cmLocalGenerator.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" +#include "cmake.h" + +class cmLinkItem; + +class FileSetPropertyEntry : public cm::TargetPropertyEntry +{ +public: + FileSetPropertyEntry( + std::vector dirs, bool contextSensitiveDirs, + std::unique_ptr const& cge, + cmGeneratorFileSet const* fileSet, cmLinkItem const& item = NoLinkItem) + : cm::TargetPropertyEntry(item) + , BaseDirs(std::move(dirs)) + , ContextSensitiveDirs(contextSensitiveDirs) + , Cge(cge) + , FileSet(fileSet) + { + } + + static std::unique_ptr CreateFileSetEntry( + std::vector dirs, bool contextSensitiveDirs, + std::unique_ptr const& cge, + cmGeneratorFileSet const* fileSet, cmLinkItem const& item = NoLinkItem) + { + return cm::make_unique( + std::move(dirs), contextSensitiveDirs, cge, fileSet, item); + } + + std::string const& Evaluate( + cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget, + cmGeneratorExpressionDAGChecker* dagChecker) const override + { + std::map> filesPerDir; + this->FileSet->EvaluateFileEntry(this->BaseDirs, filesPerDir, this->Cge, + context, headTarget, dagChecker); + + std::vector files; + for (auto const& it : filesPerDir) { + files.insert(files.end(), it.second.begin(), it.second.end()); + } + + this->Value = cmList::to_string(files); + return Value; + } + + cmListFileBacktrace GetBacktrace() const override + { + return this->Cge->GetBacktrace(); + } + + std::string const& GetInput() const override + { + return this->Cge->GetInput(); + } + + bool GetHadContextSensitiveCondition() const override + { + return this->ContextSensitiveDirs || + this->Cge->GetHadContextSensitiveCondition(); + } + +private: + std::vector const BaseDirs; + bool const ContextSensitiveDirs; + std::unique_ptr const& Cge; + cmGeneratorFileSet const* FileSet; + mutable std::string Value; +}; + +// +// Class cmGeneratorFileSet +// +cmGeneratorFileSet::cmGeneratorFileSet(cmFileSet const* fileSet) + : FileSet(fileSet) +{ +} + +std::string const& cmGeneratorFileSet::GetName() const +{ + return this->FileSet->GetName(); +} +std::string const& cmGeneratorFileSet::GetType() const +{ + return this->FileSet->GetType(); +} +cm::FileSetMetadata::Visibility cmGeneratorFileSet::GetVisibility() const +{ + return this->FileSet->GetVisibility(); +} + +bool cmGeneratorFileSet::IsForSelf() const +{ + return this->FileSet->IsForSelf(); +} +bool cmGeneratorFileSet::IsForInterface() const +{ + return this->FileSet->IsForInterface(); +} +bool cmGeneratorFileSet::CanBeIncluded() const +{ + return this->FileSet->CanBeIncluded(); +} + +cmValue cmGeneratorFileSet::GetProperty(std::string const& prop) const +{ + return this->FileSet->GetProperty(prop); +} + +std::vector> const& cmGeneratorFileSet::GetDirectoryEntries() + const +{ + return this->FileSet->GetDirectoryEntries(); +} + +std::vector> const& cmGeneratorFileSet::GetFileEntries() const +{ + return this->FileSet->GetFileEntries(); +} + +std::vector> const& +cmGeneratorFileSet::CompileFileEntries() const +{ + if (this->CompiledFileEntries.empty() && + !this->FileSet->GetFileEntries().empty()) { + for (auto const& entry : this->FileSet->GetFileEntries()) { + for (auto const& ex : cmList{ entry.Value }) { + cmGeneratorExpression ge( + *this->FileSet->GetMakefile()->GetCMakeInstance(), entry.Backtrace); + auto cge = ge.Parse(ex); + this->CompiledFileEntries.push_back(std::move(cge)); + } + } + } + + return this->CompiledFileEntries; +} + +std::vector> const& +cmGeneratorFileSet::CompileDirectoryEntries() const +{ + if (this->CompiledDirectoryEntries.empty() && + !this->FileSet->GetDirectoryEntries().empty()) { + for (auto const& entry : this->FileSet->GetDirectoryEntries()) { + for (auto const& ex : cmList{ entry.Value }) { + cmGeneratorExpression ge( + *this->FileSet->GetMakefile()->GetCMakeInstance(), entry.Backtrace); + auto cge = ge.Parse(ex); + this->CompiledDirectoryEntries.push_back(std::move(cge)); + } + } + } + + return this->CompiledDirectoryEntries; +} + +std::vector cmGeneratorFileSet::EvaluateDirectoryEntries( + std::vector> const& cges, + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker) const +{ + struct DirCacheEntry + { + std::string collapsedDir; + cm::optional fileId; + }; + + std::unordered_map dirCache; + std::vector result; + for (auto const& cge : cges) { + auto entry = cge->Evaluate(context, dagChecker, target); + cmList dirs{ entry }; + for (std::string dir : dirs) { + if (!cmSystemTools::FileIsFullPath(dir)) { + dir = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', dir); + } + + auto dirCacheResult = dirCache.emplace(dir, DirCacheEntry()); + auto& dirCacheEntry = dirCacheResult.first->second; + auto const isNewCacheEntry = dirCacheResult.second; + + if (isNewCacheEntry) { + cmSystemTools::FileId fileId; + auto isFileIdValid = cmSystemTools::GetFileId(dir, fileId); + dirCacheEntry.collapsedDir = cmSystemTools::CollapseFullPath(dir); + dirCacheEntry.fileId = + isFileIdValid ? cm::optional(fileId) : cm::nullopt; + } + + for (auto const& priorDir : result) { + auto priorDirCacheEntry = dirCache.at(priorDir); + bool sameFile = dirCacheEntry.fileId.has_value() && + priorDirCacheEntry.fileId.has_value() && + (*dirCacheEntry.fileId == *priorDirCacheEntry.fileId); + if (!sameFile && + (cmSystemTools::IsSubDirectory(dirCacheEntry.collapsedDir, + priorDirCacheEntry.collapsedDir) || + cmSystemTools::IsSubDirectory(priorDirCacheEntry.collapsedDir, + dirCacheEntry.collapsedDir))) { + context.LG->GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Base directories in file set cannot be subdirectories of each " + "other:\n ", + priorDir, "\n ", dir), + cge->GetBacktrace()); + return {}; + } + } + result.push_back(dir); + } + } + return result; +} + +void cmGeneratorFileSet::EvaluateFileEntry( + std::vector const& dirs, + std::map>& filesPerDir, + std::unique_ptr const& cge, + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker) const +{ + auto files = cge->Evaluate(context, dagChecker, target); + for (std::string file : cmList{ files }) { + if (!cmSystemTools::FileIsFullPath(file)) { + file = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', file); + } + auto collapsedFile = cmSystemTools::CollapseFullPath(file); + bool found = false; + std::string relDir; + for (auto const& dir : dirs) { + auto collapsedDir = cmSystemTools::CollapseFullPath(dir); + if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) { + found = true; + relDir = cmSystemTools::GetParentDirectory( + cmSystemTools::RelativePath(collapsedDir, collapsedFile)); + break; + } + } + if (!found) { + std::ostringstream e; + e << "File:\n " << file + << "\nmust be in one of the file set's base directories:"; + for (auto const& dir : dirs) { + e << "\n " << dir; + } + context.LG->GetCMakeInstance()->IssueMessage( + MessageType::FATAL_ERROR, e.str(), cge->GetBacktrace()); + return; + } + + filesPerDir[relDir].push_back(file); + } +} + +namespace { +bool EntryIsContextSensitive( + std::unique_ptr const& cge) +{ + return cge->GetHadContextSensitiveCondition(); +} +} + +std::vector> +cmGeneratorFileSet::GetSources( + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker) const +{ + std::vector> entries; + + auto directories = this->GetDirectories(context, target, dagChecker); + bool contextSensitive = directories.second; + + for (auto const& entry : this->CompileFileEntries()) { + auto propEntry = FileSetPropertyEntry::CreateFileSetEntry( + directories.first, contextSensitive, entry, this); + entries.push_back(std::move(propEntry)); + } + + return entries; +} + +std::pair, bool> cmGeneratorFileSet::GetDirectories( + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker) const +{ + auto const& directoryEntries = this->CompileDirectoryEntries(); + auto directories = this->EvaluateDirectoryEntries(directoryEntries, context, + target, dagChecker); + bool contextSensitive = std::any_of( + directoryEntries.begin(), directoryEntries.end(), EntryIsContextSensitive); + + return std::make_pair(std::move(directories), contextSensitive); +} + +std::pair>, bool> +cmGeneratorFileSet::GetFiles(cm::GenEx::Context const& context, + cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker) const +{ + auto directories = this->GetDirectories(context, target, dagChecker); + + auto const& fileEntries = this->CompileFileEntries(); + std::map> files; + for (auto const& entry : fileEntries) { + this->EvaluateFileEntry(directories.first, files, entry, context, target, + dagChecker); + } + bool contextSensitive = directories.second || + std::any_of(fileEntries.begin(), fileEntries.end(), + EntryIsContextSensitive); + + return std::make_pair(std::move(files), contextSensitive); +} diff --git a/Source/cmGeneratorFileSet.h b/Source/cmGeneratorFileSet.h new file mode 100644 index 0000000000..76cb9b3c19 --- /dev/null +++ b/Source/cmGeneratorFileSet.h @@ -0,0 +1,100 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include +#include +#include +#include + +#include "cmFileSetMetadata.h" +#include "cmGeneratorExpression.h" +#include "cmTargetPropertyEntry.h" +#include "cmValue.h" + +namespace cm { +namespace GenEx { +struct Context; +} +} + +template +class BT; + +struct cmGeneratorExpressionDAGChecker; + +class cmFileSet; +class cmGeneratorTarget; + +class cmGeneratorFileSet +{ +public: + using TargetPropertyEntry = cm::TargetPropertyEntry; + + cmGeneratorFileSet(cmFileSet const*); + ~cmGeneratorFileSet() = default; + + cmGeneratorFileSet(cmGeneratorFileSet&&) = default; + cmGeneratorFileSet(cmGeneratorFileSet const&) = delete; + cmGeneratorFileSet& operator=(cmGeneratorFileSet const&) = delete; + + std::string const& GetName() const; + std::string const& GetType() const; + cm::FileSetMetadata::Visibility GetVisibility() const; + + bool IsForSelf() const; + bool IsForInterface() const; + bool CanBeIncluded() const; + + cmFileSet const* GetFileSet() const { return this->FileSet; } + + cmValue GetProperty(std::string const& prop) const; + + std::vector> const& GetDirectoryEntries() const; + std::vector> const& GetFileEntries() const; + + std::vector> GetSources( + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; + + // returned value: + // first: list of directories + // second: is context sensitive + std::pair, bool> GetDirectories( + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; + // returned value: + // first: list of files per directory + // second: is context sensitive + std::pair>, bool> GetFiles( + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; + + std::vector> const& + CompileFileEntries() const; + + std::vector> const& + CompileDirectoryEntries() const; + + std::vector EvaluateDirectoryEntries( + std::vector> const& cges, + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; + + void EvaluateFileEntry( + std::vector const& dirs, + std::map>& filesPerDir, + std::unique_ptr const& cge, + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; + +private: + cmFileSet const* FileSet; + mutable std::vector> + CompiledDirectoryEntries; + mutable std::vector> + CompiledFileEntries; +}; diff --git a/Source/cmGeneratorFileSets.cxx b/Source/cmGeneratorFileSets.cxx new file mode 100644 index 0000000000..01269a07ae --- /dev/null +++ b/Source/cmGeneratorFileSets.cxx @@ -0,0 +1,160 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#include "cmGeneratorFileSets.h" + +#include +#include +#include +#include +#include + +#include + +#include "cmGenExContext.h" +#include "cmGeneratorFileSet.h" +#include "cmGeneratorTarget.h" +#include "cmSourceFile.h" +#include "cmSystemTools.h" +#include "cmTarget.h" + +cmGeneratorFileSets::cmGeneratorFileSets(cmGeneratorTarget* target, + cmLocalGenerator* lg) + : Target(target) + , LocalGenerator(lg) +{ + for (auto const& name : target->Target->GetAllFileSetNames()) { + auto entry = this->FileSets.emplace( + name, + cm::make_unique(target->Target->GetFileSet(name))); + + auto const* fileSet = entry.first->second.get(); + this->AllFileSets.push_back(fileSet); + if (fileSet->IsForSelf()) { + this->SelfFileSets[fileSet->GetType()].push_back(fileSet); + } + if (fileSet->IsForInterface()) { + this->InterfaceFileSets[fileSet->GetType()].push_back(fileSet); + } + } +} +cmGeneratorFileSets::~cmGeneratorFileSets() = default; + +std::vector const& +cmGeneratorFileSets::GetAllFileSets() const +{ + return this->AllFileSets; +} + +namespace { +std::vector NoFileSets; +} + +std::vector const& cmGeneratorFileSets::GetFileSets( + cm::string_view type) const +{ + auto it = this->SelfFileSets.find(type); + if (it != this->SelfFileSets.end()) { + return it->second; + } + return NoFileSets; +} +std::vector const& +cmGeneratorFileSets::GetInterfaceFileSets(cm::string_view type) const +{ + auto it = this->InterfaceFileSets.find(type); + if (it != this->InterfaceFileSets.end()) { + return it->second; + } + return NoFileSets; +} + +cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSet( + std::string const& name) const +{ + auto const it = this->FileSets.find(name); + if (it != this->FileSets.end()) { + return it->second.get(); + } + return nullptr; +} + +cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource( + std::string const& config, std::string const& path) const +{ + this->BuildInfoCache(config); + + auto const& info = this->Configs[config]; + + auto const it = info.FileSetCache.find(path); + if (it == info.FileSetCache.end()) { + return nullptr; + } + return it->second; +} +cmGeneratorFileSet const* cmGeneratorFileSets::GetFileSetForSource( + std::string const& config, cmSourceFile const* sf) const +{ + return this->GetFileSetForSource(config, sf->GetFullPath()); +} + +std::vector> +cmGeneratorFileSets::GetSources( + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker) const +{ + std::vector> entries; + + for (auto const& entry : this->FileSets) { + auto const* fileSet = entry.second.get(); + if (fileSet->IsForSelf()) { + auto sources = fileSet->GetSources(context, target, dagChecker); + std::move(sources.begin(), sources.end(), std::back_inserter(entries)); + } + } + + return entries; +} + +std::vector> +cmGeneratorFileSets::GetSources( + std::string type, cm::GenEx::Context const& context, + cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker) const +{ + std::vector> entries; + + for (auto const& entry : this->FileSets) { + auto const* fileSet = entry.second.get(); + if (!fileSet->IsForSelf() && fileSet->GetType() == type) { + auto sources = fileSet->GetSources(context, target, dagChecker); + std::move(sources.begin(), sources.end(), std::back_inserter(entries)); + } + } + + return entries; +} + +void cmGeneratorFileSets::BuildInfoCache(std::string const& config) const +{ + auto& info = this->Configs[config]; + + if (info.BuiltCache) { + return; + } + + for (auto const& item : this->FileSets) { + cm::GenEx::Context context(this->LocalGenerator, config); + auto const* file_set = item.second.get(); + + auto files = file_set->GetFiles(context, this->Target); + + for (auto const& it : files.first) { + for (auto const& filename : it.second) { + auto collapsedFile = cmSystemTools::CollapseFullPath(filename); + info.FileSetCache[collapsedFile] = file_set; + } + } + } + + info.BuiltCache = true; +} diff --git a/Source/cmGeneratorFileSets.h b/Source/cmGeneratorFileSets.h new file mode 100644 index 0000000000..65398ef0d2 --- /dev/null +++ b/Source/cmGeneratorFileSets.h @@ -0,0 +1,86 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file LICENSE.rst or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include +#include +#include +#include +#include + +#include + +#include "cmTargetPropertyEntry.h" + +namespace cm { +namespace GenEx { +struct Context; +} +} + +struct cmGeneratorExpressionDAGChecker; + +class cmSourceFile; +class cmGeneratorTarget; +class cmGeneratorFileSet; +class cmLocalGenerator; + +class cmGeneratorFileSets +{ +public: + using TargetPropertyEntry = cm::TargetPropertyEntry; + + cmGeneratorFileSets(cmGeneratorTarget* target, cmLocalGenerator* lg); + ~cmGeneratorFileSets(); + + cmGeneratorFileSets(cmGeneratorFileSets const&) = delete; + cmGeneratorFileSets& operator=(cmGeneratorFileSets const&) = delete; + + bool Empty() const { return this->FileSets.empty(); } + + std::vector const& GetAllFileSets() const; + std::vector const& GetFileSets( + cm::string_view type) const; + std::vector const& GetInterfaceFileSets( + cm::string_view type) const; + + cmGeneratorFileSet const* GetFileSet(std::string const& name) const; + + cmGeneratorFileSet const* GetFileSetForSource(std::string const& config, + std::string const& file) const; + cmGeneratorFileSet const* GetFileSetForSource(std::string const& config, + cmSourceFile const* sf) const; + + std::vector> GetSources( + cm::GenEx::Context const& context, cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; + std::vector> GetSources( + std::string type, cm::GenEx::Context const& context, + cmGeneratorTarget const* target, + cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const; + +private: + // file sets indexed by name + std::map> FileSets; + std::vector AllFileSets; + // list of private file sets indexed by type + std::unordered_map> + SelfFileSets; + // list of interface file sets indexed by type + std::unordered_map> + InterfaceFileSets; + + struct InfoByConfig + { + bool BuiltCache = false; + std::map FileSetCache; + }; + mutable std::map Configs; + + void BuildInfoCache(std::string const& config) const; + + cmGeneratorTarget* Target; + cmLocalGenerator* LocalGenerator; +}; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 61c35b2741..a8018a96ac 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -28,11 +28,14 @@ #include "cmCxxModuleUsageEffects.h" #include "cmExperimental.h" #include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmFileTimes.h" #include "cmGenExContext.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionDAGChecker.h" +#include "cmGeneratorFileSet.h" +#include "cmGeneratorFileSets.h" #include "cmGeneratorOptions.h" #include "cmGlobalGenerator.h" #include "cmList.h" @@ -90,6 +93,7 @@ static void CreatePropertyGeneratorExpressions( cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) : Target(t) + , FileSets(cm::make_unique(this, lg)) { this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = lg; @@ -1122,8 +1126,8 @@ bool cmGeneratorTarget::IsInBuildSystem() const // An INTERFACE library is in the build system if it has SOURCES // or C++ module filesets. if (!this->SourceEntries.empty() || - !this->Target->GetFileSetsEntries(cmFileSet::HEADERS).empty() || - !this->Target->GetFileSetsEntries(cmFileSet::CXX_MODULES).empty()) { + !this->GetFileSets(cm::FileSetMetadata::HEADERS).empty() || + !this->GetFileSets(cm::FileSetMetadata::CXX_MODULES).empty()) { return true; } break; @@ -2342,7 +2346,7 @@ cmGeneratorTarget::GetClassifiedFlagsForSource(cmSourceFile const* sf, std::string bmiFlags; auto const* fs = this->GetFileSetForSource(config, sf); - if (fs && fs->GetType() == cmFileSet::CXX_MODULES) { + if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) { if (lang != "CXX"_s) { mf->IssueMessage( MessageType::FATAL_ERROR, @@ -5369,21 +5373,13 @@ bool cmGeneratorTarget::DiscoverSyntheticTargets( // Copy file sets. { - auto fsNames = model->GetAllFileSetNames(); - for (auto const& fsName : fsNames) { - auto const* fs = model->GetFileSet(fsName); - if (!fs) { - mf->IssueMessage(MessageType::INTERNAL_ERROR, - cmStrCat("Failed to find file set named '", - fsName, "' on target '", tgt->GetName(), - '\'')); - continue; - } - auto* newFs = tgt - ->GetOrCreateFileSet(fs->GetName(), fs->GetType(), - fs->GetVisibility()) - .first; - newFs->CopyEntries(fs); + for (auto const* gfs : gt->GetAllFileSets()) { + auto* newFs = + tgt + ->GetOrCreateFileSet(gfs->GetName(), gfs->GetType(), + cm::FileSetMetadata::Visibility::Public) + .first; + newFs->CopyEntries(gfs->GetFileSet()); } } @@ -5782,16 +5778,14 @@ bool cmGeneratorTarget::AddHeaderSetVerification() allVerifyTargetName, { cmStateEnums::TargetDomain::NATIVE }); auto fileSetEntries = isInterface - ? this->Target->GetInterfaceFileSetsEntries(cmFileSet::HEADERS) - : this->Target->GetFileSetsEntries(cmFileSet::HEADERS); + ? this->GetInterfaceFileSets(cm::FileSetMetadata::HEADERS) + : this->GetFileSets(cm::FileSetMetadata::HEADERS); - std::set fileSets; - for (auto const& entry : fileSetEntries) { - for (auto const& name : cmList{ entry.Value }) { - if (all || verifySet.count(name)) { - fileSets.insert(this->Target->GetFileSet(name)); - verifySet.erase(name); - } + std::set fileSets; + for (auto const& fileSet : fileSetEntries) { + if (all || verifySet.count(fileSet->GetName())) { + fileSets.insert(fileSet); + verifySet.erase(fileSet->GetName()); } } @@ -5828,9 +5822,9 @@ bool cmGeneratorTarget::AddHeaderSetVerification() } cm::optional> languages; - for (auto* fileSet : fileSets) { - auto dirCges = fileSet->CompileDirectoryEntries(); - auto fileCges = fileSet->CompileFileEntries(); + for (auto const* fileSet : fileSets) { + auto const& dirCges = fileSet->CompileDirectoryEntries(); + auto const& fileCges = fileSet->CompileFileEntries(); static auto const contextSensitive = [](std::unique_ptr const& cge) { @@ -6143,28 +6137,14 @@ bool cmGeneratorTarget::HaveFortranSources() const return have_direct || have_via_target_objects; } -bool cmGeneratorTarget::HaveCxx20ModuleSources(std::string* errorMessage) const +bool cmGeneratorTarget::HaveCxx20ModuleSources() const { - auto const& fs_names = this->Target->GetAllFileSetNames(); - return std::any_of( - fs_names.begin(), fs_names.end(), - [this, errorMessage](std::string const& name) -> bool { - auto const* file_set = this->Target->GetFileSet(name); - if (!file_set) { - auto message = cmStrCat("Target \"", this->Target->GetName(), - "\" is tracked to have file set \"", name, - "\", but it was not found."); - if (errorMessage) { - *errorMessage = std::move(message); - } else { - this->Makefile->IssueMessage(MessageType::INTERNAL_ERROR, message); - } - return false; - } - - auto const& fs_type = file_set->GetType(); - return fs_type == cmFileSet::CXX_MODULES; - }); + auto const& fileSets = this->GetAllFileSets(); + return std::any_of(fileSets.begin(), fileSets.end(), + [](cmGeneratorFileSet const* file_set) -> bool { + auto const& fs_type = file_set->GetType(); + return fs_type == cm::FileSetMetadata::CXX_MODULES; + }); } cmGeneratorTarget::Cxx20SupportLevel cmGeneratorTarget::HaveCxxModuleSupport( @@ -6306,21 +6286,6 @@ bool cmGeneratorTarget::NeedDyndep(std::string const& lang, return lang == "Fortran"_s || this->NeedCxxModuleSupport(lang, config); } -cmFileSet const* cmGeneratorTarget::GetFileSetForSource( - std::string const& config, cmSourceFile const* sf) const -{ - this->BuildFileSetInfoCache(config); - - auto const& path = sf->GetFullPath(); - auto const& per_config = this->Configs[config]; - - auto const fsit = per_config.FileSetCache.find(path); - if (fsit == per_config.FileSetCache.end()) { - return nullptr; - } - return fsit->second; -} - bool cmGeneratorTarget::NeedDyndepForSource(std::string const& lang, std::string const& config, cmSourceFile const* sf) const @@ -6337,7 +6302,7 @@ bool cmGeneratorTarget::NeedDyndepForSource(std::string const& lang, // Any file in `CXX_MODULES` file sets need scanned (it being `CXX` is // enforced elsewhere). auto const* fs = this->GetFileSetForSource(config, sf); - if (fs && fs->GetType() == cmFileSet::CXX_MODULES) { + if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) { return true; } @@ -6395,6 +6360,40 @@ cmGeneratorTarget::CxxModuleSupport cmGeneratorTarget::NeedCxxDyndep( return policyAnswer; } +bool cmGeneratorTarget::HasFileSets() const +{ + return !this->FileSets->Empty(); +} + +std::vector const& +cmGeneratorTarget::GetAllFileSets() const +{ + return this->FileSets->GetAllFileSets(); +} + +std::vector const& cmGeneratorTarget::GetFileSets( + cm::string_view type) const +{ + return this->FileSets->GetFileSets(type); +} +std::vector const& +cmGeneratorTarget::GetInterfaceFileSets(cm::string_view type) const +{ + return this->FileSets->GetInterfaceFileSets(type); +} + +cmGeneratorFileSet const* cmGeneratorTarget::GetFileSet( + std::string const& name) const +{ + return this->FileSets->GetFileSet(name); +} + +cmGeneratorFileSet const* cmGeneratorTarget::GetFileSetForSource( + std::string const& config, cmSourceFile const* sf) const +{ + return this->FileSets->GetFileSetForSource(config, sf); +} + std::string cmGeneratorTarget::BuildDatabasePath( std::string const& lang, std::string const& config) const { @@ -6420,50 +6419,6 @@ std::string cmGeneratorTarget::BuildDatabasePath( "_build_database.json"); } -void cmGeneratorTarget::BuildFileSetInfoCache(std::string const& config) const -{ - auto& per_config = this->Configs[config]; - - if (per_config.BuiltFileSetCache) { - return; - } - - auto const* tgt = this->Target; - - for (auto const& name : tgt->GetAllFileSetNames()) { - auto const* file_set = tgt->GetFileSet(name); - if (!file_set) { - tgt->GetMakefile()->IssueMessage( - MessageType::INTERNAL_ERROR, - cmStrCat("Target \"", tgt->GetName(), - "\" is tracked to have file set \"", name, - "\", but it was not found.")); - continue; - } - - cm::GenEx::Context context(this->LocalGenerator, config); - - auto fileEntries = file_set->CompileFileEntries(); - auto directoryEntries = file_set->CompileDirectoryEntries(); - auto directories = - file_set->EvaluateDirectoryEntries(directoryEntries, context, this); - - std::map> files; - for (auto const& entry : fileEntries) { - file_set->EvaluateFileEntry(directories, files, entry, context, this); - } - - for (auto const& it : files) { - for (auto const& filename : it.second) { - auto collapsedFile = cmSystemTools::CollapseFullPath(filename); - per_config.FileSetCache[collapsedFile] = file_set; - } - } - } - - per_config.BuiltFileSetCache = true; -} - std::string cmGeneratorTarget::GetSwiftModuleName() const { return this->GetPropertyOrDefault("Swift_MODULE_NAME", this->GetName()); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index cf87543a38..818d92393e 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -37,12 +37,11 @@ struct Evaluation; } } -class cmake; enum class cmBuildStep; -class cmCompiledGeneratorExpression; class cmComputeLinkInformation; class cmCustomCommand; -class cmFileSet; +class cmGeneratorFileSets; +class cmGeneratorFileSet; class cmGlobalGenerator; class cmLocalGenerator; class cmMakefile; @@ -1500,6 +1499,18 @@ public: bool HaveFortranSources() const; bool HaveFortranSources(std::string const& config) const; + // File sets support queries + + bool HasFileSets() const; + std::vector const& GetAllFileSets() const; + std::vector const& GetFileSets( + cm::string_view type) const; + std::vector const& GetInterfaceFileSets( + cm::string_view type) const; + cmGeneratorFileSet const* GetFileSet(std::string const& name) const; + cmGeneratorFileSet const* GetFileSetForSource(std::string const& config, + cmSourceFile const* sf) const; + // C++20 module support queries. /** @@ -1507,11 +1518,8 @@ public: * * This will inspect the target itself to see if C++20 module * support is expected to work based on its sources. - * - * If `errorMessage` is given a non-`nullptr`, any error message will be - * stored in it, otherwise the error will be reported directly. */ - bool HaveCxx20ModuleSources(std::string* errorMessage = nullptr) const; + bool HaveCxx20ModuleSources() const; enum class Cxx20SupportLevel { @@ -1524,6 +1532,7 @@ public: // C++20 modules are available and working. Supported, }; + /** * Query whether the target has C++20 module support available (regardless of * whether it is required or not). @@ -1536,8 +1545,6 @@ public: bool NeedCxxModuleSupport(std::string const& lang, std::string const& config) const; bool NeedDyndep(std::string const& lang, std::string const& config) const; - cmFileSet const* GetFileSetForSource(std::string const& config, - cmSourceFile const* sf) const; bool NeedDyndepForSource(std::string const& lang, std::string const& config, cmSourceFile const* sf) const; enum class CxxModuleSupport @@ -1563,16 +1570,14 @@ public: static MsvcCharSet GetMsvcCharSet(std::string const& singleDefine); private: - void BuildFileSetInfoCache(std::string const& config) const; struct InfoByConfig { - bool BuiltFileSetCache = false; - std::map FileSetCache; std::map> SyntheticDeps; std::map SourceFlags; }; mutable std::map Configs; + std::unique_ptr FileSets; bool PchReused = false; mutable bool ComputingPchReuse = false; mutable bool PchReuseCycleDetected = false; diff --git a/Source/cmGeneratorTarget_Sources.cxx b/Source/cmGeneratorTarget_Sources.cxx index b167a731d3..9f31bd4231 100644 --- a/Source/cmGeneratorTarget_Sources.cxx +++ b/Source/cmGeneratorTarget_Sources.cxx @@ -5,6 +5,7 @@ /* clang-format on */ #include +#include #include #include #include @@ -16,15 +17,16 @@ #include #include -#include #include "cmsys/RegularExpression.hxx" #include "cmEvaluatedTargetProperty.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGenExContext.h" #include "cmGeneratorExpression.h" #include "cmGeneratorExpressionDAGChecker.h" +#include "cmGeneratorFileSet.h" +#include "cmGeneratorFileSets.h" #include "cmGlobalGenerator.h" #include "cmLinkItem.h" #include "cmList.h" @@ -80,92 +82,23 @@ void AddObjectEntries(cmGeneratorTarget const* headTarget, } } -void addFileSetEntry(cmGeneratorTarget const* headTarget, - cm::GenEx::Context const& context, - cmGeneratorExpressionDAGChecker* dagChecker, - cmFileSet const* fileSet, - EvaluatedTargetPropertyEntries& entries) -{ - auto dirCges = fileSet->CompileDirectoryEntries(); - auto dirs = fileSet->EvaluateDirectoryEntries(dirCges, context, headTarget, - dagChecker); - bool contextSensitiveDirs = false; - for (auto const& dirCge : dirCges) { - if (dirCge->GetHadContextSensitiveCondition()) { - contextSensitiveDirs = true; - break; - } - } - cmake* cm = headTarget->GetLocalGenerator()->GetCMakeInstance(); - for (auto& entryCge : fileSet->CompileFileEntries()) { - auto targetPropEntry = cm::TargetPropertyEntry::CreateFileSet( - dirs, contextSensitiveDirs, std::move(entryCge), fileSet); - entries.Entries.emplace_back(EvaluateTargetPropertyEntry( - headTarget, context, dagChecker, *targetPropEntry)); - EvaluatedTargetPropertyEntry const& entry = entries.Entries.back(); - for (auto const& file : entry.Values) { - auto* sf = headTarget->Makefile->GetOrCreateSource(file); - if (fileSet->GetType() == cmFileSet::HEADERS) { - sf->SetProperty("HEADER_FILE_ONLY", "TRUE"); - } - -#ifndef CMAKE_BOOTSTRAP - std::string e; - std::string w; - auto path = sf->ResolveFullPath(&e, &w); - if (!w.empty()) { - cm->IssueMessage(MessageType::AUTHOR_WARNING, w, entry.Backtrace); - } - if (path.empty()) { - if (!e.empty()) { - cm->IssueMessage(MessageType::FATAL_ERROR, e, entry.Backtrace); - } - return; - } - bool found = false; - for (auto const& sg : headTarget->Makefile->GetSourceGroups()) { - if (sg->MatchChildrenFiles(path)) { - found = true; - break; - } - } - if (!found) { - if (fileSet->GetType() == cmFileSet::HEADERS) { - headTarget->Makefile->GetOrCreateSourceGroup("Header Files") - ->AddGroupFile(path); - } - } -#endif - } - } -} - void AddFileSetEntries(cmGeneratorTarget const* headTarget, + cmGeneratorFileSets const* fileSets, cm::GenEx::Context const& context, cmGeneratorExpressionDAGChecker* dagChecker, EvaluatedTargetPropertyEntries& entries) { - for (auto const& entry : - headTarget->Target->GetFileSetsEntries(cmFileSet::HEADERS)) { - for (auto const& name : cmList{ entry.Value }) { - auto const* headerSet = headTarget->Target->GetFileSet(name); - addFileSetEntry(headTarget, context, dagChecker, headerSet, entries); - } - } - for (auto const& entry : - headTarget->Target->GetFileSetsEntries(cmFileSet::CXX_MODULES)) { - for (auto const& name : cmList{ entry.Value }) { - auto const* cxxModuleSet = headTarget->Target->GetFileSet(name); - addFileSetEntry(headTarget, context, dagChecker, cxxModuleSet, entries); - } - } + auto sources = fileSets->GetSources(context, headTarget, dagChecker); + entries = + EvaluateTargetPropertyEntries(headTarget, context, dagChecker, sources); } bool processSources(cmGeneratorTarget const* tgt, EvaluatedTargetPropertyEntries& entries, std::vector>& srcs, std::unordered_set& uniqueSrcs, - bool debugSources) + bool debugSources, + std::function postProcess = {}) { cmMakefile* mf = tgt->Target->GetMakefile(); @@ -210,6 +143,10 @@ bool processSources(cmGeneratorTarget const* tgt, return contextDependent; } src = fullPath; + + if (postProcess) { + postProcess(sf); + } } std::string usedSources; for (std::string const& src : entry.Values) { @@ -281,9 +218,33 @@ std::vector> cmGeneratorTarget::GetSourceFilePaths( // Collect this target's file sets. EvaluatedTargetPropertyEntries fileSetEntries; - AddFileSetEntries(this, context, &dagChecker, fileSetEntries); + AddFileSetEntries(this, this->FileSets.get(), context, &dagChecker, + fileSetEntries); + auto processFileSetEntry = [this, &config](cmSourceFile* sf) { + auto const* fileSet = this->GetFileSetForSource(config, sf); + if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) { + sf->SetProperty("HEADER_FILE_ONLY", "TRUE"); + } +#if !defined(CMAKE_BOOTSTRAP) + cmMakefile* mf = this->Target->GetMakefile(); + auto const& path = sf->GetFullPath(); + bool found = false; + for (auto const& sg : mf->GetSourceGroups()) { + if (sg->MatchChildrenFiles(path)) { + found = true; + break; + } + } + if (!found) { + if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) { + mf->GetOrCreateSourceGroup("Header Files")->AddGroupFile(path); + } + } +#endif + }; bool contextDependentFileSets = - processSources(this, fileSetEntries, files, uniqueSrcs, debugSources); + processSources(this, fileSetEntries, files, uniqueSrcs, debugSources, + processFileSetEntry); // Determine if sources are context-dependent or not. if (!contextDependentDirectSources && !contextDependentInterfaceSources && @@ -397,11 +358,11 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, // Compute the kind (classification) of this source file. SourceKind kind; std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); - cmFileSet const* fs = this->GetFileSetForSource(config, sf); + cmGeneratorFileSet const* fs = this->GetFileSetForSource(config, sf); if (sf->GetCustomCommand()) { kind = SourceKindCustomCommand; } else if (!this->Target->IsNormal() && !this->Target->IsImported() && - fs && (fs->GetType() == cmFileSet::CXX_MODULES)) { + fs && (fs->GetType() == cm::FileSetMetadata::CXX_MODULES)) { kind = SourceKindCxxModuleSource; } else if (this->Target->GetType() == cmStateEnums::UTILITY || this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY diff --git a/Source/cmInstallFileSetGenerator.cxx b/Source/cmInstallFileSetGenerator.cxx index 8cf3b67b5b..422bf8cdb6 100644 --- a/Source/cmInstallFileSetGenerator.cxx +++ b/Source/cmInstallFileSetGenerator.cxx @@ -9,11 +9,11 @@ #include #include -#include -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGenExContext.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmInstallType.h" @@ -54,8 +54,7 @@ bool cmInstallFileSetGenerator::Compute(cmLocalGenerator* lg) lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName); } - auto const& target = *this->Target->Target; - this->FileSet = target.GetFileSet(this->FileSetName); + this->FileSet = this->Target->GetFileSet(this->FileSetName); if (!this->FileSet) { // No file set of the given name was ever provided for this target, nothing @@ -63,12 +62,13 @@ bool cmInstallFileSetGenerator::Compute(cmLocalGenerator* lg) return true; } + auto const& target = *this->Target->Target; cmList interfaceFileSetEntries{ target.GetSafeProperty( target.GetInterfaceFileSetsPropertyName(this->FileSet->GetType())) }; if (std::find(interfaceFileSetEntries.begin(), interfaceFileSetEntries.end(), this->FileSetName) != interfaceFileSetEntries.end()) { - if (this->FileSet->GetType() == cmFileSet::HEADERS) { + if (this->FileSet->GetType() == cm::FileSetMetadata::HEADERS) { this->Destination = this->FileSetDestinations.Headers; } else { this->Destination = this->FileSetDestinations.CXXModules; @@ -121,19 +121,7 @@ std::map> cmInstallFileSetGenerator::CalculateFilesPerDir( std::string const& config) const { - std::map> result; - cm::GenEx::Context context(this->LocalGenerator, config); - auto dirCges = this->FileSet->CompileDirectoryEntries(); - auto dirs = - this->FileSet->EvaluateDirectoryEntries(dirCges, context, this->Target); - - auto fileCges = this->FileSet->CompileFileEntries(); - for (auto const& fileCge : fileCges) { - this->FileSet->EvaluateFileEntry(dirs, result, fileCge, context, - this->Target); - } - - return result; + return this->FileSet->GetFiles(context, this->Target).first; } diff --git a/Source/cmInstallFileSetGenerator.h b/Source/cmInstallFileSetGenerator.h index ba30414edc..0972e0c142 100644 --- a/Source/cmInstallFileSetGenerator.h +++ b/Source/cmInstallFileSetGenerator.h @@ -10,7 +10,7 @@ #include "cmInstallGenerator.h" class cmGeneratorTarget; -class cmFileSet; +class cmGeneratorFileSet; class cmListFileBacktrace; class cmLocalGenerator; @@ -38,7 +38,7 @@ public: std::string GetDestination() const { return this->Destination; } bool GetOptional() const { return this->Optional; } std::string GetFileSetName() const { return this->FileSetName; } - cmFileSet const* GetFileSet() const { return this->FileSet; }; + cmGeneratorFileSet const* GetFileSet() const { return this->FileSet; }; cmGeneratorTarget* GetTarget() const { return this->Target; } protected: @@ -48,7 +48,7 @@ protected: private: std::string TargetName; cmLocalGenerator* LocalGenerator; - cmFileSet const* FileSet; + cmGeneratorFileSet const* FileSet; std::string const FileSetName; std::string const FilePermissions; cmFileSetDestinations FileSetDestinations; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index b773d9dafe..949f48c2f3 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -24,10 +24,11 @@ #include "cmComputeLinkInformation.h" #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGenExContext.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorOptions.h" #include "cmGeneratorTarget.h" #include "cmGlobalUnixMakefileGenerator3.h" @@ -347,28 +348,8 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() std::map file_set_map; auto const* tgt = this->GeneratorTarget->Target; - for (auto const& name : tgt->GetAllFileSetNames()) { - auto const* file_set = tgt->GetFileSet(name); - if (!file_set) { - this->Makefile->IssueMessage( - MessageType::INTERNAL_ERROR, - cmStrCat("Target \"", tgt->GetName(), - "\" is tracked to have file set \"", name, - "\", but it was not found.")); - continue; - } - - auto fileEntries = file_set->CompileFileEntries(); - auto directoryEntries = file_set->CompileDirectoryEntries(); - auto directories = file_set->EvaluateDirectoryEntries( - directoryEntries, context, this->GeneratorTarget); - - std::map> files; - for (auto const& entry : fileEntries) { - file_set->EvaluateFileEntry(directories, files, entry, context, - this->GeneratorTarget); - } - + for (auto const* file_set : this->GeneratorTarget->GetAllFileSets()) { + auto files = file_set->GetFiles(context, this->GeneratorTarget).first; for (auto const& it : files) { for (auto const& filename : it.second) { file_set_map[filename] = file_set->GetType(); @@ -394,7 +375,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() auto const it = file_set_map.find(path); if (it != file_set_map.end()) { auto const& file_set_type = it->second; - if (file_set_type == cmFileSet::CXX_MODULES) { + if (file_set_type == cm::FileSetMetadata::CXX_MODULES) { if (sf->GetLanguage() != "CXX"_s) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index c26dc69d11..397b677519 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -27,9 +27,10 @@ #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" #include "cmDyndepCollation.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorOptions.h" #include "cmGeneratorTarget.h" #include "cmGlobalCommonGenerator.h" @@ -254,7 +255,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( } auto const* fs = this->GeneratorTarget->GetFileSetForSource(config, source); - if (fs && fs->GetType() == cmFileSet::CXX_MODULES) { + if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) { if (source->GetLanguage() != "CXX"_s) { this->GetMakefile()->IssueMessage( MessageType::FATAL_ERROR, @@ -1030,7 +1031,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( std::vector ccouts; std::vector ccouts_private; bool usePrivateGeneratedSources = false; - if (this->GeneratorTarget->Target->HasFileSets()) { + if (this->GeneratorTarget->HasFileSets()) { switch (this->GetGeneratorTarget()->GetPolicyStatusCMP0154()) { case cmPolicies::WARN: case cmPolicies::OLD: @@ -1052,13 +1053,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( // Skip over outputs that were already detected. std::advance(it, nPreviousOutputs); while (it != ccouts.end()) { - cmFileSet const* fileset = + cmGeneratorFileSet const* fileset = this->GeneratorTarget->GetFileSetForSource( config, this->Makefile->GetOrCreateGeneratedSource(*it)); - bool isVisible = fileset && - cmFileSet::VisibilityIsForInterface(fileset->GetVisibility()); - bool isIncludeable = - !fileset || cmFileSet::TypeCanBeIncluded(fileset->GetType()); + bool isVisible = fileset && fileset->IsForInterface(); + bool isIncludeable = !fileset || fileset->CanBeIncluded(); if (fileset && isVisible && isIncludeable) { ++it; continue; @@ -1164,12 +1163,12 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( std::vector sources; this->GeneratorTarget->GetSourceFiles(sources, config); for (cmSourceFile const* sf : sources) { - cmFileSet const* fs = + cmGeneratorFileSet const* fs = this->GeneratorTarget->GetFileSetForSource(config, sf); if (!fs) { continue; } - if (fs->GetType() != cmFileSet::CXX_MODULES) { + if (fs->GetType() != cm::FileSetMetadata::CXX_MODULES) { continue; } if (sf->GetLanguage().empty()) { @@ -1177,7 +1176,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( MessageType::FATAL_ERROR, cmStrCat("Target \"", this->GeneratorTarget->GetName(), "\" has source file\n ", sf->GetFullPath(), - "\nin a \"FILE_SET TYPE ", cmFileSet::CXX_MODULES, + "\nin a \"FILE_SET TYPE ", cm::FileSetMetadata::CXX_MODULES, "\" but it is not scheduled for compilation.")); } } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index febe43528b..f0ea224b50 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -21,6 +21,7 @@ #include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmFindPackageStack.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" @@ -98,18 +99,18 @@ cmValue cmTargetPropertyComputer::GetSources(cmTarget const* tgt) namespace { struct FileSetEntries { - FileSetEntries(cm::static_string_view propertyName) + FileSetEntries(cm::string_view propertyName) : PropertyName(propertyName) { } - cm::static_string_view const PropertyName; + cm::string_view const PropertyName; std::vector> Entries; }; struct FileSetType { - FileSetType(cm::static_string_view typeName, + FileSetType(cm::string_view typeName, cm::static_string_view defaultDirectoryProperty, cm::static_string_view defaultPathProperty, cm::static_string_view directoryPrefix, @@ -131,7 +132,7 @@ struct FileSetType { } - cm::static_string_view const TypeName; + cm::string_view const TypeName; cm::static_string_view const DefaultDirectoryProperty; cm::static_string_view const DefaultPathProperty; cm::static_string_view const DirectoryPrefix; @@ -157,7 +158,7 @@ struct FileSetType cmTargetInternals const* impl, std::string const& prop) const; - void AddFileSet(std::string const& name, cmFileSet::Visibility vis, + void AddFileSet(std::string const& name, cm::FileSetMetadata::Visibility vis, cmListFileBacktrace bt); }; @@ -703,19 +704,19 @@ cmTargetInternals::cmTargetInternals() "IMPORTED_CXX_MODULES_COMPILE_FEATURES"_s) , ImportedCxxModulesCompileOptions("IMPORTED_CXX_MODULES_COMPILE_OPTIONS"_s) , ImportedCxxModulesLinkLibraries("IMPORTED_CXX_MODULES_LINK_LIBRARIES"_s) - , FileSetTypes{ - { cmFileSet::HEADERS, - { cmFileSet::HEADERS, "HEADER_DIRS"_s, "HEADER_SET"_s, "HEADER_DIRS_"_s, - "HEADER_SET_"_s, "Header"_s, "The default header set"_s, - "Header set"_s, FileSetEntries{ "HEADER_SETS"_s }, - FileSetEntries{ "INTERFACE_HEADER_SETS"_s } } }, - { cmFileSet::CXX_MODULES, - { cmFileSet::CXX_MODULES, "CXX_MODULE_DIRS"_s, "CXX_MODULE_SET"_s, - "CXX_MODULE_DIRS_"_s, "CXX_MODULE_SET_"_s, "C++ module"_s, - "The default C++ module set"_s, "C++ module set"_s, - FileSetEntries{ "CXX_MODULE_SETS"_s }, - FileSetEntries{ "INTERFACE_CXX_MODULE_SETS"_s } } } - } + , FileSetTypes{ { cm::FileSetMetadata::HEADERS, + { cm::FileSetMetadata::HEADERS, "HEADER_DIRS"_s, + "HEADER_SET"_s, "HEADER_DIRS_"_s, "HEADER_SET_"_s, + "Header"_s, "The default header set"_s, "Header set"_s, + FileSetEntries{ "HEADER_SETS"_s }, + FileSetEntries{ "INTERFACE_HEADER_SETS"_s } } }, + { cm::FileSetMetadata::CXX_MODULES, + { cm::FileSetMetadata::CXX_MODULES, "CXX_MODULE_DIRS"_s, + "CXX_MODULE_SET"_s, "CXX_MODULE_DIRS_"_s, + "CXX_MODULE_SET_"_s, "C++ module"_s, + "The default C++ module set"_s, "C++ module set"_s, + FileSetEntries{ "CXX_MODULE_SETS"_s }, + FileSetEntries{ "INTERFACE_CXX_MODULE_SETS"_s } } } } { } @@ -805,12 +806,13 @@ std::pair FileSetType::ReadProperties( } void FileSetType::AddFileSet(std::string const& name, - cmFileSet::Visibility vis, cmListFileBacktrace bt) + cm::FileSetMetadata::Visibility vis, + cmListFileBacktrace bt) { - if (cmFileSet::VisibilityIsForSelf(vis)) { + if (cm::FileSetMetadata::VisibilityIsForSelf(vis)) { this->SelfEntries.Entries.emplace_back(name, bt); } - if (cmFileSet::VisibilityIsForInterface(vis)) { + if (cm::FileSetMetadata::VisibilityIsForInterface(vis)) { this->InterfaceEntries.Entries.emplace_back(name, std::move(bt)); } } @@ -1771,10 +1773,10 @@ void cmTarget::CopyCxxModulesEntries(cmTarget const* tgt) // Copy the C++ module fileset entries from `tgt`'s `INTERFACE` to this // target's `PRIVATE`. - auto& entries = - this->impl->FileSetTypes.at(cmFileSet::CXX_MODULES).SelfEntries.Entries; + auto& entries = this->impl->FileSetTypes.at(cm::FileSetMetadata::CXX_MODULES) + .SelfEntries.Entries; entries.clear(); - entries = tgt->impl->FileSetTypes.at(cmFileSet::CXX_MODULES) + entries = tgt->impl->FileSetTypes.at(cm::FileSetMetadata::CXX_MODULES) .InterfaceEntries.Entries; } @@ -3154,7 +3156,8 @@ cmFileSet* cmTarget::GetFileSet(std::string const& name) } std::pair cmTarget::GetOrCreateFileSet( - std::string const& name, std::string const& type, cmFileSet::Visibility vis) + std::string const& name, std::string const& type, + cm::FileSetMetadata::Visibility vis) { auto result = this->impl->FileSets.emplace( name, cmFileSet(this->GetMakefile(), name, type, vis)); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 6044cf2a9d..24ea5627d4 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -13,9 +13,9 @@ #include #include +#include #include "cmAlgorithms.h" -#include "cmFileSet.h" #include "cmListFileCache.h" #include "cmPolicies.h" #include "cmStateTypes.h" @@ -23,6 +23,12 @@ #include "cmTargetLinkLibraryType.h" #include "cmValue.h" +namespace cm { +namespace FileSetMetadata { +enum class Visibility; +} +} + class cmCustomCommand; class cmFileSet; class cmFindPackageStack; @@ -344,9 +350,9 @@ public: cmFileSet const* GetFileSet(std::string const& name) const; cmFileSet* GetFileSet(std::string const& name); - std::pair GetOrCreateFileSet(std::string const& name, - std::string const& type, - cmFileSet::Visibility vis); + std::pair GetOrCreateFileSet( + std::string const& name, std::string const& type, + cm::FileSetMetadata::Visibility vis); std::vector GetAllFileSetNames() const; std::vector GetAllInterfaceFileSets() const; diff --git a/Source/cmTargetPropertyEntry.cxx b/Source/cmTargetPropertyEntry.cxx index ef88f51e3b..86c2dd2e7e 100644 --- a/Source/cmTargetPropertyEntry.cxx +++ b/Source/cmTargetPropertyEntry.cxx @@ -3,17 +3,13 @@ #include "cmTargetPropertyEntry.h" -#include #include #include -#include #include -#include "cmFileSet.h" #include "cmGeneratorExpression.h" #include "cmLinkItem.h" -#include "cmList.h" #include "cmListFileCache.h" class cmake; @@ -84,63 +80,6 @@ private: std::unique_ptr const ge; }; -class TargetPropertyEntryFileSet : public TargetPropertyEntry -{ -public: - TargetPropertyEntryFileSet( - std::vector dirs, bool contextSensitiveDirs, - std::unique_ptr entryCge, - cmFileSet const* fileSet, cmLinkItem const& item = NoLinkItem) - : TargetPropertyEntry(item) - , BaseDirs(std::move(dirs)) - , ContextSensitiveDirs(contextSensitiveDirs) - , EntryCge(std::move(entryCge)) - , FileSet(fileSet) - { - } - - std::string const& Evaluate( - cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget, - cmGeneratorExpressionDAGChecker* dagChecker) const override - { - std::map> filesPerDir; - this->FileSet->EvaluateFileEntry(this->BaseDirs, filesPerDir, - this->EntryCge, context, headTarget, - dagChecker); - - std::vector files; - for (auto const& it : filesPerDir) { - files.insert(files.end(), it.second.begin(), it.second.end()); - } - - static std::string filesStr; - filesStr = cmList::to_string(files); - return filesStr; - } - - cmListFileBacktrace GetBacktrace() const override - { - return this->EntryCge->GetBacktrace(); - } - - std::string const& GetInput() const override - { - return this->EntryCge->GetInput(); - } - - bool GetHadContextSensitiveCondition() const override - { - return this->ContextSensitiveDirs || - this->EntryCge->GetHadContextSensitiveCondition(); - } - -private: - std::vector const BaseDirs; - bool const ContextSensitiveDirs; - std::unique_ptr const EntryCge; - cmFileSet const* FileSet; -}; - std::unique_ptr TargetPropertyEntry::Create( cmake& cmakeInstance, const BT& propertyValue, bool evaluateForBuildsystem) @@ -158,15 +97,6 @@ std::unique_ptr TargetPropertyEntry::Create( cm::make_unique(propertyValue)); } -std::unique_ptr TargetPropertyEntry::CreateFileSet( - std::vector dirs, bool contextSensitiveDirs, - std::unique_ptr entryCge, - cmFileSet const* fileSet, cmLinkItem const& item) -{ - return cm::make_unique( - std::move(dirs), contextSensitiveDirs, std::move(entryCge), fileSet, item); -} - TargetPropertyEntry::TargetPropertyEntry(cmLinkItem const& item) : LinkItem(item) { diff --git a/Source/cmTargetPropertyEntry.h b/Source/cmTargetPropertyEntry.h index fdb4f26c9d..4f39224ae5 100644 --- a/Source/cmTargetPropertyEntry.h +++ b/Source/cmTargetPropertyEntry.h @@ -10,9 +10,7 @@ class cmLinkItem; class cmake; class cmGeneratorTarget; -class cmFileSet; struct cmGeneratorExpressionDAGChecker; -class cmCompiledGeneratorExpression; namespace cm { namespace GenEx { @@ -32,11 +30,6 @@ public: cmake& cmakeInstance, const BT& propertyValue, bool evaluateForBuildsystem = false); - static std::unique_ptr CreateFileSet( - std::vector dirs, bool contextSensitiveDirs, - std::unique_ptr entryCge, - cmFileSet const* fileSet, cmLinkItem const& item = NoLinkItem); - virtual std::string const& Evaluate( cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget, cmGeneratorExpressionDAGChecker* dagChecker) const = 0; diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index d1eca7db1e..96919a0d5d 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -12,6 +12,7 @@ #include "cmArgumentParser.h" #include "cmArgumentParserTypes.h" #include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGeneratorExpression.h" #include "cmList.h" #include "cmListFileCache.h" @@ -232,17 +233,18 @@ bool TargetSourcesImpl::HandleOneFileSet( return false; } - if (!args.Type.empty() && !cmFileSet::IsKnownType(args.Type)) { - this->SetError(cmStrCat("File set TYPE may only be \"", - cmFileSet::GetKnownTypes().join("\", \""), '"')); + if (!args.Type.empty() && !cm::FileSetMetadata::IsKnownType(args.Type)) { + this->SetError( + cmStrCat("File set TYPE may only be \"", + cmJoin(cm::FileSetMetadata::GetKnownTypes(), "\", \""), '"')); return false; } if (args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z' && - !cmFileSet::IsKnownType(args.FileSet)) { + !cm::FileSetMetadata::IsKnownType(args.FileSet)) { this->SetError( cmStrCat("FILE_SET names starting with a capital letter are reserved " "for built-in file sets and may only be \"", - cmFileSet::GetKnownTypes().join("\", \""), '"')); + cmJoin(cm::FileSetMetadata::GetKnownTypes(), "\", \""), '"')); return false; } if (!args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z' && @@ -254,9 +256,9 @@ bool TargetSourcesImpl::HandleOneFileSet( } bool const isDefault = args.Type == args.FileSet || - (args.Type.empty() && cmFileSet::IsKnownType(args.FileSet)); + (args.Type.empty() && cm::FileSetMetadata::IsKnownType(args.FileSet)); - if (!isDefault && !cmFileSet::IsValidName(args.FileSet)) { + if (!isDefault && !cm::FileSetMetadata::IsValidName(args.FileSet)) { this->SetError("Non-default file set name must contain only letters, " "numbers, and underscores, and must not start with a " "capital letter or underscore"); @@ -264,8 +266,8 @@ bool TargetSourcesImpl::HandleOneFileSet( } std::string type = isDefault ? args.FileSet : args.Type; - cmFileSet::Visibility visibility = - cmFileSet::VisibilityFromName(scope, this->Makefile); + cm::FileSetMetadata::Visibility visibility = + cm::FileSetMetadata::VisibilityFromName(scope, this->Makefile); auto fileSet = this->Target->GetOrCreateFileSet(args.FileSet, type, visibility); @@ -275,12 +277,12 @@ bool TargetSourcesImpl::HandleOneFileSet( return false; } - if (cmFileSet::VisibilityIsForSelf(visibility) && + if (cm::FileSetMetadata::VisibilityIsForSelf(visibility) && this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY && !this->Target->IsImported()) { - if (type == cmFileSet::CXX_MODULES) { + if (type == cm::FileSetMetadata::CXX_MODULES) { this->SetError( - cmStrCat(R"(File set TYPE ")", cmFileSet::CXX_MODULES, + cmStrCat(R"(File set TYPE ")", cm::FileSetMetadata::CXX_MODULES, R"(" may not have "PUBLIC" )" R"(or "PRIVATE" visibility on INTERFACE libraries.)")); return false; @@ -289,11 +291,12 @@ bool TargetSourcesImpl::HandleOneFileSet( // FIXME(https://wg21.link/P3470): This condition can go // away when interface-only module units are a thing. - if (cmFileSet::VisibilityIsForInterface(visibility) && - !cmFileSet::VisibilityIsForSelf(visibility) && + if (cm::FileSetMetadata::VisibilityIsForInterface(visibility) && + !cm::FileSetMetadata::VisibilityIsForSelf(visibility) && !this->Target->IsImported()) { - if (type == cmFileSet::CXX_MODULES) { - this->SetError(cmStrCat(R"(File set TYPE ")", cmFileSet::CXX_MODULES, + if (type == cm::FileSetMetadata::CXX_MODULES) { + this->SetError(cmStrCat(R"(File set TYPE ")", + cm::FileSetMetadata::CXX_MODULES, R"(" may not have "INTERFACE" visibility)")); return false; } @@ -312,10 +315,11 @@ bool TargetSourcesImpl::HandleOneFileSet( } if (visibility != fileSet.first->GetVisibility()) { - this->SetError( - cmStrCat("Scope ", scope, " for file set \"", args.FileSet, - "\" does not match original scope ", - cmFileSet::VisibilityToName(fileSet.first->GetVisibility()))); + this->SetError(cmStrCat("Scope ", scope, " for file set \"", + args.FileSet, + "\" does not match original scope ", + cm::FileSetMetadata::VisibilityToName( + fileSet.first->GetVisibility()))); return false; } } @@ -332,16 +336,16 @@ bool TargetSourcesImpl::HandleOneFileSet( if (!baseDirectories.empty()) { fileSet.first->AddDirectoryEntry( BT(baseDirectories, this->Makefile->GetBacktrace())); - if (type == cmFileSet::HEADERS) { + if (type == cm::FileSetMetadata::HEADERS) { for (auto const& dir : cmList{ baseDirectories }) { auto interfaceDirectoriesGenex = cmStrCat("$'); - if (cmFileSet::VisibilityIsForSelf(visibility)) { + if (cm::FileSetMetadata::VisibilityIsForSelf(visibility)) { this->Target->AppendProperty("INCLUDE_DIRECTORIES", interfaceDirectoriesGenex, this->Makefile->GetBacktrace()); } - if (cmFileSet::VisibilityIsForInterface(visibility)) { + if (cm::FileSetMetadata::VisibilityIsForInterface(visibility)) { this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", interfaceDirectoriesGenex, this->Makefile->GetBacktrace()); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 1ce96600fa..d66f0c3a6f 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -27,9 +27,10 @@ #include "cmCryptoHash.h" #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" -#include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorFileSet.h" #include "cmGeneratorOptions.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -2711,12 +2712,12 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) if (si.Kind == cmGeneratorTarget::SourceKindObjectSource || si.Kind == cmGeneratorTarget::SourceKindUnityBatched) { this->OutputSourceSpecificFlags(e2, si.Source); - } else if (fs && fs->GetType() == cmFileSet::CXX_MODULES) { + } else if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) { this->GeneratorTarget->Makefile->IssueMessage( MessageType::FATAL_ERROR, cmStrCat("Target \"", this->GeneratorTarget->GetName(), "\" has source file\n ", si.Source->GetFullPath(), - "\nin a \"FILE_SET TYPE ", cmFileSet::CXX_MODULES, + "\nin a \"FILE_SET TYPE ", cm::FileSetMetadata::CXX_MODULES, "\" but it is not scheduled for compilation.")); } if (si.Source->GetPropertyAsBool("SKIP_PRECOMPILE_HEADERS")) { @@ -2753,12 +2754,12 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) } this->FinishWritingSource(e2, toolSettings); - } else if (fs && fs->GetType() == cmFileSet::CXX_MODULES) { + } else if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) { this->GeneratorTarget->Makefile->IssueMessage( MessageType::FATAL_ERROR, cmStrCat("Target \"", this->GeneratorTarget->GetName(), "\" has source file\n ", si.Source->GetFullPath(), - "\nin a \"FILE_SET TYPE ", cmFileSet::CXX_MODULES, + "\nin a \"FILE_SET TYPE ", cm::FileSetMetadata::CXX_MODULES, "\" but it is not scheduled for compilation.")); } } @@ -2884,9 +2885,9 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( auto const* fs = this->GeneratorTarget->GetFileSetForSource(config, source); char const* compileAsPerConfig = compileAs; - if (fs && fs->GetType() == cmFileSet::CXX_MODULES) { + if (fs && fs->GetType() == cm::FileSetMetadata::CXX_MODULES) { if (lang == "CXX"_s) { - if (fs->GetType() == cmFileSet::CXX_MODULES) { + if (fs->GetType() == cm::FileSetMetadata::CXX_MODULES) { isCppModule = true; if (shouldScanForModules && this->GlobalGenerator->IsScanDependenciesSupported()) { diff --git a/Tests/CMakeLib/testDebuggerVariablesHelper.cxx b/Tests/CMakeLib/testDebuggerVariablesHelper.cxx index f69e36c774..4f78f18331 100644 --- a/Tests/CMakeLib/testDebuggerVariablesHelper.cxx +++ b/Tests/CMakeLib/testDebuggerVariablesHelper.cxx @@ -18,6 +18,7 @@ #include "cmDebuggerVariablesHelper.h" #include "cmDebuggerVariablesManager.h" #include "cmFileSet.h" +#include "cmFileSetMetadata.h" #include "cmGlobalGenerator.h" #include "cmListFileCache.h" #include "cmMakefile.h" @@ -502,7 +503,7 @@ static bool testCreateFromFileSet() auto dummies = CreateDummies("Foo"); cmFileSet fileSet(dummies.Makefile.get(), "Foo", "HEADERS", - cmFileSet::Visibility::Public); + cm::FileSetMetadata::Visibility::Public); BT directory; directory.Value = "c:/"; fileSet.AddDirectoryEntry(directory); @@ -547,7 +548,7 @@ static bool testCreateFromFileSets() auto dummies = CreateDummies("Foo"); cmFileSet fileSet(dummies.Makefile.get(), "Foo", "HEADERS", - cmFileSet::Visibility::Public); + cm::FileSetMetadata::Visibility::Public); BT directory; directory.Value = "c:/"; fileSet.AddDirectoryEntry(directory); diff --git a/bootstrap b/bootstrap index dc9db3e43b..226270501d 100755 --- a/bootstrap +++ b/bootstrap @@ -360,6 +360,7 @@ CMAKE_CXX_SOURCES="\ cmFileCopier \ cmFileInstaller \ cmFileSet \ + cmFileSetMetadata \ cmFileTime \ cmFileTimeCache \ cmFileTimes \ @@ -385,6 +386,8 @@ CMAKE_CXX_SOURCES="\ cmGeneratorExpressionLexer \ cmGeneratorExpressionNode \ cmGeneratorExpressionParser \ + cmGeneratorFileSet \ + cmGeneratorFileSets \ cmGeneratorTarget \ cmGeneratorTarget_CompatibleInterface \ cmGeneratorTarget_IncludeDirectories \