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