浏览代码

INTERFACE_POSITION_INDEPENDENT_CODE: add generator expressions support

Fixes: #16532
Marc Chevrier 7 年之前
父节点
当前提交
023188ffb4

+ 6 - 0
Help/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE.rst

@@ -14,3 +14,9 @@ undefined, then consumers will determine their
 :prop_tgt:`POSITION_INDEPENDENT_CODE` property by other means.  Consumers
 must ensure that the targets that they link to have a consistent
 requirement for their ``INTERFACE_POSITION_INDEPENDENT_CODE`` property.
+
+Contents of ``INTERFACE_POSITION_INDEPENDENT_CODE`` may use
+"generator expressions" with the syntax ``$<...>``.  See the
+:manual:`cmake-generator-expressions(7)` manual for available expressions.
+See the :manual:`cmake-buildsystem(7)` manual for more on defining buildsystem
+properties.

+ 5 - 0
Help/release/dev/INTERFACE_POSITION_INDEPENDENT_CODE.rst

@@ -0,0 +1,5 @@
+INTERFACE_POSITION_INDEPENDENT_CODE
+-----------------------------------
+
+* :prop_tgt:`INTERFACE_POSITION_INDEPENDENT_CODE` target property gains the
+  support of :manual:`generator expressions <cmake-generator-expressions(7)>`.

+ 12 - 0
Source/cmGeneratorExpressionDAGChecker.cxx

@@ -166,6 +166,18 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingGenexExpression()
   return top->Property == "TARGET_GENEX_EVAL" || top->Property == "GENEX_EVAL";
 }
 
+bool cmGeneratorExpressionDAGChecker::EvaluatingPICExpression()
+{
+  const cmGeneratorExpressionDAGChecker* top = this;
+  const cmGeneratorExpressionDAGChecker* parent = this->Parent;
+  while (parent) {
+    top = parent;
+    parent = parent->Parent;
+  }
+
+  return top->Property == "INTERFACE_POSITION_INDEPENDENT_CODE";
+}
+
 bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(
   cmGeneratorTarget const* tgt)
 {

+ 1 - 0
Source/cmGeneratorExpressionDAGChecker.h

@@ -66,6 +66,7 @@ struct cmGeneratorExpressionDAGChecker
                    const std::string& expr);
 
   bool EvaluatingGenexExpression();
+  bool EvaluatingPICExpression();
   bool EvaluatingLinkLibraries(cmGeneratorTarget const* tgt = nullptr);
 
 #define DECLARE_TRANSITIVE_PROPERTY_METHOD(METHOD) bool METHOD() const;

+ 2 - 1
Source/cmGeneratorExpressionNode.cxx

@@ -1225,7 +1225,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
     const char* prop = target->GetProperty(propertyName);
 
     if (dagCheckerParent) {
-      if (dagCheckerParent->EvaluatingGenexExpression()) {
+      if (dagCheckerParent->EvaluatingGenexExpression() ||
+          dagCheckerParent->EvaluatingPICExpression()) {
         // No check required.
       } else if (dagCheckerParent->EvaluatingLinkLibraries()) {
 #define TRANSITIVE_PROPERTY_COMPARE(PROPERTY)                                 \

+ 28 - 9
Source/cmGeneratorTarget.cxx

@@ -4268,21 +4268,35 @@ std::string compatibilityAgree(CompatibleType t, bool dominant)
 }
 
 template <typename PropertyType>
-PropertyType getTypedProperty(cmGeneratorTarget const* tgt,
-                              const std::string& prop);
+PropertyType getTypedProperty(
+  cmGeneratorTarget const* tgt, const std::string& prop,
+  cmGeneratorExpressionInterpreter* genexInterpreter = nullptr);
 
 template <>
 bool getTypedProperty<bool>(cmGeneratorTarget const* tgt,
-                            const std::string& prop)
+                            const std::string& prop,
+                            cmGeneratorExpressionInterpreter* genexInterpreter)
 {
-  return tgt->GetPropertyAsBool(prop);
+  if (genexInterpreter == nullptr) {
+    return tgt->GetPropertyAsBool(prop);
+  }
+
+  const char* value = tgt->GetProperty(prop);
+  return cmSystemTools::IsOn(genexInterpreter->Evaluate(value, prop));
 }
 
 template <>
-const char* getTypedProperty<const char*>(cmGeneratorTarget const* tgt,
-                                          const std::string& prop)
+const char* getTypedProperty<const char*>(
+  cmGeneratorTarget const* tgt, const std::string& prop,
+  cmGeneratorExpressionInterpreter* genexInterpreter)
 {
-  return tgt->GetProperty(prop);
+  const char* value = tgt->GetProperty(prop);
+
+  if (genexInterpreter == nullptr) {
+    return value;
+  }
+
+  return genexInterpreter->Evaluate(value, prop).c_str();
 }
 
 template <typename PropertyType>
@@ -4423,6 +4437,11 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
   }
 
   std::string interfaceProperty = "INTERFACE_" + p;
+  std::unique_ptr<cmGeneratorExpressionInterpreter> genexInterpreter(
+    p == "POSITION_INDEPENDENT_CODE" ? new cmGeneratorExpressionInterpreter(
+                                         tgt->GetLocalGenerator(), config, tgt)
+                                     : nullptr);
+
   for (cmGeneratorTarget const* theTarget : deps) {
     // An error should be reported if one dependency
     // has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other
@@ -4434,8 +4453,8 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
 
     const bool ifaceIsSet = std::find(propKeys.begin(), propKeys.end(),
                                       interfaceProperty) != propKeys.end();
-    PropertyType ifacePropContent =
-      getTypedProperty<PropertyType>(theTarget, interfaceProperty);
+    PropertyType ifacePropContent = getTypedProperty<PropertyType>(
+      theTarget, interfaceProperty, genexInterpreter.get());
 
     std::string reportEntry;
     if (ifaceIsSet) {

+ 1 - 0
Tests/RunCMake/PositionIndependentCode/Genex1-result.txt

@@ -0,0 +1 @@
+1

+ 3 - 0
Tests/RunCMake/PositionIndependentCode/Genex1-stderr.txt

@@ -0,0 +1,3 @@
+CMake Error: Property POSITION_INDEPENDENT_CODE on target "conflict1" does
+not match the INTERFACE_POSITION_INDEPENDENT_CODE property requirement
+of dependency "genex_pic".

+ 9 - 0
Tests/RunCMake/PositionIndependentCode/Genex1.cmake

@@ -0,0 +1,9 @@
+
+add_library(genex_pic UNKNOWN IMPORTED)
+# PIC is ON if sibling target is a library, OFF if it is an executable
+set_property(TARGET genex_pic PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE $<NOT:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>>)
+
+
+add_library(conflict1 STATIC main.cpp)
+set_property(TARGET conflict1 PROPERTY POSITION_INDEPENDENT_CODE OFF)
+target_link_libraries(conflict1 PRIVATE genex_pic)

+ 1 - 0
Tests/RunCMake/PositionIndependentCode/Genex2-result.txt

@@ -0,0 +1 @@
+1

+ 3 - 0
Tests/RunCMake/PositionIndependentCode/Genex2-stderr.txt

@@ -0,0 +1,3 @@
+CMake Error: Property POSITION_INDEPENDENT_CODE on target "conflict2" does
+not match the INTERFACE_POSITION_INDEPENDENT_CODE property requirement
+of dependency "genex_pic".

+ 9 - 0
Tests/RunCMake/PositionIndependentCode/Genex2.cmake

@@ -0,0 +1,9 @@
+
+add_library(genex_pic UNKNOWN IMPORTED)
+# PIC is ON if sibling target is a library, OFF if it is an executable
+set_property(TARGET genex_pic PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE $<NOT:$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>>)
+
+
+add_executable(conflict2 main.cpp)
+set_property(TARGET conflict2 PROPERTY POSITION_INDEPENDENT_CODE ON)
+target_link_libraries(conflict2 PRIVATE genex_pic)

+ 2 - 0
Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake

@@ -7,3 +7,5 @@ run_cmake(Conflict4)
 run_cmake(Conflict5)
 run_cmake(Conflict6)
 run_cmake(Debug)
+run_cmake(Genex1)
+run_cmake(Genex2)