diff options
Diffstat (limited to 'Source/cmGeneratorExpressionNode.cxx')
-rw-r--r-- | Source/cmGeneratorExpressionNode.cxx | 218 |
1 files changed, 207 insertions, 11 deletions
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index c1f1ee4..7b35bce 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -275,6 +275,203 @@ static const struct EqualNode : public cmGeneratorExpressionNode } } equalNode; +static const struct InListNode : public cmGeneratorExpressionNode +{ + InListNode() {} + + int NumExpectedParameters() const override { return 2; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* /*context*/, + const GeneratorExpressionContent* /*content*/, + cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override + { + std::vector<std::string> values; + cmSystemTools::ExpandListArgument(parameters[1], values); + if (values.empty()) { + return "0"; + } + + return std::find(values.cbegin(), values.cend(), parameters.front()) == + values.cend() + ? "0" + : "1"; + } +} inListNode; + +static const struct TargetExistsNode : public cmGeneratorExpressionNode +{ + TargetExistsNode() {} + + int NumExpectedParameters() const override { return 1; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override + { + if (parameters.size() != 1) { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_EXISTS:...> expression requires one parameter"); + return std::string(); + } + + std::string targetName = parameters.front(); + if (targetName.empty() || + !cmGeneratorExpression::IsValidTargetName(targetName)) { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_EXISTS:tgt> expression requires a non-empty " + "valid target name."); + return std::string(); + } + + return context->LG->GetMakefile()->FindTargetToUse(targetName) ? "1" : "0"; + } +} targetExistsNode; + +static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode +{ + TargetNameIfExistsNode() {} + + int NumExpectedParameters() const override { return 1; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override + { + if (parameters.size() != 1) { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_NAME_IF_EXISTS:...> expression requires one " + "parameter"); + return std::string(); + } + + std::string targetName = parameters.front(); + if (targetName.empty() || + !cmGeneratorExpression::IsValidTargetName(targetName)) { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_NAME_IF_EXISTS:tgt> expression requires a " + "non-empty valid target name."); + return std::string(); + } + + return context->LG->GetMakefile()->FindTargetToUse(targetName) + ? targetName + : std::string(); + } +} targetNameIfExistsNode; + +struct GenexEvaluator : public cmGeneratorExpressionNode +{ + GenexEvaluator() {} + +protected: + std::string EvaluateExpression( + const std::string& genexOperator, const std::string& expression, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagCheckerParent) const + { + if (context->HeadTarget) { + cmGeneratorExpressionDAGChecker dagChecker( + context->Backtrace, context->HeadTarget->GetName(), genexOperator, + content, dagCheckerParent); + switch (dagChecker.Check()) { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: { + dagChecker.ReportError(context, content->GetOriginalExpression()); + return std::string(); + } + case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: + case cmGeneratorExpressionDAGChecker::DAG: + break; + } + + return this->EvaluateDependentExpression( + expression, context->LG, context, context->HeadTarget, + context->CurrentTarget, &dagChecker); + } + + return this->EvaluateDependentExpression( + expression, context->LG, context, context->HeadTarget, + context->CurrentTarget, dagCheckerParent); + } +}; + +static const struct TargetGenexEvalNode : public GenexEvaluator +{ + TargetGenexEvalNode() {} + + int NumExpectedParameters() const override { return 2; } + + bool AcceptsArbitraryContentParameter() const override { return true; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagCheckerParent) const override + { + const std::string& targetName = parameters.front(); + if (targetName.empty() || + !cmGeneratorExpression::IsValidTargetName(targetName)) { + reportError(context, content->GetOriginalExpression(), + "$<TARGET_GENEX_EVAL:tgt, ...> expression requires a " + "non-empty valid target name."); + return std::string(); + } + + const auto* target = context->LG->FindGeneratorTargetToUse(targetName); + if (!target) { + std::ostringstream e; + e << "$<TARGET_GENEX_EVAL:tgt, ...> target \"" << targetName + << "\" not found."; + reportError(context, content->GetOriginalExpression(), e.str()); + return std::string(); + } + + const std::string& expression = parameters[1]; + if (expression.empty()) { + return expression; + } + + cmGeneratorExpressionContext targetContext( + context->LG, context->Config, context->Quiet, target, target, + context->EvaluateForBuildsystem, context->Backtrace, context->Language); + + return this->EvaluateExpression("TARGET_GENEX_EVAL", expression, + &targetContext, content, dagCheckerParent); + } +} targetGenexEvalNode; + +static const struct GenexEvalNode : public GenexEvaluator +{ + GenexEvalNode() {} + + int NumExpectedParameters() const override { return 1; } + + bool AcceptsArbitraryContentParameter() const override { return true; } + + std::string Evaluate( + const std::vector<std::string>& parameters, + cmGeneratorExpressionContext* context, + const GeneratorExpressionContent* content, + cmGeneratorExpressionDAGChecker* dagCheckerParent) const override + { + const std::string& expression = parameters[0]; + if (expression.empty()) { + return expression; + } + + return this->EvaluateExpression("GENEX_EVAL", expression, context, content, + dagCheckerParent); + } +} genexEvalNode; + static const struct LowerCaseNode : public cmGeneratorExpressionNode { LowerCaseNode() {} @@ -816,16 +1013,7 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode return std::string(); } - std::vector<std::string> enabledLanguages; cmGlobalGenerator* gg = context->LG->GetGlobalGenerator(); - gg->GetEnabledLanguages(enabledLanguages); - if (!parameters.empty() && - std::find(enabledLanguages.begin(), enabledLanguages.end(), - parameters.front()) == enabledLanguages.end()) { - reportError(context, content->GetOriginalExpression(), - "$<COMPILE_LANGUAGE:...> Unknown language."); - return std::string(); - } std::string genName = gg->GetName(); if (genName.find("Makefiles") == std::string::npos && genName.find("Ninja") == std::string::npos && @@ -1034,7 +1222,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode const char* prop = target->GetProperty(propertyName); if (dagCheckerParent) { - if (dagCheckerParent->EvaluatingLinkLibraries()) { + if (dagCheckerParent->EvaluatingGenexExpression()) { + // No check required. + } else if (dagCheckerParent->EvaluatingLinkLibraries()) { #define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \ (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) || if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME( @@ -1585,7 +1775,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag> "executables with ENABLE_EXPORTS."); return std::string(); } - cmStateEnums::ArtifactType artifact = target->HasImportLibrary() + cmStateEnums::ArtifactType artifact = + target->HasImportLibrary(context->Config) ? cmStateEnums::ImportLibraryArtifact : cmStateEnums::RuntimeBinaryArtifact; return target->GetFullPath(context->Config, artifact); @@ -1827,6 +2018,7 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( nodeMap["TARGET_BUNDLE_CONTENT_DIR"] = &targetBundleContentDirNode; nodeMap["STREQUAL"] = &strEqualNode; nodeMap["EQUAL"] = &equalNode; + nodeMap["IN_LIST"] = &inListNode; nodeMap["LOWER_CASE"] = &lowerCaseNode; nodeMap["UPPER_CASE"] = &upperCaseNode; nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode; @@ -1839,6 +2031,10 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode( nodeMap["TARGET_NAME"] = &targetNameNode; nodeMap["TARGET_OBJECTS"] = &targetObjectsNode; nodeMap["TARGET_POLICY"] = &targetPolicyNode; + nodeMap["TARGET_EXISTS"] = &targetExistsNode; + nodeMap["TARGET_NAME_IF_EXISTS"] = &targetNameIfExistsNode; + nodeMap["TARGET_GENEX_EVAL"] = &targetGenexEvalNode; + nodeMap["GENEX_EVAL"] = &genexEvalNode; nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode; nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode; nodeMap["INSTALL_PREFIX"] = &installPrefixNode; |