/*============================================================================ CMake - Cross Platform Makefile Generator Copyright 2015 Stephen Kelly Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ #include "cmState.h" #include "cmake.h" #include "cmCacheManager.h" #include "cmCommand.h" #include "cmAlgorithms.h" #include "cmDefinitions.h" #include struct cmState::SnapshotDataType { cmState::PositionType ScopeParent; cmState::PositionType DirectoryParent; cmLinkedTree::iterator Policies; cmLinkedTree::iterator PolicyRoot; cmLinkedTree::iterator PolicyScope; cmState::SnapshotType SnapshotType; cmLinkedTree::iterator ExecutionListFile; cmLinkedTree::iterator BuildSystemDirectory; cmLinkedTree::iterator Vars; cmLinkedTree::iterator Root; cmLinkedTree::iterator Parent; std::string EntryPointCommand; long EntryPointLine; std::vector::size_type IncludeDirectoryPosition; std::vector::size_type CompileDefinitionsPosition; std::vector::size_type CompileOptionsPosition; }; struct cmState::PolicyStackEntry: public cmPolicies::PolicyMap { typedef cmPolicies::PolicyMap derived; PolicyStackEntry(bool w = false): derived(), Weak(w) {} PolicyStackEntry(derived const& d, bool w): derived(d), Weak(w) {} PolicyStackEntry(PolicyStackEntry const& r): derived(r), Weak(r.Weak) {} bool Weak; }; struct cmState::BuildsystemDirectoryStateType { cmState::PositionType DirectoryEnd; std::string Location; std::string OutputLocation; std::vector CurrentSourceDirectoryComponents; std::vector CurrentBinaryDirectoryComponents; // The top-most directories for relative path conversion. Both the // source and destination location of a relative path conversion // must be underneath one of these directories (both under source or // both under binary) in order for the relative path to be evaluated // safely by the build tools. std::string RelativePathTopSource; std::string RelativePathTopBinary; std::vector IncludeDirectories; std::vector IncludeDirectoryBacktraces; std::vector CompileDefinitions; std::vector CompileDefinitionsBacktraces; std::vector CompileOptions; std::vector CompileOptionsBacktraces; std::string ProjectName; cmPropertyMap Properties; std::vector Children; }; cmState::cmState(cmake* cm) : CMakeInstance(cm), IsInTryCompile(false), WindowsShell(false), WindowsVSIDE(false), WatcomWMake(false), MinGWMake(false), NMake(false), MSYSShell(false) { } cmState::~cmState() { cmDeleteAll(this->Commands); } const char* cmCacheEntryTypes[] = { "BOOL", "PATH", "FILEPATH", "STRING", "INTERNAL", "STATIC", "UNINITIALIZED", 0 }; const char* cmState::CacheEntryTypeToString(cmState::CacheEntryType type) { if ( type > 6 ) { return cmCacheEntryTypes[6]; } return cmCacheEntryTypes[type]; } cmState::CacheEntryType cmState::StringToCacheEntryType(const char* s) { int i = 0; while(cmCacheEntryTypes[i]) { if(strcmp(s, cmCacheEntryTypes[i]) == 0) { return static_cast(i); } ++i; } return STRING; } bool cmState::IsCacheEntryType(std::string const& key) { for(int i=0; cmCacheEntryTypes[i]; ++i) { if(strcmp(key.c_str(), cmCacheEntryTypes[i]) == 0) { return true; } } return false; } bool cmState::LoadCache(const std::string& path, bool internal, std::set& excludes, std::set& includes) { return this->CMakeInstance->GetCacheManager()->LoadCache(path, internal, excludes, includes); } bool cmState::SaveCache(const std::string& path) { return this->CMakeInstance->GetCacheManager()->SaveCache(path); } bool cmState::DeleteCache(const std::string& path) { return this->CMakeInstance->GetCacheManager()->DeleteCache(path); } std::vector cmState::GetCacheEntryKeys() const { std::vector definitions; definitions.reserve(this->CMakeInstance->GetCacheManager()->GetSize()); cmCacheManager::CacheIterator cit = this->CMakeInstance->GetCacheManager()->GetCacheIterator(); for ( cit.Begin(); !cit.IsAtEnd(); cit.Next() ) { definitions.push_back(cit.GetName()); } return definitions; } const char* cmState::GetCacheEntryValue(std::string const& key) const { cmCacheManager::CacheEntry* e = this->CMakeInstance->GetCacheManager() ->GetCacheEntry(key); if (!e) { return 0; } return e->Value.c_str(); } const char* cmState::GetInitializedCacheValue(std::string const& key) const { return this->CMakeInstance->GetCacheManager()->GetInitializedCacheValue(key); } cmState::CacheEntryType cmState::GetCacheEntryType(std::string const& key) const { cmCacheManager::CacheIterator it = this->CMakeInstance->GetCacheManager()->GetCacheIterator(key.c_str()); return it.GetType(); } void cmState::SetCacheEntryValue(std::string const& key, std::string const& value) { this->CMakeInstance->GetCacheManager()->SetCacheEntryValue(key, value); } void cmState::SetCacheEntryProperty(std::string const& key, std::string const& propertyName, std::string const& value) { cmCacheManager::CacheIterator it = this->CMakeInstance->GetCacheManager()->GetCacheIterator(key.c_str()); it.SetProperty(propertyName, value.c_str()); } void cmState::SetCacheEntryBoolProperty(std::string const& key, std::string const& propertyName, bool value) { cmCacheManager::CacheIterator it = this->CMakeInstance->GetCacheManager()->GetCacheIterator(key.c_str()); it.SetProperty(propertyName, value); } const char* cmState::GetCacheEntryProperty(std::string const& key, std::string const& propertyName) { cmCacheManager::CacheIterator it = this->CMakeInstance->GetCacheManager() ->GetCacheIterator(key.c_str()); if (!it.PropertyExists(propertyName)) { return 0; } return it.GetProperty(propertyName); } bool cmState::GetCacheEntryPropertyAsBool(std::string const& key, std::string const& propertyName) { return this->CMakeInstance->GetCacheManager() ->GetCacheIterator(key.c_str()).GetPropertyAsBool(propertyName); } void cmState::AddCacheEntry(const std::string& key, const char* value, const char* helpString, cmState::CacheEntryType type) { this->CMakeInstance->GetCacheManager()->AddCacheEntry(key, value, helpString, type); } void cmState::RemoveCacheEntry(std::string const& key) { this->CMakeInstance->GetCacheManager()->RemoveCacheEntry(key); } void cmState::AppendCacheEntryProperty(const std::string& key, const std::string& property, const std::string& value, bool asString) { this->CMakeInstance->GetCacheManager() ->GetCacheIterator(key.c_str()).AppendProperty(property, value.c_str(), asString); } void cmState::RemoveCacheEntryProperty(std::string const& key, std::string const& propertyName) { this->CMakeInstance->GetCacheManager() ->GetCacheIterator(key.c_str()).SetProperty(propertyName, (void*)0); } cmState::Snapshot cmState::Reset() { this->GlobalProperties.clear(); this->PropertyDefinitions.clear(); PositionType pos = this->SnapshotData.Truncate(); this->ExecutionListFiles.Truncate(); { cmLinkedTree::iterator it = this->BuildsystemDirectory.Truncate(); it->IncludeDirectories.clear(); it->IncludeDirectoryBacktraces.clear(); it->CompileDefinitions.clear(); it->CompileDefinitionsBacktraces.clear(); it->CompileOptions.clear(); it->CompileOptionsBacktraces.clear(); it->DirectoryEnd = pos; it->Properties.clear(); it->Children.clear(); } this->PolicyStack.Clear(); pos->Policies = this->PolicyStack.Root(); pos->PolicyRoot = this->PolicyStack.Root(); pos->PolicyScope = this->PolicyStack.Root(); assert(pos->Policies.IsValid()); assert(pos->PolicyRoot.IsValid()); this->VarTree.Clear(); pos->Vars = this->VarTree.Extend(this->VarTree.Root()); pos->Parent = this->VarTree.Root(); pos->Root = this->VarTree.Root(); this->DefineProperty ("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, "", "", true); this->DefineProperty ("RULE_LAUNCH_LINK", cmProperty::DIRECTORY, "", "", true); this->DefineProperty ("RULE_LAUNCH_CUSTOM", cmProperty::DIRECTORY, "", "", true); this->DefineProperty ("RULE_LAUNCH_COMPILE", cmProperty::TARGET, "", "", true); this->DefineProperty ("RULE_LAUNCH_LINK", cmProperty::TARGET, "", "", true); this->DefineProperty ("RULE_LAUNCH_CUSTOM", cmProperty::TARGET, "", "", true); return Snapshot(this, pos); } void cmState::DefineProperty(const std::string& name, cmProperty::ScopeType scope, const char *ShortDescription, const char *FullDescription, bool chained) { this->PropertyDefinitions[scope].DefineProperty(name,scope,ShortDescription, FullDescription, chained); } cmPropertyDefinition const* cmState ::GetPropertyDefinition(const std::string& name, cmProperty::ScopeType scope) const { if (this->IsPropertyDefined(name,scope)) { cmPropertyDefinitionMap const& defs = this->PropertyDefinitions.find(scope)->second; return &defs.find(name)->second; } return 0; } bool cmState::IsPropertyDefined(const std::string& name, cmProperty::ScopeType scope) const { std::map::const_iterator it = this->PropertyDefinitions.find(scope); if (it == this->PropertyDefinitions.end()) { return false; } return it->second.IsPropertyDefined(name); } bool cmState::IsPropertyChained(const std::string& name, cmProperty::ScopeType scope) const { std::map::const_iterator it = this->PropertyDefinitions.find(scope); if (it == this->PropertyDefinitions.end()) { return false; } return it->second.IsPropertyChained(name); } void cmState::SetLanguageEnabled(std::string const& l) { std::vector::iterator it = std::lower_bound(this->EnabledLanguages.begin(), this->EnabledLanguages.end(), l); if (it == this->EnabledLanguages.end() || *it != l) { this->EnabledLanguages.insert(it, l); } } bool cmState::GetLanguageEnabled(std::string const& l) const { return std::binary_search(this->EnabledLanguages.begin(), this->EnabledLanguages.end(), l); } std::vector cmState::GetEnabledLanguages() const { return this->EnabledLanguages; } void cmState::SetEnabledLanguages(std::vector const& langs) { this->EnabledLanguages = langs; } void cmState::ClearEnabledLanguages() { this->EnabledLanguages.clear(); } bool cmState::GetIsInTryCompile() const { return this->IsInTryCompile; } void cmState::SetIsInTryCompile(bool b) { this->IsInTryCompile = b; } void cmState::RenameCommand(std::string const& oldName, std::string const& newName) { // if the command already exists, free the old one std::string sOldName = cmSystemTools::LowerCase(oldName); std::string sNewName = cmSystemTools::LowerCase(newName); std::map::iterator pos = this->Commands.find(sOldName); if ( pos == this->Commands.end() ) { return; } cmCommand* cmd = pos->second; pos = this->Commands.find(sNewName); if (pos != this->Commands.end()) { delete pos->second; this->Commands.erase(pos); } this->Commands.insert(std::make_pair(sNewName, cmd)); pos = this->Commands.find(sOldName); this->Commands.erase(pos); } void cmState::AddCommand(cmCommand* command) { std::string name = cmSystemTools::LowerCase(command->GetName()); // if the command already exists, free the old one std::map::iterator pos = this->Commands.find(name); if (pos != this->Commands.end()) { delete pos->second; this->Commands.erase(pos); } this->Commands.insert(std::make_pair(name, command)); } void cmState::RemoveUnscriptableCommands() { std::vector unscriptableCommands; for (std::map::iterator pos = this->Commands.begin(); pos != this->Commands.end(); ) { if (!pos->second->IsScriptable()) { delete pos->second; this->Commands.erase(pos++); } else { ++pos; } } } cmCommand* cmState::GetCommand(std::string const& name) const { cmCommand* command = 0; std::string sName = cmSystemTools::LowerCase(name); std::map::const_iterator pos = this->Commands.find(sName); if (pos != this->Commands.end()) { command = (*pos).second; } return command; } std::vector cmState::GetCommandNames() const { std::vector commandNames; commandNames.reserve(this->Commands.size()); std::map::const_iterator cmds = this->Commands.begin(); for ( ; cmds != this->Commands.end(); ++ cmds ) { commandNames.push_back(cmds->first); } return commandNames; } void cmState::RemoveUserDefinedCommands() { std::vector renamedCommands; for(std::map::iterator j = this->Commands.begin(); j != this->Commands.end(); ) { if (j->second->IsA("cmMacroHelperCommand") || j->second->IsA("cmFunctionHelperCommand")) { delete j->second; this->Commands.erase(j++); } else if (j->first != j->second->GetName()) { renamedCommands.push_back(j->second); this->Commands.erase(j++); } else { ++j; } } for (std::vector::const_iterator it = renamedCommands.begin(); it != renamedCommands.end(); ++it) { this->Commands[cmSystemTools::LowerCase((*it)->GetName())] = *it; } } void cmState::SetGlobalProperty(const std::string& prop, const char* value) { this->GlobalProperties.SetProperty(prop, value); } void cmState::AppendGlobalProperty(const std::string& prop, const char* value, bool asString) { this->GlobalProperties.AppendProperty(prop, value, asString); } const char *cmState::GetGlobalProperty(const std::string& prop) { if ( prop == "CACHE_VARIABLES" ) { std::vector cacheKeys = this->GetCacheEntryKeys(); this->SetGlobalProperty("CACHE_VARIABLES", cmJoin(cacheKeys, ";").c_str()); } else if ( prop == "COMMANDS" ) { std::vector commands = this->GetCommandNames(); this->SetGlobalProperty("COMMANDS", cmJoin(commands, ";").c_str()); } else if ( prop == "IN_TRY_COMPILE" ) { this->SetGlobalProperty("IN_TRY_COMPILE", this->IsInTryCompile ? "1" : "0"); } else if ( prop == "ENABLED_LANGUAGES" ) { std::string langs; langs = cmJoin(this->EnabledLanguages, ";"); this->SetGlobalProperty("ENABLED_LANGUAGES", langs.c_str()); } #define STRING_LIST_ELEMENT(F) ";" #F if (prop == "CMAKE_C_KNOWN_FEATURES") { return FOR_EACH_C_FEATURE(STRING_LIST_ELEMENT) + 1; } if (prop == "CMAKE_CXX_KNOWN_FEATURES") { return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1; } #undef STRING_LIST_ELEMENT return this->GlobalProperties.GetPropertyValue(prop); } bool cmState::GetGlobalPropertyAsBool(const std::string& prop) { return cmSystemTools::IsOn(this->GetGlobalProperty(prop)); } void cmState::SetSourceDirectory(std::string const& sourceDirectory) { this->SourceDirectory = sourceDirectory; cmSystemTools::ConvertToUnixSlashes(this->SourceDirectory); cmSystemTools::SplitPath( cmSystemTools::CollapseFullPath(this->SourceDirectory), this->SourceDirectoryComponents); } const char* cmState::GetSourceDirectory() const { return this->SourceDirectory.c_str(); } std::vector const& cmState::GetSourceDirectoryComponents() const { return this->SourceDirectoryComponents; } void cmState::SetBinaryDirectory(std::string const& binaryDirectory) { this->BinaryDirectory = binaryDirectory; cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory); cmSystemTools::SplitPath( cmSystemTools::CollapseFullPath(this->BinaryDirectory), this->BinaryDirectoryComponents); } void cmState::SetWindowsShell(bool windowsShell) { this->WindowsShell = windowsShell; } bool cmState::UseWindowsShell() const { return this->WindowsShell; } void cmState::SetWindowsVSIDE(bool windowsVSIDE) { this->WindowsVSIDE = windowsVSIDE; } bool cmState::UseWindowsVSIDE() const { return this->WindowsVSIDE; } void cmState::SetWatcomWMake(bool watcomWMake) { this->WatcomWMake = watcomWMake; } bool cmState::UseWatcomWMake() const { return this->WatcomWMake; } void cmState::SetMinGWMake(bool minGWMake) { this->MinGWMake = minGWMake; } bool cmState::UseMinGWMake() const { return this->MinGWMake; } void cmState::SetNMake(bool nMake) { this->NMake = nMake; } bool cmState::UseNMake() const { return this->NMake; } void cmState::SetMSYSShell(bool mSYSShell) { this->MSYSShell = mSYSShell; } bool cmState::UseMSYSShell() const { return this->MSYSShell; } const char* cmState::GetBinaryDirectory() const { return this->BinaryDirectory.c_str(); } std::vector const& cmState::GetBinaryDirectoryComponents() const { return this->BinaryDirectoryComponents; } void cmState::Directory::ComputeRelativePathTopSource() { // Relative path conversion inside the source tree is not used to // construct relative paths passed to build tools so it is safe to use // even when the source is a network path. cmState::Snapshot snapshot = this->Snapshot_; std::vector snapshots; snapshots.push_back(snapshot); while (true) { snapshot = snapshot.GetBuildsystemDirectoryParent(); if (snapshot.IsValid()) { snapshots.push_back(snapshot); } else { break; } } std::string result = snapshots.front().GetDirectory().GetCurrentSource(); for (std::vector::const_iterator it = snapshots.begin() + 1; it != snapshots.end(); ++it) { std::string currentSource = it->GetDirectory().GetCurrentSource(); if(cmSystemTools::IsSubDirectory(result, currentSource)) { result = currentSource; } } this->DirectoryState->RelativePathTopSource = result; } void cmState::Directory::ComputeRelativePathTopBinary() { cmState::Snapshot snapshot = this->Snapshot_; std::vector snapshots; snapshots.push_back(snapshot); while (true) { snapshot = snapshot.GetBuildsystemDirectoryParent(); if (snapshot.IsValid()) { snapshots.push_back(snapshot); } else { break; } } std::string result = snapshots.front().GetDirectory().GetCurrentBinary(); for (std::vector::const_iterator it = snapshots.begin() + 1; it != snapshots.end(); ++it) { std::string currentBinary = it->GetDirectory().GetCurrentBinary(); if(cmSystemTools::IsSubDirectory(result, currentBinary)) { result = currentBinary; } } // The current working directory on Windows cannot be a network // path. Therefore relative paths cannot work when the binary tree // is a network path. if(result.size() < 2 || result.substr(0, 2) != "//") { this->DirectoryState->RelativePathTopBinary = result; } else { this->DirectoryState->RelativePathTopBinary = ""; } } cmState::Snapshot cmState::CreateBaseSnapshot() { PositionType pos = this->SnapshotData.Extend(this->SnapshotData.Root()); pos->DirectoryParent = this->SnapshotData.Root(); pos->ScopeParent = this->SnapshotData.Root(); pos->SnapshotType = BaseType; pos->BuildSystemDirectory = this->BuildsystemDirectory.Extend(this->BuildsystemDirectory.Root()); pos->ExecutionListFile = this->ExecutionListFiles.Extend(this->ExecutionListFiles.Root()); pos->IncludeDirectoryPosition = 0; pos->CompileDefinitionsPosition = 0; pos->CompileOptionsPosition = 0; pos->BuildSystemDirectory->DirectoryEnd = pos; pos->Policies = this->PolicyStack.Root(); pos->PolicyRoot = this->PolicyStack.Root(); pos->PolicyScope = this->PolicyStack.Root(); assert(pos->Policies.IsValid()); assert(pos->PolicyRoot.IsValid()); pos->Vars = this->VarTree.Extend(this->VarTree.Root()); assert(pos->Vars.IsValid()); pos->Parent = this->VarTree.Root(); pos->Root = this->VarTree.Root(); return cmState::Snapshot(this, pos); } cmState::Snapshot cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot, std::string const& entryPointCommand, long entryPointLine) { assert(originSnapshot.IsValid()); PositionType pos = this->SnapshotData.Extend(originSnapshot.Position); pos->EntryPointLine = entryPointLine; pos->EntryPointCommand = entryPointCommand; pos->DirectoryParent = originSnapshot.Position; pos->ScopeParent = originSnapshot.Position; pos->SnapshotType = BuildsystemDirectoryType; pos->BuildSystemDirectory = this->BuildsystemDirectory.Extend( originSnapshot.Position->BuildSystemDirectory); pos->ExecutionListFile = this->ExecutionListFiles.Extend( originSnapshot.Position->ExecutionListFile); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->Policies = originSnapshot.Position->Policies; pos->PolicyRoot = originSnapshot.Position->Policies; pos->PolicyScope = originSnapshot.Position->Policies; assert(pos->Policies.IsValid()); assert(pos->PolicyRoot.IsValid()); cmLinkedTree::iterator origin = originSnapshot.Position->Vars; pos->Parent = origin; pos->Root = origin; pos->Vars = this->VarTree.Extend(origin); cmState::Snapshot snapshot = cmState::Snapshot(this, pos); originSnapshot.Position->BuildSystemDirectory->Children.push_back(snapshot); snapshot.InitializeFromParent(); return snapshot; } cmState::Snapshot cmState::CreateFunctionCallSnapshot(cmState::Snapshot originSnapshot, std::string const& entryPointCommand, long entryPointLine, std::string const& fileName) { PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, *originSnapshot.Position); pos->ScopeParent = originSnapshot.Position; pos->EntryPointLine = entryPointLine; pos->EntryPointCommand = entryPointCommand; pos->SnapshotType = FunctionCallType; pos->ExecutionListFile = this->ExecutionListFiles.Extend( originSnapshot.Position->ExecutionListFile, fileName); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; assert(originSnapshot.Position->Vars.IsValid()); cmLinkedTree::iterator origin = originSnapshot.Position->Vars; pos->Parent = origin; pos->Vars = this->VarTree.Extend(origin); return cmState::Snapshot(this, pos); } cmState::Snapshot cmState::CreateMacroCallSnapshot(cmState::Snapshot originSnapshot, std::string const& entryPointCommand, long entryPointLine, std::string const& fileName) { PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, *originSnapshot.Position); pos->EntryPointLine = entryPointLine; pos->EntryPointCommand = entryPointCommand; pos->SnapshotType = MacroCallType; pos->ExecutionListFile = this->ExecutionListFiles.Extend( originSnapshot.Position->ExecutionListFile, fileName); assert(originSnapshot.Position->Vars.IsValid()); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; return cmState::Snapshot(this, pos); } cmState::Snapshot cmState::CreateCallStackSnapshot(cmState::Snapshot originSnapshot, const std::string& entryPointCommand, long entryPointLine, const std::string& fileName) { PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, *originSnapshot.Position); pos->EntryPointLine = entryPointLine; pos->EntryPointCommand = entryPointCommand; pos->SnapshotType = CallStackType; pos->ExecutionListFile = this->ExecutionListFiles.Extend( originSnapshot.Position->ExecutionListFile, fileName); assert(originSnapshot.Position->Vars.IsValid()); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; return cmState::Snapshot(this, pos); } cmState::Snapshot cmState::CreateVariableScopeSnapshot(cmState::Snapshot originSnapshot, std::string const& entryPointCommand, long entryPointLine) { PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, *originSnapshot.Position); pos->ScopeParent = originSnapshot.Position; pos->EntryPointLine = entryPointLine; pos->EntryPointCommand = entryPointCommand; pos->SnapshotType = VariableScopeType; assert(originSnapshot.Position->Vars.IsValid()); cmLinkedTree::iterator origin = originSnapshot.Position->Vars; pos->Parent = origin; pos->Vars = this->VarTree.Extend(origin); assert(pos->Vars.IsValid()); return cmState::Snapshot(this, pos); } cmState::Snapshot cmState::CreateInlineListFileSnapshot(cmState::Snapshot originSnapshot, const std::string& entryPointCommand, long entryPointLine, const std::string& fileName) { PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, *originSnapshot.Position); pos->EntryPointLine = entryPointLine; pos->EntryPointCommand = entryPointCommand; pos->SnapshotType = InlineListFileType; pos->ExecutionListFile = this->ExecutionListFiles.Extend( originSnapshot.Position->ExecutionListFile, fileName); pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; return cmState::Snapshot(this, pos); } cmState::Snapshot cmState::CreatePolicyScopeSnapshot(cmState::Snapshot originSnapshot) { PositionType pos = this->SnapshotData.Extend(originSnapshot.Position, *originSnapshot.Position); pos->SnapshotType = PolicyScopeType; pos->BuildSystemDirectory->DirectoryEnd = pos; pos->PolicyScope = originSnapshot.Position->Policies; return cmState::Snapshot(this, pos); } cmState::Snapshot cmState::Pop(cmState::Snapshot originSnapshot) { PositionType pos = originSnapshot.Position; PositionType prevPos = pos; ++prevPos; prevPos->IncludeDirectoryPosition = prevPos->BuildSystemDirectory->IncludeDirectories.size(); prevPos->CompileDefinitionsPosition = prevPos->BuildSystemDirectory->CompileDefinitions.size(); prevPos->CompileOptionsPosition = prevPos->BuildSystemDirectory->CompileOptions.size(); prevPos->BuildSystemDirectory->DirectoryEnd = prevPos; return Snapshot(this, prevPos); } cmState::Snapshot::Snapshot(cmState* state) : State(state) , Position() { } std::vector cmState::Snapshot::GetChildren() { return this->Position->BuildSystemDirectory->Children; } cmState::Snapshot::Snapshot(cmState* state, PositionType position) : State(state), Position(position) { } cmState::SnapshotType cmState::Snapshot::GetType() const { return this->Position->SnapshotType; } const char* cmState::Directory::GetCurrentSource() const { return this->DirectoryState->Location.c_str(); } void cmState::Directory::SetCurrentSource(std::string const& dir) { std::string& loc = this->DirectoryState->Location; loc = dir; cmSystemTools::ConvertToUnixSlashes(loc); loc = cmSystemTools::CollapseFullPath(loc); cmSystemTools::SplitPath( loc, this->DirectoryState->CurrentSourceDirectoryComponents); this->ComputeRelativePathTopSource(); } const char* cmState::Directory::GetCurrentBinary() const { return this->DirectoryState->OutputLocation.c_str(); } void cmState::Directory::SetCurrentBinary(std::string const& dir) { std::string& loc = this->DirectoryState->OutputLocation; loc = dir; cmSystemTools::ConvertToUnixSlashes(loc); loc = cmSystemTools::CollapseFullPath(loc); cmSystemTools::SplitPath( loc, this->DirectoryState->CurrentBinaryDirectoryComponents); this->ComputeRelativePathTopBinary(); } void cmState::Snapshot::SetListFile(const std::string& listfile) { *this->Position->ExecutionListFile = listfile; } std::vector const& cmState::Directory::GetCurrentSourceComponents() const { return this->DirectoryState->CurrentSourceDirectoryComponents; } std::vector const& cmState::Directory::GetCurrentBinaryComponents() const { return this->DirectoryState->CurrentBinaryDirectoryComponents; } const char* cmState::Directory::GetRelativePathTopSource() const { return this->DirectoryState->RelativePathTopSource.c_str(); } const char* cmState::Directory::GetRelativePathTopBinary() const { return this->DirectoryState->RelativePathTopBinary.c_str(); } void cmState::Directory::SetRelativePathTopSource(const char* dir) { this->DirectoryState->RelativePathTopSource = dir; } void cmState::Directory::SetRelativePathTopBinary(const char* dir) { this->DirectoryState->RelativePathTopBinary = dir; } std::string cmState::Snapshot::GetExecutionListFile() const { return *this->Position->ExecutionListFile; } std::string cmState::Snapshot::GetEntryPointCommand() const { return this->Position->EntryPointCommand; } long cmState::Snapshot::GetEntryPointLine() const { return this->Position->EntryPointLine; } bool cmState::Snapshot::IsValid() const { return this->State && this->Position.IsValid() ? this->Position != this->State->SnapshotData.Root() : false; } cmState::Snapshot cmState::Snapshot::GetBuildsystemDirectoryParent() const { Snapshot snapshot; if (!this->State || this->Position == this->State->SnapshotData.Root()) { return snapshot; } PositionType parentPos = this->Position->DirectoryParent; if (parentPos != this->State->SnapshotData.Root()) { snapshot = Snapshot(this->State, parentPos->BuildSystemDirectory->DirectoryEnd); } return snapshot; } cmState::Snapshot cmState::Snapshot::GetCallStackParent() const { assert(this->State); assert(this->Position != this->State->SnapshotData.Root()); Snapshot snapshot; PositionType parentPos = this->Position; while(parentPos->SnapshotType == cmState::PolicyScopeType) { ++parentPos; } if (parentPos->SnapshotType == cmState::BuildsystemDirectoryType || parentPos->SnapshotType == cmState::BaseType) { return snapshot; } ++parentPos; while(parentPos->SnapshotType == cmState::PolicyScopeType) { ++parentPos; } if (parentPos == this->State->SnapshotData.Root()) { return snapshot; } snapshot = Snapshot(this->State, parentPos); return snapshot; } void cmState::Snapshot::PushPolicy(cmPolicies::PolicyMap entry, bool weak) { PositionType pos = this->Position; pos->Policies = this->State->PolicyStack.Extend(pos->Policies, PolicyStackEntry(entry, weak)); } bool cmState::Snapshot::PopPolicy() { PositionType pos = this->Position; if (pos->Policies == pos->PolicyScope) { return false; } ++pos->Policies; return true; } bool cmState::Snapshot::CanPopPolicyScope() { return this->Position->Policies == this->Position->PolicyScope; } void cmState::Snapshot::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::iterator psi = this->Position->Policies; previous_was_weak && psi != this->Position->PolicyRoot; ++psi) { psi->Set(id, status); previous_was_weak = psi->Weak; } } cmPolicies::PolicyStatus cmState::Snapshot::GetPolicy(cmPolicies::PolicyID id) const { cmPolicies::PolicyStatus status = cmPolicies::GetPolicyStatus(id); if(status == cmPolicies::REQUIRED_ALWAYS || status == cmPolicies::REQUIRED_IF_USED) { return status; } cmLinkedTree::iterator dir = this->Position->BuildSystemDirectory; while (true) { assert(dir.IsValid()); cmLinkedTree::iterator leaf = dir->DirectoryEnd->Policies; cmLinkedTree::iterator root = dir->DirectoryEnd->PolicyRoot; for( ; leaf != root; ++leaf) { if(leaf->IsDefined(id)) { status = leaf->Get(id); return status; } } cmState::PositionType e = dir->DirectoryEnd; cmState::PositionType p = e->DirectoryParent; if (p == this->State->SnapshotData.Root()) { break; } dir = p->BuildSystemDirectory; } return status; } bool cmState::Snapshot::HasDefinedPolicyCMP0011() { return !this->Position->Policies->IsEmpty(); } const char* cmState::Snapshot::GetDefinition(std::string const& name) const { assert(this->Position->Vars.IsValid()); return cmDefinitions::Get(name, this->Position->Vars, this->Position->Root); } bool cmState::Snapshot::IsInitialized(std::string const& name) const { return cmDefinitions::HasKey(name, this->Position->Vars, this->Position->Root); } void cmState::Snapshot::SetDefinition(std::string const& name, std::string const& value) { this->Position->Vars->Set(name, value.c_str()); } void cmState::Snapshot::RemoveDefinition(std::string const& name) { this->Position->Vars->Set(name, 0); } std::vector cmState::Snapshot::UnusedKeys() const { return this->Position->Vars->UnusedKeys(); } std::vector cmState::Snapshot::ClosureKeys() const { return cmDefinitions::ClosureKeys(this->Position->Vars, this->Position->Root); } bool cmState::Snapshot::RaiseScope(std::string const& var, const char* varDef) { if(this->Position->ScopeParent == this->Position->DirectoryParent) { Snapshot 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. this->Position->Parent->Set(var, varDef); return true; } static const std::string cmPropertySentinal = std::string(); template void InitializeContentFromParent(T& parentContent, T& thisContent, U& parentBacktraces, U& thisBacktraces, V& contentEndPosition) { std::vector::const_iterator parentBegin = parentContent.begin(); std::vector::const_iterator parentEnd = parentContent.end(); std::vector::const_reverse_iterator parentRbegin = cmMakeReverseIterator(parentEnd); std::vector::const_reverse_iterator parentRend = parentContent.rend(); parentRbegin = std::find(parentRbegin, parentRend, cmPropertySentinal); std::vector::const_iterator parentIt = parentRbegin.base(); thisContent = std::vector(parentIt, parentEnd); std::vector::const_iterator btIt = parentBacktraces.begin() + std::distance(parentBegin, parentIt); std::vector::const_iterator btEnd = parentBacktraces.end(); thisBacktraces = std::vector(btIt, btEnd); contentEndPosition = thisContent.size(); } void cmState::Snapshot::InitializeFromParent() { 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, parent->BuildSystemDirectory->IncludeDirectoryBacktraces, this->Position->BuildSystemDirectory->IncludeDirectoryBacktraces, this->Position->IncludeDirectoryPosition); InitializeContentFromParent(parent->BuildSystemDirectory->CompileDefinitions, this->Position->BuildSystemDirectory->CompileDefinitions, parent->BuildSystemDirectory->CompileDefinitionsBacktraces, this->Position->BuildSystemDirectory->CompileDefinitionsBacktraces, this->Position->CompileDefinitionsPosition); InitializeContentFromParent(parent->BuildSystemDirectory->CompileOptions, this->Position->BuildSystemDirectory->CompileOptions, parent->BuildSystemDirectory->CompileOptionsBacktraces, this->Position->BuildSystemDirectory->CompileOptionsBacktraces, this->Position->CompileOptionsPosition); } cmState* cmState::Snapshot::GetState() const { return this->State; } cmState::Directory cmState::Snapshot::GetDirectory() const { return Directory(this->Position->BuildSystemDirectory, *this); } void cmState::Snapshot::SetProjectName(const std::string& name) { this->Position->BuildSystemDirectory->ProjectName = name; } std::string cmState::Snapshot::GetProjectName() const { return this->Position->BuildSystemDirectory->ProjectName; } cmState::Directory::Directory( cmLinkedTree::iterator iter, const cmState::Snapshot& snapshot) : DirectoryState(iter), Snapshot_(snapshot) { } template cmStringRange GetPropertyContent(T const& content, U contentEndPosition) { std::vector::const_iterator end = content.begin() + contentEndPosition; std::vector::const_reverse_iterator rbegin = cmMakeReverseIterator(end); rbegin = std::find(rbegin, content.rend(), cmPropertySentinal); return cmMakeRange(rbegin.base(), end); } template cmBacktraceRange GetPropertyBacktraces(T const& content, U const& backtraces, V contentEndPosition) { std::vector::const_iterator entryEnd = content.begin() + contentEndPosition; std::vector::const_reverse_iterator rbegin = cmMakeReverseIterator(entryEnd); rbegin = std::find(rbegin, content.rend(), cmPropertySentinal); std::vector::const_iterator it = backtraces.begin() + std::distance(content.begin(), rbegin.base()); std::vector::const_iterator end = backtraces.end(); return cmMakeRange(it, end); } template void AppendEntry(T& content, U& backtraces, V& endContentPosition, const std::string& value, const cmListFileBacktrace& lfbt) { if (value.empty()) { return; } assert(endContentPosition == content.size()); content.push_back(value); backtraces.push_back(lfbt); endContentPosition = content.size(); } template void SetContent(T& content, U& backtraces, V& endContentPosition, const std::string& vec, const cmListFileBacktrace& lfbt) { assert(endContentPosition == content.size()); content.resize(content.size() + 2); backtraces.resize(backtraces.size() + 2); content.back() = vec; backtraces.back() = lfbt; endContentPosition = content.size(); } template void ClearContent(T& content, U& backtraces, V& endContentPosition) { assert(endContentPosition == content.size()); content.resize(content.size() + 1); backtraces.resize(backtraces.size() + 1); endContentPosition = content.size(); } cmStringRange cmState::Directory::GetIncludeDirectoriesEntries() const { return GetPropertyContent(this->DirectoryState->IncludeDirectories, this->Snapshot_.Position->IncludeDirectoryPosition); } cmBacktraceRange cmState::Directory::GetIncludeDirectoriesEntryBacktraces() const { return GetPropertyBacktraces(this->DirectoryState->IncludeDirectories, this->DirectoryState->IncludeDirectoryBacktraces, this->Snapshot_.Position->IncludeDirectoryPosition); } void cmState::Directory::AppendIncludeDirectoriesEntry( const std::string& vec, const cmListFileBacktrace& lfbt) { AppendEntry(this->DirectoryState->IncludeDirectories, this->DirectoryState->IncludeDirectoryBacktraces, this->Snapshot_.Position->IncludeDirectoryPosition, vec, lfbt); } void cmState::Directory::PrependIncludeDirectoriesEntry( const std::string& vec, const cmListFileBacktrace& lfbt) { std::vector::iterator entryEnd = this->DirectoryState->IncludeDirectories.begin() + this->Snapshot_.Position->IncludeDirectoryPosition; std::vector::reverse_iterator rend = this->DirectoryState->IncludeDirectories.rend(); std::vector::reverse_iterator rbegin = cmMakeReverseIterator(entryEnd); rbegin = std::find(rbegin, rend, cmPropertySentinal); std::vector::iterator entryIt = rbegin.base(); std::vector::iterator entryBegin = this->DirectoryState->IncludeDirectories.begin(); std::vector::iterator btIt = this->DirectoryState->IncludeDirectoryBacktraces.begin() + std::distance(entryBegin, entryIt); this->DirectoryState->IncludeDirectories.insert(entryIt, vec); this->DirectoryState->IncludeDirectoryBacktraces.insert(btIt, lfbt); this->Snapshot_.Position->IncludeDirectoryPosition = this->DirectoryState->IncludeDirectories.size(); } void cmState::Directory::SetIncludeDirectories( const std::string& vec, const cmListFileBacktrace& lfbt) { SetContent(this->DirectoryState->IncludeDirectories, this->DirectoryState->IncludeDirectoryBacktraces, this->Snapshot_.Position->IncludeDirectoryPosition, vec, lfbt); } void cmState::Directory::ClearIncludeDirectories() { ClearContent(this->DirectoryState->IncludeDirectories, this->DirectoryState->IncludeDirectoryBacktraces, this->Snapshot_.Position->IncludeDirectoryPosition); } cmStringRange cmState::Directory::GetCompileDefinitionsEntries() const { return GetPropertyContent(this->DirectoryState->CompileDefinitions, this->Snapshot_.Position->CompileDefinitionsPosition); } cmBacktraceRange cmState::Directory::GetCompileDefinitionsEntryBacktraces() const { return GetPropertyBacktraces(this->DirectoryState->CompileDefinitions, this->DirectoryState->CompileDefinitionsBacktraces, this->Snapshot_.Position->CompileDefinitionsPosition); } void cmState::Directory::AppendCompileDefinitionsEntry(const std::string& vec, const cmListFileBacktrace& lfbt) { AppendEntry(this->DirectoryState->CompileDefinitions, this->DirectoryState->CompileDefinitionsBacktraces, this->Snapshot_.Position->CompileDefinitionsPosition, vec, lfbt); } void cmState::Directory::SetCompileDefinitions(const std::string& vec, const cmListFileBacktrace& lfbt) { SetContent(this->DirectoryState->CompileDefinitions, this->DirectoryState->CompileDefinitionsBacktraces, this->Snapshot_.Position->CompileDefinitionsPosition, vec, lfbt); } void cmState::Directory::ClearCompileDefinitions() { ClearContent(this->DirectoryState->CompileDefinitions, this->DirectoryState->CompileDefinitionsBacktraces, this->Snapshot_.Position->CompileDefinitionsPosition); } cmStringRange cmState::Directory::GetCompileOptionsEntries() const { return GetPropertyContent(this->DirectoryState->CompileOptions, this->Snapshot_.Position->CompileOptionsPosition); } cmBacktraceRange cmState::Directory::GetCompileOptionsEntryBacktraces() const { return GetPropertyBacktraces(this->DirectoryState->CompileOptions, this->DirectoryState->CompileOptionsBacktraces, this->Snapshot_.Position->CompileOptionsPosition); } void cmState::Directory::AppendCompileOptionsEntry(const std::string& vec, const cmListFileBacktrace& lfbt) { AppendEntry(this->DirectoryState->CompileOptions, this->DirectoryState->CompileOptionsBacktraces, this->Snapshot_.Position->CompileOptionsPosition, vec, lfbt); } void cmState::Directory::SetCompileOptions(const std::string& vec, const cmListFileBacktrace& lfbt) { SetContent(this->DirectoryState->CompileOptions, this->DirectoryState->CompileOptionsBacktraces, this->Snapshot_.Position->CompileOptionsPosition, vec, lfbt); } void cmState::Directory::ClearCompileOptions() { ClearContent(this->DirectoryState->CompileOptions, this->DirectoryState->CompileOptionsBacktraces, this->Snapshot_.Position->CompileOptionsPosition); } bool cmState::Snapshot::StrictWeakOrder::operator()( const cmState::Snapshot& lhs, const cmState::Snapshot& rhs) const { return lhs.Position.StrictWeakOrdered(rhs.Position); } void cmState::Directory::SetProperty(const std::string& prop, const char* value, cmListFileBacktrace lfbt) { if (prop == "INCLUDE_DIRECTORIES") { if (!value) { this->ClearIncludeDirectories(); return; } this->SetIncludeDirectories(value, lfbt); return; } if (prop == "COMPILE_OPTIONS") { if (!value) { this->ClearCompileOptions(); return; } this->SetCompileOptions(value, lfbt); return; } if (prop == "COMPILE_DEFINITIONS") { if (!value) { this->ClearCompileDefinitions(); return; } this->SetCompileDefinitions(value, lfbt); return; } this->DirectoryState->Properties.SetProperty(prop, value); } void cmState::Directory::AppendProperty(const std::string& prop, const char* value, bool asString, cmListFileBacktrace lfbt) { if (prop == "INCLUDE_DIRECTORIES") { this->AppendIncludeDirectoriesEntry(value, lfbt); return; } if (prop == "COMPILE_OPTIONS") { this->AppendCompileOptionsEntry(value, lfbt); return; } if (prop == "COMPILE_DEFINITIONS") { this->AppendCompileDefinitionsEntry(value, lfbt); return; } this->DirectoryState->Properties.AppendProperty(prop, value, asString); } const char*cmState::Directory::GetProperty(const std::string& prop) const { const bool chain = this->Snapshot_.State-> IsPropertyChained(prop, cmProperty::DIRECTORY); return this->GetProperty(prop, chain); } const char* cmState::Directory::GetProperty(const std::string& prop, bool chain) const { static std::string output; output = ""; if (prop == "PARENT_DIRECTORY") { cmState::Snapshot parent = this->Snapshot_.GetBuildsystemDirectoryParent(); if(parent.IsValid()) { return parent.GetDirectory().GetCurrentSource(); } return ""; } else if (prop == "LISTFILE_STACK") { std::vector listFiles; cmState::Snapshot snp = this->Snapshot_; while (snp.IsValid()) { listFiles.push_back(snp.GetExecutionListFile()); snp = snp.GetCallStackParent(); } std::reverse(listFiles.begin(), listFiles.end()); output = cmJoin(listFiles, ";"); return output.c_str(); } else if ( prop == "CACHE_VARIABLES" ) { output = cmJoin(this->Snapshot_.State->GetCacheEntryKeys(), ";"); return output.c_str(); } else if (prop == "VARIABLES") { std::vector res = this->Snapshot_.ClosureKeys(); std::vector cacheKeys = this->Snapshot_.State->GetCacheEntryKeys(); res.insert(res.end(), cacheKeys.begin(), cacheKeys.end()); std::sort(res.begin(), res.end()); output = cmJoin(res, ";"); return output.c_str(); } else if (prop == "INCLUDE_DIRECTORIES") { output = cmJoin(this->GetIncludeDirectoriesEntries(), ";"); return output.c_str(); } else if (prop == "COMPILE_OPTIONS") { output = cmJoin(this->GetCompileOptionsEntries(), ";"); return output.c_str(); } else if (prop == "COMPILE_DEFINITIONS") { output = cmJoin(this->GetCompileDefinitionsEntries(), ";"); return output.c_str(); } const char *retVal = this->DirectoryState->Properties.GetPropertyValue(prop); if (!retVal && chain) { Snapshot parentSnapshot = this->Snapshot_.GetBuildsystemDirectoryParent(); if (parentSnapshot.IsValid()) { return parentSnapshot.GetDirectory().GetProperty(prop, chain); } return this->Snapshot_.State->GetGlobalProperty(prop); } return retVal; } bool cmState::Directory::GetPropertyAsBool(const std::string& prop) const { return cmSystemTools::IsOn(this->GetProperty(prop)); } std::vector cmState::Directory::GetPropertyKeys() const { std::vector keys; keys.reserve(this->DirectoryState->Properties.size()); for(cmPropertyMap::const_iterator it = this->DirectoryState->Properties.begin(); it != this->DirectoryState->Properties.end(); ++it) { keys.push_back(it->first); } return keys; } bool operator==(const cmState::Snapshot& lhs, const cmState::Snapshot& rhs) { return lhs.Position == rhs.Position; } bool operator!=(const cmState::Snapshot& lhs, const cmState::Snapshot& rhs) { return lhs.Position != rhs.Position; }