summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2019-10-13 23:35:57 -0700
committerTodd Gamblin <tgamblin@llnl.gov>2020-11-17 10:04:13 -0800
commitcde10692b0b12f859098cb8abe5450e72ea1a040 (patch)
tree12a67f1a99c49b1cce53fcaf7429ad0ea6d44703 /lib
parent18fba433f6fade2a2fec225ff9dd1a84dc79112e (diff)
downloadspack-cde10692b0b12f859098cb8abe5450e72ea1a040.tar.gz
spack-cde10692b0b12f859098cb8abe5450e72ea1a040.tar.bz2
spack-cde10692b0b12f859098cb8abe5450e72ea1a040.tar.xz
spack-cde10692b0b12f859098cb8abe5450e72ea1a040.zip
concretizer: prioritize versions by package pref, newest, preferred, actual
Solver now prefers newer versions like the old concretizer. Prefer package preferences from packages.yaml, preferred=True, package definition, and finally each version itself.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/solver/asp.py48
-rw-r--r--lib/spack/spack/solver/concretize.lp7
2 files changed, 53 insertions, 2 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index 05954d6335..85b42453a4 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -195,8 +195,44 @@ class AspGenerator(object):
that arise from a spec.
"""
pkg = packagize(pkg)
- for v in self.possible_versions[pkg.name]:
- self.fact(fn.version_declared(pkg.name, v))
+
+ config = spack.config.get("packages")
+ version_prefs = config.get(pkg.name, {}).get("version", {})
+ priority = dict((v, i) for i, v in enumerate(version_prefs))
+
+ # The keys below show the order of precedence of factors used
+ # to select a version when concretizing. The item with
+ # the "largest" key will be selected.
+ #
+ # NOTE: When COMPARING VERSIONS, the '@develop' version is always
+ # larger than other versions. BUT when CONCRETIZING,
+ # the largest NON-develop version is selected by default.
+ keyfn = lambda v: (
+ # ------- Special direction from the user
+ # Respect order listed in packages.yaml
+ -priority.get(v, 0),
+
+ # The preferred=True flag (packages or packages.yaml or both?)
+ pkg.versions.get(v).get('preferred', False),
+
+ # ------- Regular case: use latest non-develop version by default.
+ # Avoid @develop version, which would otherwise be the "largest"
+ # in straight version comparisons
+ not v.isdevelop(),
+
+ # Compare the version itself
+ # This includes the logic:
+ # a) develop > everything (disabled by "not v.isdevelop() above)
+ # b) numeric > non-numeric
+ # c) Numeric or string comparison
+ v)
+
+ most_to_least_preferred = sorted(
+ self.possible_versions[pkg.name], key=keyfn, reverse=True
+ )
+
+ for i, v in enumerate(most_to_least_preferred):
+ self.fact(fn.version_declared(pkg.name, v, i))
def spec_versions(self, spec):
"""Return list of clauses expressing spec's version constraints."""
@@ -718,6 +754,14 @@ def solve(specs, dump=None, models=0):
# 1 is "competition" format with just optimal answer
# 2 is JSON format with all explored answers
'--outf=1',
+ # Use a highest priority criteria-first optimization
+ # strategy, which means we'll explore recent
+ # versions, preferred packages first. This works
+ # well because Spack solutions are pretty easy to
+ # find -- there are just a lot of them. Without
+ # this, it can take a VERY long time to find good
+ # solutions, and a lot of models are explored.
+ '--opt-strategy=bb,hier',
input=program,
output=output,
error=warnings,
diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp
index e43feb4ae1..3b58cb4e80 100644
--- a/lib/spack/spack/solver/concretize.lp
+++ b/lib/spack/spack/solver/concretize.lp
@@ -6,12 +6,19 @@
% Version semantics
%-----------------------------------------------------------------------------
+% versions are declared w/priority -- declared with priority implies declared
+version_declared(P, V) :- version_declared(P, V, _).
+
% If something is a package, it has only one version and that must be a
% possible version.
1 { version(P, V) : version_possible(P, V) } 1 :- node(P).
% If a version is declared but conflicted, it's not possible.
version_possible(P, V) :- version_declared(P, V), not version_conflict(P, V).
+
+version_weight(P, V, N) :- version(P, V), version_declared(P, V, N).
+#minimize{ N@3,P,V : version_weight(P, V, N) }.
+
#defined version_conflict/2.
%-----------------------------------------------------------------------------