From d3b4636ca3f4c3ad98c8096326c5b1460d05691d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 26 Oct 2023 12:33:34 +0200 Subject: Add inject_fsdir_direct(), fsdir_rule::perform_clean_direct() functions --- libbuild2/algorithm.cxx | 25 ++++++++++++++++++++++++- libbuild2/algorithm.hxx | 12 +++++++++--- libbuild2/rule.cxx | 19 +++++++++++++++++++ libbuild2/rule.hxx | 3 +++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx index bd64cb1..01d5016 100644 --- a/libbuild2/algorithm.cxx +++ b/libbuild2/algorithm.cxx @@ -1593,7 +1593,7 @@ namespace build2 } const fsdir* - inject_fsdir (action a, target& t, bool prereq, bool parent) + inject_fsdir_impl (target& t, bool prereq, bool parent) { tracer trace ("inject_fsdir"); @@ -1614,6 +1614,7 @@ namespace build2 // subprojects (e.g., tests/). // const fsdir* r (nullptr); + if (rs != nullptr && !d.sub (rs->src_path ())) { l6 ([&]{trace << d << " for " << t;}); @@ -1641,6 +1642,14 @@ namespace build2 } } + return r; + } + + const fsdir* + inject_fsdir (action a, target& t, bool prereq, bool parent) + { + const fsdir* r (inject_fsdir_impl (t, prereq, parent)); + if (r != nullptr) { // Make it ad hoc so that it doesn't end up in prerequisite_targets @@ -1653,6 +1662,20 @@ namespace build2 return r; } + const fsdir* + inject_fsdir_direct (action a, target& t, bool prereq, bool parent) + { + 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); + } + + return r; + } + // Execute the specified recipe (if any) and the scope operation callbacks // (if any/applicable) then merge and return the resulting target state. // diff --git a/libbuild2/algorithm.hxx b/libbuild2/algorithm.hxx index 5ebbee2..983e7f5 100644 --- a/libbuild2/algorithm.hxx +++ b/libbuild2/algorithm.hxx @@ -565,9 +565,9 @@ namespace build2 // Inject dependency on the target's directory fsdir{}, unless it is in the // src tree or is outside of any project (say, for example, an installation // directory). If the parent argument is true, then inject the parent - // directory of a target that is itself a directory (name is empty). Return - // the injected target or NULL. Normally this function is called from the - // rule's apply() function. + // directory of a target that is itself a directory (name is empty). Match + // and return the injected target or NULL. Normally this function is called + // from the rule's apply() function. // // As an extension, unless prereq is false, this function will also search // for an existing fsdir{} prerequisite for the directory and if one exists, @@ -577,6 +577,12 @@ namespace build2 LIBBUILD2_SYMEXPORT const fsdir* inject_fsdir (action, target&, bool prereq = true, bool parent = true); + // As above, but match the injected fsdir{} target directly (that is, + // without incrementing the dependency counts). + // + LIBBUILD2_SYMEXPORT const fsdir* + inject_fsdir_direct (action, target&, bool prereq = true, bool parent = true); + // Execute the action on target, assuming a rule has been matched and the // recipe for this action has been set. This is the synchrounous executor // implementation that waits for completion if the target is already being diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx index 0d6ec8c..13dd467 100644 --- a/libbuild2/rule.cxx +++ b/libbuild2/rule.cxx @@ -366,6 +366,8 @@ namespace build2 // Don't fail if we couldn't remove the directory because it is not empty // (or is current working directory). In this case rmdir() will issue a // warning when appropriate. + + // The same code as in perform_clean_direct() below. // target_state ts (rmdir (t.dir, t, t.ctx.current_diag_noise ? 1 : 2) ? target_state::changed @@ -377,6 +379,23 @@ namespace build2 return ts; } + void fsdir_rule:: + perform_clean_direct (action a, const target& t) + { + // The same code as in perform_clean() above. + // + rmdir (t.dir, t, t.ctx.current_diag_noise ? 1 : 2); + + // Then clean the parent directory. If present, it is always first. + // + const target* p (t.prerequisite_targets[a].empty () + ? nullptr + : t.prerequisite_targets[a][0]); + + if (p != nullptr && p->is_a ()) + perform_clean_direct (a, *p); + } + const fsdir_rule fsdir_rule::instance; // noop_rule diff --git a/libbuild2/rule.hxx b/libbuild2/rule.hxx index bf6f0a5..dea9c9a 100644 --- a/libbuild2/rule.hxx +++ b/libbuild2/rule.hxx @@ -178,6 +178,9 @@ namespace build2 static void perform_update_direct (action, const target&); + static void + perform_clean_direct (action, const target&); + fsdir_rule () {} static const fsdir_rule instance; }; -- cgit v1.1