diff options
author | Massimiliano Culpo <massimiliano.culpo@gmail.com> | 2023-08-09 16:35:01 +0200 |
---|---|---|
committer | Todd Gamblin <tgamblin@llnl.gov> | 2023-08-15 15:54:37 -0700 |
commit | 1db73eb1f222048fbdaf43835000ac17c12694bf (patch) | |
tree | a7f221f10b4acafb34f0be7b9896e5a1963f7524 /lib | |
parent | 2da34de519c847d86f40ac16734ed4ef9e30c0c8 (diff) | |
download | spack-1db73eb1f222048fbdaf43835000ac17c12694bf.tar.gz spack-1db73eb1f222048fbdaf43835000ac17c12694bf.tar.bz2 spack-1db73eb1f222048fbdaf43835000ac17c12694bf.tar.xz spack-1db73eb1f222048fbdaf43835000ac17c12694bf.zip |
Add vendors directive
For the time being this directive prevents the vendored package
to be in the same DAG as the one vendoring it.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/directives.py | 24 | ||||
-rw-r--r-- | lib/spack/spack/solver/asp.py | 12 | ||||
-rw-r--r-- | lib/spack/spack/solver/concretize.lp | 10 | ||||
-rw-r--r-- | lib/spack/spack/test/env.py | 35 |
4 files changed, 81 insertions, 0 deletions
diff --git a/lib/spack/spack/directives.py b/lib/spack/spack/directives.py index 2b7aefca55..03f2f38189 100644 --- a/lib/spack/spack/directives.py +++ b/lib/spack/spack/directives.py @@ -69,6 +69,7 @@ __all__ = [ "resource", "build_system", "requires", + "vendors", ] #: These are variant names used by Spack internally; packages can't use them @@ -916,6 +917,29 @@ def requires(*requirement_specs, policy="one_of", when=None, msg=None): return _execute_requires +@directive("vendors") +def vendors(spec, when=None): + """Declares that a package has an internal copy of another package. + + Currently, the effect is to forbid having the two packages in the same + "unification set". + + Args: + spec: spec being vendored + when: optional constraint that triggers vendoring + """ + + def _execute_vendors(pkg): + when_spec = make_when_spec(when) + if not when_spec: + return + + when_spec_list = pkg.vendors.setdefault(spec, []) + when_spec_list.append(when_spec) + + return _execute_vendors + + class DirectiveError(spack.error.SpackError): """This is raised when something is wrong with a package directive.""" diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index e9141d071d..71aa57e1bf 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -1040,6 +1040,15 @@ class SpackSolverSetup: ) self.gen.newline() + def vendor_rules(self, pkg): + """Facts about vendored packages.""" + for vendored_spec_str, constraints in pkg.vendors.items(): + vendored_spec = spack.spec.Spec(vendored_spec_str) + for constraint in constraints: + constraint_id = self.condition(constraint, name=pkg.name) + self.gen.fact(fn.pkg_fact(pkg.name, fn.vendors(constraint_id, vendored_spec.name))) + self.gen.newline() + def compiler_facts(self): """Facts about available compilers.""" @@ -1189,6 +1198,9 @@ class SpackSolverSetup: # conflicts self.conflict_rules(pkg) + # vendoring + self.vendor_rules(pkg) + # default compilers for this package self.package_compiler_defaults(pkg) diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp index eb691225b8..e41539a366 100644 --- a/lib/spack/spack/solver/concretize.lp +++ b/lib/spack/spack/solver/concretize.lp @@ -450,6 +450,16 @@ error(1, Msg) not attr("hash", node(ID, Package), _). % ignore conflicts for installed packages %----------------------------------------------------------------------------- +% Vendoring +%----------------------------------------------------------------------------- +error(1, "{0} vendors an internal copy of {1}, so it cannot be in the same unification set as {1}", Package, VendoredPackage) + :- pkg_fact(Package, vendors(ConditionID, VendoredPackage)), + attr("node", node(ID, Package)), + condition_holds(ConditionID, node(ID, Package)), + unification_set(X, node(ID, Package)), + unification_set(X, node(_, VendoredPackage)). + +%----------------------------------------------------------------------------- % Virtual dependencies %----------------------------------------------------------------------------- diff --git a/lib/spack/spack/test/env.py b/lib/spack/spack/test/env.py index bcb459f100..23c429de16 100644 --- a/lib/spack/spack/test/env.py +++ b/lib/spack/spack/test/env.py @@ -551,3 +551,38 @@ spack: with spack.config.override("concretizer:unify", unify_in_config): with ev.Environment(manifest.parent) as e: assert e.unify == unify_in_config + + +@pytest.mark.parametrize( + "spec_str,expected_raise,expected_spec", + [ + # vendorsb vendors "b" only when @=1.1 + ("vendorsb", False, "vendorsb@=1.0"), + ("vendorsb@=1.1", True, None), + ], +) +def test_vendors_directive( + spec_str, expected_raise, expected_spec, tmp_path, mock_packages, config +): + """Tests that we cannot concretize two specs together, if one vendors the other.""" + if spack.config.get("config:concretizer") == "original": + pytest.xfail("Known failure of the original concretizer") + + manifest = tmp_path / "spack.yaml" + manifest.write_text( + f"""\ +spack: + specs: + - {spec_str} + - b + concretizer: + unify: true +""" + ) + with ev.Environment(manifest.parent) as e: + if expected_raise: + with pytest.raises(spack.solver.asp.UnsatisfiableSpecError): + e.concretize() + else: + e.concretize() + assert any(s.satisfies(expected_spec) for s in e.concrete_roots()) |