aboutsummaryrefslogtreecommitdiff
path: root/build2/target
diff options
context:
space:
mode:
Diffstat (limited to 'build2/target')
-rw-r--r--build2/target95
1 files changed, 58 insertions, 37 deletions
diff --git a/build2/target b/build2/target
index 241f6ff..9061e2d 100644
--- a/build2/target
+++ b/build2/target
@@ -127,24 +127,24 @@ namespace build2
public:
typedef build2::action action_type;
- virtual
- ~target () = default;
-
- target (const target&) = delete;
- target& operator= (const target&) = delete;
-
- target (dir_path d, string n, const string* e)
- : dir (move (d)), name (move (n)), ext (e) {}
-
- // Reset the target before matching a rule for it. The
- // default implementation clears prerequisite_targets.
+ // For targets that are in the src tree of a project we also keep the
+ // corresponding out directory. As a result we may end up with multiple
+ // targets for the same file if we are building multiple configurations of
+ // the same project at once. We do it this way because, in a sense, a
+ // target's out directory is its "configuration" (in terms of variables).
+ // As an example, consider installing the same README file (src) but for
+ // two different project configurations at once. Which installation
+ // directory should we use? The answer depends on which configuration you
+ // ask.
+ //
+ // Empty out directory indicates this target is in the out tree (including
+ // when src == out). We also treat out of project targets as being in the
+ // out tree.
//
- virtual void
- reset (action_type);
-
const dir_path dir; // Absolute and normalized.
+ const dir_path out; // Empty or absolute and normalized.
const string name;
- const string* ext; // Extension, NULL - unspecified, empty - no extension.
+ const string* ext; // Extension. NULL - unspecified, empty - no extension.
// Target group to which this target belongs, if any. Note that
// we assume that the group and all its members are in the same
@@ -187,6 +187,22 @@ namespace build2
//
target* group = nullptr;
+ public:
+ virtual
+ ~target () = default;
+
+ target (const target&) = delete;
+ target& operator= (const target&) = delete;
+
+ target (dir_path d, dir_path o, string n, const string* e)
+ : dir (move (d)), out (move (o)), name (move (n)), ext (e) {}
+
+ // Reset the target before matching a rule for it. The default
+ // implementation clears prerequisite_targets.
+ //
+ virtual void
+ reset (action_type);
+
// You should not call this function directly; rather use
// resolve_group_members() from <build2/algorithm>.
//
@@ -197,7 +213,7 @@ namespace build2
// to the targets's members will be reflected in the key.
//
target_key
- key () const {return target_key {&type (), &dir, &name, ext};}
+ key () const {return target_key {&type (), &dir, &out, &name, ext};}
// Scoping.
//
@@ -227,13 +243,10 @@ namespace build2
scope&
weak_scope () const {return *root_scope ().weak_scope ();}
-
bool
in (const scope& s) const
{
- return
- (s.out_path_ != nullptr && dir.sub (*s.out_path_)) ||
- (s.src_path_ != nullptr && dir.sub (*s.src_path_));
+ return (out.empty () ? dir : out).sub (s.out_path ());
}
// Prerequisites.
@@ -401,8 +414,9 @@ namespace build2
recipe_type recipe_;
};
- ostream&
- operator<< (ostream&, const target&);
+ inline ostream&
+ operator<< (ostream& os, const target& t) {return os << t.key ();}
+
// A "range" that presents the prerequisites of a group and one of
// its members as one continuous sequence, or, in other words, as
@@ -780,21 +794,23 @@ namespace build2
iterator
find (const target_type& type,
const dir_path& dir,
+ const dir_path& out,
const string& name,
const string* ext,
tracer& trace) const
{
- return find (target_key {&type, &dir, &name, ext}, trace);
+ return find (target_key {&type, &dir, &out, &name, ext}, trace);
}
- // As above but ignore the extension and return the target or
- // nullptr instead of the iterator.
+ // As above but ignore the extension and return the target or nullptr
+ // instead of the iterator.
//
template <typename T>
T*
- find (const dir_path& dir, const string& name) const
+ find (const dir_path& dir, const dir_path& out, const string& name) const
{
- auto i (map_.find (target_key {&T::static_type, &dir, &name, nullptr}));
+ auto i (map_.find (
+ target_key {&T::static_type, &dir, &out, &name, nullptr}));
return i != map_.end () ? static_cast<T*> (i->second.get ()) : nullptr;
}
@@ -804,27 +820,33 @@ namespace build2
pair<target&, bool>
insert (const target_type&,
dir_path dir,
+ dir_path out,
string name,
const string* ext,
tracer&);
+
template <typename T>
T&
insert (const dir_path& dir,
+ const dir_path& out,
const string& name,
const string* ext,
tracer& t)
{
return static_cast<T&> (
- insert (T::static_type, dir, name, ext, t).first);
+ insert (T::static_type, dir, out, name, ext, t).first);
}
template <typename T>
T&
- insert (const dir_path& dir, const string& name, tracer& t)
+ insert (const dir_path& dir,
+ const dir_path& out,
+ const string& name,
+ tracer& t)
{
return static_cast<T&> (
- insert (T::static_type, dir, name, nullptr, t).first);
+ insert (T::static_type, dir, out, name, nullptr, t).first);
}
void
@@ -1072,9 +1094,13 @@ namespace build2
//
template <typename T>
target*
- target_factory (const target_type&, dir_path d, string n, const string* e)
+ target_factory (const target_type&,
+ dir_path d,
+ dir_path o,
+ string n,
+ const string* e)
{
- return new T (move (d), move (n), e);
+ return new T (move (d), move (o), move (n), e);
}
// Return fixed target extension.
@@ -1095,11 +1121,6 @@ namespace build2
const string*
target_extension_null (const target_key&, scope&);
- // Issue diagnostics and fail if called.
- //
- const string*
- target_extension_fail (const target_key&, scope&);
-
// Assert if called.
//
const string*