diff --git a/lib/spack/docs/build_settings.rst b/lib/spack/docs/build_settings.rst index de55cf08349..0a05c01e1d9 100644 --- a/lib/spack/docs/build_settings.rst +++ b/lib/spack/docs/build_settings.rst @@ -34,6 +34,7 @@ an object, with the following keys: 1. ``roots``: if ``true`` root specs are reused, if ``false`` only dependencies of root specs are reused 2. ``from``: list of sources from which reused specs are taken +3. ``namespaces``: list of namespaces from which to reuse specs, or the string ``"any"``. Each source in ``from`` is itself an object: @@ -56,6 +57,7 @@ For instance, the following configuration: concretizer: reuse: roots: true + namespaces: [builtin] from: - type: local include: @@ -63,7 +65,8 @@ For instance, the following configuration: - "%clang" tells the concretizer to reuse all specs compiled with either ``gcc`` or ``clang``, that are installed -in the local store. Any spec from remote buildcaches is disregarded. +in the local store. Any spec from remote buildcaches is disregarded. Any spec from a namespace other than +Spack's builtin repo is disregarded. To reduce the boilerplate in configuration files, default values for the ``include`` and ``exclude`` options can be pushed up one level: diff --git a/lib/spack/spack/schema/concretizer.py b/lib/spack/spack/schema/concretizer.py index 7a866dfbbd7..899eee6114f 100644 --- a/lib/spack/spack/schema/concretizer.py +++ b/lib/spack/spack/schema/concretizer.py @@ -25,6 +25,12 @@ "roots": {"type": "boolean"}, "include": LIST_OF_SPECS, "exclude": LIST_OF_SPECS, + "namespaces": { + "oneOf": [ + {"type": "string", "enum": ["any"]}, + {"type": "array", "items": {"type": "string"}}, + ] + }, "from": { "type": "array", "items": { diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index ce0f0a48c58..e4fb6ded8e7 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -3986,6 +3986,7 @@ def __init__(self, configuration: spack.config.Configuration) -> None: self.configuration = configuration self.store = spack.store.create(configuration) self.reuse_strategy = ReuseStrategy.ROOTS + self.reuse_namespaces = "any" reuse_yaml = self.configuration.get("concretizer:reuse", False) self.reuse_sources = [] @@ -4016,6 +4017,7 @@ def __init__(self, configuration: spack.config.Configuration) -> None: self.reuse_strategy = ReuseStrategy.ROOTS else: self.reuse_strategy = ReuseStrategy.DEPENDENCIES + self.reuse_namespaces = reuse_yaml.get("namespaces", "any") default_include = reuse_yaml.get("include", []) default_exclude = reuse_yaml.get("exclude", []) default_sources = [{"type": "local"}, {"type": "buildcache"}] @@ -4083,6 +4085,9 @@ def reusable_specs(self, specs: List[spack.spec.Spec]) -> List[spack.spec.Spec]: if self.reuse_strategy == ReuseStrategy.DEPENDENCIES: result = [spec for spec in result if not any(root in spec for root in specs)] + if self.reuse_namespaces != "any": + result = [spec for spec in result if spec.namespace in self.reuse_namespaces] + return result diff --git a/lib/spack/spack/test/concretization/core.py b/lib/spack/spack/test/concretization/core.py index 0950e227ea9..809f203d481 100644 --- a/lib/spack/spack/test/concretization/core.py +++ b/lib/spack/spack/test/concretization/core.py @@ -1460,6 +1460,19 @@ def test_no_reuse_when_variant_condition_does_not_hold(self, mutable_database, m new2 = spack.concretize.concretize_one("conditional-variant-pkg +two_whens") assert new2.satisfies("@2 +two_whens +version_based") + def test_reuse_by_namespace(self, mutable_database, mock_packages): + spack.config.set("concretizer:reuse", True) + spack.config.set("packages:libelf", {"version": ["0.8.10"]}) + + reuse = spack.concretize.concretize_one("libelf") + assert reuse.installed + assert reuse.satisfies("@0.8.13") + + spack.config.set("concretizer:reuse", {"namespaces": []}) + noreuse = spack.concretize.concretize_one("libelf") + assert not noreuse.installed + assert noreuse.satisfies("@0.8.10") + def test_reuse_with_flags(self, mutable_database, mutable_config): spack.config.set("concretizer:reuse", True) spec = spack.concretize.concretize_one("pkg-a cflags=-g cxxflags=-g")