From 7382e4bf15d11b9200d6220b2a89e1f82b220c5e Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 12 Aug 2021 09:27:24 +0200 Subject: Avoid duplication in Libs/Libs.private in generated .pc files --- libbuild2/cc/common.cxx | 2 ++ libbuild2/cc/link-rule.hxx | 51 +++++++++++++++++++++++++++++++--------------- libbuild2/cc/pkgconfig.cxx | 39 ++++++++++++++++++++++++++++------- 3 files changed, 69 insertions(+), 23 deletions(-) diff --git a/libbuild2/cc/common.cxx b/libbuild2/cc/common.cxx index d9afd21..934ea38 100644 --- a/libbuild2/cc/common.cxx +++ b/libbuild2/cc/common.cxx @@ -305,7 +305,9 @@ namespace build2 // if (impl && !c_e_libs.defined () && !x_e_libs.defined ()) { +#if 0 assert (top_li); // Must pick a member if implementation (see above). +#endif for (const prerequisite_target& pt: l.prerequisite_targets[a]) { diff --git a/libbuild2/cc/link-rule.hxx b/libbuild2/cc/link-rule.hxx index 23f7167..3d801d6 100644 --- a/libbuild2/cc/link-rule.hxx +++ b/libbuild2/cc/link-rule.hxx @@ -81,11 +81,10 @@ namespace build2 class appended_libraries: public small_vector { public: - // Find existing or append new entry. If appending new, use the second - // argument as the begin value. + // Find existing entry, if any. // - appended_library& - append (const file& l, size_t b) + appended_library* + find (const file& l) { auto i (find_if (begin (), end (), [&l] (const appended_library& al) @@ -93,19 +92,11 @@ namespace build2 return al.l2 == nullptr && al.l1 == &l; })); - if (i != end ()) - return *i; - - push_back (appended_library {&l, nullptr, b, appended_library::npos}); - return back (); + return i != end () ? &*i : nullptr; } - // Return NULL if no duplicate tracking can be performed for this - // library. - // appended_library* - append (const small_vector, 2>& ns, - size_t b) + find (const small_vector, 2>& ns) { size_t n (ns.size ()); @@ -125,8 +116,36 @@ namespace build2 : al.l1 == nullptr); })); - if (i != end ()) - return &*i; + return i != end () ? &*i : nullptr; + } + + // Find existing or append new entry. If appending new, use the second + // argument as the begin value. + // + appended_library& + append (const file& l, size_t b) + { + if (appended_library* r = find (l)) + return *r; + + push_back (appended_library {&l, nullptr, b, appended_library::npos}); + return back (); + } + + // Return NULL if no duplicate tracking can be performed for this + // library. + // + appended_library* + append (const small_vector, 2>& ns, + size_t b) + { + size_t n (ns.size ()); + + if (n > 2) + return nullptr; + + if (appended_library* r = find (ns)) + return r; push_back (appended_library { n == 2 ? &ns[1].get () : nullptr, &ns[0].get (), diff --git a/libbuild2/cc/pkgconfig.cxx b/libbuild2/cc/pkgconfig.cxx index 9177dbb..3fcfb9a 100644 --- a/libbuild2/cc/pkgconfig.cxx +++ b/libbuild2/cc/pkgconfig.cxx @@ -1642,9 +1642,10 @@ namespace build2 struct data { ofdstream& os; - appended_libraries& ls; + appended_libraries* pls; // Previous. + appended_libraries* ls; // Current. strings& args; - } d {os, ls, args}; + } d {os, nullptr, &ls, args}; auto imp = [&priv] (const target&, bool la) {return priv && la;}; @@ -1656,17 +1657,31 @@ namespace build2 { const file* l (lc != nullptr ? &(*lc)->as () : nullptr); + // Suppress duplicates from the previous run (Libs/Libs.private + // split). + // + if (d.pls != nullptr) + { + // Doesn't feel like we can prune here: we may have seen this + // interface library but not its implementation dependencies. + // + if ((l != nullptr + ? d.pls->find (*l) + : d.pls->find (ns)) != nullptr) + return true; + } + // Suppress duplicates (see append_libraries() for details). // // Note that we use the original name for duplicate tracking. // appended_library* al (l != nullptr - ? &d.ls.append (*l, d.args.size ()) - : d.ls.append (ns, d.args.size ())); + ? &d.ls->append (*l, d.args.size ()) + : d.ls->append (ns, d.args.size ())); if (al != nullptr && al->end != appended_library::npos) { - d.ls.hoist (d.args, *al); + d.ls->hoist (d.args, *al); return true; } @@ -1697,9 +1712,12 @@ namespace build2 //@@ TODO: how will the Libs/Libs.private work? //@@ TODO: remember to use escape() + if (d.pls != nullptr && d.pls->find (l) != nullptr) + return true; + // See link_rule::append_libraries(). - if (d.ls.append (l, d.args.size ()).end != appended_library::npos) + if (d.ls->append (l, d.args.size ()).end != appended_library::npos) return true; return true; @@ -1723,9 +1741,16 @@ namespace build2 { os << "Libs.private:"; - ls.clear (); args.clear (); priv = true; + + // Use previous appended_libraries to weed out entries that are + // already in Libs. + // + appended_libraries als; + d.pls = d.ls; + d.ls = &als; + process_libraries (a, bs, li, sys_lib_dirs, l, la, 0, // Link flags. imp, lib, opt, false /* self */, &lib_cache); -- cgit v1.1