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