Stricter compatibility rules for OS and compiler when reusing specs (#31170)

* Stricter compatibility rules for OS and compiler when reusing specs
* Add unit test
This commit is contained in:
Massimiliano Culpo 2022-06-21 02:32:13 +02:00 committed by GitHub
parent d95f53e1ac
commit aebb601b70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 3 deletions

View File

@ -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")

View File

@ -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

View File

@ -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").

View File

@ -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')