Hotfix/namespace (#33870)

Concretize namespaces

Add new concretizer option `enable_node_namespace` that enables namespace-specific concretization
This commit is contained in:
Greg Becker 2022-11-13 03:08:39 -08:00 committed by GitHub
parent cd94827c5f
commit a86911246a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 5 deletions

View File

@ -15,6 +15,7 @@
"additionalProperties": False, "additionalProperties": False,
"properties": { "properties": {
"reuse": {"type": "boolean"}, "reuse": {"type": "boolean"},
"enable_node_namespace": {"type": "boolean"},
"targets": { "targets": {
"type": "object", "type": "object",
"properties": { "properties": {

View File

@ -595,13 +595,14 @@ def fact(self, head):
if choice: if choice:
self.assumptions.append(atom) self.assumptions.append(atom)
def solve(self, setup, specs, reuse=None, output=None, control=None): def solve(self, setup, specs, reuse=None, namespace=False, output=None, control=None):
"""Set up the input and solve for dependencies of ``specs``. """Set up the input and solve for dependencies of ``specs``.
Arguments: Arguments:
setup (SpackSolverSetup): An object to set up the ASP problem. setup (SpackSolverSetup): An object to set up the ASP problem.
specs (list): List of ``Spec`` objects to solve for. specs (list): List of ``Spec`` objects to solve for.
reuse (None or list): list of concrete specs that can be reused reuse (None or list): list of concrete specs that can be reused
namespace (bool): enable node namespacing
output (None or OutputConfiguration): configuration object to set output (None or OutputConfiguration): configuration object to set
the output of this solve. the output of this solve.
control (clingo.Control): configuration for the solver. If None, control (clingo.Control): configuration for the solver. If None,
@ -624,7 +625,7 @@ def solve(self, setup, specs, reuse=None, output=None, control=None):
self.assumptions = [] self.assumptions = []
with self.control.backend() as backend: with self.control.backend() as backend:
self.backend = backend self.backend = backend
setup.setup(self, specs, reuse=reuse) setup.setup(self, specs, reuse=reuse, namespace=namespace)
timer.phase("setup") timer.phase("setup")
# read in the main ASP program and display logic -- these are # read in the main ASP program and display logic -- these are
@ -760,6 +761,10 @@ def __init__(self, tests=False):
# whether to add installed/binary hashes to the solve # whether to add installed/binary hashes to the solve
self.tests = tests self.tests = tests
# whether to namespace nodes in the solve
# set by setup()
self.namespace = None
# If False allows for input specs that are not solved # If False allows for input specs that are not solved
self.concretize_everything = True self.concretize_everything = True
@ -1348,6 +1353,7 @@ def _spec_clauses(
# TODO: do this with consistent suffixes. # TODO: do this with consistent suffixes.
class Head(object): class Head(object):
node = fn.node node = fn.node
node_namespace = fn.node_namespace
virtual_node = fn.virtual_node virtual_node = fn.virtual_node
node_platform = fn.node_platform_set node_platform = fn.node_platform_set
node_os = fn.node_os_set node_os = fn.node_os_set
@ -1361,6 +1367,7 @@ class Head(object):
class Body(object): class Body(object):
node = fn.node node = fn.node
node_namespace = fn.node_namespace
virtual_node = fn.virtual_node virtual_node = fn.virtual_node
node_platform = fn.node_platform node_platform = fn.node_platform
node_os = fn.node_os node_os = fn.node_os
@ -1377,6 +1384,9 @@ class Body(object):
if spec.name: if spec.name:
clauses.append(f.node(spec.name) if not spec.virtual else f.virtual_node(spec.name)) clauses.append(f.node(spec.name) if not spec.virtual else f.virtual_node(spec.name))
if self.namespace and spec.namespace:
clauses.append(f.node_namespace(spec.name, spec.namespace))
clauses.extend(self.spec_versions(spec)) clauses.extend(self.spec_versions(spec))
# seed architecture at the root (we'll propagate later) # seed architecture at the root (we'll propagate later)
@ -1917,7 +1927,7 @@ def define_concrete_input_specs(self, specs, possible):
if spec.concrete: if spec.concrete:
self._facts_from_concrete_spec(spec, possible) self._facts_from_concrete_spec(spec, possible)
def setup(self, driver, specs, reuse=None): def setup(self, driver, specs, reuse=None, namespace=False):
"""Generate an ASP program with relevant constraints for specs. """Generate an ASP program with relevant constraints for specs.
This calls methods on the solve driver to set up the problem with This calls methods on the solve driver to set up the problem with
@ -1928,6 +1938,7 @@ def setup(self, driver, specs, reuse=None):
driver (PyclingoDriver): driver instance of this solve driver (PyclingoDriver): driver instance of this solve
specs (list): list of Specs to solve specs (list): list of Specs to solve
reuse (None or list): list of concrete specs that can be reused reuse (None or list): list of concrete specs that can be reused
namespace (bool): enable namespace matching in the solve
""" """
self._condition_id_counter = itertools.count() self._condition_id_counter = itertools.count()
@ -1980,6 +1991,10 @@ def setup(self, driver, specs, reuse=None):
self.gen.h1("Concrete input spec definitions") self.gen.h1("Concrete input spec definitions")
self.define_concrete_input_specs(specs, possible) self.define_concrete_input_specs(specs, possible)
self.namespace = namespace
if namespace:
self.gen.fact(fn.enable_node_namespace())
if reuse: if reuse:
self.gen.h1("Reusable specs") self.gen.h1("Reusable specs")
self.gen.fact(fn.optimize_for_reuse()) self.gen.fact(fn.optimize_for_reuse())
@ -2073,6 +2088,9 @@ def node(self, pkg):
if pkg not in self._specs: if pkg not in self._specs:
self._specs[pkg] = spack.spec.Spec(pkg) self._specs[pkg] = spack.spec.Spec(pkg)
def node_namespace(self, pkg, namespace):
self._specs[pkg].namespace = namespace
def _arch(self, pkg): def _arch(self, pkg):
arch = self._specs[pkg].architecture arch = self._specs[pkg].architecture
if not arch: if not arch:
@ -2368,6 +2386,7 @@ def __init__(self):
# These properties are settable via spack configuration, and overridable # These properties are settable via spack configuration, and overridable
# by setting them directly as properties. # by setting them directly as properties.
self.reuse = spack.config.get("concretizer:reuse", False) self.reuse = spack.config.get("concretizer:reuse", False)
self.namespace = spack.config.get("concretizer:enable_node_namespace", False)
@staticmethod @staticmethod
def _check_input_and_extract_concrete_specs(specs): def _check_input_and_extract_concrete_specs(specs):
@ -2430,7 +2449,9 @@ def solve(
reusable_specs.extend(self._reusable_specs()) reusable_specs.extend(self._reusable_specs())
setup = SpackSolverSetup(tests=tests) setup = SpackSolverSetup(tests=tests)
output = OutputConfiguration(timers=timers, stats=stats, out=out, setup_only=setup_only) output = OutputConfiguration(timers=timers, stats=stats, out=out, setup_only=setup_only)
result, _, _ = self.driver.solve(setup, specs, reuse=reusable_specs, output=output) result, _, _ = self.driver.solve(
setup, specs, reuse=reusable_specs, namespace=self.namespace, output=output
)
return result return result
def solve_in_rounds( def solve_in_rounds(
@ -2467,7 +2488,7 @@ def solve_in_rounds(
output = OutputConfiguration(timers=timers, stats=stats, out=out, setup_only=False) output = OutputConfiguration(timers=timers, stats=stats, out=out, setup_only=False)
while True: while True:
result, _, _ = self.driver.solve( result, _, _ = self.driver.solve(
setup, input_specs, reuse=reusable_specs, output=output setup, input_specs, reuse=reusable_specs, namespace=self.namespace, output=output
) )
yield result yield result

View File

@ -210,6 +210,14 @@ attr(Name, A1, A2, A3, A4) :- impose(ID), imposed_constraint(ID, Name, A1, A2, A
not imposed_constraint(Hash, "node_flag", Package, FlagType, Flag), not imposed_constraint(Hash, "node_flag", Package, FlagType, Flag),
internal_error("imposed hash without imposing all flag values"). internal_error("imposed hash without imposing all flag values").
% cannot have multiple namespaces for a package
:- node(Package),
node_namespace(Package, Namespace1),
node_namespace(Package, Namespace2),
Namespace1 < Namespace2,
enable_node_namespace().
#defined enable_node_namespace/0.
#defined condition/2. #defined condition/2.
#defined condition_requirement/3. #defined condition_requirement/3.
#defined condition_requirement/4. #defined condition_requirement/4.
@ -405,6 +413,7 @@ possible_provider_weight(Dependency, Virtual, 100, "fallback") :- provider(Depen
% These allow us to easily define conditional dependency and conflict rules % These allow us to easily define conditional dependency and conflict rules
% without enumerating all spec attributes every time. % without enumerating all spec attributes every time.
node(Package) :- attr("node", Package). node(Package) :- attr("node", Package).
node_namespace(Package, Namespace) :- attr("node_namespace", Package, Namespace).
virtual_node(Virtual) :- attr("virtual_node", Virtual). virtual_node(Virtual) :- attr("virtual_node", Virtual).
hash(Package, Hash) :- attr("hash", Package, Hash). hash(Package, Hash) :- attr("hash", Package, Hash).
version(Package, Version) :- attr("version", Package, Version). version(Package, Version) :- attr("version", Package, Version).
@ -427,6 +436,7 @@ node_flag_propagate(Package, FlagType)
:- attr("node_flag_propagate", Package, FlagType). :- attr("node_flag_propagate", Package, FlagType).
attr("node", Package) :- node(Package). attr("node", Package) :- node(Package).
attr("node_namespace", Package, Namespace) :- node_namespace(Package, Namespace).
attr("virtual_node", Virtual) :- virtual_node(Virtual). attr("virtual_node", Virtual) :- virtual_node(Virtual).
attr("hash", Package, Hash) :- hash(Package, Hash). attr("hash", Package, Hash) :- hash(Package, Hash).
attr("version", Package, Version) :- version(Package, Version). attr("version", Package, Version) :- version(Package, Version).
@ -464,6 +474,7 @@ attr("node_flag_propagate", Package, FlagType)
#defined node_version_satisfies/2. #defined node_version_satisfies/2.
#defined node_compiler_version_satisfies/3. #defined node_compiler_version_satisfies/3.
#defined root/1. #defined root/1.
#defined node_namespace/2.
%----------------------------------------------------------------------------- %-----------------------------------------------------------------------------
% External semantics % External semantics

View File

@ -12,6 +12,7 @@
% Spec-related functions. % Spec-related functions.
% Used to build the result of the solve. % Used to build the result of the solve.
#show node/1. #show node/1.
#show node_namespace/2.
#show hash/2. #show hash/2.
#show depends_on/3. #show depends_on/3.
#show version/2. #show version/2.