Coverage Report

Created: 2026-04-29 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmIncludeCommand.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 "cmIncludeCommand.h"
4
5
#include <map>
6
#include <utility>
7
8
#include "cmDiagnostics.h"
9
#include "cmExecutionStatus.h"
10
#include "cmGlobalGenerator.h"
11
#include "cmMakefile.h"
12
#include "cmMessageType.h"
13
#include "cmPolicies.h"
14
#include "cmStateSnapshot.h"
15
#include "cmStateTypes.h"
16
#include "cmStringAlgorithms.h"
17
#include "cmSystemTools.h"
18
19
// cmIncludeCommand
20
bool cmIncludeCommand(std::vector<std::string> const& args,
21
                      cmExecutionStatus& status)
22
0
{
23
0
  static std::map<std::string, cmPolicies::PolicyID> DeprecatedModules;
24
0
  if (DeprecatedModules.empty()) {
25
0
    DeprecatedModules["CMakeDetermineVSServicePack"] = cmPolicies::CMP0196;
26
0
    DeprecatedModules["CMakeFindFrameworks"] = cmPolicies::CMP0173;
27
0
    DeprecatedModules["Dart"] = cmPolicies::CMP0145;
28
0
    DeprecatedModules["Documentation"] = cmPolicies::CMP0106;
29
0
    DeprecatedModules["FindBoost"] = cmPolicies::CMP0167;
30
0
    DeprecatedModules["FindCABLE"] = cmPolicies::CMP0191;
31
0
    DeprecatedModules["FindCUDA"] = cmPolicies::CMP0146;
32
0
    DeprecatedModules["FindDart"] = cmPolicies::CMP0145;
33
0
    DeprecatedModules["FindGCCXML"] = cmPolicies::CMP0188;
34
0
    DeprecatedModules["FindPythonInterp"] = cmPolicies::CMP0148;
35
0
    DeprecatedModules["FindPythonLibs"] = cmPolicies::CMP0148;
36
0
    DeprecatedModules["WriteCompilerDetectionHeader"] = cmPolicies::CMP0120;
37
0
  }
38
39
0
  if (args.empty() || args.size() > 4) {
40
0
    status.SetError("called with wrong number of arguments.  "
41
0
                    "include() only takes one file.");
42
0
    return false;
43
0
  }
44
45
0
  if (status.GetMakefile().GetStateSnapshot().GetUnwindState() ==
46
0
      cmStateEnums::UNWINDING) {
47
0
    status.SetError("called while already in an UNWIND state");
48
0
    return false;
49
0
  }
50
51
0
  bool optional = false;
52
0
  cm::PolicyScope policyScope = cm::PolicyScope::Local;
53
0
  cm::DiagnosticScope diagnosticScope = cm::DiagnosticScope::Local;
54
0
  std::string fname = args[0];
55
0
  std::string resultVarName;
56
57
0
  for (unsigned int i = 1; i < args.size(); i++) {
58
0
    if (args[i] == "OPTIONAL") {
59
0
      if (optional) {
60
0
        status.SetError("called with invalid arguments: OPTIONAL used twice");
61
0
        return false;
62
0
      }
63
0
      optional = true;
64
0
    } else if (args[i] == "RESULT_VARIABLE") {
65
0
      if (!resultVarName.empty()) {
66
0
        status.SetError("called with invalid arguments: "
67
0
                        "only one result variable allowed");
68
0
        return false;
69
0
      }
70
0
      if (++i < args.size()) {
71
0
        resultVarName = args[i];
72
0
      } else {
73
0
        status.SetError("called with no value for RESULT_VARIABLE.");
74
0
        return false;
75
0
      }
76
0
    } else if (args[i] == "NO_POLICY_SCOPE") {
77
0
      policyScope = cm::PolicyScope::None;
78
0
    } else if (args[i] == "NO_DIAGNOSTIC_SCOPE") {
79
0
      diagnosticScope = cm::DiagnosticScope::None;
80
0
    } else if (i > 1) // compat.: in previous cmake versions the second
81
                      // parameter was ignored if it wasn't "OPTIONAL"
82
0
    {
83
0
      std::string errorText =
84
0
        cmStrCat("called with invalid argument: ", args[i]);
85
0
      status.SetError(errorText);
86
0
      return false;
87
0
    }
88
0
  }
89
90
0
  if (fname.empty()) {
91
0
    status.GetMakefile().IssueDiagnostic(
92
0
      cmDiagnostics::CMD_AUTHOR, "include() given empty file name (ignored).");
93
0
    return true;
94
0
  }
95
96
0
  if (!cmSystemTools::FileIsFullPath(fname)) {
97
0
    bool system = false;
98
    // Not a path. Maybe module.
99
0
    std::string module = cmStrCat(fname, ".cmake");
100
0
    std::string mfile = status.GetMakefile().GetModulesFile(module, system);
101
102
0
    if (system) {
103
0
      auto ModulePolicy = DeprecatedModules.find(fname);
104
0
      if (ModulePolicy != DeprecatedModules.end()) {
105
0
        cmPolicies::PolicyStatus PolicyStatus =
106
0
          status.GetMakefile().GetPolicyStatus(ModulePolicy->second);
107
0
        switch (PolicyStatus) {
108
0
          case cmPolicies::WARN: {
109
0
            status.GetMakefile().IssueDiagnostic(
110
0
              cmDiagnostics::CMD_AUTHOR,
111
0
              cmStrCat(cmPolicies::GetPolicyWarning(ModulePolicy->second),
112
0
                       '\n'));
113
0
            CM_FALLTHROUGH;
114
0
          }
115
0
          case cmPolicies::OLD:
116
0
            break;
117
0
          case cmPolicies::NEW:
118
0
            mfile = "";
119
0
            break;
120
0
        }
121
0
      }
122
0
    }
123
124
0
    if (!mfile.empty()) {
125
0
      fname = mfile;
126
0
    }
127
0
  }
128
129
0
  std::string fname_abs = cmSystemTools::CollapseFullPath(
130
0
    fname, status.GetMakefile().GetCurrentSourceDirectory());
131
132
0
  cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
133
0
  if (gg->IsExportedTargetsFile(fname_abs)) {
134
0
    status.GetMakefile().IssueMessage(
135
0
      MessageType::FATAL_ERROR,
136
0
      cmStrCat(
137
0
        "The file\n  ", fname_abs,
138
0
        "\nwas generated by the export() "
139
0
        "command.  It may not be used as the argument to the "
140
0
        "include() command.  Use ALIAS targets instead to refer to targets "
141
0
        "by alternative names.\n"));
142
0
    return false;
143
0
  }
144
145
0
  std::string listFile = cmSystemTools::CollapseFullPath(
146
0
    fname, status.GetMakefile().GetCurrentSourceDirectory());
147
148
0
  bool const fileDoesnotExist = !cmSystemTools::FileExists(listFile);
149
0
  bool const fileIsDirectory = cmSystemTools::FileIsDirectory(listFile);
150
0
  if (fileDoesnotExist || fileIsDirectory) {
151
0
    if (!resultVarName.empty()) {
152
0
      status.GetMakefile().AddDefinition(resultVarName, "NOTFOUND");
153
0
    }
154
0
    if (optional) {
155
0
      return true;
156
0
    }
157
0
    if (fileDoesnotExist) {
158
0
      status.SetError(cmStrCat("could not find requested file:\n  ", fname));
159
0
      return false;
160
0
    }
161
0
    if (fileIsDirectory) {
162
0
      status.SetError(cmStrCat("requested file is a directory:\n  ", fname));
163
0
      return false;
164
0
    }
165
0
  }
166
167
0
  bool const readit = status.GetMakefile().ReadDependentFile(
168
0
    listFile, policyScope, diagnosticScope);
169
170
  // add the location of the included file if a result variable was given
171
0
  if (!resultVarName.empty()) {
172
0
    status.GetMakefile().AddDefinition(
173
0
      resultVarName, readit ? fname_abs.c_str() : "NOTFOUND");
174
0
  }
175
176
0
  if (!optional && !readit && !cmSystemTools::GetFatalErrorOccurred()) {
177
0
    std::string m = cmStrCat("could not load requested file:\n  ", fname);
178
0
    status.SetError(m);
179
0
    return false;
180
0
  }
181
182
0
  if (status.GetMakefile().GetStateSnapshot().GetUnwindState() ==
183
0
      cmStateEnums::UNWINDING) {
184
185
0
    if (status.GetMakefile().GetStateSnapshot().GetUnwindType() !=
186
0
        cmStateEnums::CAN_UNWIND) {
187
0
      std::string m = cmStrCat("requested file is attempting to unwind the "
188
0
                               "stack in an invalid context:\n ",
189
0
                               fname);
190
0
      status.SetError(m);
191
0
      cmSystemTools::SetFatalErrorOccurred();
192
0
      return false;
193
0
    }
194
195
0
    status.SetReturnInvoked();
196
0
  }
197
198
0
  return true;
199
0
}