Repository: spack/spack

Issue:
lmod generation broken for llvm
### Steps to reproduce

enable lmod generation in modules.yaml
```console
spack install llvm
```
install will fail when module file generation fails.

Issue seems to be that the spec for the package isn't concertized when it tries to call .version on the  CompilerSpec that gets passed in for value. I'm not sure why though. Might be related to #36273, I'm working on a bisect right now, but hoping someone will pop in before that.

### Error message

```console
....
lib/spack/spack/config.py:996 ==> [2023-05-10-21:40:49.480072] Reading config from file /root/spack/etc/spack/defaults/modules.yaml
lib/spack/spack/config.py:996 ==> [2023-05-10-21:40:49.491953] Reading config from file /root/spack/etc/spack/defaults/linux/modules.yaml
lib/spack/spack/config.py:996 ==> [2023-05-10-21:40:49.493759] Reading config from file /root/.spack/modules.yaml
lib/spack/spack/hooks/module_file_generation.py:19 ==> [2023-05-10-21:40:49.495847] NO MODULE WRITTEN: list of enabled module files is empty
lib/spack/spack/modules/common.py:875 ==> [2023-05-10-21:40:49.503087]  WRITE: llvm@16.0.2%gcc@=11.2.1+clang+compiler-rt~cuda~flang+gold+internal_unwind~ipo+libcxx~link_llvm_dylib+lld+lldb+llvm_dylib~mlir+omp_as_runtime~omp_debug~omp_tsan+polly~python~split_dwarf~z3~zstd build_system=cmake build_type=Release generator=ninja shlib_symbol_version=none targets=none version_suffix=none arch=linux-rhel9-zen2/vdehamq [/root/spack/share/spack/lmod/linux-rhel9-x86_64/Core/llvm/16.0.2-vdehamq.lua]
lib/spack/spack/error.py:54 ==> [2023-05-10-21:40:49.560046] Error: SpecError: Spec is not concrete: clang@16.0.2
See build log for details:
  /tmp/root/spack-stage/spack-stage-llvm-16.0.2-vdehamqhopo3teuma4gf5opdgqk7nzue/spack-build-out.txt

Traceback (most recent call last):
  File "/root/spack/lib/spack/spack/build_environment.py", line 1051, in _setup_pkg_and_run
    return_value = function(pkg, kwargs)
  File "/root/spack/lib/spack/spack/installer.py", line 2089, in build_process
    return installer.run()
  File "/root/spack/lib/spack/spack/installer.py", line 1958, in run
    spack.hooks.post_install(self.pkg.spec, self.explicit)
  File "/root/spack/lib/spack/spack/hooks/__init__.py", line 74, in __call__
    hook(*args, **kwargs)
  File "/root/spack/lib/spack/spack/hooks/module_file_generation.py", line 41, in post_install
    _for_each_enabled(spec, "write", explicit)
  File "/root/spack/lib/spack/spack/hooks/module_file_generation.py", line 25, in _for_each_enabled
    getattr(generator, method_name)()
  File "/root/spack/lib/spack/spack/modules/common.py", line 903, in write
    context = self.context.to_dict()
  File "/root/spack/lib/spack/spack/tengine.py", line 65, in to_dict
    d = [(name, getattr(self, name)) for name in self.context_properties]
  File "/root/spack/lib/spack/spack/tengine.py", line 65, in <listcomp>
    d = [(name, getattr(self, name)) for name in self.context_properties]
  File "/root/spack/lib/spack/spack/modules/lmod.py", line 430, in unlocked_paths
    return [os.path.join(*parts) for parts in layout.unlocked_paths[None]]
  File "/root/spack/lib/spack/spack/modules/lmod.py", line 352, in unlocked_paths
    parts = [self.token_to_path(x, available[x]) for x in ac]
  File "/root/spack/lib/spack/spack/modules/lmod.py", line 352, in <listcomp>
    parts = [self.token_to_path(x, available[x]) for x in ac]
  File "/root/spack/lib/spack/spack/modules/lmod.py", line 292, in token_to_path
    return path_part_fmt.format(token=value)
  File "/root/spack/lib/spack/spack/spec.py", line 648, in version
    raise spack.error.SpecError("Spec is not concrete: " + str(self))
spack.error.SpecError: Spec is not concrete: clang@16.0.2
lib/spack/spack/installer.py:1470 ==> [2023-05-10-21:40:49.560372] Flagging llvm-16.0.2-vdehamqhopo3teuma4gf5opdgqk7nzue as failed: SpecError: Spec is not concrete: clang@16.0.2
lib/spack/spack/main.py:1007 ==> [2023-05-10-21:40:50.625463] ChildError: SpecError: Spec is not concrete: clang@16.0.2
```

similarly if you have an already installed llvm with lua module generation disabled and try to generate a module:
```console
bin/spack --debug --stacktrace module lmod refresh -y llvm
lib/spack/spack/cmd/__init__.py:123 ==> [2023-05-10-21:44:11.368398] Imported module from built-in commands
lib/spack/spack/cmd/__init__.py:123 ==> [2023-05-10-21:44:11.371417] Imported module from built-in commands
lib/spack/spack/config.py:996 ==> [2023-05-10-21:44:11.374955] Reading config from file /root/spack/etc/spack/defaults/config.yaml
lib/spack/spack/database.py:391 ==> [2023-05-10-21:44:11.396977] DATABASE LOCK TIMEOUT: 60s
lib/spack/spack/database.py:397 ==> [2023-05-10-21:44:11.397129] PACKAGE LOCK TIMEOUT: No timeout
lib/spack/spack/config.py:996 ==> [2023-05-10-21:44:11.402304] Reading config from file /root/spack/etc/spack/defaults/repos.yaml
lib/spack/spack/config.py:996 ==> [2023-05-10-21:44:11.499408] Reading config from file /root/spack/etc/spack/defaults/modules.yaml
lib/spack/spack/config.py:996 ==> [2023-05-10-21:44:11.511379] Reading config from file /root/spack/etc/spack/defaults/linux/modules.yaml
lib/spack/spack/config.py:996 ==> [2023-05-10-21:44:11.513263] Reading config from file /root/.spack/modules.yaml
lib/spack/spack/config.py:996 ==> [2023-05-10-21:44:11.563658] Reading config from file /root/spack/etc/spack/defaults/packages.yaml
lib/spack/spack/cmd/modules/__init__.py:339 ==> [2023-05-10-21:44:11.669827] Regenerating lmod module files
lib/spack/spack/modules/common.py:875 ==> [2023-05-10-21:44:11.713137]  WRITE: llvm@11.1.0%gcc@=11.2.1+clang+compiler-rt~cuda~flang+gold+internal_unwind~ipo+libcxx~link_llvm_dylib+lld+lldb+llvm_dylib~mlir~omp_debug~omp_tsan+polly~python~split_dwarf~z3 build_system=cmake build_type=Release generator=ninja patches=1b1f41a,4728466,514926d,6811ad4,7b286b1,f920173 targets=none version_suffix=none arch=linux-rhel9-zen2/ehut2k4 [/root/spack/share/spack/lmod/linux-rhel9-x86_64/Core/llvm/11.1.0-ehut2k4.lua]
lib/spack/spack/cmd/modules/__init__.py:352 ==> [2023-05-10-21:44:11.785526] SpecError: Spec is not concrete: clang@11.1.0
lib/spack/spack/cmd/modules/__init__.py:354 ==> [2023-05-10-21:44:11.788616] Warning: Could not write module file [/root/spack/share/spack/lmod/linux-rhel9-x86_64/Core/llvm/11.1.0-ehut2k4.lua]
lib/spack/spack/cmd/modules/__init__.py:355 ==> [2023-05-10-21:44:11.788705] Warning:   --> Spec is not concrete: clang@11.1.0 <--
```

### Information on your system

* **Spack:** 0.20.0.dev0 (f51a4a1ae1b78f91feff07f34619ea410be21033)
* **Python:** 3.9.10
* **Platform:** linux-rhel9-zen2
* **Concretizer:** clingo


### General information

- [X] I have run `spack debug report` and reported the version of Spack/Python/Platform
- [X] I have searched the issues of this repo and believe this is not a duplicate
- [X] I have run the failing commands in debug mode and reported the output


Discussion:
Actually outside of my container I'm unable to reproduce this right now. Investigating.
Ah, no it is fa7719a031e5da11d0e8f1afad097e2e1d47aae3 that breaks it, I'd checked out f6497972b863f5b5a0c0a774388f3e1404635603 with my last attempt thinking I was on master.

Resolving patch:
diff --git a/lib/spack/spack/modules/lmod.py b/lib/spack/spack/modules/lmod.py
--- a/lib/spack/spack/modules/lmod.py
+++ b/lib/spack/spack/modules/lmod.py
@@ -197,11 +197,11 @@ def provides(self):
 
         # If it is in the list of supported compilers family -> compiler
         if self.spec.name in spack.compilers.supported_compilers():
-            provides["compiler"] = spack.spec.CompilerSpec(self.spec.format("{name}{@version}"))
+            provides["compiler"] = spack.spec.CompilerSpec(self.spec.format("{name}{@versions}"))
         elif self.spec.name in spack.compilers.package_name_to_compiler_name:
             # If it is the package for a supported compiler, but of a different name
             cname = spack.compilers.package_name_to_compiler_name[self.spec.name]
-            provides["compiler"] = spack.spec.CompilerSpec("%s@%s" % (cname, self.spec.version))
+            provides["compiler"] = spack.spec.CompilerSpec(cname, self.spec.versions)
 
         # All the other tokens in the hierarchy must be virtual dependencies
         for x in self.hierarchy_tokens:


Test patch:
diff --git a/lib/spack/spack/test/modules/lmod.py b/lib/spack/spack/test/modules/lmod.py
--- a/lib/spack/spack/test/modules/lmod.py
+++ b/lib/spack/spack/test/modules/lmod.py
@@ -95,7 +95,7 @@ def test_compilers_provided_different_name(self, factory, module_configuration):
         provides = module.conf.provides
 
         assert "compiler" in provides
-        assert provides["compiler"] == spack.spec.CompilerSpec("oneapi@3.0")
+        assert provides["compiler"] == spack.spec.CompilerSpec("oneapi@=3.0")
 
     def test_simple_case(self, modulefile_content, module_configuration):
         """Tests the generation of a simple Lua module file."""