cmGeneratorFileSet: Support different mappings

The full path of a file in a file set can be broken into groups like
`<base>/[<sub>/]<name>`, where `<base>` is the base directory and
`<name>` is the file name without any directory components. Existing
users evaluate file set files as a mapping from `<rel>` to the full
path. However, CPS export needs files grouped by base directory, and
cares about the composition of `<rel>` and `<name>`. To facilitate
obtaining this information in a more useful form, refactor how we
extract file set files to allow the user to pass a lambda 'handler' for
each file, which has the base directory, full path, and path relative to
the base directory available. (We already obtained `<rel>` from the
latter, so while this technically means the existing use needs to do
additional work, in practice it just means the call to get `<rel>` moves
to the lambda.)

Because there are many existing users that would need to duplicate the
lambda, the old methods are retained as-is, although this does result in
minor code duplication between `GetFiles` (which calls the overload of
`EvaluateFileEntry` which fills the old file map) and `EvaluateFiles`
(which is essentially `GetFiles`, but accepts a user-provided 'handler'
lambda rather than directly producing a file map).
This commit is contained in:
Matthew Woehlke
2026-06-30 15:08:02 -04:00
parent c79c5aea4a
commit 8d229ec702
2 changed files with 61 additions and 16 deletions
+41 -13
View File
@@ -498,8 +498,7 @@ std::vector<std::string> cmGeneratorFileSet::EvaluateDirectoryEntries(
}
void cmGeneratorFileSet::EvaluateFileEntry(
std::vector<std::string> const& dirs,
std::map<std::string, std::vector<std::string>>& filesPerDir,
std::vector<std::string> const& dirs, EvaluateFileEntryFunction handler,
std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
cmGeneratorExpressionDAGChecker* dagChecker) const
@@ -510,18 +509,17 @@ void cmGeneratorFileSet::EvaluateFileEntry(
file = cmStrCat(context.LG->GetCurrentSourceDirectory(), '/', file);
}
auto collapsedFile = cmSystemTools::CollapseFullPath(file);
bool found = false;
std::string relDir;
std::string baseDir;
std::string relPath;
for (auto const& dir : dirs) {
auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) {
found = true;
relDir = cmSystemTools::GetParentDirectory(
cmSystemTools::RelativePath(collapsedDir, collapsedFile));
baseDir = collapsedDir;
relPath = cmSystemTools::RelativePath(collapsedDir, collapsedFile);
break;
}
}
if (!found) {
if (baseDir.empty()) {
std::ostringstream e;
e << "File:\n " << file
<< "\nmust be in one of the file set's base directories:";
@@ -533,10 +531,24 @@ void cmGeneratorFileSet::EvaluateFileEntry(
return;
}
filesPerDir[relDir].push_back(file);
handler(std::move(baseDir), std::move(relPath), std::move(file));
}
}
void cmGeneratorFileSet::EvaluateFileEntry(
std::vector<std::string> const& dirs, FileMap& filesPerDir,
std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
cmGeneratorExpressionDAGChecker* dagChecker) const
{
auto handler = [&filesPerDir](std::string&& /*baseDir*/,
std::string&& relPath, std::string&& file) {
std::string relDir = cmSystemTools::GetParentDirectory(relPath);
filesPerDir[std::move(relDir)].emplace_back(std::move(file));
};
this->EvaluateFileEntry(dirs, handler, cge, context, target, dagChecker);
}
namespace {
bool EntryIsContextSensitive(
std::unique_ptr<cmCompiledGeneratorExpression> const& cge)
@@ -577,10 +589,9 @@ std::pair<std::vector<std::string>, bool> cmGeneratorFileSet::GetDirectories(
return std::make_pair(std::move(directories), contextSensitive);
}
std::pair<std::map<std::string, std::vector<std::string>>, bool>
cmGeneratorFileSet::GetFiles(cm::GenEx::Context const& context,
cmGeneratorTarget const* target,
cmGeneratorExpressionDAGChecker* dagChecker) const
std::pair<cmGeneratorFileSet::FileMap, bool> cmGeneratorFileSet::GetFiles(
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
cmGeneratorExpressionDAGChecker* dagChecker) const
{
auto directories = this->GetDirectories(context, target, dagChecker);
@@ -596,3 +607,20 @@ cmGeneratorFileSet::GetFiles(cm::GenEx::Context const& context,
return std::make_pair(std::move(files), contextSensitive);
}
bool cmGeneratorFileSet::EvaluateFiles(
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
EvaluateFileEntryFunction callback,
cmGeneratorExpressionDAGChecker* dagChecker) const
{
auto directories = this->GetDirectories(context, target, dagChecker);
auto const& fileEntries = this->CompileFileEntries();
for (auto const& entry : fileEntries) {
this->EvaluateFileEntry(directories.first, callback, entry, context,
target, dagChecker);
}
return directories.second ||
std::any_of(fileEntries.begin(), fileEntries.end(),
EntryIsContextSensitive);
}
+20 -3
View File
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <functional>
#include <map>
#include <memory>
#include <string>
@@ -79,6 +80,8 @@ public:
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
using FileMap = std::map<std::string, std::vector<std::string>>;
// returned value:
// first: list of directories
// second: is context sensitive
@@ -88,7 +91,7 @@ public:
// returned value:
// first: list of files per directory
// second: is context sensitive
std::pair<std::map<std::string, std::vector<std::string>>, bool> GetFiles(
std::pair<FileMap, bool> GetFiles(
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
@@ -103,9 +106,23 @@ public:
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
using EvaluateFileEntryFunction =
std::function<void(std::string&&, std::string&&, std::string&&)>;
// returned value: is context sensitive
bool EvaluateFiles(
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
EvaluateFileEntryFunction callback,
cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
void EvaluateFileEntry(
std::vector<std::string> const& dirs,
std::map<std::string, std::vector<std::string>>& filesPerDir,
std::vector<std::string> const& dirs, EvaluateFileEntryFunction handler,
std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;
void EvaluateFileEntry(
std::vector<std::string> const& dirs, FileMap& filesPerDir,
std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
cmGeneratorExpressionDAGChecker* dagChecker = nullptr) const;