aboutsummaryrefslogtreecommitdiff
path: root/libbuild2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2020-06-08 08:12:54 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2020-06-08 08:12:54 +0200
commit8e42d1ec329ac16ec5ae9692f18cdb0f2444d2fb (patch)
tree386ea3472fa382727d1f377c0c7090f81ddd292a /libbuild2
parentfb56fc798110c8ee9685bec156b21f1f87aca121 (diff)
Fix handling of inner/outer operations in ad hoc recipes machinery
Diffstat (limited to 'libbuild2')
-rw-r--r--libbuild2/action.hxx2
-rw-r--r--libbuild2/algorithm.cxx23
-rw-r--r--libbuild2/rule.cxx18
3 files changed, 29 insertions, 14 deletions
diff --git a/libbuild2/action.hxx b/libbuild2/action.hxx
index 906d7eb..e149574 100644
--- a/libbuild2/action.hxx
+++ b/libbuild2/action.hxx
@@ -115,6 +115,8 @@ namespace build2
bool operator>= (action, action) = delete;
bool operator<= (action, action) = delete;
+ // Note: prints in numeric form (mostly used in tracing).
+ //
LIBBUILD2_SYMEXPORT ostream&
operator<< (ostream&, action); // operation.cxx
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx
index 6ea1e1f..077bdf2 100644
--- a/libbuild2/algorithm.cxx
+++ b/libbuild2/algorithm.cxx
@@ -326,33 +326,34 @@ namespace build2
dr << info << "while matching ad hoc recipe to " << diag_do (a, t);
});
- // @@ TODO:
+ // The action could be Y-for-X while the ad hoc recipes are always for
+ // X. So strip the Y-for part for comparison (but not for the match()
+ // calls; see below for the hairy inner/outer semantics details).
//
- // 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.
+ action ca (a.outer ()
+ ? action (a.meta_operation (), a.outer_operation ())
+ : a);
auto b (t.adhoc_recipes.begin ()), e (t.adhoc_recipes.end ());
auto i (find_if (
b, e,
- [a, &t] (const adhoc_recipe& r)
+ [a, ca, &t] (const adhoc_recipe& r)
{
auto& as (r.actions);
- return (find (as.begin (), as.end (), a) != as.end () &&
+ return (find (as.begin (), as.end (), ca) != as.end () &&
r.rule->match (a, t, string () /* hint */, nullopt));
}));
if (i == e)
i = find_if (
b, e,
- [a, &t] (const adhoc_recipe& r)
+ [a, ca, &t] (const adhoc_recipe& r)
{
- // See the adhoc_rule::match() documentation for details.
+ // See the adhoc_rule::match() documentation for details on what's
+ // going on here.
//
auto& as (r.actions);
- if (find (as.begin (), as.end (), a) == as.end ())
+ if (find (as.begin (), as.end (), ca) == as.end ())
{
for (auto ra: as)
if (r.rule->match (a, t, string () /* hint */, ra))
diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx
index fb769fd..f257b62 100644
--- a/libbuild2/rule.cxx
+++ b/libbuild2/rule.cxx
@@ -472,12 +472,24 @@ namespace build2
recipe adhoc_script_rule::
apply (action a, target& t) const
{
+ // If this is an outer operation (e.g., update-for-test), then delegate to
+ // the inner.
+ //
+ if (a.outer ())
+ {
+ match_inner (a, t);
+ return execute_inner;
+ }
+
// 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 (a == perform_update_id || a == perform_clean_id)
{
- if (auto* p = m->is_a<path_target> ())
- p->derive_path ();
+ 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.