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->DirectoryEnd };
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->DirectoryEnd);
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->DirectoryEnd->Policies;
181 cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator root =
182 dir->DirectoryEnd->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->DirectoryEnd;
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 this->SetDefinition("CMAKE_MAJOR_VERSION",
321 std::to_string(cmVersion::GetMajorVersion()));
322 this->SetDefinition("CMAKE_MINOR_VERSION",
323 std::to_string(cmVersion::GetMinorVersion()));
324 this->SetDefinition("CMAKE_PATCH_VERSION",
325 std::to_string(cmVersion::GetPatchVersion()));
326 this->SetDefinition("CMAKE_TWEAK_VERSION",
327 std::to_string(cmVersion::GetTweakVersion()));
328 this->SetDefinition("CMAKE_VERSION", cmVersion::GetCMakeVersion());
330 this->SetDefinition("CMAKE_FILES_DIRECTORY", "/CMakeFiles");
332 // Setup the default include file regular expression (match everything).
333 this->Position->BuildSystemDirectory->Properties.SetProperty(
334 "INCLUDE_REGULAR_EXPRESSION", "^.*$");
337 void cmStateSnapshot::SetDirectoryDefinitions()
339 this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory());
340 this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR",
341 this->State->GetSourceDirectory());
342 this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory());
343 this->SetDefinition("CMAKE_CURRENT_BINARY_DIR",
344 this->State->GetBinaryDirectory());
347 void cmStateSnapshot::InitializeFromParent()
349 cmStateDetail::PositionType parent = this->Position->DirectoryParent;
350 assert(this->Position->Vars.IsValid());
351 assert(parent->Vars.IsValid());
353 *this->Position->Vars =
354 cmDefinitions::MakeClosure(parent->Vars, parent->Root);
356 InitializeContentFromParent(
357 parent->BuildSystemDirectory->IncludeDirectories,
358 this->Position->BuildSystemDirectory->IncludeDirectories,
359 this->Position->IncludeDirectoryPosition);
361 InitializeContentFromParent(
362 parent->BuildSystemDirectory->CompileDefinitions,
363 this->Position->BuildSystemDirectory->CompileDefinitions,
364 this->Position->CompileDefinitionsPosition);
366 InitializeContentFromParent(
367 parent->BuildSystemDirectory->CompileOptions,
368 this->Position->BuildSystemDirectory->CompileOptions,
369 this->Position->CompileOptionsPosition);
371 InitializeContentFromParent(
372 parent->BuildSystemDirectory->LinkOptions,
373 this->Position->BuildSystemDirectory->LinkOptions,
374 this->Position->LinkOptionsPosition);
376 InitializeContentFromParent(
377 parent->BuildSystemDirectory->LinkDirectories,
378 this->Position->BuildSystemDirectory->LinkDirectories,
379 this->Position->LinkDirectoriesPosition);
381 cmValue include_regex =
382 parent->BuildSystemDirectory->Properties.GetPropertyValue(
383 "INCLUDE_REGULAR_EXPRESSION");
384 this->Position->BuildSystemDirectory->Properties.SetProperty(
385 "INCLUDE_REGULAR_EXPRESSION", include_regex);
388 cmState* cmStateSnapshot::GetState() const
393 cmStateDirectory cmStateSnapshot::GetDirectory() const
395 return { this->Position->BuildSystemDirectory, *this };
398 void cmStateSnapshot::SetProjectName(const std::string& name)
400 this->Position->BuildSystemDirectory->ProjectName = name;
403 std::string cmStateSnapshot::GetProjectName() const
405 return this->Position->BuildSystemDirectory->ProjectName;
408 void cmStateSnapshot::InitializeFromParent_ForSubdirsCommand()
410 std::string currentSrcDir = *this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR");
411 std::string currentBinDir = *this->GetDefinition("CMAKE_CURRENT_BINARY_DIR");
412 this->InitializeFromParent();
413 this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory());
414 this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory());
416 this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR", currentSrcDir);
417 this->SetDefinition("CMAKE_CURRENT_BINARY_DIR", currentBinDir);
420 bool cmStateSnapshot::StrictWeakOrder::operator()(
421 const cmStateSnapshot& lhs, const cmStateSnapshot& rhs) const
423 return lhs.Position.StrictWeakOrdered(rhs.Position);
426 bool operator==(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs)
428 return lhs.Position == rhs.Position;
431 bool operator!=(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs)
433 return lhs.Position != rhs.Position;