From 8a855ddac5bfc9540215356e24c385afefd809a5 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Fri, 23 Oct 2020 18:10:53 +0200 Subject: [PATCH] concretizer: added handling for dev_path variant This variant is currently either set from command line, in which case it enters the concretization, or attached from environment after concretization. --- lib/spack/spack/solver/asp.py | 73 ++++++++++++++++++++++++--- lib/spack/spack/test/cmd/dev_build.py | 2 + lib/spack/spack/test/cmd/env.py | 12 +++-- 3 files changed, 77 insertions(+), 10 deletions(-) diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index f41a0c117a..a50f61f9a0 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -2,7 +2,6 @@ # Spack Project Developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) - from __future__ import print_function import collections @@ -38,6 +37,7 @@ import spack.package import spack.package_prefs import spack.repo +import spack.variant from spack.util.executable import which from spack.version import ver @@ -1485,7 +1485,8 @@ def setup(self, driver, specs, tests=False): for dep in spec.traverse(): self.gen.h2('Spec: %s' % str(dep)) - + # Inject dev_path from environment + _develop_specs_from_env(dep) if dep.virtual: for clause in self.virtual_spec_clauses(dep): self.gen.fact(clause) @@ -1499,11 +1500,33 @@ def setup(self, driver, specs, tests=False): # TODO: then it's also a possible value. if clause.name == 'variant_set': variant_name = clause.args[1] - variant_def = dep.package.variants[variant_name] - variant_def.validate_or_raise( - dep.variants[variant_name], - dep.package - ) + # 'dev_path' and 'patches are treated in a + # special way, as they are injected from cli + # or files + if variant_name == 'dev_path': + pkg_name = clause.args[0] + self.gen.fact(fn.variant( + pkg_name, variant_name + )) + self.gen.fact(fn.variant_single_value( + pkg_name, variant_name + )) + elif variant_name == 'patches': + pkg_name = clause.args[0] + self.gen.fact(fn.variant( + pkg_name, variant_name + )) + else: + variant_def = dep.package.variants[ + variant_name + ] + variant_def.validate_or_raise( + dep.variants[variant_name], + dep.package + ) + # State that this variant is a possible value + # to account for variant values that are not + # enumerated explicitly self.gen.fact( fn.variant_possible_value(*clause.args) ) @@ -1556,6 +1579,21 @@ def node_target(self, pkg, target): self._arch(pkg).target = target def variant_value(self, pkg, name, value): + # FIXME: is there a way not to special case 'dev_path' everywhere? + if name == 'dev_path': + self._specs[pkg].variants.setdefault( + name, + spack.variant.SingleValuedVariant(name, value) + ) + return + + if name == 'patches': + self._specs[pkg].variants.setdefault( + name, + spack.variant.MultiValuedVariant(name, value) + ) + return + pkg_class = spack.repo.path.get_pkg_class(pkg) variant = self._specs[pkg].variants.get(name) @@ -1696,6 +1734,9 @@ def build_specs(self, function_tuples): for s in self._specs.values(): spack.spec.Spec.ensure_external_path_if_external(s) + for s in self._specs.values(): + _develop_specs_from_env(s) + for s in self._specs.values(): s._mark_concrete() @@ -1738,6 +1779,24 @@ def highlight(string): return string +def _develop_specs_from_env(spec): + env = spack.environment.get_env(None, None) + dev_info = env.dev_specs.get(spec.name, {}) if env else {} + if not dev_info: + return + + path = dev_info['path'] + path = path if os.path.isabs(path) else os.path.join(env.path, path) + + if 'dev_path' in spec.variants: + assert spec.variants['dev_path'].value == path + else: + spec.variants.setdefault( + 'dev_path', spack.variant.SingleValuedVariant('dev_path', path) + ) + spec.constrain(dev_info['spec']) + + # # These are handwritten parts for the Spack ASP model. # diff --git a/lib/spack/spack/test/cmd/dev_build.py b/lib/spack/spack/test/cmd/dev_build.py index 30d99c8562..3067f5a0dd 100644 --- a/lib/spack/spack/test/cmd/dev_build.py +++ b/lib/spack/spack/test/cmd/dev_build.py @@ -19,6 +19,8 @@ def test_dev_build_basics(tmpdir, mock_packages, install_mockery): spec = spack.spec.Spec('dev-build-test-install@0.0.0 dev_path=%s' % tmpdir) spec.concretize() + assert 'dev_path' in spec.variants + with tmpdir.as_cwd(): with open(spec.package.filename, 'w') as f: f.write(spec.package.original_string) diff --git a/lib/spack/spack/test/cmd/env.py b/lib/spack/spack/test/cmd/env.py index 5fbd5f2c85..49a2126877 100644 --- a/lib/spack/spack/test/cmd/env.py +++ b/lib/spack/spack/test/cmd/env.py @@ -468,8 +468,9 @@ def test_init_from_yaml(tmpdir): @pytest.mark.usefixtures('config') -def test_env_view_external_prefix(tmpdir_factory, mutable_database, - mock_packages): +def test_env_view_external_prefix( + tmpdir_factory, mutable_database, mock_packages +): fake_prefix = tmpdir_factory.mktemp('a-prefix') fake_bin = fake_prefix.join('bin') fake_bin.ensure(dir=True) @@ -485,7 +486,7 @@ def test_env_view_external_prefix(tmpdir_factory, mutable_database, packages: a: externals: - - spec: a + - spec: a@2.0 prefix: {a_prefix} buildable: false """.format(a_prefix=str(fake_prefix))) @@ -1441,6 +1442,11 @@ def test_stack_yaml_force_remove_from_matrix(tmpdir): def test_stack_concretize_extraneous_deps(tmpdir, config, mock_packages): + # FIXME: The new concretizer doesn't handle yet soft + # FIXME: constraints for stacks + if spack.config.get('config:concretizer') == 'clingo': + pytest.skip('Clingo concretizer does not support soft constraints') + filename = str(tmpdir.join('spack.yaml')) with open(filename, 'w') as f: f.write("""\