diff options
-rw-r--r-- | libbuild2/adhoc-rule-buildscript.cxx | 36 | ||||
-rw-r--r-- | libbuild2/build/script/runner.cxx | 8 |
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) |