cmGeneratorTarget: Factor out EvaluatedTargetProperty infrastructure

Make it available outside the `cmGeneratorTarget` implementation.
In particular, we will later use it in `cmQtAutoGenInitializer`.
This commit is contained in:
Orkun Tokdemir
2023-04-03 16:55:13 +02:00
committed by Brad King
parent 2daba01ddf
commit 7cecb6353e
6 changed files with 253 additions and 189 deletions
+2
View File
@@ -193,6 +193,8 @@ add_library(
cmDyndepCollation.h cmDyndepCollation.h
cmELF.h cmELF.h
cmELF.cxx cmELF.cxx
cmEvaluatedTargetProperty.cxx
cmEvaluatedTargetProperty.h
cmExprParserHelper.cxx cmExprParserHelper.cxx
cmExportBuildAndroidMKGenerator.h cmExportBuildAndroidMKGenerator.h
cmExportBuildAndroidMKGenerator.cxx cmExportBuildAndroidMKGenerator.cxx
+111
View File
@@ -0,0 +1,111 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmEvaluatedTargetProperty.h"
#include <unordered_map>
#include <utility>
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmStringAlgorithms.h"
struct cmGeneratorExpressionDAGChecker;
EvaluatedTargetPropertyEntry::EvaluatedTargetPropertyEntry(
cmLinkImplItem const& item, cmListFileBacktrace bt)
: LinkImplItem(item)
, Backtrace(std::move(bt))
{
}
EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
cmGeneratorTarget const* thisTarget, std::string const& config,
std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
cmGeneratorTarget::TargetPropertyEntry& entry)
{
EvaluatedTargetPropertyEntry ee(entry.LinkImplItem, entry.GetBacktrace());
cmExpandList(entry.Evaluate(thisTarget->GetLocalGenerator(), config,
thisTarget, dagChecker, lang),
ee.Values);
if (entry.GetHadContextSensitiveCondition()) {
ee.ContextDependent = true;
}
return ee;
}
EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(
cmGeneratorTarget const* thisTarget, std::string const& config,
std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const&
in)
{
EvaluatedTargetPropertyEntries out;
out.Entries.reserve(in.size());
for (auto const& entry : in) {
out.Entries.emplace_back(EvaluateTargetPropertyEntry(
thisTarget, config, lang, dagChecker, *entry));
}
return out;
}
namespace {
void addInterfaceEntry(cmGeneratorTarget const* headTarget,
std::string const& config, std::string const& prop,
std::string const& lang,
cmGeneratorExpressionDAGChecker* dagChecker,
EvaluatedTargetPropertyEntries& entries,
cmGeneratorTarget::LinkInterfaceFor interfaceFor,
std::vector<cmLinkImplItem> const& libraries)
{
for (cmLinkImplItem const& lib : libraries) {
if (lib.Target) {
EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
// Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
// caller's property and hand-evaluate it as if it were compiled.
// Create a context as cmCompiledGeneratorExpression::Evaluate does.
cmGeneratorExpressionContext context(
headTarget->GetLocalGenerator(), config, false, headTarget, headTarget,
true, lib.Backtrace, lang);
cmExpandList(lib.Target->EvaluateInterfaceProperty(
prop, &context, dagChecker, interfaceFor),
ee.Values);
ee.ContextDependent = context.HadContextSensitiveCondition;
entries.Entries.emplace_back(std::move(ee));
}
}
}
}
void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
std::string const& config, std::string const& prop,
std::string const& lang,
cmGeneratorExpressionDAGChecker* dagChecker,
EvaluatedTargetPropertyEntries& entries,
IncludeRuntimeInterface searchRuntime,
cmGeneratorTarget::LinkInterfaceFor interfaceFor)
{
if (searchRuntime == IncludeRuntimeInterface::Yes) {
if (cmLinkImplementation const* impl =
headTarget->GetLinkImplementation(config, interfaceFor)) {
entries.HadContextSensitiveCondition =
impl->HadContextSensitiveCondition;
auto runtimeLibIt = impl->LanguageRuntimeLibraries.find(lang);
if (runtimeLibIt != impl->LanguageRuntimeLibraries.end()) {
addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
interfaceFor, runtimeLibIt->second);
}
addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
interfaceFor, impl->Libraries);
}
} else {
if (cmLinkImplementationLibraries const* impl =
headTarget->GetLinkImplementationLibraries(config, interfaceFor)) {
entries.HadContextSensitiveCondition =
impl->HadContextSensitiveCondition;
addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
interfaceFor, impl->Libraries);
}
}
}
+80
View File
@@ -0,0 +1,80 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "cmGeneratorTarget.h"
#include "cmListFileCache.h"
class cmLinkImplItem;
struct cmGeneratorExpressionDAGChecker;
// Represent a target property entry after evaluating generator expressions
// and splitting up lists.
struct EvaluatedTargetPropertyEntry
{
EvaluatedTargetPropertyEntry(cmLinkImplItem const& item,
cmListFileBacktrace bt);
// Move-only.
EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry&&) = default;
EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry const&) = delete;
EvaluatedTargetPropertyEntry& operator=(EvaluatedTargetPropertyEntry&&) =
delete;
EvaluatedTargetPropertyEntry& operator=(
EvaluatedTargetPropertyEntry const&) = delete;
cmLinkImplItem const& LinkImplItem;
cmListFileBacktrace Backtrace;
std::vector<std::string> Values;
bool ContextDependent = false;
};
EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
cmGeneratorTarget const* thisTarget, std::string const& config,
std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
cmGeneratorTarget::TargetPropertyEntry& entry);
struct EvaluatedTargetPropertyEntries
{
std::vector<EvaluatedTargetPropertyEntry> Entries;
bool HadContextSensitiveCondition = false;
};
EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(
cmGeneratorTarget const* thisTarget, std::string const& config,
std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const&
in);
// IncludeRuntimeInterface is used to break the cycle in computing
// the necessary transitive dependencies of targets that can occur
// now that we have implicit language runtime targets.
//
// To determine the set of languages that a target has we need to iterate
// all the sources which includes transitive INTERFACE sources.
// Therefore we can't determine what language runtimes are needed
// for a target until after all sources are computed.
//
// Therefore while computing the applicable INTERFACE_SOURCES we
// must ignore anything in LanguageRuntimeLibraries or we would
// create a cycle ( INTERFACE_SOURCES requires LanguageRuntimeLibraries,
// LanguageRuntimeLibraries requires INTERFACE_SOURCES).
//
enum class IncludeRuntimeInterface
{
Yes,
No
};
void AddInterfaceEntries(cmGeneratorTarget const* headTarget,
std::string const& config, std::string const& prop,
std::string const& lang,
cmGeneratorExpressionDAGChecker* dagChecker,
EvaluatedTargetPropertyEntries& entries,
IncludeRuntimeInterface searchRuntime,
cmGeneratorTarget::LinkInterfaceFor interfaceFor =
cmGeneratorTarget::LinkInterfaceFor::Usage);
+37 -189
View File
@@ -27,6 +27,7 @@
#include "cmAlgorithms.h" #include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h" #include "cmComputeLinkInformation.h"
#include "cmCustomCommandGenerator.h" #include "cmCustomCommandGenerator.h"
#include "cmEvaluatedTargetProperty.h"
#include "cmFileSet.h" #include "cmFileSet.h"
#include "cmFileTimes.h" #include "cmFileTimes.h"
#include "cmGeneratedFileStream.h" #include "cmGeneratedFileStream.h"
@@ -89,31 +90,38 @@ cmTargetPropertyComputer::ComputeLocation<cmGeneratorTarget>(
return tgt->GetLocation(config); return tgt->GetLocation(config);
} }
class cmGeneratorTarget::TargetPropertyEntry cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
{
protected:
static cmLinkImplItem NoLinkImplItem;
class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry
{
public: public:
TargetPropertyEntry(cmLinkImplItem const& item) TargetPropertyEntryString(BT<std::string> propertyValue,
: LinkImplItem(item) cmLinkImplItem const& item = NoLinkImplItem)
: cmGeneratorTarget::TargetPropertyEntry(item)
, PropertyValue(std::move(propertyValue))
{ {
} }
virtual ~TargetPropertyEntry() = default;
virtual const std::string& Evaluate( const std::string& Evaluate(cmLocalGenerator*, const std::string&,
cmLocalGenerator* lg, const std::string& config, cmGeneratorTarget const*,
cmGeneratorTarget const* headTarget, cmGeneratorExpressionDAGChecker*,
cmGeneratorExpressionDAGChecker* dagChecker, std::string const&) const override
std::string const& language) const = 0; {
return this->PropertyValue.Value;
}
virtual cmListFileBacktrace GetBacktrace() const = 0; cmListFileBacktrace GetBacktrace() const override
virtual std::string const& GetInput() const = 0; {
virtual bool GetHadContextSensitiveCondition() const { return false; } return this->PropertyValue.Backtrace;
}
std::string const& GetInput() const override
{
return this->PropertyValue.Value;
}
cmLinkImplItem const& LinkImplItem; private:
BT<std::string> PropertyValue;
}; };
cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem;
class TargetPropertyEntryGenex : public cmGeneratorTarget::TargetPropertyEntry class TargetPropertyEntryGenex : public cmGeneratorTarget::TargetPropertyEntry
{ {
@@ -150,37 +158,6 @@ private:
const std::unique_ptr<cmCompiledGeneratorExpression> ge; const std::unique_ptr<cmCompiledGeneratorExpression> ge;
}; };
class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry
{
public:
TargetPropertyEntryString(BT<std::string> propertyValue,
cmLinkImplItem const& item = NoLinkImplItem)
: cmGeneratorTarget::TargetPropertyEntry(item)
, PropertyValue(std::move(propertyValue))
{
}
const std::string& Evaluate(cmLocalGenerator*, const std::string&,
cmGeneratorTarget const*,
cmGeneratorExpressionDAGChecker*,
std::string const&) const override
{
return this->PropertyValue.Value;
}
cmListFileBacktrace GetBacktrace() const override
{
return this->PropertyValue.Backtrace;
}
std::string const& GetInput() const override
{
return this->PropertyValue.Value;
}
private:
BT<std::string> PropertyValue;
};
class TargetPropertyEntryFileSet class TargetPropertyEntryFileSet
: public cmGeneratorTarget::TargetPropertyEntry : public cmGeneratorTarget::TargetPropertyEntry
{ {
@@ -263,6 +240,18 @@ std::unique_ptr<
cm::make_unique<TargetPropertyEntryString>(propertyValue)); cm::make_unique<TargetPropertyEntryString>(propertyValue));
} }
cmGeneratorTarget::TargetPropertyEntry::TargetPropertyEntry(
cmLinkImplItem const& item)
: LinkImplItem(item)
{
}
bool cmGeneratorTarget::TargetPropertyEntry::GetHadContextSensitiveCondition()
const
{
return false;
}
static void CreatePropertyGeneratorExpressions( static void CreatePropertyGeneratorExpressions(
cmake& cmakeInstance, cmBTStringRange entries, cmake& cmakeInstance, cmBTStringRange entries,
std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items, std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items,
@@ -274,69 +263,6 @@ static void CreatePropertyGeneratorExpressions(
} }
} }
namespace {
// Represent a target property entry after evaluating generator expressions
// and splitting up lists.
struct EvaluatedTargetPropertyEntry
{
EvaluatedTargetPropertyEntry(cmLinkImplItem const& item,
cmListFileBacktrace bt)
: LinkImplItem(item)
, Backtrace(std::move(bt))
{
}
// Move-only.
EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry&&) = default;
EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry const&) = delete;
EvaluatedTargetPropertyEntry& operator=(EvaluatedTargetPropertyEntry&&) =
delete;
EvaluatedTargetPropertyEntry& operator=(
EvaluatedTargetPropertyEntry const&) = delete;
cmLinkImplItem const& LinkImplItem;
cmListFileBacktrace Backtrace;
std::vector<std::string> Values;
bool ContextDependent = false;
};
EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry(
cmGeneratorTarget const* thisTarget, std::string const& config,
std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
cmGeneratorTarget::TargetPropertyEntry& entry)
{
EvaluatedTargetPropertyEntry ee(entry.LinkImplItem, entry.GetBacktrace());
cmExpandList(entry.Evaluate(thisTarget->GetLocalGenerator(), config,
thisTarget, dagChecker, lang),
ee.Values);
if (entry.GetHadContextSensitiveCondition()) {
ee.ContextDependent = true;
}
return ee;
}
struct EvaluatedTargetPropertyEntries
{
std::vector<EvaluatedTargetPropertyEntry> Entries;
bool HadContextSensitiveCondition = false;
};
EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries(
cmGeneratorTarget const* thisTarget, std::string const& config,
std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker,
std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const&
in)
{
EvaluatedTargetPropertyEntries out;
out.Entries.reserve(in.size());
for (auto const& entry : in) {
out.Entries.emplace_back(EvaluateTargetPropertyEntry(
thisTarget, config, lang, dagChecker, *entry));
}
return out;
}
}
cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg)
: Target(t) : Target(t)
{ {
@@ -1607,84 +1533,6 @@ void AddLangSpecificImplicitIncludeDirectories(
} }
} }
void addInterfaceEntry(cmGeneratorTarget const* headTarget,
std::string const& config, std::string const& prop,
std::string const& lang,
cmGeneratorExpressionDAGChecker* dagChecker,
EvaluatedTargetPropertyEntries& entries,
LinkInterfaceFor interfaceFor,
std::vector<cmLinkImplItem> const& libraries)
{
for (cmLinkImplItem const& lib : libraries) {
if (lib.Target) {
EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
// Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
// caller's property and hand-evaluate it as if it were compiled.
// Create a context as cmCompiledGeneratorExpression::Evaluate does.
cmGeneratorExpressionContext context(
headTarget->GetLocalGenerator(), config, false, headTarget, headTarget,
true, lib.Backtrace, lang);
cmExpandList(lib.Target->EvaluateInterfaceProperty(
prop, &context, dagChecker, interfaceFor),
ee.Values);
ee.ContextDependent = context.HadContextSensitiveCondition;
entries.Entries.emplace_back(std::move(ee));
}
}
}
// IncludeRuntimeInterface is used to break the cycle in computing
// the necessary transitive dependencies of targets that can occur
// now that we have implicit language runtime targets.
//
// To determine the set of languages that a target has we need to iterate
// all the sources which includes transitive INTERFACE sources.
// Therefore we can't determine what language runtimes are needed
// for a target until after all sources are computed.
//
// Therefore while computing the applicable INTERFACE_SOURCES we
// must ignore anything in LanguageRuntimeLibraries or we would
// create a cycle ( INTERFACE_SOURCES requires LanguageRuntimeLibraries,
// LanguageRuntimeLibraries requires INTERFACE_SOURCES).
//
enum class IncludeRuntimeInterface
{
Yes,
No
};
void AddInterfaceEntries(
cmGeneratorTarget const* headTarget, std::string const& config,
std::string const& prop, std::string const& lang,
cmGeneratorExpressionDAGChecker* dagChecker,
EvaluatedTargetPropertyEntries& entries,
IncludeRuntimeInterface searchRuntime,
LinkInterfaceFor interfaceFor = LinkInterfaceFor::Usage)
{
if (searchRuntime == IncludeRuntimeInterface::Yes) {
if (cmLinkImplementation const* impl =
headTarget->GetLinkImplementation(config, interfaceFor)) {
entries.HadContextSensitiveCondition =
impl->HadContextSensitiveCondition;
auto runtimeLibIt = impl->LanguageRuntimeLibraries.find(lang);
if (runtimeLibIt != impl->LanguageRuntimeLibraries.end()) {
addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
interfaceFor, runtimeLibIt->second);
}
addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
interfaceFor, impl->Libraries);
}
} else {
if (cmLinkImplementationLibraries const* impl =
headTarget->GetLinkImplementationLibraries(config, interfaceFor)) {
entries.HadContextSensitiveCondition =
impl->HadContextSensitiveCondition;
addInterfaceEntry(headTarget, config, prop, lang, dagChecker, entries,
interfaceFor, impl->Libraries);
}
}
}
void AddObjectEntries(cmGeneratorTarget const* headTarget, void AddObjectEntries(cmGeneratorTarget const* headTarget,
std::string const& config, std::string const& config,
cmGeneratorExpressionDAGChecker* dagChecker, cmGeneratorExpressionDAGChecker* dagChecker,
+22
View File
@@ -1291,3 +1291,25 @@ private:
}; };
mutable std::map<std::string, InfoByConfig> Configs; mutable std::map<std::string, InfoByConfig> Configs;
}; };
class cmGeneratorTarget::TargetPropertyEntry
{
protected:
static cmLinkImplItem NoLinkImplItem;
public:
TargetPropertyEntry(cmLinkImplItem const& item);
virtual ~TargetPropertyEntry() = default;
virtual const std::string& Evaluate(
cmLocalGenerator* lg, const std::string& config,
cmGeneratorTarget const* headTarget,
cmGeneratorExpressionDAGChecker* dagChecker,
std::string const& language) const = 0;
virtual cmListFileBacktrace GetBacktrace() const = 0;
virtual std::string const& GetInput() const = 0;
virtual bool GetHadContextSensitiveCondition() const;
cmLinkImplItem const& LinkImplItem;
};
+1
View File
@@ -337,6 +337,7 @@ CMAKE_CXX_SOURCES="\
cmELF \ cmELF \
cmEnableLanguageCommand \ cmEnableLanguageCommand \
cmEnableTestingCommand \ cmEnableTestingCommand \
cmEvaluatedTargetProperty \
cmExecProgramCommand \ cmExecProgramCommand \
cmExecuteProcessCommand \ cmExecuteProcessCommand \
cmExpandedCommandArgument \ cmExpandedCommandArgument \