From fc18a6dc1fcb02b505f07914e484cebbaf268698 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 19 Apr 2016 09:24:38 +0200 Subject: Redesign src/out scoping We no longer enter paths from the src tree into scope map. Instead, targets from the src tree now include their out tree directory (in essence their "configuration"). This is then used to find a target's scope. See the comment in class target for details. The result of this change is that we can now again build multiple configurations (out trees) for same project at once. --- build2/scope.cxx | 161 +++++++++++++++++++------------------------------------ 1 file changed, 54 insertions(+), 107 deletions(-) (limited to 'build2/scope.cxx') diff --git a/build2/scope.cxx b/build2/scope.cxx index 1459687..70442f6 100644 --- a/build2/scope.cxx +++ b/build2/scope.cxx @@ -523,105 +523,70 @@ namespace build2 scope* global_scope; auto scope_map:: - insert (const dir_path& k, scope* ns, bool parent, bool root) -> iterator + insert (const dir_path& k, bool root) -> iterator { - auto er (map_.emplace (k, nullptr)); - scope*& ps (er.first->second); + scope_map_base& m (*this); + auto er (m.emplace (k, scope ())); + scope& s (er.first->second); + + // If this is a new scope, update the parent chain. + // if (er.second) - ps = ns == nullptr ? new scope : ns; - else if (ns != nullptr && ps != ns) { - assert (ps->out_path_ == nullptr || ps->src_path_ == nullptr); - - if (!ps->empty ()) - fail << "attempt to replace non-empty scope " << k; + scope* p (nullptr); - // Un-parent ourselves. We will becomes a new parent below, - // if requested by the caller. + // Update scopes of which we are a new parent/root (unless this is the + // global scope). Also find our parent while at it. // - auto r (map_.find_prefix (k)); // The first entry is ourselves. - for (++r.first; r.first != r.second; ++r.first) - { - scope& c (*r.first->second); - - if (c.parent_ == ps) // No intermediate parent. - c.parent_ = ps->parent_; - } - - delete ps; - ps = ns; - er.second = true; - } - - scope& s (*ps); - - if (parent) - { - if (er.second) + if (m.size () > 1) { - scope* p (nullptr); - - // Update scopes of which we are a new parent/root (unless this - // is the global scope). Also find our parent while at it. + // The first entry is ourselves. // - if (map_.size () > 1) + auto r (m.find_prefix (k)); + for (++r.first; r.first != r.second; ++r.first) { - // The first entry is ourselves. - // - auto r (map_.find_prefix (k)); - for (++r.first; r.first != r.second; ++r.first) - { - scope& c (*r.first->second); - - // The child-parent relationship is based on the out hierarchy, - // thus the extra check. - // - if (c.out_path_ != nullptr && !c.out_path_->sub (k)) - continue; - - // The first scope of which we are a parent is the least - // (shortest) one which means there is no other scope - // between it and our parent. - // - if (p == nullptr) - p = c.parent_; - - if (root && c.root_ == p->root_) // No intermediate root. - c.root_ = &s; - - if (p == c.parent_) // No intermediate parent. - c.parent_ = &s; - } + scope& c (r.first->second); - // We couldn't get the parent from one of its old children - // so we have to find it ourselves. + // The first scope of which we are a parent is the least (shortest) + // one which means there is no other scope between it and our + // parent. // if (p == nullptr) - p = &find (k.directory ()); + p = c.parent_; + + if (root && c.root_ == p->root_) // No intermediate root. + c.root_ = &s; + + if (p == c.parent_) // No intermediate parent. + c.parent_ = &s; } - s.parent_ = p; - s.root_ = root ? &s : (p != nullptr ? p->root_ : nullptr); - } - else if (root && !s.root ()) - { - // Upgrade to root scope. + // We couldn't get the parent from one of its old children so we have + // to find it ourselves. // - auto r (map_.find_prefix (k)); - for (++r.first; r.first != r.second; ++r.first) - { - scope& c (*r.first->second); + if (p == nullptr) + p = &find (k.directory ()); + } - if (c.root_ == s.root_) // No intermediate root. - c.root_ = &s; - } + s.parent_ = p; + s.root_ = root ? &s : (p != nullptr ? p->root_ : nullptr); + } + else if (root && !s.root ()) + { + // Upgrade to root scope. + // + auto r (m.find_prefix (k)); + for (++r.first; r.first != r.second; ++r.first) + { + scope& c (r.first->second); - s.root_ = &s; + if (c.root_ == s.root_) // No intermediate root. + c.root_ = &s; } + + s.root_ = &s; } - else - assert (s.parent_ != nullptr); return er.first; } @@ -629,44 +594,26 @@ namespace build2 // Find the most qualified scope that encompasses this path. // scope& scope_map:: - find (const dir_path& k) const + find (const dir_path& k) { - // Normally we would have a scope for the full path so try - // that before making any copies. + scope_map_base& m (*this); + + // Normally we would have a scope for the full path so try that before + // making any copies. // - auto i (map_.find (k)), e (map_.end ()); + auto i (m.find (k)), e (m.end ()); if (i != e) - return *i->second; + return i->second; for (dir_path d (k.directory ());; d = d.directory ()) { - auto i (map_.find (d)); + auto i (m.find (d)); if (i != e) - return *i->second; + return i->second; assert (!d.empty ()); // We should have the global scope. } } - - void scope_map:: - clear () - { - for (auto& p: map_) - { - scope* s (p.second); - - if (s->out_path_ == &p.first) - s->out_path_ = nullptr; - - if (s->src_path_ == &p.first) - s->src_path_ = nullptr; - - if (s->out_path_ == nullptr && s->src_path_ == nullptr) - delete s; - } - - map_.clear (); - } } -- cgit v1.1