diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2022-06-21 10:04:07 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2022-06-21 10:04:07 +0200 |
commit | bbe8cbd13c40a1309e0d7724319c5487a5df0879 (patch) | |
tree | bdd1e00d9605ec7d5d3d99f44f7eafaf7249a64c /libbuild2/algorithm.cxx | |
parent | 2f29c7fbe758ffb53e4de9983df8b1cc927dad05 (diff) |
Add --trace-{match,execute} options
These options can be used to understand which dependency chain causes matching
or execution of a particular target.
Diffstat (limited to 'libbuild2/algorithm.cxx')
-rw-r--r-- | libbuild2/algorithm.cxx | 96 |
1 files changed, 95 insertions, 1 deletions
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx index 355e633..564105c 100644 --- a/libbuild2/algorithm.cxx +++ b/libbuild2/algorithm.cxx @@ -357,6 +357,70 @@ namespace build2 return *m; }; + static bool + trace_target (const target& t, const vector<name>& ns) + { + for (const name& n: ns) + { + if (n.untyped () || n.qualified () || n.pattern) + fail << "unsupported trace target name '" << n << "'" << + info << "unqualified, typed, non-pattern name expected"; + + if (!n.dir.empty ()) + { + if (n.dir.relative () || !n.dir.normalized ()) + fail << "absolute and normalized trace target directory expected"; + + if (t.dir != n.dir) + continue; + } + + if (n.type == t.type ().name && n.value == t.name) + return true; + } + + return false; + } + + void + set_rule_trace (target_lock& l, const rule_match* rm) + { + action a (l.action); + target& t (*l.target); + + // Note: see similar code in execute_impl() for execute. + // + if (trace_target (t, *t.ctx.trace_match)) + { + diag_record dr (info); + + dr << "matching to " << diag_do (a, t); + + if (rm != nullptr) + { + const rule& r (rm->second); + + if (const adhoc_rule* ar = dynamic_cast<const adhoc_rule*> (&r)) + { + dr << info (ar->loc); + + if (ar->pattern != nullptr) + dr << "using ad hoc pattern rule "; + else + dr << "using ad hoc recipe "; + } + else + dr << info << "using rule "; + + dr << rm->first; + } + else + dr << info << "using directly-assigned recipe"; + } + + t[a].rule = rm; + } + // Return the matching rule or NULL if no match and try_match is true. // const rule_match* @@ -837,7 +901,7 @@ namespace build2 return make_pair (false, target_state::unknown); } - s.rule = r; + set_rule (l, r); l.offset = target::offset_matched; if (step) @@ -1899,6 +1963,36 @@ namespace build2 backlink_clean_pre (a, t, *blm); } + // Note: see similar code in set_rule_trace() for match. + // + if (ctx.trace_execute != nullptr && trace_target (t, *ctx.trace_execute)) + { + diag_record dr (info); + + dr << diag_doing (a, t); + + if (s.rule != nullptr) + { + const rule& r (s.rule->second); + + if (const adhoc_rule* ar = dynamic_cast<const adhoc_rule*> (&r)) + { + dr << info (ar->loc); + + if (ar->pattern != nullptr) + dr << "using ad hoc pattern rule "; + else + dr << "using ad hoc recipe "; + } + else + dr << info << "using rule "; + + dr << s.rule->first; + } + else + dr << info << "using directly-assigned recipe"; + } + ts = execute_recipe (a, t, s.recipe); if (blm) |