Repository: spack/spack

Issue:
Spack fails to install zlib on Ubuntu 20.04 when reusing specs from v0.18 mirror
### Steps to reproduce

Start a container:
```console
$ docker pull ghcr.io/spack/ubuntu-focal:latest
[ ... ]
4f4fb700ef54: Pull complete 
539a8da1363c: Pull complete 
Digest: sha256:1ba749c5389997d86070cebed4ea430259fbcc44aae9363f87e167c8ba585186
Status: Downloaded newer image for ghcr.io/spack/ubuntu-focal:latest
ghcr.io/spack/ubuntu-focal:latest
$ docker run -it --rm ghcr.io/spack/ubuntu-focal:latest
```
From within the container:
```console
root@9a6485bdd519:~# spack compiler list
==> Available compilers
-- gcc ubuntu20.04-x86_64 ---------------------------------------
gcc@9.4.0
root@9a6485bdd519:~# spack mirror add binary_mirror  https://binaries.spack.io/releases/v0.18
root@9a6485bdd519:~# spack buildcache keys --install --trust
==> Fetching https://binaries.spack.io/releases/v0.18/build_cache/_pgp/2C8DD3224EF3573A42BD221FA8E0CA3C1C2ADA2F.pub
gpg: key A8E0CA3C1C2ADA2F: 7 signatures not checked due to missing keys
gpg: key A8E0CA3C1C2ADA2F: public key "Spack Project Official Binaries <maintainers@spack.io>" imported
gpg: Total number processed: 1
gpg:               imported: 1
gpg: no ultimately trusted keys found
gpg: inserting ownertrust of 6
root@9a6485bdd519:~# spack solve zlib
==> Best of 3 considered solutions.
==> Optimization Criteria:
  Priority  Criterion                                            Installed  ToBuild
  1         number of input specs not concretized                        -        0
  2         number of packages to build (vs. reuse)                      -        0
  3         deprecated versions used                                     0        0
  4         version weight                                               0        0
  5         number of non-default variants (roots)                       1        0
  6         preferred providers for roots                                0        0
  7         default values of variants not being used (roots)            0        0
  8         number of non-default variants (non-roots)                   0        0
  9         preferred providers (non-roots)                              0        0
  10        compiler mismatches                                          0        0
  11        OS mismatches                                                0        0
  12        non-preferred OS's                                           1        0
  13        version badness                                              0        0
  14        default values of variants not being used (non-roots)        0        0
  15        non-preferred compilers                                    100        0
  16        target mismatches                                            0        0
  17        non-preferred targets                                       46        0

zlib@1.2.12%clang@7.0.0+optimize+pic+shared patches=0d38234 arch=linux-ubuntu18.04-x86_64
```
Note that Spack wants to install an Ubuntu 18.04 binary built with `clang@7.0.0` on an Ubuntu 20.04 with GCC 9.4.0


### Error message

If we try to install this is what happens:
```console
root@9a6485bdd519:~# spack install zlib
==> Error: No valid version for 'llvm' satisfies '@7.0.0'
```
which is really not very informative on why `zlib` was not installed.

### Information on your system

* **Spack:** 0.19.0.dev0
* **Python:** 3.8.10
* **Platform:** linux-ubuntu20.04-icelake
* **Concretizer:** clingo

Docker image:
```
latest: Pulling from spack/ubuntu-focal
d7bfe07ed847: Pull complete 
98e022cc2e0d: Pull complete 
4b12514f808d: Pull complete 
0ce4dac69a12: Pull complete 
37d4c5f214f0: Pull complete 
a31a74ffdcb6: Pull complete 
4f4fb700ef54: Pull complete 
539a8da1363c: Pull complete 
Digest: sha256:1ba749c5389997d86070cebed4ea430259fbcc44aae9363f87e167c8ba585186
Status: Downloaded newer image for ghcr.io/spack/ubuntu-focal:latest
```

### 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:
Should be solvable by something similar to:
```
% We can select only operating systems compatible with the one we are currently on
:- not os_compatible(CurrentOS, ReusedOS),
   buildable_os(CurrentOS),
   node_os(Package, ReusedOS).
```
added to `concretize.lp`.

Resolving patch:
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -631,6 +631,7 @@ def visit(node):
 
         # Load the file itself
         self.control.load(os.path.join(parent_dir, 'concretize.lp'))
+        self.control.load(os.path.join(parent_dir, "os_facts.lp"))
         self.control.load(os.path.join(parent_dir, "display.lp"))
         timer.phase("load")
 


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
@@ -1786,3 +1786,25 @@ def test_version_weight_and_provenance(self):
             ]:
                 assert criterion in result.criteria
             assert result.specs[0].satisfies('^b@1.0')
+
+    @pytest.mark.regression('31169')
+    def test_not_reusing_incompatible_os_or_compiler(self):
+        import spack.solver.asp
+        if spack.config.get('config:concretizer') == 'original':
+            pytest.skip('Original concretizer cannot reuse')
+
+        root_spec = spack.spec.Spec('b')
+        s = root_spec.concretized()
+        wrong_compiler, wrong_os = s.copy(), s.copy()
+        wrong_compiler.compiler = spack.spec.CompilerSpec('gcc@12.1.0')
+        wrong_os.architecture = spack.spec.ArchSpec('test-ubuntu2204-x86_64')
+        reusable_specs = [wrong_compiler, wrong_os]
+        with spack.config.override("concretizer:reuse", True):
+            solver = spack.solver.asp.Solver()
+            setup = spack.solver.asp.SpackSolverSetup()
+            result = solver.driver.solve(
+                setup, [root_spec], reuse=reusable_specs, out=sys.stdout
+            )
+        concrete_spec = result.specs[0]
+        assert concrete_spec.satisfies('%gcc@4.5.0')
+        assert concrete_spec.satisfies('os=debian6')