From 14ab63f97cf34c3a43a16717ccc7a360e6bd4287 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Sun, 7 Jun 2020 11:09:18 -0700 Subject: concretizer: add a configuration option to use new or old concretizer - [x] spec.py can call out to the new concretizer - [x] config.yaml now has an option to choose a concretizer (original, clingo) --- etc/spack/defaults/config.yaml | 16 ++++++++++++++++ lib/spack/spack/config.py | 1 + lib/spack/spack/schema/config.py | 4 ++++ lib/spack/spack/spec.py | 31 ++++++++++++++++++++++++++++++- 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/etc/spack/defaults/config.yaml b/etc/spack/defaults/config.yaml index 6c5e8697b1..15ce68c68f 100644 --- a/etc/spack/defaults/config.yaml +++ b/etc/spack/defaults/config.yaml @@ -145,6 +145,20 @@ config: ccache: false + # The concretization algorithm to use in Spack. Options are: + # + # 'original': Spack's original greedy, fixed-point concretizer. This + # algorithm can make decisions too early and will not backtrack + # sufficiently for many specs. + # + # 'clingo': Uses a logic solver under the hood to solve DAGs with full + # backtracking and optimization for user preferences. + # + # 'clingo' currently requires the clingo ASP solver to be installed and + # built with python bindings. 'original' is built in. + concretizer: original + + # How long to wait to lock the Spack installation database. This lock is used # when Spack needs to manage its own package metadata and all operations are # expected to complete within the default time limit. The timeout should @@ -159,11 +173,13 @@ config: # never succeed. package_lock_timeout: null + # Control whether Spack embeds RPATH or RUNPATH attributes in ELF binaries. # Has no effect on macOS. DO NOT MIX these within the same install tree. # See the Spack documentation for details. shared_linking: 'rpath' + # Set to 'false' to allow installation on filesystems that doesn't allow setgid bit # manipulation by unprivileged user (e.g. AFS) allow_sgid: true diff --git a/lib/spack/spack/config.py b/lib/spack/spack/config.py index 393a2ebb31..531100e772 100644 --- a/lib/spack/spack/config.py +++ b/lib/spack/spack/config.py @@ -109,6 +109,7 @@ config_defaults = { 'dirty': False, 'build_jobs': min(16, multiprocessing.cpu_count()), 'build_stage': '$tempdir/spack-stage', + 'concretizer': 'original', } } diff --git a/lib/spack/spack/schema/config.py b/lib/spack/spack/schema/config.py index 7e422eb5b3..bc9575d94a 100644 --- a/lib/spack/spack/schema/config.py +++ b/lib/spack/spack/schema/config.py @@ -82,6 +82,10 @@ properties = { 'build_language': {'type': 'string'}, 'build_jobs': {'type': 'integer', 'minimum': 1}, 'ccache': {'type': 'boolean'}, + 'concretizer': { + 'type': 'string', + 'enum': ['original', 'clingo'] + }, 'db_lock_timeout': {'type': 'integer', 'minimum': 1}, 'package_lock_timeout': { 'anyOf': [ diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py index e886108df1..ab429b5e49 100644 --- a/lib/spack/spack/spec.py +++ b/lib/spack/spack/spec.py @@ -97,12 +97,14 @@ import spack.paths import spack.architecture import spack.compiler import spack.compilers as compilers +import spack.config import spack.dependency as dp import spack.error import spack.hash_types as ht import spack.parse import spack.provider_index import spack.repo +import spack.solver import spack.store import spack.util.crypto import spack.util.executable @@ -2244,7 +2246,7 @@ class Spec(object): return changed - def concretize(self, tests=False): + def _old_concretize(self, tests=False): """A spec is concrete if it describes one build of a package uniquely. This will ensure that this spec is concrete. @@ -2417,6 +2419,33 @@ class Spec(object): # there are declared inconsistencies) self.architecture.target.optimization_flags(self.compiler) + def _new_concretize(self, tests=False): + import spack.solver.asp + + if not self.name: + raise spack.error.SpecError( + "Spec has no name; cannot concretize an anonymous spec") + + result = spack.solver.asp.solve([self]) + if not result.satisfiable: + raise spack.error.UnsatisfiableSpecError( + self, "unknown", "Unsatisfiable!") + + # take the best answer + opt, i, answer = min(result.answers) + assert self.name in answer + + concretized = answer[self.name] + self._dup(concretized) + self._mark_concrete() + + #: choose your concretizer here. + def concretize(self, tests=False): + if spack.config.get('config:concretizer') == "original": + self._old_concretize(tests) + else: + self._new_concretize(tests) + def _mark_concrete(self, value=True): """Mark this spec and its dependencies as concrete. -- cgit v1.2.3-70-g09d2