aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-01-23 10:53:33 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-01-23 10:53:33 +0200
commit1c7d67d9895c2bdbef13541b154ea17d25b8d515 (patch)
treeac06cf710a0104c51fdb4c4c47db3e245ac2c793
parent91495e646c688eade6b46f21bb40e3da8b8d6f1a (diff)
Go back to storing scope instead of target in prerequisite
Turns out this was semantically the right way to do it.
-rw-r--r--build2/cc/link.cxx8
-rw-r--r--build2/cli/rule.cxx2
-rw-r--r--build2/parser.cxx18
-rw-r--r--build2/prerequisite49
-rw-r--r--build2/prerequisite.cxx28
-rw-r--r--build2/target7
-rw-r--r--build2/target.ixx6
7 files changed, 56 insertions, 62 deletions
diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx
index a8b7dcb..c94eb26 100644
--- a/build2/cc/link.cxx
+++ b/build2/cc/link.cxx
@@ -165,7 +165,7 @@ namespace build2
// If the prerequisite came from the lib{} group, then also
// add it to lib's prerequisite_targets.
//
- if (p.prerequisite.owner != t)
+ if (!p.prerequisite.belongs (t))
t.group->prerequisite_targets.push_back (pt);
t.prerequisite_targets.push_back (pt);
@@ -487,7 +487,7 @@ namespace build2
// @@ Why are we creating the obj{} group if the source came from a
// group?
//
- bool group (p.prerequisite.owner != t); // Group's prerequisite.
+ bool group (!p.prerequisite.belongs (t)); // Group's prerequisite.
const prerequisite_key& cp (p.key ()); // C-source (X or C) key.
const target_type& tt (group ? obj::static_type : ott);
@@ -614,7 +614,7 @@ namespace build2
{
// Note: add the source to the group, not the member.
//
- ot.prerequisites.push_back (p.as_prerequisite_for (ot));
+ ot.prerequisites.push_back (p.as_prerequisite ());
// Add our lib*{} prerequisites to the object file (see the export.*
// machinery for details).
@@ -634,7 +634,7 @@ namespace build2
for (prerequisite& p: group_prerequisites (t))
{
if (p.is_a<lib> () || p.is_a<liba> () || p.is_a<libs> ())
- ot.prerequisites.emplace_back (p, ot);
+ ot.prerequisites.emplace_back (p);
}
build2::match (a, *pt);
diff --git a/build2/cli/rule.cxx b/build2/cli/rule.cxx
index f5405a5..706830c 100644
--- a/build2/cli/rule.cxx
+++ b/build2/cli/rule.cxx
@@ -136,7 +136,7 @@ namespace build2
if (g == nullptr)
g = &targets.insert<cli_cxx> (t.dir, t.out, t.name, trace);
- g->prerequisites.push_back (p.as_prerequisite_for (*g));
+ g->prerequisites.push_back (p.as_prerequisite ());
}
else
l4 ([&]{trace << ".cli file stem '" << p.name () << "' "
diff --git a/build2/parser.cxx b/build2/parser.cxx
index 9d118e8..ec9d9e4 100644
--- a/build2/parser.cxx
+++ b/build2/parser.cxx
@@ -693,14 +693,16 @@ namespace build2
dir_path (),
move (pn.value),
move (e),
- tgs.back ());
+ *scope_);
- // Move last prerequisite (which will normally be the only one).
- //
- for (target& t: tgs)
- t.prerequisites.push_back (&t == &p.owner
- ? move (p)
- : prerequisite (p, t));
+ for (auto i (tgs.begin ()), e (tgs.end ()); i != e; )
+ {
+ // Move last prerequisite (which will normally be the only
+ // one).
+ //
+ target& t (*i);
+ t.prerequisites.push_back (++i == e ? move (p) : p);
+ }
}
}
@@ -3552,7 +3554,7 @@ namespace build2
false, // Enter as real (not implied).
trace).first);
- ct.prerequisites.emplace_back (dt, ct);
+ ct.prerequisites.emplace_back (prerequisite (dt));
}
void parser::
diff --git a/build2/prerequisite b/build2/prerequisite
index f951e0a..abfb2c1 100644
--- a/build2/prerequisite
+++ b/build2/prerequisite
@@ -48,20 +48,28 @@ namespace build2
class prerequisite
{
public:
- typedef build2::target target_type;
- typedef build2::target_type target_type_type;
+ using scope_type = build2::scope;
+ using target_type = build2::target;
+ using target_type_type = build2::target_type;
// Note that unlike targets, for prerequisites an empty out directory
// means undetermined rather than being definitely in the out tree.
//
+ // It might seem natural to keep the reference to the owner target instead
+ // of to the scope. But that's not the semantics that we have, consider:
+ //
+ // foo/obj{x}: bar/cxx{y}
+ //
+ // bar/ here is relative to the scope, not to foo/. Plus, bar/ can resolve
+ // to either src or out.
+ //
const optional<string> proj;
const target_type_type& type;
const dir_path dir; // Normalized absolute or relative (to scope).
const dir_path out; // Empty, normalized absolute, or relative.
const string name;
const optional<string> ext; // Absent if unspecified.
-
- target_type& owner; // Target to which this prerequisite belongs.
+ scope_type& scope;
target_type* target; // NULL if not yet resolved. Note that this
// should always be the "primary target", not
@@ -74,36 +82,39 @@ namespace build2
dir_path o,
string n,
optional<string> e,
- target_type& w)
+ scope_type& s)
: proj (move (p)),
type (t),
dir (move (d)),
out (move (o)),
name (move (n)),
ext (move (e)),
- owner (w),
+ scope (s),
target (nullptr) {}
- // Make a copy for a new owner target. Note that both owner targets should
- // be in the same scope.
- //
- prerequisite (const prerequisite&, target_type& owner);
-
// Make a prerequisite from a target.
//
- prerequisite (target_type&, target_type& owner);
-
- prerequisite (const prerequisite&) = delete;
- prerequisite (prerequisite&&) = default;
-
- prerequisite& operator= (const prerequisite&) = delete;
- prerequisite& operator= (prerequisite&&) = default;
+ explicit
+ prerequisite (target_type&);
// Note that the returned key "tracks" the prerequisite; that is, any
// updates to the prerequisite's members will be reflected in the key.
//
prerequisite_key
- key () const;
+ key () const
+ {
+ return prerequisite_key {proj, {&type, &dir, &out, &name, ext}, &scope};
+ }
+
+ // Return true if this prerequisite instance (physically) belongs to the
+ // target's prerequisite list. Note that this test only works if you use
+ // references to the container elements and the container hasn't been
+ // resized since such a reference was obtained. Normally this function is
+ // used when iterating over a combined prerequisites range to detect if
+ // the prerequisite came from the group (see group_prerequisites).
+ //
+ bool
+ belongs (const target_type&) const;
// Prerequisite (target) type.
//
diff --git a/build2/prerequisite.cxx b/build2/prerequisite.cxx
index 469bdf9..3bffa3d 100644
--- a/build2/prerequisite.cxx
+++ b/build2/prerequisite.cxx
@@ -51,38 +51,22 @@ namespace build2
// prerequisite
//
prerequisite::
- prerequisite (const prerequisite& p, target_type& w)
- : proj (p.proj),
- type (p.type),
- dir (p.dir),
- out (p.out),
- name (p.name),
- ext (p.ext),
- owner (w),
- target (nullptr)
- {
- assert (&w.base_scope () == &p.owner.base_scope ());
- }
-
- // Make a prerequisite from a target.
- //
- prerequisite::
- prerequisite (target_type& t, target_type& w)
+ prerequisite (target_type& t)
: proj (nullopt),
type (t.type ()),
dir (t.dir),
out (t.out), // @@ If it's empty, then we treat as undetermined?
name (t.name),
ext (t.ext),
- owner (w),
+ scope (t.base_scope ()),
target (&t)
{
}
- prerequisite_key prerequisite::
- key () const
+ bool prerequisite::
+ belongs (const target_type& t) const
{
- return prerequisite_key {
- proj, {&type, &dir, &out, &name, ext}, &owner.base_scope ()};
+ const auto& p (t.prerequisites);
+ return !(p.empty () || this < &p.front () || this > &p.back ());
}
}
diff --git a/build2/target b/build2/target
index 3bc9d5c..339ff90 100644
--- a/build2/target
+++ b/build2/target
@@ -763,13 +763,10 @@ namespace build2
return target != nullptr ? *target : build2::search (prerequisite);
}
- // Return as a new prerequisite instance for the specified owner target.
- // Note that if this is a prerequisite, then both owners should be in the
- // same scope (not a requirement if this is a target because then its path
- // will be absolute).
+ // Return as a new prerequisite instance.
//
prerequisite_type
- as_prerequisite_for (target_type& owner) const;
+ as_prerequisite () const;
};
// It is often stored as the target's auxiliary data so make sure there is
diff --git a/build2/target.ixx b/build2/target.ixx
index 9c2c838..e2ac111 100644
--- a/build2/target.ixx
+++ b/build2/target.ixx
@@ -7,17 +7,17 @@ namespace build2
// prerequisite_member
//
inline prerequisite prerequisite_member::
- as_prerequisite_for (target_type& owner) const
+ as_prerequisite () const
{
if (target == nullptr)
- return prerequisite_type (prerequisite, owner);
+ return prerequisite;
// An ad hoc group member cannot be used as a prerequisite (use the whole
// group instead).
//
assert (!target->adhoc_member ());
- return prerequisite_type (*target, owner);
+ return prerequisite_type (*target);
}
// prerequisite_members