mirror of
https://github.com/Kitware/CMake.git
synced 2026-11-06 05:16:58 +00:00
$<TARGET_PROPERTY:prop> in the interface compile requirements of a file set read the owner's property, and the result was shared by all consumers. Evaluate with the consumer as head target and the owner as current target, and cache per consumer. Fixes: #28207
644 lines
22 KiB
C++
644 lines
22 KiB
C++
/* 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 <algorithm>
|
|
#include <map>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include <cm/memory>
|
|
#include <cm/optional>
|
|
#include <cm/string_view>
|
|
#include <cmext/string_view>
|
|
|
|
#include "cmAlgorithms.h"
|
|
#include "cmEvaluatedTargetProperty.h"
|
|
#include "cmFileSet.h"
|
|
#include "cmGenExContext.h"
|
|
#include "cmGeneratorExpression.h"
|
|
#include "cmGeneratorExpressionDAGChecker.h"
|
|
#include "cmGeneratorTarget.h"
|
|
#include "cmList.h"
|
|
#include "cmListFileCache.h"
|
|
#include "cmLocalGenerator.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmMessageType.h"
|
|
#include "cmPolicies.h"
|
|
#include "cmStringAlgorithms.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmake.h"
|
|
|
|
class cmLinkItem;
|
|
|
|
namespace {
|
|
class FileSetPropertyEntry : public cm::TargetPropertyEntry
|
|
{
|
|
public:
|
|
FileSetPropertyEntry(
|
|
std::vector<std::string> dirs, bool contextSensitiveDirs,
|
|
std::unique_ptr<cmCompiledGeneratorExpression> 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<cm::TargetPropertyEntry> CreateFileSetEntry(
|
|
std::vector<std::string> dirs, bool contextSensitiveDirs,
|
|
std::unique_ptr<cmCompiledGeneratorExpression> const& cge,
|
|
cmGeneratorFileSet const* fileSet, cmLinkItem const& item = NoLinkItem)
|
|
{
|
|
return cm::make_unique<FileSetPropertyEntry>(
|
|
std::move(dirs), contextSensitiveDirs, cge, fileSet, item);
|
|
}
|
|
|
|
std::string const& Evaluate(
|
|
cm::GenEx::Context const& context, cmGeneratorTarget const* headTarget,
|
|
cmGeneratorExpressionDAGChecker* dagChecker,
|
|
cmGeneratorFileSet const* /*fileSet*/) const override
|
|
{
|
|
std::map<std::string, std::vector<std::string>> filesPerDir;
|
|
this->FileSet->EvaluateFileEntry(this->BaseDirs, filesPerDir, this->Cge,
|
|
context, headTarget, dagChecker);
|
|
|
|
std::vector<std::string> 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<std::string> const BaseDirs;
|
|
bool const ContextSensitiveDirs;
|
|
std::unique_ptr<cmCompiledGeneratorExpression> const& Cge;
|
|
cmGeneratorFileSet const* FileSet;
|
|
mutable std::string Value;
|
|
};
|
|
|
|
void CreatePropertyGeneratorExpressions(
|
|
cmake& cmakeInstance, cmBTStringRange entries,
|
|
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>& items)
|
|
{
|
|
for (auto const& entry : entries) {
|
|
items.emplace_back(
|
|
cm::TargetPropertyEntry::Create(cmakeInstance, entry, false));
|
|
}
|
|
}
|
|
|
|
enum class OptionsParse
|
|
{
|
|
None,
|
|
Shell
|
|
};
|
|
|
|
std::vector<BT<std::string>> ProcessOptions(
|
|
cm::EvaluatedTargetPropertyEntries const& entries,
|
|
OptionsParse parse = OptionsParse::None)
|
|
{
|
|
std::vector<BT<std::string>> options;
|
|
std::unordered_set<std::string> uniqueOptions;
|
|
|
|
for (cm::EvaluatedTargetPropertyEntry const& entry : entries.Entries) {
|
|
for (std::string const& opt : entry.Values) {
|
|
if (uniqueOptions.insert(opt).second) {
|
|
if (parse == OptionsParse::Shell &&
|
|
cmHasLiteralPrefix(opt, "SHELL:")) {
|
|
std::vector<std::string> tmp;
|
|
cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp);
|
|
for (std::string& o : tmp) {
|
|
options.emplace_back(std::move(o), entry.Backtrace);
|
|
}
|
|
} else {
|
|
options.emplace_back(opt, entry.Backtrace);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return options;
|
|
}
|
|
std::vector<BT<std::string>> ProcessIncludes(
|
|
cmGeneratorTarget const* target, std::string const& fileSetName,
|
|
cm::string_view property, cm::EvaluatedTargetPropertyEntries& entries)
|
|
{
|
|
std::vector<BT<std::string>> includes;
|
|
std::unordered_set<std::string> uniqueIncludes;
|
|
|
|
for (cm::EvaluatedTargetPropertyEntry& entry : entries.Entries) {
|
|
for (std::string& include : entry.Values) {
|
|
if (!cmValue::IsOff(include)) {
|
|
cmSystemTools::ConvertToUnixSlashes(include);
|
|
}
|
|
|
|
if (!cmSystemTools::FileIsFullPath(include)) {
|
|
target->GetLocalGenerator()->IssueMessage(
|
|
MessageType::FATAL_ERROR,
|
|
cmStrCat("File set \"", fileSetName, "\" from the target \"",
|
|
target->GetName(), "\" contains relative path in its ",
|
|
property, ":\n \"", include, '"'));
|
|
return includes;
|
|
}
|
|
|
|
if (uniqueIncludes.insert(include).second) {
|
|
includes.emplace_back(include, entry.Backtrace);
|
|
}
|
|
}
|
|
}
|
|
return includes;
|
|
}
|
|
|
|
// The target that interface usage requirements of a file set owned by
|
|
// `owner` are evaluated for when compiling the sources of `consumer`.
|
|
cmGeneratorTarget const* GetUsageRequirementTarget(
|
|
cmGeneratorTarget const* owner, cmGeneratorTarget const* consumer)
|
|
{
|
|
return owner->GetPolicyStatusCMP0228() == cmPolicies::NEW ? consumer : owner;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Class cmGeneratorFileSet
|
|
//
|
|
cmGeneratorFileSet::cmGeneratorFileSet(
|
|
cmGeneratorTarget const* target, cmFileSet const* fileSet,
|
|
cm::FileSetMetadata::FileSetDomain domain)
|
|
: Target(target)
|
|
, FileSet(fileSet)
|
|
, Domain(domain)
|
|
{
|
|
auto& cmake = *target->GetLocalGenerator()->GetCMakeInstance();
|
|
|
|
CreatePropertyGeneratorExpressions(cmake, fileSet->GetIncludeDirectories(),
|
|
this->IncludeDirectories);
|
|
CreatePropertyGeneratorExpressions(cmake,
|
|
fileSet->GetInterfaceIncludeDirectories(),
|
|
this->InterfaceIncludeDirectories);
|
|
|
|
CreatePropertyGeneratorExpressions(cmake, fileSet->GetCompileOptions(),
|
|
this->CompileOptions);
|
|
CreatePropertyGeneratorExpressions(cmake,
|
|
fileSet->GetInterfaceCompileOptions(),
|
|
this->InterfaceCompileOptions);
|
|
|
|
CreatePropertyGeneratorExpressions(cmake, fileSet->GetCompileDefinitions(),
|
|
this->CompileDefinitions);
|
|
CreatePropertyGeneratorExpressions(cmake,
|
|
fileSet->GetInterfaceCompileDefinitions(),
|
|
this->InterfaceCompileDefinitions);
|
|
}
|
|
|
|
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<BT<std::string>> cmGeneratorFileSet::GetIncludeDirectories(
|
|
std::string const& config, std::string const& lang) const
|
|
{
|
|
ConfigAndLanguage cacheKey(config, lang);
|
|
{
|
|
auto it = this->IncludeDirectoriesCache.find(cacheKey);
|
|
if (it != this->IncludeDirectoriesCache.end()) {
|
|
return it->second;
|
|
}
|
|
}
|
|
|
|
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, lang);
|
|
cmGeneratorExpressionDAGChecker dagChecker{
|
|
this->Target, "INCLUDE_DIRECTORIES", nullptr, nullptr, context,
|
|
};
|
|
|
|
cm::EvaluatedTargetPropertyEntries entries =
|
|
cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
|
|
this->IncludeDirectories);
|
|
auto includes = ProcessIncludes(this->Target, this->GetName(),
|
|
"INCLUDE_DIRECTORIES"_s, entries);
|
|
this->IncludeDirectoriesCache.emplace(cacheKey, includes);
|
|
|
|
return includes;
|
|
}
|
|
std::vector<BT<std::string>>
|
|
cmGeneratorFileSet::GetInterfaceIncludeDirectories(
|
|
std::string const& config, std::string const& lang,
|
|
cmGeneratorTarget const* consumer) const
|
|
{
|
|
ConsumerConfigAndLanguage cacheKey(consumer, config, lang);
|
|
{
|
|
auto it = this->InterfaceIncludeDirectoriesCache.find(cacheKey);
|
|
if (it != this->InterfaceIncludeDirectoriesCache.end()) {
|
|
return it->second;
|
|
}
|
|
}
|
|
|
|
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config, lang);
|
|
cmGeneratorExpressionDAGChecker dagChecker{
|
|
this->Target, "INCLUDE_DIRECTORIES", nullptr, nullptr, context,
|
|
};
|
|
|
|
cm::EvaluatedTargetPropertyEntries entries =
|
|
cm::EvaluateTargetPropertyEntries(
|
|
GetUsageRequirementTarget(this->Target, consumer), context, &dagChecker,
|
|
this->InterfaceIncludeDirectories, this);
|
|
auto includes = ProcessIncludes(this->Target, this->GetName(),
|
|
"INTERFACE_INCLUDE_DIRECTORIES"_s, entries);
|
|
this->InterfaceIncludeDirectoriesCache.emplace(cacheKey, includes);
|
|
|
|
return includes;
|
|
}
|
|
|
|
std::vector<BT<std::string>> cmGeneratorFileSet::GetCompileOptions(
|
|
std::string const& config, std::string const& language) const
|
|
{
|
|
ConfigAndLanguage cacheKey(config, language);
|
|
{
|
|
auto it = this->CompileOptionsCache.find(cacheKey);
|
|
if (it != this->CompileOptionsCache.end()) {
|
|
return it->second;
|
|
}
|
|
}
|
|
|
|
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
|
|
language);
|
|
cmGeneratorExpressionDAGChecker dagChecker{
|
|
this->Target, "COMPILE_OPTIONS", nullptr, nullptr, context,
|
|
};
|
|
|
|
cm::EvaluatedTargetPropertyEntries entries =
|
|
cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
|
|
this->CompileOptions);
|
|
auto options = ProcessOptions(entries, OptionsParse::Shell);
|
|
this->CompileOptionsCache.emplace(cacheKey, options);
|
|
|
|
return options;
|
|
}
|
|
std::vector<BT<std::string>> cmGeneratorFileSet::GetInterfaceCompileOptions(
|
|
std::string const& config, std::string const& language,
|
|
cmGeneratorTarget const* consumer) const
|
|
{
|
|
ConsumerConfigAndLanguage cacheKey(consumer, config, language);
|
|
{
|
|
auto it = this->InterfaceCompileOptionsCache.find(cacheKey);
|
|
if (it != this->InterfaceCompileOptionsCache.end()) {
|
|
return it->second;
|
|
}
|
|
}
|
|
|
|
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
|
|
language);
|
|
cmGeneratorExpressionDAGChecker dagChecker{
|
|
this->Target, "COMPILE_OPTIONS", nullptr, nullptr, context,
|
|
};
|
|
|
|
cm::EvaluatedTargetPropertyEntries entries =
|
|
cm::EvaluateTargetPropertyEntries(
|
|
GetUsageRequirementTarget(this->Target, consumer), context, &dagChecker,
|
|
this->InterfaceCompileOptions, this);
|
|
auto options = ProcessOptions(entries, OptionsParse::Shell);
|
|
this->InterfaceCompileOptionsCache.emplace(cacheKey, options);
|
|
|
|
return options;
|
|
}
|
|
|
|
std::vector<BT<std::string>> cmGeneratorFileSet::GetCompileDefinitions(
|
|
std::string const& config, std::string const& language) const
|
|
{
|
|
ConfigAndLanguage cacheKey(config, language);
|
|
{
|
|
auto it = this->CompileDefinitionsCache.find(cacheKey);
|
|
if (it != this->CompileDefinitionsCache.end()) {
|
|
return it->second;
|
|
}
|
|
}
|
|
|
|
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
|
|
language);
|
|
cmGeneratorExpressionDAGChecker dagChecker{
|
|
this->Target, "COMPILE_DEFINITIONS", nullptr, nullptr, context,
|
|
};
|
|
|
|
cm::EvaluatedTargetPropertyEntries entries =
|
|
cm::EvaluateTargetPropertyEntries(this->Target, context, &dagChecker,
|
|
this->CompileDefinitions);
|
|
auto defines = ProcessOptions(entries);
|
|
this->CompileDefinitionsCache.emplace(cacheKey, defines);
|
|
|
|
return defines;
|
|
}
|
|
std::vector<BT<std::string>>
|
|
cmGeneratorFileSet::GetInterfaceCompileDefinitions(
|
|
std::string const& config, std::string const& language,
|
|
cmGeneratorTarget const* consumer) const
|
|
{
|
|
ConsumerConfigAndLanguage cacheKey(consumer, config, language);
|
|
{
|
|
auto it = this->InterfaceCompileDefinitionsCache.find(cacheKey);
|
|
if (it != this->InterfaceCompileDefinitionsCache.end()) {
|
|
return it->second;
|
|
}
|
|
}
|
|
|
|
cm::GenEx::Context context(this->Target->GetLocalGenerator(), config,
|
|
language);
|
|
cmGeneratorExpressionDAGChecker dagChecker{
|
|
this->Target, "COMPILE_DEFINITIONS", nullptr, nullptr, context,
|
|
};
|
|
|
|
cm::EvaluatedTargetPropertyEntries entries =
|
|
cm::EvaluateTargetPropertyEntries(
|
|
GetUsageRequirementTarget(this->Target, consumer), context, &dagChecker,
|
|
this->InterfaceCompileDefinitions, this);
|
|
auto defines = ProcessOptions(entries);
|
|
this->InterfaceCompileDefinitionsCache.emplace(cacheKey, defines);
|
|
|
|
return defines;
|
|
}
|
|
|
|
std::vector<BT<std::string>> const& cmGeneratorFileSet::GetDirectoryEntries()
|
|
const
|
|
{
|
|
return this->FileSet->GetDirectoryEntries();
|
|
}
|
|
|
|
std::vector<BT<std::string>> const& cmGeneratorFileSet::GetFileEntries() const
|
|
{
|
|
return this->FileSet->GetFileEntries();
|
|
}
|
|
|
|
std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const&
|
|
cmGeneratorFileSet::CompileFileEntries() const
|
|
{
|
|
std::unordered_set<std::string> uniqueSrcs;
|
|
|
|
if (this->CompiledFileEntries.empty() &&
|
|
!this->FileSet->GetFileEntries().empty()) {
|
|
for (auto const& entry : this->FileSet->GetFileEntries()) {
|
|
for (auto const& ex : cmList{ entry.Value }) {
|
|
if (uniqueSrcs.insert(ex).second) {
|
|
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<std::unique_ptr<cmCompiledGeneratorExpression>> 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<std::string> cmGeneratorFileSet::EvaluateDirectoryEntries(
|
|
std::vector<std::unique_ptr<cmCompiledGeneratorExpression>> const& cges,
|
|
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
|
|
cmGeneratorExpressionDAGChecker* dagChecker) const
|
|
{
|
|
struct DirCacheEntry
|
|
{
|
|
std::string collapsedDir;
|
|
cm::optional<cmSystemTools::FileId> fileId;
|
|
};
|
|
|
|
std::unordered_map<std::string, DirCacheEntry> dirCache;
|
|
std::vector<std::string> 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(), '/',
|
|
std::move(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<decltype(fileId)>(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<std::string> const& dirs, EvaluateFileEntryFunction handler,
|
|
std::unique_ptr<cmCompiledGeneratorExpression> 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(), '/',
|
|
std::move(file));
|
|
}
|
|
auto collapsedFile = cmSystemTools::CollapseFullPath(file);
|
|
std::string baseDir;
|
|
std::string relPath;
|
|
for (auto const& dir : dirs) {
|
|
auto collapsedDir = cmSystemTools::CollapseFullPath(dir);
|
|
if (cmSystemTools::IsSubDirectory(collapsedFile, collapsedDir)) {
|
|
baseDir = collapsedDir;
|
|
relPath = cmSystemTools::RelativePath(collapsedDir, collapsedFile);
|
|
break;
|
|
}
|
|
}
|
|
if (baseDir.empty()) {
|
|
context.LG->GetCMakeInstance()->IssueMessage(
|
|
MessageType::FATAL_ERROR,
|
|
cmStrCat("File:\n ", file,
|
|
"\nmust be in one of the file set's base directories:",
|
|
cmWrap("\n ", dirs, "", "")),
|
|
cge->GetBacktrace());
|
|
return;
|
|
}
|
|
|
|
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)
|
|
{
|
|
return cge->GetHadContextSensitiveCondition();
|
|
}
|
|
}
|
|
|
|
std::vector<std::unique_ptr<cm::TargetPropertyEntry>>
|
|
cmGeneratorFileSet::GetSources(
|
|
cm::GenEx::Context const& context, cmGeneratorTarget const* target,
|
|
cmGeneratorExpressionDAGChecker* dagChecker) const
|
|
{
|
|
std::vector<std::unique_ptr<TargetPropertyEntry>> 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<std::vector<std::string>, 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<cmGeneratorFileSet::FileMap, 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<std::string, std::vector<std::string>> 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);
|
|
}
|
|
|
|
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);
|
|
}
|