From 7cecb6353e0018fc2b4d0de83c209c0465b585ce Mon Sep 17 00:00:00 2001 From: Orkun Tokdemir Date: Mon, 3 Apr 2023 16:55:13 +0200 Subject: cmGeneratorTarget: Factor out EvaluatedTargetProperty infrastructure Make it available outside the `cmGeneratorTarget` implementation. In particular, we will later use it in `cmQtAutoGenInitializer`. --- Source/CMakeLists.txt | 2 + Source/cmEvaluatedTargetProperty.cxx | 111 +++++++++++++++++ Source/cmEvaluatedTargetProperty.h | 80 +++++++++++++ Source/cmGeneratorTarget.cxx | 226 ++++++----------------------------- Source/cmGeneratorTarget.h | 22 ++++ bootstrap | 1 + 6 files changed, 253 insertions(+), 189 deletions(-) create mode 100644 Source/cmEvaluatedTargetProperty.cxx create mode 100644 Source/cmEvaluatedTargetProperty.h diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 3ae0bc6..dcc7174 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -193,6 +193,8 @@ add_library( cmDyndepCollation.h cmELF.h cmELF.cxx + cmEvaluatedTargetProperty.cxx + cmEvaluatedTargetProperty.h cmExprParserHelper.cxx cmExportBuildAndroidMKGenerator.h cmExportBuildAndroidMKGenerator.cxx diff --git a/Source/cmEvaluatedTargetProperty.cxx b/Source/cmEvaluatedTargetProperty.cxx new file mode 100644 index 0000000..1173690 --- /dev/null +++ b/Source/cmEvaluatedTargetProperty.cxx @@ -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 +#include + +#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> 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 const& libraries) +{ + for (cmLinkImplItem const& lib : libraries) { + if (lib.Target) { + EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace); + // Pretend $ 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); + } + } +} diff --git a/Source/cmEvaluatedTargetProperty.h b/Source/cmEvaluatedTargetProperty.h new file mode 100644 index 0000000..e413ab0 --- /dev/null +++ b/Source/cmEvaluatedTargetProperty.h @@ -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 +#include +#include + +#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 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 Entries; + bool HadContextSensitiveCondition = false; +}; + +EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries( + cmGeneratorTarget const* thisTarget, std::string const& config, + std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, + std::vector> 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); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 81e95a7..90cddb5 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -27,6 +27,7 @@ #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" +#include "cmEvaluatedTargetProperty.h" #include "cmFileSet.h" #include "cmFileTimes.h" #include "cmGeneratedFileStream.h" @@ -89,31 +90,38 @@ cmTargetPropertyComputer::ComputeLocation( return tgt->GetLocation(config); } -class cmGeneratorTarget::TargetPropertyEntry -{ -protected: - static cmLinkImplItem NoLinkImplItem; +cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem; +class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry +{ public: - TargetPropertyEntry(cmLinkImplItem const& item) - : LinkImplItem(item) + TargetPropertyEntryString(BT propertyValue, + cmLinkImplItem const& item = NoLinkImplItem) + : cmGeneratorTarget::TargetPropertyEntry(item) + , PropertyValue(std::move(propertyValue)) { } - 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; + const std::string& Evaluate(cmLocalGenerator*, const std::string&, + cmGeneratorTarget const*, + cmGeneratorExpressionDAGChecker*, + std::string const&) const override + { + return this->PropertyValue.Value; + } - virtual cmListFileBacktrace GetBacktrace() const = 0; - virtual std::string const& GetInput() const = 0; - virtual bool GetHadContextSensitiveCondition() const { return false; } + cmListFileBacktrace GetBacktrace() const override + { + return this->PropertyValue.Backtrace; + } + std::string const& GetInput() const override + { + return this->PropertyValue.Value; + } - cmLinkImplItem const& LinkImplItem; +private: + BT PropertyValue; }; -cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem; class TargetPropertyEntryGenex : public cmGeneratorTarget::TargetPropertyEntry { @@ -150,37 +158,6 @@ private: const std::unique_ptr ge; }; -class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry -{ -public: - TargetPropertyEntryString(BT 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 PropertyValue; -}; - class TargetPropertyEntryFileSet : public cmGeneratorTarget::TargetPropertyEntry { @@ -263,6 +240,18 @@ std::unique_ptr< cm::make_unique(propertyValue)); } +cmGeneratorTarget::TargetPropertyEntry::TargetPropertyEntry( + cmLinkImplItem const& item) + : LinkImplItem(item) +{ +} + +bool cmGeneratorTarget::TargetPropertyEntry::GetHadContextSensitiveCondition() + const +{ + return false; +} + static void CreatePropertyGeneratorExpressions( cmake& cmakeInstance, cmBTStringRange entries, std::vector>& 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 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 Entries; - bool HadContextSensitiveCondition = false; -}; - -EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries( - cmGeneratorTarget const* thisTarget, std::string const& config, - std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector> 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) : 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 const& libraries) -{ - for (cmLinkImplItem const& lib : libraries) { - if (lib.Target) { - EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace); - // Pretend $ 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, std::string const& config, cmGeneratorExpressionDAGChecker* dagChecker, diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 256ca3b..87227fd 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1291,3 +1291,25 @@ private: }; mutable std::map 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; +}; diff --git a/bootstrap b/bootstrap index 83f4814..88438df 100755 --- a/bootstrap +++ b/bootstrap @@ -337,6 +337,7 @@ CMAKE_CXX_SOURCES="\ cmELF \ cmEnableLanguageCommand \ cmEnableTestingCommand \ + cmEvaluatedTargetProperty \ cmExecProgramCommand \ cmExecuteProcessCommand \ cmExpandedCommandArgument \ -- cgit v0.12