aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/cc
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/cc')
-rw-r--r--libbuild2/cc/guess.cxx20
-rw-r--r--libbuild2/cc/module.cxx85
2 files changed, 69 insertions, 36 deletions
diff --git a/libbuild2/cc/guess.cxx b/libbuild2/cc/guess.cxx
index 5a2e3b3..daa9d9b 100644
--- a/libbuild2/cc/guess.cxx
+++ b/libbuild2/cc/guess.cxx
@@ -2956,8 +2956,7 @@ namespace build2
// 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;
- static mutex cache_mutex;
+ static global_cache<compiler_info> cache;
const compiler_info&
guess (const char* xm,
@@ -2988,11 +2987,8 @@ namespace build2
if (x_lo != nullptr) append_options (cs, *x_lo);
key = cs.string ();
- mlock l (cache_mutex);
-
- auto i (cache.find (key));
- if (i != cache.end ())
- return i->second;
+ if (const compiler_info* r = cache.find (key))
+ return *r;
}
// Parse the user-specified compiler id (config.x.id).
@@ -3144,15 +3140,7 @@ namespace build2
r.bin_pattern = p.directory ().representation (); // Trailing slash.
}
- // It's possible the cache entry already exists, in which case we
- // ignore our value.
- //
- // But what if the compiler information it contains is different? Well,
- // we don't generally deal with toolchain changes during the build so we
- // ignore this special case as well.
- //
- mlock l (cache_mutex);
- return cache.insert (make_pair (move (key), move (r))).first->second;
+ return cache.insert (move (key), move (r));
}
strings
diff --git a/libbuild2/cc/module.cxx b/libbuild2/cc/module.cxx
index 14182a2..8241a01 100644
--- a/libbuild2/cc/module.cxx
+++ b/libbuild2/cc/module.cxx
@@ -338,6 +338,17 @@ namespace build2
# endif
#endif
+ // Extracting search dirs can be expensive (we may need to run the
+ // compiler several times) so we cache the result.
+ //
+ struct search_dirs
+ {
+ pair<dir_paths, size_t> lib;
+ pair<dir_paths, size_t> inc;
+ };
+
+ static global_cache<search_dirs> dirs_cache;
+
void config_module::
init (scope& rs, const location& loc, const variable_map&)
{
@@ -440,33 +451,67 @@ namespace build2
pair<dir_paths, size_t> inc_dirs;
const optional<pair<dir_paths, size_t>>& mod_dirs (xi.sys_mod_dirs);
- if (xi.sys_lib_dirs)
+ if (xi.sys_lib_dirs && xi.sys_inc_dirs)
+ {
lib_dirs = *xi.sys_lib_dirs;
+ inc_dirs = *xi.sys_inc_dirs;
+ }
else
{
- switch (xi.class_)
+ string key;
{
- case compiler_class::gcc:
- lib_dirs = gcc_library_search_dirs (xi.path, rs);
- break;
- case compiler_class::msvc:
- lib_dirs = msvc_library_search_dirs (xi.path, rs);
- break;
+ sha256 cs;
+ cs.append (static_cast<size_t> (x_lang));
+ cs.append (xi.path.effect_string ());
+ append_options (cs, mode);
+ key = cs.string ();
}
- }
- if (xi.sys_inc_dirs)
- inc_dirs = *xi.sys_inc_dirs;
- else
- {
- switch (xi.class_)
+ // Because the compiler info (xi) is also cached, we can assume that
+ // if dirs come from there, then they do so consistently.
+ //
+ const search_dirs* sd (dirs_cache.find (key));
+
+ if (xi.sys_lib_dirs)
+ lib_dirs = *xi.sys_lib_dirs;
+ else if (sd != nullptr)
+ lib_dirs = sd->lib;
+ else
+ {
+ switch (xi.class_)
+ {
+ case compiler_class::gcc:
+ lib_dirs = gcc_library_search_dirs (xi.path, rs);
+ break;
+ case compiler_class::msvc:
+ lib_dirs = msvc_library_search_dirs (xi.path, rs);
+ break;
+ }
+ }
+
+ if (xi.sys_inc_dirs)
+ inc_dirs = *xi.sys_inc_dirs;
+ else if (sd != nullptr)
+ inc_dirs = sd->inc;
+ else
+ {
+ switch (xi.class_)
+ {
+ case compiler_class::gcc:
+ inc_dirs = gcc_header_search_dirs (xi.path, rs);
+ break;
+ case compiler_class::msvc:
+ inc_dirs = msvc_header_search_dirs (xi.path, rs);
+ break;
+ }
+ }
+
+ if (sd == nullptr)
{
- case compiler_class::gcc:
- inc_dirs = gcc_header_search_dirs (xi.path, rs);
- break;
- case compiler_class::msvc:
- inc_dirs = msvc_header_search_dirs (xi.path, rs);
- break;
+ search_dirs sd;
+ if (!xi.sys_lib_dirs) sd.lib = lib_dirs;
+ if (!xi.sys_inc_dirs) sd.inc = inc_dirs;
+ dirs_cache.insert (move (key), move (sd));
}
}