aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2023-10-17 15:01:53 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2023-10-26 13:29:24 +0200
commit4d34633cfbd3936cb4d20545b48a031ba011db4c (patch)
tree9ea6786ae920dfdf4e8622b7b630f34a21182d8e
parentd3b4636ca3f4c3ad98c8096326c5b1460d05691d (diff)
WIP: add match_extra data member and rule::rematch()
-rw-r--r--libbuild2/algorithm.cxx4
-rw-r--r--libbuild2/rule.cxx11
-rw-r--r--libbuild2/rule.hxx7
-rw-r--r--libbuild2/target.hxx29
-rw-r--r--libbuild2/target.ixx5
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::