resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmCMakePolicyCommand.cxx
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"
4
5 #include "cmExecutionStatus.h"
6 #include "cmMakefile.h"
7 #include "cmMessageType.h"
8 #include "cmPolicies.h"
9 #include "cmState.h"
10 #include "cmStateTypes.h"
11 #include "cmStringAlgorithms.h"
12 #include "cmValue.h"
13
14 namespace {
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);
23 }
24
25 // cmCMakePolicyCommand
26 bool cmCMakePolicyCommand(std::vector<std::string> const& args,
27                           cmExecutionStatus& status)
28 {
29   if (args.empty()) {
30     status.SetError("requires at least one argument.");
31     return false;
32   }
33
34   if (args[0] == "SET") {
35     return HandleSetMode(args, status);
36   }
37   if (args[0] == "GET") {
38     return HandleGetMode(args, status);
39   }
40   if (args[0] == "PUSH") {
41     if (args.size() > 1) {
42       status.SetError("PUSH may not be given additional arguments.");
43       return false;
44     }
45     status.GetMakefile().PushPolicy();
46     return true;
47   }
48   if (args[0] == "POP") {
49     if (args.size() > 1) {
50       status.SetError("POP may not be given additional arguments.");
51       return false;
52     }
53     status.GetMakefile().PopPolicy();
54     return true;
55   }
56   if (args[0] == "VERSION") {
57     return HandleVersionMode(args, status);
58   }
59   if (args[0] == "GET_WARNING") {
60     return HandleGetWarningMode(args, status);
61   }
62
63   status.SetError(cmStrCat("given unknown first argument \"", args[0], "\""));
64   return false;
65 }
66
67 namespace {
68
69 bool HandleSetMode(std::vector<std::string> const& args,
70                    cmExecutionStatus& status)
71 {
72   if (args.size() != 3) {
73     status.SetError("SET must be given exactly 2 additional arguments.");
74     return false;
75   }
76
77   cmPolicies::PolicyStatus policyStatus;
78   if (args[2] == "OLD") {
79     policyStatus = cmPolicies::OLD;
80   } else if (args[2] == "NEW") {
81     policyStatus = cmPolicies::NEW;
82   } else {
83     status.SetError(
84       cmStrCat("SET given unrecognized policy status \"", args[2], "\""));
85     return false;
86   }
87
88   if (!status.GetMakefile().SetPolicy(args[1].c_str(), policyStatus)) {
89     status.SetError("SET failed to set policy.");
90     return false;
91   }
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 "
101         "commands and "
102         "syntax should this version of CMake try to support.",
103         cmStateEnums::STRING);
104     }
105   }
106   return true;
107 }
108
109 bool HandleGetMode(std::vector<std::string> const& args,
110                    cmExecutionStatus& status)
111 {
112   bool parent_scope = false;
113   if (args.size() == 4 && args[3] == "PARENT_SCOPE") {
114     // Undocumented PARENT_SCOPE option for use within CMake.
115     parent_scope = true;
116   } else if (args.size() != 3) {
117     status.SetError("GET must be given exactly 2 additional arguments.");
118     return false;
119   }
120
121   // Get arguments.
122   std::string const& id = args[1];
123   std::string const& var = args[2];
124
125   // Lookup the policy number.
126   cmPolicies::PolicyID pid;
127   if (!cmPolicies::GetPolicyID(id.c_str(), pid)) {
128     status.SetError(
129       cmStrCat("GET given policy \"", id,
130                "\" which is not known to this version of CMake."));
131     return false;
132   }
133
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");
141       break;
142     case cmPolicies::WARN:
143       // Report that the policy is not set.
144       status.GetMakefile().AddDefinition(var, "");
145       break;
146     case cmPolicies::NEW:
147       // Report that the policy is set to NEW.
148       status.GetMakefile().AddDefinition(var, "NEW");
149       break;
150     case cmPolicies::REQUIRED_IF_USED:
151     case cmPolicies::REQUIRED_ALWAYS:
152       // The policy is required to be set before anything needs it.
153       {
154         status.GetMakefile().IssueMessage(
155           MessageType::FATAL_ERROR,
156           cmStrCat(
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."));
162       }
163   }
164
165   return true;
166 }
167
168 bool HandleVersionMode(std::vector<std::string> const& args,
169                        cmExecutionStatus& status)
170 {
171   if (args.size() <= 1) {
172     status.SetError("VERSION not given an argument");
173     return false;
174   }
175   if (args.size() >= 3) {
176     status.SetError("VERSION given too many arguments");
177     return false;
178   }
179   std::string const& version_string = args[1];
180
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)
186     : std::string();
187   if (dd != std::string::npos &&
188       (version_min.empty() || version_max.empty())) {
189     status.SetError(
190       cmStrCat("VERSION \"", version_string,
191                R"(" does not have a version on both sides of "...".)"));
192     return false;
193   }
194
195   return status.GetMakefile().SetPolicyVersion(version_min, version_max);
196 }
197
198 bool HandleGetWarningMode(std::vector<std::string> const& args,
199                           cmExecutionStatus& status)
200 {
201   if (args.size() != 3) {
202     status.SetError(
203       "GET_WARNING must be given exactly 2 additional arguments.");
204     return false;
205   }
206
207   // Get arguments.
208   std::string const& id = args[1];
209   std::string const& var = args[2];
210
211   // Lookup the policy number.
212   cmPolicies::PolicyID pid;
213   if (!cmPolicies::GetPolicyID(id.c_str(), pid)) {
214     status.SetError(
215       cmStrCat("GET_WARNING given policy \"", id,
216                "\" which is not known to this version of CMake."));
217     return false;
218   }
219
220   // Lookup the policy warning.
221   status.GetMakefile().AddDefinition(var, cmPolicies::GetPolicyWarning(pid));
222
223   return true;
224 }
225 }