aboutsummaryrefslogtreecommitdiff
path: root/build2/scope.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2016-04-19 09:24:38 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2016-04-19 15:25:50 +0200
commitfc18a6dc1fcb02b505f07914e484cebbaf268698 (patch)
tree2cb9b04c5924dfd46e7d934912b41c3efd894a93 /build2/scope.cxx
parentae20570f2ad55b2fa8e71cf450457cb9c4b21b1b (diff)
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.
Diffstat (limited to 'build2/scope.cxx')
-rw-r--r--build2/scope.cxx161
1 files changed, 54 insertions, 107 deletions
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 ();
- }
}