summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@gmail.com>2021-05-12 16:17:38 +0200
committerGitHub <noreply@github.com>2021-05-12 07:17:38 -0700
commitfc2ac099cddc8896f0741091b6be96d4379fd5e2 (patch)
tree1397ee5e5cb0c6aa365b7dde52db8d43e29d3b8d /lib
parentb768d7bb09b6913bd1885e7e57654a75bba6fdf3 (diff)
downloadspack-fc2ac099cddc8896f0741091b6be96d4379fd5e2.tar.gz
spack-fc2ac099cddc8896f0741091b6be96d4379fd5e2.tar.bz2
spack-fc2ac099cddc8896f0741091b6be96d4379fd5e2.tar.xz
spack-fc2ac099cddc8896f0741091b6be96d4379fd5e2.zip
ASP-based solver: account for deprecated versions (#23491)
fixes #22351 The ASP-based solver now accounts for the presence in the DAG of deprecated versions and tries to minimize their number at highest priority.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/solver/asp.py16
-rw-r--r--lib/spack/spack/solver/concretize.lp9
-rw-r--r--lib/spack/spack/solver/display.lp3
-rw-r--r--lib/spack/spack/test/concretize.py16
4 files changed, 43 insertions, 1 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index 8fb426c325..99e556a764 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -411,6 +411,7 @@ class SpackSolverSetup(object):
self.gen = None # set by setup()
self.possible_versions = {}
self.versions_in_package_py = {}
+ self.deprecated_versions = {}
self.versions_from_externals = {}
self.possible_virtuals = None
self.possible_compilers = []
@@ -481,6 +482,11 @@ class SpackSolverSetup(object):
for i, v in enumerate(most_to_least_preferred):
self.gen.fact(fn.version_declared(pkg.name, v, i))
+ # Declare deprecated versions for this package, if any
+ deprecated = self.deprecated_versions[pkg.name]
+ for v in sorted(deprecated):
+ self.gen.fact(fn.deprecated_version(pkg.name, v))
+
def spec_versions(self, spec):
"""Return list of clauses expressing spec's version constraints."""
spec = specify(spec)
@@ -1020,12 +1026,16 @@ class SpackSolverSetup(object):
self.possible_versions = collections.defaultdict(set)
self.versions_in_package_py = collections.defaultdict(set)
self.versions_from_externals = collections.defaultdict(set)
+ self.deprecated_versions = collections.defaultdict(set)
for pkg_name in possible_pkgs:
pkg = spack.repo.get(pkg_name)
- for v in pkg.versions:
+ for v, version_info in pkg.versions.items():
self.versions_in_package_py[pkg_name].add(v)
self.possible_versions[pkg_name].add(v)
+ deprecated = version_info.get('deprecated', False)
+ if deprecated:
+ self.deprecated_versions[pkg_name].add(v)
for spec in specs:
for dep in spec.traverse():
@@ -1553,6 +1563,10 @@ class SpecBuilder(object):
check_same_flags(spec.compiler_flags, flags)
spec.compiler_flags.update(flags)
+ def deprecated(self, pkg, version):
+ msg = 'using "{0}@{1}" which is a deprecated version'
+ tty.warn(msg.format(pkg, version))
+
def build_specs(self, function_tuples):
# Functions don't seem to be in particular order in output. Sort
# them here so that directives that build objects (like node and
diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp
index 8b5671ee4e..ec0d4fdf5a 100644
--- a/lib/spack/spack/solver/concretize.lp
+++ b/lib/spack/spack/solver/concretize.lp
@@ -19,6 +19,9 @@ version_declared(Package, Version) :- version_declared(Package, Version, _).
1 { version(Package, Version) : version_declared(Package, Version) } 1
:- node(Package).
+% If we select a deprecated version, mark the package as deprecated
+deprecated(Package, Version) :- version(Package, Version), deprecated_version(Package, Version).
+
possible_version_weight(Package, Weight)
:- version(Package, Version), version_declared(Package, Version, Weight),
not preferred_version_declared(Package, Version, _).
@@ -37,6 +40,7 @@ version_satisfies(Package, Constraint)
#defined preferred_version_declared/3.
#defined version_satisfies/3.
+#defined deprecated_version/2.
%-----------------------------------------------------------------------------
% Spec conditions and imposed constraints
@@ -696,6 +700,11 @@ no_flags(Package, FlagType)
% 2. a `#minimize{ 0@2 : #true }.` statement that ensures the criterion
% is displayed (clingo doesn't display sums over empty sets by default)
+% Minimize the number of deprecated versions being used
+opt_criterion(16, "deprecated versions used").
+#minimize{ 0@16 : #true }.
+#minimize{ 1@16,Package : deprecated(Package, _)}.
+
% The highest priority is to minimize the:
% 1. Version weight
% 2. Number of variants with a non default value, if not set
diff --git a/lib/spack/spack/solver/display.lp b/lib/spack/spack/solver/display.lp
index c1231ca62a..818ce2d90a 100644
--- a/lib/spack/spack/solver/display.lp
+++ b/lib/spack/spack/solver/display.lp
@@ -28,3 +28,6 @@
% names of optimization criteria
#show opt_criterion/2.
+
+% deprecated packages
+#show deprecated/2.
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index fd97c8684f..f392387099 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -1228,3 +1228,19 @@ class TestConcretize(object):
for constraint, value in expected_dict.items():
assert s.satisfies(constraint) == value
+
+ @pytest.mark.regression('22351')
+ @pytest.mark.parametrize('spec_str,expected', [
+ # Version 1.1.0 is deprecated and should not be selected, unless we
+ # explicitly asked for that
+ ('deprecated-versions', ['deprecated-versions@1.0.0']),
+ ('deprecated-versions@1.1.0', ['deprecated-versions@1.1.0']),
+ ])
+ def test_deprecated_versions_not_selected(self, spec_str, expected):
+ if spack.config.get('config:concretizer') == 'original':
+ pytest.xfail('Known failure of the original concretizer')
+
+ s = Spec(spec_str).concretized()
+
+ for abstract_spec in expected:
+ assert abstract_spec in s