Coverage Report

Created: 2026-06-15 07:03

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