Genex: Fix the HEAD target used for evaluated expressions

If the expression $<TARGET_PROPERTY:prop> appears in the content
of a target property, the target that prop is read from is
the 'head target' of the expression. In contexts such as evaluating
the content of a target property during generation, such
as INCLUDE_DIRECTORIES, the 'head target' is the one on which the
initial request was made.

If evaluating a generator expression which is not a target property
content, the target must be explicitly specified. Such contexts
include add_custom_command and file(GENERATE). The content might
then look like

 $<TARGET_PROPERTY:tgt,prop>

However, as there is no HeadTarget set, any generator expressions
evaluated as part of reading prop from tgt which do not specify
the tgt directly report an error.

Modify the logic of the TARGET_PROPERTY generator expression so
that in such contexts, the 'head target' is set to the appropriate
target which was first encountered.
This commit is contained in:
Stephen Kelly 2013-06-03 23:53:29 +02:00 committed by Brad King
parent 3aa9ce441f
commit 5b222354de
3 changed files with 20 additions and 4 deletions

View File

@ -315,6 +315,7 @@ static const char* targetPropertyTransitiveWhitelist[] = {
std::string getLinkedTargetsContent(const std::vector<std::string> &libraries, std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
cmTarget *target, cmTarget *target,
cmTarget *headTarget,
cmGeneratorExpressionContext *context, cmGeneratorExpressionContext *context,
cmGeneratorExpressionDAGChecker *dagChecker, cmGeneratorExpressionDAGChecker *dagChecker,
const std::string &interfacePropertyName) const std::string &interfacePropertyName)
@ -345,7 +346,7 @@ std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
std::string linkedTargetsContent = cge->Evaluate(context->Makefile, std::string linkedTargetsContent = cge->Evaluate(context->Makefile,
context->Config, context->Config,
context->Quiet, context->Quiet,
context->HeadTarget, headTarget,
target, target,
dagChecker); dagChecker);
if (cge->GetHadContextSensitiveCondition()) if (cge->GetHadContextSensitiveCondition())
@ -538,6 +539,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS"; interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
} }
cmTarget *headTarget = context->HeadTarget ? context->HeadTarget : target;
const char **transBegin = targetPropertyTransitiveWhitelist; const char **transBegin = targetPropertyTransitiveWhitelist;
const char **transEnd = targetPropertyTransitiveWhitelist const char **transEnd = targetPropertyTransitiveWhitelist
+ (sizeof(targetPropertyTransitiveWhitelist) / + (sizeof(targetPropertyTransitiveWhitelist) /
@ -547,11 +550,12 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{ {
const cmTarget::LinkInterface *iface = target->GetLinkInterface( const cmTarget::LinkInterface *iface = target->GetLinkInterface(
context->Config, context->Config,
context->HeadTarget); headTarget);
if(iface) if(iface)
{ {
linkedTargetsContent = linkedTargetsContent =
getLinkedTargetsContent(iface->Libraries, target, getLinkedTargetsContent(iface->Libraries, target,
headTarget,
context, &dagChecker, context, &dagChecker,
interfacePropertyName); interfacePropertyName);
} }
@ -561,11 +565,12 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{ {
const cmTarget::LinkImplementation *impl = target->GetLinkImplementation( const cmTarget::LinkImplementation *impl = target->GetLinkImplementation(
context->Config, context->Config,
context->HeadTarget); headTarget);
if(impl) if(impl)
{ {
linkedTargetsContent = linkedTargetsContent =
getLinkedTargetsContent(impl->Libraries, target, getLinkedTargetsContent(impl->Libraries, target,
headTarget,
context, &dagChecker, context, &dagChecker,
interfacePropertyName); interfacePropertyName);
} }
@ -614,7 +619,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
std::string result = cge->Evaluate(context->Makefile, std::string result = cge->Evaluate(context->Makefile,
context->Config, context->Config,
context->Quiet, context->Quiet,
context->HeadTarget, headTarget,
target, target,
&dagChecker); &dagChecker);

View File

@ -109,6 +109,11 @@ set_property(TARGET libbad APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/bad" INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/bad"
) )
add_library(lib6 SHARED other.cpp)
add_library(lib7 SHARED other.cpp)
target_link_libraries(lib7 $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:lib6>)
target_include_directories(lib7 PUBLIC $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:/lib7/include>)
add_custom_target(head_target_test "some_bogus_custom_tool \"$<TARGET_PROPERTY:lib7,INCLUDE_DIRECTORIES>$<TARGET_PROPERTY:lib7,INTERFACE_INCLUDE_DIRECTORIES>\"")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp" "#include \"common.h\"\n") file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp" "#include \"common.h\"\n")
add_library(lib5 "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp") add_library(lib5 "${CMAKE_CURRENT_BINARY_DIR}/lib5.cpp")

View File

@ -0,0 +1,6 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
int other() {
return 0;
}