aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-09-07 10:56:46 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-09-07 10:56:46 +0200
commitb6dfd0e94aad546069eee7749a0b78eda45f6a78 (patch)
tree1dcc5b7498077323c821daccd911af4d71df5e45
parent7595381c1a6aa75eedae3c982d923ba4154c8e32 (diff)
Fix fsdir{} handling corner cases in ad hoc buildscript recipes/rulesdist-remap
-rw-r--r--libbuild2/adhoc-rule-buildscript.cxx34
-rw-r--r--libbuild2/algorithm.cxx4
-rw-r--r--libbuild2/algorithm.hxx10
-rw-r--r--libbuild2/rule.cxx2
4 files changed, 39 insertions, 11 deletions
diff --git a/libbuild2/adhoc-rule-buildscript.cxx b/libbuild2/adhoc-rule-buildscript.cxx
index 9a38a31..c5eaa60 100644
--- a/libbuild2/adhoc-rule-buildscript.cxx
+++ b/libbuild2/adhoc-rule-buildscript.cxx
@@ -325,7 +325,11 @@ namespace build2
// We do it always instead of only if one of the targets is path-based in
// case the recipe creates temporary files or some such.
//
- const fsdir* dir (inject_fsdir (a, xt));
+ // Note that we disable the prerequisite search for fsdir{} because of the
+ // prerequisites injected by the pattern. So we have to handle this ad hoc
+ // below.
+ //
+ const fsdir* dir (inject_fsdir (a, xt, false /* prereq */));
// Match prerequisites.
//
@@ -382,6 +386,9 @@ namespace build2
const target& pt (p.search (xt));
+ if (&pt == dir) // Don't add injected fsdir{} twice.
+ continue;
+
if (clean && !pt.in (*bs.root_scope ()))
continue;
@@ -405,7 +412,7 @@ namespace build2
for (const prerequisite_target& pt: pts)
{
- if (pt.target == dir)
+ if (pt.target == dir) // Don't match injected fsdir{} twice.
continue;
match_async (a, *pt.target, ctx.count_busy (), xt[a].task_count);
@@ -417,7 +424,7 @@ namespace build2
//
for (prerequisite_target& pt: pts)
{
- if (pt.target == dir)
+ if (pt.target == dir) // See above.
continue;
// Handle update=unmatch.
@@ -525,6 +532,27 @@ namespace build2
file& t (xt.as<file> ());
const path& tp (t.path ());
+ // Re-acquire fsdir{} specified by the user, similar to inject_fsdir()
+ // (which we have disabled; see above).
+ //
+ if (dir == nullptr)
+ {
+ for (const target* pt: pts)
+ {
+ if (pt != nullptr)
+ {
+ if (const fsdir* dt = pt->is_a<fsdir> ())
+ {
+ if (dt->dir == t.dir)
+ {
+ dir = dt;
+ break;
+ }
+ }
+ }
+ }
+ }
+
if (dir != nullptr)
fsdir_rule::perform_update_direct (a, t);
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index e2873fb..fcff50e 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -1291,7 +1291,7 @@ namespace build2
}
const fsdir*
- inject_fsdir (action a, target& t, bool parent)
+ inject_fsdir (action a, target& t, bool prereq, bool parent)
{
tracer trace ("inject_fsdir");
@@ -1320,7 +1320,7 @@ namespace build2
//
r = &search<fsdir> (t, d, dir_path (), string (), nullptr, nullptr);
}
- else
+ else if (prereq)
{
// See if one was mentioned explicitly.
//
diff --git a/libbuild2/algorithm.hxx b/libbuild2/algorithm.hxx
index 0f981a9..b7f6809 100644
--- a/libbuild2/algorithm.hxx
+++ b/libbuild2/algorithm.hxx
@@ -546,13 +546,13 @@ namespace build2
// the injected target or NULL. Normally this function is called from the
// rule's apply() function.
//
- // As an extension, 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.
+ // 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.
//
LIBBUILD2_SYMEXPORT const fsdir*
- inject_fsdir (action, target&, bool parent = true);
+ inject_fsdir (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
diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx
index 6ede2dd..210f1ef 100644
--- a/libbuild2/rule.cxx
+++ b/libbuild2/rule.cxx
@@ -195,7 +195,7 @@ namespace build2
// Inject dependency on our directory (note: not parent) so that it is
// automatically created on update and removed on clean.
//
- inject_fsdir (a, t, false);
+ inject_fsdir (a, t, true, false);
match_prerequisites (a, t);
return default_recipe;