concretizer: handle conflicts with compiler ranges correctly
As reported, conflicts with compiler ranges were not treated correctly. This commit adds tests to verify the expected behavior for the new concretizer. The new rules to enforce a correct behavior involve: - Adding a rule to prefer the compiler selected for the root package, if no other preference is set - Give a strong negative weight to compiler preferences expressed in packages.yaml - Maximize on compiler AND compiler version match
This commit is contained in:
parent
0a56b7cfd6
commit
d00e8394f8
@ -771,9 +771,7 @@ def conflict_rules(self, pkg):
|
||||
# TODO: find a better way to generate clauses for integrity
|
||||
# TODO: constraints, instead of generating them for the body
|
||||
# TODO: of a rule and filter unwanted functions.
|
||||
to_be_filtered = [
|
||||
'node_compiler_hard', 'node_compiler_version_satisfies'
|
||||
]
|
||||
to_be_filtered = ['node_compiler_hard']
|
||||
clauses = [x for x in clauses if x.name not in to_be_filtered]
|
||||
external = fn.external(pkg.name)
|
||||
|
||||
@ -835,9 +833,10 @@ def package_compiler_defaults(self, pkg):
|
||||
ppk = spack.package_prefs.PackagePrefs(pkg.name, 'compiler', all=False)
|
||||
matches = sorted(compiler_list, key=ppk)
|
||||
|
||||
for i, cspec in enumerate(matches):
|
||||
for i, cspec in enumerate(reversed(matches)):
|
||||
self.gen.fact(fn.node_compiler_preference(
|
||||
pkg.name, cspec.name, cspec.version, i))
|
||||
pkg.name, cspec.name, cspec.version, -i * 100
|
||||
))
|
||||
|
||||
def pkg_rules(self, pkg, tests):
|
||||
pkg = packagize(pkg)
|
||||
@ -1438,7 +1437,7 @@ def setup(self, driver, specs, tests=False):
|
||||
possible = spack.package.possible_dependencies(
|
||||
*specs,
|
||||
virtuals=self.possible_virtuals,
|
||||
deptype=("build", "link", "run", "test")
|
||||
deptype=spack.dependency.all_deptypes
|
||||
)
|
||||
pkgs = set(possible)
|
||||
|
||||
|
@ -61,15 +61,22 @@ provider(Package, Virtual)
|
||||
0 { provider(Package, Virtual) : node(Package) } 1 :- virtual(Virtual).
|
||||
|
||||
% give dependents the virtuals they want
|
||||
provider_weight(Dependency, -10)
|
||||
:- virtual(Virtual), depends_on(Package, Dependency),
|
||||
provider(Dependency, Virtual),
|
||||
external(Dependency).
|
||||
|
||||
provider_weight(Dependency, Weight)
|
||||
:- virtual(Virtual), depends_on(Package, Dependency),
|
||||
provider(Dependency, Virtual),
|
||||
pkg_provider_preference(Package, Virtual, Dependency, Weight).
|
||||
pkg_provider_preference(Package, Virtual, Dependency, Weight),
|
||||
not external(Dependency).
|
||||
|
||||
provider_weight(Dependency, Weight)
|
||||
:- virtual(Virtual), depends_on(Package, Dependency),
|
||||
provider(Dependency, Virtual),
|
||||
not pkg_provider_preference(Package, Virtual, Dependency, _),
|
||||
not external(Dependency),
|
||||
default_provider_preference(Virtual, Dependency, Weight).
|
||||
|
||||
% if there's no preference for something, it costs 100 to discourage its
|
||||
@ -347,13 +354,26 @@ compiler_match(Package, 1)
|
||||
:- node_compiler(Package, Compiler),
|
||||
node_compiler_match_pref(Package, Compiler).
|
||||
|
||||
% If the compiler is what was prescribed from command line etc.
|
||||
% or is the same as a root node, there is a version match
|
||||
|
||||
% Compiler prescribed from command line
|
||||
node_compiler_version_match_pref(Package, Compiler, V)
|
||||
:- node_compiler_hard(Package, Compiler),
|
||||
node_compiler_version(Package, Compiler, V).
|
||||
|
||||
% Compiler inherited from a root node
|
||||
node_compiler_version_match_pref(Dependency, Compiler, V)
|
||||
:- depends_on(Package, Dependency),
|
||||
node_compiler_version_match_pref(Package, Compiler, V),
|
||||
not node_compiler_hard(Dependency, Compiler).
|
||||
|
||||
% Compiler inherited from the root package
|
||||
node_compiler_version_match_pref(Dependency, Compiler, V)
|
||||
:- depends_on(Package, Dependency),
|
||||
node_compiler_version(Package, Compiler, V), root(Package),
|
||||
not node_compiler_hard(Dependency, Compiler).
|
||||
|
||||
compiler_version_match(Package, 1)
|
||||
:- node_compiler_version(Package, Compiler, V),
|
||||
node_compiler_version_match_pref(Package, Compiler, V).
|
||||
@ -371,13 +391,13 @@ compiler_weight(Package, Weight)
|
||||
compiler_weight(Package, Weight)
|
||||
:- node_compiler(Package, Compiler),
|
||||
node_compiler_version(Package, Compiler, V),
|
||||
not node_compiler_preference(Package, Compiler, _, _),
|
||||
not node_compiler_preference(Package, Compiler, V, _),
|
||||
default_compiler_preference(Compiler, V, Weight).
|
||||
compiler_weight(Package, 100)
|
||||
:- node_compiler(Package, Compiler),
|
||||
node_compiler_version(Package, Compiler, Version),
|
||||
not node_compiler_preference(Package, Compiler, _, _),
|
||||
not default_compiler_preference(Compiler, _, _).
|
||||
not node_compiler_preference(Package, Compiler, Version, _),
|
||||
not default_compiler_preference(Compiler, Version, _).
|
||||
|
||||
#defined node_compiler_preference/4.
|
||||
#defined default_compiler_preference/3.
|
||||
@ -464,7 +484,7 @@ root(Dependency, 1) :- not root(Dependency), node(Dependency).
|
||||
}.
|
||||
|
||||
% compiler preferences
|
||||
#maximize{ Weight@8,Package : compiler_match(Package, Weight) }.
|
||||
#maximize{ Weight@8,Package : compiler_version_match(Package, Weight) }.
|
||||
#minimize{ Weight@7,Package : compiler_weight(Package, Weight) }.
|
||||
|
||||
% prefer more recent versions.
|
||||
|
@ -14,7 +14,7 @@
|
||||
import spack.repo
|
||||
|
||||
from spack.concretize import find_spec
|
||||
from spack.spec import Spec, CompilerSpec
|
||||
from spack.spec import Spec
|
||||
from spack.version import ver
|
||||
from spack.util.mock_package import MockPackageMultiRepo
|
||||
import spack.compilers
|
||||
@ -351,14 +351,14 @@ def test_my_dep_depends_on_provider_of_my_virtual_dep(self):
|
||||
spec.normalize()
|
||||
spec.concretize()
|
||||
|
||||
def test_compiler_inheritance(self):
|
||||
spec = Spec('mpileaks')
|
||||
spec.normalize()
|
||||
spec['dyninst'].compiler = CompilerSpec('clang')
|
||||
spec.concretize()
|
||||
# TODO: not exactly the syntax I would like.
|
||||
assert spec['libdwarf'].compiler.satisfies('clang')
|
||||
assert spec['libelf'].compiler.satisfies('clang')
|
||||
@pytest.mark.parametrize('compiler_str', [
|
||||
'clang', 'gcc', 'gcc@4.5.0', 'clang@:3.3.0'
|
||||
])
|
||||
def test_compiler_inheritance(self, compiler_str):
|
||||
spec_str = 'mpileaks %{0}'.format(compiler_str)
|
||||
spec = Spec(spec_str).concretized()
|
||||
assert spec['libdwarf'].compiler.satisfies(compiler_str)
|
||||
assert spec['libelf'].compiler.satisfies(compiler_str)
|
||||
|
||||
def test_external_package(self):
|
||||
spec = Spec('externaltool%gcc')
|
||||
@ -660,3 +660,18 @@ def test_concretize_anonymous_dep(self, spec_str):
|
||||
with pytest.raises(spack.error.SpackError):
|
||||
s = Spec(spec_str)
|
||||
s.concretize()
|
||||
|
||||
@pytest.mark.parametrize('spec_str,expected_str', [
|
||||
# Unconstrained versions select default compiler (gcc@4.5.0)
|
||||
('bowtie@1.3.0', '%gcc@4.5.0'),
|
||||
# Version with conflicts and no valid gcc select another compiler
|
||||
('bowtie@1.2.2', '%clang@3.3'),
|
||||
# If a higher gcc is available still prefer that
|
||||
('bowtie@1.2.2 os=redhat6', '%gcc@4.7.2'),
|
||||
])
|
||||
def test_compiler_conflicts_in_package_py(self, spec_str, expected_str):
|
||||
if spack.config.get('config:concretizer') == 'original':
|
||||
pytest.skip('Original concretizer cannot work around conflicts')
|
||||
|
||||
s = Spec(spec_str).concretized()
|
||||
assert s.satisfies(expected_str)
|
||||
|
15
var/spack/repos/builtin.mock/packages/bowtie/package.py
Normal file
15
var/spack/repos/builtin.mock/packages/bowtie/package.py
Normal file
@ -0,0 +1,15 @@
|
||||
# Copyright 2013-2020 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)
|
||||
class Bowtie(Package):
|
||||
"""Mock package to test conflicts on compiler ranges"""
|
||||
|
||||
homepage = "http://www.example.org"
|
||||
url = "http://bowtie-1.2.2.tar.bz2"
|
||||
|
||||
version('1.3.0', '1c837ecd990bb022d07e7aab32b09847')
|
||||
version('1.2.2', '1c837ecd990bb022d07e7aab32b09847')
|
||||
version('1.2.0', '1c837ecd990bb022d07e7aab32b09847')
|
||||
|
||||
conflicts('%gcc@:4.5.0', when='@1.2.2')
|
@ -49,7 +49,7 @@ class Akantu(CMakePackage):
|
||||
|
||||
extends('python', when='+python')
|
||||
|
||||
conflicts('gcc@:5.3.99')
|
||||
conflicts('%gcc@:5.3.99')
|
||||
conflicts('@:3.0.99 external_solvers=petsc')
|
||||
conflicts('@:3.0.99 +python')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user