Merge branch 'release-3.29'
[kiteware-cmake.git] / Source / cmIncludeCommand.cxx
blob3695a9b26dc68c954dfdc8db264a2a4be361fdb0
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 "cmIncludeCommand.h"
5 #include <map>
6 #include <sstream>
7 #include <utility>
9 #include "cmExecutionStatus.h"
10 #include "cmGlobalGenerator.h"
11 #include "cmMakefile.h"
12 #include "cmMessageType.h"
13 #include "cmPolicies.h"
14 #include "cmStringAlgorithms.h"
15 #include "cmSystemTools.h"
17 // cmIncludeCommand
18 bool cmIncludeCommand(std::vector<std::string> const& args,
19 cmExecutionStatus& status)
21 static std::map<std::string, cmPolicies::PolicyID> DeprecatedModules;
22 if (DeprecatedModules.empty()) {
23 DeprecatedModules["Dart"] = cmPolicies::CMP0145;
24 DeprecatedModules["Documentation"] = cmPolicies::CMP0106;
25 DeprecatedModules["FindCUDA"] = cmPolicies::CMP0146;
26 DeprecatedModules["FindDart"] = cmPolicies::CMP0145;
27 DeprecatedModules["FindPythonInterp"] = cmPolicies::CMP0148;
28 DeprecatedModules["FindPythonLibs"] = cmPolicies::CMP0148;
29 DeprecatedModules["WriteCompilerDetectionHeader"] = cmPolicies::CMP0120;
32 if (args.empty() || args.size() > 4) {
33 status.SetError("called with wrong number of arguments. "
34 "include() only takes one file.");
35 return false;
37 bool optional = false;
38 bool noPolicyScope = false;
39 std::string fname = args[0];
40 std::string resultVarName;
42 for (unsigned int i = 1; i < args.size(); i++) {
43 if (args[i] == "OPTIONAL") {
44 if (optional) {
45 status.SetError("called with invalid arguments: OPTIONAL used twice");
46 return false;
48 optional = true;
49 } else if (args[i] == "RESULT_VARIABLE") {
50 if (!resultVarName.empty()) {
51 status.SetError("called with invalid arguments: "
52 "only one result variable allowed");
53 return false;
55 if (++i < args.size()) {
56 resultVarName = args[i];
57 } else {
58 status.SetError("called with no value for RESULT_VARIABLE.");
59 return false;
61 } else if (args[i] == "NO_POLICY_SCOPE") {
62 noPolicyScope = true;
63 } else if (i > 1) // compat.: in previous cmake versions the second
64 // parameter was ignored if it wasn't "OPTIONAL"
66 std::string errorText =
67 cmStrCat("called with invalid argument: ", args[i]);
68 status.SetError(errorText);
69 return false;
73 if (fname.empty()) {
74 status.GetMakefile().IssueMessage(
75 MessageType::AUTHOR_WARNING,
76 "include() given empty file name (ignored).");
77 return true;
80 if (!cmSystemTools::FileIsFullPath(fname)) {
81 bool system = false;
82 // Not a path. Maybe module.
83 std::string module = cmStrCat(fname, ".cmake");
84 std::string mfile = status.GetMakefile().GetModulesFile(module, system);
86 if (system) {
87 auto ModulePolicy = DeprecatedModules.find(fname);
88 if (ModulePolicy != DeprecatedModules.end()) {
89 cmPolicies::PolicyStatus PolicyStatus =
90 status.GetMakefile().GetPolicyStatus(ModulePolicy->second);
91 switch (PolicyStatus) {
92 case cmPolicies::WARN: {
93 status.GetMakefile().IssueMessage(
94 MessageType::AUTHOR_WARNING,
95 cmStrCat(cmPolicies::GetPolicyWarning(ModulePolicy->second),
96 "\n"));
97 CM_FALLTHROUGH;
99 case cmPolicies::OLD:
100 break;
101 case cmPolicies::REQUIRED_IF_USED:
102 case cmPolicies::REQUIRED_ALWAYS:
103 case cmPolicies::NEW:
104 mfile = "";
105 break;
110 if (!mfile.empty()) {
111 fname = mfile;
115 std::string fname_abs = cmSystemTools::CollapseFullPath(
116 fname, status.GetMakefile().GetCurrentSourceDirectory());
118 cmGlobalGenerator* gg = status.GetMakefile().GetGlobalGenerator();
119 if (gg->IsExportedTargetsFile(fname_abs)) {
120 const char* modal = nullptr;
121 std::ostringstream e;
122 MessageType messageType = MessageType::AUTHOR_WARNING;
124 switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0024)) {
125 case cmPolicies::WARN:
126 e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0024) << "\n";
127 modal = "should";
128 CM_FALLTHROUGH;
129 case cmPolicies::OLD:
130 break;
131 case cmPolicies::REQUIRED_IF_USED:
132 case cmPolicies::REQUIRED_ALWAYS:
133 case cmPolicies::NEW:
134 modal = "may";
135 messageType = MessageType::FATAL_ERROR;
137 if (modal) {
138 e << "The file\n " << fname_abs
139 << "\nwas generated by the export() "
140 "command. It "
141 << modal
142 << " not be used as the argument to the "
143 "include() command. Use ALIAS targets instead to refer to targets "
144 "by alternative names.\n";
145 status.GetMakefile().IssueMessage(messageType, e.str());
146 if (messageType == MessageType::FATAL_ERROR) {
147 return false;
150 gg->CreateGenerationObjects();
151 gg->GenerateImportFile(fname_abs);
154 std::string listFile = cmSystemTools::CollapseFullPath(
155 fname, status.GetMakefile().GetCurrentSourceDirectory());
157 const bool fileDoesnotExist = !cmSystemTools::FileExists(listFile);
158 const bool fileIsDirectory = cmSystemTools::FileIsDirectory(listFile);
159 if (fileDoesnotExist || fileIsDirectory) {
160 if (!resultVarName.empty()) {
161 status.GetMakefile().AddDefinition(resultVarName, "NOTFOUND");
163 if (optional) {
164 return true;
166 if (fileDoesnotExist) {
167 status.SetError(cmStrCat("could not find requested file:\n ", fname));
168 return false;
170 if (fileIsDirectory) {
171 status.SetError(cmStrCat("requested file is a directory:\n ", fname));
172 return false;
176 bool readit =
177 status.GetMakefile().ReadDependentFile(listFile, noPolicyScope);
179 // add the location of the included file if a result variable was given
180 if (!resultVarName.empty()) {
181 status.GetMakefile().AddDefinition(
182 resultVarName, readit ? fname_abs.c_str() : "NOTFOUND");
185 if (!optional && !readit && !cmSystemTools::GetFatalErrorOccurred()) {
186 std::string m = cmStrCat("could not load requested file:\n ", fname);
187 status.SetError(m);
188 return false;
190 return true;