Commit 023188ff authored by Marc Chevrier's avatar Marc Chevrier
Browse files

INTERFACE_POSITION_INDEPENDENT_CODE: add generator expressions support

Fixes: #16532
parent 17e98e00
......@@ -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.
INTERFACE_POSITION_INDEPENDENT_CODE
-----------------------------------
* :prop_tgt:`INTERFACE_POSITION_INDEPENDENT_CODE` target property gains the
support of :manual:`generator expressions <cmake-generator-expressions(7)>`.
......@@ -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)
{
......
......@@ -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;
......
......@@ -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) \
......
......@@ -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) {
......
CMake Error: Property POSITION_INDEPENDENT_CODE on target "conflict1" does
not match the INTERFACE_POSITION_INDEPENDENT_CODE property requirement
of dependency "genex_pic".
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)
CMake Error: Property POSITION_INDEPENDENT_CODE on target "conflict2" does
not match the INTERFACE_POSITION_INDEPENDENT_CODE property requirement
of dependency "genex_pic".
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)
......@@ -7,3 +7,5 @@ run_cmake(Conflict4)
run_cmake(Conflict5)
run_cmake(Conflict6)
run_cmake(Debug)
run_cmake(Genex1)
run_cmake(Genex2)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment