Move concretization into its own class.

Allows easy overriding of a single policy.
This commit is contained in:
Todd Gamblin 2013-11-23 15:18:43 -08:00
parent f31aaeed98
commit 6cf6eac3de
5 changed files with 73 additions and 56 deletions

View File

@ -15,66 +15,72 @@
from spack.spec import * from spack.spec import *
def concretize_version(spec): class DefaultConcretizer(object):
"""If the spec is already concrete, return. Otherwise take """This class doesn't have any state, it just provides some methods for
the most recent available version, and default to the package's concretization. You can subclass it to override just some of the
version if there are no avaialble versions. default concretization strategies, or you can override all of them.
""" """
# return if already concrete.
if spec.versions.concrete:
return
pkg = spec.package def concretize_version(self, spec):
"""If the spec is already concrete, return. Otherwise take
the most recent available version, and default to the package's
version if there are no avaialble versions.
"""
# return if already concrete.
if spec.versions.concrete:
return
# If there are known avaialble versions, return the most recent pkg = spec.package
available_versions = pkg.available_versions
if available_versions: # If there are known avaialble versions, return the most recent
spec.versions = ver([available_versions[-1]]) available_versions = pkg.available_versions
else: if available_versions:
spec.versions = ver([pkg.version]) spec.versions = ver([available_versions[-1]])
else:
spec.versions = ver([pkg.version])
def concretize_architecture(spec): def concretize_architecture(self, spec):
"""If the spec already had an architecture, return. Otherwise if """If the spec already had an architecture, return. Otherwise if
the root of the DAG has an architecture, then use that. the root of the DAG has an architecture, then use that.
Otherwise take the system's default architecture. Otherwise take the system's default architecture.
Intuition: Architectures won't be set a lot, and generally you Intuition: Architectures won't be set a lot, and generally you
want the host system's architecture. When architectures are want the host system's architecture. When architectures are
mised in a spec, it is likely because the tool requries a mised in a spec, it is likely because the tool requries a
cross-compiled component, e.g. for tools that run on BlueGene cross-compiled component, e.g. for tools that run on BlueGene
or Cray machines. These constraints will likely come directly or Cray machines. These constraints will likely come directly
from packages, so require the user to be explicit if they want from packages, so require the user to be explicit if they want
to mess with the architecture, and revert to the default when to mess with the architecture, and revert to the default when
they're not explicit. they're not explicit.
""" """
if spec.architecture is not None: if spec.architecture is not None:
return return
if spec.root.architecture: if spec.root.architecture:
spec.architecture = spec.root.architecture spec.architecture = spec.root.architecture
else: else:
spec.architecture = spack.arch.sys_type() spec.architecture = spack.arch.sys_type()
def concretize_compiler(spec): def concretize_compiler(self, spec):
"""Currently just sets the compiler to gcc or throws an exception """Currently just sets the compiler to gcc or throws an exception
if the compiler is set to something else. if the compiler is set to something else.
TODO: implement below description. TODO: implement below description.
If the spec already has a compiler, we're done. If not, then If the spec already has a compiler, we're done. If not, then
take the compiler used for the nearest ancestor with a concrete take the compiler used for the nearest ancestor with a concrete
compiler, or use the system default if there is no ancestor compiler, or use the system default if there is no ancestor
with a compiler. with a compiler.
Intuition: Use the system default if no package that depends on Intuition: Use the system 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.
""" """
if spec.compiler and spec.compiler.concrete: if spec.compiler and spec.compiler.concrete:
if spec.compiler != spack.compilers.default_compiler(): if spec.compiler != spack.compilers.default_compiler():
raise spack.spec.UnknownCompilerError(str(spec.compiler)) raise spack.spec.UnknownCompilerError(str(spec.compiler))
else: else:
spec.compiler = spack.compilers.default_compiler() spec.compiler = spack.compilers.default_compiler()

View File

@ -5,6 +5,7 @@
from spack.util.filesystem import * from spack.util.filesystem import *
from spack.util.executable import * from spack.util.executable import *
from spack.directory_layout import DefaultDirectoryLayout from spack.directory_layout import DefaultDirectoryLayout
from spack.concretize import DefaultConcretizer
# This lives in $prefix/lib/spac/spack/__file__ # This lives in $prefix/lib/spac/spack/__file__
prefix = ancestor(__file__, 4) prefix = ancestor(__file__, 4)
@ -31,6 +32,13 @@
# #
install_layout = DefaultDirectoryLayout(install_path) install_layout = DefaultDirectoryLayout(install_path)
#
# This controls how things are concretized in spack.
# Replace it with a subclass if you want different
# policies.
#
concretizer = DefaultConcretizer()
# Version information # Version information
spack_version = Version("0.5") spack_version = Version("0.5")

View File

@ -81,4 +81,4 @@ def provides(*args):
# Get the enclosing package's scope and add deps to it. # Get the enclosing package's scope and add deps to it.
provided = _caller_locals().setdefault("provided", []) provided = _caller_locals().setdefault("provided", [])
for name in args: for name in args:
provides.append(name) provided.append(name)

View File

@ -67,7 +67,6 @@
import tty import tty
import spack.parse import spack.parse
import spack.error import spack.error
import spack.concretize
import spack.compilers import spack.compilers
import spack.compilers.gcc import spack.compilers.gcc
import spack.packages as packages import spack.packages as packages
@ -330,6 +329,8 @@ def virtual(self):
"""Right now, a spec is virtual if no package exists with its name. """Right now, a spec is virtual if no package exists with its name.
TODO: revisit this -- might need to use a separate namespace and TODO: revisit this -- might need to use a separate namespace and
be more explicit about this. be more explicit about this.
Possible idea: just use conventin and make virtual deps all
caps, e.g., MPI vs mpi.
""" """
return not packages.exists(self.name) return not packages.exists(self.name)
@ -400,9 +401,9 @@ def _concretize_helper(self, presets):
if self.name in presets: if self.name in presets:
self.constrain(presets[self.name]) self.constrain(presets[self.name])
else: else:
spack.concretize.concretize_architecture(self) spack.concretizer.concretize_architecture(self)
spack.concretize.concretize_compiler(self) spack.concretizer.concretize_compiler(self)
spack.concretize.concretize_version(self) spack.concretizer.concretize_version(self)
presets[self.name] = self presets[self.name] = self

View File

@ -10,6 +10,8 @@ class Mpich(Package):
versions = '1.0.3, 1.3.2p1, 1.4.1p1, 3.0.4, 3.1b1' versions = '1.0.3, 1.3.2p1, 1.4.1p1, 3.0.4, 3.1b1'
provides('mpi')
def install(self, prefix): def install(self, prefix):
configure("--prefix=%s" % prefix) configure("--prefix=%s" % prefix)
make() make()