aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/rule-map.hxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-04-06 11:26:52 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-04-06 13:51:56 +0200
commit76be0a35f6c37cda7ba65530330f1ac246fb52a8 (patch)
treef613ceafcf6c7208984d4536653061c4e0c23be7 /libbuild2/rule-map.hxx
parent0a9dd0c7d31cbba2170fdfda4b747a1fe5ce665a (diff)
Add support for rule hints
A rule hint is a target attribute, for example: [rule_hint=cxx] exe{hello}: c{hello} Rule hints can be used to resolve ambiguity when multiple rules match the same target as well as to override an unambiguous match.
Diffstat (limited to 'libbuild2/rule-map.hxx')
-rw-r--r--libbuild2/rule-map.hxx56
1 files changed, 42 insertions, 14 deletions
diff --git a/libbuild2/rule-map.hxx b/libbuild2/rule-map.hxx
index d4a0f33..8f6f59f 100644
--- a/libbuild2/rule-map.hxx
+++ b/libbuild2/rule-map.hxx
@@ -14,10 +14,38 @@
namespace build2
{
- using hint_rule_map =
- butl::prefix_map<string, reference_wrapper<const rule>, '.'>;
+ // A rule name is used both for diagnostics as well as to match rule hints
+ // (see rule_hints). A rule hint is a potentially partial rule name.
+ //
+ // The recommended rule naming scheme is to start with the module name, for
+ // example: cxx.compile, cxx.link. This way a rule hint can be just the
+ // module name, for example [rule_hint=cxx]. If a module can only possibly
+ // have a single rule, then the rule name can be just the module name (e.g.,
+ // `in`; though make doubly sure there is unlikely to be a need for another
+ // rule, for example, for documentation generation, in the future).
+ //
+ // The two common choices of names for the second component in a rule name
+ // is an action (e.g., cxx.compile, cxx.link) or a target type (e.g.,
+ // bin.def, bin.lib). The latter is a good choice when the action is
+ // inherent to the target type (e.g., "generate def file", "see through lib
+ // group"). Also note that a rule for compensating operations (e.g.,
+ // update/clean, install/uninstall) is customarily registered with the same
+ // name.
+ //
+ struct name_rule_map: butl::prefix_map<string,
+ reference_wrapper<const rule>,
+ '.'>
+ {
+ // Return true if the rule name matches a rule hint.
+ //
+ static bool
+ sub (const string& hint, const string& name)
+ {
+ return compare_type ('.').prefix (hint, name);
+ }
+ };
- using target_type_rule_map = map<const target_type*, hint_rule_map>;
+ using target_type_rule_map = map<const target_type*, name_rule_map>;
// This is an "indexed map" with operation_id being the index. Entry
// with id 0 is a wildcard.
@@ -33,7 +61,7 @@ namespace build2
bool
insert (operation_id oid,
const target_type& tt,
- string hint,
+ string name,
const rule& r)
{
// 3 is the number of builtin operations.
@@ -41,7 +69,7 @@ namespace build2
if (oid >= map_.size ())
map_.resize ((oid < 3 ? 3 : oid) + 1);
- return map_[oid][&tt].emplace (move (hint), r).second;
+ return map_[oid][&tt].emplace (move (name), r).second;
}
// Return NULL if not found.
@@ -78,17 +106,17 @@ namespace build2
bool
insert (action_id a,
const target_type& tt,
- string hint,
+ string name,
const rule& r)
{
- return insert (a >> 4, a & 0x0F, tt, move (hint), r);
+ return insert (a >> 4, a & 0x0F, tt, move (name), r);
}
template <typename T>
bool
- insert (action_id a, string hint, const rule& r)
+ insert (action_id a, string name, const rule& r)
{
- return insert (a, T::static_type, move (hint), r);
+ return insert (a, T::static_type, move (name), r);
}
// 0 oid is a wildcard.
@@ -97,17 +125,17 @@ namespace build2
insert (meta_operation_id mid,
operation_id oid,
const target_type& tt,
- string hint,
+ string name,
const rule& r)
{
if (mid_ == mid)
- return map_.insert (oid, tt, move (hint), r);
+ return map_.insert (oid, tt, move (name), r);
else
{
if (next_ == nullptr)
next_.reset (new rule_map (mid));
- return next_->insert (mid, oid, tt, move (hint), r);
+ return next_->insert (mid, oid, tt, move (name), r);
}
}
@@ -115,10 +143,10 @@ namespace build2
bool
insert (meta_operation_id mid,
operation_id oid,
- string hint,
+ string name,
const rule& r)
{
- return insert (mid, oid, T::static_type, move (hint), r);
+ return insert (mid, oid, T::static_type, move (name), r);
}
// Return NULL if not found.