aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/rule.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-05-01 08:08:46 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-05-27 08:35:29 +0200
commite63b427c51e37135e50dec9435659d661872fe95 (patch)
treedc2cf324dac7b5720bb24cd44da8f437d0ba9b0b /libbuild2/rule.cxx
parent05ae6014aa01a8347844cce89085bdcb591160f0 (diff)
WIP
Diffstat (limited to 'libbuild2/rule.cxx')
-rw-r--r--libbuild2/rule.cxx82
1 files changed, 74 insertions, 8 deletions
diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx
index a57aaaa..bbb854c 100644
--- a/libbuild2/rule.cxx
+++ b/libbuild2/rule.cxx
@@ -308,23 +308,89 @@ namespace build2
// adhoc_rule
//
- bool adhoc_rule::
- match (action a, target& t, const string&) const
+ static inline const adhoc_recipe*
+ find_recipe (action a, target& t)
{
- // @@ Should we be looking for outer/inner and then just inner, like in
- // rule match? See match_rule() for the normal rule semantics.
- //
auto i (find_if (t.adhoc_recipes.begin (),
t.adhoc_recipes.end (),
[a] (const adhoc_recipe& r) {return r.action == a;}));
- return i != t.adhoc_recipes.end ();
+ return i != t.adhoc_recipes.end () ? &*i : nullptr;
+ }
+
+ bool adhoc_rule::
+ match (action a, target& t, const string&) const
+ {
+ // TODO:
+ //
+ // @@ If action is Y-for-X, how would we distinguish between X and
+ // Y-for-X? See match_rule() for the hairy details. We could start with
+ // supporting just the inner case. Or we could try to just match an
+ // inner rule by default? I think need a clear use-case to see what's
+ // the correct semantics.
+
+ if (find_recipe (a, t))
+ return true;
+
+ // If this is clean for a file target and we have a recipe for update,
+ // then we will supply the standard clean.
+ //
+ if (a == perform_clean_id &&
+ t.is_a<file> () &&
+ find_recipe (action (perform_id, update_id), t))
+ return true;
+
+ return false;
}
recipe adhoc_rule::
- apply (action, target&) const
+ apply (action a, target& t) const
{
- return empty_recipe;
+ // Derive file names for the target and its ad hoc group members, if any.
+ //
+ for (target* m (&t); m != nullptr; m = m->adhoc_member)
+ {
+ if (auto* p = m->is_a<path_target> ())
+ p->derive_path ();
+ }
+
+ // Inject dependency on the output directory.
+ //
+ // 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.
+ //
+ inject_fsdir (a, t);
+
+ // Match prerequisites.
+ //
+ match_prerequisite_members (a, t);
+
+ // For update inject dependency on the tool target.
+ //
+ // @@ We could see that it's a target and do it but not sure if we should
+ // bother. We dropped this idea of implicit targets in tests. Maybe we
+ // should verify path assigned, like we do there? I think we will have
+ // to.
+ //
+ // if (a == perform_update_id)
+ // inject (a, t, tgt);
+
+ if (const adhoc_recipe* r = find_recipe (a, t))
+ {
+ // @@ Perhaps we should have different implementations for file-based
+ // targets (depdb, timestamp, etc) and non.
+ //
+ return [r] (action a, const target& t)
+ {
+ // @@ TODO
+ text << t << ' ' << a << ' ' << r;
+ return target_state::unchanged;
+ };
+ }
+
+ // Otherwise this should be the standard clean.
+ //
+ return &perform_clean_depdb;
}
const adhoc_rule adhoc_rule::instance;