From 53cb6312a84c3e310adcdaa4c531b5b86db88819 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Tue, 21 Jun 2022 02:32:13 +0200 Subject: Stricter compatibility rules for OS and compiler when reusing specs (#31170) * Stricter compatibility rules for OS and compiler when reusing specs * Add unit test --- lib/spack/spack/solver/asp.py | 1 + lib/spack/spack/solver/concretize.lp | 15 ++++++++++++--- lib/spack/spack/solver/os_facts.lp | 22 ++++++++++++++++++++++ lib/spack/spack/test/concretize.py | 22 ++++++++++++++++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 lib/spack/spack/solver/os_facts.lp diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index d9b8fae725..3b475c2c77 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -631,6 +631,7 @@ class PyclingoDriver(object): # 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") diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp index 94a4bedcfe..6f767e317c 100644 --- a/lib/spack/spack/solver/concretize.lp +++ b/lib/spack/spack/solver/concretize.lp @@ -737,9 +737,14 @@ node_os_mismatch(Package, Dependency) :- % every OS is compatible with itself. We can use `os_compatible` to declare os_compatible(OS, OS) :- os(OS). -% OS compatibility rules for reusing solves. -% catalina binaries can be used on bigsur. Direction is package -> dependency. -os_compatible("bigsur", "catalina"). +% Transitive compatibility among operating systems +os_compatible(OS1, OS3) :- os_compatible(OS1, OS2), os_compatible(OS2, OS3). + +% We can select only operating systems compatible with the ones +% for which we can build software. We need a cardinality constraint +% since we might have more than one "buildable_os(OS)" fact. +:- not 1 { os_compatible(CurrentOS, ReusedOS) : buildable_os(CurrentOS) }, + node_os(Package, ReusedOS). % If an OS is set explicitly respect the value node_os(Package, OS) :- node_os_set(Package, OS), node(Package). @@ -961,6 +966,9 @@ compiler_weight(Package, 100) not node_compiler_preference(Package, Compiler, Version, _), not default_compiler_preference(Compiler, Version, _). +% For the time being, be strict and reuse only if the compiler match one we have on the system +:- node_compiler_version(Package, Compiler, Version), not compiler_version(Compiler, Version). + #defined node_compiler_preference/4. #defined default_compiler_preference/3. @@ -1269,6 +1277,7 @@ opt_criterion(1, "non-preferred targets"). #heuristic variant_value(Package, Variant, Value) : variant_default_value(Package, Variant, Value), node(Package). [10, true] #heuristic provider(Package, Virtual) : possible_provider_weight(Package, Virtual, 0, _), virtual_node(Virtual). [10, true] #heuristic node(Package) : possible_provider_weight(Package, Virtual, 0, _), virtual_node(Virtual). [10, true] +#heuristic node_os(Package, OS) : buildable_os(OS). [10, true] %----------- % Notes diff --git a/lib/spack/spack/solver/os_facts.lp b/lib/spack/spack/solver/os_facts.lp new file mode 100644 index 0000000000..e3d322b8f6 --- /dev/null +++ b/lib/spack/spack/solver/os_facts.lp @@ -0,0 +1,22 @@ +% Copyright 2013-2022 Lawrence Livermore National Security, LLC and other +% Spack Project Developers. See the top-level COPYRIGHT file for details. +% +% SPDX-License-Identifier: (Apache-2.0 OR MIT) + +% OS compatibility rules for reusing solves. +% os_compatible(RecentOS, OlderOS) +% OlderOS binaries can be used on RecentOS + +% macOS +os_compatible("monterey", "bigsur"). +os_compatible("bigsur", "catalina"). + +% Ubuntu +os_compatible("ubuntu22.04", "ubuntu21.10"). +os_compatible("ubuntu21.10", "ubuntu21.04"). +os_compatible("ubuntu21.04", "ubuntu20.10"). +os_compatible("ubuntu20.10", "ubuntu20.04"). +os_compatible("ubuntu20.04", "ubuntu19.10"). +os_compatible("ubuntu19.10", "ubuntu19.04"). +os_compatible("ubuntu19.04", "ubuntu18.10"). +os_compatible("ubuntu18.10", "ubuntu18.04"). diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index ceb72078e6..25728a0c13 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -1786,3 +1786,25 @@ class TestConcretize(object): ]: 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') -- cgit v1.2.3-70-g09d2