diff options
Diffstat (limited to 'Source/cmGeneratorExpressionEvaluator.cxx')
-rw-r--r-- | Source/cmGeneratorExpressionEvaluator.cxx | 268 |
1 files changed, 267 insertions, 1 deletions
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 8e40815a..5d94718 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -238,6 +238,7 @@ static const struct ConfigurationNode : public cmGeneratorExpressionNode const GeneratorExpressionContent *, cmGeneratorExpressionDAGChecker *) const { + context->HadContextSensitiveCondition = true; return context->Config ? context->Config : ""; } } configurationNode; @@ -262,6 +263,7 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode "Expression syntax not recognized."); return std::string(); } + context->HadContextSensitiveCondition = true; if (!context->Config) { return parameters.front().empty() ? "1" : "0"; @@ -435,6 +437,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: // No error. We just skip cyclic references. return std::string(); + case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: + // No error. We're not going to find anything new here. + return std::string(); case cmGeneratorExpressionDAGChecker::DAG: break; } @@ -442,6 +447,39 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode const char *prop = target->GetProperty(propertyName.c_str()); if (!prop) { + if (target->IsImported()) + { + return std::string(); + } + if (dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries()) + { + return std::string(); + } + if (propertyName == "POSITION_INDEPENDENT_CODE") + { + context->HadContextSensitiveCondition = true; + return target->GetLinkInterfaceDependentBoolProperty( + "POSITION_INDEPENDENT_CODE", context->Config) ? "1" : "0"; + } + if (target->IsLinkInterfaceDependentBoolProperty(propertyName, + context->Config)) + { + context->HadContextSensitiveCondition = true; + return target->GetLinkInterfaceDependentBoolProperty( + propertyName, + context->Config) ? "1" : "0"; + } + if (target->IsLinkInterfaceDependentStringProperty(propertyName, + context->Config)) + { + context->HadContextSensitiveCondition = true; + const char *propContent = + target->GetLinkInterfaceDependentStringProperty( + propertyName, + context->Config); + return propContent ? propContent : ""; + } + return std::string(); } @@ -453,12 +491,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode if (targetPropertyTransitiveWhitelist[i] == propertyName) { cmGeneratorExpression ge(context->Backtrace); - return ge.Parse(prop)->Evaluate(context->Makefile, + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop); + std::string result = cge->Evaluate(context->Makefile, context->Config, context->Quiet, context->HeadTarget, target, &dagChecker); + + if (cge->GetHadContextSensitiveCondition()) + { + context->HadContextSensitiveCondition = true; + } + return result; } } return prop; @@ -488,6 +533,221 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode } targetNameNode; //---------------------------------------------------------------------------- +static const char* targetPolicyWhitelist[] = { + "CMP0003" + , "CMP0004" + , "CMP0008" + , "CMP0020" +}; + +cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy) +{ +#define RETURN_POLICY(POLICY) \ + if (strcmp(policy, #POLICY) == 0) \ + { \ + return tgt->GetPolicyStatus ## POLICY (); \ + } \ + + RETURN_POLICY(CMP0003) + RETURN_POLICY(CMP0004) + RETURN_POLICY(CMP0008) + RETURN_POLICY(CMP0020) + +#undef RETURN_POLICY + + assert("!Unreachable code. Not a valid policy"); + return cmPolicies::WARN; +} + +cmPolicies::PolicyID policyForString(const char *policy_id) +{ +#define RETURN_POLICY_ID(POLICY_ID) \ + if (strcmp(policy_id, #POLICY_ID) == 0) \ + { \ + return cmPolicies:: POLICY_ID; \ + } \ + + RETURN_POLICY_ID(CMP0003) + RETURN_POLICY_ID(CMP0004) + RETURN_POLICY_ID(CMP0008) + RETURN_POLICY_ID(CMP0020) + +#undef RETURN_POLICY_ID + + assert("!Unreachable code. Not a valid policy"); + return cmPolicies::CMP0002; +} + +//---------------------------------------------------------------------------- +static const struct TargetPolicyNode : public cmGeneratorExpressionNode +{ + TargetPolicyNode() {} + + virtual int NumExpectedParameters() const { return 1; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context , + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *) const + { + if (!context->HeadTarget) + { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_POLICY:prop> may only be used with targets. It may not " + "be used with add_custom_command."); + return std::string(); + } + + context->HadContextSensitiveCondition = true; + + for (size_t i = 0; + i < (sizeof(targetPolicyWhitelist) / + sizeof(*targetPolicyWhitelist)); + ++i) + { + const char *policy = targetPolicyWhitelist[i]; + if (parameters.front() == policy) + { + cmMakefile *mf = context->HeadTarget->GetMakefile(); + switch(statusForTarget(context->HeadTarget, policy)) + { + case cmPolicies::WARN: + mf->IssueMessage(cmake::AUTHOR_WARNING, + mf->GetPolicies()-> + GetPolicyWarning(policyForString(policy))); + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::OLD: + return "0"; + case cmPolicies::NEW: + return "1"; + } + } + } + reportError(context, content->GetOriginalExpression(), + "$<TARGET_POLICY:prop> may only be used with a limited number of " + "policies. Currently it may be used with policies CMP0003, CMP0004, " + "CMP0008 and CMP0020." + ); + return std::string(); + } + +} targetPolicyNode; + +//---------------------------------------------------------------------------- +static const struct InstallPrefixNode : public cmGeneratorExpressionNode +{ + InstallPrefixNode() {} + + virtual bool GeneratesContent() const { return true; } + virtual int NumExpectedParameters() const { return 0; } + + std::string Evaluate(const std::vector<std::string> &, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *) const + { + reportError(context, content->GetOriginalExpression(), + "INSTALL_PREFIX is a marker for install(EXPORT) only. It " + "should never be evaluated."); + return std::string(); + } + +} installPrefixNode; + +//---------------------------------------------------------------------------- +static const struct LinkedNode : public cmGeneratorExpressionNode +{ + LinkedNode() {} + + virtual bool GeneratesContent() const { return true; } + virtual int NumExpectedParameters() const { return 1; } + virtual bool RequiresLiteralInput() const { return true; } + + std::string Evaluate(const std::vector<std::string> ¶meters, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagChecker) const + { + if (dagChecker->EvaluatingIncludeDirectories()) + { + return this->GetInterfaceProperty(parameters.front(), + "INCLUDE_DIRECTORIES", + context, content, dagChecker); + } + if (dagChecker->EvaluatingCompileDefinitions()) + { + return this->GetInterfaceProperty(parameters.front(), + "COMPILE_DEFINITIONS", + context, content, dagChecker); + } + + reportError(context, content->GetOriginalExpression(), + "$<LINKED:...> may only be used in INCLUDE_DIRECTORIES and " + "COMPILE_DEFINITIONS properties."); + + return std::string(); + } + +private: + std::string GetInterfaceProperty(const std::string &item, + const std::string &prop, + cmGeneratorExpressionContext *context, + const GeneratorExpressionContent *content, + cmGeneratorExpressionDAGChecker *dagCheckerParent) const + { + cmTarget *target = context->CurrentTarget + ->GetMakefile()->FindTargetToUse(item.c_str()); + if (!target) + { + return std::string(); + } + std::string propertyName = "INTERFACE_" + prop; + const char *propContent = target->GetProperty(propertyName.c_str()); + if (!propContent) + { + return std::string(); + } + + cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, + target->GetName(), + propertyName, + content, + dagCheckerParent); + + switch (dagChecker.check()) + { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: + dagChecker.reportError(context, content->GetOriginalExpression()); + return std::string(); + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: + // No error. We just skip cyclic references. + return std::string(); + case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: + // No error. We're not going to find anything new here. + return std::string(); + case cmGeneratorExpressionDAGChecker::DAG: + break; + } + + cmGeneratorExpression ge(context->Backtrace); + cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(propContent); + std::string result = cge->Evaluate(context->Makefile, + context->Config, + context->Quiet, + context->HeadTarget, + target, + &dagChecker); + if (cge->GetHadContextSensitiveCondition()) + { + context->HadContextSensitiveCondition = true; + } + return result; + } + +} linkedNode; + +//---------------------------------------------------------------------------- template<bool linker, bool soname> struct TargetFilesystemArtifactResultCreator { @@ -714,12 +974,18 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier) return &targetPropertyNode; else if (identifier == "TARGET_NAME") return &targetNameNode; + else if (identifier == "TARGET_POLICY") + return &targetPolicyNode; else if (identifier == "BUILD_INTERFACE") return &buildInterfaceNode; else if (identifier == "INSTALL_INTERFACE") return &installInterfaceNode; else if (identifier == "TARGET_DEFINED") return &targetDefinedNode; + else if (identifier == "INSTALL_PREFIX") + return &installPrefixNode; + else if (identifier == "LINKED") + return &linkedNode; return 0; } |