diff options
Diffstat (limited to 'libbuild2/rule.hxx')
-rw-r--r-- | libbuild2/rule.hxx | 80 |
1 files changed, 69 insertions, 11 deletions
diff --git a/libbuild2/rule.hxx b/libbuild2/rule.hxx index 77c2d2c..eceb6ad 100644 --- a/libbuild2/rule.hxx +++ b/libbuild2/rule.hxx @@ -22,7 +22,8 @@ namespace build2 // you need to modify some state (e.g., counters or some such), then make // sure things are MT-safe. // - // Note: match() is only called once but may not be followed by apply(). + // Note: match() could be called multiple times (so should be idempotent) + // and it may not be followed by apply(). // // The hint argument is the rule hint, if any, that was used to select this // rule. While normally not factored into the match decision, a rule may @@ -33,6 +34,13 @@ namespace build2 // implementations. It is also a way for us to later pass more information // without breaking source compatibility. // + // A rule may adjust post hoc prerequisites by overriding apply_posthoc(). + // See match_extra::posthoc_prerequisite_targets for background and details. + // + // 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 @@ -44,6 +52,12 @@ namespace build2 virtual recipe apply (action, target&, match_extra&) const = 0; + virtual void + apply_posthoc (action, target&, match_extra&) const; + + virtual void + reapply (action, target&, match_extra&) const; + rule () = default; virtual @@ -52,15 +66,31 @@ namespace build2 rule (const rule&) = delete; rule& operator= (const rule&) = delete; + // Resolve a project-qualified target in a rule-specific manner. + // + // This is optional functionality that may be provided by some rules to + // facilitate immediate importation of certain target types. See the + // import machinery for details. The default implementation always returns + // NULL. + // + // Note that if this function returns a target, it should have the + // extension assigned so that as_name() returns a stable name. + // + virtual const target* + import (const prerequisite_key&, + const optional<string>& metadata, + const location&) const; + // Sometimes we want to match only if another rule of ours would match // another operation. For example, we would want our install rule to match // only if our update rule also matches. // // Arranging this, however, is not a simple matter of calling the other - // rule's match(): we also have to take into account the rule hints for - // that operation. This helper performs all the necessary steps. Note: - // should only be called from match() (see target::find_hint() for - // details). + // rule's match(): we also have to take into account ad hoc recipes and + // rule hints for that operation. This helper performs all the necessary + // checks. Note: should only be called from match() (see + // target::find_hint() for details). Note also that ad hoc recipes are + // checked for hint_op, not action's operation. // bool sub_match (const string& rule_name, operation_id hint_op, @@ -109,10 +139,19 @@ namespace build2 virtual recipe apply (action, target&, match_extra&) const override; - file_rule () {} + // While this rule expects an mtime_target-based target, sometimes it's + // necessary to register it for something less specific (normally target) + // in order to achieve the desired rule matching priority (see the dist + // and config modules for an example). For such cases this rule can be + // instructed to check the type and only match if it's mtime_target-based. + // + file_rule (bool match_type = false): match_type_ (match_type) {} - static const file_rule instance; + static const file_rule instance; // Note: does not match the target type. static const build2::rule_match rule_match; + + private: + bool match_type_; }; class LIBBUILD2_SYMEXPORT alias_rule: public simple_rule @@ -150,7 +189,10 @@ namespace build2 // of fsdir{} without the overhead of switching to the execute phase. // static void - perform_update_direct (action, const target&); + perform_update_direct (action, const fsdir&); + + static void + perform_clean_direct (action, const fsdir&); fsdir_rule () {} static const fsdir_rule instance; @@ -235,6 +277,16 @@ namespace build2 // The default implementation forwards to the pattern's match() if there // is a pattern and returns true otherwise. // + // Note also that in case of a member of a group-based target, match() is + // called on the group while apply() on the member (see match_rule_impl() + // in algorithms.cxx for details). This means that match() may be called + // without having the target locked and as a result match() should (unless + // known to only match a non-group) treat the target as const and only + // rely on immutable information (type, name, etc) since the group could + // be matched concurrenly. This case can be detected by examining + // match_extra::locked (see adhoc_rule_regex_pattern::match() for a + // use-case). + // virtual bool match (action, target&, const string&, match_extra&) const override; @@ -301,18 +353,24 @@ namespace build2 ~adhoc_rule_pattern (); public: + // Note: the adhoc_rule::match() restrictions apply here as well. + // virtual bool - match (action, target&, const string&, match_extra&) const = 0; + match (action, const target&, const string&, match_extra&) const = 0; + // Append additional group members. Note that this function should handle + // both ad hoc and explicit groups. + // virtual void - apply_adhoc_members (action, target&, + apply_group_members (action, target&, const scope& base, match_extra&) const = 0; // The implementation should append pattern prerequisites to // t.prerequisite_targets[a] but not match. It should set bit 2 in // prerequisite_target::include to indicate update=match and bit 3 - // to indicate update=unmatch. + // to indicate update=unmatch. It should also avoid adding duplicate + // fsdir{} similar to the search_prerequisite*() functions. // virtual void apply_prerequisites (action, target&, |