From e2468c89288f1312ae058949918f4a9c70bd5901 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Wed, 24 Aug 2022 09:33:55 +0200 Subject: 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. --- lib/spack/docs/build_settings.rst | 28 ++++++++++++- lib/spack/spack/solver/asp.py | 4 +- lib/spack/spack/test/concretize_requirements.py | 52 +++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 3 deletions(-) (limited to 'lib') 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) -- cgit v1.2.3-70-g09d2