summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/bootstrap.py23
-rw-r--r--lib/spack/spack/cmd/compiler.py28
-rw-r--r--lib/spack/spack/compilers/__init__.py34
-rw-r--r--lib/spack/spack/test/bootstrap.py21
-rw-r--r--lib/spack/spack/test/cmd/compiler.py12
-rw-r--r--lib/spack/spack/test/conftest.py9
6 files changed, 80 insertions, 47 deletions
diff --git a/lib/spack/spack/bootstrap.py b/lib/spack/spack/bootstrap.py
index 5d1a494065..fbfeefe92f 100644
--- a/lib/spack/spack/bootstrap.py
+++ b/lib/spack/spack/bootstrap.py
@@ -490,18 +490,20 @@ def _bootstrap_config_scopes():
return config_scopes
-@contextlib.contextmanager
-def ensure_bootstrap_configuration():
- # We may need to compile code from sources, so ensure we have compilers
- # for the current platform before switching parts.
- arch = spack.architecture.default_arch()
+def _add_compilers_if_missing():
+ # Do not use spack.architecture.default_arch() since it memoize the result
+ arch = spack.architecture.Arch(
+ spack.architecture.real_platform(), 'default_os', 'default_target'
+ )
arch = spack.spec.ArchSpec(str(arch)) # The call below expects an ArchSpec object
if not spack.compilers.compilers_for_arch(arch):
- compiler_cmd = spack.main.SpackCommand('compiler')
- compiler_cmd(
- 'find', output=os.devnull, error=os.devnull, fail_on_error=False
- )
+ new_compilers = spack.compilers.find_new_compilers()
+ if new_compilers:
+ spack.compilers.add_compilers_to_config(new_compilers, init_config=False)
+
+@contextlib.contextmanager
+def ensure_bootstrap_configuration():
bootstrap_store_path = store_path()
with spack.environment.deactivate_environment():
with spack.architecture.use_platform(spack.architecture.real_platform()):
@@ -511,6 +513,9 @@ def ensure_bootstrap_configuration():
# and builtin but accounting for platform specific scopes
config_scopes = _bootstrap_config_scopes()
with spack.config.use_configuration(*config_scopes):
+ # We may need to compile code from sources, so ensure we have
+ # compilers for the current platform before switching parts.
+ _add_compilers_if_missing()
with spack.modules.disable_modules():
with spack_python_interpreter():
yield
diff --git a/lib/spack/spack/cmd/compiler.py b/lib/spack/spack/cmd/compiler.py
index 51d3dcced3..3543025cc0 100644
--- a/lib/spack/spack/cmd/compiler.py
+++ b/lib/spack/spack/cmd/compiler.py
@@ -18,7 +18,6 @@ from llnl.util.tty.color import colorize
import spack.compilers
import spack.config
import spack.spec
-from spack.spec import ArchSpec, CompilerSpec
description = "manage compilers"
section = "system"
@@ -78,24 +77,13 @@ def compiler_find(args):
# None signals spack.compiler.find_compilers to use its default logic
paths = args.add_paths or None
- # Don't initialize compilers config via compilers.get_compiler_config.
- # Just let compiler_find do the
- # entire process and return an empty config from all_compilers
- # Default for any other process is init_config=True
- compilers = [c for c in spack.compilers.find_compilers(paths)]
- new_compilers = []
- for c in compilers:
- arch_spec = ArchSpec((None, c.operating_system, c.target))
- same_specs = spack.compilers.compilers_for_spec(
- c.spec, arch_spec, init_config=False)
-
- if not same_specs:
- new_compilers.append(c)
-
+ # Below scope=None because we want new compilers that don't appear
+ # in any other configuration.
+ new_compilers = spack.compilers.find_new_compilers(paths, scope=None)
if new_compilers:
- spack.compilers.add_compilers_to_config(new_compilers,
- scope=args.scope,
- init_config=False)
+ spack.compilers.add_compilers_to_config(
+ new_compilers, scope=args.scope, init_config=False
+ )
n = len(new_compilers)
s = 's' if n > 1 else ''
@@ -110,7 +98,7 @@ def compiler_find(args):
def compiler_remove(args):
- cspec = CompilerSpec(args.compiler_spec)
+ cspec = spack.spec.CompilerSpec(args.compiler_spec)
compilers = spack.compilers.compilers_for_spec(cspec, scope=args.scope)
if not compilers:
tty.die("No compilers match spec %s" % cspec)
@@ -128,7 +116,7 @@ def compiler_remove(args):
def compiler_info(args):
"""Print info about all compilers matching a spec."""
- cspec = CompilerSpec(args.compiler_spec)
+ cspec = spack.spec.CompilerSpec(args.compiler_spec)
compilers = spack.compilers.compilers_for_spec(cspec, scope=args.scope)
if not compilers:
diff --git a/lib/spack/spack/compilers/__init__.py b/lib/spack/spack/compilers/__init__.py
index 7959dad25b..9ecfa69393 100644
--- a/lib/spack/spack/compilers/__init__.py
+++ b/lib/spack/spack/compilers/__init__.py
@@ -192,15 +192,12 @@ def all_compiler_specs(scope=None, init_config=True):
def find_compilers(path_hints=None):
- """Returns the list of compilers found in the paths given as arguments.
+ """Return the list of compilers found in the paths given as arguments.
Args:
path_hints (list or None): list of path hints where to look for.
A sensible default based on the ``PATH`` environment variable
will be used if the value is None
-
- Returns:
- List of compilers found
"""
if path_hints is None:
path_hints = get_path('PATH')
@@ -242,6 +239,30 @@ def find_compilers(path_hints=None):
)
+def find_new_compilers(path_hints=None, scope=None):
+ """Same as ``find_compilers`` but return only the compilers that are not
+ already in compilers.yaml.
+
+ Args:
+ path_hints (list or None): list of path hints where to look for.
+ A sensible default based on the ``PATH`` environment variable
+ will be used if the value is None
+ scope (str): scope to look for a compiler. If None consider the
+ merged configuration.
+ """
+ compilers = find_compilers(path_hints)
+ compilers_not_in_config = []
+ for c in compilers:
+ arch_spec = spack.spec.ArchSpec((None, c.operating_system, c.target))
+ same_specs = compilers_for_spec(
+ c.spec, arch_spec, scope=scope, init_config=False
+ )
+ if not same_specs:
+ compilers_not_in_config.append(c)
+
+ return compilers_not_in_config
+
+
def supported_compilers():
"""Return a set of names of compilers supported by Spack.
@@ -289,8 +310,9 @@ def all_compilers(scope=None):
@_auto_compiler_spec
-def compilers_for_spec(compiler_spec, arch_spec=None, scope=None,
- use_cache=True, init_config=True):
+def compilers_for_spec(
+ compiler_spec, arch_spec=None, scope=None, use_cache=True, init_config=True
+):
"""This gets all compilers that satisfy the supplied CompilerSpec.
Returns an empty list if none are found.
"""
diff --git a/lib/spack/spack/test/bootstrap.py b/lib/spack/spack/test/bootstrap.py
index bb03df3aae..3aed7231f3 100644
--- a/lib/spack/spack/test/bootstrap.py
+++ b/lib/spack/spack/test/bootstrap.py
@@ -5,6 +5,7 @@
import pytest
import spack.bootstrap
+import spack.compilers
import spack.environment
import spack.store
import spack.util.path
@@ -78,3 +79,23 @@ def test_bootstrap_disables_modulefile_generation(mutable_config):
assert 'lmod' not in spack.config.get('modules:enable')
assert 'tcl' in spack.config.get('modules:enable')
assert 'lmod' in spack.config.get('modules:enable')
+
+
+@pytest.mark.regression('25992')
+@pytest.mark.requires_executables('gcc')
+def test_bootstrap_search_for_compilers_with_no_environment(no_compilers_yaml):
+ assert not spack.compilers.all_compiler_specs(init_config=False)
+ with spack.bootstrap.ensure_bootstrap_configuration():
+ assert spack.compilers.all_compiler_specs(init_config=False)
+ assert not spack.compilers.all_compiler_specs(init_config=False)
+
+
+@pytest.mark.regression('25992')
+@pytest.mark.requires_executables('gcc')
+def test_bootstrap_search_for_compilers_with_environment_active(
+ no_compilers_yaml, active_mock_environment
+):
+ assert not spack.compilers.all_compiler_specs(init_config=False)
+ with spack.bootstrap.ensure_bootstrap_configuration():
+ assert spack.compilers.all_compiler_specs(init_config=False)
+ assert not spack.compilers.all_compiler_specs(init_config=False)
diff --git a/lib/spack/spack/test/cmd/compiler.py b/lib/spack/spack/test/cmd/compiler.py
index 2d554c2474..cb04e9bd27 100644
--- a/lib/spack/spack/test/cmd/compiler.py
+++ b/lib/spack/spack/test/cmd/compiler.py
@@ -17,18 +17,6 @@ compiler = spack.main.SpackCommand('compiler')
@pytest.fixture
-def no_compilers_yaml(mutable_config):
- """Creates a temporary configuration without compilers.yaml"""
-
- for scope, local_config in mutable_config.scopes.items():
- compilers_yaml = os.path.join(
- local_config.path, scope, 'compilers.yaml'
- )
- if os.path.exists(compilers_yaml):
- os.remove(compilers_yaml)
-
-
-@pytest.fixture
def mock_compiler_version():
return '4.5.3'
diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py
index 456624127a..7ef3429383 100644
--- a/lib/spack/spack/test/conftest.py
+++ b/lib/spack/spack/test/conftest.py
@@ -652,6 +652,15 @@ def mutable_empty_config(tmpdir_factory, configuration_dir):
yield cfg
+@pytest.fixture
+def no_compilers_yaml(mutable_config):
+ """Creates a temporary configuration without compilers.yaml"""
+ for scope, local_config in mutable_config.scopes.items():
+ compilers_yaml = os.path.join(local_config.path, 'compilers.yaml')
+ if os.path.exists(compilers_yaml):
+ os.remove(compilers_yaml)
+
+
@pytest.fixture()
def mock_low_high_config(tmpdir):
"""Mocks two configuration scopes: 'low' and 'high'."""