summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@gmail.com>2022-08-24 09:33:55 +0200
committerGitHub <noreply@github.com>2022-08-24 09:33:55 +0200
commite2468c89288f1312ae058949918f4a9c70bd5901 (patch)
tree90e4856e53c0f8819ebd9800e26e7c987e918e2c
parentb4df535e8d8823cb8ea707b742b0fbd9e59bccfb (diff)
downloadspack-e2468c89288f1312ae058949918f4a9c70bd5901.tar.gz
spack-e2468c89288f1312ae058949918f4a9c70bd5901.tar.bz2
spack-e2468c89288f1312ae058949918f4a9c70bd5901.tar.xz
spack-e2468c89288f1312ae058949918f4a9c70bd5901.zip
Allow default requirements in packages.yaml (#32260)
Allow users to express default requirements in packages.yaml. These requirements are overridden if more specific requirements are present for a given package.
-rw-r--r--lib/spack/docs/build_settings.rst28
-rw-r--r--lib/spack/spack/solver/asp.py4
-rw-r--r--lib/spack/spack/test/concretize_requirements.py52
3 files changed, 81 insertions, 3 deletions
diff --git a/lib/spack/docs/build_settings.rst b/lib/spack/docs/build_settings.rst
index c306536c51..6438c0735e 100644
--- a/lib/spack/docs/build_settings.rst
+++ b/lib/spack/docs/build_settings.rst
@@ -396,10 +396,34 @@ choose between a set of options using ``any_of`` or ``one_of``:
``mpich`` already includes a conflict, so this is redundant but
still demonstrates the concept).
+You can also set default requirements for all packages under ``all``
+like this:
+
+.. code-block:: yaml
+
+ packages:
+ all:
+ require: '%clang'
+
+which means every spec will be required to use ``clang`` as a compiler.
+
+Note that in this case ``all`` represents a *default set of requirements* -
+if there are specific package requirements, then the default requirements
+under ``all`` are disregarded. For example, with a configuration like this:
+
+.. code-block:: yaml
+
+ packages:
+ all:
+ require: '%clang'
+ cmake:
+ require: '%gcc'
+
+Spack requires ``cmake`` to use ``gcc`` and all other nodes (including cmake dependencies)
+to use ``clang``.
+
Other notes about ``requires``:
-* You can only specify requirements for specific packages: you cannot
- add ``requires`` under ``all``.
* You cannot specify requirements for virtual packages (e.g. you can
specify requirements for ``openmpi`` but not ``mpi``).
* For ``any_of`` and ``one_of``, the order of specs indicates a
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index 3351ffb7f8..b1d5f284ce 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -942,7 +942,9 @@ class SpackSolverSetup(object):
def package_requirement_rules(self, pkg):
pkg_name = pkg.name
config = spack.config.get("packages")
- requirements = config.get(pkg_name, {}).get("require", [])
+ requirements = config.get(pkg_name, {}).get("require", []) or config.get("all", {}).get(
+ "require", []
+ )
if isinstance(requirements, string_types):
rules = [(pkg_name, "one_of", [requirements])]
else:
diff --git a/lib/spack/spack/test/concretize_requirements.py b/lib/spack/spack/test/concretize_requirements.py
index 42d680dd72..329c881cf9 100644
--- a/lib/spack/spack/test/concretize_requirements.py
+++ b/lib/spack/spack/test/concretize_requirements.py
@@ -297,3 +297,55 @@ packages:
s1 = Spec("y").concretized()
assert s1.satisfies("@2.3")
assert s1.satisfies("%gcc")
+
+
+@pytest.mark.parametrize("spec_str,requirement_str", [("x", "%gcc"), ("x", "%clang")])
+def test_default_requirements_with_all(spec_str, requirement_str, concretize_scope, test_repo):
+ """Test that default requirements are applied to all packages."""
+ if spack.config.get("config:concretizer") == "original":
+ pytest.skip("Original concretizer does not support configuration" " requirements")
+
+ conf_str = """\
+packages:
+ all:
+ require: "{}"
+""".format(
+ requirement_str
+ )
+ update_packages_config(conf_str)
+
+ spec = Spec(spec_str).concretized()
+ for s in spec.traverse():
+ assert s.satisfies(requirement_str)
+
+
+@pytest.mark.parametrize(
+ "requirements,expectations",
+ [
+ (("%gcc", "%clang"), ("%gcc", "%clang")),
+ (("%gcc ~shared", "@1.0"), ("%gcc ~shared", "@1.0 +shared")),
+ ],
+)
+def test_default_and_package_specific_requirements(
+ concretize_scope, requirements, expectations, test_repo
+):
+ """Test that specific package requirements override default package requirements."""
+ if spack.config.get("config:concretizer") == "original":
+ pytest.skip("Original concretizer does not support configuration" " requirements")
+ generic_req, specific_req = requirements
+ generic_exp, specific_exp = expectations
+ conf_str = """\
+packages:
+ all:
+ require: "{}"
+ x:
+ require: "{}"
+""".format(
+ generic_req, specific_req
+ )
+ update_packages_config(conf_str)
+
+ spec = Spec("x").concretized()
+ assert spec.satisfies(specific_exp)
+ for s in spec.traverse(root=False):
+ assert s.satisfies(generic_exp)