From 53b6896e48aaa6ee2b414bd36275263c57b490f8 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 14 Feb 2024 08:39:58 +0200 Subject: Avoid duplicate fsdir{} in inject_fsdir(), match_prerequisite*() call sequences --- libbuild2/algorithm.cxx | 31 +++++++++++++++++++++++++++---- libbuild2/algorithm.hxx | 9 +++++++-- libbuild2/algorithm.ixx | 3 +++ 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 ()) + 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)) { // 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, -- cgit v1.1