Repository: spack/spack

Issue:
compiler version in spec
This is a general question that confuse me:

I have only one compiler, gcc 4.4.6 installed,  I would like to install a package, let's call it P

Why `spack install P%gcc@4.4` and `spack install P%gcc@4.4.6` install the same package twice at two different locations, using the same compiler?

What is the purpose of this behavior? I expect spack automatically complete the compiler version if it is unique or report if it is ambiguous. 


Discussion:
I'm surprised that it even works at all. In my experience (albeit only with versions of the package, not the once on the compiler) `spack` happily tries to install a `python@3` and then fails with the error that it doesn't know any `python@3`.

But I'm running rather old versions of `spack` atm, so this might already be fixed in the current HEAD
Confirmed the existence of this bug in the fairly recent commit 75fe3a5436eb46498d0adb4791ce9284ee680162. Added it to the list of the most wanted because I think it needs to be fixed rather sooner than later. @tgamblin @scheibelp 

Resolving patch:
diff --git a/lib/spack/spack/concretize.py b/lib/spack/spack/concretize.py
--- a/lib/spack/spack/concretize.py
+++ b/lib/spack/spack/concretize.py
@@ -362,7 +362,16 @@ def concretize_compiler(self, spec):
         # compiler_for_spec Should think whether this can be more
         # efficient
         def _proper_compiler_style(cspec, aspec):
-            return spack.compilers.compilers_for_spec(cspec, arch_spec=aspec)
+            compilers = spack.compilers.compilers_for_spec(
+                cspec, arch_spec=aspec
+            )
+            # If the spec passed as argument is concrete we want to check
+            # the versions match exactly
+            if (cspec.concrete and compilers and
+                cspec.version not in [c.version for c in compilers]):
+                return []
+
+            return compilers
 
         if spec.compiler and spec.compiler.concrete:
             if (self.check_for_compiler_existence and not
@@ -403,7 +412,9 @@ def _proper_compiler_style(cspec, aspec):
                     return True
                 else:
                     # No compiler with a satisfactory spec was found
-                    raise UnavailableCompilerVersionError(other_compiler)
+                    raise UnavailableCompilerVersionError(
+                        other_compiler, spec.architecture
+                    )
         else:
             # We have no hints to go by, grab any compiler
             compiler_list = spack.compilers.all_compiler_specs()


Test patch:
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -620,3 +620,16 @@ def test_adjusting_default_target_based_on_compiler(
         with spack.concretize.disable_compiler_existence_check():
             s = Spec(spec).concretized()
             assert str(s.architecture.target) == str(expected)
+
+    @pytest.mark.regression('8735,14730')
+    def test_compiler_version_matches_any_entry_in_compilers_yaml(self):
+        # Ensure that a concrete compiler with different compiler version
+        # doesn't match (here it's 4.5 vs. 4.5.0)
+        with pytest.raises(spack.concretize.UnavailableCompilerVersionError):
+            s = Spec('mpileaks %gcc@4.5')
+            s.concretize()
+
+        # An abstract compiler with a version list could resolve to 4.5.0
+        s = Spec('mpileaks %gcc@4.5:')
+        s.concretize()
+        assert str(s.compiler.version) == '4.5.0'