summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/operating_systems/cray_frontend.py43
-rw-r--r--lib/spack/spack/test/compilers/detection.py44
2 files changed, 85 insertions, 2 deletions
diff --git a/lib/spack/spack/operating_systems/cray_frontend.py b/lib/spack/spack/operating_systems/cray_frontend.py
index 15f5b23baf..a11875ae75 100644
--- a/lib/spack/spack/operating_systems/cray_frontend.py
+++ b/lib/spack/spack/operating_systems/cray_frontend.py
@@ -5,8 +5,11 @@
import contextlib
import os
+import re
import llnl.util.filesystem as fs
+import llnl.util.lang
+import llnl.util.tty as tty
from spack.operating_systems.linux_distro import LinuxDistro
from spack.util.environment import get_path
@@ -60,6 +63,42 @@ class CrayFrontend(LinuxDistro):
This prevents from detecting Cray compiler wrappers and avoids
possible false detections.
"""
+ import spack.compilers
+
with unload_programming_environment():
- search_paths = fs.search_paths_for_executables(*get_path('PATH'))
- return search_paths
+ search_paths = get_path('PATH')
+
+ extract_path_re = re.compile(r'prepend-path[\s]*PATH[\s]*([/\w\.:-]*)')
+
+ for compiler_cls in spack.compilers.all_compiler_types():
+ # Check if the compiler class is supported on Cray
+ prg_env = getattr(compiler_cls, 'PrgEnv', None)
+ compiler_module = getattr(compiler_cls, 'PrgEnv_compiler', None)
+ if not (prg_env and compiler_module):
+ continue
+
+ # It is supported, check which versions are available
+ output = module('avail', compiler_cls.PrgEnv_compiler)
+ version_regex = r'({0})/([\d\.]+[\d]-?[\w]*)'.format(
+ compiler_cls.PrgEnv_compiler
+ )
+ matches = re.findall(version_regex, output)
+ versions = tuple(version for _, version in matches)
+
+ # Now inspect the modules and add to paths
+ msg = "[CRAY FE] Detected FE compiler [name={0}, versions={1}]"
+ tty.debug(msg.format(compiler_module, versions))
+ for v in versions:
+ try:
+ current_module = compiler_module + '/' + v
+ out = module('show', current_module)
+ match = extract_path_re.search(out)
+ search_paths += match.group(1).split(':')
+ except Exception as e:
+ msg = ("[CRAY FE] An unexpected error occurred while "
+ "detecting FE compiler [compiler={0}, "
+ " version={1}, error={2}]")
+ tty.debug(msg.format(compiler_cls.name, v, str(e)))
+
+ search_paths = list(llnl.util.lang.dedupe(search_paths))
+ return fs.search_paths_for_executables(*search_paths)
diff --git a/lib/spack/spack/test/compilers/detection.py b/lib/spack/spack/test/compilers/detection.py
index b38cf89b5d..f36e15804d 100644
--- a/lib/spack/spack/test/compilers/detection.py
+++ b/lib/spack/spack/test/compilers/detection.py
@@ -4,6 +4,9 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""Test detection of compiler version"""
import pytest
+import os
+
+import llnl.util.filesystem as fs
import spack.compilers.arm
import spack.compilers.cce
@@ -16,6 +19,9 @@ import spack.compilers.pgi
import spack.compilers.xl
import spack.compilers.xl_r
+from spack.operating_systems.cray_frontend import CrayFrontend
+import spack.util.module_cmd
+
@pytest.mark.parametrize('version_str,expected_version', [
('Arm C/C++/Fortran Compiler version 19.0 (build number 73) (based on LLVM 7.0.2)\n' # NOQA
@@ -189,3 +195,41 @@ def test_xl_version_detection(version_str, expected_version):
version = spack.compilers.xl_r.XlR.extract_version_from_output(version_str)
assert version == expected_version
+
+
+@pytest.mark.parametrize('compiler,version', [
+ ('gcc', '8.1.0'),
+ ('gcc', '1.0.0-foo'),
+ ('pgi', '19.1'),
+ ('pgi', '19.1a'),
+ ('intel', '9.0.0'),
+ ('intel', '0.0.0-foobar')
+])
+def test_cray_frontend_compiler_detection(
+ compiler, version, tmpdir, monkeypatch, working_env
+):
+ """Test that the Cray frontend properly finds compilers form modules"""
+ # setup the fake compiler directory
+ compiler_dir = tmpdir.join(compiler)
+ compiler_exe = compiler_dir.join('cc').ensure()
+ fs.set_executable(str(compiler_exe))
+
+ # mock modules
+ def _module(cmd, *args):
+ module_name = '%s/%s' % (compiler, version)
+ module_contents = 'prepend-path PATH %s' % compiler_dir
+ if cmd == 'avail':
+ return module_name if compiler in args[0] else ''
+ if cmd == 'show':
+ return module_contents if module_name in args else ''
+ monkeypatch.setattr(spack.operating_systems.cray_frontend, 'module',
+ _module)
+
+ # remove PATH variable
+ os.environ.pop('PATH', None)
+
+ # get a CrayFrontend object
+ cray_fe_os = CrayFrontend()
+
+ paths = cray_fe_os.compiler_search_paths
+ assert paths == [str(compiler_dir)]