aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/algorithm.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-06-02 08:34:38 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2021-06-08 15:43:08 +0200
commit1346f4cd0d20a5dc7e0471edbbb6ce00f2da5c18 (patch)
tree25a2b70304520bac33aede420ab2ad7715791d69 /libbuild2/algorithm.cxx
parentc5feaaf745421f2ecda672585c462cf4c807d25d (diff)
Redo fallback reverse operation machinery in ad hoc recipes
Diffstat (limited to 'libbuild2/algorithm.cxx')
-rw-r--r--libbuild2/algorithm.cxx43
1 files changed, 30 insertions, 13 deletions
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index a19a6a0..acff325 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -345,16 +345,22 @@ namespace build2
dr << info << "while matching ad hoc recipe to " << diag_do (a, t);
});
- auto match = [a, &t] (const adhoc_rule& r, optional<action> ra)
+ auto match = [a, &t] (const adhoc_rule& r, bool fallback) -> bool
{
- match_extra me;
+ match_extra me {fallback};
+ bool m;
if (auto* f = (a.outer ()
? t.ctx.current_outer_oif
: t.ctx.current_inner_oif)->adhoc_match)
- return f (r, a, t, string () /* hint */, me, ra);
+ m = f (r, a, t, string () /* hint */, me);
else
- return r.match (a, t, string () /* hint */, me, ra);
+ m = r.match (a, t, string () /* hint */, me);
+
+ if (m)
+ t[a].match_extra = move (me);
+
+ return m;
};
// The action could be Y-for-X while the ad hoc recipes are always for
@@ -372,13 +378,16 @@ namespace build2
{
auto& as (r.actions);
return (find (as.begin (), as.end (), ca) != as.end () &&
- match (*r.rule, nullopt));
+ match (*r.rule, false));
}));
if (i == e)
+ {
+ // See if we have a fallback implementation.
+ //
i = find_if (
b, e,
- [&match, ca] (const adhoc_recipe& r)
+ [&match, ca, &t] (const adhoc_recipe& r)
{
// See the adhoc_rule::match() documentation for details on what's
// going on here.
@@ -386,12 +395,17 @@ namespace build2
auto& as (r.actions);
if (find (as.begin (), as.end (), ca) == as.end ())
{
- for (auto ra: as)
- if (match (*r.rule, ra))
+ for (auto sa: as)
+ {
+ optional<action> ra (r.rule->reverse_fallback (sa, t.type ()));
+
+ if (ra && *ra == ca && match (*r.rule, true))
return true;
+ }
}
return false;
});
+ }
if (i != e)
return &i->rule->rule_match;
@@ -470,6 +484,7 @@ namespace build2
if (&ru == skip)
continue;
+ match_extra me {false};
{
auto df = make_diag_frame (
[a, &t, &n](const diag_record& dr)
@@ -479,7 +494,6 @@ namespace build2
<< diag_do (a, t);
});
- match_extra me;
if (!ru.match (a, t, hint, me))
continue;
}
@@ -509,7 +523,7 @@ namespace build2
//
// @@ Can't we temporarily swap things out in target?
//
- match_extra me1;
+ match_extra me1 {false};
if (!ru1.match (a, t, hint, me1))
continue;
}
@@ -525,7 +539,10 @@ namespace build2
}
if (!ambig)
+ {
+ t[a].match_extra = move (me);
return &r;
+ }
else
dr << info << "use rule hint to disambiguate this match";
}
@@ -607,6 +624,9 @@ namespace build2
if (const scope* rs = bs.root_scope ())
penv = auto_project_env (*rs);
+ const rule& r (m.second);
+ match_extra& me (t[a].match_extra);
+
auto df = make_diag_frame (
[a, &t, &m](const diag_record& dr)
{
@@ -615,9 +635,6 @@ namespace build2
<< diag_do (a, t);
});
- const rule& r (m.second);
- match_extra me;
-
if (auto* f = (a.outer ()
? t.ctx.current_outer_oif
: t.ctx.current_inner_oif)->adhoc_apply)