aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/algorithm.cxx31
-rw-r--r--libbuild2/algorithm.hxx9
-rw-r--r--libbuild2/algorithm.ixx3
3 files changed, 37 insertions, 6 deletions
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index 87217f7..26fad23 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -1723,12 +1723,25 @@ namespace build2
{
auto& pts (t.prerequisite_targets[a]);
+ size_t i (pts.size ()); // Index of the first to be added.
+
+ // Avoid duplicating fsdir{} that may have already been injected by
+ // inject_fsdir() (in which case it is expected to be first).
+ //
+ const target* dir (nullptr);
+ if (i != 0)
+ {
+ const prerequisite_target& pt (pts.front ());
+
+ if (pt.target != nullptr && pt.adhoc () && pt.target->is_a<fsdir> ())
+ dir = pt.target;
+ }
+
// Start asynchronous matching of prerequisites. Wait with unlocked phase
// to allow phase switching.
//
wait_guard wg (t.ctx, t.ctx.count_busy (), t[a].task_count, true);
- size_t i (pts.size ()); // Index of the first to be added.
for (auto&& p: forward<R> (r))
{
// Ignore excluded.
@@ -1742,7 +1755,9 @@ namespace build2
? ms (a, t, p, pi)
: prerequisite_target (&search (t, p), pi));
- if (pt.target == nullptr || (s != nullptr && !pt.target->in (*s)))
+ if (pt.target == nullptr ||
+ pt.target == dir ||
+ (s != nullptr && !pt.target->in (*s)))
continue;
match_async (a, *pt.target, t.ctx.count_busy (), t[a].task_count);
@@ -1905,6 +1920,10 @@ namespace build2
const fsdir*
inject_fsdir (action a, target& t, bool match, bool prereq, bool parent)
{
+ auto& pts (t.prerequisite_targets[a]);
+
+ assert (!prereq || pts.empty ()); // This prerequisite target must be first.
+
const fsdir* r (inject_fsdir_impl (t, prereq, parent));
if (r != nullptr)
@@ -1915,7 +1934,7 @@ namespace build2
// Make it ad hoc so that it doesn't end up in prerequisite_targets
// after execution.
//
- t.prerequisite_targets[a].emplace_back (r, include_type::adhoc);
+ pts.emplace_back (r, include_type::adhoc);
}
return r;
@@ -1924,12 +1943,16 @@ namespace build2
const fsdir*
inject_fsdir_direct (action a, target& t, bool prereq, bool parent)
{
+ auto& pts (t.prerequisite_targets[a]);
+
+ assert (!prereq || pts.empty ()); // This prerequisite target must be first.
+
const fsdir* r (inject_fsdir_impl (t, prereq, parent));
if (r != nullptr)
{
match_direct_sync (a, *r);
- t.prerequisite_targets[a].emplace_back (r, include_type::adhoc);
+ pts.emplace_back (r, include_type::adhoc);
}
return r;
diff --git a/libbuild2/algorithm.hxx b/libbuild2/algorithm.hxx
index 64660a9..1c5b717 100644
--- a/libbuild2/algorithm.hxx
+++ b/libbuild2/algorithm.hxx
@@ -659,8 +659,13 @@ namespace build2
//
// As an extension, unless prereq is false, this function will also search
// for an existing fsdir{} prerequisite for the directory and if one exists,
- // return that (even if the target is in src tree). This can be used, for
- // example, to place output into an otherwise non-existent directory.
+ // return that (even if the target is in the src tree). In this case, the
+ // injected fsdir{} (if any) must be the first prerequisite in this target's
+ // prerequisite_targets, which is relied upon by the match_prerequisite*()
+ // family of functons to suppress the duplicate addition.
+ //
+ // Note that the explicit fsdir{} prerquiste is used to place output into an
+ // otherwise non-existent (in src) directory.
//
LIBBUILD2_SYMEXPORT const fsdir*
inject_fsdir (action, target&,
diff --git a/libbuild2/algorithm.ixx b/libbuild2/algorithm.ixx
index 2fbec3f..de175eb 100644
--- a/libbuild2/algorithm.ixx
+++ b/libbuild2/algorithm.ixx
@@ -776,6 +776,9 @@ namespace build2
// groups since the group target should clean eveything up. A bit of an
// optimization.
//
+ // @@ TMP: I wonder if this still holds for the new group semantics
+ // we have in Qt automoc?
+ //
match_search ms (
msm
? [&msm] (action a,