aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/target.ixx
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/target.ixx
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/target.ixx')
-rw-r--r--libbuild2/target.ixx87
1 files changed, 86 insertions, 1 deletions
diff --git a/libbuild2/target.ixx b/libbuild2/target.ixx
index 8f0768e..af75cd1 100644
--- a/libbuild2/target.ixx
+++ b/libbuild2/target.ixx
@@ -53,6 +53,91 @@ namespace build2
return r;
}
+ // rule_hints
+ //
+ inline const string& rule_hints::
+ find (const target_type& tt, operation_id o, bool ut) const
+ {
+ // Look for fallback during the same iteration.
+ //
+ const value_type* f (nullptr);
+
+ for (const value_type& v: map)
+ {
+ if (!(v.type == nullptr ? ut : tt.is_a (*v.type)))
+ continue;
+
+ if (v.operation == o)
+ return v.hint;
+
+ if (f == nullptr &&
+ v.operation == default_id &&
+ (o == update_id || o == clean_id))
+ f = &v;
+ }
+
+ return f != nullptr ? f->hint : empty_string;
+ }
+
+ inline void rule_hints::
+ insert (const target_type* tt, operation_id o, string h)
+ {
+ auto i (find_if (map.begin (), map.end (),
+ [tt, o] (const value_type& v)
+ {
+ return v.operation == o && v.type == tt;
+ }));
+
+ if (i == map.end ())
+ map.push_back (value_type {tt, o, move (h)});
+ else
+ i->hint = move (h);
+ }
+
+ inline const string& target::
+ find_hint (operation_id o) const
+ {
+ using flag = target_type::flag;
+
+ const target_type* tt (nullptr); // Resolve lazily.
+
+ // First check the target itself.
+ //
+ if (!rule_hints.empty ())
+ {
+ // If this is a group that "gave" its untyped hints to the members, then
+ // ignore untyped entries.
+ //
+ tt = &type ();
+ bool ut ((tt->flags & flag::member_hint) != flag::member_hint);
+
+ const string& r (rule_hints.find (*tt, o, ut));
+ if (!r.empty ())
+ return r;
+ }
+
+ // Then check the group.
+ //
+ if (const target* g = group)
+ {
+ if (!g->rule_hints.empty ())
+ {
+ // If the group "gave" its untyped hints to the members, then don't
+ // ignore untyped entries.
+ //
+ const target_type& gt (g->type ());
+ bool ut ((gt.flags & flag::member_hint) == flag::member_hint);
+
+ if (tt == nullptr)
+ tt = &type ();
+
+ return g->rule_hints.find (*tt, o, ut);
+ }
+ }
+
+ return empty_string;
+ }
+
// match_extra
//
inline void match_extra::
@@ -524,7 +609,7 @@ namespace build2
if (r_->mode_ != members_mode::never &&
i_ != r_->e_ &&
- i_->type.see_through)
+ i_->type.see_through ())
switch_mode ();
}