aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/algorithm.cxx25
-rw-r--r--libbuild2/algorithm.hxx12
-rw-r--r--libbuild2/rule.cxx19
-rw-r--r--libbuild2/rule.hxx3
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<fsdir> ())
+ 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;
};