From 214bc8317696f31d7a121d41e5484d91b0959444 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 28 Aug 2016 15:26:20 +0200 Subject: Optimize library processing --- build2/cc/compile.cxx | 176 +++++++++++++++++++++++++------------------------- build2/cc/link.cxx | 11 +++- 2 files changed, 98 insertions(+), 89 deletions(-) diff --git a/build2/cc/compile.cxx b/build2/cc/compile.cxx index ca01468..39856df 100644 --- a/build2/cc/compile.cxx +++ b/build2/cc/compile.cxx @@ -64,10 +64,8 @@ namespace build2 // (first one is cc.export.*) recursively, prerequisite libraries first. // void compile:: - append_lib_options (cstrings& args, target& xt, scope& bs, lorder lo) const + append_lib_options (cstrings& args, target& t, scope& bs, lorder lo) const { - file& l (static_cast (xt)); - auto opt = [&args, this] (file& l, const string& t, bool com, bool exp) { // Note that in our model *.export.poptions are always "interface", @@ -83,16 +81,32 @@ namespace build2 append_options (args, l, var); }; - process_libraries (bs, lo, sys_lib_dirs, - l, l.is_a (), - nullptr, nullptr, opt); + // In case we don't have the "small function object" optimization. + // + const function optf (opt); + + // Note that here we don't need to see group members (see apply()). + // + for (prerequisite& p: group_prerequisites (t)) + { + target* pt (p.target); // Already searched and matched. + + bool a; + + if (lib* l = pt->is_a ()) + a = (pt = &link_member (*l, lo))->is_a (); + else if (!(a = pt->is_a ()) && !pt->is_a ()) + continue; + + process_libraries (bs, lo, sys_lib_dirs, + static_cast (*pt), a, + nullptr, nullptr, optf); + } } void compile:: - hash_lib_options (sha256& cs, target& xt, scope& bs, lorder lo) const + hash_lib_options (sha256& cs, target& t, scope& bs, lorder lo) const { - file& l (static_cast (xt)); - auto opt = [&cs, this] (file& l, const string& t, bool com, bool exp) { assert (exp); @@ -105,9 +119,64 @@ namespace build2 hash_options (cs, l, var); }; - process_libraries (bs, lo, sys_lib_dirs, - l, l.is_a (), - nullptr, nullptr, opt); + // In case we don't have the "small function object" optimization. + // + const function optf (opt); + + for (prerequisite& p: group_prerequisites (t)) + { + target* pt (p.target); // Already searched and matched. + + bool a; + + if (lib* l = pt->is_a ()) + a = (pt = &link_member (*l, lo))->is_a (); + else if (!(a = pt->is_a ()) && !pt->is_a ()) + continue; + + process_libraries (bs, lo, sys_lib_dirs, + static_cast (*pt), a, + nullptr, nullptr, optf); + } + } + + // Append library prefixes based on the *.export.poptions variables + // recursively, prerequisite libraries first. + // + void compile:: + append_lib_prefixes (prefix_map& m, target& t, scope& bs, lorder lo) const + { + auto opt = [&m, this] (file& l, const string& t, bool com, bool exp) + { + assert (exp); + + const variable& var ( + com + ? c_export_poptions + : (t == x ? x_export_poptions : var_pool[t + ".export.poptions"])); + + append_prefixes (m, l, var); + }; + + // In case we don't have the "small function object" optimization. + // + const function optf (opt); + + for (prerequisite& p: group_prerequisites (t)) + { + target* pt (p.target); // Already searched and matched. + + bool a; + + if (lib* l = pt->is_a ()) + a = (pt = &link_member (*l, lo))->is_a (); + else if (!(a = pt->is_a ()) && !pt->is_a ()) + continue; + + process_libraries (bs, lo, sys_lib_dirs, + static_cast (*pt), a, + nullptr, nullptr, optf); + } } recipe compile:: @@ -267,17 +336,7 @@ namespace build2 // Hash *.export.poptions from prerequisite libraries. // - for (prerequisite& p: group_prerequisites (t)) - { - target* pt (p.target); // Already searched and matched. - - if (lib* l = pt->is_a ()) - pt = &link_member (*l, lo); - else if (!pt->is_a () && !pt->is_a ()) - continue; - - hash_lib_options (cs, *pt, bs, lo); - } + hash_lib_options (cs, t, bs, lo); hash_options (cs, t, c_poptions); hash_options (cs, t, x_poptions); @@ -444,50 +503,14 @@ namespace build2 } } - // Append library prefixes based on the *.export.poptions variables - // recursively, prerequisite libraries first. - // - void compile:: - append_lib_prefixes (prefix_map& m, target& xt, scope& bs, lorder lo) const - { - file& l (static_cast (xt)); - - auto opt = [&m, this] (file& l, const string& t, bool com, bool exp) - { - assert (exp); - - const variable& var ( - com - ? c_export_poptions - : (t == x ? x_export_poptions : var_pool[t + ".export.poptions"])); - - append_prefixes (m, l, var); - }; - - process_libraries (bs, lo, sys_lib_dirs, - l, l.is_a (), - nullptr, nullptr, opt); - } - auto compile:: build_prefix_map (target& t, scope& bs, lorder lo) const -> prefix_map { prefix_map m; // First process the include directories from prerequisite libraries. - // Note that here we don't need to see group members (see apply()). // - for (prerequisite& p: group_prerequisites (t)) - { - target* pt (p.target); // Already searched and matched. - - if (lib* l = pt->is_a ()) - pt = &link_member (*l, lo); - else if (!pt->is_a () && !pt->is_a ()) - continue; - - append_lib_prefixes (m, *pt, bs, lo); - } + append_lib_prefixes (m, t, bs, lo); // Then process our own. // @@ -701,20 +724,9 @@ namespace build2 xc = &cast (rs[x_path]); args.push_back (xc->recall_string ()); - // Add *.export.poptions from prerequisite libraries. Note that here - // we don't need to see group members (see apply()). + // Add *.export.poptions from prerequisite libraries. // - for (prerequisite& p: group_prerequisites (t)) - { - target* pt (p.target); // Already searched and matched. - - if (lib* l = pt->is_a ()) - pt = &link_member (*l, lo); - else if (!pt->is_a () && !pt->is_a ()) - continue; - - append_lib_options (args, *pt, bs, lo); - } + append_lib_options (args, t, bs, lo); append_options (args, t, c_poptions); append_options (args, t, x_poptions); @@ -1361,7 +1373,9 @@ namespace build2 scope& bs (t.base_scope ()); scope& rs (*bs.root_scope ()); + otype ct (compile_type (t)); + lorder lo (link_order (bs, ct)); const process_path& xc (cast (rs[x_path])); cstrings args {xc.recall_string ()}; @@ -1372,21 +1386,9 @@ namespace build2 path relo (relative (t.path ())); path rels (relative (s->path ())); - // Add *.export.poptions from prerequisite libraries. Note that here we - // don't need to see group members (see apply()). + // Add *.export.poptions from prerequisite libraries. // - lorder lo (link_order (bs, ct)); - for (prerequisite& p: group_prerequisites (t)) - { - target* pt (p.target); // Already searched and matched. - - if (lib* l = pt->is_a ()) - pt = &link_member (*l, lo); - else if (!pt->is_a () && !pt->is_a ()) - continue; - - append_lib_options (args, *pt, bs, lo); - } + append_lib_options (args, t, bs, lo); append_options (args, t, c_poptions); append_options (args, t, x_poptions); diff --git a/build2/cc/link.cxx b/build2/cc/link.cxx index e6e7a98..d0e887e 100644 --- a/build2/cc/link.cxx +++ b/build2/cc/link.cxx @@ -38,7 +38,6 @@ namespace build2 { } - match_result link:: match (action a, target& t, const string& hint) const { @@ -559,6 +558,9 @@ namespace build2 file& l, bool la, scope& bs, lorder lo) const { + // Note: lack of the "small function object" optimization will really + // kill us here since we are called in a loop. + // bool win (tclass == "windows"); auto imp = [] (file&, bool la) {return la;}; @@ -734,6 +736,11 @@ namespace build2 d.args.push_back (move (o)); }; + // In case we don't have the "small function object" optimization. + // + const function impf (imp); + const function libf (lib); + for (target* pt: t.prerequisite_targets) { file* f; @@ -754,7 +761,7 @@ namespace build2 process_libraries (bs, lo, sys_lib_dirs, *f, a != nullptr, - imp, lib, nullptr); + impf, libf, nullptr); } } } -- cgit v1.1