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"
5 #include "cmExecutionStatus.h"
6 #include "cmMakefile.h"
7 #include "cmMessageType.h"
8 #include "cmPolicies.h"
10 #include "cmStateSnapshot.h"
11 #include "cmStateTypes.h"
12 #include "cmStringAlgorithms.h"
16 bool cmOptionCommand(std::vector<std::string> const& args,
17 cmExecutionStatus& status)
19 const bool argError = (args.size() < 2) || (args.size() > 3);
21 std::string m = cmStrCat("called with incorrect number of arguments: ",
27 // Determine the state of the option policy
28 bool checkAndWarn = false;
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);
39 // OLD behavior does not warn.
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) {
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]);
58 (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED)) {
59 state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]);
63 // Nothing in the cache so add it
64 std::string initialValue = existingValue ? *existingValue : "Off";
65 if (args.size() == 3) {
66 initialValue = args[2];
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) !=
73 status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0126) ==
75 // if there was a definition then remove it
76 status.GetMakefile().GetStateSnapshot().RemoveDefinition(args[0]);
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),
87 "For compatibility with older versions of CMake, option "
88 "is clearing the normal variable '",