diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2023-10-17 15:01:53 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2023-10-26 13:29:24 +0200 |
commit | 4d34633cfbd3936cb4d20545b48a031ba011db4c (patch) | |
tree | 9ea6786ae920dfdf4e8622b7b630f34a21182d8e | |
parent | d3b4636ca3f4c3ad98c8096326c5b1460d05691d (diff) |
WIP: add match_extra data member and rule::rematch()
-rw-r--r-- | libbuild2/algorithm.cxx | 4 | ||||
-rw-r--r-- | libbuild2/rule.cxx | 11 | ||||
-rw-r--r-- | libbuild2/rule.hxx | 7 | ||||
-rw-r--r-- | libbuild2/target.hxx | 29 | ||||
-rw-r--r-- | libbuild2/target.ixx | 5 |
5 files changed, 50 insertions, 6 deletions
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx index 01d5016..2b5e402 100644 --- a/libbuild2/algorithm.cxx +++ b/libbuild2/algorithm.cxx @@ -448,7 +448,7 @@ namespace build2 auto match = [a, &t, &me] (const adhoc_rule& r, bool fallback) -> bool { - me.init (fallback); + me.reinit (fallback); if (auto* f = (a.outer () ? t.ctx.current_outer_oif @@ -756,7 +756,7 @@ namespace build2 if (&ru == skip) continue; - me.init (oi == 0 /* fallback */); + me.reinit (oi == 0 /* fallback */); { auto df = make_diag_frame ( [a, &t, &n](const diag_record& dr) diff --git a/libbuild2/rule.cxx b/libbuild2/rule.cxx index 13dd467..e475375 100644 --- a/libbuild2/rule.cxx +++ b/libbuild2/rule.cxx @@ -15,13 +15,22 @@ using namespace butl; namespace build2 { - // rule (vtable) + // rule // rule:: ~rule () { } + void rule:: + reapply (action, target&, match_extra&) const + { + // Unless the rule overrode cur_options, this function should never get + // called. And if it did, then it should override this function. + // + assert (false); + } + const target* rule:: import (const prerequisite_key&, const optional<string>&, diff --git a/libbuild2/rule.hxx b/libbuild2/rule.hxx index dea9c9a..c693f8d 100644 --- a/libbuild2/rule.hxx +++ b/libbuild2/rule.hxx @@ -34,6 +34,10 @@ namespace build2 // implementations. It is also a way for us to later pass more information // without breaking source compatibility. // + // A rule may support match options and if such a rule is rematched with + // different options, then reapply() is called. See + // match_extra::{cur,new}_options for background and details. + // struct match_extra; class LIBBUILD2_SYMEXPORT rule @@ -45,6 +49,9 @@ namespace build2 virtual recipe apply (action, target&, match_extra&) const = 0; + virtual void + reapply (action, target&, match_extra&) const; + rule () = default; virtual diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx index 1178371..ed8c0bf 100644 --- a/libbuild2/target.hxx +++ b/libbuild2/target.hxx @@ -180,6 +180,29 @@ namespace build2 bool locked; // Normally true (see adhoc_rule::match() for background). bool fallback; // True if matching a fallback rule (see match_rule()). + // Match options. + // + // On initial match()/apply(), cur_options is initialized to ~0 (all + // options enabled) and the matching rule is expected to override it with + // new_options in match() (if it matches). This way a rule that does not + // support any match options does not need to do anything. On rematch in + // the reapply() call, cur_options are the currently enabled options and + // new_options are the newly requested options. Here the rule is expected + // to factor new_options to cur_options as appropriate. Note also that on + // rematch, if current options already include new options, then no call + // to reapply() is made. This, in particular, means that a rule that does + // not adjust cur_options in match() will never get a reapply() call + // (because all the options are enabled from the start). + // + // @@ TODO: clear already enabled options from new_options on rematch. + // + // @@ TODO doc + // + uint64_t cur_options; + uint64_t new_options; + + static const uint64_t all_options = ~uint64_t (0); + // Auxiliary data storage. // // A rule (whether matches or not) may use this pad to pass data between @@ -249,10 +272,12 @@ namespace build2 // public: explicit - match_extra (bool l = true, bool f = false): locked (l), fallback (f) {} + match_extra (bool l = true, bool f = false) + : locked (l), fallback (f), + cur_options (all_options), new_options (0) {} void - init (bool fallback); + reinit (bool fallback); // Force freeing of the dynamically-allocated memory. // diff --git a/libbuild2/target.ixx b/libbuild2/target.ixx index f0d5cea..8873b7b 100644 --- a/libbuild2/target.ixx +++ b/libbuild2/target.ixx @@ -136,10 +136,13 @@ namespace build2 // match_extra // inline void match_extra:: - init (bool f) + reinit (bool f) { + //assert (locked); clear_data (); fallback = f; + cur_options = all_options; + new_options = 0; } inline void match_extra:: |