123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file LICENSE.rst or https://cmake.org/licensing for details. */
- #include "cmGeneratorExpressionEvaluator.h"
- #include <sstream>
- #ifndef CMAKE_BOOTSTRAP
- # include <cm3p/json/value.h>
- #endif
- #include "cmGenExContext.h"
- #include "cmGenExEvaluation.h"
- #include "cmGeneratorExpressionNode.h"
- #include "cmLocalGenerator.h"
- #include "cmake.h"
- GeneratorExpressionContent::GeneratorExpressionContent(
- char const* startContent, size_t length)
- : StartContent(startContent)
- , ContentLength(length)
- {
- }
- GeneratorExpressionContent::~GeneratorExpressionContent() = default;
- std::string GeneratorExpressionContent::GetOriginalExpression() const
- {
- return std::string(this->StartContent, this->ContentLength);
- }
- std::string GeneratorExpressionContent::ProcessArbitraryContent(
- cmGeneratorExpressionNode const* node, std::string const& identifier,
- cm::GenEx::Evaluation* eval, cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<cmGeneratorExpressionEvaluatorVector>::const_iterator pit) const
- {
- std::string result;
- auto const pend = this->ParamChildren.end();
- for (; pit != pend; ++pit) {
- for (auto const& pExprEval : *pit) {
- if (node->RequiresLiteralInput()) {
- if (pExprEval->GetType() != cmGeneratorExpressionEvaluator::Text) {
- reportError(eval, this->GetOriginalExpression(),
- "$<" + identifier +
- "> expression requires literal input.");
- return std::string();
- }
- }
- result += pExprEval->Evaluate(eval, dagChecker);
- if (eval->HadError) {
- return std::string();
- }
- }
- if ((pit + 1) != pend) {
- result += ",";
- }
- }
- if (node->RequiresLiteralInput()) {
- std::vector<std::string> parameters;
- parameters.push_back(result);
- return node->Evaluate(parameters, eval, this, dagChecker);
- }
- return result;
- }
- std::string GeneratorExpressionContent::Evaluate(
- cm::GenEx::Evaluation* eval,
- cmGeneratorExpressionDAGChecker* dagChecker) const
- {
- #ifndef CMAKE_BOOTSTRAP
- auto evalProfilingRAII =
- eval->Context.LG->GetCMakeInstance()->CreateProfilingEntry(
- "genex_eval", this->GetOriginalExpression());
- #endif
- std::string identifier;
- {
- for (auto const& pExprEval : this->IdentifierChildren) {
- identifier += pExprEval->Evaluate(eval, dagChecker);
- if (eval->HadError) {
- return std::string();
- }
- }
- }
- cmGeneratorExpressionNode const* node =
- cmGeneratorExpressionNode::GetNode(identifier);
- if (!node) {
- reportError(eval, this->GetOriginalExpression(),
- "Expression did not evaluate to a known generator expression");
- return std::string();
- }
- if (!node->GeneratesContent()) {
- if (node->NumExpectedParameters() == 1 &&
- node->AcceptsArbitraryContentParameter()) {
- if (this->ParamChildren.empty()) {
- reportError(eval, this->GetOriginalExpression(),
- "$<" + identifier + "> expression requires a parameter.");
- }
- } else {
- std::vector<std::string> parameters;
- this->EvaluateParameters(node, identifier, eval, dagChecker, parameters);
- }
- return std::string();
- }
- std::vector<std::string> parameters;
- this->EvaluateParameters(node, identifier, eval, dagChecker, parameters);
- if (eval->HadError) {
- return std::string();
- }
- {
- #ifndef CMAKE_BOOTSTRAP
- auto execProfilingRAII =
- eval->Context.LG->GetCMakeInstance()->CreateProfilingEntry(
- "genex_exec", identifier, [¶meters]() -> Json::Value {
- Json::Value args = Json::objectValue;
- if (!parameters.empty()) {
- args["genexArgs"] = Json::arrayValue;
- for (auto const& parameter : parameters) {
- args["genexArgs"].append(parameter);
- }
- }
- return args;
- });
- #endif
- return node->Evaluate(parameters, eval, this, dagChecker);
- }
- }
- std::string GeneratorExpressionContent::EvaluateParameters(
- cmGeneratorExpressionNode const* node, std::string const& identifier,
- cm::GenEx::Evaluation* eval, cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<std::string>& parameters) const
- {
- int const numExpected = node->NumExpectedParameters();
- {
- auto pit = this->ParamChildren.begin();
- auto const pend = this->ParamChildren.end();
- bool const acceptsArbitraryContent =
- node->AcceptsArbitraryContentParameter();
- int counter = 1;
- for (; pit != pend; ++pit, ++counter) {
- if (acceptsArbitraryContent && counter == numExpected) {
- parameters.push_back(this->ProcessArbitraryContent(
- node, identifier, eval, dagChecker, pit));
- return std::string();
- }
- std::string parameter;
- if (node->ShouldEvaluateNextParameter(parameters, parameter)) {
- for (auto const& pExprEval : *pit) {
- parameter += pExprEval->Evaluate(eval, dagChecker);
- if (eval->HadError) {
- return std::string();
- }
- }
- }
- parameters.push_back(std::move(parameter));
- }
- }
- if ((numExpected > cmGeneratorExpressionNode::DynamicParameters &&
- static_cast<unsigned int>(numExpected) != parameters.size())) {
- if (numExpected == 0) {
- reportError(eval, this->GetOriginalExpression(),
- "$<" + identifier + "> expression requires no parameters.");
- } else if (numExpected == 1) {
- reportError(eval, this->GetOriginalExpression(),
- "$<" + identifier +
- "> expression requires "
- "exactly one parameter.");
- } else {
- std::ostringstream e;
- e << "$<" + identifier + "> expression requires " << numExpected
- << " comma separated parameters, but got " << parameters.size()
- << " instead.";
- reportError(eval, this->GetOriginalExpression(), e.str());
- }
- return std::string();
- }
- if (numExpected == cmGeneratorExpressionNode::OneOrMoreParameters &&
- parameters.empty()) {
- reportError(eval, this->GetOriginalExpression(),
- "$<" + identifier +
- "> expression requires at least one parameter.");
- } else if (numExpected == cmGeneratorExpressionNode::TwoOrMoreParameters &&
- parameters.size() < 2) {
- reportError(eval, this->GetOriginalExpression(),
- "$<" + identifier +
- "> expression requires at least two parameters.");
- } else if (numExpected == cmGeneratorExpressionNode::OneOrZeroParameters &&
- parameters.size() > 1) {
- reportError(eval, this->GetOriginalExpression(),
- "$<" + identifier +
- "> expression requires one or zero parameters.");
- }
- return std::string();
- }
|