| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| |
| #include "cmStateSnapshot.h" |
| |
| #include <algorithm> |
| #include <cassert> |
| #include <string> |
| |
| #include <cm/iterator> |
| |
| #include "cmDefinitions.h" |
| #include "cmLinkedTree.h" |
| #include "cmListFileCache.h" |
| #include "cmPropertyMap.h" |
| #include "cmState.h" |
| #include "cmStateDirectory.h" |
| #include "cmStatePrivate.h" |
| #include "cmSystemTools.h" |
| #include "cmValue.h" |
| #include "cmVersion.h" |
| |
| #if defined(__CYGWIN__) |
| # include "cmStringAlgorithms.h" |
| #endif |
| |
| cmStateSnapshot::cmStateSnapshot(cmState* state) |
| : State(state) |
| { |
| } |
| |
| std::vector<cmStateSnapshot> cmStateSnapshot::GetChildren() |
| { |
| return this->Position->BuildSystemDirectory->Children; |
| } |
| |
| cmStateSnapshot::cmStateSnapshot(cmState* state, |
| cmStateDetail::PositionType position) |
| : State(state) |
| , Position(position) |
| { |
| } |
| |
| cmStateEnums::SnapshotType cmStateSnapshot::GetType() const |
| { |
| return this->Position->SnapshotType; |
| } |
| |
| void cmStateSnapshot::SetListFile(const std::string& listfile) |
| { |
| *this->Position->ExecutionListFile = listfile; |
| } |
| |
| std::string const& cmStateSnapshot::GetExecutionListFile() const |
| { |
| return *this->Position->ExecutionListFile; |
| } |
| |
| bool cmStateSnapshot::IsValid() const |
| { |
| return this->State && this->Position.IsValid() |
| ? this->Position != this->State->SnapshotData.Root() |
| : false; |
| } |
| |
| cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const |
| { |
| return { this->State, this->Position->BuildSystemDirectory->CurrentScope }; |
| } |
| |
| cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const |
| { |
| cmStateSnapshot snapshot; |
| if (!this->State || this->Position == this->State->SnapshotData.Root()) { |
| return snapshot; |
| } |
| cmStateDetail::PositionType parentPos = this->Position->DirectoryParent; |
| if (parentPos != this->State->SnapshotData.Root()) { |
| snapshot = cmStateSnapshot(this->State, |
| parentPos->BuildSystemDirectory->CurrentScope); |
| } |
| |
| return snapshot; |
| } |
| |
| cmStateSnapshot cmStateSnapshot::GetCallStackParent() const |
| { |
| assert(this->State); |
| assert(this->Position != this->State->SnapshotData.Root()); |
| |
| cmStateSnapshot snapshot; |
| cmStateDetail::PositionType parentPos = this->Position; |
| while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType || |
| parentPos->SnapshotType == cmStateEnums::VariableScopeType) { |
| ++parentPos; |
| } |
| if (parentPos->SnapshotType == cmStateEnums::BuildsystemDirectoryType || |
| parentPos->SnapshotType == cmStateEnums::BaseType) { |
| return snapshot; |
| } |
| |
| ++parentPos; |
| while (parentPos->SnapshotType == cmStateEnums::PolicyScopeType || |
| parentPos->SnapshotType == cmStateEnums::VariableScopeType) { |
| ++parentPos; |
| } |
| |
| if (parentPos == this->State->SnapshotData.Root()) { |
| return snapshot; |
| } |
| |
| snapshot = cmStateSnapshot(this->State, parentPos); |
| return snapshot; |
| } |
| |
| cmStateSnapshot cmStateSnapshot::GetCallStackBottom() const |
| { |
| assert(this->State); |
| assert(this->Position != this->State->SnapshotData.Root()); |
| |
| cmStateDetail::PositionType pos = this->Position; |
| while (pos->SnapshotType != cmStateEnums::BaseType && |
| pos->SnapshotType != cmStateEnums::BuildsystemDirectoryType && |
| pos != this->State->SnapshotData.Root()) { |
| ++pos; |
| } |
| return { this->State, pos }; |
| } |
| |
| void cmStateSnapshot::PushPolicy(cmPolicies::PolicyMap const& entry, bool weak) |
| { |
| cmStateDetail::PositionType pos = this->Position; |
| pos->Policies = this->State->PolicyStack.Push( |
| pos->Policies, cmStateDetail::PolicyStackEntry(entry, weak)); |
| } |
| |
| bool cmStateSnapshot::PopPolicy() |
| { |
| cmStateDetail::PositionType pos = this->Position; |
| if (pos->Policies == pos->PolicyScope) { |
| return false; |
| } |
| pos->Policies = this->State->PolicyStack.Pop(pos->Policies); |
| return true; |
| } |
| |
| bool cmStateSnapshot::CanPopPolicyScope() |
| { |
| return this->Position->Policies != this->Position->PolicyScope; |
| } |
| |
| void cmStateSnapshot::SetPolicy(cmPolicies::PolicyID id, |
| cmPolicies::PolicyStatus status) |
| { |
| // Update the policy stack from the top to the top-most strong entry. |
| bool previous_was_weak = true; |
| for (cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator psi = |
| this->Position->Policies; |
| previous_was_weak && psi != this->Position->PolicyRoot; ++psi) { |
| psi->Set(id, status); |
| previous_was_weak = psi->Weak; |
| } |
| } |
| |
| cmPolicies::PolicyStatus cmStateSnapshot::GetPolicy(cmPolicies::PolicyID id, |
| bool parent_scope) const |
| { |
| cmPolicies::PolicyStatus status = cmPolicies::GetPolicyStatus(id); |
| |
| if (status == cmPolicies::REQUIRED_ALWAYS || |
| status == cmPolicies::REQUIRED_IF_USED) { |
| return status; |
| } |
| |
| cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator dir = |
| this->Position->BuildSystemDirectory; |
| |
| while (true) { |
| assert(dir.IsValid()); |
| cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator leaf = |
| dir->CurrentScope->Policies; |
| cmLinkedTree<cmStateDetail::PolicyStackEntry>::iterator root = |
| dir->CurrentScope->PolicyRoot; |
| for (; leaf != root; ++leaf) { |
| if (parent_scope) { |
| parent_scope = false; |
| continue; |
| } |
| if (leaf->IsDefined(id)) { |
| status = leaf->Get(id); |
| return status; |
| } |
| } |
| cmStateDetail::PositionType e = dir->CurrentScope; |
| cmStateDetail::PositionType p = e->DirectoryParent; |
| if (p == this->State->SnapshotData.Root()) { |
| break; |
| } |
| dir = p->BuildSystemDirectory; |
| } |
| return status; |
| } |
| |
| bool cmStateSnapshot::HasDefinedPolicyCMP0011() |
| { |
| return !this->Position->Policies->IsEmpty(); |
| } |
| |
| cmValue cmStateSnapshot::GetDefinition(std::string const& name) const |
| { |
| assert(this->Position->Vars.IsValid()); |
| return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root); |
| } |
| |
| bool cmStateSnapshot::IsInitialized(std::string const& name) const |
| { |
| return cmDefinitions::HasKey(name, this->Position->Vars, |
| this->Position->Root); |
| } |
| |
| void cmStateSnapshot::SetDefinition(std::string const& name, |
| cm::string_view value) |
| { |
| this->Position->Vars->Set(name, value); |
| } |
| |
| void cmStateSnapshot::RemoveDefinition(std::string const& name) |
| { |
| this->Position->Vars->Unset(name); |
| } |
| |
| std::vector<std::string> cmStateSnapshot::ClosureKeys() const |
| { |
| return cmDefinitions::ClosureKeys(this->Position->Vars, |
| this->Position->Root); |
| } |
| |
| bool cmStateSnapshot::RaiseScope(std::string const& var, const char* varDef) |
| { |
| if (this->Position->ScopeParent == this->Position->DirectoryParent) { |
| cmStateSnapshot parentDir = this->GetBuildsystemDirectoryParent(); |
| if (!parentDir.IsValid()) { |
| return false; |
| } |
| // Update the definition in the parent directory top scope. This |
| // directory's scope was initialized by the closure of the parent |
| // scope, so we do not need to localize the definition first. |
| if (varDef) { |
| parentDir.SetDefinition(var, varDef); |
| } else { |
| parentDir.RemoveDefinition(var); |
| } |
| return true; |
| } |
| // First localize the definition in the current scope. |
| cmDefinitions::Raise(var, this->Position->Vars, this->Position->Root); |
| |
| // Now update the definition in the parent scope. |
| if (varDef) { |
| this->Position->Parent->Set(var, varDef); |
| } else { |
| this->Position->Parent->Unset(var); |
| } |
| return true; |
| } |
| |
| template <typename T, typename U> |
| void InitializeContentFromParent(T& parentContent, T& thisContent, |
| U& contentEndPosition) |
| { |
| auto parentEnd = parentContent.end(); |
| |
| auto parentRbegin = cm::make_reverse_iterator(parentEnd); |
| auto parentRend = parentContent.rend(); |
| parentRbegin = std::find(parentRbegin, parentRend, cmPropertySentinal); |
| auto parentIt = parentRbegin.base(); |
| |
| thisContent = std::vector<BT<std::string>>(parentIt, parentEnd); |
| |
| contentEndPosition = thisContent.size(); |
| } |
| |
| void cmStateSnapshot::SetDefaultDefinitions() |
| { |
| /* Up to CMake 2.4 here only WIN32, UNIX and APPLE were set. |
| With CMake must separate between target and host platform. In most cases |
| the tests for WIN32, UNIX and APPLE will be for the target system, so an |
| additional set of variables for the host system is required -> |
| CMAKE_HOST_WIN32, CMAKE_HOST_UNIX, CMAKE_HOST_APPLE. |
| WIN32, UNIX and APPLE are now set in the platform files in |
| Modules/Platforms/. |
| To keep cmake scripts (-P) and custom language and compiler modules |
| working, these variables are still also set here in this place, but they |
| will be reset in CMakeSystemSpecificInformation.cmake before the platform |
| files are executed. */ |
| cm::string_view hostSystemName = cmSystemTools::GetSystemName(); |
| this->SetDefinition("CMAKE_HOST_SYSTEM_NAME", hostSystemName); |
| if (hostSystemName == "Windows") { |
| this->SetDefinition("WIN32", "1"); |
| this->SetDefinition("CMAKE_HOST_WIN32", "1"); |
| } else { |
| this->SetDefinition("UNIX", "1"); |
| this->SetDefinition("CMAKE_HOST_UNIX", "1"); |
| } |
| #if defined(__APPLE__) |
| this->SetDefinition("APPLE", "1"); |
| this->SetDefinition("CMAKE_HOST_APPLE", "1"); |
| #endif |
| #if defined(__sun__) |
| this->SetDefinition("CMAKE_HOST_SOLARIS", "1"); |
| #endif |
| |
| #if defined(__OpenBSD__) |
| this->SetDefinition("BSD", "OpenBSD"); |
| this->SetDefinition("CMAKE_HOST_BSD", "OpenBSD"); |
| #elif defined(__FreeBSD__) |
| this->SetDefinition("BSD", "FreeBSD"); |
| this->SetDefinition("CMAKE_HOST_BSD", "FreeBSD"); |
| #elif defined(__NetBSD__) |
| this->SetDefinition("BSD", "NetBSD"); |
| this->SetDefinition("CMAKE_HOST_BSD", "NetBSD"); |
| #elif defined(__DragonFly__) |
| this->SetDefinition("BSD", "DragonFlyBSD"); |
| this->SetDefinition("CMAKE_HOST_BSD", "DragonFlyBSD"); |
| #endif |
| |
| #if defined(__linux__) |
| this->SetDefinition("LINUX", "1"); |
| this->SetDefinition("CMAKE_HOST_LINUX", "1"); |
| #endif |
| |
| this->SetDefinition("CMAKE_MAJOR_VERSION", |
| std::to_string(cmVersion::GetMajorVersion())); |
| this->SetDefinition("CMAKE_MINOR_VERSION", |
| std::to_string(cmVersion::GetMinorVersion())); |
| this->SetDefinition("CMAKE_PATCH_VERSION", |
| std::to_string(cmVersion::GetPatchVersion())); |
| this->SetDefinition("CMAKE_TWEAK_VERSION", |
| std::to_string(cmVersion::GetTweakVersion())); |
| this->SetDefinition("CMAKE_VERSION", cmVersion::GetCMakeVersion()); |
| |
| this->SetDefinition("CMAKE_FILES_DIRECTORY", "/CMakeFiles"); |
| |
| // Setup the default include file regular expression (match everything). |
| this->Position->BuildSystemDirectory->Properties.SetProperty( |
| "INCLUDE_REGULAR_EXPRESSION", "^.*$"); |
| } |
| |
| void cmStateSnapshot::SetDirectoryDefinitions() |
| { |
| this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory()); |
| this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR", |
| this->State->GetSourceDirectory()); |
| this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory()); |
| this->SetDefinition("CMAKE_CURRENT_BINARY_DIR", |
| this->State->GetBinaryDirectory()); |
| } |
| |
| void cmStateSnapshot::InitializeFromParent() |
| { |
| cmStateDetail::PositionType parent = this->Position->DirectoryParent; |
| assert(this->Position->Vars.IsValid()); |
| assert(parent->Vars.IsValid()); |
| |
| *this->Position->Vars = |
| cmDefinitions::MakeClosure(parent->Vars, parent->Root); |
| |
| InitializeContentFromParent( |
| parent->BuildSystemDirectory->IncludeDirectories, |
| this->Position->BuildSystemDirectory->IncludeDirectories, |
| this->Position->IncludeDirectoryPosition); |
| |
| InitializeContentFromParent( |
| parent->BuildSystemDirectory->CompileDefinitions, |
| this->Position->BuildSystemDirectory->CompileDefinitions, |
| this->Position->CompileDefinitionsPosition); |
| |
| InitializeContentFromParent( |
| parent->BuildSystemDirectory->CompileOptions, |
| this->Position->BuildSystemDirectory->CompileOptions, |
| this->Position->CompileOptionsPosition); |
| |
| InitializeContentFromParent( |
| parent->BuildSystemDirectory->LinkOptions, |
| this->Position->BuildSystemDirectory->LinkOptions, |
| this->Position->LinkOptionsPosition); |
| |
| InitializeContentFromParent( |
| parent->BuildSystemDirectory->LinkDirectories, |
| this->Position->BuildSystemDirectory->LinkDirectories, |
| this->Position->LinkDirectoriesPosition); |
| |
| cmValue include_regex = |
| parent->BuildSystemDirectory->Properties.GetPropertyValue( |
| "INCLUDE_REGULAR_EXPRESSION"); |
| this->Position->BuildSystemDirectory->Properties.SetProperty( |
| "INCLUDE_REGULAR_EXPRESSION", include_regex); |
| } |
| |
| cmState* cmStateSnapshot::GetState() const |
| { |
| return this->State; |
| } |
| |
| cmStateDirectory cmStateSnapshot::GetDirectory() const |
| { |
| return { this->Position->BuildSystemDirectory, *this }; |
| } |
| |
| void cmStateSnapshot::SetProjectName(const std::string& name) |
| { |
| this->Position->BuildSystemDirectory->ProjectName = name; |
| } |
| |
| std::string cmStateSnapshot::GetProjectName() const |
| { |
| return this->Position->BuildSystemDirectory->ProjectName; |
| } |
| |
| void cmStateSnapshot::InitializeFromParent_ForSubdirsCommand() |
| { |
| std::string currentSrcDir = *this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR"); |
| std::string currentBinDir = *this->GetDefinition("CMAKE_CURRENT_BINARY_DIR"); |
| this->InitializeFromParent(); |
| this->SetDefinition("CMAKE_SOURCE_DIR", this->State->GetSourceDirectory()); |
| this->SetDefinition("CMAKE_BINARY_DIR", this->State->GetBinaryDirectory()); |
| |
| this->SetDefinition("CMAKE_CURRENT_SOURCE_DIR", currentSrcDir); |
| this->SetDefinition("CMAKE_CURRENT_BINARY_DIR", currentBinDir); |
| } |
| |
| bool cmStateSnapshot::StrictWeakOrder::operator()( |
| const cmStateSnapshot& lhs, const cmStateSnapshot& rhs) const |
| { |
| return lhs.Position.StrictWeakOrdered(rhs.Position); |
| } |
| |
| bool operator==(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs) |
| { |
| return lhs.Position == rhs.Position; |
| } |
| |
| bool operator!=(const cmStateSnapshot& lhs, const cmStateSnapshot& rhs) |
| { |
| return lhs.Position != rhs.Position; |
| } |