concretizer: prioritize matching compilers over newer versions (#20020)

fixes #20019

Before this modification having a newer version of a node came
at higher priority in the optimization than having matching
compilers. This could result in unexpected configurations for
packages with conflict directives on compilers of the type:

conflicts('%gcc@X.Y:', when='@:A.B')

where changing the compiler for just that node is preferred to
lower the node version to less than 'A.B'. Now the priority has
been switched so the solver will try to lower the version of the
nodes in question before changing their compiler.
This commit is contained in:
Massimiliano Culpo 2020-11-26 13:10:48 +01:00 committed by GitHub
parent adccaa7af5
commit 03ff89fee6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 6 deletions

View file

@ -537,9 +537,6 @@ root(Dependency, 1) :- not root(Dependency), node(Dependency).
1@8,Package,Variant,Value
: variant_not_default(Package, Variant, Value, Weight), not root(Package)
}.
#minimize{
Weight@8,Package : version_weight(Package, Weight)
}.
% Try to maximize the number of compiler matches in the DAG,
% while minimizing the number of nodes. This is done because
@ -548,10 +545,15 @@ root(Dependency, 1) :- not root(Dependency), node(Dependency).
#minimize{ 1@7,Package : node(Package) }.
#maximize{ Weight@7,Package : compiler_version_match(Package, Weight) }.
% Choose more recent versions for nodes
#minimize{
Weight@6,Package : version_weight(Package, Weight)
}.
% Try to use preferred compilers
#minimize{ Weight@6,Package : compiler_weight(Package, Weight) }.
#minimize{ Weight@5,Package : compiler_weight(Package, Weight) }.
% Maximize the number of matches for targets in the DAG, try
% to select the preferred target.
#maximize{ Weight@5,Package : node_target_match(Package, Weight) }.
#minimize{ Weight@4,Package : node_target_weight(Package, Weight) }.
#maximize{ Weight@4,Package : node_target_match(Package, Weight) }.
#minimize{ Weight@3,Package : node_target_weight(Package, Weight) }.

View file

@ -923,3 +923,18 @@ def test_activating_test_dependencies(
msg = "Test dependency in package '{0}' is unexpected"
node = s[pkg_name]
assert not node.dependencies(deptype='test'), msg.format(pkg_name)
@pytest.mark.regression('20019')
def test_compiler_match_is_preferred_to_newer_version(self):
if spack.config.get('config:concretizer') == 'original':
pytest.xfail('Known failure of the original concretizer')
# This spec depends on openblas. Openblas has a conflict
# that doesn't allow newer versions with gcc@4.4.0. Check
# that an old version of openblas is selected, rather than
# a different compiler for just that node.
spec_str = 'simple-inheritance+openblas %gcc@4.4.0 os=redhat6'
s = Spec(spec_str).concretized()
assert 'openblas@0.2.13' in s
assert s['openblas'].satisfies('%gcc@4.4.0')

View file

@ -102,6 +102,15 @@ compilers:
cxxflags: -O0 -g
fflags: -O0 -g
modules: 'None'
- compiler:
spec: gcc@4.4.0
operating_system: redhat6
paths:
cc: /path/to/gcc440
cxx: /path/to/g++440
f77: /path/to/gfortran440
fc: /path/to/gfortran440
modules: 'None'
- compiler:
spec: clang@3.5
operating_system: redhat6

View file

@ -12,5 +12,10 @@ class Openblas(Package):
url = "http://github.com/xianyi/OpenBLAS/archive/v0.2.15.tar.gz"
version('0.2.15', 'b1190f3d3471685f17cfd1ec1d252ac9')
version('0.2.14', 'b1190f3d3471685f17cfd1ec1d252ac9')
version('0.2.13', 'b1190f3d3471685f17cfd1ec1d252ac9')
# See #20019 for this conflict
conflicts('%gcc@:4.4.99', when='@0.2.14:')
provides('blas')