aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbuild2/algorithm.cxx100
-rw-r--r--libbuild2/parser.cxx13
2 files changed, 84 insertions, 29 deletions
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index 581da2e..670355c 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -466,39 +466,85 @@ namespace build2
? a
: action (a.meta_operation (), a.outer_operation ()));
- auto b (t.adhoc_recipes.begin ()), e (t.adhoc_recipes.end ());
- auto i (find_if (
- b, e,
- [&match, ca] (const shared_ptr<adhoc_rule>& r)
- {
- auto& as (r->actions);
- return (find (as.begin (), as.end (), ca) != as.end () &&
- match (*r, false));
- }));
-
- if (i == e)
+ // If returned rule_match is NULL, then the second half indicates whether
+ // the rule was found (but did not match).
+ //
+ auto find_match = [&t, &match] (action ca) -> pair<const rule_match*, bool>
{
- // See if we have a fallback implementation.
- //
- // See the adhoc_rule::reverse_fallback() documentation for details on
- // what's going on here.
+ // Note that there can be at most one recipe for any action.
//
- i = find_if (
- b, e,
- [&match, ca, &t] (const shared_ptr<adhoc_rule>& r)
+ auto b (t.adhoc_recipes.begin ()), e (t.adhoc_recipes.end ());
+ auto i (find_if (
+ b, e,
+ [ca] (const shared_ptr<adhoc_rule>& r)
+ {
+ auto& as (r->actions);
+ return find (as.begin (), as.end (), ca) != as.end ();
+ }));
+
+ bool f (i != e);
+ if (f)
+ {
+ if (!match (**i, false /* fallback */))
+ i = e;
+ }
+ else
+ {
+ // See if we have a fallback implementation.
+ //
+ // See the adhoc_rule::reverse_fallback() documentation for details on
+ // what's going on here.
+ //
+ // Note that it feels natural not to look for a fallback if a custom
+ // recipe was provided but did not match.
+ //
+ const target_type& tt (t.type ());
+ i = find_if (
+ b, e,
+ [ca, &tt] (const shared_ptr<adhoc_rule>& r)
+ {
+ // Only the rule that provides the "forward" action can provide
+ // "reverse", so there can be at most one such rule.
+ //
+ return r->reverse_fallback (ca, tt);
+ });
+
+ f = (i != e);
+ if (f)
{
- auto& as (r->actions);
+ if (!match (**i, true /* fallback */))
+ i = e;
+ }
+ }
- // Note that the rule could be there but not match (see above),
- // thus this extra check.
- //
- return (find (as.begin (), as.end (), ca) == as.end () &&
- r->reverse_fallback (ca, t.type ()) &&
- match (*r, true));
- });
+ return pair<const rule_match*, bool> (
+ i != e ? &(*i)->rule_match : nullptr,
+ f);
+ };
+
+ pair<const rule_match*, bool> r (find_match (ca));
+
+ // Provide the "add dist_* and configure_* actions for every perform_*
+ // action unless there is a custom one" semantics (see the equivalent ad
+ // hoc rule registration code in the parser for background).
+ //
+ // Note that handling this in the parser by adding the extra actions is
+ // difficult because we store recipe actions in the recipe itself (
+ // adhoc_rule::actions) and a recipe could be shared among multiple
+ // targets, some of which may provide a "custom one" as another recipe. On
+ // the other hand, handling it here is relatively straightforward.
+ //
+ if (r.first == nullptr && !r.second)
+ {
+ meta_operation_id mo (ca.meta_operation ());
+ if (mo == configure_id || mo == dist_id)
+ {
+ action pa (perform_id, ca.operation ());
+ r = find_match (pa);
+ }
}
- return i != e ? &(*i)->rule_match : nullptr;
+ return r.first;
}
// Return the matching rule or NULL if no match and try_match is true.
diff --git a/libbuild2/parser.cxx b/libbuild2/parser.cxx
index 1b8e2d3..b79b65c 100644
--- a/libbuild2/parser.cxx
+++ b/libbuild2/parser.cxx
@@ -1447,7 +1447,12 @@ namespace build2
// And the same for the configure meta-operation to, for
// example, make sure a hinted ad hoc rule matches. @@ Hm,
// maybe we fixed this with action-specific hints? But the
- // injection part above may still apply.
+ // injection part above may still apply. BTW, this is also
+ // required for see-through groups in order to resolve their
+ // member.
+ //
+ // Note also that the equivalent semantics for ad hoc recipes
+ // is provided by match_adhoc_recipe().
//
if (a.meta_operation () == perform_id)
{
@@ -1469,7 +1474,8 @@ namespace build2
// see-through target group, then we may also need to
// register update for other meta-operations (see, for
// example, wildcard update registration in the cli
- // module).
+ // module). BTW, we can now detect such a target via
+ // its target type flags.
}
}
}
@@ -2225,6 +2231,9 @@ namespace build2
}
target_->adhoc_recipes.push_back (r);
+
+ // Note that "registration" of configure_* and dist_* actions
+ // (similar to ad hoc rules) is provided by match_adhoc_recipe().
}
}