diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/bootstrap.py | 23 | ||||
-rw-r--r-- | lib/spack/spack/cmd/compiler.py | 28 | ||||
-rw-r--r-- | lib/spack/spack/compilers/__init__.py | 34 | ||||
-rw-r--r-- | lib/spack/spack/test/bootstrap.py | 21 | ||||
-rw-r--r-- | lib/spack/spack/test/cmd/compiler.py | 12 | ||||
-rw-r--r-- | lib/spack/spack/test/conftest.py | 9 |
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'.""" |