summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/solver/asp.py2
-rw-r--r--lib/spack/spack/solver/concretize.lp78
-rw-r--r--lib/spack/spack/test/concretize.py14
-rw-r--r--lib/spack/spack/test/data/config/packages.yaml1
-rw-r--r--var/spack/repos/builtin.mock/packages/leaf-adds-virtual/package.py9
-rw-r--r--var/spack/repos/builtin.mock/packages/middle-adds-virtual/package.py7
-rw-r--r--var/spack/repos/builtin.mock/packages/root-adds-virtual/package.py8
7 files changed, 75 insertions, 44 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index 35181d69c9..2c0a072548 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -767,7 +767,7 @@ class SpackSolverSetup(object):
for i, provider in enumerate(providers):
provider_name = spack.spec.Spec(provider).name
- func(vspec, provider_name, i + 10)
+ func(vspec, provider_name, i)
def provider_defaults(self):
self.gen.h2("Default virtual providers")
diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp
index 9bc0d42516..0ee2e08a18 100644
--- a/lib/spack/spack/solver/concretize.lp
+++ b/lib/spack/spack/solver/concretize.lp
@@ -193,45 +193,37 @@ provides_virtual(Provider, Virtual) :-
%-----------------------------------------------------------------------------
% Virtual dependency weights
%-----------------------------------------------------------------------------
-% give dependents the virtuals they want
-provider_weight(Dependency, 0)
- :- 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),
- 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
-% use with minimization
-provider_weight(Dependency, 100)
- :- virtual(Virtual),
- provider(Dependency, Virtual),
- depends_on(Package, Dependency),
- not external(Dependency),
- not pkg_provider_preference(Package, Virtual, Dependency, _),
- not default_provider_preference(Virtual, Dependency, _).
-
-% Do the same for virtual roots
-provider_weight(Package, Weight)
- :- virtual_root(Virtual),
- provider(Package, Virtual),
- default_provider_preference(Virtual, Package, Weight).
-
-provider_weight(Package, 100)
- :- virtual_root(Virtual),
- provider(Package, Virtual),
- not default_provider_preference(Virtual, Package, _).
+
+% A provider may have different possible weights depending on whether it's an external
+% or not, or on preferences expressed in packages.yaml etc. This rule ensures that
+% we select the weight, among the possible ones, that minimizes the overall objective function.
+1 { provider_weight(Dependency, Virtual, Weight, Reason) :
+ possible_provider_weight(Dependency, Virtual, Weight, Reason) } 1
+ :- provider(Dependency, Virtual).
+
+% Get rid or the reason for enabling the possible weight (useful for debugging)
+provider_weight(Dependency, Virtual, Weight) :- provider_weight(Dependency, Virtual, Weight, _).
+
+% A provider that is an external can use a weight of 0
+possible_provider_weight(Dependency, Virtual, 0, "external")
+ :- provider(Dependency, Virtual),
+ external(Dependency).
+
+% A provider mentioned in packages.yaml can use a weight
+% according to its priority in the list of providers
+possible_provider_weight(Dependency, Virtual, Weight, "packages_yaml")
+ :- provider(Dependency, Virtual),
+ depends_on(Package, Dependency),
+ pkg_provider_preference(Package, Virtual, Dependency, Weight).
+
+% A provider mentioned in the default configuration can use a weight
+% according to its priority in the list of providers
+possible_provider_weight(Dependency, Virtual, Weight, "default")
+ :- provider(Dependency, Virtual),
+ default_provider_preference(Virtual, Dependency, Weight).
+
+% Any provider can use 100 as a weight, which is very high and discourage its use
+possible_provider_weight(Dependency, Virtual, 100, "fallback") :- provider(Dependency, Virtual).
#defined possible_provider/2.
#defined provider_condition/3.
@@ -747,8 +739,8 @@ opt_criterion(13, "multi-valued variants").
opt_criterion(12, "preferred providers for roots").
#minimize{ 0@12 : #true }.
#minimize{
- Weight@12,Provider
- : provider_weight(Provider, Weight), root(Provider)
+ Weight@12,Provider,Virtual
+ : provider_weight(Provider, Virtual, Weight), root(Provider)
}.
% Try to use default variants or variants that have been set
@@ -764,8 +756,8 @@ opt_criterion(11, "number of non-default variants (non-roots)").
opt_criterion(9, "preferred providers (non-roots)").
#minimize{ 0@9 : #true }.
#minimize{
- Weight@9,Provider
- : provider_weight(Provider, Weight), not root(Provider)
+ Weight@9,Provider,Virtual
+ : provider_weight(Provider, Virtual, Weight), not root(Provider)
}.
% Try to minimize the number of compiler mismatches in the DAG.
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index 757fdc2706..0becb4d55b 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -1260,3 +1260,17 @@ class TestConcretize(object):
s = spack.spec.Spec('unsat-virtual-dependency')
with pytest.raises((RuntimeError, spack.error.UnsatisfiableSpecError)):
s.concretize()
+
+ @pytest.mark.regression('23951')
+ def test_newer_dependency_adds_a_transitive_virtual(self):
+ # Ensure that a package doesn't concretize any of its transitive
+ # dependencies to an old version because newer versions pull in
+ # a new virtual dependency. The possible concretizations here are:
+ #
+ # root@1.0 <- middle@1.0 <- leaf@2.0 <- blas
+ # root@1.0 <- middle@1.0 <- leaf@1.0
+ #
+ # and "blas" is pulled in only by newer versions of "leaf"
+ s = spack.spec.Spec('root-adds-virtual').concretized()
+ assert s['leaf-adds-virtual'].satisfies('@2.0')
+ assert 'blas' in s
diff --git a/lib/spack/spack/test/data/config/packages.yaml b/lib/spack/spack/test/data/config/packages.yaml
index 496c3623cc..b2c3a33b42 100644
--- a/lib/spack/spack/test/data/config/packages.yaml
+++ b/lib/spack/spack/test/data/config/packages.yaml
@@ -2,6 +2,7 @@ packages:
all:
providers:
mpi: [openmpi, mpich]
+ blas: [openblas]
externaltool:
buildable: False
externals:
diff --git a/var/spack/repos/builtin.mock/packages/leaf-adds-virtual/package.py b/var/spack/repos/builtin.mock/packages/leaf-adds-virtual/package.py
new file mode 100644
index 0000000000..be4cc17711
--- /dev/null
+++ b/var/spack/repos/builtin.mock/packages/leaf-adds-virtual/package.py
@@ -0,0 +1,9 @@
+# Copyright 2013-2021 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 LeafAddsVirtual(Package):
+ version('2.0', sha256='abcde')
+ version('1.0', sha256='abcde')
+
+ depends_on('blas', when='@2.0')
diff --git a/var/spack/repos/builtin.mock/packages/middle-adds-virtual/package.py b/var/spack/repos/builtin.mock/packages/middle-adds-virtual/package.py
new file mode 100644
index 0000000000..884d8737c0
--- /dev/null
+++ b/var/spack/repos/builtin.mock/packages/middle-adds-virtual/package.py
@@ -0,0 +1,7 @@
+# Copyright 2013-2021 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 MiddleAddsVirtual(Package):
+ version('1.0', sha256='abcde')
+ depends_on('leaf-adds-virtual')
diff --git a/var/spack/repos/builtin.mock/packages/root-adds-virtual/package.py b/var/spack/repos/builtin.mock/packages/root-adds-virtual/package.py
new file mode 100644
index 0000000000..167a81ca67
--- /dev/null
+++ b/var/spack/repos/builtin.mock/packages/root-adds-virtual/package.py
@@ -0,0 +1,8 @@
+# Copyright 2013-2021 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 RootAddsVirtual(Package):
+ version('1.0', sha256='abcde')
+
+ depends_on('middle-adds-virtual')