aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/rule-map.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/rule-map.hxx')
-rw-r--r--libbuild2/rule-map.hxx89
1 files changed, 70 insertions, 19 deletions
diff --git a/libbuild2/rule-map.hxx b/libbuild2/rule-map.hxx
index df59548..8f6f59f 100644
--- a/libbuild2/rule-map.hxx
+++ b/libbuild2/rule-map.hxx
@@ -4,9 +4,7 @@
#ifndef LIBBUILD2_RULE_MAP_HXX
#define LIBBUILD2_RULE_MAP_HXX
-#include <map>
-
-#include <libbutl/prefix-map.mxx>
+#include <libbutl/prefix-map.hxx>
#include <libbuild2/types.hxx>
#include <libbuild2/forward.hxx>
@@ -16,30 +14,62 @@
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 = std::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.
//
- // Note that while we may resize some vectors during non-serial load, this
+ // Note that while we may resize some vectors during non-initial load, this
// is MT-safe since we never cache any references to their elements.
//
class operation_rule_map
{
public:
- template <typename T>
- void
- insert (operation_id oid, const char* hint, const rule& r)
+ // Return false in case of a duplicate.
+ //
+ bool
+ insert (operation_id oid,
+ const target_type& tt,
+ string name,
+ const rule& r)
{
// 3 is the number of builtin operations.
//
if (oid >= map_.size ())
map_.resize ((oid < 3 ? 3 : oid) + 1);
- map_[oid][&T::static_type].emplace (hint, r);
+ return map_[oid][&tt].emplace (move (name), r).second;
}
// Return NULL if not found.
@@ -71,33 +101,54 @@ namespace build2
class rule_map
{
public:
+ // Return false in case of a duplicate.
+ //
+ bool
+ insert (action_id a,
+ const target_type& tt,
+ string name,
+ const rule& r)
+ {
+ return insert (a >> 4, a & 0x0F, tt, move (name), r);
+ }
+
template <typename T>
- void
- insert (action_id a, const char* hint, const rule& r)
+ bool
+ insert (action_id a, string name, const rule& r)
{
- insert<T> (a >> 4, a & 0x0F, hint, r);
+ return insert (a, T::static_type, move (name), r);
}
// 0 oid is a wildcard.
//
- template <typename T>
- void
+ bool
insert (meta_operation_id mid,
operation_id oid,
- const char* hint,
+ const target_type& tt,
+ string name,
const rule& r)
{
if (mid_ == mid)
- map_.insert<T> (oid, hint, r);
+ return map_.insert (oid, tt, move (name), r);
else
{
if (next_ == nullptr)
next_.reset (new rule_map (mid));
- next_->insert<T> (mid, oid, hint, r);
+ return next_->insert (mid, oid, tt, move (name), r);
}
}
+ template <typename T>
+ bool
+ insert (meta_operation_id mid,
+ operation_id oid,
+ string name,
+ const rule& r)
+ {
+ return insert (mid, oid, T::static_type, move (name), r);
+ }
+
// Return NULL if not found.
//
const operation_rule_map*