From 8b07d68462c5fec92fd5a4aab77ddfd425d1f8d0 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 8 Jan 2018 12:46:10 +0200 Subject: Implement compiler_info caching --- build2/c/init.cxx | 8 ++++---- build2/cc/gcc.cxx | 4 ++-- build2/cc/guess.cxx | 41 ++++++++++++++++++++++++++++++++++------- build2/cc/guess.hxx | 2 +- build2/cc/module.cxx | 26 ++++++++++++++------------ build2/cc/module.hxx | 14 +++++++++----- build2/cc/msvc.cxx | 4 ++-- build2/cxx/init.cxx | 8 ++++---- build2/utility.cxx | 7 ++++++- build2/utility.hxx | 25 +++++++++++++++---------- build2/utility.txx | 11 ++++++----- 11 files changed, 97 insertions(+), 53 deletions(-) diff --git a/build2/c/init.cxx b/build2/c/init.cxx index db512ef..a564451 100644 --- a/build2/c/init.cxx +++ b/build2/c/init.cxx @@ -306,10 +306,10 @@ namespace build2 "c.install", "c.uninstall", - cm.ci.id.value (), - cm.ci.class_, - cm.ci.version.major, - cm.ci.version.minor, + cm.ci_->id.value (), + cm.ci_->class_, + cm.ci_->version.major, + cm.ci_->version.minor, cast (rs[cm.x_path]), cast (rs[cm.x_target]), diff --git a/build2/cc/gcc.cxx b/build2/cc/gcc.cxx index ec69524..523236a 100644 --- a/build2/cc/gcc.cxx +++ b/build2/cc/gcc.cxx @@ -28,7 +28,7 @@ namespace build2 // (Clang, Intel) using the -v -E +#include #include // strlen(), strchr() #include @@ -44,12 +45,12 @@ namespace build2 // static string stdlib (lang xl, - const process_path& xc, + const process_path& xp, const strings* c_po, const strings* x_po, const strings* c_co, const strings* x_co, const char* src) { - cstrings args {xc.recall_string ()}; + cstrings args {xp.recall_string ()}; if (c_po != nullptr) append_options (args, *c_po); if (x_po != nullptr) append_options (args, *x_po); if (c_co != nullptr) append_options (args, *c_co); @@ -72,6 +73,7 @@ namespace build2 // options but that we simply leave to blow up later). // process pr (run_start (3 /* verbosity */, + xp, args.data (), -1 /* stdin */, -1 /* stdout */, @@ -268,7 +270,7 @@ namespace build2 guess_result r; - process_path xp (run_search (xc, true)); + process_path xp (run_search (xc, false /* init */)); // Note: cached. // Start with -v. This will cover gcc and clang. // @@ -601,7 +603,7 @@ namespace build2 // multi-arch support), then use the result. Otherwise, fallback to // -dumpmachine (older gcc or not multi-arch). // - cstrings args {xc.string ().c_str (), "-print-multiarch"}; + cstrings args {xp.recall_string (), "-print-multiarch"}; if (c_co != nullptr) append_options (args, *c_co); if (x_co != nullptr) append_options (args, *x_co); args.push_back (nullptr); @@ -1042,7 +1044,7 @@ namespace build2 // "Intel(R)" "64" // "Intel(R)" "MIC" (-dumpmachine says: x86_64-k1om-linux) // - cstrings args {xc.string ().c_str (), "-V"}; + cstrings args {xp.recall_string (), "-V"}; if (c_co != nullptr) append_options (args, *c_co); if (x_co != nullptr) append_options (args, *x_co); args.push_back (nullptr); @@ -1408,13 +1410,38 @@ namespace build2 move (xsl)}; } - compiler_info + // Compiler checks can be expensive (we often need to run the compiler + // several times) so we cache the result. + // + static map cache; + + const compiler_info& guess (lang xl, const path& xc, const strings* c_po, const strings* x_po, const strings* c_co, const strings* x_co, const strings* c_lo, const strings* x_lo) { + // First check the cache. + // + string key; + { + sha256 cs; + cs.append (static_cast (xl)); + cs.append (xc.string ()); + if (c_po != nullptr) hash_options (cs, *c_po); + if (x_po != nullptr) hash_options (cs, *x_po); + if (c_co != nullptr) hash_options (cs, *c_co); + if (x_co != nullptr) hash_options (cs, *x_co); + if (c_lo != nullptr) hash_options (cs, *c_lo); + if (x_lo != nullptr) hash_options (cs, *x_lo); + key = cs.string (); + + auto i (cache.find (key)); + if (i != cache.end ()) + return i->second; + } + string pre (pre_guess (xl, xc)); guess_result gr; @@ -1520,7 +1547,7 @@ namespace build2 r.bin_pattern = p.directory ().representation (); // Trailing slash. } - return r; + return (cache[key] = move (r)); } path diff --git a/build2/cc/guess.hxx b/build2/cc/guess.hxx index d6ca28d..8c291a9 100644 --- a/build2/cc/guess.hxx +++ b/build2/cc/guess.hxx @@ -202,7 +202,7 @@ namespace build2 // of fur in multiple places doesn't seem wise, especially considering // that most of it will be the same, at least for C and C++. // - compiler_info + const compiler_info& guess (lang, const path& xc, const strings* c_poptions, const strings* x_poptions, diff --git a/build2/cc/module.cxx b/build2/cc/module.cxx index 1020bd6..c56bca9 100644 --- a/build2/cc/module.cxx +++ b/build2/cc/module.cxx @@ -107,14 +107,15 @@ namespace build2 // Figure out which compiler we are dealing with, its target, etc. // const path& xc (cast (*p.first)); - ci = build2::cc::guess (x_lang, - xc, - cast_null (rs[config_c_poptions]), - cast_null (rs[config_x_poptions]), - cast_null (rs[config_c_coptions]), - cast_null (rs[config_x_coptions]), - cast_null (rs[config_c_loptions]), - cast_null (rs[config_x_loptions])); + ci_ = &build2::cc::guess (x_lang, + xc, + cast_null (rs[config_c_poptions]), + cast_null (rs[config_x_poptions]), + cast_null (rs[config_c_coptions]), + cast_null (rs[config_x_coptions]), + cast_null (rs[config_c_loptions]), + cast_null (rs[config_x_loptions])); + const compiler_info& ci (*ci_); // Split/canonicalize the target. First see if the user asked us to // use config.sub. @@ -262,6 +263,7 @@ namespace build2 { tracer trace (x, "config_init"); + const compiler_info& ci (*ci_); const target_triplet& tt (cast (rs[x_target])); // Translate x_std value (if any) to the compiler option(s) (if any). @@ -398,12 +400,12 @@ namespace build2 } } - rs.assign (x_path) = move (ci.path); + rs.assign (x_path) = process_path (ci.path, false /* init */); rs.assign (x_sys_lib_dirs) = move (lib_dirs); rs.assign (x_sys_inc_dirs) = move (inc_dirs); - rs.assign (x_signature) = move (ci.signature); - rs.assign (x_checksum) = move (ci.checksum); + rs.assign (x_signature) = ci.signature; + rs.assign (x_checksum) = ci.checksum; // config.x.{p,c,l}options // config.x.libs @@ -440,7 +442,7 @@ namespace build2 variable_map h; if (!ci.bin_pattern.empty ()) - h.assign ("config.bin.pattern") = move (ci.bin_pattern); + h.assign ("config.bin.pattern") = ci.bin_pattern; load_module (rs, rs, "cc.core.config", loc, false, h); } diff --git a/build2/cc/module.hxx b/build2/cc/module.hxx index 928e16c..de61611 100644 --- a/build2/cc/module.hxx +++ b/build2/cc/module.hxx @@ -52,20 +52,24 @@ namespace build2 size_t sys_lib_dirs_extra; // First extra path (size if none). size_t sys_inc_dirs_extra; // First extra path (size if none). - compiler_info ci; // Note: some members are moved from. + const compiler_info* ci_; private: + // Defined in gcc.cxx. + // dir_paths - gcc_header_search_paths (process_path&, scope&) const; // gcc.cxx + gcc_header_search_paths (const process_path&, scope&) const; dir_paths - gcc_library_search_paths (process_path&, scope&) const; // gcc.cxx + gcc_library_search_paths (const process_path&, scope&) const; + // Defined in msvc.cxx. + // dir_paths - msvc_header_search_paths (process_path&, scope&) const; // msvc.cxx + msvc_header_search_paths (const process_path&, scope&) const; dir_paths - msvc_library_search_paths (process_path&, scope&) const; // msvc.cxx + msvc_library_search_paths (const process_path&, scope&) const; private: bool new_; // See guess() and init() for details. diff --git a/build2/cc/msvc.cxx b/build2/cc/msvc.cxx index b418f78..1d94f66 100644 --- a/build2/cc/msvc.cxx +++ b/build2/cc/msvc.cxx @@ -86,7 +86,7 @@ namespace build2 // Extract system header search paths from MSVC. // dir_paths config_module:: - msvc_header_search_paths (process_path&, scope&) const + msvc_header_search_paths (const process_path&, scope&) const { // The compiler doesn't seem to have any built-in paths and all of them // come from the INCLUDE environment variable. @@ -105,7 +105,7 @@ namespace build2 // Extract system library search paths from MSVC. // dir_paths config_module:: - msvc_library_search_paths (process_path&, scope&) const + msvc_library_search_paths (const process_path&, scope&) const { // The linker doesn't seem to have any built-in paths and all of them // come from the LIB environment variable. diff --git a/build2/cxx/init.cxx b/build2/cxx/init.cxx index fc3bafb..ff97f5b 100644 --- a/build2/cxx/init.cxx +++ b/build2/cxx/init.cxx @@ -540,10 +540,10 @@ namespace build2 "cxx.install", "cxx.uninstall", - cm.ci.id.value (), - cm.ci.class_, - cm.ci.version.major, - cm.ci.version.minor, + cm.ci_->id.value (), + cm.ci_->class_, + cm.ci_->version.major, + cm.ci_->version.minor, cast (rs[cm.x_path]), cast (rs[cm.x_target]), diff --git a/build2/utility.cxx b/build2/utility.cxx index 4196b03..8d450df 100644 --- a/build2/utility.cxx +++ b/build2/utility.cxx @@ -208,7 +208,8 @@ namespace build2 } process - run_start (const process_path& pp, + run_start (uint16_t verbosity, + const process_path& pp, const char* args[], int in, int out, @@ -217,6 +218,10 @@ namespace build2 try { assert (args[0] == pp.recall_string ()); + + if (verb >= verbosity) + print_process (args, 0); + return process (pp, args, in, out, (err ? 2 : 1), cwd.string ().c_str ()); } catch (const process_error& e) diff --git a/build2/utility.hxx b/build2/utility.hxx index bbd6bc3..6325780 100644 --- a/build2/utility.hxx +++ b/build2/utility.hxx @@ -169,9 +169,6 @@ namespace build2 extern uint16_t verb; const uint16_t verb_never = 7; - void - print_process (const char* const*, size_t); - // Basic process utilities. // // The run*() functions with process_path assume that you are printing @@ -213,13 +210,25 @@ namespace build2 // error. // process - run_start (const process_path&, + run_start (uint16_t verbosity, + const process_path&, const char* args[], int in, int out, bool error = true, const dir_path& cwd = dir_path ()); + inline process + run_start (const process_path& pp, + const char* args[], + int in, + int out, + bool error = true, + const dir_path& cwd = dir_path ()) + { + return run_start (verb_never, pp, args, in, out, error, cwd); + } + inline void run (const process_path& p, const char* args[], @@ -249,11 +258,7 @@ namespace build2 const dir_path& cwd = dir_path ()) { process_path pp (run_search (args[0])); - - if (verb >= verbosity) - print_process (args, 0); - - return run_start (pp, args, in, out, error, cwd); + return run_start (verbosity, pp, args, in, out, error, cwd); } inline void @@ -304,7 +309,7 @@ namespace build2 sha256* checksum = nullptr); template - T + inline T run (const process_path& pp, const char* args[], F&& f, diff --git a/build2/utility.txx b/build2/utility.txx index cea44ad..0d9d342 100644 --- a/build2/utility.txx +++ b/build2/utility.txx @@ -66,11 +66,12 @@ namespace build2 bool ignore_exit, sha256* checksum) { - if (verb >= verbosity) - print_process (args, 0); - - process pr (run_start (pp, args, 0 /* stdin */, -1 /* stdout */, err)); - + process pr (run_start (verbosity, + pp, + args, + 0 /* stdin */, + -1 /* stdout */, + err)); T r; string l; // Last line of output. -- cgit v1.1