/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCMakePolicyCommand.h" #include #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" #include "cmState.h" #include "cmStateTypes.h" namespace { bool HandleSetMode(std::vector const& args, cmExecutionStatus& status); bool HandleGetMode(std::vector const& args, cmExecutionStatus& status); bool HandleVersionMode(std::vector const& args, cmExecutionStatus& status); bool HandleGetWarningMode(std::vector const& args, cmExecutionStatus& status); } // cmCMakePolicyCommand bool cmCMakePolicyCommand(std::vector const& args, cmExecutionStatus& status) { if (args.empty()) { status.SetError("requires at least one argument."); return false; } if (args[0] == "SET") { return HandleSetMode(args, status); } if (args[0] == "GET") { return HandleGetMode(args, status); } if (args[0] == "PUSH") { if (args.size() > 1) { status.SetError("PUSH may not be given additional arguments."); return false; } status.GetMakefile().PushPolicy(); return true; } if (args[0] == "POP") { if (args.size() > 1) { status.SetError("POP may not be given additional arguments."); return false; } status.GetMakefile().PopPolicy(); return true; } if (args[0] == "VERSION") { return HandleVersionMode(args, status); } if (args[0] == "GET_WARNING") { return HandleGetWarningMode(args, status); } std::ostringstream e; e << "given unknown first argument \"" << args[0] << "\""; status.SetError(e.str()); return false; } namespace { bool HandleSetMode(std::vector const& args, cmExecutionStatus& status) { if (args.size() != 3) { status.SetError("SET must be given exactly 2 additional arguments."); return false; } cmPolicies::PolicyStatus policyStatus; if (args[2] == "OLD") { policyStatus = cmPolicies::OLD; } else if (args[2] == "NEW") { policyStatus = cmPolicies::NEW; } else { std::ostringstream e; e << "SET given unrecognized policy status \"" << args[2] << "\""; status.SetError(e.str()); return false; } if (!status.GetMakefile().SetPolicy(args[1].c_str(), policyStatus)) { status.SetError("SET failed to set policy."); return false; } if (args[1] == "CMP0001" && (policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD)) { if (!(status.GetMakefile().GetState()->GetInitializedCacheValue( "CMAKE_BACKWARDS_COMPATIBILITY"))) { // Set it to 2.4 because that is the last version where the // variable had meaning. status.GetMakefile().AddCacheDefinition( "CMAKE_BACKWARDS_COMPATIBILITY", "2.4", "For backwards compatibility, what version of CMake " "commands and " "syntax should this version of CMake try to support.", cmStateEnums::STRING); } } return true; } bool HandleGetMode(std::vector const& args, cmExecutionStatus& status) { bool parent_scope = false; if (args.size() == 4 && args[3] == "PARENT_SCOPE") { // Undocumented PARENT_SCOPE option for use within CMake. parent_scope = true; } else if (args.size() != 3) { status.SetError("GET must be given exactly 2 additional arguments."); return false; } // Get arguments. std::string const& id = args[1]; std::string const& var = args[2]; // Lookup the policy number. cmPolicies::PolicyID pid; if (!cmPolicies::GetPolicyID(id.c_str(), pid)) { std::ostringstream e; e << "GET given policy \"" << id << "\" which is not known to this " << "version of CMake."; status.SetError(e.str()); return false; } // Lookup the policy setting. cmPolicies::PolicyStatus policyStatus = status.GetMakefile().GetPolicyStatus(pid, parent_scope); switch (policyStatus) { case cmPolicies::OLD: // Report that the policy is set to OLD. status.GetMakefile().AddDefinition(var, "OLD"); break; case cmPolicies::WARN: // Report that the policy is not set. status.GetMakefile().AddDefinition(var, ""); break; case cmPolicies::NEW: // Report that the policy is set to NEW. status.GetMakefile().AddDefinition(var, "NEW"); break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: // The policy is required to be set before anything needs it. { std::ostringstream e; e << cmPolicies::GetRequiredPolicyError(pid) << "\n" << "The call to cmake_policy(GET " << id << " ...) at which this " << "error appears requests the policy, and this version of CMake " << "requires that the policy be set to NEW before it is checked."; status.GetMakefile().IssueMessage(MessageType::FATAL_ERROR, e.str()); } } return true; } bool HandleVersionMode(std::vector const& args, cmExecutionStatus& status) { if (args.size() <= 1) { status.SetError("VERSION not given an argument"); return false; } if (args.size() >= 3) { status.SetError("VERSION given too many arguments"); return false; } std::string const& version_string = args[1]; // Separate the version and any trailing ... component. std::string::size_type const dd = version_string.find("..."); std::string const version_min = version_string.substr(0, dd); std::string const version_max = dd != std::string::npos ? version_string.substr(dd + 3, std::string::npos) : std::string(); if (dd != std::string::npos && (version_min.empty() || version_max.empty())) { std::ostringstream e; e << "VERSION \"" << version_string << R"(" does not have a version on both sides of "...".)"; status.SetError(e.str()); return false; } status.GetMakefile().SetPolicyVersion(version_min, version_max); return true; } bool HandleGetWarningMode(std::vector const& args, cmExecutionStatus& status) { if (args.size() != 3) { status.SetError( "GET_WARNING must be given exactly 2 additional arguments."); return false; } // Get arguments. std::string const& id = args[1]; std::string const& var = args[2]; // Lookup the policy number. cmPolicies::PolicyID pid; if (!cmPolicies::GetPolicyID(id.c_str(), pid)) { std::ostringstream e; e << "GET_WARNING given policy \"" << id << "\" which is not known to this version of CMake."; status.SetError(e.str()); return false; } // Lookup the policy warning. status.GetMakefile().AddDefinition(var, cmPolicies::GetPolicyWarning(pid)); return true; } }