From b01aaa16e5adaa0cc064490535f8756b2ef8d421 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 12 Aug 2021 13:05:54 +0200 Subject: Add ${c,cxx}.deduplicate_export_libs() function This function deduplicates interface library dependencies by removing libraries that are also interface dependencies of the specified libraries. This can result in significantly better build performance for heavily interface-interdependent library families (for example, like Boost). Typical usage: import intf_libs = ... import intf_libs += ... ... import intf_libs += ... intf_libs = $cxx.deduplicate_export_libs($intf_libs) --- libbuild2/cc/functions.cxx | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'libbuild2/cc/functions.cxx') diff --git a/libbuild2/cc/functions.cxx b/libbuild2/cc/functions.cxx index 7f9a6c2..6d54c49 100644 --- a/libbuild2/cc/functions.cxx +++ b/libbuild2/cc/functions.cxx @@ -399,6 +399,65 @@ namespace build2 fail << t << " is not an object file target"; }}); + // $.deduplicate_export_libs() + // + // Deduplicate interface library dependencies by removing libraries that + // are also interface dependencies of the specified libraries. This can + // result in significantly better build performance for heavily + // interface-interdependent library families (for example, like Boost). + // Typical usage: + // + // import intf_libs = ... + // import intf_libs += ... + // ... + // import intf_libs += ... + // intf_libs = $cxx.deduplicate_export_libs($intf_libs) + // + // Notes: + // + // 1. We only consider unqualified absolute/normalized target names (the + // idea is that the installed case will already be deduplicated). + // + // 2. We assume all the libraries listed are of the module type and only + // look for cc.export.libs and .export.libs. + // + // 3. No member/group selection/linkup: we resolve *.export.libs on + // whatever is listed. + // + // Note that this function is not pure. + // + f.insert (".deduplicate_export_libs", false). + insert ( + [] (const scope* bs, + vector_view vs, + const function_overload& f) -> value + { + const char* x (*reinterpret_cast (&f.data)); + + if (bs == nullptr) + fail << f.name << " called out of scope"; + + const scope* rs (bs->root_scope ()); + + if (rs == nullptr) + fail << f.name << " called out of project"; + + const module* m (rs->find_module (x)); + + if (m == nullptr) + fail << f.name << " called without " << x << " module loaded"; + + // We can assume the argument is present due to function's types + // signature. + // + names& r (vs[0].as ()); + m->deduplicate_export_libs (*bs, + vector (r.begin (), r.end ()), + r); + return value (move (r)); + }, + x); + // $.find_system_library() // // Return the library path if the specified library exists in one of the -- cgit v1.1