/src/CMake/Source/cmStateSnapshot.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 | | |
4 | | #include "cmStateSnapshot.h" |
5 | | |
6 | | #include <algorithm> |
7 | | #include <cassert> |
8 | | #include <set> |
9 | | #include <string> |
10 | | #include <unordered_map> |
11 | | |
12 | | #include <cm/iterator> |
13 | | #include <cmext/algorithm> |
14 | | |
15 | | #include "cmDefinitions.h" |
16 | | #include "cmLinkedTree.h" |
17 | | #include "cmListFileCache.h" |
18 | | #include "cmPackageState.h" |
19 | | #include "cmPropertyMap.h" |
20 | | #include "cmState.h" |
21 | | #include "cmStateDirectory.h" |
22 | | #include "cmStatePrivate.h" |
23 | | #include "cmSystemTools.h" |
24 | | #include "cmValue.h" |
25 | | #include "cmVersion.h" |
26 | | |
27 | | #if defined(__CYGWIN__) |
28 | | # include "cmStringAlgorithms.h" |
29 | | #endif |
30 | | |
31 | | cmStateSnapshot::cmStateSnapshot(cmState* state) |
32 | 35 | : State(state) |
33 | 35 | { |
34 | 35 | } |
35 | | |
36 | | std::vector<cmStateSnapshot> cmStateSnapshot::GetChildren() |
37 | 0 | { |
38 | 0 | return this->Position->BuildSystemDirectory->Children; |
39 | 0 | } |
40 | | |
41 | | cmStateSnapshot::cmStateSnapshot(cmState* state, |
42 | | cmStateDetail::PositionType position) |
43 | 39 | : State(state) |
44 | 39 | , Position(position) |
45 | 39 | { |
46 | 39 | } |
47 | | |
48 | | cmStateEnums::SnapshotType cmStateSnapshot::GetType() const |
49 | 0 | { |
50 | 0 | return this->Position->SnapshotType; |
51 | 0 | } |
52 | | |
53 | | cmStateEnums::SnapshotUnwindType cmStateSnapshot::GetUnwindType() const |
54 | 0 | { |
55 | 0 | return this->Position->UnwindType; |
56 | 0 | } |
57 | | |
58 | | void cmStateSnapshot::SetUnwindType(cmStateEnums::SnapshotUnwindType type) |
59 | 0 | { |
60 | 0 | this->Position->UnwindType = type; |
61 | 0 | } |
62 | | |
63 | | cmStateEnums::SnapshotUnwindState cmStateSnapshot::GetUnwindState() const |
64 | 0 | { |
65 | 0 | return this->Position->UnwindState; |
66 | 0 | } |
67 | | |
68 | | void cmStateSnapshot::SetUnwindState(cmStateEnums::SnapshotUnwindState state) |
69 | 0 | { |
70 | 0 | this->Position->UnwindState = state; |
71 | 0 | } |
72 | | |
73 | | void cmStateSnapshot::SetListFile(std::string const& listfile) |
74 | 0 | { |
75 | 0 | *this->Position->ExecutionListFile = listfile; |
76 | 0 | } |
77 | | |
78 | | std::string const& cmStateSnapshot::GetExecutionListFile() const |
79 | 0 | { |
80 | 0 | return *this->Position->ExecutionListFile; |
81 | 0 | } |
82 | | |
83 | | bool cmStateSnapshot::IsValid() const |
84 | 72 | { |
85 | 72 | return this->State && this->Position.IsValid() |
86 | 72 | ? this->Position != this->State->SnapshotData.Root() |
87 | 72 | : false; |
88 | 72 | } |
89 | | |
90 | | cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const |
91 | 0 | { |
92 | 0 | return { this->State, this->Position->BuildSystemDirectory->CurrentScope }; |
93 | 0 | } |
94 | | |
95 | | cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const |
96 | 0 | { |
97 | 0 | cmStateSnapshot snapshot; |
98 | 0 | if (!this->State || this->Position == this->State->SnapshotData.Root()) { |
99 | 0 | return snapshot; |
100 | 0 | } |
101 | 0 | cmStateDetail::PositionType parentPos = this->Position->DirectoryParent; |
102 | 0 | if (parentPos != this->State->SnapshotData.Root()) { |
103 | 0 | snapshot = cmStateSnapshot(this->State, |
104 | 0 | parentPos->BuildSystemDirectory->CurrentScope); |
105 | 0 | } |
106 | |
|
107 | 0 | return snapshot; |
108 | 0 | } |
109 | | |
110 | | cmStateSnapshot cmStateSnapshot::GetCallStackParent() const |
111 | 0 | { |
112 | 0 | assert(this->State); |
113 | 0 | assert(this->Position != this->State->SnapshotData.Root()); |
114 | |
|
115 | 0 | cmStateSnapshot snapshot; |
116 | 0 | cmStateDetail::PositionType parentPos = this->Position; |
117 | 0 | while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType || |
118 | 0 | parentPos->SnapshotType == cmStateEnums::VariableScopeType) { |
119 | 0 | ++parentPos; |
120 | 0 | } |
121 | 0 | if (parentPos->SnapshotType == cmStateEnums::BuildsystemDirectoryType || |
122 | 0 | parentPos->SnapshotType == cmStateEnums::BaseType) { |
123 | 0 | return snapshot; |
124 | 0 | } |
125 | | |
126 | 0 | ++parentPos; |
127 | 0 | while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType || |
128 | 0 | parentPos->SnapshotType == cmStateEnums::VariableScopeType) { |
129 | 0 | ++parentPos; |
130 | 0 | } |
131 | |
|
132 | 0 | if (parentPos == this->State->SnapshotData.Root()) { |
133 | 0 | return snapshot; |
134 | 0 | } |
135 | | |
136 | 0 | snapshot = cmStateSnapshot(this->State, parentPos); |
137 | 0 | return snapshot; |
138 | 0 | } |
139 | | |
140 | | cmStateSnapshot cmStateSnapshot::GetCallStackBottom() const |
141 | 0 | { |
142 | 0 | assert(this->State); |
143 | 0 | assert(this->Position != this->State->SnapshotData.Root()); |
144 | |
|
145 | 0 | cmStateDetail::PositionType pos = this->Position; |
146 | 0 | while (pos->SnapshotType != cmStateEnums::BaseType && |
147 | 0 | pos->SnapshotType != cmStateEnums::BuildsystemDirectoryType && |
148 | 0 | pos != this->State->SnapshotData.Root()) { |
149 | 0 | ++pos; |
150 | 0 | } |
151 | 0 | return { this->State, pos }; |
152 | 0 | } |
153 | | |
154 | | void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap const& entry, bool weak) |
155 | 1 | { |
156 | 1 | cmStateDetail::PositionType pos = this->Position; |
157 | 1 | pos->Policies = this->State->PolicyStack.Push( |
158 | 1 | pos->Policies, cmStateDetail::PolicyStackEntry(entry, weak)); |
159 | 1 | } |
160 | | |
161 | | bool cmStateSnapshot::PopPolicy() |
162 | 0 | { |
163 | 0 | cmStateDetail::PositionType pos = this->Position; |
164 | 0 | if (pos->Policies == pos->PolicyScope) { |
165 | 0 | return false; |
166 | 0 | } |
167 | 0 | pos->Policies = this->State->PolicyStack.Pop(pos->Policies); |
168 | 0 | return true; |
169 | 0 | } |
170 | | |
171 | | bool cmStateSnapshot::CanPopPolicyScope() |
172 | 1 | { |
173 | 1 | return this->Position->Policies != this->Position->PolicyScope; |
174 | 1 | } |
175 | | |
176 | | void cmStateSnapshot::SetPolicy(cmPolicies::PolicyID id, |
177 | | cmPolicies::PolicyStatus status) |
178 | 0 | { |
179 | | // Update the policy stack from the top to the top-most strong entry. |
180 | 0 | bool previous_was_weak = true; |
181 | 0 | for (cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator psi = |
182 | 0 | this->Position->Policies; |
183 | 0 | previous_was_weak && psi != this->Position->PolicyRoot; ++psi) { |
184 | 0 | psi->Set(id, status); |
185 | 0 | previous_was_weak = psi->Weak; |
186 | 0 | } |
187 | 0 | } |
188 | | |
189 | | cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id, |
190 | | bool parent_scope) const |
191 | 0 | { |
192 | 0 | if (cmPolicies::IsRemoved(id)) { |
193 | 0 | return cmPolicies::NEW; |
194 | 0 | } |
195 | | |
196 | 0 | cmPolicies::PolicyStatus status = cmPolicies::WARN; |
197 | |
|
198 | 0 | cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator dir = |
199 | 0 | this->Position->BuildSystemDirectory; |
200 | |
|
201 | 0 | while (true) { |
202 | 0 | assert(dir.IsValid()); |
203 | 0 | cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator leaf = |
204 | 0 | dir->CurrentScope->Policies; |
205 | 0 | cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator root = |
206 | 0 | dir->CurrentScope->PolicyRoot; |
207 | 0 | for (; leaf != root; ++leaf) { |
208 | 0 | if (parent_scope) { |
209 | 0 | parent_scope = false; |
210 | 0 | continue; |
211 | 0 | } |
212 | 0 | if (leaf->IsDefined(id)) { |
213 | 0 | status = leaf->Get(id); |
214 | 0 | return status; |
215 | 0 | } |
216 | 0 | } |
217 | 0 | cmStateDetail::PositionType e = dir->CurrentScope; |
218 | 0 | cmStateDetail::PositionType p = e->DirectoryParent; |
219 | 0 | if (p == this->State->SnapshotData.Root()) { |
220 | 0 | break; |
221 | 0 | } |
222 | 0 | dir = p->BuildSystemDirectory; |
223 | 0 | } |
224 | 0 | return status; |
225 | 0 | } |
226 | | |
227 | | cmValue cmStateSnapshot::GetDefinition(std::string const& name) const |
228 | 6 | { |
229 | 6 | assert(this->Position->Vars.IsValid()); |
230 | 6 | return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root); |
231 | 6 | } |
232 | | |
233 | | bool cmStateSnapshot::IsInitialized(std::string const& name) const |
234 | 0 | { |
235 | 0 | return cmDefinitions::HasKey(name, this->Position->Vars, |
236 | 0 | this->Position->Root); |
237 | 0 | } |
238 | | |
239 | | void cmStateSnapshot::SetDefinition(std::string const& name, |
240 | | cm::string_view value) |
241 | 95 | { |
242 | 95 | this->Position->Vars->Set(name, value); |
243 | 95 | } |
244 | | |
245 | | void cmStateSnapshot::RemoveDefinition(std::string const& name) |
246 | 1 | { |
247 | 1 | this->Position->Vars->Unset(name); |
248 | 1 | } |
249 | | |
250 | | std::vector<std::string> cmStateSnapshot::ClosureKeys() const |
251 | 0 | { |
252 | 0 | return cmDefinitions::ClosureKeys(this->Position->Vars, |
253 | 0 | this->Position->Root); |
254 | 0 | } |
255 | | |
256 | | bool cmStateSnapshot::RaiseScope(std::string const& var, char const* varDef) |
257 | 0 | { |
258 | 0 | if (this->Position->ScopeParent == this->Position->DirectoryParent) { |
259 | 0 | cmStateSnapshot parentDir = this->GetBuildsystemDirectoryParent(); |
260 | 0 | if (!parentDir.IsValid()) { |
261 | 0 | return false; |
262 | 0 | } |
263 | | // Update the definition in the parent directory top scope. This |
264 | | // directory's scope was initialized by the closure of the parent |
265 | | // scope, so we do not need to localize the definition first. |
266 | 0 | if (varDef) { |
267 | 0 | parentDir.SetDefinition(var, varDef); |
268 | 0 | } else { |
269 | 0 | parentDir.RemoveDefinition(var); |
270 | 0 | } |
271 | 0 | return true; |
272 | 0 | } |
273 | | // First localize the definition in the current scope. |
274 | 0 | cmDefinitions::Raise(var, this->Position->Vars, this->Position->Root); |
275 | | |
276 | | // Now update the definition in the parent scope. |
277 | 0 | if (varDef) { |
278 | 0 | this->Position->Parent->Set(var, varDef); |
279 | 0 | } else { |
280 | 0 | this->Position->Parent->Unset(var); |
281 | 0 | } |
282 | 0 | return true; |
283 | 0 | } |
284 | | |
285 | | template <typename T, typename U> |
286 | | void InitializeContentFromParent(T& parentContent, T& thisContent, |
287 | | U& contentEndPosition) |
288 | 0 | { |
289 | 0 | auto parentEnd = parentContent.end(); |
290 | |
|
291 | 0 | auto parentRbegin = cm::make_reverse_iterator(parentEnd); |
292 | 0 | auto parentRend = parentContent.rend(); |
293 | 0 | parentRbegin = |
294 | 0 | std::find(parentRbegin, parentRend, cmStateDetail::PropertySentinel); |
295 | 0 | auto parentIt = parentRbegin.base(); |
296 | |
|
297 | 0 | thisContent = std::vector<BT<std::string>>(parentIt, parentEnd); |
298 | |
|
299 | 0 | contentEndPosition = thisContent.size(); |
300 | 0 | } |
301 | | |
302 | | void cmStateSnapshot::SetDefaultDefinitions() |
303 | 1 | { |
304 | | /* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set. |
305 | | With CMake must separate between target and host platform. In most cases |
306 | | the tests for WIN32, UNIX and APPLE will be for the target system, so an |
307 | | additional set of variables for the host system is required -> |
308 | | CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE. |
309 | | WIN32, UNIX and APPLE are now set in the platform files in |
310 | | Modules/Platforms/. |
311 | | To keep cmake scripts (-P) and custom language and compiler modules |
312 | | working, these variables are still also set here in this place, but they |
313 | | will be reset in CMakeSystemSpecificInformation.cmake before the platform |
314 | | files are executed. */ |
315 | 1 | cm::string_view hostSystemName = cmSystemTools::GetSystemName(); |
316 | 1 | this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", hostSystemName); |
317 | 1 | if (hostSystemName == "Windows") { |
318 | 0 | this->SetDefinition("WIN32", "1"); |
319 | 0 | this->SetDefinition("CMAKE_HOST_WIN32", "1"); |
320 | 0 | this->SetDefinition("CMAKE_HOST_EXECUTABLE_SUFFIX", ".exe"); |
321 | 1 | } else { |
322 | 1 | this->SetDefinition("UNIX", "1"); |
323 | 1 | this->SetDefinition("CMAKE_HOST_UNIX", "1"); |
324 | 1 | this->SetDefinition("CMAKE_HOST_EXECUTABLE_SUFFIX", ""); |
325 | 1 | } |
326 | | #if defined(__APPLE__) |
327 | | this->SetDefinition("APPLE", "1"); |
328 | | this->SetDefinition("CMAKE_HOST_APPLE", "1"); |
329 | | #endif |
330 | | #if defined(__sun__) |
331 | | this->SetDefinition("CMAKE_HOST_SOLARIS", "1"); |
332 | | #endif |
333 | | |
334 | | #if defined(__OpenBSD__) |
335 | | this->SetDefinition("BSD", "OpenBSD"); |
336 | | this->SetDefinition("CMAKE_HOST_BSD", "OpenBSD"); |
337 | | #elif defined(__FreeBSD__) |
338 | | this->SetDefinition("BSD", "FreeBSD"); |
339 | | this->SetDefinition("CMAKE_HOST_BSD", "FreeBSD"); |
340 | | #elif defined(__NetBSD__) |
341 | | this->SetDefinition("BSD", "NetBSD"); |
342 | | this->SetDefinition("CMAKE_HOST_BSD", "NetBSD"); |
343 | | #elif defined(__DragonFly__) |
344 | | this->SetDefinition("BSD", "DragonFlyBSD"); |
345 | | this->SetDefinition("CMAKE_HOST_BSD", "DragonFlyBSD"); |
346 | | #endif |
347 | | |
348 | 1 | #if defined(__linux__) |
349 | 1 | this->SetDefinition("LINUX", "1"); |
350 | 1 | this->SetDefinition("CMAKE_HOST_LINUX", "1"); |
351 | 1 | #endif |
352 | | |
353 | | #if defined(_AIX) |
354 | | this->SetDefinition("AIX", "1"); |
355 | | this->SetDefinition("CMAKE_HOST_AIX", "1"); |
356 | | #endif |
357 | | |
358 | 1 | this->SetDefinition("CMAKE_MAJOR_VERSION", |
359 | 1 | std::to_string(cmVersion::GetMajorVersion())); |
360 | 1 | this->SetDefinition("CMAKE_MINOR_VERSION", |
361 | 1 | std::to_string(cmVersion::GetMinorVersion())); |
362 | 1 | this->SetDefinition("CMAKE_PATCH_VERSION", |
363 | 1 | std::to_string(cmVersion::GetPatchVersion())); |
364 | 1 | this->SetDefinition("CMAKE_TWEAK_VERSION", |
365 | 1 | std::to_string(cmVersion::GetTweakVersion())); |
366 | 1 | this->SetDefinition("CMAKE_VERSION", cmVersion::GetCMakeVersion()); |
367 | | |
368 | 1 | this->SetDefinition("CMAKE_FILES_DIRECTORY", "/CMakeFiles"); |
369 | | |
370 | | // Setup the default include file regular expression (match everything). |
371 | 1 | this->Position->BuildSystemDirectory->Properties.SetProperty( |
372 | 1 | "INCLUDE_REGULAR_EXPRESSION", "^.*$"); |
373 | 1 | } |
374 | | |
375 | | void cmStateSnapshot::SetDirectoryDefinitions() |
376 | 0 | { |
377 | 0 | this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory()); |
378 | 0 | this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR", |
379 | 0 | this->State->GetSourceDirectory()); |
380 | 0 | this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory()); |
381 | 0 | this->SetDefinition("CMAKE_CURRENT_BINARY_DIR", |
382 | 0 | this->State->GetBinaryDirectory()); |
383 | 0 | } |
384 | | |
385 | | void cmStateSnapshot::InitializeFromParent() |
386 | 0 | { |
387 | 0 | cmStateDetail::PositionType parent = this->Position->DirectoryParent; |
388 | 0 | assert(this->Position->Vars.IsValid()); |
389 | 0 | assert(parent->Vars.IsValid()); |
390 | |
|
391 | 0 | *this->Position->Vars = |
392 | 0 | cmDefinitions::MakeClosure(parent->Vars, parent->Root); |
393 | |
|
394 | 0 | InitializeContentFromParent( |
395 | 0 | parent->BuildSystemDirectory->IncludeDirectories, |
396 | 0 | this->Position->BuildSystemDirectory->IncludeDirectories, |
397 | 0 | this->Position->IncludeDirectoryPosition); |
398 | |
|
399 | 0 | InitializeContentFromParent( |
400 | 0 | parent->BuildSystemDirectory->CompileDefinitions, |
401 | 0 | this->Position->BuildSystemDirectory->CompileDefinitions, |
402 | 0 | this->Position->CompileDefinitionsPosition); |
403 | |
|
404 | 0 | InitializeContentFromParent( |
405 | 0 | parent->BuildSystemDirectory->CompileOptions, |
406 | 0 | this->Position->BuildSystemDirectory->CompileOptions, |
407 | 0 | this->Position->CompileOptionsPosition); |
408 | |
|
409 | 0 | InitializeContentFromParent( |
410 | 0 | parent->BuildSystemDirectory->LinkOptions, |
411 | 0 | this->Position->BuildSystemDirectory->LinkOptions, |
412 | 0 | this->Position->LinkOptionsPosition); |
413 | |
|
414 | 0 | InitializeContentFromParent( |
415 | 0 | parent->BuildSystemDirectory->LinkDirectories, |
416 | 0 | this->Position->BuildSystemDirectory->LinkDirectories, |
417 | 0 | this->Position->LinkDirectoriesPosition); |
418 | |
|
419 | 0 | cmValue include_regex = |
420 | 0 | parent->BuildSystemDirectory->Properties.GetPropertyValue( |
421 | 0 | "INCLUDE_REGULAR_EXPRESSION"); |
422 | 0 | this->Position->BuildSystemDirectory->Properties.SetProperty( |
423 | 0 | "INCLUDE_REGULAR_EXPRESSION", include_regex); |
424 | 0 | } |
425 | | |
426 | | cmState* cmStateSnapshot::GetState() const |
427 | 1 | { |
428 | 1 | return this->State; |
429 | 1 | } |
430 | | |
431 | | cmStateDirectory cmStateSnapshot::GetDirectory() const |
432 | 3 | { |
433 | 3 | return { this->Position->BuildSystemDirectory, *this }; |
434 | 3 | } |
435 | | |
436 | | void cmStateSnapshot::SetProjectName(std::string const& name) |
437 | 0 | { |
438 | 0 | this->Position->BuildSystemDirectory->ProjectName = name; |
439 | 0 | this->Position->BuildSystemDirectory->Projects.insert(name); |
440 | 0 | } |
441 | | |
442 | | std::string cmStateSnapshot::GetProjectName() const |
443 | 0 | { |
444 | 0 | return this->Position->BuildSystemDirectory->ProjectName; |
445 | 0 | } |
446 | | |
447 | | bool cmStateSnapshot::CheckProjectName(std::string const& name) const |
448 | 0 | { |
449 | 0 | return cm::contains(this->Position->BuildSystemDirectory->Projects, name); |
450 | 0 | } |
451 | | |
452 | | cmPackageState& cmStateSnapshot::GetPackageState( |
453 | | std::string const& packagePath) |
454 | 0 | { |
455 | 0 | return this->Position->BuildSystemDirectory->Packages[packagePath]; |
456 | 0 | } |
457 | | |
458 | | void cmStateSnapshot::InitializeFromParent_ForSubdirsCommand() |
459 | 0 | { |
460 | 0 | std::string currentSrcDir = *this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR"); |
461 | 0 | std::string currentBinDir = *this->GetDefinition("CMAKE_CURRENT_BINARY_DIR"); |
462 | 0 | this->InitializeFromParent(); |
463 | 0 | this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory()); |
464 | 0 | this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory()); |
465 | |
|
466 | 0 | this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR", currentSrcDir); |
467 | 0 | this->SetDefinition("CMAKE_CURRENT_BINARY_DIR", currentBinDir); |
468 | 0 | } |
469 | | |
470 | | bool cmStateSnapshot::StrictWeakOrder::operator()( |
471 | | cmStateSnapshot const& lhs, cmStateSnapshot const& rhs) const |
472 | 0 | { |
473 | 0 | return lhs.Position.StrictWeakOrdered(rhs.Position); |
474 | 0 | } |
475 | | |
476 | | bool operator==(cmStateSnapshot const& lhs, cmStateSnapshot const& rhs) |
477 | 0 | { |
478 | 0 | return lhs.Position == rhs.Position; |
479 | 0 | } |
480 | | |
481 | | bool operator!=(cmStateSnapshot const& lhs, cmStateSnapshot const& rhs) |
482 | 0 | { |
483 | 0 | return lhs.Position != rhs.Position; |
484 | 0 | } |