1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmCMakePolicyCommand.h"
5 #include "cmExecutionStatus.h"
6 #include "cmMakefile.h"
7 #include "cmMessageType.h"
8 #include "cmPolicies.h"
10 #include "cmStateTypes.h"
11 #include "cmStringAlgorithms.h"
15 bool HandleSetMode(std::vector<std::string> const& args,
16 cmExecutionStatus& status);
17 bool HandleGetMode(std::vector<std::string> const& args,
18 cmExecutionStatus& status);
19 bool HandleVersionMode(std::vector<std::string> const& args,
20 cmExecutionStatus& status);
21 bool HandleGetWarningMode(std::vector<std::string> const& args,
22 cmExecutionStatus& status);
25 // cmCMakePolicyCommand
26 bool cmCMakePolicyCommand(std::vector<std::string> const& args,
27 cmExecutionStatus& status)
30 status.SetError("requires at least one argument.");
34 if (args[0] == "SET") {
35 return HandleSetMode(args, status);
37 if (args[0] == "GET") {
38 return HandleGetMode(args, status);
40 if (args[0] == "PUSH") {
41 if (args.size() > 1) {
42 status.SetError("PUSH may not be given additional arguments.");
45 status.GetMakefile().PushPolicy();
48 if (args[0] == "POP") {
49 if (args.size() > 1) {
50 status.SetError("POP may not be given additional arguments.");
53 status.GetMakefile().PopPolicy();
56 if (args[0] == "VERSION") {
57 return HandleVersionMode(args, status);
59 if (args[0] == "GET_WARNING") {
60 return HandleGetWarningMode(args, status);
63 status.SetError(cmStrCat("given unknown first argument \"", args[0], "\""));
69 bool HandleSetMode(std::vector<std::string> const& args,
70 cmExecutionStatus& status)
72 if (args.size() != 3) {
73 status.SetError("SET must be given exactly 2 additional arguments.");
77 cmPolicies::PolicyStatus policyStatus;
78 if (args[2] == "OLD") {
79 policyStatus = cmPolicies::OLD;
80 } else if (args[2] == "NEW") {
81 policyStatus = cmPolicies::NEW;
84 cmStrCat("SET given unrecognized policy status \"", args[2], "\""));
88 if (!status.GetMakefile().SetPolicy(args[1].c_str(), policyStatus)) {
89 status.SetError("SET failed to set policy.");
92 if (args[1] == "CMP0001" &&
93 (policyStatus == cmPolicies::WARN || policyStatus == cmPolicies::OLD)) {
94 if (!(status.GetMakefile().GetState()->GetInitializedCacheValue(
95 "CMAKE_BACKWARDS_COMPATIBILITY"))) {
96 // Set it to 2.4 because that is the last version where the
97 // variable had meaning.
98 status.GetMakefile().AddCacheDefinition(
99 "CMAKE_BACKWARDS_COMPATIBILITY", "2.4",
100 "For backwards compatibility, what version of CMake "
102 "syntax should this version of CMake try to support.",
103 cmStateEnums::STRING);
109 bool HandleGetMode(std::vector<std::string> const& args,
110 cmExecutionStatus& status)
112 bool parent_scope = false;
113 if (args.size() == 4 && args[3] == "PARENT_SCOPE") {
114 // Undocumented PARENT_SCOPE option for use within CMake.
116 } else if (args.size() != 3) {
117 status.SetError("GET must be given exactly 2 additional arguments.");
122 std::string const& id = args[1];
123 std::string const& var = args[2];
125 // Lookup the policy number.
126 cmPolicies::PolicyID pid;
127 if (!cmPolicies::GetPolicyID(id.c_str(), pid)) {
129 cmStrCat("GET given policy \"", id,
130 "\" which is not known to this version of CMake."));
134 // Lookup the policy setting.
135 cmPolicies::PolicyStatus policyStatus =
136 status.GetMakefile().GetPolicyStatus(pid, parent_scope);
137 switch (policyStatus) {
138 case cmPolicies::OLD:
139 // Report that the policy is set to OLD.
140 status.GetMakefile().AddDefinition(var, "OLD");
142 case cmPolicies::WARN:
143 // Report that the policy is not set.
144 status.GetMakefile().AddDefinition(var, "");
146 case cmPolicies::NEW:
147 // Report that the policy is set to NEW.
148 status.GetMakefile().AddDefinition(var, "NEW");
150 case cmPolicies::REQUIRED_IF_USED:
151 case cmPolicies::REQUIRED_ALWAYS:
152 // The policy is required to be set before anything needs it.
154 status.GetMakefile().IssueMessage(
155 MessageType::FATAL_ERROR,
157 cmPolicies::GetRequiredPolicyError(pid), "\n",
158 "The call to cmake_policy(GET ", id,
159 " ...) at which this "
160 "error appears requests the policy, and this version of CMake ",
161 "requires that the policy be set to NEW before it is checked."));
168 bool HandleVersionMode(std::vector<std::string> const& args,
169 cmExecutionStatus& status)
171 if (args.size() <= 1) {
172 status.SetError("VERSION not given an argument");
175 if (args.size() >= 3) {
176 status.SetError("VERSION given too many arguments");
179 std::string const& version_string = args[1];
181 // Separate the <min> version and any trailing ...<max> component.
182 std::string::size_type const dd = version_string.find("...");
183 std::string const version_min = version_string.substr(0, dd);
184 std::string const version_max = dd != std::string::npos
185 ? version_string.substr(dd + 3, std::string::npos)
187 if (dd != std::string::npos &&
188 (version_min.empty() || version_max.empty())) {
190 cmStrCat("VERSION \"", version_string,
191 R"(" does not have a version on both sides of "...".)"));
195 return status.GetMakefile().SetPolicyVersion(version_min, version_max);
198 bool HandleGetWarningMode(std::vector<std::string> const& args,
199 cmExecutionStatus& status)
201 if (args.size() != 3) {
203 "GET_WARNING must be given exactly 2 additional arguments.");
208 std::string const& id = args[1];
209 std::string const& var = args[2];
211 // Lookup the policy number.
212 cmPolicies::PolicyID pid;
213 if (!cmPolicies::GetPolicyID(id.c_str(), pid)) {
215 cmStrCat("GET_WARNING given policy \"", id,
216 "\" which is not known to this version of CMake."));
220 // Lookup the policy warning.
221 status.GetMakefile().AddDefinition(var, cmPolicies::GetPolicyWarning(pid));