Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmOptionCommand.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst 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
0
{
19
0
  bool const argError = (args.size() < 2) || (args.size() > 3);
20
0
  if (argError) {
21
0
    std::string m = cmStrCat("called with incorrect number of arguments: ",
22
0
                             cmJoin(args, " "));
23
0
    status.SetError(m);
24
0
    return false;
25
0
  }
26
27
  // Determine the state of the option policy
28
0
  bool checkAndWarn = false;
29
0
  {
30
0
    auto policyStatus =
31
0
      status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077);
32
0
    auto const& existsBeforeSet =
33
0
      status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]);
34
0
    switch (policyStatus) {
35
0
      case cmPolicies::WARN:
36
0
        checkAndWarn = (existsBeforeSet != nullptr);
37
0
        CM_FALLTHROUGH;
38
0
      case cmPolicies::OLD:
39
        // OLD behavior does not warn.
40
0
        break;
41
0
      case cmPolicies::NEW: {
42
        // See if a local variable with this name already exists.
43
        // If so we ignore the option command.
44
0
        if (existsBeforeSet) {
45
0
          return true;
46
0
        }
47
0
      } break;
48
0
    }
49
0
  }
50
51
  // See if a cache variable with this name already exists
52
  // If so just make sure the doc state is correct
53
0
  cmState* state = status.GetMakefile().GetState();
54
0
  cmValue existingValue = state->GetCacheEntryValue(args[0]);
55
0
  if (existingValue &&
56
0
      (state->GetCacheEntryType(args[0]) != cmStateEnums::UNINITIALIZED)) {
57
0
    state->SetCacheEntryProperty(args[0], "HELPSTRING", args[1]);
58
0
    return true;
59
0
  }
60
61
  // Nothing in the cache so add it
62
0
  std::string initialValue = existingValue ? *existingValue : "Off";
63
0
  if (args.size() == 3) {
64
0
    initialValue = args[2];
65
0
  }
66
0
  bool init = cmIsOn(initialValue);
67
0
  status.GetMakefile().AddCacheDefinition(args[0], init ? "ON" : "OFF",
68
0
                                          args[1], cmStateEnums::BOOL);
69
0
  if (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0077) !=
70
0
        cmPolicies::NEW &&
71
0
      status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0126) ==
72
0
        cmPolicies::NEW) {
73
    // if there was a definition then remove it
74
0
    status.GetMakefile().GetStateSnapshot().RemoveDefinition(args[0]);
75
0
  }
76
77
0
  if (checkAndWarn) {
78
0
    auto const& existsAfterSet =
79
0
      status.GetMakefile().GetStateSnapshot().GetDefinition(args[0]);
80
0
    if (!existsAfterSet) {
81
0
      status.GetMakefile().IssueMessage(
82
0
        MessageType::AUTHOR_WARNING,
83
0
        cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0077),
84
0
                 "\n"
85
0
                 "For compatibility with older versions of CMake, option "
86
0
                 "is clearing the normal variable '",
87
0
                 args[0], "'."));
88
0
    }
89
0
  }
90
0
  return true;
91
0
}