diff options
-rw-r--r-- | lib/spack/spack/compilers/__init__.py | 11 | ||||
-rw-r--r-- | lib/spack/spack/concretize.py | 77 | ||||
-rw-r--r-- | lib/spack/spack/test/concretize.py | 10 |
3 files changed, 77 insertions, 21 deletions
diff --git a/lib/spack/spack/compilers/__init__.py b/lib/spack/spack/compilers/__init__.py index 771c8c0559..cb3aab9b97 100644 --- a/lib/spack/spack/compilers/__init__.py +++ b/lib/spack/spack/compilers/__init__.py @@ -230,10 +230,15 @@ def compilers_for_spec(compiler_spec, arch_spec=None, scope=None, matches = set(find(compiler_spec, scope, init_config)) compilers = [] for cspec in matches: - compilers.extend(get_compilers(cspec, config, arch_spec)) + compilers.extend(get_compilers(config, cspec, arch_spec)) return compilers +def compilers_for_arch(arch_spec, scope=None): + config = all_compilers_config(scope) + return list(get_compilers(config, arch_spec=arch_spec)) + + def compiler_from_config_entry(items): cspec = spack.spec.CompilerSpec(items['spec']) os = items.get('operating_system', None) @@ -266,12 +271,12 @@ def compiler_from_config_entry(items): environment, extra_rpaths, **compiler_flags) -def get_compilers(cspec, config, arch_spec=None): +def get_compilers(config, cspec=None, arch_spec=None): compilers = [] for items in config: items = items['compiler'] - if items['spec'] != str(cspec): + if cspec and items['spec'] != str(cspec): continue # If an arch spec is given, confirm that this compiler diff --git a/lib/spack/spack/concretize.py b/lib/spack/spack/concretize.py index 3d38f22cb6..126db8b780 100644 --- a/lib/spack/spack/concretize.py +++ b/lib/spack/spack/concretize.py @@ -315,11 +315,16 @@ class DefaultConcretizer(object): def _proper_compiler_style(cspec, aspec): return spack.compilers.compilers_for_spec(cspec, arch_spec=aspec) - all_compilers = spack.compilers.all_compiler_specs() + all_compiler_specs = spack.compilers.all_compiler_specs() + if not all_compiler_specs: + raise spack.compilers.NoCompilersError() if (spec.compiler and spec.compiler.concrete and - spec.compiler in all_compilers): + spec.compiler in all_compiler_specs): + if not _proper_compiler_style(spec.compiler, spec.architecture): + _compiler_concretization_failure( + spec.compiler, spec.architecture) return False # Find the another spec that has a compiler, or the root if none do @@ -332,22 +337,23 @@ class DefaultConcretizer(object): assert(other_spec) # Check if the compiler is already fully specified - if other_compiler in all_compilers: + if other_compiler in all_compiler_specs: spec.compiler = other_compiler.copy() + if not _proper_compiler_style(spec.compiler, spec.architecture): + _compiler_concretization_failure( + spec.compiler, spec.architecture) return True # Filter the compilers into a sorted list based on the compiler_order # from spackconfig - compiler_list = all_compilers if not other_compiler else \ + compiler_list = all_compiler_specs if not other_compiler else \ spack.compilers.find(other_compiler) + if not compiler_list: + # No compiler with a satisfactory spec was found + raise UnavailableCompilerVersionError(other_compiler) cmp_compilers = partial( pkgsort().compiler_compare, other_spec.name) matches = sorted(compiler_list, cmp=cmp_compilers) - if not matches: - arch = spec.architecture - raise UnavailableCompilerVersionError(other_compiler, - arch.platform_os, - arch.target) # copy concrete version into other_compiler try: @@ -355,10 +361,9 @@ class DefaultConcretizer(object): c for c in matches if _proper_compiler_style(c, spec.architecture)).copy() except StopIteration: - raise UnavailableCompilerVersionError( - spec.compiler, spec.architecture.platform_os, - spec.architecture.target - ) + # No compiler with a satisfactory spec has a suitable arch + _compiler_concretization_failure( + other_compiler, spec.architecture) assert(spec.compiler.concrete) return True # things changed. @@ -443,17 +448,53 @@ def find_spec(spec, condition): return None # Nothing matched the condition. +def _compiler_concretization_failure(compiler_spec, arch): + # Distinguish between the case that there are compilers for + # the arch but not with the given compiler spec and the case that + # there are no compilers for the arch at all + if not spack.compilers.compilers_for_arch(arch): + available_os_targets = set( + (c.operating_system, c.target) for c in + spack.compilers.all_compilers()) + raise NoCompilersForArchError(arch, available_os_targets) + else: + raise UnavailableCompilerVersionError(compiler_spec, arch) + + +class NoCompilersForArchError(spack.error.SpackError): + def __init__(self, arch, available_os_targets): + err_msg = ("No compilers found" + " for operating system %s and target %s." + "\nIf previous installations have succeeded, the" + " operating system may have been updated." % + (arch.platform_os, arch.target)) + + available_os_target_strs = list() + for os, t in available_os_targets: + os_target_str = "%s-%s" % (os, t) if t else os + available_os_target_strs.append(os_target_str) + err_msg += ( + "\nCompilers are defined for the following" + " operating systems and targets:\n\t" + + "\n\t".join(available_os_target_strs)) + + super(NoCompilersForArchError, self).__init__( + err_msg, "Run 'spack compiler find' to add compilers.") + + class UnavailableCompilerVersionError(spack.error.SpackError): """Raised when there is no available compiler that satisfies a compiler spec.""" - def __init__(self, compiler_spec, operating_system, target): + def __init__(self, compiler_spec, arch=None): + err_msg = "No compilers with spec %s found" % compiler_spec + if arch: + err_msg += (" for operating system %s and target %s." % + (compiler_spec, arch.platform_os, arch.target)) + super(UnavailableCompilerVersionError, self).__init__( - "No available compiler version matches '%s' on operating_system " - "'%s' for target '%s'" - % (compiler_spec, operating_system, target), - "Run 'spack compilers' to see available compiler Options.") + err_msg, "Run 'spack compiler find' to add compilers.") class NoValidVersionError(spack.error.SpackError): diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index 0cb3a34a48..f4021a89ee 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -221,6 +221,16 @@ class TestConcretize(object): with pytest.raises(spack.spec.MultipleProviderError): s.concretize() + def test_no_matching_compiler_specs(self): + s = Spec('a %gcc@0.0.0') + with pytest.raises(spack.concretize.UnavailableCompilerVersionError): + s.concretize() + + def test_no_compilers_for_arch(self): + s = Spec('a arch=linux-rhel0-x86_64') + with pytest.raises(spack.concretize.NoCompilersForArchError): + s.concretize() + def test_virtual_is_fully_expanded_for_callpath(self): # force dependence on fake "zmpi" by asking for MPI 10.0 spec = Spec('callpath ^mpi@10.0') |