concretizer: handle dependency types

This commit is contained in:
Todd Gamblin 2019-10-17 00:01:44 -07:00
parent cde10692b0
commit db62b00d58
5 changed files with 42 additions and 17 deletions

View File

@ -101,8 +101,9 @@ def solve(parser, args):
assert best[1] == result.answers[-1][1] assert best[1] == result.answers[-1][1]
opt, i, answer = best opt, i, answer = best
tty.msg("Best of %d answers." % (i + 1)) if not args.yaml:
tty.msg("Optimization %s" % opt) tty.msg("Best of %d answers." % (i + 1))
tty.msg("Optimization %s" % opt)
# iterate over roots from command line # iterate over roots from command line
for spec in specs: for spec in specs:

View File

@ -19,6 +19,7 @@
import spack import spack
import spack.cmd import spack.cmd
import spack.config import spack.config
import spack.dependency
import spack.spec import spack.spec
import spack.package import spack.package
import spack.package_prefs import spack.package_prefs
@ -345,17 +346,26 @@ def pkg_rules(self, pkg):
# dependencies # dependencies
for name, conditions in pkg.dependencies.items(): for name, conditions in pkg.dependencies.items():
for cond, dep in conditions.items(): for cond, dep in conditions.items():
decl = fn.declared_dependency(dep.pkg.name, dep.spec.name)
if cond == spack.spec.Spec(): if cond == spack.spec.Spec():
self.fact(decl) for t in dep.type:
self.fact(
fn.declared_dependency(
dep.pkg.name, dep.spec.name, t
)
)
else: else:
named_cond = cond.copy() named_cond = cond.copy()
if not named_cond.name: if not named_cond.name:
named_cond.name = pkg.name named_cond.name = pkg.name
self.rule( for t in dep.type:
decl, self.rule(
self._and(*self.spec_clauses(named_cond, body=True)) fn.declared_dependency(
) dep.pkg.name, dep.spec.name, t
),
self._and(
*self.spec_clauses(named_cond, body=True)
)
)
# virtual preferences # virtual preferences
self.virtual_preferences( self.virtual_preferences(
@ -586,9 +596,13 @@ def node_compiler_version(self, pkg, compiler, version):
self._specs[pkg].compiler.versions = spack.version.VersionList( self._specs[pkg].compiler.versions = spack.version.VersionList(
[version]) [version])
def depends_on(self, pkg, dep): def depends_on(self, pkg, dep, type):
self._specs[pkg]._add_dependency( dependency = self._specs[pkg]._dependencies.get(dep)
self._specs[dep], ('link', 'run')) if not dependency:
self._specs[pkg]._add_dependency(
self._specs[dep], (type,))
else:
dependency.add_type(type)
def call_actions_for_functions(self, function_strings): def call_actions_for_functions(self, function_strings):
function_re = re.compile(r'(\w+)\(([^)]*)\)') function_re = re.compile(r'(\w+)\(([^)]*)\)')
@ -665,6 +679,8 @@ def parse_best(self, output, result):
costs = re.split(r"\s+", next(output).strip()) costs = re.split(r"\s+", next(output).strip())
opt = [int(x) for x in costs[1:]] opt = [int(x) for x in costs[1:]]
for spec in self._specs.values():
spec._mark_concrete()
result.answers.append((opt, best_model_number, self._specs)) result.answers.append((opt, best_model_number, self._specs))

View File

@ -24,12 +24,15 @@ version_weight(P, V, N) :- version(P, V), version_declared(P, V, N).
%----------------------------------------------------------------------------- %-----------------------------------------------------------------------------
% Dependency semantics % Dependency semantics
%----------------------------------------------------------------------------- %-----------------------------------------------------------------------------
% Dependencies of any type imply that one package "depends on" another
depends_on(P, D) :- depends_on(P, D, _).
% declared dependencies are real if they're not virtual % declared dependencies are real if they're not virtual
depends_on(P, D) :- declared_dependency(P, D), not virtual(D), node(P). depends_on(P, D, T) :- declared_dependency(P, D, T), not virtual(D), node(P).
% if you declare a dependency on a virtual, you depend on one of its providers % if you declare a dependency on a virtual, you depend on one of its providers
1 { depends_on(P, Q) : provides_virtual(Q, V) } 1 1 { depends_on(P, Q, T) : provides_virtual(Q, V) } 1
:- declared_dependency(P, V), virtual(V), node(P). :- declared_dependency(P, V, T), virtual(V), node(P).
% for any virtual, there can only be one node providing it in the DAG % for any virtual, there can only be one node providing it in the DAG
provider(P, V) :- node(P), provides_virtual(P, V). provider(P, V) :- node(P), provides_virtual(P, V).
@ -64,8 +67,8 @@ needed(D) :- needed(P), depends_on(P, D), node(P).
node(D) :- node(P), depends_on(P, D). node(D) :- node(P), depends_on(P, D).
% do not warn if generated program contains none of these. % do not warn if generated program contains none of these.
#defined depends_on/2. #defined depends_on/3.
#defined declared_dependency/2. #defined declared_dependency/3.
#defined virtual/1. #defined virtual/1.
#defined provides_virtual/2. #defined provides_virtual/2.
#defined pkg_provider_preference/4. #defined pkg_provider_preference/4.

View File

@ -4,7 +4,7 @@
% This section determines what parts of the model are printed at the end % This section determines what parts of the model are printed at the end
%============================================================================== %==============================================================================
#show node/1. #show node/1.
#show depends_on/2. #show depends_on/3.
#show version/2. #show version/2.
#show variant_value/3. #show variant_value/3.
#show arch_platform/2. #show arch_platform/2.

View File

@ -622,6 +622,11 @@ def update_deptypes(self, deptypes):
def copy(self): def copy(self):
return DependencySpec(self.parent, self.spec, self.deptypes) return DependencySpec(self.parent, self.spec, self.deptypes)
def add_type(self, type):
self.deptypes = dp.canonical_deptype(
self.deptypes + dp.canonical_deptype(type)
)
def _cmp_key(self): def _cmp_key(self):
return (self.parent.name if self.parent else None, return (self.parent.name if self.parent else None,
self.spec.name if self.spec else None, self.spec.name if self.spec else None,