cmake/Source/cmGeneratorExpressionNode.cxx

2073 lines
71 KiB
C++
Raw Normal View History

2016-10-30 18:24:19 +01:00
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
2015-08-17 11:37:30 +02:00
#include "cmGeneratorExpressionNode.h"
2016-07-09 11:21:54 +02:00
2015-08-17 11:37:30 +02:00
#include "cmAlgorithms.h"
2016-10-30 18:24:19 +01:00
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpressionEvaluator.h"
#include "cmGeneratorTarget.h"
2016-07-09 11:21:54 +02:00
#include "cmGlobalGenerator.h"
2016-10-30 18:24:19 +01:00
#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
2016-03-13 13:35:51 +01:00
#include "cmMakefile.h"
2016-07-09 11:21:54 +02:00
#include "cmOutputConverter.h"
2016-10-30 18:24:19 +01:00
#include "cmPolicies.h"
2017-04-14 19:02:05 +02:00
#include "cmStateTypes.h"
2016-10-30 18:24:19 +01:00
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
2017-07-20 19:35:53 +02:00
#include "cmsys/RegularExpression.hxx"
#include "cmsys/String.h"
2016-10-30 18:24:19 +01:00
#include <algorithm>
#include <assert.h>
#include <errno.h>
#include <map>
2018-01-26 17:06:56 +01:00
#include <memory> // IWYU pragma: keep
2016-10-30 18:24:19 +01:00
#include <set>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <utility>
2015-08-17 11:37:30 +02:00
std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
2016-07-09 11:21:54 +02:00
std::string const& prop, cmLocalGenerator* lg,
cmGeneratorExpressionContext* context, cmGeneratorTarget const* headTarget,
cmGeneratorTarget const* currentTarget,
cmGeneratorExpressionDAGChecker* dagChecker)
2015-08-17 11:37:30 +02:00
{
2015-11-17 17:22:37 +01:00
cmGeneratorExpression ge(context->Backtrace);
2018-01-26 17:06:56 +01:00
std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
2015-08-17 11:37:30 +02:00
cge->SetEvaluateForBuildsystem(context->EvaluateForBuildsystem);
2016-07-09 11:21:54 +02:00
std::string result =
cge->Evaluate(lg, context->Config, context->Quiet, headTarget,
currentTarget, dagChecker, context->Language);
if (cge->GetHadContextSensitiveCondition()) {
2015-08-17 11:37:30 +02:00
context->HadContextSensitiveCondition = true;
2016-07-09 11:21:54 +02:00
}
if (cge->GetHadHeadSensitiveCondition()) {
2015-08-17 11:37:30 +02:00
context->HadHeadSensitiveCondition = true;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return result;
}
static const struct ZeroNode : public cmGeneratorExpressionNode
{
ZeroNode() {}
2018-01-26 17:06:56 +01:00
bool GeneratesContent() const override { return false; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
bool AcceptsArbitraryContentParameter() const override { return true; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& /*parameters*/,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return std::string();
}
} zeroNode;
static const struct OneNode : public cmGeneratorExpressionNode
{
OneNode() {}
2018-01-26 17:06:56 +01:00
bool AcceptsArbitraryContentParameter() const override { return true; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return parameters.front();
}
} oneNode;
static const struct OneNode buildInterfaceNode;
static const struct ZeroNode installInterfaceNode;
2016-07-09 11:21:54 +02:00
#define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
static const struct OP##Node : public cmGeneratorExpressionNode \
{ \
OP##Node() {} \
virtual int NumExpectedParameters() const { return OneOrMoreParameters; } \
\
std::string Evaluate(const std::vector<std::string>& parameters, \
cmGeneratorExpressionContext* context, \
const GeneratorExpressionContent* content, \
cmGeneratorExpressionDAGChecker*) const \
{ \
std::vector<std::string>::const_iterator it = parameters.begin(); \
const std::vector<std::string>::const_iterator end = parameters.end(); \
for (; it != end; ++it) { \
if (*it == #FAILURE_VALUE) { \
return #FAILURE_VALUE; \
2016-10-30 18:24:19 +01:00
} \
if (*it != #SUCCESS_VALUE) { \
2016-07-09 11:21:54 +02:00
reportError(context, content->GetOriginalExpression(), \
"Parameters to $<" #OP \
"> must resolve to either '0' or '1'."); \
return std::string(); \
} \
} \
return #SUCCESS_VALUE; \
} \
} OPNAME;
2015-08-17 11:37:30 +02:00
BOOLEAN_OP_NODE(andNode, AND, 1, 0)
BOOLEAN_OP_NODE(orNode, OR, 0, 1)
#undef BOOLEAN_OP_NODE
static const struct NotNode : public cmGeneratorExpressionNode
{
NotNode() {}
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
if (*parameters.begin() != "0" && *parameters.begin() != "1") {
reportError(
context, content->GetOriginalExpression(),
"$<NOT> parameter must resolve to exactly one '0' or '1' value.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return *parameters.begin() == "0" ? "1" : "0";
}
} notNode;
static const struct BoolNode : public cmGeneratorExpressionNode
{
BoolNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 1; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0";
}
} boolNode;
2017-04-14 19:02:05 +02:00
static const struct IfNode : public cmGeneratorExpressionNode
{
IfNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 3; }
2017-04-14 19:02:05 +02:00
std::string Evaluate(const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
2018-01-26 17:06:56 +01:00
cmGeneratorExpressionDAGChecker*) const override
2017-04-14 19:02:05 +02:00
{
if (parameters[0] != "1" && parameters[0] != "0") {
reportError(context, content->GetOriginalExpression(),
"First parameter to $<IF> must resolve to exactly one '0' "
"or '1' value.");
return std::string();
}
return parameters[0] == "1" ? parameters[1] : parameters[2];
}
} ifNode;
2015-08-17 11:37:30 +02:00
static const struct StrEqualNode : public cmGeneratorExpressionNode
{
StrEqualNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 2; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return *parameters.begin() == parameters[1] ? "1" : "0";
}
} strEqualNode;
static const struct EqualNode : public cmGeneratorExpressionNode
{
EqualNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 2; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
char* pEnd;
2015-08-17 11:37:30 +02:00
int base = 0;
bool flipSign = false;
2016-07-09 11:21:54 +02:00
const char* lhs = parameters[0].c_str();
if (cmHasLiteralPrefix(lhs, "0b") || cmHasLiteralPrefix(lhs, "0B")) {
2015-08-17 11:37:30 +02:00
base = 2;
lhs += 2;
2016-07-09 11:21:54 +02:00
}
if (cmHasLiteralPrefix(lhs, "-0b") || cmHasLiteralPrefix(lhs, "-0B")) {
2015-08-17 11:37:30 +02:00
base = 2;
lhs += 3;
flipSign = true;
2016-07-09 11:21:54 +02:00
}
if (cmHasLiteralPrefix(lhs, "+0b") || cmHasLiteralPrefix(lhs, "+0B")) {
2015-08-17 11:37:30 +02:00
base = 2;
lhs += 3;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
long lnum = strtol(lhs, &pEnd, base);
2016-07-09 11:21:54 +02:00
if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE) {
2015-08-17 11:37:30 +02:00
reportError(context, content->GetOriginalExpression(),
2016-07-09 11:21:54 +02:00
"$<EQUAL> parameter " + parameters[0] +
" is not a valid integer.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (flipSign) {
2015-08-17 11:37:30 +02:00
lnum = -lnum;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
base = 0;
flipSign = false;
2016-07-09 11:21:54 +02:00
const char* rhs = parameters[1].c_str();
if (cmHasLiteralPrefix(rhs, "0b") || cmHasLiteralPrefix(rhs, "0B")) {
2015-08-17 11:37:30 +02:00
base = 2;
rhs += 2;
2016-07-09 11:21:54 +02:00
}
if (cmHasLiteralPrefix(rhs, "-0b") || cmHasLiteralPrefix(rhs, "-0B")) {
2015-08-17 11:37:30 +02:00
base = 2;
rhs += 3;
flipSign = true;
2016-07-09 11:21:54 +02:00
}
if (cmHasLiteralPrefix(rhs, "+0b") || cmHasLiteralPrefix(rhs, "+0B")) {
2015-08-17 11:37:30 +02:00
base = 2;
rhs += 3;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
long rnum = strtol(rhs, &pEnd, base);
2016-07-09 11:21:54 +02:00
if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE) {
2015-08-17 11:37:30 +02:00
reportError(context, content->GetOriginalExpression(),
2016-07-09 11:21:54 +02:00
"$<EQUAL> parameter " + parameters[1] +
" is not a valid integer.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (flipSign) {
2015-08-17 11:37:30 +02:00
rnum = -rnum;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return lnum == rnum ? "1" : "0";
}
} equalNode;
2018-08-09 18:06:22 +02:00
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;
2015-08-17 11:37:30 +02:00
static const struct LowerCaseNode : public cmGeneratorExpressionNode
{
LowerCaseNode() {}
2018-01-26 17:06:56 +01:00
bool AcceptsArbitraryContentParameter() const override { return true; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return cmSystemTools::LowerCase(parameters.front());
}
} lowerCaseNode;
static const struct UpperCaseNode : public cmGeneratorExpressionNode
{
UpperCaseNode() {}
2018-01-26 17:06:56 +01:00
bool AcceptsArbitraryContentParameter() const override { return true; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return cmSystemTools::UpperCase(parameters.front());
}
} upperCaseNode;
static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode
{
MakeCIdentifierNode() {}
2018-01-26 17:06:56 +01:00
bool AcceptsArbitraryContentParameter() const override { return true; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return cmSystemTools::MakeCidentifier(parameters.front());
}
} makeCIdentifierNode;
static const struct Angle_RNode : public cmGeneratorExpressionNode
{
Angle_RNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 0; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& /*parameters*/,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return ">";
}
} angle_rNode;
static const struct CommaNode : public cmGeneratorExpressionNode
{
CommaNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 0; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& /*parameters*/,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return ",";
}
} commaNode;
static const struct SemicolonNode : public cmGeneratorExpressionNode
{
SemicolonNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 0; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& /*parameters*/,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return ";";
}
} semicolonNode;
struct CompilerIdNode : public cmGeneratorExpressionNode
{
CompilerIdNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return OneOrZeroParameters; }
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
std::string EvaluateWithLanguage(const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
2016-10-30 18:24:19 +01:00
cmGeneratorExpressionDAGChecker* /*unused*/,
2016-07-09 11:21:54 +02:00
const std::string& lang) const
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
const char* compilerId = context->LG->GetMakefile()->GetSafeDefinition(
"CMAKE_" + lang + "_COMPILER_ID");
if (parameters.empty()) {
2015-08-17 11:37:30 +02:00
return compilerId ? compilerId : "";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
2016-07-09 11:21:54 +02:00
if (!compilerIdValidator.find(*parameters.begin())) {
2015-08-17 11:37:30 +02:00
reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
return std::string();
2016-07-09 11:21:54 +02:00
}
if (!compilerId) {
2015-08-17 11:37:30 +02:00
return parameters.front().empty() ? "1" : "0";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (strcmp(parameters.begin()->c_str(), compilerId) == 0) {
2015-08-17 11:37:30 +02:00
return "1";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0) {
switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) {
case cmPolicies::WARN: {
2015-08-17 11:37:30 +02:00
std::ostringstream e;
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044);
2016-07-09 11:21:54 +02:00
context->LG->GetCMakeInstance()->IssueMessage(
cmake::AUTHOR_WARNING, e.str(), context->Backtrace);
2017-07-20 19:35:53 +02:00
CM_FALLTHROUGH;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
case cmPolicies::OLD:
return "1";
case cmPolicies::NEW:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
break;
}
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return "0";
}
};
static const struct CCompilerIdNode : public CompilerIdNode
{
CCompilerIdNode() {}
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagChecker) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
if (!context->HeadTarget) {
reportError(
context, content->GetOriginalExpression(),
"$<C_COMPILER_ID> may only be used with binary targets. It may "
"not be used with add_custom_command or add_custom_target.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
"C");
2015-08-17 11:37:30 +02:00
}
} cCompilerIdNode;
static const struct CXXCompilerIdNode : public CompilerIdNode
{
CXXCompilerIdNode() {}
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagChecker) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
if (!context->HeadTarget) {
reportError(
context, content->GetOriginalExpression(),
"$<CXX_COMPILER_ID> may only be used with binary targets. It may "
"not be used with add_custom_command or add_custom_target.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
"CXX");
2015-08-17 11:37:30 +02:00
}
} cxxCompilerIdNode;
struct CompilerVersionNode : public cmGeneratorExpressionNode
{
CompilerVersionNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return OneOrZeroParameters; }
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
std::string EvaluateWithLanguage(const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
2016-10-30 18:24:19 +01:00
cmGeneratorExpressionDAGChecker* /*unused*/,
2016-07-09 11:21:54 +02:00
const std::string& lang) const
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
const char* compilerVersion =
context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
"_COMPILER_VERSION");
if (parameters.empty()) {
2015-08-17 11:37:30 +02:00
return compilerVersion ? compilerVersion : "";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$");
2016-07-09 11:21:54 +02:00
if (!compilerIdValidator.find(*parameters.begin())) {
2015-08-17 11:37:30 +02:00
reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
return std::string();
2016-07-09 11:21:54 +02:00
}
if (!compilerVersion) {
2015-08-17 11:37:30 +02:00
return parameters.front().empty() ? "1" : "0";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
2016-07-09 11:21:54 +02:00
parameters.begin()->c_str(),
compilerVersion)
? "1"
: "0";
2015-08-17 11:37:30 +02:00
}
};
static const struct CCompilerVersionNode : public CompilerVersionNode
{
CCompilerVersionNode() {}
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagChecker) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
if (!context->HeadTarget) {
reportError(
context, content->GetOriginalExpression(),
"$<C_COMPILER_VERSION> may only be used with binary targets. It "
"may not be used with add_custom_command or add_custom_target.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
"C");
2015-08-17 11:37:30 +02:00
}
} cCompilerVersionNode;
static const struct CxxCompilerVersionNode : public CompilerVersionNode
{
CxxCompilerVersionNode() {}
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagChecker) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
if (!context->HeadTarget) {
reportError(
context, content->GetOriginalExpression(),
"$<CXX_COMPILER_VERSION> may only be used with binary targets. It "
"may not be used with add_custom_command or add_custom_target.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
"CXX");
2015-08-17 11:37:30 +02:00
}
} cxxCompilerVersionNode;
struct PlatformIdNode : public cmGeneratorExpressionNode
{
PlatformIdNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return OneOrZeroParameters; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
const char* platformId =
2016-03-13 13:35:51 +01:00
context->LG->GetMakefile()->GetSafeDefinition("CMAKE_SYSTEM_NAME");
2016-07-09 11:21:54 +02:00
if (parameters.empty()) {
2015-08-17 11:37:30 +02:00
return platformId ? platformId : "";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (!platformId) {
2015-08-17 11:37:30 +02:00
return parameters.front().empty() ? "1" : "0";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (strcmp(parameters.begin()->c_str(), platformId) == 0) {
2015-08-17 11:37:30 +02:00
return "1";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return "0";
}
} platformIdNode;
static const struct VersionGreaterNode : public cmGeneratorExpressionNode
{
VersionGreaterNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 2; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
parameters.front().c_str(),
2016-07-09 11:21:54 +02:00
parameters[1].c_str())
? "1"
: "0";
2015-08-17 11:37:30 +02:00
}
} versionGreaterNode;
2016-10-30 18:24:19 +01:00
static const struct VersionGreaterEqNode : public cmGeneratorExpressionNode
{
VersionGreaterEqNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 2; }
2016-10-30 18:24:19 +01:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2016-10-30 18:24:19 +01:00
{
return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER_EQUAL,
parameters.front().c_str(),
parameters[1].c_str())
? "1"
: "0";
}
} versionGreaterEqNode;
2015-08-17 11:37:30 +02:00
static const struct VersionLessNode : public cmGeneratorExpressionNode
{
VersionLessNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 2; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
parameters.front().c_str(),
2016-07-09 11:21:54 +02:00
parameters[1].c_str())
? "1"
: "0";
2015-08-17 11:37:30 +02:00
}
} versionLessNode;
2016-10-30 18:24:19 +01:00
static const struct VersionLessEqNode : public cmGeneratorExpressionNode
{
VersionLessEqNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 2; }
2016-10-30 18:24:19 +01:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2016-10-30 18:24:19 +01:00
{
return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS_EQUAL,
parameters.front().c_str(),
parameters[1].c_str())
? "1"
: "0";
}
} versionLessEqNode;
2015-08-17 11:37:30 +02:00
static const struct VersionEqualNode : public cmGeneratorExpressionNode
{
VersionEqualNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 2; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
parameters.front().c_str(),
2016-07-09 11:21:54 +02:00
parameters[1].c_str())
? "1"
: "0";
2015-08-17 11:37:30 +02:00
}
} versionEqualNode;
static const struct LinkOnlyNode : public cmGeneratorExpressionNode
{
LinkOnlyNode() {}
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagChecker) const override
2015-08-17 11:37:30 +02:00
{
2016-10-30 18:24:19 +01:00
if (!dagChecker) {
reportError(context, content->GetOriginalExpression(),
"$<LINK_ONLY:...> may only be used for linking");
return std::string();
}
2016-07-09 11:21:54 +02:00
if (!dagChecker->GetTransitivePropertiesOnly()) {
2015-08-17 11:37:30 +02:00
return parameters.front();
2016-07-09 11:21:54 +02:00
}
2016-10-30 18:24:19 +01:00
return std::string();
2015-08-17 11:37:30 +02:00
}
} linkOnlyNode;
static const struct ConfigurationNode : public cmGeneratorExpressionNode
{
ConfigurationNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 0; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& /*parameters*/,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
context->HadContextSensitiveCondition = true;
return context->Config;
}
} configurationNode;
static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
{
ConfigurationTestNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return OneOrZeroParameters; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
if (parameters.empty()) {
2018-01-26 17:06:56 +01:00
return configurationNode.Evaluate(parameters, context, content, nullptr);
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
static cmsys::RegularExpression configValidator("^[A-Za-z0-9_]*$");
2016-07-09 11:21:54 +02:00
if (!configValidator.find(*parameters.begin())) {
2015-08-17 11:37:30 +02:00
reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
context->HadContextSensitiveCondition = true;
2016-07-09 11:21:54 +02:00
if (context->Config.empty()) {
2015-08-17 11:37:30 +02:00
return parameters.front().empty() ? "1" : "0";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
if (cmsysString_strcasecmp(parameters.begin()->c_str(),
2016-07-09 11:21:54 +02:00
context->Config.c_str()) == 0) {
2015-08-17 11:37:30 +02:00
return "1";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (context->CurrentTarget && context->CurrentTarget->IsImported()) {
2018-01-26 17:06:56 +01:00
const char* loc = nullptr;
const char* imp = nullptr;
2015-08-17 11:37:30 +02:00
std::string suffix;
2016-07-09 11:21:54 +02:00
if (context->CurrentTarget->Target->GetMappedConfig(
context->Config, &loc, &imp, suffix)) {
2015-08-17 11:37:30 +02:00
// This imported target has an appropriate location
// for this (possibly mapped) config.
// Check if there is a proper config mapping for the tested config.
std::vector<std::string> mappedConfigs;
std::string mapProp = "MAP_IMPORTED_CONFIG_";
mapProp += cmSystemTools::UpperCase(context->Config);
2016-07-09 11:21:54 +02:00
if (const char* mapValue =
context->CurrentTarget->GetProperty(mapProp)) {
2015-08-17 11:37:30 +02:00
cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue),
mappedConfigs);
return std::find(mappedConfigs.begin(), mappedConfigs.end(),
2016-07-09 11:21:54 +02:00
cmSystemTools::UpperCase(parameters.front())) !=
mappedConfigs.end()
? "1"
: "0";
2015-08-17 11:37:30 +02:00
}
}
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return "0";
}
} configurationTestNode;
static const struct JoinNode : public cmGeneratorExpressionNode
{
JoinNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 2; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
bool AcceptsArbitraryContentParameter() const override { return true; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
std::vector<std::string> list;
cmSystemTools::ExpandListArgument(parameters.front(), list);
return cmJoin(list, parameters[1]);
}
} joinNode;
static const struct CompileLanguageNode : public cmGeneratorExpressionNode
{
CompileLanguageNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return OneOrZeroParameters; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
2018-04-23 21:13:27 +02:00
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
if (context->Language.empty()) {
reportError(
context, content->GetOriginalExpression(),
"$<COMPILE_LANGUAGE:...> may only be used to specify include "
2018-01-26 17:06:56 +01:00
"directories, compile definitions, compile options, and to evaluate "
2016-07-09 11:21:54 +02:00
"components of the file(GENERATE) command.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-03-13 13:35:51 +01:00
cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
2015-08-17 11:37:30 +02:00
std::string genName = gg->GetName();
2018-04-23 21:13:27 +02:00
if (genName.find("Makefiles") == std::string::npos &&
genName.find("Ninja") == std::string::npos &&
genName.find("Visual Studio") == std::string::npos &&
genName.find("Xcode") == std::string::npos &&
genName.find("Watcom WMake") == std::string::npos) {
2015-08-17 11:37:30 +02:00
reportError(context, content->GetOriginalExpression(),
2018-04-23 21:13:27 +02:00
"$<COMPILE_LANGUAGE:...> not supported for this generator.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-10-30 18:24:19 +01:00
}
2016-07-09 11:21:54 +02:00
if (parameters.empty()) {
2015-08-17 11:37:30 +02:00
return context->Language;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return context->Language == parameters.front() ? "1" : "0";
}
} languageNode;
2016-07-09 11:21:54 +02:00
#define TRANSITIVE_PROPERTY_NAME(PROPERTY) , "INTERFACE_" #PROPERTY
2015-08-17 11:37:30 +02:00
static const char* targetPropertyTransitiveWhitelist[] = {
2018-01-26 17:06:56 +01:00
nullptr CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
2015-08-17 11:37:30 +02:00
};
#undef TRANSITIVE_PROPERTY_NAME
template <typename T>
2016-07-09 11:21:54 +02:00
std::string getLinkedTargetsContent(
std::vector<T> const& libraries, cmGeneratorTarget const* target,
cmGeneratorTarget const* headTarget, cmGeneratorExpressionContext* context,
cmGeneratorExpressionDAGChecker* dagChecker,
const std::string& interfacePropertyName)
2015-08-17 11:37:30 +02:00
{
std::string linkedTargetsContent;
std::string sep;
std::string depString;
2018-01-26 17:06:56 +01:00
for (T const& l : libraries) {
2015-08-17 11:37:30 +02:00
// 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.
2018-01-26 17:06:56 +01:00
if (l.Target && l.Target != target) {
depString += sep + "$<TARGET_PROPERTY:" + l.Target->GetName() + "," +
2016-07-09 11:21:54 +02:00
interfacePropertyName + ">";
2015-08-17 11:37:30 +02:00
sep = ";";
}
2016-07-09 11:21:54 +02:00
}
if (!depString.empty()) {
2015-08-17 11:37:30 +02:00
linkedTargetsContent =
2016-07-09 11:21:54 +02:00
cmGeneratorExpressionNode::EvaluateDependentExpression(
depString, target->GetLocalGenerator(), context, headTarget, target,
dagChecker);
}
2015-08-17 11:37:30 +02:00
linkedTargetsContent =
cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
return linkedTargetsContent;
}
static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{
TargetPropertyNode() {}
// This node handles errors on parameter count itself.
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return OneOrMoreParameters; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
if (parameters.size() != 1 && parameters.size() != 2) {
reportError(
context, content->GetOriginalExpression(),
"$<TARGET_PROPERTY:...> expression requires one or two parameters");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$");
2016-03-13 13:35:51 +01:00
cmGeneratorTarget const* target = context->HeadTarget;
2015-08-17 11:37:30 +02:00
std::string propertyName = *parameters.begin();
2016-07-09 11:21:54 +02:00
if (parameters.size() == 1) {
2015-08-17 11:37:30 +02:00
context->HadHeadSensitiveCondition = true;
2016-07-09 11:21:54 +02:00
}
if (!target && parameters.size() == 1) {
reportError(
context, content->GetOriginalExpression(),
"$<TARGET_PROPERTY:prop> may only be used with binary targets. "
"It may not be used with add_custom_command or add_custom_target. "
"Specify the target to read a property from using the "
"$<TARGET_PROPERTY:tgt,prop> signature instead.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (parameters.size() == 2) {
if (parameters.begin()->empty() && parameters[1].empty()) {
reportError(
context, content->GetOriginalExpression(),
"$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
"target name and property name.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
if (parameters.begin()->empty()) {
reportError(
context, content->GetOriginalExpression(),
"$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
"target name.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
std::string targetName = parameters.front();
propertyName = parameters[1];
2016-07-09 11:21:54 +02:00
if (!cmGeneratorExpression::IsValidTargetName(targetName)) {
if (!propertyNameValidator.find(propertyName.c_str())) {
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"Target name and property name not supported.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"Target name not supported.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2018-04-23 21:13:27 +02:00
static const std::string propALIASED_TARGET = "ALIASED_TARGET";
if (propertyName == propALIASED_TARGET) {
2016-07-09 11:21:54 +02:00
if (context->LG->GetMakefile()->IsAlias(targetName)) {
if (cmGeneratorTarget* tgt =
context->LG->FindGeneratorTargetToUse(targetName)) {
2015-08-17 11:37:30 +02:00
return tgt->GetName();
}
}
2016-07-09 11:21:54 +02:00
return "";
}
2016-03-13 13:35:51 +01:00
target = context->LG->FindGeneratorTargetToUse(targetName);
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (!target) {
2015-08-17 11:37:30 +02:00
std::ostringstream e;
2016-07-09 11:21:54 +02:00
e << "Target \"" << targetName << "\" not found.";
2015-08-17 11:37:30 +02:00
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
2016-07-09 11:21:54 +02:00
context->AllTargets.insert(target);
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (target == context->HeadTarget) {
2015-08-17 11:37:30 +02:00
// Keep track of the properties seen while processing.
// The evaluation of the LINK_LIBRARIES generator expressions
// will check this to ensure that properties have one consistent
// value for all evaluations.
context->SeenTargetProperties.insert(propertyName);
2016-07-09 11:21:54 +02:00
}
if (propertyName == "SOURCES") {
2015-08-17 11:37:30 +02:00
context->SourceSensitiveTargets.insert(target);
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (propertyName.empty()) {
reportError(
context, content->GetOriginalExpression(),
"$<TARGET_PROPERTY:...> expression requires a non-empty property "
"name.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (!propertyNameValidator.find(propertyName)) {
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"Property name not supported.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
assert(target);
2016-07-09 11:21:54 +02:00
if (propertyName == "LINKER_LANGUAGE") {
if (target->LinkLanguagePropagatesToDependents() && dagCheckerParent &&
(dagCheckerParent->EvaluatingLinkLibraries() ||
dagCheckerParent->EvaluatingSources())) {
reportError(
context, content->GetOriginalExpression(),
"LINKER_LANGUAGE target property can not be used while evaluating "
"link libraries for a static library");
2015-08-17 11:37:30 +02:00
return std::string();
}
2016-07-09 11:21:54 +02:00
return target->GetLinkerLanguage(context->Config);
}
2015-08-17 11:37:30 +02:00
cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
2016-07-09 11:21:54 +02:00
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:
2018-04-23 21:13:27 +02:00
for (size_t i = 1; i < cm::size(targetPropertyTransitiveWhitelist);
2016-07-09 11:21:54 +02:00
++i) {
if (targetPropertyTransitiveWhitelist[i] == propertyName) {
// No error. We're not going to find anything new here.
return std::string();
2015-08-17 11:37:30 +02:00
}
}
2016-07-09 11:21:54 +02:00
case cmGeneratorExpressionDAGChecker::DAG:
break;
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
const char* prop = target->GetProperty(propertyName);
if (dagCheckerParent) {
2018-08-09 18:06:22 +02:00
if (dagCheckerParent->EvaluatingGenexExpression()) {
// No check required.
} else if (dagCheckerParent->EvaluatingLinkLibraries()) {
2016-07-09 11:21:54 +02:00
#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
(#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(
2017-04-14 19:02:05 +02:00
TRANSITIVE_PROPERTY_COMPARE) false) { // NOLINT(clang-tidy)
2016-07-09 11:21:54 +02:00
reportError(
context, content->GetOriginalExpression(),
"$<TARGET_PROPERTY:...> expression in link libraries "
"evaluation depends on target property which is transitive "
"over the link libraries, creating a recursion.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
#undef TRANSITIVE_PROPERTY_COMPARE
2016-07-09 11:21:54 +02:00
if (!prop) {
2015-08-17 11:37:30 +02:00
return std::string();
}
2016-07-09 11:21:54 +02:00
} else {
#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) dagCheckerParent->METHOD() ||
assert(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
2017-04-14 19:02:05 +02:00
ASSERT_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(clang-tidy)
2015-08-17 11:37:30 +02:00
#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
}
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
std::string linkedTargetsContent;
std::string interfacePropertyName;
bool isInterfaceProperty = false;
2016-07-09 11:21:54 +02:00
#define POPULATE_INTERFACE_PROPERTY_NAME(prop) \
if (propertyName == #prop) { \
interfacePropertyName = "INTERFACE_" #prop; \
} else if (propertyName == "INTERFACE_" #prop) { \
interfacePropertyName = "INTERFACE_" #prop; \
isInterfaceProperty = true; \
} else
2015-08-17 11:37:30 +02:00
CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME)
2016-07-09 11:21:54 +02:00
// Note that the above macro terminates with an else
2018-04-23 21:13:27 +02:00
/* else */ if (cmHasLiteralPrefix(propertyName, "COMPILE_DEFINITIONS_")) {
2015-08-17 11:37:30 +02:00
cmPolicies::PolicyStatus polSt =
2016-07-09 11:21:54 +02:00
context->LG->GetPolicyStatus(cmPolicies::CMP0043);
if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
2015-08-17 11:37:30 +02:00
interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
}
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
#undef POPULATE_INTERFACE_PROPERTY_NAME
2016-03-13 13:35:51 +01:00
cmGeneratorTarget const* headTarget =
2016-07-09 11:21:54 +02:00
context->HeadTarget && isInterfaceProperty ? context->HeadTarget
: target;
if (isInterfaceProperty) {
if (cmLinkInterfaceLibraries const* iface =
target->GetLinkInterfaceLibraries(context->Config, headTarget,
true)) {
2015-08-17 11:37:30 +02:00
linkedTargetsContent =
2016-07-09 11:21:54 +02:00
getLinkedTargetsContent(iface->Libraries, target, headTarget,
context, &dagChecker, interfacePropertyName);
2015-08-17 11:37:30 +02:00
}
2016-07-09 11:21:54 +02:00
} else if (!interfacePropertyName.empty()) {
if (cmLinkImplementationLibraries const* impl =
target->GetLinkImplementationLibraries(context->Config)) {
2015-08-17 11:37:30 +02:00
linkedTargetsContent =
2016-07-09 11:21:54 +02:00
getLinkedTargetsContent(impl->Libraries, target, target, context,
&dagChecker, interfacePropertyName);
2015-08-17 11:37:30 +02:00
}
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (!prop) {
if (target->IsImported() ||
2017-04-14 19:02:05 +02:00
target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
2015-08-17 11:37:30 +02:00
return linkedTargetsContent;
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
2016-07-09 11:21:54 +02:00
context->Config)) {
2015-08-17 11:37:30 +02:00
context->HadContextSensitiveCondition = true;
2016-07-09 11:21:54 +02:00
return target->GetLinkInterfaceDependentBoolProperty(propertyName,
context->Config)
? "1"
: "0";
}
2016-03-13 13:35:51 +01:00
if (target->IsLinkInterfaceDependentStringProperty(propertyName,
2016-07-09 11:21:54 +02:00
context->Config)) {
2015-08-17 11:37:30 +02:00
context->HadContextSensitiveCondition = true;
2016-07-09 11:21:54 +02:00
const char* propContent =
target->GetLinkInterfaceDependentStringProperty(propertyName,
context->Config);
2015-08-17 11:37:30 +02:00
return propContent ? propContent : "";
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
2016-07-09 11:21:54 +02:00
context->Config)) {
2015-08-17 11:37:30 +02:00
context->HadContextSensitiveCondition = true;
2016-07-09 11:21:54 +02:00
const char* propContent =
target->GetLinkInterfaceDependentNumberMinProperty(propertyName,
context->Config);
2015-08-17 11:37:30 +02:00
return propContent ? propContent : "";
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
2016-07-09 11:21:54 +02:00
context->Config)) {
2015-08-17 11:37:30 +02:00
context->HadContextSensitiveCondition = true;
2016-07-09 11:21:54 +02:00
const char* propContent =
target->GetLinkInterfaceDependentNumberMaxProperty(propertyName,
context->Config);
2015-08-17 11:37:30 +02:00
return propContent ? propContent : "";
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return linkedTargetsContent;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (!target->IsImported() && dagCheckerParent &&
!dagCheckerParent->EvaluatingLinkLibraries()) {
2016-03-13 13:35:51 +01:00
if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
2016-07-09 11:21:54 +02:00
context->Config)) {
2015-08-17 11:37:30 +02:00
context->HadContextSensitiveCondition = true;
2016-07-09 11:21:54 +02:00
const char* propContent =
target->GetLinkInterfaceDependentNumberMinProperty(propertyName,
context->Config);
2015-08-17 11:37:30 +02:00
return propContent ? propContent : "";
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
2016-07-09 11:21:54 +02:00
context->Config)) {
2015-08-17 11:37:30 +02:00
context->HadContextSensitiveCondition = true;
2016-07-09 11:21:54 +02:00
const char* propContent =
target->GetLinkInterfaceDependentNumberMaxProperty(propertyName,
context->Config);
2015-08-17 11:37:30 +02:00
return propContent ? propContent : "";
}
2016-07-09 11:21:54 +02:00
}
if (!interfacePropertyName.empty()) {
std::string result = this->EvaluateDependentExpression(
prop, context->LG, context, headTarget, target, &dagChecker);
if (!linkedTargetsContent.empty()) {
2015-08-17 11:37:30 +02:00
result += (result.empty() ? "" : ";") + linkedTargetsContent;
}
2016-07-09 11:21:54 +02:00
return result;
}
2015-08-17 11:37:30 +02:00
return prop;
}
} targetPropertyNode;
static const struct TargetNameNode : public cmGeneratorExpressionNode
{
TargetNameNode() {}
2018-01-26 17:06:56 +01:00
bool GeneratesContent() const override { return true; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
bool AcceptsArbitraryContentParameter() const override { return true; }
bool RequiresLiteralInput() const override { return true; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* /*context*/,
const GeneratorExpressionContent* /*content*/,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
return parameters.front();
}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 1; }
2015-08-17 11:37:30 +02:00
} targetNameNode;
static const struct TargetObjectsNode : public cmGeneratorExpressionNode
{
TargetObjectsNode() {}
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
std::string tgtName = parameters.front();
2016-07-09 11:21:54 +02:00
cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);
if (!gt) {
2015-08-17 11:37:30 +02:00
std::ostringstream e;
e << "Objects of target \"" << tgtName
<< "\" referenced but no such target exists.";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
2016-07-09 11:21:54 +02:00
}
2017-04-14 19:02:05 +02:00
if (gt->GetType() != cmStateEnums::OBJECT_LIBRARY) {
2015-08-17 11:37:30 +02:00
std::ostringstream e;
e << "Objects of target \"" << tgtName
<< "\" referenced but is not an OBJECT library.";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
2016-07-09 11:21:54 +02:00
}
2017-07-20 19:35:53 +02:00
if (!context->EvaluateForBuildsystem) {
cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
std::string reason;
if (!gg->HasKnownObjectFileLocation(&reason)) {
std::ostringstream e;
e << "The evaluation of the TARGET_OBJECTS generator expression "
"is only suitable for consumption by CMake (limited"
2018-08-09 18:06:22 +02:00
<< reason
<< "). "
"It is not suitable for writing out elsewhere.";
2017-07-20 19:35:53 +02:00
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
}
2015-08-17 11:37:30 +02:00
2017-07-20 19:35:53 +02:00
std::vector<std::string> objects;
if (gt->IsImported()) {
2018-01-26 17:06:56 +01:00
const char* loc = nullptr;
const char* imp = nullptr;
2017-07-20 19:35:53 +02:00
std::string suffix;
if (gt->Target->GetMappedConfig(context->Config, &loc, &imp, suffix)) {
cmSystemTools::ExpandListArgument(loc, objects);
}
context->HadContextSensitiveCondition = true;
} else {
gt->GetTargetObjectNames(context->Config, objects);
std::string obj_dir;
if (context->EvaluateForBuildsystem) {
// Use object file directory with buildsystem placeholder.
obj_dir = gt->ObjectDirectory;
// Here we assume that the set of object files produced
// by an object library does not vary with configuration
// and do not set HadContextSensitiveCondition to true.
} else {
// Use object file directory with per-config location.
obj_dir = gt->GetObjectDirectory(context->Config);
context->HadContextSensitiveCondition = true;
}
2018-01-26 17:06:56 +01:00
for (std::string& o : objects) {
o = obj_dir + o;
2017-07-20 19:35:53 +02:00
}
2016-07-09 11:21:54 +02:00
}
2017-07-20 19:35:53 +02:00
// Create the cmSourceFile instances in the referencing directory.
cmMakefile* mf = context->LG->GetMakefile();
2018-01-26 17:06:56 +01:00
for (std::string& o : objects) {
mf->AddTargetObject(tgtName, o);
2017-07-20 19:35:53 +02:00
}
return cmJoin(objects, ";");
2015-08-17 11:37:30 +02:00
}
} targetObjectsNode;
static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
{
CompileFeaturesNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return OneOrMoreParameters; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagChecker) const override
2015-08-17 11:37:30 +02:00
{
2016-03-13 13:35:51 +01:00
cmGeneratorTarget const* target = context->HeadTarget;
2016-07-09 11:21:54 +02:00
if (!target) {
reportError(
context, content->GetOriginalExpression(),
"$<COMPILE_FEATURE> may only be used with binary targets. It may "
"not be used with add_custom_command or add_custom_target.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
context->HadHeadSensitiveCondition = true;
2018-01-26 17:06:56 +01:00
typedef std::map<std::string, std::vector<std::string>> LangMap;
2015-08-17 11:37:30 +02:00
static LangMap availableFeatures;
LangMap testedFeatures;
2018-01-26 17:06:56 +01:00
for (std::string const& p : parameters) {
2015-08-17 11:37:30 +02:00
std::string error;
std::string lang;
2016-03-13 13:35:51 +01:00
if (!context->LG->GetMakefile()->CompileFeatureKnown(
2018-01-26 17:06:56 +01:00
context->HeadTarget->Target, p, lang, &error)) {
2015-08-17 11:37:30 +02:00
reportError(context, content->GetOriginalExpression(), error);
return std::string();
2016-07-09 11:21:54 +02:00
}
2018-01-26 17:06:56 +01:00
testedFeatures[lang].push_back(p);
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
if (availableFeatures.find(lang) == availableFeatures.end()) {
const char* featuresKnown =
context->LG->GetMakefile()->CompileFeaturesAvailable(lang, &error);
if (!featuresKnown) {
2015-08-17 11:37:30 +02:00
reportError(context, content->GetOriginalExpression(), error);
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
cmSystemTools::ExpandListArgument(featuresKnown,
availableFeatures[lang]);
}
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
bool evalLL = dagChecker && dagChecker->EvaluatingLinkLibraries();
2018-01-26 17:06:56 +01:00
for (auto const& lit : testedFeatures) {
2016-07-09 11:21:54 +02:00
std::vector<std::string> const& langAvailable =
2018-01-26 17:06:56 +01:00
availableFeatures[lit.first];
2016-07-09 11:21:54 +02:00
const char* standardDefault = context->LG->GetMakefile()->GetDefinition(
2018-01-26 17:06:56 +01:00
"CMAKE_" + lit.first + "_STANDARD_DEFAULT");
for (std::string const& it : lit.second) {
if (std::find(langAvailable.begin(), langAvailable.end(), it) ==
2016-07-09 11:21:54 +02:00
langAvailable.end()) {
2015-08-17 11:37:30 +02:00
return "0";
2016-07-09 11:21:54 +02:00
}
if (standardDefault && !*standardDefault) {
2015-08-17 11:37:30 +02:00
// This compiler has no notion of language standard levels.
// All features known for the language are always available.
continue;
2016-07-09 11:21:54 +02:00
}
if (!context->LG->GetMakefile()->HaveStandardAvailable(
2018-01-26 17:06:56 +01:00
target->Target, lit.first, it)) {
2016-07-09 11:21:54 +02:00
if (evalLL) {
2018-01-26 17:06:56 +01:00
const char* l = target->GetProperty(lit.first + "_STANDARD");
2016-07-09 11:21:54 +02:00
if (!l) {
2015-08-17 11:37:30 +02:00
l = standardDefault;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
assert(l);
2018-01-26 17:06:56 +01:00
context->MaxLanguageStandard[target][lit.first] = l;
2016-07-09 11:21:54 +02:00
} else {
2015-08-17 11:37:30 +02:00
return "0";
}
}
}
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return "1";
}
} compileFeaturesNode;
static const char* targetPolicyWhitelist[] = {
2018-01-26 17:06:56 +01:00
nullptr
2016-07-09 11:21:54 +02:00
#define TARGET_POLICY_STRING(POLICY) , #POLICY
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
2015-08-17 11:37:30 +02:00
#undef TARGET_POLICY_STRING
};
2016-03-13 13:35:51 +01:00
cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt,
2016-07-09 11:21:54 +02:00
const char* policy)
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
#define RETURN_POLICY(POLICY) \
if (strcmp(policy, #POLICY) == 0) { \
return tgt->GetPolicyStatus##POLICY(); \
}
2015-08-17 11:37:30 +02:00
CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY)
#undef RETURN_POLICY
2017-04-14 19:02:05 +02:00
assert(false && "Unreachable code. Not a valid policy");
2015-08-17 11:37:30 +02:00
return cmPolicies::WARN;
}
2016-07-09 11:21:54 +02:00
cmPolicies::PolicyID policyForString(const char* policy_id)
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
#define RETURN_POLICY_ID(POLICY_ID) \
if (strcmp(policy_id, #POLICY_ID) == 0) { \
return cmPolicies::POLICY_ID; \
}
2015-08-17 11:37:30 +02:00
CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID)
#undef RETURN_POLICY_ID
2017-04-14 19:02:05 +02:00
assert(false && "Unreachable code. Not a valid policy");
2015-08-17 11:37:30 +02:00
return cmPolicies::CMP0002;
}
static const struct TargetPolicyNode : public cmGeneratorExpressionNode
{
TargetPolicyNode() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 1; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
if (!context->HeadTarget) {
reportError(
context, content->GetOriginalExpression(),
"$<TARGET_POLICY:prop> may only be used with binary targets. It "
"may not be used with add_custom_command or add_custom_target.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
context->HadContextSensitiveCondition = true;
context->HadHeadSensitiveCondition = true;
2018-04-23 21:13:27 +02:00
for (size_t i = 1; i < cm::size(targetPolicyWhitelist); ++i) {
2016-07-09 11:21:54 +02:00
const char* policy = targetPolicyWhitelist[i];
if (parameters.front() == policy) {
2016-03-13 13:35:51 +01:00
cmLocalGenerator* lg = context->HeadTarget->GetLocalGenerator();
2016-07-09 11:21:54 +02:00
switch (statusForTarget(context->HeadTarget, policy)) {
2015-08-17 11:37:30 +02:00
case cmPolicies::WARN:
2016-07-09 11:21:54 +02:00
lg->IssueMessage(
cmake::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(policyForString(policy)));
2017-07-20 19:35:53 +02:00
CM_FALLTHROUGH;
2015-08-17 11:37:30 +02:00
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::OLD:
return "0";
case cmPolicies::NEW:
return "1";
}
}
2016-07-09 11:21:54 +02:00
}
reportError(
context, content->GetOriginalExpression(),
2015-08-17 11:37:30 +02:00
"$<TARGET_POLICY:prop> may only be used with a limited number of "
"policies. Currently it may be used with the following policies:\n"
#define STRINGIFY_HELPER(X) #X
#define STRINGIFY(X) STRINGIFY_HELPER(X)
2016-07-09 11:21:54 +02:00
#define TARGET_POLICY_LIST_ITEM(POLICY) " * " STRINGIFY(POLICY) "\n"
2015-08-17 11:37:30 +02:00
CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
#undef TARGET_POLICY_LIST_ITEM
2018-08-09 18:06:22 +02:00
);
2015-08-17 11:37:30 +02:00
return std::string();
}
} targetPolicyNode;
static const struct InstallPrefixNode : public cmGeneratorExpressionNode
{
InstallPrefixNode() {}
2018-01-26 17:06:56 +01:00
bool GeneratesContent() const override { return true; }
int NumExpectedParameters() const override { return 0; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& /*parameters*/,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-08-17 11:37:30 +02:00
{
reportError(context, content->GetOriginalExpression(),
"INSTALL_PREFIX is a marker for install(EXPORT) only. It "
"should never be evaluated.");
return std::string();
}
} installPrefixNode;
2016-10-30 18:24:19 +01:00
class ArtifactDirTag;
2015-08-17 11:37:30 +02:00
class ArtifactLinkerTag;
2016-10-30 18:24:19 +01:00
class ArtifactNameTag;
2015-08-17 11:37:30 +02:00
class ArtifactPathTag;
2016-10-30 18:24:19 +01:00
class ArtifactPdbTag;
class ArtifactSonameTag;
2017-07-20 19:35:53 +02:00
class ArtifactBundleDirTag;
class ArtifactBundleContentDirTag;
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
template <typename ArtifactT>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifactResultCreator
{
2015-11-17 17:22:37 +01:00
static std::string Create(cmGeneratorTarget* target,
2016-07-09 11:21:54 +02:00
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content);
2015-08-17 11:37:30 +02:00
};
2016-07-09 11:21:54 +02:00
template <>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
{
2015-11-17 17:22:37 +01:00
static std::string Create(cmGeneratorTarget* target,
2016-07-09 11:21:54 +02:00
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
2015-08-17 11:37:30 +02:00
{
// The target soname file (.so.1).
2016-07-09 11:21:54 +02:00
if (target->IsDLLPlatform()) {
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"TARGET_SONAME_FILE is not allowed "
"for DLL target platforms.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2017-04-14 19:02:05 +02:00
if (target->GetType() != cmStateEnums::SHARED_LIBRARY) {
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"TARGET_SONAME_FILE is allowed only for "
"SHARED libraries.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
std::string result = target->GetDirectory(context->Config);
2015-08-17 11:37:30 +02:00
result += "/";
result += target->GetSOName(context->Config);
return result;
}
};
2016-07-09 11:21:54 +02:00
template <>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
{
2015-11-17 17:22:37 +01:00
static std::string Create(cmGeneratorTarget* target,
2016-07-09 11:21:54 +02:00
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
2015-08-17 11:37:30 +02:00
{
2016-07-09 11:21:54 +02:00
if (target->IsImported()) {
2015-11-17 17:22:37 +01:00
::reportError(context, content->GetOriginalExpression(),
"TARGET_PDB_FILE not allowed for IMPORTED targets.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-11-17 17:22:37 +01:00
2015-08-17 11:37:30 +02:00
std::string language = target->GetLinkerLanguage(context->Config);
std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB";
2016-07-09 11:21:54 +02:00
if (!context->LG->GetMakefile()->IsOn(pdbSupportVar)) {
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"TARGET_PDB_FILE is not supported by the target linker.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2017-04-14 19:02:05 +02:00
cmStateEnums::TargetType targetType = target->GetType();
2015-08-17 11:37:30 +02:00
2017-04-14 19:02:05 +02:00
if (targetType != cmStateEnums::SHARED_LIBRARY &&
targetType != cmStateEnums::MODULE_LIBRARY &&
targetType != cmStateEnums::EXECUTABLE) {
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"TARGET_PDB_FILE is allowed only for "
"targets with linker created artifacts.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
2016-03-13 13:35:51 +01:00
std::string result = target->GetPDBDirectory(context->Config);
2015-08-17 11:37:30 +02:00
result += "/";
result += target->GetPDBName(context->Config);
return result;
}
};
2016-07-09 11:21:54 +02:00
template <>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
{
2015-11-17 17:22:37 +01:00
static std::string Create(cmGeneratorTarget* target,
2016-07-09 11:21:54 +02:00
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
2015-08-17 11:37:30 +02:00
{
// The file used to link to the target (.so, .lib, .a).
2016-07-09 11:21:54 +02:00
if (!target->IsLinkable()) {
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"TARGET_LINKER_FILE is allowed only for libraries and "
"executables with ENABLE_EXPORTS.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2018-08-09 18:06:22 +02:00
cmStateEnums::ArtifactType artifact =
target->HasImportLibrary(context->Config)
2017-07-20 19:35:53 +02:00
? cmStateEnums::ImportLibraryArtifact
: cmStateEnums::RuntimeBinaryArtifact;
return target->GetFullPath(context->Config, artifact);
}
};
template <>
struct TargetFilesystemArtifactResultCreator<ArtifactBundleDirTag>
{
static std::string Create(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
if (target->IsImported()) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_BUNDLE_DIR not allowed for IMPORTED targets.");
return std::string();
}
if (!target->IsBundleOnApple()) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_BUNDLE_DIR is allowed only for Bundle targets.");
return std::string();
}
std::string outpath = target->GetDirectory(context->Config) + '/';
return target->BuildBundleDirectory(outpath, context->Config,
cmGeneratorTarget::BundleDirLevel);
}
};
template <>
struct TargetFilesystemArtifactResultCreator<ArtifactBundleContentDirTag>
{
static std::string Create(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
if (target->IsImported()) {
::reportError(
context, content->GetOriginalExpression(),
"TARGET_BUNDLE_CONTENT_DIR not allowed for IMPORTED targets.");
return std::string();
}
if (!target->IsBundleOnApple()) {
::reportError(
context, content->GetOriginalExpression(),
"TARGET_BUNDLE_CONTENT_DIR is allowed only for Bundle targets.");
return std::string();
}
std::string outpath = target->GetDirectory(context->Config) + '/';
return target->BuildBundleDirectory(outpath, context->Config,
cmGeneratorTarget::ContentLevel);
2015-08-17 11:37:30 +02:00
}
};
2016-07-09 11:21:54 +02:00
template <>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifactResultCreator<ArtifactNameTag>
{
2015-11-17 17:22:37 +01:00
static std::string Create(cmGeneratorTarget* target,
2016-07-09 11:21:54 +02:00
cmGeneratorExpressionContext* context,
2016-10-30 18:24:19 +01:00
const GeneratorExpressionContent* /*unused*/)
2015-08-17 11:37:30 +02:00
{
2017-07-20 19:35:53 +02:00
return target->GetFullPath(context->Config,
cmStateEnums::RuntimeBinaryArtifact, true);
2015-08-17 11:37:30 +02:00
}
};
2016-07-09 11:21:54 +02:00
template <typename ArtifactT>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifactResultGetter
{
2016-07-09 11:21:54 +02:00
static std::string Get(const std::string& result);
2015-08-17 11:37:30 +02:00
};
2016-07-09 11:21:54 +02:00
template <>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifactResultGetter<ArtifactNameTag>
{
2016-07-09 11:21:54 +02:00
static std::string Get(const std::string& result)
{
return cmSystemTools::GetFilenameName(result);
}
2015-08-17 11:37:30 +02:00
};
2016-07-09 11:21:54 +02:00
template <>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifactResultGetter<ArtifactDirTag>
{
2016-07-09 11:21:54 +02:00
static std::string Get(const std::string& result)
{
return cmSystemTools::GetFilenamePath(result);
}
2015-08-17 11:37:30 +02:00
};
2016-07-09 11:21:54 +02:00
template <>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifactResultGetter<ArtifactPathTag>
{
2016-07-09 11:21:54 +02:00
static std::string Get(const std::string& result) { return result; }
2015-08-17 11:37:30 +02:00
};
2016-07-09 11:21:54 +02:00
template <typename ArtifactT, typename ComponentT>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
{
TargetFilesystemArtifact() {}
2018-01-26 17:06:56 +01:00
int NumExpectedParameters() const override { return 1; }
2015-08-17 11:37:30 +02:00
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* dagChecker) const override
2015-08-17 11:37:30 +02:00
{
// Lookup the referenced target.
std::string name = *parameters.begin();
2016-07-09 11:21:54 +02:00
if (!cmGeneratorExpression::IsValidTargetName(name)) {
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"Expression syntax not recognized.");
return std::string();
2016-07-09 11:21:54 +02:00
}
cmGeneratorTarget* target = context->LG->FindGeneratorTargetToUse(name);
if (!target) {
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"No target \"" + name + "\"");
return std::string();
2016-07-09 11:21:54 +02:00
}
2017-04-14 19:02:05 +02:00
if (target->GetType() >= cmStateEnums::OBJECT_LIBRARY &&
target->GetType() != cmStateEnums::UNKNOWN_LIBRARY) {
2018-08-09 18:06:22 +02:00
::reportError(context, content->GetOriginalExpression(),
"Target \"" + name +
"\" is not an executable or library.");
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
2018-08-09 18:06:22 +02:00
if (dagChecker &&
(dagChecker->EvaluatingLinkLibraries(name.c_str()) ||
(dagChecker->EvaluatingSources() &&
name == dagChecker->TopTarget()))) {
2015-08-17 11:37:30 +02:00
::reportError(context, content->GetOriginalExpression(),
"Expressions which require the linker language may not "
"be used while evaluating link libraries");
return std::string();
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
context->DependTargets.insert(target);
context->AllTargets.insert(target);
2015-08-17 11:37:30 +02:00
std::string result =
2016-07-09 11:21:54 +02:00
TargetFilesystemArtifactResultCreator<ArtifactT>::Create(target, context,
content);
if (context->HadError) {
2015-08-17 11:37:30 +02:00
return std::string();
2016-07-09 11:21:54 +02:00
}
return TargetFilesystemArtifactResultGetter<ComponentT>::Get(result);
2015-08-17 11:37:30 +02:00
}
};
2016-07-09 11:21:54 +02:00
template <typename ArtifactT>
2015-08-17 11:37:30 +02:00
struct TargetFilesystemArtifactNodeGroup
{
2016-07-09 11:21:54 +02:00
TargetFilesystemArtifactNodeGroup() {}
2015-08-17 11:37:30 +02:00
TargetFilesystemArtifact<ArtifactT, ArtifactPathTag> File;
TargetFilesystemArtifact<ArtifactT, ArtifactNameTag> FileName;
TargetFilesystemArtifact<ArtifactT, ArtifactDirTag> FileDir;
};
2016-07-09 11:21:54 +02:00
static const TargetFilesystemArtifactNodeGroup<ArtifactNameTag>
targetNodeGroup;
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
static const TargetFilesystemArtifactNodeGroup<ArtifactLinkerTag>
targetLinkerNodeGroup;
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
static const TargetFilesystemArtifactNodeGroup<ArtifactSonameTag>
targetSoNameNodeGroup;
2015-08-17 11:37:30 +02:00
2016-07-09 11:21:54 +02:00
static const TargetFilesystemArtifactNodeGroup<ArtifactPdbTag>
targetPdbNodeGroup;
2015-08-17 11:37:30 +02:00
2017-07-20 19:35:53 +02:00
static const TargetFilesystemArtifact<ArtifactBundleDirTag, ArtifactPathTag>
targetBundleDirNode;
static const TargetFilesystemArtifact<ArtifactBundleContentDirTag,
ArtifactPathTag>
targetBundleContentDirNode;
2015-11-17 17:22:37 +01:00
static const struct ShellPathNode : public cmGeneratorExpressionNode
{
ShellPathNode() {}
2018-01-26 17:06:56 +01:00
std::string Evaluate(
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
2015-11-17 17:22:37 +01:00
{
2016-07-09 11:21:54 +02:00
if (!cmSystemTools::FileIsFullPath(parameters.front())) {
2015-11-17 17:22:37 +01:00
reportError(context, content->GetOriginalExpression(),
"\"" + parameters.front() + "\" is not an absolute path.");
return std::string();
2016-07-09 11:21:54 +02:00
}
2016-03-13 13:35:51 +01:00
cmOutputConverter converter(context->LG->GetStateSnapshot());
2015-11-17 17:22:37 +01:00
return converter.ConvertDirectorySeparatorsForShell(parameters.front());
}
} shellPathNode;
2016-07-09 11:21:54 +02:00
const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
const std::string& identifier)
2015-08-17 11:37:30 +02:00
{
typedef std::map<std::string, const cmGeneratorExpressionNode*> NodeMap;
static NodeMap nodeMap;
2016-07-09 11:21:54 +02:00
if (nodeMap.empty()) {
2015-08-17 11:37:30 +02:00
nodeMap["0"] = &zeroNode;
nodeMap["1"] = &oneNode;
nodeMap["AND"] = &andNode;
nodeMap["OR"] = &orNode;
nodeMap["NOT"] = &notNode;
nodeMap["C_COMPILER_ID"] = &cCompilerIdNode;
nodeMap["CXX_COMPILER_ID"] = &cxxCompilerIdNode;
nodeMap["VERSION_GREATER"] = &versionGreaterNode;
2016-10-30 18:24:19 +01:00
nodeMap["VERSION_GREATER_EQUAL"] = &versionGreaterEqNode;
2015-08-17 11:37:30 +02:00
nodeMap["VERSION_LESS"] = &versionLessNode;
2016-10-30 18:24:19 +01:00
nodeMap["VERSION_LESS_EQUAL"] = &versionLessEqNode;
2015-08-17 11:37:30 +02:00
nodeMap["VERSION_EQUAL"] = &versionEqualNode;
nodeMap["C_COMPILER_VERSION"] = &cCompilerVersionNode;
nodeMap["CXX_COMPILER_VERSION"] = &cxxCompilerVersionNode;
nodeMap["PLATFORM_ID"] = &platformIdNode;
nodeMap["COMPILE_FEATURES"] = &compileFeaturesNode;
nodeMap["CONFIGURATION"] = &configurationNode;
nodeMap["CONFIG"] = &configurationTestNode;
nodeMap["TARGET_FILE"] = &targetNodeGroup.File;
nodeMap["TARGET_LINKER_FILE"] = &targetLinkerNodeGroup.File;
nodeMap["TARGET_SONAME_FILE"] = &targetSoNameNodeGroup.File;
nodeMap["TARGET_PDB_FILE"] = &targetPdbNodeGroup.File;
nodeMap["TARGET_FILE_NAME"] = &targetNodeGroup.FileName;
nodeMap["TARGET_LINKER_FILE_NAME"] = &targetLinkerNodeGroup.FileName;
nodeMap["TARGET_SONAME_FILE_NAME"] = &targetSoNameNodeGroup.FileName;
nodeMap["TARGET_PDB_FILE_NAME"] = &targetPdbNodeGroup.FileName;
nodeMap["TARGET_FILE_DIR"] = &targetNodeGroup.FileDir;
nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerNodeGroup.FileDir;
nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameNodeGroup.FileDir;
nodeMap["TARGET_PDB_FILE_DIR"] = &targetPdbNodeGroup.FileDir;
2017-07-20 19:35:53 +02:00
nodeMap["TARGET_BUNDLE_DIR"] = &targetBundleDirNode;
nodeMap["TARGET_BUNDLE_CONTENT_DIR"] = &targetBundleContentDirNode;
2015-08-17 11:37:30 +02:00
nodeMap["STREQUAL"] = &strEqualNode;
nodeMap["EQUAL"] = &equalNode;
2018-08-09 18:06:22 +02:00
nodeMap["IN_LIST"] = &inListNode;
2015-08-17 11:37:30 +02:00
nodeMap["LOWER_CASE"] = &lowerCaseNode;
nodeMap["UPPER_CASE"] = &upperCaseNode;
nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode;
nodeMap["BOOL"] = &boolNode;
2017-04-14 19:02:05 +02:00
nodeMap["IF"] = &ifNode;
2015-08-17 11:37:30 +02:00
nodeMap["ANGLE-R"] = &angle_rNode;
nodeMap["COMMA"] = &commaNode;
nodeMap["SEMICOLON"] = &semicolonNode;
nodeMap["TARGET_PROPERTY"] = &targetPropertyNode;
nodeMap["TARGET_NAME"] = &targetNameNode;
nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
nodeMap["TARGET_POLICY"] = &targetPolicyNode;
2018-08-09 18:06:22 +02:00
nodeMap["TARGET_EXISTS"] = &targetExistsNode;
nodeMap["TARGET_NAME_IF_EXISTS"] = &targetNameIfExistsNode;
nodeMap["TARGET_GENEX_EVAL"] = &targetGenexEvalNode;
nodeMap["GENEX_EVAL"] = &genexEvalNode;
2015-08-17 11:37:30 +02:00
nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;
nodeMap["INSTALL_PREFIX"] = &installPrefixNode;
nodeMap["JOIN"] = &joinNode;
nodeMap["LINK_ONLY"] = &linkOnlyNode;
nodeMap["COMPILE_LANGUAGE"] = &languageNode;
2015-11-17 17:22:37 +01:00
nodeMap["SHELL_PATH"] = &shellPathNode;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
NodeMap::const_iterator i = nodeMap.find(identifier);
2016-07-09 11:21:54 +02:00
if (i == nodeMap.end()) {
2018-01-26 17:06:56 +01:00
return nullptr;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
return i->second;
}
2016-07-09 11:21:54 +02:00
void reportError(cmGeneratorExpressionContext* context,
const std::string& expr, const std::string& result)
2015-08-17 11:37:30 +02:00
{
context->HadError = true;
2016-07-09 11:21:54 +02:00
if (context->Quiet) {
2015-08-17 11:37:30 +02:00
return;
2016-07-09 11:21:54 +02:00
}
2015-08-17 11:37:30 +02:00
std::ostringstream e;
2016-07-09 11:21:54 +02:00
/* clang-format off */
2015-08-17 11:37:30 +02:00
e << "Error evaluating generator expression:\n"
<< " " << expr << "\n"
<< result;
2016-07-09 11:21:54 +02:00
/* clang-format on */
context->LG->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
context->Backtrace);
2015-08-17 11:37:30 +02:00
}