aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/adhoc-rule-regex-pattern.cxx12
-rw-r--r--libbuild2/algorithm.cxx43
-rw-r--r--libbuild2/algorithm.hxx26
3 files changed, 73 insertions, 8 deletions
diff --git a/libbuild2/adhoc-rule-regex-pattern.cxx b/libbuild2/adhoc-rule-regex-pattern.cxx
index cd8c241..9101000 100644
--- a/libbuild2/adhoc-rule-regex-pattern.cxx
+++ b/libbuild2/adhoc-rule-regex-pattern.cxx
@@ -366,7 +366,9 @@ namespace build2
// @@ TODO: save location in constructor?
//
- optional<string> ext (target::split_name (n, location ()));
+ location loc;
+
+ optional<string> ext (target::split_name (n, loc));
if (g != nullptr)
{
@@ -425,16 +427,14 @@ namespace build2
}
else
{
- // @@ TODO: currently this uses type as the ad hoc member identity.
- // Use inject_adhoc_group_member() variant?
- //
- add_adhoc_member (
+ add_adhoc_member_identity (
t,
e.type,
move (d),
dir_path (), // Always in out.
move (n),
- move (ext));
+ move (ext),
+ loc);
}
}
}
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index df8e650..2abf391 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -400,6 +400,49 @@ namespace build2
return *m;
};
+ pair<target&, bool>
+ add_adhoc_member_identity (target& t,
+ const target_type& tt,
+ dir_path dir,
+ dir_path out,
+ string n,
+ optional<string> ext,
+ const location& loc)
+ {
+ // NOTE: see similar code in parser::enter_adhoc_members().
+
+ tracer trace ("add_adhoc_member_identity");
+
+ pair<target&, ulock> r (
+ t.ctx.targets.insert_locked (tt,
+ move (dir),
+ move (out),
+ move (n),
+ move (ext),
+ target_decl::implied,
+ trace,
+ true /* skip_find */));
+ target& m (r.first);
+
+ // Add as an ad hoc member at the end of the chain skipping duplicates.
+ //
+ const_ptr<target>* mp (&t.adhoc_member);
+ for (; *mp != nullptr; mp = &(*mp)->adhoc_member)
+ {
+ if (*mp == &m)
+ return {m, false};
+ }
+
+ if (!r.second)
+ fail (loc) << "target " << m << " already exists and cannot be made "
+ << "ad hoc member of group " << t;
+
+ m.group = &t;
+ *mp = &m;
+
+ return {m, true};
+ }
+
static bool
trace_target (const target& t, const vector<name>& ns)
{
diff --git a/libbuild2/algorithm.hxx b/libbuild2/algorithm.hxx
index 2c57b74..dd5d367 100644
--- a/libbuild2/algorithm.hxx
+++ b/libbuild2/algorithm.hxx
@@ -274,11 +274,15 @@ namespace build2
//
// Note that here and in find_adhoc_member() below (as well as in
// perform_clean_extra()) we use target type (as opposed to, say, type and
- // name) as the member's identity. This fits our current needs where every
+ // name) as the member's identity. This fits common needs where every
// (rule-managed) ad hoc member has a unique target type and we have no need
// for multiple members of the same type. This also allows us to support
// things like changing the ad hoc member name by declaring it in a
- // buildfile.
+ // buildfile. However, if this semantics is not appropriate, use the
+ // add_adhoc_member_identity() version below.
+ //
+ // Note that the current implementation asserts if the member target already
+ // exists but is not already a member.
//
LIBBUILD2_SYMEXPORT target&
add_adhoc_member (target&,
@@ -309,6 +313,24 @@ namespace build2
return add_adhoc_member<T> (g, T::static_type, e);
}
+ // Add an ad hoc member using the member identity (as opposed to only its
+ // type as in add_adhoc_member() above) to suppress diplicates. See also
+ // dyndep::inject_adhoc_group_member().
+ //
+ // Return the member target as well as an indication of whether it was added
+ // or was already a member. Fail if the member target already exists but is
+ // not a member since it's not possible to make it a member in an MT-safe
+ // manner.
+ //
+ LIBBUILD2_SYMEXPORT pair<target&, bool>
+ add_adhoc_member_identity (target&,
+ const target_type&,
+ dir_path dir,
+ dir_path out,
+ string name,
+ optional<string> ext,
+ const location& = location ());
+
// Find an ad hoc member of the specified target type returning NULL if not
// found.
//