diff options
author | Brad King <brad.king@kitware.com> | 2015-04-30 15:19:20 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2015-04-30 15:19:20 (GMT) |
commit | 5e35d4a67f347cd1e4bb66dc225385ce4e8b1f5a (patch) | |
tree | cd42e19fe02c91968c3255b859be26f62ccacbeb | |
parent | 88c5ec72b07914e96af9a97c23a5701adc8739cf (diff) | |
parent | b48ea26a9d3b4384874554fe64edfce8784a9255 (diff) | |
download | CMake-5e35d4a67f347cd1e4bb66dc225385ce4e8b1f5a.zip CMake-5e35d4a67f347cd1e4bb66dc225385ce4e8b1f5a.tar.gz CMake-5e35d4a67f347cd1e4bb66dc225385ce4e8b1f5a.tar.bz2 |
Merge topic 'refactor-cmDefinitions'
b48ea26a cmDefinitions: Invert conditional code.
5ccff640 cmDefinitions: Externalize looping for ClosureKeys.
f79cd99d cmDefinitions: Implement MakeClosure in terms of reverse iterators.
aa4d1ee8 cmDefinitions: Convert MakeClosure into a static method.
60becdc6 cmDefinitions: Implement MakeClosure in terms of a list of ancestors.
d858f363 cmDefinitions: Use list of cmDefinitions* to create closure.
aaaa65b6 cmMakefile: Remove stack adaptor for the VarStack.
f983d891 cmDefinitions: Replace recursion with loop.
24885d4e cmDefinitions: Replace private constructor with MakeClosure.
012a75a0 cmDefinitions: Make ClosureKeys API vector-based.
ca9fa77d cmDefinitions: Inline GetClosureKeys implementation.
78e1454e cmDefinitions: Replace ClosureKeys recursion with looping.
818bf727 cmDefinitions: Change LocalKeys to return a vector.
5067ae41 cmDefinitions: Externalize the Set logic.
60200ca5 cmDefinitions: Add an Erase method.
b43c162e cmMakefile: Use the Internal class to enclose the VarStack.
-rw-r--r-- | Source/cmDefinitions.cxx | 118 | ||||
-rw-r--r-- | Source/cmDefinitions.h | 28 | ||||
-rw-r--r-- | Source/cmMakefile.cxx | 167 |
3 files changed, 179 insertions, 134 deletions
diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index abb46b3..61328be 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -29,13 +29,14 @@ cmDefinitions::GetInternal(const std::string& key) { return i->second; } - if(cmDefinitions* up = this->Up) + cmDefinitions* up = this->Up; + if(!up) { - // Query the parent scope and store the result locally. - Def def = up->GetInternal(key); - return this->Map.insert(MapType::value_type(key, def)).first->second; + return this->NoDef; } - return this->NoDef; + // Query the parent scope and store the result locally. + Def def = up->GetInternal(key); + return this->Map.insert(MapType::value_type(key, def)).first->second; } //---------------------------------------------------------------------------- @@ -49,107 +50,86 @@ const char* cmDefinitions::Get(const std::string& key) void cmDefinitions::Set(const std::string& key, const char* value) { Def def(value); - if(this->Up || def.Exists) - { - // In lower scopes we store keys, defined or not. - this->Map[key] = def; - } - else - { - // In the top-most scope we need not store undefined keys. - this->Map.erase(key); - } + this->Map[key] = def; +} + +void cmDefinitions::Erase(const std::string& key) +{ + this->Map.erase(key); } //---------------------------------------------------------------------------- -std::set<std::string> cmDefinitions::LocalKeys() const +std::vector<std::string> cmDefinitions::LocalKeys() const { - std::set<std::string> keys; + std::vector<std::string> keys; + keys.reserve(this->Map.size()); // Consider local definitions. for(MapType::const_iterator mi = this->Map.begin(); mi != this->Map.end(); ++mi) { if (mi->second.Exists) { - keys.insert(mi->first); + keys.push_back(mi->first); } } return keys; } //---------------------------------------------------------------------------- -cmDefinitions cmDefinitions::Closure() const -{ - return cmDefinitions(ClosureTag(), this); -} - -//---------------------------------------------------------------------------- -cmDefinitions::cmDefinitions(ClosureTag const&, cmDefinitions const* root): - Up(0) +cmDefinitions cmDefinitions::MakeClosure( + std::list<cmDefinitions>::const_reverse_iterator rbegin, + std::list<cmDefinitions>::const_reverse_iterator rend) { std::set<std::string> undefined; - this->ClosureImpl(undefined, root); + cmDefinitions closure; + closure.MakeClosure(undefined, rbegin, rend); + return closure; } //---------------------------------------------------------------------------- -void cmDefinitions::ClosureImpl(std::set<std::string>& undefined, - cmDefinitions const* defs) +void +cmDefinitions::MakeClosure(std::set<std::string>& undefined, + std::list<cmDefinitions>::const_reverse_iterator rbegin, + std::list<cmDefinitions>::const_reverse_iterator rend) { - // Consider local definitions. - for(MapType::const_iterator mi = defs->Map.begin(); - mi != defs->Map.end(); ++mi) + for (std::list<cmDefinitions>::const_reverse_iterator it = rbegin; + it != rend; ++it) { - // Use this key if it is not already set or unset. - if(this->Map.find(mi->first) == this->Map.end() && - undefined.find(mi->first) == undefined.end()) + // Consider local definitions. + for(MapType::const_iterator mi = it->Map.begin(); + mi != it->Map.end(); ++mi) { - if(mi->second.Exists) - { - this->Map.insert(*mi); - } - else + // Use this key if it is not already set or unset. + if(this->Map.find(mi->first) == this->Map.end() && + undefined.find(mi->first) == undefined.end()) { - undefined.insert(mi->first); + if(mi->second.Exists) + { + this->Map.insert(*mi); + } + else + { + undefined.insert(mi->first); + } } } } - - // Traverse parents. - if(cmDefinitions const* up = defs->Up) - { - this->ClosureImpl(undefined, up); - } -} - -//---------------------------------------------------------------------------- -std::set<std::string> cmDefinitions::ClosureKeys() const -{ - std::set<std::string> defined; - std::set<std::string> undefined; - this->ClosureKeys(defined, undefined); - return defined; } //---------------------------------------------------------------------------- -void cmDefinitions::ClosureKeys(std::set<std::string>& defined, - std::set<std::string>& undefined) const +std::vector<std::string> +cmDefinitions::ClosureKeys(std::set<std::string>& bound) const { - // Consider local definitions. + std::vector<std::string> defined; + defined.reserve(this->Map.size()); for(MapType::const_iterator mi = this->Map.begin(); mi != this->Map.end(); ++mi) { // Use this key if it is not already set or unset. - if(defined.find(mi->first) == defined.end() && - undefined.find(mi->first) == undefined.end()) + if(bound.insert(mi->first).second && mi->second.Exists) { - std::set<std::string>& m = mi->second.Exists? defined : undefined; - m.insert(mi->first); + defined.push_back(mi->first); } } - - // Traverse parents. - if(cmDefinitions const* up = this->Up) - { - up->ClosureKeys(defined, undefined); - } + return defined; } diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index 83cd0d9..4c7f11f 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -17,6 +17,8 @@ #include "cmsys/hash_map.hxx" #endif +#include <list> + /** \class cmDefinitions * \brief Store a scope of variable definitions for CMake language. * @@ -40,15 +42,17 @@ public: /** Set (or unset if null) a value associated with a key. */ void Set(const std::string& key, const char* value); + void Erase(const std::string& key); + /** Get the set of all local keys. */ - std::set<std::string> LocalKeys() const; + std::vector<std::string> LocalKeys() const; - /** Compute the closure of all defined keys with values. - This flattens the scope. The result has no parent. */ - cmDefinitions Closure() const; + std::vector<std::string> + ClosureKeys(std::set<std::string>& bound) const; - /** Compute the set of all defined keys. */ - std::set<std::string> ClosureKeys() const; + static cmDefinitions MakeClosure( + std::list<cmDefinitions>::const_reverse_iterator rbegin, + std::list<cmDefinitions>::const_reverse_iterator rend); private: // String with existence boolean. @@ -79,15 +83,9 @@ private: // Internal query and update methods. Def const& GetInternal(const std::string& key); - // Implementation of Closure() method. - struct ClosureTag {}; - cmDefinitions(ClosureTag const&, cmDefinitions const* root); - void ClosureImpl(std::set<std::string>& undefined, - cmDefinitions const* defs); - - // Implementation of ClosureKeys() method. - void ClosureKeys(std::set<std::string>& defined, - std::set<std::string>& undefined) const; + void MakeClosure(std::set<std::string>& undefined, + std::list<cmDefinitions>::const_reverse_iterator rbegin, + std::list<cmDefinitions>::const_reverse_iterator rend); }; #endif diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 9f1d107..bd42f4e 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -46,10 +46,107 @@ class cmMakefile::Internals { public: - std::stack<cmDefinitions, std::list<cmDefinitions> > VarStack; + std::list<cmDefinitions> VarStack; std::stack<std::set<std::string> > VarInitStack; std::stack<std::set<std::string> > VarUsageStack; bool IsSourceFileTryCompile; + + void PushDefinitions() + { + cmDefinitions* parent = 0; + if (!this->VarStack.empty()) + { + parent = &this->VarStack.back(); + } + this->VarStack.push_back(cmDefinitions(parent)); + } + + void InitializeDefinitions(cmMakefile* parent) + { + this->VarStack.back() = + cmDefinitions::MakeClosure(parent->Internal->VarStack.rbegin(), + parent->Internal->VarStack.rend()); + } + + const char* GetDefinition(std::string const& name) + { + return this->VarStack.back().Get(name); + } + + void SetDefinition(std::string const& name, std::string const& value) + { + this->VarStack.back().Set(name, value.c_str()); + } + + void RemoveDefinition(std::string const& name) + { + if (this->VarStack.size() > 1) + { + // In lower scopes we store keys, defined or not. + this->VarStack.back().Set(name, 0); + } + else + { + this->VarStack.back().Erase(name); + } + } + + std::vector<std::string> LocalKeys() const + { + return this->VarStack.back().LocalKeys(); + } + + std::vector<std::string> ClosureKeys() const + { + std::vector<std::string> closureKeys; + std::set<std::string> bound; + for (std::list<cmDefinitions>::const_reverse_iterator it = + this->VarStack.rbegin(); it != this->VarStack.rend(); ++it) + { + std::vector<std::string> const& localKeys = it->ClosureKeys(bound); + closureKeys.insert(closureKeys.end(), + localKeys.begin(), localKeys.end()); + } + return closureKeys; + } + + void PopDefinitions() + { + this->VarStack.pop_back(); + } + + bool RaiseScope(std::string const& var, const char* varDef, cmMakefile* mf) + { + cmDefinitions& cur = this->VarStack.back(); + if(cmDefinitions* up = cur.GetParent()) + { + // First localize the definition in the current scope. + cur.Get(var); + + // Now update the definition in the parent scope. + up->Set(var, varDef); + } + else if(cmLocalGenerator* plg = mf->GetLocalGenerator()->GetParent()) + { + // 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); + } + } + else + { + return false; + } + return true; + } }; // default is not to be building executables @@ -59,11 +156,9 @@ cmMakefile::cmMakefile(cmLocalGenerator* localGenerator) StateSnapshot(localGenerator->GetGlobalGenerator() ->GetCMakeInstance()->GetState()) { - const cmDefinitions& defs = cmDefinitions(); - const std::set<std::string> globalKeys = defs.LocalKeys(); - this->Internal->VarStack.push(defs); - this->Internal->VarInitStack.push(globalKeys); - this->Internal->VarUsageStack.push(globalKeys); + this->Internal->PushDefinitions(); + this->Internal->VarInitStack.push(std::set<std::string>()); + this->Internal->VarUsageStack.push(std::set<std::string>()); this->Internal->IsSourceFileTryCompile = false; if (this->LocalGenerator->GetParent()) @@ -1496,7 +1591,7 @@ void cmMakefile::InitializeFromParent() cmMakefile *parent = this->LocalGenerator->GetParent()->GetMakefile(); // Initialize definitions with the closure of the parent scope. - this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure(); + this->Internal->InitializeDefinitions(parent); this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", this->GetCurrentSourceDirectory()); @@ -1690,7 +1785,7 @@ void cmMakefile::AddDefinition(const std::string& name, const char* value) return; } - this->Internal->VarStack.top().Set(name, value); + this->Internal->SetDefinition(name, value); if (!this->Internal->VarUsageStack.empty() && this->VariableInitialized(name)) { @@ -1760,13 +1855,13 @@ 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->VarStack.top().Set(name, 0); + this->Internal->RemoveDefinition(name); } void cmMakefile::AddDefinition(const std::string& name, bool value) { - this->Internal->VarStack.top().Set(name, value? "ON" : "OFF"); + this->Internal->SetDefinition(name, value ? "ON" : "OFF"); if (!this->Internal->VarUsageStack.empty() && this->VariableInitialized(name)) { @@ -1790,9 +1885,8 @@ void cmMakefile::CheckForUnusedVariables() const { return; } - const cmDefinitions& defs = this->Internal->VarStack.top(); - const std::set<std::string>& locals = defs.LocalKeys(); - std::set<std::string>::const_iterator it = locals.begin(); + const std::vector<std::string>& locals = this->Internal->LocalKeys(); + std::vector<std::string>::const_iterator it = locals.begin(); for (; it != locals.end(); ++it) { this->CheckForUnused("out of scope", *it); @@ -1865,7 +1959,7 @@ void cmMakefile::CheckForUnused(const char* reason, void cmMakefile::RemoveDefinition(const std::string& name) { - this->Internal->VarStack.top().Set(name, 0); + this->Internal->RemoveDefinition(name); if (!this->Internal->VarUsageStack.empty() && this->VariableInitialized(name)) { @@ -2338,7 +2432,7 @@ const char* cmMakefile::GetRequiredDefinition(const std::string& name) const bool cmMakefile::IsDefinitionSet(const std::string& name) const { - const char* def = this->Internal->VarStack.top().Get(name); + const char* def = this->Internal->GetDefinition(name); this->Internal->VarUsageStack.top().insert(name); if(!def) { @@ -2364,7 +2458,7 @@ const char* cmMakefile::GetDefinition(const std::string& name) const { this->Internal->VarUsageStack.top().insert(name); } - const char* def = this->Internal->VarStack.top().Get(name); + const char* def = this->Internal->GetDefinition(name); if(!def) { def = this->GetState()->GetInitializedCacheValue(name); @@ -2404,9 +2498,7 @@ std::vector<std::string> cmMakefile std::vector<std::string> res; if ( !cacheonly ) { - std::set<std::string> definitions = - this->Internal->VarStack.top().ClosureKeys(); - res.insert(res.end(), definitions.begin(), definitions.end()); + res = this->Internal->ClosureKeys(); } std::vector<std::string> cacheKeys = this->GetState()->GetCacheEntryKeys(); @@ -4297,10 +4389,9 @@ std::string cmMakefile::GetListFileStack() const void cmMakefile::PushScope() { - cmDefinitions* parent = &this->Internal->VarStack.top(); + this->Internal->PushDefinitions(); const std::set<std::string>& init = this->Internal->VarInitStack.top(); const std::set<std::string>& usage = this->Internal->VarUsageStack.top(); - this->Internal->VarStack.push(cmDefinitions(parent)); this->Internal->VarInitStack.push(init); this->Internal->VarUsageStack.push(usage); @@ -4321,13 +4412,12 @@ void cmMakefile::PopScope() this->PopLoopBlockBarrier(); - cmDefinitions* current = &this->Internal->VarStack.top(); std::set<std::string> init = this->Internal->VarInitStack.top(); std::set<std::string> usage = this->Internal->VarUsageStack.top(); - const std::set<std::string>& locals = current->LocalKeys(); + const std::vector<std::string>& locals = this->Internal->LocalKeys(); // Remove initialization and usage information for variables in the local // scope. - std::set<std::string>::const_iterator it = locals.begin(); + std::vector<std::string>::const_iterator it = locals.begin(); for (; it != locals.end(); ++it) { init.erase(*it); @@ -4340,7 +4430,8 @@ void cmMakefile::PopScope() usage.erase(*it); } } - this->Internal->VarStack.pop(); + + this->Internal->PopDefinitions(); this->Internal->VarInitStack.pop(); this->Internal->VarUsageStack.pop(); // Push initialization and usage up to the parent scope. @@ -4355,31 +4446,7 @@ void cmMakefile::RaiseScope(const std::string& var, const char *varDef) return; } - cmDefinitions& cur = this->Internal->VarStack.top(); - if(cmDefinitions* up = cur.GetParent()) - { - // First localize the definition in the current scope. - cur.Get(var); - - // Now update the definition in the parent scope. - up->Set(var, varDef); - } - else if(cmLocalGenerator* plg = this->LocalGenerator->GetParent()) - { - // 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); - } - } - else + if (!this->Internal->RaiseScope(var, varDef, this)) { std::ostringstream m; m << "Cannot set \"" << var << "\": current scope has no parent."; |