From 53164ac997f6ce2a4fd1245956a815bfdb893c27 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 16 May 2013 15:52:14 +0200 Subject: [PATCH 1/3] cmTarget: Remove some hardcoding of transitive property names. --- Source/cmGeneratorExpressionEvaluator.cxx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 6618e83e2..60c969efe 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -313,6 +313,17 @@ static const char* targetPropertyTransitiveWhitelist[] = { , "INTERFACE_COMPILE_DEFINITIONS" }; +//---------------------------------------------------------------------------- +struct TransitiveWhitelistCompare +{ + explicit TransitiveWhitelistCompare(const std::string &needle) + : Needle(needle) {} + bool operator() (const char *item) + { return strcmp(item, this->Needle.c_str()) == 0; } +private: + std::string Needle; +}; + //---------------------------------------------------------------------------- static const struct TargetPropertyNode : public cmGeneratorExpressionNode { @@ -485,8 +496,12 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS"; } - if (interfacePropertyName == "INTERFACE_INCLUDE_DIRECTORIES" - || interfacePropertyName == "INTERFACE_COMPILE_DEFINITIONS") + const char **transBegin = targetPropertyTransitiveWhitelist; + const char **transEnd = targetPropertyTransitiveWhitelist + + (sizeof(targetPropertyTransitiveWhitelist) / + sizeof(*targetPropertyTransitiveWhitelist)); + if (std::find_if(transBegin, transEnd, + TransitiveWhitelistCompare(interfacePropertyName)) != transEnd) { const cmTarget::LinkInterface *iface = target->GetLinkInterface( context->Config, From 0b39fefeac550c8277ebde308fcb9198e43e46a7 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 29 May 2013 00:34:30 +0200 Subject: [PATCH 2/3] GenexEval: Extract a getLinkedTargetsContent from TargetPropertyNode. This will be used to process transitive components of properties which depend on linked targets. Currently only the link interface of the target can be used as the source of the linked targets, but in the next commit it will be possible to use the link implementation as the source of link targets. This commit does not change the semantics of the code. --- Source/cmGeneratorExpressionEvaluator.cxx | 81 +++++++++++++---------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 60c969efe..ba74e6047 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -313,6 +313,48 @@ static const char* targetPropertyTransitiveWhitelist[] = { , "INTERFACE_COMPILE_DEFINITIONS" }; +std::string getLinkedTargetsContent(const std::vector &libraries, + cmTarget *target, + cmGeneratorExpressionContext *context, + cmGeneratorExpressionDAGChecker *dagChecker, + const std::string &interfacePropertyName) +{ + cmGeneratorExpression ge(context->Backtrace); + + std::string sep; + std::string depString; + for (std::vector::const_iterator + it = libraries.begin(); + it != libraries.end(); ++it) + { + if (*it == target->GetName()) + { + // Broken code can have a target in its own link interface. + // Don't follow such link interface entries so as not to create a + // self-referencing loop. + continue; + } + if (context->Makefile->FindTargetToUse(it->c_str())) + { + depString += + sep + "$"; + sep = ";"; + } + } + cmsys::auto_ptr cge = ge.Parse(depString); + std::string linkedTargetsContent = cge->Evaluate(context->Makefile, + context->Config, + context->Quiet, + context->HeadTarget, + target, + dagChecker); + if (cge->GetHadContextSensitiveCondition()) + { + context->HadContextSensitiveCondition = true; + } + return linkedTargetsContent; +} + //---------------------------------------------------------------------------- struct TransitiveWhitelistCompare { @@ -508,41 +550,10 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode context->HeadTarget); if(iface) { - cmGeneratorExpression ge(context->Backtrace); - - std::string sep; - std::string depString; - for (std::vector::const_iterator - it = iface->Libraries.begin(); - it != iface->Libraries.end(); ++it) - { - if (*it == target->GetName()) - { - // Broken code can have a target in its own link interface. - // Don't follow such link interface entries so as not to create a - // self-referencing loop. - continue; - } - if (context->Makefile->FindTargetToUse(it->c_str())) - { - depString += - sep + "$"; - sep = ";"; - } - } - cmsys::auto_ptr cge = - ge.Parse(depString); - linkedTargetsContent = cge->Evaluate(context->Makefile, - context->Config, - context->Quiet, - context->HeadTarget, - target, - &dagChecker); - if (cge->GetHadContextSensitiveCondition()) - { - context->HadContextSensitiveCondition = true; - } + linkedTargetsContent = + getLinkedTargetsContent(iface->Libraries, target, + context, &dagChecker, + interfacePropertyName); } } From 3aa9ce441f010362e404e6f9126ecd3028de76b9 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 30 May 2013 15:30:24 +0200 Subject: [PATCH 3/3] GenexEval: Fix evaluation of INCLUDE_DIRECTORIES target property. This property should come from the content of the property itself, plus the INTERFACE_INCLUDE_DIRECTORIES of the link *implementation*. In contrast, when the INTERFACE_INCLUDE_DIRECTORIES is evaluated for a target, the INTERFACE_INCLUDE_DIRECTORIES of the link *interface* is used. Similar logic applies for the COMPILE_DEFINITIONS target properties. If the propertyName is already an INTERFACE_ variant of the property, ie, the expression is similar to $ then the INTERFACE_INCLUDE_DIRECTORIES of the link *interface* of foo is used. However, if the propertyName is not an INTERFACE_ variant, and the interfacePropertyName is, ie, the expression is similar to: $ then the INTERFACE_INCLUDE_DIRECTORIES of the link *implementation* of foo is used. --- Source/cmGeneratorExpressionEvaluator.cxx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index ba74e6047..de6371a57 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -543,7 +543,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode + (sizeof(targetPropertyTransitiveWhitelist) / sizeof(*targetPropertyTransitiveWhitelist)); if (std::find_if(transBegin, transEnd, - TransitiveWhitelistCompare(interfacePropertyName)) != transEnd) + TransitiveWhitelistCompare(propertyName)) != transEnd) { const cmTarget::LinkInterface *iface = target->GetLinkInterface( context->Config, @@ -556,6 +556,20 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode interfacePropertyName); } } + else if (std::find_if(transBegin, transEnd, + TransitiveWhitelistCompare(interfacePropertyName)) != transEnd) + { + const cmTarget::LinkImplementation *impl = target->GetLinkImplementation( + context->Config, + context->HeadTarget); + if(impl) + { + linkedTargetsContent = + getLinkedTargetsContent(impl->Libraries, target, + context, &dagChecker, + interfacePropertyName); + } + } linkedTargetsContent = cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);