1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-17 07:11:52 +08:00

GenEx: Fix evaluation of LINK_LIBRARIES as custom transitive property

Fix logic from commit b9ee79b8a1 (GenEx: Add support for custom
transitive compile properties, 2024-05-09, v3.30.0-rc1~82^2~1) to more
precisely know when we are computing the link dependency graph.

Issue: #20416
Issue: #26709
This commit is contained in:
Brad King
2025-02-22 07:39:04 -05:00
parent 161f703e76
commit 8b5af40b34
8 changed files with 53 additions and 22 deletions

View File

@@ -21,21 +21,22 @@ cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
cmGeneratorTarget const* target, std::string property, cmGeneratorTarget const* target, std::string property,
GeneratorExpressionContent const* content, GeneratorExpressionContent const* content,
cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG, cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG,
std::string const& contextConfig, cmListFileBacktrace backtrace) std::string const& contextConfig, cmListFileBacktrace backtrace,
ComputingLinkLibraries computingLinkLibraries)
: Parent(parent) : Parent(parent)
, Top(parent ? parent->Top : this) , Top(parent ? parent->Top : this)
, Target(target) , Target(target)
, Property(std::move(property)) , Property(std::move(property))
, Content(content) , Content(content)
, Backtrace(std::move(backtrace)) , Backtrace(std::move(backtrace))
, ComputingLinkLibraries_(computingLinkLibraries)
{ {
if (parent) { if (parent) {
this->TopIsTransitiveProperty = parent->TopIsTransitiveProperty; this->TopIsTransitiveProperty = parent->TopIsTransitiveProperty;
} else { } else {
this->TopIsTransitiveProperty = this->TopIsTransitiveProperty =
this->Target this->Target
->IsTransitiveProperty(this->Property, contextLG, contextConfig, ->IsTransitiveProperty(this->Property, contextLG, contextConfig, this)
this->EvaluatingLinkLibraries())
.has_value(); .has_value();
} }
@@ -193,6 +194,11 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkerLauncher() const
"_LINKER_LAUNCHER"_s; "_LINKER_LAUNCHER"_s;
} }
bool cmGeneratorExpressionDAGChecker::IsComputingLinkLibraries() const
{
return this->Top->ComputingLinkLibraries_ == ComputingLinkLibraries::Yes;
}
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries( bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
cmGeneratorTarget const* tgt, ForGenex genex) const cmGeneratorTarget const* tgt, ForGenex genex) const
{ {

View File

@@ -17,12 +17,19 @@ class cmLocalGenerator;
struct cmGeneratorExpressionDAGChecker struct cmGeneratorExpressionDAGChecker
{ {
enum class ComputingLinkLibraries
{
No,
Yes,
};
cmGeneratorExpressionDAGChecker( cmGeneratorExpressionDAGChecker(
cmGeneratorTarget const* target, std::string property, cmGeneratorTarget const* target, std::string property,
GeneratorExpressionContent const* content, GeneratorExpressionContent const* content,
cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG, cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG,
std::string const& contextConfig, std::string const& contextConfig,
cmListFileBacktrace backtrace = cmListFileBacktrace()); cmListFileBacktrace backtrace = cmListFileBacktrace(),
ComputingLinkLibraries computingLinkLibraries =
ComputingLinkLibraries::No);
enum Result enum Result
{ {
@@ -45,6 +52,11 @@ struct cmGeneratorExpressionDAGChecker
bool EvaluatingLinkOptionsExpression() const; bool EvaluatingLinkOptionsExpression() const;
bool EvaluatingLinkerLauncher() const; bool EvaluatingLinkerLauncher() const;
/** Returns true only when computing the actual link dependency
graph for cmGeneratorTarget::GetLinkImplementationLibraries
or cmGeneratorTarget::GetLinkInterfaceLibraries. */
bool IsComputingLinkLibraries() const;
enum class ForGenex enum class ForGenex
{ {
ANY, ANY,
@@ -78,4 +90,6 @@ private:
bool TransitivePropertiesOnly = false; bool TransitivePropertiesOnly = false;
bool CMP0131 = false; bool CMP0131 = false;
bool TopIsTransitiveProperty = false; bool TopIsTransitiveProperty = false;
ComputingLinkLibraries const ComputingLinkLibraries_ =
ComputingLinkLibraries::No;
}; };

View File

@@ -2957,8 +2957,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
if (cm::optional<cmGeneratorTarget::TransitiveProperty> transitiveProp = if (cm::optional<cmGeneratorTarget::TransitiveProperty> transitiveProp =
target->IsTransitiveProperty(propertyName, context->LG, target->IsTransitiveProperty(propertyName, context->LG,
context->Config, context->Config, dagCheckerParent)) {
evaluatingLinkLibraries)) {
interfacePropertyName = std::string(transitiveProp->InterfaceName); interfacePropertyName = std::string(transitiveProp->InterfaceName);
isInterfaceProperty = transitiveProp->InterfaceName == propertyName; isInterfaceProperty = transitiveProp->InterfaceName == propertyName;
usage = transitiveProp->Usage; usage = transitiveProp->Usage;

View File

@@ -935,7 +935,8 @@ public:
cm::optional<TransitiveProperty> IsTransitiveProperty( cm::optional<TransitiveProperty> IsTransitiveProperty(
cm::string_view prop, cmLocalGenerator const* lg, cm::string_view prop, cmLocalGenerator const* lg,
std::string const& config, bool evaluatingLinkLibraries) const; std::string const& config,
cmGeneratorExpressionDAGChecker const* dagChecker) const;
bool HaveInstallTreeRPATH(const std::string& config) const; bool HaveInstallTreeRPATH(const std::string& config) const;

View File

@@ -565,7 +565,14 @@ void cmGeneratorTarget::ExpandLinkItems(std::string const& prop,
} }
// Keep this logic in sync with ComputeLinkImplementationLibraries. // Keep this logic in sync with ComputeLinkImplementationLibraries.
cmGeneratorExpressionDAGChecker dagChecker{ cmGeneratorExpressionDAGChecker dagChecker{
this, prop, nullptr, nullptr, this->LocalGenerator, config, this,
prop,
nullptr,
nullptr,
this->LocalGenerator,
config,
cmListFileBacktrace(),
cmGeneratorExpressionDAGChecker::ComputingLinkLibraries::Yes,
}; };
// The $<LINK_ONLY> expression may be in a link interface to specify // The $<LINK_ONLY> expression may be in a link interface to specify
// private link dependencies that are otherwise excluded from usage // private link dependencies that are otherwise excluded from usage
@@ -1322,7 +1329,14 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
for (auto const& entry : entryRange) { for (auto const& entry : entryRange) {
// Keep this logic in sync with ExpandLinkItems. // Keep this logic in sync with ExpandLinkItems.
cmGeneratorExpressionDAGChecker dagChecker{ cmGeneratorExpressionDAGChecker dagChecker{
this, "LINK_LIBRARIES", nullptr, nullptr, this->LocalGenerator, config, this,
"LINK_LIBRARIES",
nullptr,
nullptr,
this->LocalGenerator,
config,
cmListFileBacktrace(),
cmGeneratorExpressionDAGChecker::ComputingLinkLibraries::Yes,
}; };
// The $<LINK_ONLY> expression may be used to specify link dependencies // The $<LINK_ONLY> expression may be used to specify link dependencies
// that are otherwise excluded from usage requirements. // that are otherwise excluded from usage requirements.

View File

@@ -183,10 +183,9 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty(
} }
cm::optional<cmGeneratorTarget::TransitiveProperty> cm::optional<cmGeneratorTarget::TransitiveProperty>
cmGeneratorTarget::IsTransitiveProperty(cm::string_view prop, cmGeneratorTarget::IsTransitiveProperty(
cmLocalGenerator const* lg, cm::string_view prop, cmLocalGenerator const* lg, std::string const& config,
std::string const& config, cmGeneratorExpressionDAGChecker const* dagChecker) const
bool evaluatingLinkLibraries) const
{ {
cm::optional<TransitiveProperty> result; cm::optional<TransitiveProperty> result;
static const cm::string_view kINTERFACE_ = "INTERFACE_"_s; static const cm::string_view kINTERFACE_ = "INTERFACE_"_s;
@@ -215,7 +214,7 @@ cmGeneratorTarget::IsTransitiveProperty(cm::string_view prop,
result = TransitiveProperty{ "INTERFACE_COMPILE_DEFINITIONS"_s, result = TransitiveProperty{ "INTERFACE_COMPILE_DEFINITIONS"_s,
UseTo::Compile }; UseTo::Compile };
} }
} else if (!evaluatingLinkLibraries) { } else if (!dagChecker || !dagChecker->IsComputingLinkLibraries()) {
// Honor TRANSITIVE_COMPILE_PROPERTIES and TRANSITIVE_LINK_PROPERTIES // Honor TRANSITIVE_COMPILE_PROPERTIES and TRANSITIVE_LINK_PROPERTIES
// from the link closure when we are not evaluating the closure itself. // from the link closure when we are not evaluating the closure itself.
CustomTransitiveProperties const& ctp = CustomTransitiveProperties const& ctp =

View File

@@ -200,14 +200,12 @@ add_custom_target(check ALL VERBATIM
# / \ # / \
# "static10[iface11];iface11[iface10]" # "static10[iface11];iface11[iface10]"
"$<TARGET_PROPERTY:static10,INTERFACE_LINK_LIBRARIES>" "iface11;iface10" "$<TARGET_PROPERTY:static10,INTERFACE_LINK_LIBRARIES>" "iface11;iface10"
"$<TARGET_PROPERTY:static11,LINK_LIBRARIES>" "static10;iface11;iface11;iface10;iface10" "$<TARGET_PROPERTY:static11,LINK_LIBRARIES>" "static10;iface11;iface11;iface10"
# / / \ \ \___ extra!
# __/ __/ \__ \__________ # __/ __/ \__ \__________
# / / \ \ # / / \ \
# "static11[static10;iface11];static10[iface11;iface11[iface10]]" # "static11[static10;iface11];static10[iface11;iface11[iface10]]"
"$<TARGET_PROPERTY:static11,INTERFACE_LINK_LIBRARIES>" "static10;iface11;iface11;iface10;iface10" "$<TARGET_PROPERTY:static11,INTERFACE_LINK_LIBRARIES>" "static10;iface11;iface11;iface10"
"$<TARGET_PROPERTY:main10,LINK_LIBRARIES>" "static11;static10;static10;iface11;iface11;iface10;iface10;iface11;iface10" "$<TARGET_PROPERTY:main10,LINK_LIBRARIES>" "static11;static10;static10;iface11;iface11;iface10"
# / / | | \ \ \_______\_______\____ extra!
# _______/ _______/ | | \______ \______________ # _______/ _______/ | | \______ \______________
# / / | | \ \ # / / | | \ \
# "main10[static11;static10];static11[static10;iface11;static10[iface11;iface11[iface10]]]" # "main10[static11;static10];static11[static10;iface11;static10[iface11;iface11[iface10]]]"

View File

@@ -47,9 +47,9 @@ iface11 LINK_LIBRARIES: ''
iface11 INTERFACE_LINK_LIBRARIES: 'iface10' iface11 INTERFACE_LINK_LIBRARIES: 'iface10'
static10 LINK_LIBRARIES: 'iface11;iface10' static10 LINK_LIBRARIES: 'iface11;iface10'
static10 INTERFACE_LINK_LIBRARIES: 'iface11;iface10' static10 INTERFACE_LINK_LIBRARIES: 'iface11;iface10'
static11 LINK_LIBRARIES: 'static10;iface11;iface11;iface10;iface10' static11 LINK_LIBRARIES: 'static10;iface11;iface11;iface10'
static11 INTERFACE_LINK_LIBRARIES: 'static10;iface11;iface11;iface10;iface10' static11 INTERFACE_LINK_LIBRARIES: 'static10;iface11;iface11;iface10'
main10 LINK_LIBRARIES: 'static11;static10;static10;iface11;iface11;iface10;iface10;iface11;iface10' main10 LINK_LIBRARIES: 'static11;static10;static10;iface11;iface11;iface10'
main10 INTERFACE_LINK_LIBRARIES: '' main10 INTERFACE_LINK_LIBRARIES: ''
]]) ]])
string(REGEX REPLACE "\r\n" "\n" expect "${expect}") string(REGEX REPLACE "\r\n" "\n" expect "${expect}")