aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2023-12-01 11:11:50 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2023-12-03 16:48:07 +0200
commit01226d547c006d29731747c2e8c9df4f9312815e (patch)
treed6ca6269d1c514742d0fa94b77690298c3c0bf9f
parenta738555f02626685f119fe332d4e2e6e9f2581f4 (diff)
Make fsdir{} usable as target of ad hoc Buildscript recipes
In particular, it can now be used to represent a directory symlink. For example: exe{hello}: ... fsdir{assets} fsdir{assets}: % update {{ ln -s $src_base/assets $out_base/assets }} % clean {{ rm $out_base/assets }}
-rw-r--r--libbuild2/adhoc-rule-buildscript.cxx36
-rw-r--r--libbuild2/build/script/runner.cxx8
2 files changed, 41 insertions, 3 deletions
diff --git a/libbuild2/adhoc-rule-buildscript.cxx b/libbuild2/adhoc-rule-buildscript.cxx
index c3e559c..0395ccd 100644
--- a/libbuild2/adhoc-rule-buildscript.cxx
+++ b/libbuild2/adhoc-rule-buildscript.cxx
@@ -2336,9 +2336,34 @@ namespace build2
context& ctx (t.ctx);
- execute_prerequisites (a, t);
+ target_state ts (target_state::unchanged);
- if (!ctx.dry_run || verb != 0)
+ if (ctx.current_mode == execution_mode::first)
+ ts |= straight_execute_prerequisites (a, t);
+
+ bool exec (!ctx.dry_run || verb != 0);
+
+ // Special handling for fsdir{} (which is the recommended if somewhat
+ // hackish way to represent directory symlinks). See fsdir_rule for
+ // background.
+ //
+ // @@ Note that because there is no depdb, we cannot detect the target
+ // directory change (or any other changes in the script).
+ //
+ if (exec &&
+ (a == perform_update_id || a == perform_clean_id) &&
+ t.is_a<fsdir> ())
+ {
+ // For update we only want to skip if it's a directory. For clean we
+ // want to (try) to clean up any filesystem entry, including a dangling
+ // symlink.
+ //
+ exec = a == perform_update_id
+ ? !exists (t.dir, true /* ignore_errors */)
+ : build2::entry_exists (t.dir, false /* follow_symlinks */);
+ }
+
+ if (exec)
{
const scope& bs (t.base_scope ());
const scope& rs (*bs.root_scope ());
@@ -2394,9 +2419,14 @@ namespace build2
p.execute_body (rs, bs, e, script, r, !exec_diag /* enter */);
}
+
+ ts |= target_state::changed;
}
- return target_state::changed;
+ if (ctx.current_mode == execution_mode::last)
+ ts |= reverse_execute_prerequisites (a, t);
+
+ return ts;
}
void adhoc_buildscript_rule::
diff --git a/libbuild2/build/script/runner.cxx b/libbuild2/build/script/runner.cxx
index e08ebbf..5d9764b 100644
--- a/libbuild2/build/script/runner.cxx
+++ b/libbuild2/build/script/runner.cxx
@@ -43,6 +43,14 @@ namespace build2
}
}
}
+ else if (const fsdir* fd = env.target.is_a<fsdir> ())
+ {
+ // Compare ignoring the trailing directory separator.
+ //
+ if (path_traits::compare (i->path.string (),
+ fd->dir.string ()) == 0)
+ m = fd;
+ }
else
{
for (m = &env.target; m != nullptr; m = m->adhoc_member)