Use preferred package rules when concretize'ing specs

This commit is contained in:
Matthew LeGendre 2015-05-29 12:20:32 -07:00
parent b5c597b318
commit 8d7b7e5d5d
2 changed files with 38 additions and 32 deletions

View file

@ -38,6 +38,7 @@
import spack.architecture import spack.architecture
import spack.error import spack.error
from spack.version import * from spack.version import *
from functools import partial
@ -49,8 +50,8 @@ class DefaultConcretizer(object):
def concretize_version(self, spec): def concretize_version(self, spec):
"""If the spec is already concrete, return. Otherwise take """If the spec is already concrete, return. Otherwise take
the most recent available version, and default to the package's the preferred version from spackconfig, and default to the package's
version if there are no avaialble versions. version if there are no available versions.
TODO: In many cases we probably want to look for installed TODO: In many cases we probably want to look for installed
versions of each package and use an installed version versions of each package and use an installed version
@ -68,12 +69,14 @@ def concretize_version(self, spec):
# If there are known available versions, return the most recent # If there are known available versions, return the most recent
# version that satisfies the spec # version that satisfies the spec
pkg = spec.package pkg = spec.package
cmp_versions = partial(spack.pkgsort.version_compare, spec.name)
valid_versions = sorted( valid_versions = sorted(
[v for v in pkg.versions [v for v in pkg.versions
if any(v.satisfies(sv) for sv in spec.versions)]) if any(v.satisfies(sv) for sv in spec.versions)],
cmp=cmp_versions)
if valid_versions: if valid_versions:
spec.versions = ver([valid_versions[-1]]) spec.versions = ver([valid_versions[0]])
else: else:
# We don't know of any SAFE versions that match the given # We don't know of any SAFE versions that match the given
# spec. Grab the spec's versions and grab the highest # spec. Grab the spec's versions and grab the highest
@ -138,10 +141,10 @@ def concretize_compiler(self, spec):
"""If the spec already has a compiler, we're done. If not, then take """If the spec already has a compiler, we're done. If not, then take
the compiler used for the nearest ancestor with a compiler the compiler used for the nearest ancestor with a compiler
spec and use that. If the ancestor's compiler is not spec and use that. If the ancestor's compiler is not
concrete, then give it a valid version. If there is no concrete, then used the preferred compiler as specified in
ancestor with a compiler, use the system default compiler. spackconfig.
Intuition: Use the system default if no package that depends on Intuition: Use the spackconfig default if no package that depends on
this one has a strict compiler requirement. Otherwise, try to this one has a strict compiler requirement. Otherwise, try to
build with the compiler that will be used by libraries that build with the compiler that will be used by libraries that
link to this one, to maximize compatibility. link to this one, to maximize compatibility.
@ -153,40 +156,43 @@ def concretize_compiler(self, spec):
spec.compiler in all_compilers): spec.compiler in all_compilers):
return False return False
try: # Find the parent spec that has a compiler, or the root if none do
nearest = next(p for p in spec.traverse(direction='parents') parent_spec = next(p for p in spec.traverse(direction='parents')
if p.compiler is not None).compiler if p.compiler is not None or not p.dependents)
parent_compiler = parent_spec.compiler
if not nearest in all_compilers: assert(parent_spec)
# Take the newest compiler that saisfies the spec
matches = sorted(spack.compilers.find(nearest)) # Check if the compiler is already fully specified
if not matches: if parent_compiler in all_compilers:
raise UnavailableCompilerVersionError(nearest) spec.compiler = parent_compiler.copy()
return True
# copy concrete version into nearest spec
nearest.versions = matches[-1].versions.copy() # Filter the compilers into a sorted list based on the compiler_order from spackconfig
assert(nearest.concrete) compiler_list = all_compilers if not parent_compiler else spack.compilers.find(parent_compiler)
cmp_compilers = partial(spack.pkgsort.compiler_compare, parent_spec.name)
spec.compiler = nearest.copy() matches = sorted(compiler_list, cmp=cmp_compilers)
if not matches:
except StopIteration: raise UnavailableCompilerVersionError(parent_compiler)
spec.compiler = spack.compilers.default_compiler().copy()
# copy concrete version into parent_compiler
spec.compiler = matches[0].copy()
assert(spec.compiler.concrete)
return True # things changed. return True # things changed.
def choose_provider(self, spec, providers): def choose_provider(self, package_spec, spec, providers):
"""This is invoked for virtual specs. Given a spec with a virtual name, """This is invoked for virtual specs. Given a spec with a virtual name,
say "mpi", and a list of specs of possible providers of that spec, say "mpi", and a list of specs of possible providers of that spec,
select a provider and return it. select a provider and return it.
""" """
assert(spec.virtual) assert(spec.virtual)
assert(providers) assert(providers)
provider_cmp = partial(spack.pkgsort.provider_compare, package_spec.name, spec.name)
sorted_providers = sorted(providers, cmp=provider_cmp)
first_key = sorted_providers[0]
index = spack.spec.index_specs(providers) return first_key
first_key = sorted(index.keys())[0]
latest_version = sorted(index[first_key])[-1]
return latest_version
class UnavailableCompilerVersionError(spack.error.SpackError): class UnavailableCompilerVersionError(spack.error.SpackError):

View file

@ -796,7 +796,7 @@ def _expand_virtual_packages(self):
for spec in virtuals: for spec in virtuals:
providers = spack.db.providers_for(spec) providers = spack.db.providers_for(spec)
concrete = spack.concretizer.choose_provider(spec, providers) concrete = spack.concretizer.choose_provider(self, spec, providers)
concrete = concrete.copy() concrete = concrete.copy()
spec._replace_with(concrete) spec._replace_with(concrete)
changed = True changed = True