summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@gmail.com>2020-10-22 14:26:11 +0200
committerTodd Gamblin <tgamblin@llnl.gov>2020-11-17 10:04:13 -0800
commitae1ef85af5a4419eef83ed9f4f112770543d999d (patch)
treecd235bbb18d2f6559cfa1fcb5c190ec0f514e430 /lib
parent346beedfd40fe97f302645377cf90dbd916b44fd (diff)
downloadspack-ae1ef85af5a4419eef83ed9f4f112770543d999d.tar.gz
spack-ae1ef85af5a4419eef83ed9f4f112770543d999d.tar.bz2
spack-ae1ef85af5a4419eef83ed9f4f112770543d999d.tar.xz
spack-ae1ef85af5a4419eef83ed9f4f112770543d999d.zip
concretizer: account for test dependencies only when required
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/solver/asp.py26
-rw-r--r--lib/spack/spack/spec.py2
-rw-r--r--lib/spack/spack/test/spec_dag.py49
3 files changed, 38 insertions, 39 deletions
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index 55e18e88e8..264ab9e54b 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -593,8 +593,10 @@ class PyclingoDriver(object):
self.backend.add_rule([], [head_atom, more_than_1])
self.backend.add_rule([], [head_atom, -at_least_1])
- def solve(self, solver_setup, specs, dump=None, nmodels=0,
- timers=False, stats=False):
+ def solve(
+ self, solver_setup, specs, dump=None, nmodels=0,
+ timers=False, stats=False, tests=False
+ ):
timer = Timer()
# Initialize the control object for the solver
@@ -607,7 +609,7 @@ class PyclingoDriver(object):
self.assumptions = []
with self.control.backend() as backend:
self.backend = backend
- solver_setup.setup(self, specs)
+ solver_setup.setup(self, specs, tests=tests)
timer.phase("setup")
# read in the main ASP program and display logic -- these are
@@ -837,7 +839,7 @@ class SpackSolverSetup(object):
self.gen.fact(fn.node_compiler_preference(
pkg.name, cspec.name, cspec.version, i))
- def pkg_rules(self, pkg):
+ def pkg_rules(self, pkg, tests):
pkg = packagize(pkg)
# versions
@@ -888,7 +890,7 @@ class SpackSolverSetup(object):
self.package_compiler_defaults(pkg)
# dependencies
- self.package_dependencies_rules(pkg)
+ self.package_dependencies_rules(pkg, tests)
# virtual preferences
self.virtual_preferences(
@@ -898,7 +900,7 @@ class SpackSolverSetup(object):
)
)
- def package_dependencies_rules(self, pkg):
+ def package_dependencies_rules(self, pkg, tests):
"""Translate 'depends_on' directives into ASP logic."""
for name, conditions in sorted(pkg.dependencies.items()):
for cond, dep in sorted(conditions.items()):
@@ -906,6 +908,10 @@ class SpackSolverSetup(object):
named_cond.name = named_cond.name or pkg.name
for t in sorted(dep.type):
+ # Skip test dependencies if they're not requested
+ if t == 'test' and (not tests or pkg.name not in tests):
+ continue
+
if cond == spack.spec.Spec():
self.gen.fact(
fn.declared_dependency(
@@ -1411,7 +1417,7 @@ class SpackSolverSetup(object):
)
self.gen.newline()
- def setup(self, driver, specs):
+ def setup(self, driver, specs, tests=False):
"""Generate an ASP program with relevant constraints for specs.
This calls methods on the solve driver to set up the problem with
@@ -1464,7 +1470,7 @@ class SpackSolverSetup(object):
self.gen.h1('Package Constraints')
for pkg in sorted(pkgs):
self.gen.h2('Package rules: %s' % pkg)
- self.pkg_rules(pkg)
+ self.pkg_rules(pkg, tests=tests)
self.gen.h2('Package preferences: %s' % pkg)
self.preferred_variants(pkg)
self.preferred_targets(pkg)
@@ -1735,7 +1741,7 @@ def highlight(string):
#
# These are handwritten parts for the Spack ASP model.
#
-def solve(specs, dump=(), models=0, timers=False, stats=False):
+def solve(specs, dump=(), models=0, timers=False, stats=False, tests=False):
"""Solve for a stable model of specs.
Arguments:
@@ -1748,4 +1754,4 @@ def solve(specs, dump=(), models=0, timers=False, stats=False):
driver.out = sys.stdout
setup = SpackSolverSetup()
- return driver.solve(setup, specs, dump, models, timers, stats)
+ return driver.solve(setup, specs, dump, models, timers, stats, tests)
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index fb7c0a93ce..cacad483f6 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -2446,7 +2446,7 @@ class Spec(object):
raise spack.error.SpecError(
"Spec has no name; cannot concretize an anonymous spec")
- result = spack.solver.asp.solve([self])
+ result = spack.solver.asp.solve([self], tests=tests)
if not result.satisfiable:
result.print_cores()
raise spack.error.UnsatisfiableSpecError(
diff --git a/lib/spack/spack/test/spec_dag.py b/lib/spack/spack/test/spec_dag.py
index 0b638ada04..b68e582657 100644
--- a/lib/spack/spack/test/spec_dag.py
+++ b/lib/spack/spack/test/spec_dag.py
@@ -2,12 +2,12 @@
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
-
"""
These tests check Spec DAG operations using dummy packages.
"""
import pytest
import spack.architecture
+import spack.error
import spack.package
from spack.spec import Spec
@@ -90,6 +90,11 @@ def test_installed_deps():
that the installed instance of P should be used. In this case, D should
not be constrained by P since P is already built.
"""
+ # FIXME: this requires to concretize build deps separately if we are
+ # FIXME: using the clingo based concretizer
+ if spack.config.get('config:concretizer') == 'clingo':
+ pytest.xfail('requires separate concretization of build dependencies')
+
default = ('build', 'link')
build_only = ('build',)
@@ -152,7 +157,12 @@ def test_specify_preinstalled_dep():
@pytest.mark.usefixtures('config')
-def test_conditional_dep_with_user_constraints():
+@pytest.mark.parametrize('spec_str,expr_str,expected', [
+ ('x ^y@2', 'y@2', True),
+ ('x@1', 'y', False),
+ ('x', 'y@3', True)
+])
+def test_conditional_dep_with_user_constraints(spec_str, expr_str, expected):
"""This sets up packages X->Y such that X depends on Y conditionally. It
then constructs a Spec with X but with no constraints on X, so that the
initial normalization pass cannot determine whether the constraints are
@@ -171,27 +181,15 @@ def test_conditional_dep_with_user_constraints():
mock_repo.add_package('x', [y], [default], conditions=x_on_y_conditions)
with spack.repo.swap(mock_repo):
- spec = Spec('x ^y@2')
- spec.concretize()
-
- assert ('y@2' in spec)
-
- with spack.repo.swap(mock_repo):
- spec = Spec('x@1')
+ spec = Spec(spec_str)
spec.concretize()
- assert ('y' not in spec)
-
- with spack.repo.swap(mock_repo):
- spec = Spec('x')
- spec.concretize()
-
- assert ('y@3' in spec)
+ result = expr_str in spec
+ assert result is expected, '{0} in {1}'.format(expr_str, spec)
@pytest.mark.usefixtures('mutable_mock_repo', 'config')
class TestSpecDag(object):
-
def test_conflicting_package_constraints(self, set_dependency):
set_dependency('mpileaks', 'mpich@1.0')
set_dependency('callpath', 'mpich@2.0')
@@ -387,17 +385,12 @@ class TestSpecDag(object):
with pytest.raises(spack.spec.UnsatisfiableArchitectureSpecError):
spec.normalize()
- def test_invalid_dep(self):
- spec = Spec('libelf ^mpich')
- with pytest.raises(spack.spec.InvalidDependencyError):
- spec.concretize()
-
- spec = Spec('libelf ^libdwarf')
- with pytest.raises(spack.spec.InvalidDependencyError):
- spec.concretize()
-
- spec = Spec('mpich ^dyninst ^libelf')
- with pytest.raises(spack.spec.InvalidDependencyError):
+ @pytest.mark.parametrize('spec_str', [
+ 'libelf ^mpich', 'libelf ^libdwarf', 'mpich ^dyninst ^libelf'
+ ])
+ def test_invalid_dep(self, spec_str):
+ spec = Spec(spec_str)
+ with pytest.raises(spack.error.SpecError):
spec.concretize()
def test_equal(self):