Add vendors directive
For the time being this directive prevents the vendored package to be in the same DAG as the one vendoring it.
This commit is contained in:

committed by
Todd Gamblin

parent
2da34de519
commit
1db73eb1f2
@@ -69,6 +69,7 @@ class OpenMpi(Package):
|
||||
"resource",
|
||||
"build_system",
|
||||
"requires",
|
||||
"vendors",
|
||||
]
|
||||
|
||||
#: These are variant names used by Spack internally; packages can't use them
|
||||
@@ -916,6 +917,29 @@ def _execute_requires(pkg):
|
||||
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."""
|
||||
|
||||
|
@@ -1040,6 +1040,15 @@ def conflict_rules(self, pkg):
|
||||
)
|
||||
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 @@ def pkg_rules(self, pkg, tests):
|
||||
# conflicts
|
||||
self.conflict_rules(pkg)
|
||||
|
||||
# vendoring
|
||||
self.vendor_rules(pkg)
|
||||
|
||||
# default compilers for this package
|
||||
self.package_compiler_defaults(pkg)
|
||||
|
||||
|
@@ -449,6 +449,16 @@ error(1, Msg)
|
||||
not external(node(ID, Package)), % ignore conflicts for externals
|
||||
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
|
||||
%-----------------------------------------------------------------------------
|
||||
|
@@ -551,3 +551,38 @@ def test_environment_config_scheme_used(tmp_path, unify_in_config):
|
||||
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())
|
||||
|
Reference in New Issue
Block a user