aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/bin/rule.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2022-06-24 05:31:55 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2022-06-24 05:33:49 +0200
commit52128dcc2d88a262238c07fe8acdbcfad684035c (patch)
tree14b2e27b18e09c6577100c21bf79659743059867 /libbuild2/bin/rule.cxx
parent73c8c339c5c8fb468c4ddb1632d87d1aeb1cd497 (diff)
Match rule to libul{} with explicit bin.metadata hint
This rule picks, matches, and unmatches (if possible) a member for the purpose of making its metadata (for example, library's poptions, if it's one of the cc libraries) available.
Diffstat (limited to 'libbuild2/bin/rule.cxx')
-rw-r--r--libbuild2/bin/rule.cxx81
1 files changed, 77 insertions, 4 deletions
diff --git a/libbuild2/bin/rule.cxx b/libbuild2/bin/rule.cxx
index 38a3d98..1d33961 100644
--- a/libbuild2/bin/rule.cxx
+++ b/libbuild2/bin/rule.cxx
@@ -35,14 +35,87 @@ namespace build2
// libul_rule
//
bool libul_rule::
- match (action a, target& t) const
+ match (action a, target& t, const string& h, match_extra&) const
{
- fail << diag_doing (a, t) << " target group" <<
- info << "explicitly select libua{} or libus{} member" << endf;
+ if (!metadata_)
+ {
+ fail << diag_doing (a, t) << " target group" <<
+ info << "explicitly select libua{} or libus{} member" <<
+ info << "or use bin.metadata rule hint if this is metadata library";
+ }
+
+ return (h == "bin.metadata");
}
recipe libul_rule::
- apply (action, target&) const {return empty_recipe;}
+ apply (action a, target& t, match_extra&) const
+ {
+ assert (metadata_);
+
+ // Pick one of the members. First looking for the one already matched.
+ //
+ const target* m (nullptr);
+
+ const libus* ls (nullptr);
+ {
+ ls = search_existing<libus> (t.ctx, t.dir, t.out, t.name);
+
+ if (ls != nullptr && ls->matched (a))
+ m = ls;
+ }
+
+ const libua* la (nullptr);
+ if (m == nullptr)
+ {
+ la = search_existing<libua> (t.ctx, t.dir, t.out, t.name);
+
+ if (la != nullptr && la->matched (a))
+ m = la;
+ }
+
+ if (m == nullptr)
+ {
+ const scope& bs (t.base_scope ());
+
+ lmembers lm (link_members (*bs.root_scope ()));
+
+ if (lm.s && lm.a)
+ {
+ // Use the bin.exe.lib order as a heuristics to pick the library
+ // (i.e., the most likely utility library to be built is the one
+ // most likely to be linked).
+ //
+ lorder lo (link_order (bs, otype::e));
+
+ (lo == lorder::s_a || lo == lorder::s ? lm.a : lm.s) = false;
+ }
+
+ if (lm.s)
+ m = ls != nullptr ? ls : &search<libus> (t, t.dir, t.out, t.name);
+ else
+ m = la != nullptr ? la : &search<libua> (t, t.dir, t.out, t.name);
+ }
+
+ // Save the member we picked in case others (e.g., $x.lib_poptions())
+ // need this information.
+ //
+ t.prerequisite_targets[a].push_back (m);
+
+ if (match_sync (a, *m, unmatch::safe).first)
+ return noop_recipe;
+
+ return [] (action a, const target& t)
+ {
+ const target* m (t.prerequisite_targets[a].back ());
+
+ // For update always return unchanged so we are consistent whether we
+ // managed to unmatch or now. Note that for clean we may get postponed
+ // so let's return the actual target state.
+ //
+ target_state r (execute_sync (a, *m));
+ return a == perform_update_id ? target_state::unchanged : r;
+ };
+ }
// lib_rule
//