diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2022-06-24 05:31:55 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2022-06-24 05:33:49 +0200 |
commit | 52128dcc2d88a262238c07fe8acdbcfad684035c (patch) | |
tree | 14b2e27b18e09c6577100c21bf79659743059867 /libbuild2/bin/rule.cxx | |
parent | 73c8c339c5c8fb468c4ddb1632d87d1aeb1cd497 (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.cxx | 81 |
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 // |