/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 | } |