concretizer: generate facts for externals
Generate only facts for external specs. Substitute the use of already grounded rules with non-grounded rules in concretize.lp
This commit is contained in:
parent
a4accff266
commit
eca1dd8738
3 changed files with 42 additions and 41 deletions
|
@ -793,9 +793,6 @@ def external_packages(self):
|
||||||
if pkg_name not in spack.repo.path:
|
if pkg_name not in spack.repo.path:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if 'externals' not in data:
|
|
||||||
self.gen.fact(fn.external(pkg_name).symbol(positive=False))
|
|
||||||
|
|
||||||
self.gen.h2('External package: {0}'.format(pkg_name))
|
self.gen.h2('External package: {0}'.format(pkg_name))
|
||||||
# Check if the external package is buildable. If it is
|
# Check if the external package is buildable. If it is
|
||||||
# not then "external(<pkg>)" is a fact.
|
# not then "external(<pkg>)" is a fact.
|
||||||
|
@ -807,52 +804,40 @@ def external_packages(self):
|
||||||
externals = data.get('externals', [])
|
externals = data.get('externals', [])
|
||||||
external_specs = [spack.spec.Spec(x['spec']) for x in externals]
|
external_specs = [spack.spec.Spec(x['spec']) for x in externals]
|
||||||
|
|
||||||
# Compute versions with appropriate weights
|
# Compute versions with appropriate weights. This accounts for the
|
||||||
|
# fact that we should prefer more recent versions, but specs in
|
||||||
|
# packages.yaml may not be ordered in that sense.
|
||||||
external_versions = [
|
external_versions = [
|
||||||
(x.version, idx) for idx, x in enumerate(external_specs)
|
(x.version, local_idx)
|
||||||
|
for local_idx, x in enumerate(external_specs)
|
||||||
]
|
]
|
||||||
external_versions = [
|
external_versions = [
|
||||||
(v, -(w + 1), idx)
|
(v, -(w + 1), local_idx)
|
||||||
for w, (v, idx) in enumerate(sorted(external_versions))
|
for w, (v, local_idx) in enumerate(sorted(external_versions))
|
||||||
]
|
]
|
||||||
for version, weight, id in external_versions:
|
for version, weight, id in external_versions:
|
||||||
self.gen.fact(fn.external_version_declared(
|
self.gen.fact(fn.external_version_declared(
|
||||||
pkg_name, str(version), weight, id
|
pkg_name, str(version), weight, id
|
||||||
))
|
))
|
||||||
|
|
||||||
# Establish an equivalence between "external_spec(pkg, id)"
|
for local_idx, spec in enumerate(external_specs):
|
||||||
# and the clauses of that spec, so that we have a uniform
|
global_id = self._condition_id_counter
|
||||||
# way to identify it
|
self._condition_id_counter += 1
|
||||||
spec_id_list = []
|
|
||||||
for id, spec in enumerate(external_specs):
|
# Declare the global ID associated with this external spec
|
||||||
self.gen.newline()
|
self.gen.fact(fn.external_spec(global_id, pkg_name))
|
||||||
spec_id = fn.external_spec(pkg_name, id)
|
|
||||||
|
# Local index into packages.yaml
|
||||||
|
self.gen.fact(fn.external_spec_index(global_id, pkg_name, local_idx))
|
||||||
|
|
||||||
|
# Add conditions to be satisfied for this external
|
||||||
self.possible_versions[spec.name].add(spec.version)
|
self.possible_versions[spec.name].add(spec.version)
|
||||||
clauses = self.spec_clauses(spec, body=True)
|
clauses = self.spec_clauses(spec, body=True)
|
||||||
# This is an iff below, wish it could be written in a
|
|
||||||
# more compact form
|
|
||||||
self.gen.rule(head=spec_id.symbol(), body=AspAnd(*clauses))
|
|
||||||
for clause in clauses:
|
for clause in clauses:
|
||||||
self.gen.rule(clause, spec_id.symbol())
|
self.gen.fact(
|
||||||
spec_id_list.append(spec_id)
|
fn.external_spec_condition(global_id, clause.name, *clause.args)
|
||||||
|
)
|
||||||
# TODO: find another way to do everything below, without
|
self.gen.newline()
|
||||||
# TODO: generating ground rules.
|
|
||||||
|
|
||||||
# If one of the external specs is selected then the package
|
|
||||||
# is external and viceversa
|
|
||||||
# TODO: make it possible to declare the rule like below
|
|
||||||
# self.gen.iff(expr1=fn.external(pkg_name),
|
|
||||||
# expr2=one_of_the_externals)
|
|
||||||
self.gen.newline()
|
|
||||||
# FIXME: self.gen.one_of_iff(fn.external(pkg_name), spec_id_list)
|
|
||||||
one_of_the_externals = self.gen.one_of(*spec_id_list)
|
|
||||||
external_str = fn.external(pkg_name)
|
|
||||||
external_rule = "{0} :- {1}.\n{1} :- {0}.\n".format(
|
|
||||||
external_str, str(one_of_the_externals)
|
|
||||||
)
|
|
||||||
self.gen.out.write(external_rule)
|
|
||||||
self.gen.control.add("base", [], external_rule)
|
|
||||||
|
|
||||||
def preferred_variants(self, pkg_name):
|
def preferred_variants(self, pkg_name):
|
||||||
"""Facts on concretization preferences, as read from packages.yaml"""
|
"""Facts on concretization preferences, as read from packages.yaml"""
|
||||||
|
@ -1513,7 +1498,7 @@ def node_flag_source(self, pkg, source):
|
||||||
def no_flags(self, pkg, flag_type):
|
def no_flags(self, pkg, flag_type):
|
||||||
self._specs[pkg].compiler_flags[flag_type] = []
|
self._specs[pkg].compiler_flags[flag_type] = []
|
||||||
|
|
||||||
def external_spec(self, pkg, idx):
|
def external_spec_selected(self, global_id, pkg, idx):
|
||||||
"""This means that the external spec and index idx
|
"""This means that the external spec and index idx
|
||||||
has been selected for this package.
|
has been selected for this package.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -258,9 +258,25 @@ external(Package) :-
|
||||||
version(Package, Version), version_weight(Package, Weight),
|
version(Package, Version), version_weight(Package, Weight),
|
||||||
external_version_declared(Package, Version, Weight, ID).
|
external_version_declared(Package, Version, Weight, ID).
|
||||||
|
|
||||||
external_spec(Package, ID) :-
|
% determine if an external spec has been selected
|
||||||
|
external_spec_selected(ID, Package, LocalIndex) :-
|
||||||
version(Package, Version), version_weight(Package, Weight),
|
version(Package, Version), version_weight(Package, Weight),
|
||||||
external_version_declared(Package, Version, Weight, ID).
|
external_spec_index(ID, Package, LocalIndex),
|
||||||
|
external_version_declared(Package, Version, Weight, LocalIndex),
|
||||||
|
external_spec_conditions_hold(ID, Package).
|
||||||
|
|
||||||
|
% determine if all the conditions on an external spec hold. If they do
|
||||||
|
% the spec can be selected.
|
||||||
|
external_spec_conditions_hold(ID, Package) :-
|
||||||
|
attr(Name, Arg1) : external_spec_condition(ID, Name, Arg1);
|
||||||
|
attr(Name, Arg1, Arg2) : external_spec_condition(ID, Name, Arg1, Arg2);
|
||||||
|
attr(Name, Arg1, Arg2, Arg3) : external_spec_condition(ID, Name, Arg1, Arg2, Arg3);
|
||||||
|
external_spec(ID, Package);
|
||||||
|
node(Package).
|
||||||
|
|
||||||
|
% it cannot happen that a spec is external, but none of the external specs
|
||||||
|
% conditions hold.
|
||||||
|
:- external(Package), not external_spec_conditions_hold(_, Package).
|
||||||
|
|
||||||
%-----------------------------------------------------------------------------
|
%-----------------------------------------------------------------------------
|
||||||
% Variant semantics
|
% Variant semantics
|
||||||
|
|
|
@ -24,4 +24,4 @@
|
||||||
#show compiler_weight/2.
|
#show compiler_weight/2.
|
||||||
#show node_target_match/2.
|
#show node_target_match/2.
|
||||||
#show node_target_weight/2.
|
#show node_target_weight/2.
|
||||||
#show external_spec/2.
|
#show external_spec_selected/3.
|
||||||
|
|
Loading…
Reference in a new issue