aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-01-08 12:46:10 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-01-08 12:46:10 +0200
commit8b07d68462c5fec92fd5a4aab77ddfd425d1f8d0 (patch)
tree155b5d4e1789bdb2523081da12201d87d5fa4153
parentf6c3788de3d148c90aba705d045b1d92e7fea20a (diff)
Implement compiler_info caching
-rw-r--r--build2/c/init.cxx8
-rw-r--r--build2/cc/gcc.cxx4
-rw-r--r--build2/cc/guess.cxx41
-rw-r--r--build2/cc/guess.hxx2
-rw-r--r--build2/cc/module.cxx26
-rw-r--r--build2/cc/module.hxx14
-rw-r--r--build2/cc/msvc.cxx4
-rw-r--r--build2/cxx/init.cxx8
-rw-r--r--build2/utility.cxx7
-rw-r--r--build2/utility.hxx25
-rw-r--r--build2/utility.txx11
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<process_path> (rs[cm.x_path]),
cast<target_triplet> (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 </dev/null method.
//
dir_paths config_module::
- gcc_header_search_paths (process_path& xc, scope& rs) const
+ gcc_header_search_paths (const process_path& xc, scope& rs) const
{
dir_paths r;
@@ -161,7 +161,7 @@ namespace build2
// (Clang, Intel) using the -print-search-dirs option.
//
dir_paths config_module::
- gcc_library_search_paths (process_path& xc, scope& rs) const
+ gcc_library_search_paths (const process_path& xc, scope& rs) const
{
dir_paths r;
diff --git a/build2/cc/guess.cxx b/build2/cc/guess.cxx
index 32c3166..9299885 100644
--- a/build2/cc/guess.cxx
+++ b/build2/cc/guess.cxx
@@ -4,6 +4,7 @@
#include <build2/cc/guess.hxx>
+#include <map>
#include <cstring> // strlen(), strchr()
#include <build2/diagnostics.hxx>
@@ -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<string, compiler_info> 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<size_t> (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<path> (*p.first));
- ci = build2::cc::guess (x_lang,
- xc,
- cast_null<strings> (rs[config_c_poptions]),
- cast_null<strings> (rs[config_x_poptions]),
- cast_null<strings> (rs[config_c_coptions]),
- cast_null<strings> (rs[config_x_coptions]),
- cast_null<strings> (rs[config_c_loptions]),
- cast_null<strings> (rs[config_x_loptions]));
+ ci_ = &build2::cc::guess (x_lang,
+ xc,
+ cast_null<strings> (rs[config_c_poptions]),
+ cast_null<strings> (rs[config_x_poptions]),
+ cast_null<strings> (rs[config_c_coptions]),
+ cast_null<strings> (rs[config_x_coptions]),
+ cast_null<strings> (rs[config_c_loptions]),
+ cast_null<strings> (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<target_triplet> (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<process_path> (rs[cm.x_path]),
cast<target_triplet> (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 <typename T, typename F>
- 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.