mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-07 06:09:52 -06:00
INTERFACE_POSITION_INDEPENDENT_CODE: add generator expressions support
Fixes: #16532
This commit is contained in:
@@ -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
Help/release/dev/INTERFACE_POSITION_INDEPENDENT_CODE.rst
Normal file
5
Help/release/dev/INTERFACE_POSITION_INDEPENDENT_CODE.rst
Normal file
@@ -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)>`.
|
||||
@@ -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) {
|
||||
|
||||
1
Tests/RunCMake/PositionIndependentCode/Genex1-result.txt
Normal file
1
Tests/RunCMake/PositionIndependentCode/Genex1-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
3
Tests/RunCMake/PositionIndependentCode/Genex1-stderr.txt
Normal file
3
Tests/RunCMake/PositionIndependentCode/Genex1-stderr.txt
Normal file
@@ -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
Tests/RunCMake/PositionIndependentCode/Genex1.cmake
Normal file
9
Tests/RunCMake/PositionIndependentCode/Genex1.cmake
Normal file
@@ -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
Tests/RunCMake/PositionIndependentCode/Genex2-result.txt
Normal file
1
Tests/RunCMake/PositionIndependentCode/Genex2-result.txt
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
3
Tests/RunCMake/PositionIndependentCode/Genex2-stderr.txt
Normal file
3
Tests/RunCMake/PositionIndependentCode/Genex2-stderr.txt
Normal file
@@ -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
Tests/RunCMake/PositionIndependentCode/Genex2.cmake
Normal file
9
Tests/RunCMake/PositionIndependentCode/Genex2.cmake
Normal file
@@ -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)
|
||||
@@ -7,3 +7,5 @@ run_cmake(Conflict4)
|
||||
run_cmake(Conflict5)
|
||||
run_cmake(Conflict6)
|
||||
run_cmake(Debug)
|
||||
run_cmake(Genex1)
|
||||
run_cmake(Genex2)
|
||||
|
||||
Reference in New Issue
Block a user