From d0d4486702b045852dca36008746afeb8754ae85 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 1 Nov 2023 11:50:08 +0200 Subject: Tighten/optimize cleaning of fsdir{} during match --- libbuild2/rule.cxx | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'libbuild2/rule.cxx') diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx index 79ccb86..9f90919 100644 --- a/libbuild2/rule.cxx +++ b/libbuild2/rule.cxx @@ -354,6 +354,8 @@ namespace build2 void fsdir_rule:: perform_update_direct (action a, const fsdir& t) { + assert (t.ctx.phase == run_phase::match); + // First create the parent directory. If present, it is always first. // if (const target* p = (t.prerequisite_targets[a].empty () @@ -397,18 +399,29 @@ namespace build2 void fsdir_rule:: perform_clean_direct (action a, const fsdir& t) { + assert (t.ctx.phase == run_phase::match); + // 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. + // Except that if there are other dependens of this fsdir{} then this will + // likely be a noop (because the directory won't be empty) and it makes + // sense to just defer cleaning to such other dependents. See + // clean_during_match() for backgound. This is similar logic as in + // unmatch::safe. // - if (const target* p = (t.prerequisite_targets[a].empty () - ? nullptr - : t.prerequisite_targets[a][0])) + if (t[a].dependents.load (memory_order_relaxed) == 0) { - if (const fsdir* fp = p->is_a ()) - perform_clean_direct (a, *fp); + rmdir (t.dir, t, t.ctx.current_diag_noise ? 1 : 2); + + // Then clean the parent directory. If present, it is always first. + // + if (const target* p = (t.prerequisite_targets[a].empty () + ? nullptr + : t.prerequisite_targets[a][0])) + { + if (const fsdir* fp = p->is_a ()) + perform_clean_direct (a, *fp); + } } } -- cgit v1.1