aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/rule.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/rule.hxx')
-rw-r--r--libbuild2/rule.hxx155
1 files changed, 132 insertions, 23 deletions
diff --git a/libbuild2/rule.hxx b/libbuild2/rule.hxx
index ad6b51c..eceb6ad 100644
--- a/libbuild2/rule.hxx
+++ b/libbuild2/rule.hxx
@@ -22,13 +22,25 @@ 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
+ // "try harder" if a hint was specified (see cc::link_rule for an example).
//
// The match_extra argument (the type is defined in target.hxx) is used to
// pass additional information that is only needed by some rule
// 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
@@ -40,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
@@ -47,15 +65,45 @@ 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 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,
+ action, target&, match_extra&) const;
};
- // Simplified interface for rules that don't care about the extras.
+ // Simplified interface for rules that don't care about the hint or extras.
//
class LIBBUILD2_SYMEXPORT simple_rule: public rule
{
public:
virtual bool
- match (action, target&, const string& hint) const = 0;
+ match (action, target&) const = 0;
virtual recipe
apply (action, target&) const = 0;
@@ -65,31 +113,52 @@ namespace build2
virtual recipe
apply (action, target&, match_extra&) const override;
+
+ // The simplified version of sub_match() above.
+ //
+ // Note that it calls the simplified match() directly rather than going
+ // through the original.
+ //
+ bool
+ sub_match (const string& rule_name, operation_id hint_op,
+ action, target&) const;
};
// Fallback rule that only matches if the file exists. It will also match
// an mtime_target provided it has a set timestamp.
//
- class LIBBUILD2_SYMEXPORT file_rule: public simple_rule
+ // Note: this rule is "hot" because it matches every static source file and
+ // so we don't use simple_rule to avoid two extra virtual calls.
+ //
+ class LIBBUILD2_SYMEXPORT file_rule: public rule
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&, const string&, match_extra&) const override;
virtual recipe
- apply (action, target&) const override;
+ 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
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -105,7 +174,7 @@ namespace build2
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -120,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;
@@ -132,7 +204,7 @@ namespace build2
{
public:
virtual bool
- match (action, target&, const string&) const override;
+ match (action, target&) const override;
virtual recipe
apply (action, target&) const override;
@@ -145,9 +217,14 @@ namespace build2
//
// Used for both ad hoc pattern rules and ad hoc recipes. For recipes, it's
// essentially a rule of one case. Note that when used as part of a pattern,
- // the implementation cannot use the match_extra::buffer nor the target
- // auxiliary data storage until the pattern's apply_*() calls have been
- // made.
+ // the implementation cannot use the match_extra::data() facility nor the
+ // target auxiliary data storage until the pattern's apply_*() calls have
+ // been made.
+ //
+ // Note also that when used as part of a pattern, the rule is also register
+ // for the dist meta-operation (unless there is an explicit recipe for dist)
+ // in order to inject additional pattern prerequisites which may "pull"
+ // additional sources into the distribution.
//
// Note: not exported.
//
@@ -173,13 +250,20 @@ namespace build2
// Set the rule text, handle any recipe-specific attributes, and return
// true if the recipe builds anything in the build/recipes/ directory and
- // therefore requires cleanup. Scope is the scope of the recipe.
+ // therefore requires cleanup.
+ //
+ // Scope is the scope of the recipe and target type is the type of the
+ // first target (for ad hoc recipe) or primary group member type (for ad
+ // hoc pattern rule). The idea is that an implementation may make certain
+ // assumptions based on the first target type (e.g., file vs non-file
+ // based) in which case it should also enforce (e.g., in match()) that any
+ // other targets that share this recipe are also of suitable type.
//
// Note also that this function is called after the actions member has
// been populated.
//
virtual bool
- recipe_text (const scope&, string&&, attributes&) = 0;
+ recipe_text (const scope&, const target_type&, string&&, attributes&) = 0;
public:
// Some of the operations come in compensating pairs, such as update and
@@ -193,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;
@@ -207,8 +301,8 @@ namespace build2
// Implementation details.
//
public:
- // The name in rule_match is used as a hint and as a name in diagnostics.
- // The former does not apply to ad hoc recipes (but does apply to ad hoc
+ // The name in rule_match is used to match hints and in diagnostics. The
+ // former does not apply to ad hoc recipes (but does apply to ad hoc
// rules).
//
const build2::rule_match rule_match;
@@ -259,14 +353,29 @@ 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&, match_extra&) const = 0;
-
+ 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. It should also avoid adding duplicate
+ // fsdir{} similar to the search_prerequisite*() functions.
+ //
virtual void
- apply_prerequisites (action, target&, match_extra&) const = 0;
+ apply_prerequisites (action, target&,
+ const scope& base,
+ match_extra&) const = 0;
// Dump support.
//