summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@gmail.com>2023-08-09 16:35:01 +0200
committerTodd Gamblin <tgamblin@llnl.gov>2023-08-15 15:54:37 -0700
commit1db73eb1f222048fbdaf43835000ac17c12694bf (patch)
treea7f221f10b4acafb34f0be7b9896e5a1963f7524 /lib
parent2da34de519c847d86f40ac16734ed4ef9e30c0c8 (diff)
downloadspack-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.py24
-rw-r--r--lib/spack/spack/solver/asp.py12
-rw-r--r--lib/spack/spack/solver/concretize.lp10
-rw-r--r--lib/spack/spack/test/env.py35
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())