summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/cmd/solve.py35
-rw-r--r--lib/spack/spack/concretize.py8
-rw-r--r--lib/spack/spack/environment/environment.py24
-rw-r--r--lib/spack/spack/solver/asp.py118
-rw-r--r--lib/spack/spack/spec.py23
-rw-r--r--lib/spack/spack/test/concretize.py5
6 files changed, 106 insertions, 107 deletions
diff --git a/lib/spack/spack/cmd/solve.py b/lib/spack/spack/cmd/solve.py
index 81d6ed5268..b3b9519ea5 100644
--- a/lib/spack/spack/cmd/solve.py
+++ b/lib/spack/spack/cmd/solve.py
@@ -88,11 +88,11 @@ def solve(parser, args):
'hashes': args.long or args.very_long
}
- # process dump options
- dump = re.split(r'\s*,\s*', args.show)
- if 'all' in dump:
- dump = show_options
- for d in dump:
+ # process output options
+ show = re.split(r'\s*,\s*', args.show)
+ if 'all' in show:
+ show = show_options
+ for d in show:
if d not in show_options:
raise ValueError(
"Invalid option for '--show': '%s'\nchoose from: (%s)"
@@ -105,23 +105,28 @@ def solve(parser, args):
specs = spack.cmd.parse_specs(args.specs)
# set up solver parameters
+ # Note: reuse and other concretizer prefs are passed as configuration
solver = asp.Solver()
- solver.dump = dump
- solver.models = models
- solver.timers = args.timers
- solver.stats = args.stats
-
- result = solver.solve(specs)
- if 'solutions' not in dump:
+ output = sys.stdout if "asp" in show else None
+ result = solver.solve(
+ specs,
+ out=output,
+ models=models,
+ timers=args.timers,
+ stats=args.stats,
+ setup_only=(set(show) == {'asp'})
+ )
+ if 'solutions' not in show:
return
# die if no solution was found
result.raise_if_unsat()
- # dump the solutions as concretized specs
- if 'solutions' in dump:
+ # show the solutions as concretized specs
+ if 'solutions' in show:
opt, _, _ = min(result.answers)
- if ("opt" in dump) and (not args.format):
+
+ if ("opt" in show) and (not args.format):
tty.msg("Best of %d considered solutions." % result.nmodels)
tty.msg("Optimization Criteria:")
diff --git a/lib/spack/spack/concretize.py b/lib/spack/spack/concretize.py
index de04fecffc..62a180436b 100644
--- a/lib/spack/spack/concretize.py
+++ b/lib/spack/spack/concretize.py
@@ -751,7 +751,6 @@ def _concretize_specs_together_new(*abstract_specs, **kwargs):
solver = spack.solver.asp.Solver()
solver.tests = kwargs.get('tests', False)
- solver.reuse = kwargs.get('reuse', False)
result = solver.solve(abstract_specs)
result.raise_if_unsat()
@@ -789,15 +788,10 @@ def _concretize_specs_together_original(*abstract_specs, **kwargs):
abstract_specs = [spack.spec.Spec(s) for s in abstract_specs]
concretization_repository = make_concretization_repository(abstract_specs)
- concretization_kwargs = {
- 'tests': kwargs.get('tests', False),
- 'reuse': kwargs.get('reuse', False)
- }
-
with spack.repo.additional_repository(concretization_repository):
# Spec from a helper package that depends on all the abstract_specs
concretization_root = spack.spec.Spec('concretizationroot')
- concretization_root.concretize(**concretization_kwargs)
+ concretization_root.concretize(tests=kwargs.get("tests", False))
# Retrieve the direct dependencies
concrete_specs = [
concretization_root[spec.name].copy() for spec in abstract_specs
diff --git a/lib/spack/spack/environment/environment.py b/lib/spack/spack/environment/environment.py
index 55c8af97f7..e7f51c750a 100644
--- a/lib/spack/spack/environment/environment.py
+++ b/lib/spack/spack/environment/environment.py
@@ -1083,7 +1083,7 @@ class Environment(object):
"""Returns true when the spec is built from local sources"""
return spec.name in self.dev_specs
- def concretize(self, force=False, tests=False, reuse=None):
+ def concretize(self, force=False, tests=False):
"""Concretize user_specs in this environment.
Only concretizes specs that haven't been concretized yet unless
@@ -1097,8 +1097,6 @@ class Environment(object):
already concretized
tests (bool or list or set): False to run no tests, True to test
all packages, or a list of package names to run tests for some
- reuse (bool): if True try to maximize reuse of already installed
- specs, if False don't account for installation status.
Returns:
List of specs that have been concretized. Each entry is a tuple of
@@ -1112,15 +1110,15 @@ class Environment(object):
# Pick the right concretization strategy
if self.concretization == 'together':
- return self._concretize_together(tests=tests, reuse=reuse)
+ return self._concretize_together(tests=tests)
if self.concretization == 'separately':
- return self._concretize_separately(tests=tests, reuse=reuse)
+ return self._concretize_separately(tests=tests)
msg = 'concretization strategy not implemented [{0}]'
raise SpackEnvironmentError(msg.format(self.concretization))
- def _concretize_together(self, tests=False, reuse=None):
+ def _concretize_together(self, tests=False):
"""Concretization strategy that concretizes all the specs
in the same DAG.
"""
@@ -1153,14 +1151,14 @@ class Environment(object):
self.specs_by_hash = {}
concrete_specs = spack.concretize.concretize_specs_together(
- *self.user_specs, tests=tests, reuse=reuse
+ *self.user_specs, tests=tests
)
concretized_specs = [x for x in zip(self.user_specs, concrete_specs)]
for abstract, concrete in concretized_specs:
self._add_concrete_spec(abstract, concrete)
return concretized_specs
- def _concretize_separately(self, tests=False, reuse=None):
+ def _concretize_separately(self, tests=False):
"""Concretization strategy that concretizes separately one
user spec after the other.
"""
@@ -1185,7 +1183,7 @@ class Environment(object):
):
if uspec not in old_concretized_user_specs:
root_specs.append(uspec)
- arguments.append((uspec_constraints, tests, reuse))
+ arguments.append((uspec_constraints, tests))
# Ensure we don't try to bootstrap clingo in parallel
if spack.config.get('config:concretizer') == 'clingo':
@@ -2009,7 +2007,7 @@ def display_specs(concretized_specs):
print('')
-def _concretize_from_constraints(spec_constraints, tests=False, reuse=None):
+def _concretize_from_constraints(spec_constraints, tests=False):
# Accept only valid constraints from list and concretize spec
# Get the named spec even if out of order
root_spec = [s for s in spec_constraints if s.name]
@@ -2028,7 +2026,7 @@ def _concretize_from_constraints(spec_constraints, tests=False, reuse=None):
if c not in invalid_constraints:
s.constrain(c)
try:
- return s.concretized(tests=tests, reuse=reuse)
+ return s.concretized(tests=tests)
except spack.spec.InvalidDependencyError as e:
invalid_deps_string = ['^' + d for d in e.invalid_deps]
invalid_deps = [c for c in spec_constraints
@@ -2048,9 +2046,9 @@ def _concretize_from_constraints(spec_constraints, tests=False, reuse=None):
def _concretize_task(packed_arguments):
- spec_constraints, tests, reuse = packed_arguments
+ spec_constraints, tests = packed_arguments
with tty.SuppressOutput(msg_enabled=False):
- return _concretize_from_constraints(spec_constraints, tests, reuse)
+ return _concretize_from_constraints(spec_constraints, tests)
def make_repo_path(root):
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index 1403077997..0df83191a4 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -9,7 +9,6 @@ import copy
import itertools
import os
import pprint
-import sys
import types
import warnings
@@ -474,18 +473,16 @@ def bootstrap_clingo():
class PyclingoDriver(object):
- def __init__(self, cores=True, asp=None):
+ def __init__(self, cores=True):
"""Driver for the Python clingo interface.
Arguments:
cores (bool): whether to generate unsatisfiable cores for better
error reporting.
- asp (file-like): optional stream to write a text-based ASP program
- for debugging or verification.
"""
bootstrap_clingo()
- self.out = asp or llnl.util.lang.Devnull()
+ self.out = llnl.util.lang.Devnull()
self.cores = cores
def title(self, name, char):
@@ -528,9 +525,30 @@ class PyclingoDriver(object):
self.assumptions.append(atom)
def solve(
- self, solver_setup, specs, dump=None, nmodels=0,
- timers=False, stats=False,
+ self,
+ setup,
+ specs,
+ nmodels=0,
+ timers=False,
+ stats=False,
+ out=None,
+ setup_only=False
):
+ """Set up the input and solve for dependencies of ``specs``.
+
+ Arguments:
+ setup (SpackSolverSetup): An object to set up the ASP problem.
+ specs (list): List of ``Spec`` objects to solve for.
+ nmodels (list): Number of models to consider (default 0 for unlimited).
+ timers (bool): Print out coarse timers for different solve phases.
+ stats (bool): Whether to output Clingo's internal solver statistics.
+ out: Optional output stream for the generated ASP program.
+ setup_only (bool): if True, stop after setup and don't solve (default False).
+ """
+ # allow solve method to override the output stream
+ if out is not None:
+ self.out = out
+
timer = spack.util.timer.Timer()
# Initialize the control object for the solver
@@ -545,9 +563,13 @@ class PyclingoDriver(object):
self.assumptions = []
with self.control.backend() as backend:
self.backend = backend
- solver_setup.setup(self, specs)
+ setup.setup(self, specs)
timer.phase("setup")
+ # If we're only doing setup, just return an empty solve result
+ if setup_only:
+ return Result(specs)
+
# read in the main ASP program and display logic -- these are
# handwritten, not generated, so we load them as resources
parent_dir = os.path.dirname(__file__)
@@ -2033,49 +2055,36 @@ class Solver(object):
``reuse (bool)``
Whether to try to reuse existing installs/binaries
- ``show (tuple)``
- What information to print to the console while running. Options are:
- * asp: asp program text
- * opt: optimization criteria for best model
- * output: raw clingo output
- * solutions: models found by asp program
- * all: all of the above
-
- ``models (int)``
- Number of models to search (default: 0 for unlimited)
-
- ``timers (bool)``
- Print out coarse fimers for different solve phases.
-
- ``stats (bool)``
- Print out detailed stats from clingo
-
- ``tests (bool or tuple)``
- If ``True``, concretize test dependencies for all packages. If
- a tuple of package names, concretize test dependencies for named
- packages. If ``False``, do not concretize test dependencies.
-
"""
def __init__(self):
- self.set_default_configuration()
-
- def set_default_configuration(self):
- # These properties are settable via spack configuration. `None`
- # means go with the configuration setting; user can override.
- self.reuse = None
-
- # these are concretizer settings
- self.dump = ()
- self.models = 0
- self.timers = False
- self.stats = False
- self.tests = False
+ self.driver = PyclingoDriver()
- def solve(self, specs):
- driver = PyclingoDriver()
- if "asp" in self.dump:
- driver.out = sys.stdout
+ # These properties are settable via spack configuration, and overridable
+ # by setting them directly as properties.
+ self.reuse = spack.config.get("concretizer:reuse", False)
+ def solve(
+ self,
+ specs,
+ out=None,
+ models=0,
+ timers=False,
+ stats=False,
+ tests=False,
+ setup_only=False,
+ ):
+ """
+ Arguments:
+ specs (list): List of ``Spec`` objects to solve for.
+ out: Optionally write the generate ASP program to a file-like object.
+ models (int): Number of models to search (default: 0 for unlimited).
+ timers (bool): Print out coarse fimers for different solve phases.
+ stats (bool): Print out detailed stats from clingo.
+ tests (bool or tuple): If True, concretize test dependencies for all packages.
+ If a tuple of package names, concretize test dependencies for named
+ packages (defaults to False: do not concretize test dependencies).
+ setup_only (bool): if True, stop after setup and don't solve (default False).
+ """
# Check upfront that the variants are admissible
for root in specs:
for s in root.traverse():
@@ -2083,12 +2092,15 @@ class Solver(object):
continue
spack.spec.Spec.ensure_valid_variants(s)
- if self.reuse is None:
- self.reuse = spack.config.get("concretizer:reuse", False)
-
- setup = SpackSolverSetup(reuse=self.reuse, tests=self.tests)
- return driver.solve(
- setup, specs, self.dump, self.models, self.timers, self.stats
+ setup = SpackSolverSetup(reuse=self.reuse, tests=tests)
+ return self.driver.solve(
+ setup,
+ specs,
+ nmodels=models,
+ timers=timers,
+ stats=stats,
+ out=out,
+ setup_only=setup_only,
)
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index 7a918cc0c5..bbcad6f746 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -2605,7 +2605,7 @@ class Spec(object):
msg += " For each package listed, choose another spec\n"
raise SpecDeprecatedError(msg)
- def _new_concretize(self, tests=False, reuse=None):
+ def _new_concretize(self, tests=False):
import spack.solver.asp
if not self.name:
@@ -2616,10 +2616,7 @@ class Spec(object):
return
solver = spack.solver.asp.Solver()
- solver.reuse = reuse
- solver.tests = tests
-
- result = solver.solve([self])
+ result = solver.solve([self], tests=tests)
result.raise_if_unsat()
# take the best answer
@@ -2637,23 +2634,17 @@ class Spec(object):
self._dup(concretized)
self._mark_concrete()
- def concretize(self, tests=False, reuse=None):
+ def concretize(self, tests=False):
"""Concretize the current spec.
Args:
tests (bool or list): if False disregard 'test' dependencies,
if a list of names activate them for the packages in the list,
if True activate 'test' dependencies for all packages.
- reuse (bool): if True try to maximize reuse of already installed
- specs, if False don't account for installation status.
"""
if spack.config.get('config:concretizer') == "clingo":
- self._new_concretize(tests, reuse=reuse)
+ self._new_concretize(tests)
else:
- if reuse:
- msg = ('maximizing reuse of installed specs is not '
- 'possible with the original concretizer')
- raise spack.error.SpecError(msg)
self._old_concretize(tests)
def _mark_root_concrete(self, value=True):
@@ -2678,7 +2669,7 @@ class Spec(object):
s.clear_cached_hashes()
s._mark_root_concrete(value)
- def concretized(self, tests=False, reuse=None):
+ def concretized(self, tests=False):
"""This is a non-destructive version of concretize().
First clones, then returns a concrete version of this package
@@ -2688,11 +2679,9 @@ class Spec(object):
tests (bool or list): if False disregard 'test' dependencies,
if a list of names activate them for the packages in the list,
if True activate 'test' dependencies for all packages.
- reuse (bool): if True try to maximize reuse of already installed
- specs, if False don't account for installation status.
"""
clone = self.copy(caches=True)
- clone.concretize(tests=tests, reuse=reuse)
+ clone.concretize(tests=tests)
return clone
def flat_dependencies(self, **kwargs):
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index fae852edf8..e08ef6b6aa 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -1345,7 +1345,7 @@ class TestConcretize(object):
('mpich~debug', True)
])
def test_concrete_specs_are_not_modified_on_reuse(
- self, mutable_database, spec_str, expect_installed
+ self, mutable_database, spec_str, expect_installed, config
):
if spack.config.get('config:concretizer') == 'original':
pytest.skip('Original concretizer cannot reuse specs')
@@ -1354,7 +1354,8 @@ class TestConcretize(object):
# when reused specs are added to the mix. This prevents things
# like additional constraints being added to concrete specs in
# the answer set produced by clingo.
- s = spack.spec.Spec(spec_str).concretized(reuse=True)
+ with spack.config.override("concretizer:reuse", True):
+ s = spack.spec.Spec(spec_str).concretized()
assert s.package.installed is expect_installed
assert s.satisfies(spec_str, strict=True)