1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
4 #include "cmStateSnapshot.h"
10 #include <cm/iterator>
12 #include "cmDefinitions.h"
13 #include "cmListFileCache.h"
14 #include "cmPropertyMap.h"
16 #include "cmStateDirectory.h"
17 #include "cmStatePrivate.h"
18 #include "cmSystemTools.h"
20 #include "cmVersion.h"
22 #if defined(__CYGWIN__)
23 # include "cmStringAlgorithms.h"
26 cmStateSnapshot::cmStateSnapshot(cmState* state)
31 std::vector<cmStateSnapshot> cmStateSnapshot::GetChildren()
33 return this->Position->BuildSystemDirectory->Children;
36 cmStateSnapshot::cmStateSnapshot(cmState* state,
37 cmStateDetail::PositionType position)
43 cmStateEnums::SnapshotType cmStateSnapshot::GetType() const
45 return this->Position->SnapshotType;
48 void cmStateSnapshot::SetListFile(const std::string& listfile)
50 *this->Position->ExecutionListFile = listfile;
53 std::string const& cmStateSnapshot::GetExecutionListFile() const
55 return *this->Position->ExecutionListFile;
58 bool cmStateSnapshot::IsValid() const
60 return this->State && this->Position.IsValid()
61 ? this->Position != this->State->SnapshotData.Root()
65 cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const
67 return { this->State, this->Position->BuildSystemDirectory->CurrentScope };
70 cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const
72 cmStateSnapshot snapshot;
73 if (!this->State || this->Position == this->State->SnapshotData.Root()) {
76 cmStateDetail::PositionType parentPos = this->Position->DirectoryParent;
77 if (parentPos != this->State->SnapshotData.Root()) {
78 snapshot = cmStateSnapshot(this->State,
79 parentPos->BuildSystemDirectory->CurrentScope);
85 cmStateSnapshot cmStateSnapshot::GetCallStackParent() const
88 assert(this->Position != this->State->SnapshotData.Root());
90 cmStateSnapshot snapshot;
91 cmStateDetail::PositionType parentPos = this->Position;
92 while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType ||
93 parentPos->SnapshotType == cmStateEnums::VariableScopeType) {
96 if (parentPos->SnapshotType == cmStateEnums::BuildsystemDirectoryType ||
97 parentPos->SnapshotType == cmStateEnums::BaseType) {
102 while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType ||
103 parentPos->SnapshotType == cmStateEnums::VariableScopeType) {
107 if (parentPos == this->State->SnapshotData.Root()) {
111 snapshot = cmStateSnapshot(this->State, parentPos);
115 cmStateSnapshot cmStateSnapshot::GetCallStackBottom() const
118 assert(this->Position != this->State->SnapshotData.Root());
120 cmStateDetail::PositionType pos = this->Position;
121 while (pos->SnapshotType != cmStateEnums::BaseType &&
122 pos->SnapshotType != cmStateEnums::BuildsystemDirectoryType &&
123 pos != this->State->SnapshotData.Root()) {
126 return { this->State, pos };
129 void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap const& entry, bool weak)
131 cmStateDetail::PositionType pos = this->Position;
132 pos->Policies = this->State->PolicyStack.Push(
133 pos->Policies, cmStateDetail::PolicyStackEntry(entry, weak));
136 bool cmStateSnapshot::PopPolicy()
138 cmStateDetail::PositionType pos = this->Position;
139 if (pos->Policies == pos->PolicyScope) {
142 pos->Policies = this->State->PolicyStack.Pop(pos->Policies);
146 bool cmStateSnapshot::CanPopPolicyScope()
148 return this->Position->Policies != this->Position->PolicyScope;
151 void cmStateSnapshot::SetPolicy(cmPolicies::PolicyID id,
152 cmPolicies::PolicyStatus status)
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;
164 cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id,
165 bool parent_scope) const
167 cmPolicies::PolicyStatus status = cmPolicies::GetPolicyStatus(id);
169 if (status == cmPolicies::REQUIRED_ALWAYS ||
170 status == cmPolicies::REQUIRED_IF_USED) {
174 cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator dir =
175 this->Position->BuildSystemDirectory;
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) {
185 parent_scope = false;
188 if (leaf->IsDefined(id)) {
189 status = leaf->Get(id);
193 cmStateDetail::PositionType e = dir->CurrentScope;
194 cmStateDetail::PositionType p = e->DirectoryParent;
195 if (p == this->State->SnapshotData.Root()) {
198 dir = p->BuildSystemDirectory;
203 bool cmStateSnapshot::HasDefinedPolicyCMP0011()
205 return !this->Position->Policies->IsEmpty();
208 cmValue cmStateSnapshot::GetDefinition(std::string const& name) const
210 assert(this->Position->Vars.IsValid());
211 return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root);
214 bool cmStateSnapshot::IsInitialized(std::string const& name) const
216 return cmDefinitions::HasKey(name, this->Position->Vars,
217 this->Position->Root);
220 void cmStateSnapshot::SetDefinition(std::string const& name,
221 cm::string_view value)
223 this->Position->Vars->Set(name, value);
226 void cmStateSnapshot::RemoveDefinition(std::string const& name)
228 this->Position->Vars->Unset(name);
231 std::vector<std::string> cmStateSnapshot::ClosureKeys() const
233 return cmDefinitions::ClosureKeys(this->Position->Vars,
234 this->Position->Root);
237 bool cmStateSnapshot::RaiseScope(std::string const& var, const char* varDef)
239 if (this->Position->ScopeParent == this->Position->DirectoryParent) {
240 cmStateSnapshot parentDir = this->GetBuildsystemDirectoryParent();
241 if (!parentDir.IsValid()) {
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.
248 parentDir.SetDefinition(var, varDef);
250 parentDir.RemoveDefinition(var);
254 // First localize the definition in the current scope.
255 cmDefinitions::Raise(var, this->Position->Vars, this->Position->Root);
257 // Now update the definition in the parent scope.
259 this->Position->Parent->Set(var, varDef);
261 this->Position->Parent->Unset(var);
266 template <typename T, typename U>
267 void InitializeContentFromParent(T& parentContent, T& thisContent,
268 U& contentEndPosition)
270 auto parentEnd = parentContent.end();
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();
277 thisContent = std::vector<BT<std::string>>(parentIt, parentEnd);
279 contentEndPosition = thisContent.size();
282 void cmStateSnapshot::SetDefaultDefinitions()
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
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");
301 this->SetDefinition("UNIX", "1");
302 this->SetDefinition("CMAKE_HOST_UNIX", "1");
304 #if defined(__CYGWIN__)
306 if (cmSystemTools::GetEnv("CMAKE_LEGACY_CYGWIN_WIN32", legacy) &&
308 this->SetDefinition("WIN32", "1");
309 this->SetDefinition("CMAKE_HOST_WIN32", "1");
312 #if defined(__APPLE__)
313 this->SetDefinition("APPLE", "1");
314 this->SetDefinition("CMAKE_HOST_APPLE", "1");
317 this->SetDefinition("CMAKE_HOST_SOLARIS", "1");
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");
334 #if defined(__linux__)
335 this->SetDefinition("LINUX", "1");
336 this->SetDefinition("CMAKE_HOST_LINUX", "1");
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());
349 this->SetDefinition("CMAKE_FILES_DIRECTORY", "/CMakeFiles");
351 // Setup the default include file regular expression (match everything).
352 this->Position->BuildSystemDirectory->Properties.SetProperty(
353 "INCLUDE_REGULAR_EXPRESSION", "^.*$");
356 void cmStateSnapshot::SetDirectoryDefinitions()
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());
366 void cmStateSnapshot::InitializeFromParent()
368 cmStateDetail::PositionType parent = this->Position->DirectoryParent;
369 assert(this->Position->Vars.IsValid());
370 assert(parent->Vars.IsValid());
372 *this->Position->Vars =
373 cmDefinitions::MakeClosure(parent->Vars, parent->Root);
375 InitializeContentFromParent(
376 parent->BuildSystemDirectory->IncludeDirectories,
377 this->Position->BuildSystemDirectory->IncludeDirectories,
378 this->Position->IncludeDirectoryPosition);
380 InitializeContentFromParent(
381 parent->BuildSystemDirectory->CompileDefinitions,
382 this->Position->BuildSystemDirectory->CompileDefinitions,
383 this->Position->CompileDefinitionsPosition);
385 InitializeContentFromParent(
386 parent->BuildSystemDirectory->CompileOptions,
387 this->Position->BuildSystemDirectory->CompileOptions,
388 this->Position->CompileOptionsPosition);
390 InitializeContentFromParent(
391 parent->BuildSystemDirectory->LinkOptions,
392 this->Position->BuildSystemDirectory->LinkOptions,
393 this->Position->LinkOptionsPosition);
395 InitializeContentFromParent(
396 parent->BuildSystemDirectory->LinkDirectories,
397 this->Position->BuildSystemDirectory->LinkDirectories,
398 this->Position->LinkDirectoriesPosition);
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);
407 cmState* cmStateSnapshot::GetState() const
412 cmStateDirectory cmStateSnapshot::GetDirectory() const
414 return { this->Position->BuildSystemDirectory, *this };
417 void cmStateSnapshot::SetProjectName(const std::string& name)
419 this->Position->BuildSystemDirectory->ProjectName = name;
422 std::string cmStateSnapshot::GetProjectName() const
424 return this->Position->BuildSystemDirectory->ProjectName;
427 void cmStateSnapshot::InitializeFromParent_ForSubdirsCommand()
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());
435 this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR", currentSrcDir);
436 this->SetDefinition("CMAKE_CURRENT_BINARY_DIR", currentBinDir);
439 bool cmStateSnapshot::StrictWeakOrder::operator()(
440 const cmStateSnapshot& lhs, const cmStateSnapshot& rhs) const
442 return lhs.Position.StrictWeakOrdered(rhs.Position);
445 bool operator==(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs)
447 return lhs.Position == rhs.Position;
450 bool operator!=(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs)
452 return lhs.Position != rhs.Position;