Jelajahi Sumber

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
Brad King 8 bulan lalu
induk
melakukan
8b5af40b34

+ 9 - 3
Source/cmGeneratorExpressionDAGChecker.cxx

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

+ 15 - 1
Source/cmGeneratorExpressionDAGChecker.h

@@ -17,12 +17,19 @@ class cmLocalGenerator;
 
 struct cmGeneratorExpressionDAGChecker
 {
+  enum class ComputingLinkLibraries
+  {
+    No,
+    Yes,
+  };
   cmGeneratorExpressionDAGChecker(
     cmGeneratorTarget const* target, std::string property,
     GeneratorExpressionContent const* content,
     cmGeneratorExpressionDAGChecker* parent, cmLocalGenerator const* contextLG,
     std::string const& contextConfig,
-    cmListFileBacktrace backtrace = cmListFileBacktrace());
+    cmListFileBacktrace backtrace = cmListFileBacktrace(),
+    ComputingLinkLibraries computingLinkLibraries =
+      ComputingLinkLibraries::No);
 
   enum Result
   {
@@ -45,6 +52,11 @@ struct cmGeneratorExpressionDAGChecker
   bool EvaluatingLinkOptionsExpression() 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
   {
     ANY,
@@ -78,4 +90,6 @@ private:
   bool TransitivePropertiesOnly = false;
   bool CMP0131 = false;
   bool TopIsTransitiveProperty = false;
+  ComputingLinkLibraries const ComputingLinkLibraries_ =
+    ComputingLinkLibraries::No;
 };

+ 1 - 2
Source/cmGeneratorExpressionNode.cxx

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

+ 2 - 1
Source/cmGeneratorTarget.h

@@ -935,7 +935,8 @@ public:
 
   cm::optional<TransitiveProperty> IsTransitiveProperty(
     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;
 

+ 16 - 2
Source/cmGeneratorTarget_Link.cxx

@@ -565,7 +565,14 @@ void cmGeneratorTarget::ExpandLinkItems(std::string const& prop,
   }
   // Keep this logic in sync with ComputeLinkImplementationLibraries.
   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
   // private link dependencies that are otherwise excluded from usage
@@ -1322,7 +1329,14 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
   for (auto const& entry : entryRange) {
     // Keep this logic in sync with ExpandLinkItems.
     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
     // that are otherwise excluded from usage requirements.

+ 4 - 5
Source/cmGeneratorTarget_TransitiveProperty.cxx

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

+ 3 - 5
Tests/CustomTransitiveProperties/CMakeLists.txt

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

+ 3 - 3
Tests/CustomTransitiveProperties/check.cmake

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