Cache compilers parsed from config files

- Spack ends up constructing compilers frequently from YAML data.

- This caches the result of parsing the compiler config

- The logic in compilers/__init__.py could use a bigger cleanup, but this
  makes concretization much faster for now.

- on macOS, this also ensures that xcrun is called only twice, as opposed
  to every time a new compiler object is constructed.
This commit is contained in:
Todd Gamblin 2017-10-12 18:37:22 -07:00
parent 2e1aa0a5e9
commit 55f85f2307

View File

@ -45,6 +45,9 @@
'extra_rpaths'] 'extra_rpaths']
_cache_config_file = [] _cache_config_file = []
#: cache of compilers constructed from config data, keyed by config entry id.
_compiler_cache = {}
def _auto_compiler_spec(function): def _auto_compiler_spec(function):
def converter(cspec_like, *args, **kwargs): def converter(cspec_like, *args, **kwargs):
@ -251,35 +254,42 @@ def compilers_for_arch(arch_spec, scope=None):
def compiler_from_config_entry(items): def compiler_from_config_entry(items):
cspec = spack.spec.CompilerSpec(items['spec']) config_id = id(items)
os = items.get('operating_system', None) compiler = _compiler_cache.get(config_id, None)
target = items.get('target', None)
if not ('paths' in items and if compiler is None:
all(n in items['paths'] for n in _path_instance_vars)): cspec = spack.spec.CompilerSpec(items['spec'])
raise InvalidCompilerConfigurationError(cspec) os = items.get('operating_system', None)
target = items.get('target', None)
cls = class_for_compiler_name(cspec.name) if not ('paths' in items and
all(n in items['paths'] for n in _path_instance_vars)):
raise InvalidCompilerConfigurationError(cspec)
compiler_paths = [] cls = class_for_compiler_name(cspec.name)
for c in _path_instance_vars:
compiler_path = items['paths'][c]
if compiler_path != 'None':
compiler_paths.append(compiler_path)
else:
compiler_paths.append(None)
mods = items.get('modules') compiler_paths = []
if mods == 'None': for c in _path_instance_vars:
mods = [] compiler_path = items['paths'][c]
if compiler_path != 'None':
compiler_paths.append(compiler_path)
else:
compiler_paths.append(None)
alias = items.get('alias', None) mods = items.get('modules')
compiler_flags = items.get('flags', {}) if mods == 'None':
environment = items.get('environment', {}) mods = []
extra_rpaths = items.get('extra_rpaths', [])
return cls(cspec, os, target, compiler_paths, mods, alias, alias = items.get('alias', None)
environment, extra_rpaths, **compiler_flags) compiler_flags = items.get('flags', {})
environment = items.get('environment', {})
extra_rpaths = items.get('extra_rpaths', [])
compiler = cls(cspec, os, target, compiler_paths, mods, alias,
environment, extra_rpaths, **compiler_flags)
_compiler_cache[id(items)] = compiler
return compiler
def get_compilers(config, cspec=None, arch_spec=None): def get_compilers(config, cspec=None, arch_spec=None):