From 023188ffb48cc35ebab7cabbafefcd6dd31b750d Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Fri, 28 Sep 2018 17:30:22 +0200 Subject: INTERFACE_POSITION_INDEPENDENT_CODE: add generator expressions support Fixes: #16532 --- .../INTERFACE_POSITION_INDEPENDENT_CODE.rst | 6 ++++ .../dev/INTERFACE_POSITION_INDEPENDENT_CODE.rst | 5 +++ Source/cmGeneratorExpressionDAGChecker.cxx | 12 +++++++ Source/cmGeneratorExpressionDAGChecker.h | 1 + Source/cmGeneratorExpressionNode.cxx | 3 +- Source/cmGeneratorTarget.cxx | 37 ++++++++++++++++------ .../PositionIndependentCode/Genex1-result.txt | 1 + .../PositionIndependentCode/Genex1-stderr.txt | 3 ++ .../RunCMake/PositionIndependentCode/Genex1.cmake | 9 ++++++ .../PositionIndependentCode/Genex2-result.txt | 1 + .../PositionIndependentCode/Genex2-stderr.txt | 3 ++ .../RunCMake/PositionIndependentCode/Genex2.cmake | 9 ++++++ .../PositionIndependentCode/RunCMakeTest.cmake | 2 ++ 13 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 Help/release/dev/INTERFACE_POSITION_INDEPENDENT_CODE.rst create mode 100644 Tests/RunCMake/PositionIndependentCode/Genex1-result.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Genex1-stderr.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Genex1.cmake create mode 100644 Tests/RunCMake/PositionIndependentCode/Genex2-result.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Genex2-stderr.txt create mode 100644 Tests/RunCMake/PositionIndependentCode/Genex2.cmake diff --git a/Help/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE.rst b/Help/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE.rst index ea700df..4336d71 100644 --- a/Help/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE.rst +++ b/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. diff --git a/Help/release/dev/INTERFACE_POSITION_INDEPENDENT_CODE.rst b/Help/release/dev/INTERFACE_POSITION_INDEPENDENT_CODE.rst new file mode 100644 index 0000000..7732ff6 --- /dev/null +++ b/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 `. diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 8d57441..56eb2bf 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/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) { diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index a5134c3..1525c39 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/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; diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index f901215..49b97fb 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/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) \ diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 1663400..a278a7f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -4268,21 +4268,35 @@ std::string compatibilityAgree(CompatibleType t, bool dominant) } template -PropertyType getTypedProperty(cmGeneratorTarget const* tgt, - const std::string& prop); +PropertyType getTypedProperty( + cmGeneratorTarget const* tgt, const std::string& prop, + cmGeneratorExpressionInterpreter* genexInterpreter = nullptr); template <> bool getTypedProperty(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(cmGeneratorTarget const* tgt, - const std::string& prop) +const char* getTypedProperty( + 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 @@ -4423,6 +4437,11 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, } std::string interfaceProperty = "INTERFACE_" + p; + std::unique_ptr 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(theTarget, interfaceProperty); + PropertyType ifacePropContent = getTypedProperty( + theTarget, interfaceProperty, genexInterpreter.get()); std::string reportEntry; if (ifaceIsSet) { diff --git a/Tests/RunCMake/PositionIndependentCode/Genex1-result.txt b/Tests/RunCMake/PositionIndependentCode/Genex1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Genex1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/PositionIndependentCode/Genex1-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Genex1-stderr.txt new file mode 100644 index 0000000..c242a05 --- /dev/null +++ b/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". diff --git a/Tests/RunCMake/PositionIndependentCode/Genex1.cmake b/Tests/RunCMake/PositionIndependentCode/Genex1.cmake new file mode 100644 index 0000000..a91be3e --- /dev/null +++ b/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 $,EXECUTABLE>>) + + +add_library(conflict1 STATIC main.cpp) +set_property(TARGET conflict1 PROPERTY POSITION_INDEPENDENT_CODE OFF) +target_link_libraries(conflict1 PRIVATE genex_pic) diff --git a/Tests/RunCMake/PositionIndependentCode/Genex2-result.txt b/Tests/RunCMake/PositionIndependentCode/Genex2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/PositionIndependentCode/Genex2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/PositionIndependentCode/Genex2-stderr.txt b/Tests/RunCMake/PositionIndependentCode/Genex2-stderr.txt new file mode 100644 index 0000000..735a926 --- /dev/null +++ b/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". diff --git a/Tests/RunCMake/PositionIndependentCode/Genex2.cmake b/Tests/RunCMake/PositionIndependentCode/Genex2.cmake new file mode 100644 index 0000000..fb0a5db --- /dev/null +++ b/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 $,EXECUTABLE>>) + + +add_executable(conflict2 main.cpp) +set_property(TARGET conflict2 PROPERTY POSITION_INDEPENDENT_CODE ON) +target_link_libraries(conflict2 PRIVATE genex_pic) diff --git a/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake b/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake index 6a67e3c..20187d3 100644 --- a/Tests/RunCMake/PositionIndependentCode/RunCMakeTest.cmake +++ b/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) -- cgit v0.12