aboutsummaryrefslogtreecommitdiff
path: root/build2/target.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/target.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/target.cxx')
-rw-r--r--build2/target.cxx82
1 files changed, 33 insertions, 49 deletions
diff --git a/build2/target.cxx b/build2/target.cxx
index 782a7dd..663d31d 100644
--- a/build2/target.cxx
+++ b/build2/target.cxx
@@ -101,7 +101,10 @@ namespace build2
scope& target::
base_scope () const
{
- return scopes.find (dir);
+ // If this target is from the src tree, use its out directory to find
+ // the scope.
+ //
+ return scopes.find (out.empty () ? dir : out);
}
scope& target::
@@ -109,7 +112,7 @@ namespace build2
{
// This is tricky to cache so we do the lookup for now.
//
- scope* r (scopes.find (dir).root_scope ());
+ scope* r (base_scope ().root_scope ());
assert (r != nullptr);
return *r;
}
@@ -170,12 +173,6 @@ namespace build2
return r;
}
- ostream&
- operator<< (ostream& os, const target& t)
- {
- return os << target_key {&t.type (), &t.dir, &t.name, t.ext};
- }
-
// target_set
//
target_set targets;
@@ -216,18 +213,20 @@ namespace build2
pair<target&, bool> target_set::
insert (const target_type& tt,
dir_path dir,
+ dir_path out,
string name,
const string* ext,
tracer& trace)
{
- iterator i (find (target_key {&tt, &dir, &name, ext}, trace));
+ iterator i (find (target_key {&tt, &dir, &out, &name, ext}, trace));
bool r (i == end ());
if (r)
{
- unique_ptr<target> pt (tt.factory (tt, move (dir), move (name), ext));
+ unique_ptr<target> pt (
+ tt.factory (tt, move (dir), move (out), move (name), ext));
i = map_.emplace (
- make_pair (target_key {&tt, &pt->dir, &pt->name, pt->ext},
+ make_pair (target_key {&tt, &pt->dir, &pt->out, &pt->name, pt->ext},
move (pt))).first;
}
@@ -280,6 +279,11 @@ namespace build2
os << '}';
+ // If this target is from src, print its out.
+ //
+ if (!k.out->empty ())
+ os << '@' << diag_relative (*k.out, false); // Don't print './'.
+
return os;
}
@@ -382,17 +386,9 @@ namespace build2
if (target* t = search_existing_target (pk))
return t;
- // Then look for an existing file in this target-type-specific
- // list of paths (@@ TODO: comes from the variable).
+ // Then look for an existing file in the src tree.
//
- if (pk.tk.dir->relative ())
- {
- dir_paths sp;
- sp.push_back (pk.scope->src_path ()); // src_base
- return search_existing_file (pk, sp);
- }
- else
- return nullptr;
+ return pk.tk.dir->relative () ? search_existing_file (pk) : nullptr;
}
static target*
@@ -416,27 +412,6 @@ namespace build2
}
const string*
- target_extension_fail (const target_key& tk, scope& s)
- {
- {
- diag_record dr;
- dr << error << "no default extension to derive file name for ";
-
- // This is a bit hacky: we may be dealing with a target (see
- // file::derive_path()) or prerequisite (see search_existing_file()). So
- // we are going to check if dir is absolute. If it is, then we assume
- // this is a target, otherwise -- prerequisite.
- //
- if (tk.dir->absolute ())
- dr << "target " << tk;
- else
- dr << "prerequisite " << prerequisite_key {nullptr, tk, &s};
- }
-
- throw failed ();
- }
-
- const string*
target_extension_assert (const target_key&, scope&)
{
assert (false); // Attempt to obtain the default extension.
@@ -495,13 +470,18 @@ namespace build2
template <typename T>
static target*
- file_factory (const target_type&, dir_path d, string n, const string* e)
- {
- // The file target type doesn't imply any extension. So if one
- // wasn't specified, set it to empty rather than unspecified.
- // In other words, we always treat file{foo} as file{foo.}.
+ file_factory (const target_type&,
+ dir_path d,
+ dir_path o,
+ string n,
+ const string* e)
+ {
+ // The file target type doesn't imply any extension. So if one wasn't
+ // specified, set it to empty rather than unspecified. In other words, we
+ // always treat file{foo} as file{foo.}.
//
return new T (move (d),
+ move (o),
move (n),
(e != nullptr ? e : &extension_pool.find ("")));
}
@@ -585,12 +565,16 @@ namespace build2
};
static target*
- man_factory (const target_type&, dir_path d, string n, const string* e)
+ man_factory (const target_type&,
+ dir_path d,
+ dir_path o,
+ string n,
+ const string* e)
{
if (e == nullptr)
fail << "man target '" << n << "' must include extension (man section)";
- return new man (move (d), move (n), e);
+ return new man (move (d), move (o), move (n), e);
}
const target_type man::static_type