From dee8799d16d8abe11289e6d5fc01e18b285589dd Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Mon, 16 Feb 2026 13:38:39 +0100 Subject: [PATCH] FileSet management: Introduce dedicated classes for generation To manage the generation step, introduce cmGeneratorFileSet and cmGeneratorFileSets classes. These reorganizations of the code are done in preparation of the implementation of SOURCES file set type as well as user's file set types. Issues: #27550, #27383 --- Source/CMakeLists.txt | 6 + Source/cmBuildDatabase.cxx | 7 +- Source/cmCxxModuleMetadata.cxx | 8 +- Source/cmDebuggerVariablesHelper.cxx | 36 +- Source/cmDyndepCollation.cxx | 78 ++-- Source/cmEvaluatedTargetProperty.h | 8 +- Source/cmExportBuildCMakeConfigGenerator.cxx | 85 ++--- Source/cmExportBuildCMakeConfigGenerator.h | 6 +- Source/cmExportCMakeConfigGenerator.cxx | 9 +- Source/cmExportCMakeConfigGenerator.h | 6 +- Source/cmExportFileGenerator.cxx | 4 +- .../cmExportInstallCMakeConfigGenerator.cxx | 55 +-- Source/cmExportInstallCMakeConfigGenerator.h | 6 +- .../cmExportInstallPackageInfoGenerator.cxx | 15 +- Source/cmExportInstallPackageInfoGenerator.h | 5 +- Source/cmExportInstallSbomGenerator.cxx | 9 +- Source/cmExportInstallSbomGenerator.h | 5 +- Source/cmExportTryCompileFileGenerator.cxx | 8 +- Source/cmExportTryCompileFileGenerator.h | 5 +- Source/cmFileAPICodemodel.cxx | 64 +--- Source/cmFileSet.cxx | 236 +----------- Source/cmFileSet.h | 80 ++--- Source/cmFileSetMetadata.cxx | 102 ++++++ Source/cmFileSetMetadata.h | 36 ++ Source/cmGeneratorExpressionNode.cxx | 16 +- Source/cmGeneratorFileSet.cxx | 337 ++++++++++++++++++ Source/cmGeneratorFileSet.h | 100 ++++++ Source/cmGeneratorFileSets.cxx | 160 +++++++++ Source/cmGeneratorFileSets.h | 86 +++++ Source/cmGeneratorTarget.cxx | 177 ++++----- Source/cmGeneratorTarget.h | 29 +- Source/cmGeneratorTarget_Sources.cxx | 123 +++---- Source/cmInstallFileSetGenerator.cxx | 24 +- Source/cmInstallFileSetGenerator.h | 6 +- Source/cmMakefileTargetGenerator.cxx | 29 +- Source/cmNinjaTargetGenerator.cxx | 21 +- Source/cmTarget.cxx | 53 +-- Source/cmTarget.h | 14 +- Source/cmTargetPropertyEntry.cxx | 70 ---- Source/cmTargetPropertyEntry.h | 7 - Source/cmTargetSourcesCommand.cxx | 50 +-- Source/cmVisualStudio10TargetGenerator.cxx | 15 +- .../CMakeLib/testDebuggerVariablesHelper.cxx | 5 +- bootstrap | 3 + 44 files changed, 1265 insertions(+), 939 deletions(-) create mode 100644 Source/cmFileSetMetadata.cxx create mode 100644 Source/cmFileSetMetadata.h create mode 100644 Source/cmGeneratorFileSet.cxx create mode 100644 Source/cmGeneratorFileSet.h create mode 100644 Source/cmGeneratorFileSets.cxx create mode 100644 Source/cmGeneratorFileSets.h 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 \