diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 1d02cfaf6..513a643da 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -31,7 +31,6 @@ #endif #include "cmInstallGenerator.h" #include "cmTestGenerator.h" -#include "cmDefinitions.h" #include "cmAlgorithms.h" #include "cmake.h" #include // required for atoi @@ -47,132 +46,7 @@ class cmMakefile::Internals { public: - - enum ScopeType - { - BaseScope, - MacroScope, - FunctionScope, - VariableScope - }; - - struct VarScope - { - ScopeType Type; - cmLinkedTree::iterator Vars; - cmLinkedTree::iterator ParentScope; - }; - - cmLinkedTree VarTree; - cmLinkedTree VarScopes; - cmLinkedTree::iterator VarScopeIter; bool IsSourceFileTryCompile; - - void PushDefinitions(ScopeType scope) - { - assert(this->VarScopeIter.IsValid()); - assert(this->VarScopeIter->Vars.IsValid()); - cmLinkedTree::iterator origin = - this->VarScopeIter->Vars; - cmLinkedTree::iterator parentScope = -// this->VarTree.Extend(origin); - origin; - this->VarScopeIter->Vars = parentScope; - this->VarScopeIter = this->VarScopes.Extend(this->VarScopeIter); - this->VarScopeIter->ParentScope = parentScope; - this->VarScopeIter->Vars = this->VarTree.Extend(origin); - this->VarScopeIter->Type = scope; - } - - void InitializeVarScope() - { - assert(!this->VarScopeIter.IsValid()); - this->VarScopeIter = this->VarScopes.Extend(this->VarScopes.Root()); - this->VarScopeIter->Vars = this->VarTree.Extend(this->VarTree.Root()); - this->VarScopeIter->ParentScope = this->VarTree.Root(); - this->VarScopeIter->Type = BaseScope; - } - - void InitializeDefinitions(cmMakefile* parent) - { - assert(this->VarScopeIter.IsValid()); - assert(this->VarScopeIter->Vars.IsValid()); - *this->VarScopeIter->Vars = - cmDefinitions::MakeClosure(parent->Internal->VarScopeIter->Vars, - parent->Internal->VarTree.Root()); - } - - const char* GetDefinition(std::string const& name) - { - assert(this->VarScopeIter.IsValid()); - assert(this->VarScopeIter->Vars.IsValid()); - return cmDefinitions::Get(name, - this->VarScopeIter->Vars, this->VarTree.Root()); - } - - bool IsInitialized(std::string const& name) - { - return cmDefinitions::HasKey(name, - this->VarScopeIter->Vars, this->VarTree.Root()); - } - - void SetDefinition(std::string const& name, std::string const& value) - { - this->VarScopeIter->Vars->Set(name, value.c_str()); - } - - void RemoveDefinition(std::string const& name) - { - this->VarScopeIter->Vars->Set(name, 0); - } - - std::vector UnusedKeys() const - { - return this->VarScopeIter->Vars->UnusedKeys(); - } - - std::vector ClosureKeys() const - { - return cmDefinitions::ClosureKeys(this->VarScopeIter->Vars, - this->VarTree.Root()); - } - - void PopDefinitions() - { - ++this->VarScopeIter; - } - - bool RaiseScope(std::string const& var, const char* varDef, cmMakefile* mf) - { - assert(this->VarScopeIter->Vars != this->VarTree.Root()); - if(this->VarScopeIter->ParentScope == this->VarTree.Root()) - { - cmLocalGenerator* plg = mf->LocalGenerator->GetParent(); - if(!plg) - { - 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. - cmMakefile* parent = plg->GetMakefile(); - if (varDef) - { - parent->AddDefinition(var, varDef); - } - else - { - parent->RemoveDefinition(var); - } - return true; - } - // First localize the definition in the current scope. - cmDefinitions::Raise(var, this->VarScopeIter->Vars, this->VarTree.Root()); - - // Now update the definition in the parent scope. - this->VarScopeIter->ParentScope->Set(var, varDef); - return true; - } }; // default is not to be building executables @@ -181,7 +55,6 @@ cmMakefile::cmMakefile(cmLocalGenerator* localGenerator) LocalGenerator(localGenerator), StateSnapshot(localGenerator->GetStateSnapshot()) { - this->Internal->InitializeVarScope(); this->Internal->IsSourceFileTryCompile = false; // Initialize these first since AddDefaultDefinitions calls AddDefinition @@ -1607,9 +1480,6 @@ void cmMakefile::AddLinkLibrary(const std::string& lib) void cmMakefile::InitializeFromParent(cmMakefile* parent) { - // Initialize definitions with the closure of the parent scope. - this->Internal->InitializeDefinitions(parent); - this->StateSnapshot.InitializeFromParent(); this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", @@ -1674,8 +1544,6 @@ void cmMakefile::PushFunctionScope(std::string const& fileName, fileName); assert(this->StateSnapshot.IsValid()); - this->Internal->PushDefinitions(Internals::FunctionScope); - this->PushLoopBlockBarrier(); #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -1702,8 +1570,6 @@ void cmMakefile::PopFunctionScope(bool reportError) this->PopLoopBlockBarrier(); this->CheckForUnusedVariables(); - - this->Internal->PopDefinitions(); } void cmMakefile::PushMacroScope(std::string const& fileName, @@ -2007,7 +1873,7 @@ void cmMakefile::AddDefinition(const std::string& name, const char* value) { this->LogUnused("changing definition", name); } - this->Internal->SetDefinition(name, value); + this->StateSnapshot.SetDefinition(name, value); #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); @@ -2070,7 +1936,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, this->GetState()->AddCacheEntry(name, haveVal ? val.c_str() : 0, doc, type); // if there was a definition then remove it - this->Internal->RemoveDefinition(name); + this->StateSnapshot.RemoveDefinition(name); } @@ -2080,7 +1946,9 @@ void cmMakefile::AddDefinition(const std::string& name, bool value) { this->LogUnused("changing definition", name); } - this->Internal->SetDefinition(name, value ? "ON" : "OFF"); + + this->StateSnapshot.SetDefinition(name, value ? "ON" : "OFF"); + #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); if ( vv ) @@ -2097,7 +1965,7 @@ void cmMakefile::CheckForUnusedVariables() const { return; } - const std::vector& unused = this->Internal->UnusedKeys(); + const std::vector& unused = this->StateSnapshot.UnusedKeys(); std::vector::const_iterator it = unused.begin(); for (; it != unused.end(); ++it) { @@ -2107,12 +1975,12 @@ void cmMakefile::CheckForUnusedVariables() const void cmMakefile::MarkVariableAsUsed(const std::string& var) { - this->Internal->GetDefinition(var); + this->StateSnapshot.GetDefinition(var); } bool cmMakefile::VariableInitialized(const std::string& var) const { - return this->Internal->IsInitialized(var); + return this->StateSnapshot.IsInitialized(var); } void cmMakefile::LogUnused(const char* reason, @@ -2160,7 +2028,7 @@ void cmMakefile::RemoveDefinition(const std::string& name) { this->LogUnused("unsetting", name); } - this->Internal->RemoveDefinition(name); + this->StateSnapshot.RemoveDefinition(name); #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); if ( vv ) @@ -2626,7 +2494,7 @@ const char* cmMakefile::GetRequiredDefinition(const std::string& name) const bool cmMakefile::IsDefinitionSet(const std::string& name) const { - const char* def = this->Internal->GetDefinition(name); + const char* def = this->StateSnapshot.GetDefinition(name); if(!def) { def = this->GetState()->GetInitializedCacheValue(name); @@ -2647,7 +2515,7 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const const char* cmMakefile::GetDefinition(const std::string& name) const { - const char* def = this->Internal->GetDefinition(name); + const char* def = this->StateSnapshot.GetDefinition(name); if(!def) { def = this->GetState()->GetInitializedCacheValue(name); @@ -2683,7 +2551,7 @@ const char* cmMakefile::GetSafeDefinition(const std::string& def) const std::vector cmMakefile::GetDefinitions() const { - std::vector res = this->Internal->ClosureKeys(); + std::vector res = this->StateSnapshot.ClosureKeys(); std::vector cacheKeys = this->GetState()->GetCacheEntryKeys(); res.insert(res.end(), cacheKeys.begin(), cacheKeys.end()); std::sort(res.begin(), res.end()); @@ -4462,8 +4330,6 @@ std::string cmMakefile::FormatListFileStack() const void cmMakefile::PushScope() { - this->Internal->PushDefinitions(Internals::VariableScope); - std::string commandName; long line = 0; if (!this->ContextStack.empty()) @@ -4492,7 +4358,6 @@ void cmMakefile::PopScope() this->CheckForUnusedVariables(); - this->Internal->PopDefinitions(); this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot); assert(this->StateSnapshot.IsValid()); @@ -4505,7 +4370,7 @@ void cmMakefile::RaiseScope(const std::string& var, const char *varDef) return; } - if (!this->Internal->RaiseScope(var, varDef, this)) + if (!this->StateSnapshot.RaiseScope(var, varDef)) { std::ostringstream m; m << "Cannot set \"" << var << "\": current scope has no parent."; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index 9e09353b0..ab309ad31 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -15,6 +15,7 @@ #include "cmCacheManager.h" #include "cmCommand.h" #include "cmAlgorithms.h" +#include "cmDefinitions.h" #include @@ -29,6 +30,9 @@ struct cmState::SnapshotDataType 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; @@ -275,6 +279,10 @@ cmState::Snapshot cmState::Reset() 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, @@ -752,6 +760,10 @@ cmState::Snapshot cmState::CreateBaseSnapshot() 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); } @@ -779,6 +791,12 @@ cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot, 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); return cmState::Snapshot(this, pos); } @@ -798,6 +816,11 @@ cmState::CreateFunctionCallSnapshot(cmState::Snapshot originSnapshot, 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); } @@ -815,6 +838,7 @@ cmState::CreateMacroCallSnapshot(cmState::Snapshot originSnapshot, 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); @@ -833,6 +857,7 @@ cmState::CreateCallStackSnapshot(cmState::Snapshot originSnapshot, 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); @@ -849,7 +874,13 @@ cmState::CreateVariableScopeSnapshot(cmState::Snapshot originSnapshot, 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); } @@ -1141,6 +1172,72 @@ 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 @@ -1177,6 +1274,11 @@ void InitializeContentFromParent(T& parentContent, 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, diff --git a/Source/cmState.h b/Source/cmState.h index 4d87653bb..549966549 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -21,6 +21,8 @@ class cmake; class cmCommand; +class cmDefinitions; +class cmListFileBacktrace; class cmState { @@ -52,6 +54,14 @@ public: Snapshot(cmState* state = 0); Snapshot(cmState* state, PositionType position); + const char* GetDefinition(std::string const& name) const; + bool IsInitialized(std::string const& name) const; + void SetDefinition(std::string const& name, std::string const& value); + void RemoveDefinition(std::string const& name); + std::vector UnusedKeys() const; + std::vector ClosureKeys() const; + bool RaiseScope(std::string const& var, const char* varDef); + void SetListFile(std::string const& listfile); std::string GetExecutionListFile() const; @@ -273,6 +283,7 @@ private: cmLinkedTree PolicyStack; cmLinkedTree SnapshotData; + cmLinkedTree VarTree; std::vector SourceDirectoryComponents; std::vector BinaryDirectoryComponents;