summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/modules/lmod.py46
-rw-r--r--lib/spack/spack/test/modules/lmod.py23
2 files changed, 64 insertions, 5 deletions
diff --git a/lib/spack/spack/modules/lmod.py b/lib/spack/spack/modules/lmod.py
index aa41b27daa..a057f2bf3a 100644
--- a/lib/spack/spack/modules/lmod.py
+++ b/lib/spack/spack/modules/lmod.py
@@ -65,6 +65,42 @@ def make_context(spec):
return LmodContext(conf)
+def guess_core_compilers(store=False):
+ """Guesses the list of core compilers installed in the system.
+
+ Args:
+ store (bool): if True writes the core compilers to the
+ modules.yaml configuration file
+
+ Returns:
+ List of core compilers, if found, or None
+ """
+ core_compilers = []
+ for compiler_config in spack.compilers.all_compilers_config():
+ try:
+ compiler = compiler_config['compiler']
+ # A compiler is considered to be a core compiler if any of the
+ # C, C++ or Fortran compilers reside in a system directory
+ is_system_compiler = any(
+ os.path.dirname(x) in spack.util.environment.system_dirs
+ for x in compiler['paths'].values() if x is not None
+ )
+ if is_system_compiler:
+ core_compilers.append(str(compiler['spec']))
+ except (KeyError, TypeError, AttributeError):
+ continue
+
+ if store and core_compilers:
+ # If we asked to store core compilers, update the entry
+ # at 'site' scope (i.e. within the directory hierarchy
+ # of Spack itself)
+ modules_cfg = spack.config.get('modules', scope='site')
+ modules_cfg.setdefault('lmod', {})['core_compilers'] = core_compilers
+ spack.config.set('modules', modules_cfg, scope='site')
+
+ return core_compilers or None
+
+
class LmodConfiguration(BaseConfiguration):
"""Configuration class for lmod module files."""
@@ -77,12 +113,12 @@ class LmodConfiguration(BaseConfiguration):
specified in the configuration file or the sequence
is empty
"""
- value = configuration.get('core_compilers')
- if value is None:
- msg = "'core_compilers' key not found in configuration file"
- raise CoreCompilersNotFoundError(msg)
+ value = configuration.get(
+ 'core_compilers'
+ ) or guess_core_compilers(store=True)
+
if not value:
- msg = "'core_compilers' list cannot be empty"
+ msg = 'the key "core_compilers" must be set in modules.yaml'
raise CoreCompilersNotFoundError(msg)
return value
diff --git a/lib/spack/spack/test/modules/lmod.py b/lib/spack/spack/test/modules/lmod.py
index 2b3949621d..b262ab7b5b 100644
--- a/lib/spack/spack/test/modules/lmod.py
+++ b/lib/spack/spack/test/modules/lmod.py
@@ -258,3 +258,26 @@ class TestLmod(object):
writer, spec = factory('externaltool')
assert 'unknown' in writer.context.configure_options
+
+ def test_guess_core_compilers(
+ self, factory, module_configuration, monkeypatch
+ ):
+ """Check that we can guess core compilers."""
+
+ # In this case we miss the entry completely
+ module_configuration('missing_core_compilers')
+
+ # Our mock paths must be detected as system paths
+ monkeypatch.setattr(
+ spack.util.environment, 'system_dirs', ['/path/to']
+ )
+
+ # We don't want to really write into user configuration
+ # when running tests
+ def no_op_set(*args, **kwargs):
+ pass
+ monkeypatch.setattr(spack.config, 'set', no_op_set)
+
+ # Assert we have core compilers now
+ writer, _ = factory(mpileaks_spec_string)
+ assert writer.conf.core_compilers