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:
parent
2da34de519
commit
1db73eb1f2
9 changed files with 109 additions and 9 deletions
|
@ -69,6 +69,7 @@ class OpenMpi(Package):
|
||||||
"resource",
|
"resource",
|
||||||
"build_system",
|
"build_system",
|
||||||
"requires",
|
"requires",
|
||||||
|
"vendors",
|
||||||
]
|
]
|
||||||
|
|
||||||
#: These are variant names used by Spack internally; packages can't use them
|
#: These are variant names used by Spack internally; packages can't use them
|
||||||
|
@ -916,6 +917,29 @@ def _execute_requires(pkg):
|
||||||
return _execute_requires
|
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):
|
class DirectiveError(spack.error.SpackError):
|
||||||
"""This is raised when something is wrong with a package directive."""
|
"""This is raised when something is wrong with a package directive."""
|
||||||
|
|
||||||
|
|
|
@ -1040,6 +1040,15 @@ def conflict_rules(self, pkg):
|
||||||
)
|
)
|
||||||
self.gen.newline()
|
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):
|
def compiler_facts(self):
|
||||||
"""Facts about available compilers."""
|
"""Facts about available compilers."""
|
||||||
|
|
||||||
|
@ -1189,6 +1198,9 @@ def pkg_rules(self, pkg, tests):
|
||||||
# conflicts
|
# conflicts
|
||||||
self.conflict_rules(pkg)
|
self.conflict_rules(pkg)
|
||||||
|
|
||||||
|
# vendoring
|
||||||
|
self.vendor_rules(pkg)
|
||||||
|
|
||||||
# default compilers for this package
|
# default compilers for this package
|
||||||
self.package_compiler_defaults(pkg)
|
self.package_compiler_defaults(pkg)
|
||||||
|
|
||||||
|
|
|
@ -449,6 +449,16 @@ error(1, Msg)
|
||||||
not external(node(ID, Package)), % ignore conflicts for externals
|
not external(node(ID, Package)), % ignore conflicts for externals
|
||||||
not attr("hash", node(ID, Package), _). % ignore conflicts for installed packages
|
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
|
% 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 spack.config.override("concretizer:unify", unify_in_config):
|
||||||
with ev.Environment(manifest.parent) as e:
|
with ev.Environment(manifest.parent) as e:
|
||||||
assert e.unify == unify_in_config
|
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())
|
||||||
|
|
18
var/spack/repos/builtin.mock/packages/vendorsb/package.py
Normal file
18
var/spack/repos/builtin.mock/packages/vendorsb/package.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
|
||||||
|
from spack.package import *
|
||||||
|
|
||||||
|
|
||||||
|
class Vendorsb(Package):
|
||||||
|
"""A package that vendors another"""
|
||||||
|
|
||||||
|
homepage = "http://www.example.com"
|
||||||
|
url = "http://www.example.com/b-1.0.tar.gz"
|
||||||
|
|
||||||
|
version("1.1", md5="0123456789abcdef0123456789abcdef")
|
||||||
|
version("1.0", md5="0123456789abcdef0123456789abcdef")
|
||||||
|
|
||||||
|
vendors("b", when="@=1.1")
|
|
@ -40,7 +40,7 @@ class Memkind(AutotoolsPackage):
|
||||||
|
|
||||||
# memkind includes a copy of jemalloc; see
|
# memkind includes a copy of jemalloc; see
|
||||||
# <https://github.com/memkind/memkind#jemalloc>.
|
# <https://github.com/memkind/memkind#jemalloc>.
|
||||||
conflicts("jemalloc")
|
vendors("jemalloc")
|
||||||
|
|
||||||
# https://github.com/spack/spack/issues/37292
|
# https://github.com/spack/spack/issues/37292
|
||||||
parallel = False
|
parallel = False
|
||||||
|
|
|
@ -94,9 +94,9 @@ class Palace(CMakePackage):
|
||||||
depends_on("arpack-ng+shared", when="+shared")
|
depends_on("arpack-ng+shared", when="+shared")
|
||||||
depends_on("arpack-ng~shared", when="~shared")
|
depends_on("arpack-ng~shared", when="~shared")
|
||||||
|
|
||||||
# Conflicts: Palace always builds its own internal MFEM, GSLIB
|
# Palace always builds its own internal MFEM, GSLIB
|
||||||
conflicts("^mfem", msg="Palace builds its own internal MFEM")
|
vendors("mfem")
|
||||||
conflicts("^gslib", msg="Palace builds its own internal GSLIB")
|
vendors("gslib")
|
||||||
|
|
||||||
# More dependency variant conflicts
|
# More dependency variant conflicts
|
||||||
conflicts("^hypre+int64", msg="Palace uses HYPRE's mixedint option for 64 bit integers")
|
conflicts("^hypre+int64", msg="Palace uses HYPRE's mixedint option for 64 bit integers")
|
||||||
|
|
|
@ -70,8 +70,8 @@ class Scotch(CMakePackage, MakefilePackage):
|
||||||
|
|
||||||
# Vendored dependency of METIS/ParMETIS conflicts with standard
|
# Vendored dependency of METIS/ParMETIS conflicts with standard
|
||||||
# installations
|
# installations
|
||||||
conflicts("^metis", when="+metis")
|
vendors("metis", when="+metis")
|
||||||
conflicts("^parmetis", when="+metis")
|
vendors("parmetis", when="+metis")
|
||||||
|
|
||||||
parallel = False
|
parallel = False
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,10 @@ class Votca(CMakePackage):
|
||||||
"new-gmx", default=False, description="Build against gromacs>2019 - no tabulated kernels"
|
"new-gmx", default=False, description="Build against gromacs>2019 - no tabulated kernels"
|
||||||
)
|
)
|
||||||
variant("xtp", default=True, description="Build xtp parts of votca")
|
variant("xtp", default=True, description="Build xtp parts of votca")
|
||||||
conflicts("votca-tools")
|
|
||||||
conflicts("votca-csg")
|
vendors("votca-tools")
|
||||||
conflicts("votca-xtp")
|
vendors("votca-csg")
|
||||||
|
vendors("votca-xtp")
|
||||||
|
|
||||||
depends_on("cmake@3.13:", type="build")
|
depends_on("cmake@3.13:", type="build")
|
||||||
depends_on("expat")
|
depends_on("expat")
|
||||||
|
|
Loading…
Reference in a new issue