resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmOptionCommand.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 "cmOptionCommand.h"
4
5 #include "cmExecutionStatus.h"
6 #include "cmMakefile.h"
7 #include "cmMessageType.h"
8 #include "cmPolicies.h"
9 #include "cmState.h"
10 #include "cmStateSnapshot.h"
11 #include "cmStateTypes.h"
12 #include "cmStringAlgorithms.h"
13 #include "cmValue.h"
14
15 // cmOptionCommand
16 bool cmOptionCommand(std::vector<std::string> const& args,
17                      cmExecutionStatus& status)
18 {
19   const bool argError = (args.size() < 2) || (args.size() > 3);
20   if (argError) {
21     std::string m = cmStrCat("called with incorrect number of arguments: ",
22                              cmJoin(args, " "));
23     status.SetError(m);
24     return false;
25   }
26
27   // Determine the state of the option policy
28   bool checkAndWarn = false;
29   {
30     auto policyStatus =
31       status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077);
32     const auto& existsBeforeSet =
33       status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]);
34     switch (policyStatus) {
35       case cmPolicies::WARN:
36         checkAndWarn = (existsBeforeSet != nullptr);
37         CM_FALLTHROUGH;
38       case cmPolicies::OLD:
39         // OLD behavior does not warn.
40         break;
41       case cmPolicies::REQUIRED_ALWAYS:
42       case cmPolicies::REQUIRED_IF_USED:
43       case cmPolicies::NEW: {
44         // See if a local variable with this name already exists.
45         // If so we ignore the option command.
46         if (existsBeforeSet) {
47           return true;
48         }
49       } break;
50     }
51   }
52
53   // See if a cache variable with this name already exists
54   // If so just make sure the doc state is correct
55   cmState* state = status.GetMakefile().GetState();
56   cmValue existingValue = state->GetCacheEntryValue(args[0]);
57   if (existingValue &&
58       (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED)) {
59     state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]);
60     return true;
61   }
62
63   // Nothing in the cache so add it
64   std::string initialValue = existingValue ? *existingValue : "Off";
65   if (args.size() == 3) {
66     initialValue = args[2];
67   }
68   bool init = cmIsOn(initialValue);
69   status.GetMakefile().AddCacheDefinition(args[0], init ? "ON" : "OFF",
70                                           args[1].c_str(), cmStateEnums::BOOL);
71   if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077) !=
72         cmPolicies::NEW &&
73       status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0126) ==
74         cmPolicies::NEW) {
75     // if there was a definition then remove it
76     status.GetMakefile().GetStateSnapshot().RemoveDefinition(args[0]);
77   }
78
79   if (checkAndWarn) {
80     const auto& existsAfterSet =
81       status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]);
82     if (!existsAfterSet) {
83       status.GetMakefile().IssueMessage(
84         MessageType::AUTHOR_WARNING,
85         cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0077),
86                  "\n"
87                  "For compatibility with older versions of CMake, option "
88                  "is clearing the normal variable '",
89                  args[0], "'."));
90     }
91   }
92   return true;
93 }