concretizer: concretize a virtual root

Before this modification the root of a DAG has to be
a real package. This commit adds rules to concretize
virtual roots.
This commit is contained in:
Massimiliano Culpo 2020-10-14 15:36:24 +02:00 committed by Todd Gamblin
parent 1b115e200b
commit 4fe527cd3b
4 changed files with 41 additions and 5 deletions

View File

@ -119,7 +119,13 @@ def solve(parser, args):
# iterate over roots from command line # iterate over roots from command line
for input_spec in specs: for input_spec in specs:
spec = answer[input_spec.name] key = input_spec.name
if input_spec.virtual:
providers = [spec.name for spec in answer.values()
if spec.package.provides(key)]
key = providers[0]
spec = answer[key]
# With -y, just print YAML to output. # With -y, just print YAML to output.
if args.format == 'yaml': if args.format == 'yaml':

View File

@ -1380,7 +1380,9 @@ def setup(self, driver, specs):
check_packages_exist(specs) check_packages_exist(specs)
# get list of all possible dependencies # get list of all possible dependencies
self.possible_virtuals = set() self.possible_virtuals = set(
x.name for x in specs if x.virtual
)
possible = spack.package.possible_dependencies( possible = spack.package.possible_dependencies(
*specs, *specs,
virtuals=self.possible_virtuals, virtuals=self.possible_virtuals,
@ -1424,7 +1426,11 @@ def setup(self, driver, specs):
self.gen.h1('Spec Constraints') self.gen.h1('Spec Constraints')
for spec in sorted(specs): for spec in sorted(specs):
if not spec.virtual:
self.gen.fact(fn.root(spec.name)) self.gen.fact(fn.root(spec.name))
else:
self.gen.fact(fn.virtual_root(spec.name))
for dep in spec.traverse(): for dep in spec.traverse():
self.gen.h2('Spec: %s' % str(dep)) self.gen.h2('Spec: %s' % str(dep))

View File

@ -65,6 +65,7 @@ provider_weight(Dependency, Weight)
:- virtual(Virtual), depends_on(Package, Dependency), :- virtual(Virtual), depends_on(Package, Dependency),
provider(Dependency, Virtual), provider(Dependency, Virtual),
pkg_provider_preference(Package, Virtual, Dependency, Weight). pkg_provider_preference(Package, Virtual, Dependency, Weight).
provider_weight(Dependency, Weight) provider_weight(Dependency, Weight)
:- virtual(Virtual), depends_on(Package, Dependency), :- virtual(Virtual), depends_on(Package, Dependency),
provider(Dependency, Virtual), provider(Dependency, Virtual),
@ -80,8 +81,23 @@ provider_weight(Dependency, 100)
not pkg_provider_preference(Package, Virtual, Dependency, _), not pkg_provider_preference(Package, Virtual, Dependency, _),
not default_provider_preference(Virtual, Dependency, _). not default_provider_preference(Virtual, Dependency, _).
% Do the same for virtual roots
provider_weight(Package, Weight)
:- virtual_root(Virtual),
provider(Package, Virtual),
default_provider_preference(Virtual, Package, Weight).
provider_weight(Package, 100)
:- virtual_root(Virtual),
provider(Package, Virtual),
not default_provider_preference(Virtual, Package, _).
% all nodes must be reachable from some root % all nodes must be reachable from some root
node(Package) :- root(Package). node(Package) :- root(Package).
1 { root(Package) : provides_virtual(Package, Virtual) } 1
:- virtual_root(Virtual).
needed(Package) :- root(Package). needed(Package) :- root(Package).
needed(Dependency) :- needed(Package), depends_on(Package, Dependency). needed(Dependency) :- needed(Package), depends_on(Package, Dependency).
:- node(Package), not needed(Package). :- node(Package), not needed(Package).
@ -94,6 +110,7 @@ node(Dependency) :- node(Package), depends_on(Package, Dependency).
#defined declared_dependency/3. #defined declared_dependency/3.
#defined virtual/1. #defined virtual/1.
#defined virtual_node/1. #defined virtual_node/1.
#defined virtual_root/1.
#defined provides_virtual/2. #defined provides_virtual/2.
#defined external/1. #defined external/1.
#defined external_spec/2. #defined external_spec/2.

View File

@ -2434,9 +2434,16 @@ def _new_concretize(self, tests=False):
# take the best answer # take the best answer
opt, i, answer = min(result.answers) opt, i, answer = min(result.answers)
assert self.name in answer name = self.name
# TODO: Consolidate this code with similar code in solve.py
if self.virtual:
providers = [spec.name for spec in answer.values()
if spec.package.provides(name)]
name = providers[0]
concretized = answer[self.name] assert name in answer
concretized = answer[name]
self._dup(concretized) self._dup(concretized)
self._mark_concrete() self._mark_concrete()