package : added a stub for AutotoolsPackage, examples in szip and swiftsim
This commit is contained in:
parent
8ed028e2d6
commit
8f75d34331
4 changed files with 110 additions and 73 deletions
|
@ -176,10 +176,14 @@
|
|||
# TODO: it's not clear where all the stuff that needs to be included in packages
|
||||
# should live. This file is overloaded for spack core vs. for packages.
|
||||
#
|
||||
__all__ = ['Package', 'CMakePackage', \
|
||||
'Version', 'when', 'ver']
|
||||
__all__ = ['Package',
|
||||
'CMakePackage',
|
||||
'AutotoolsPackage',
|
||||
'Version',
|
||||
'when',
|
||||
'ver']
|
||||
from spack.package import Package, ExtensionConflictError
|
||||
from spack.package import CMakePackage
|
||||
from spack.package import CMakePackage, AutotoolsPackage
|
||||
from spack.version import Version, ver
|
||||
from spack.multimethod import when
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
import string
|
||||
import textwrap
|
||||
import time
|
||||
import inspect
|
||||
import functools
|
||||
import inspect
|
||||
from StringIO import StringIO
|
||||
from urlparse import urlparse
|
||||
|
||||
|
@ -74,7 +74,7 @@ class InstallPhase(object):
|
|||
"""Manages a single phase of the installation
|
||||
|
||||
This descriptor stores at creation time the name of the method it should search
|
||||
for execution. The method is retrieved at get time, so that it can be overridden
|
||||
for execution. The method is retrieved at __get__ time, so that it can be overridden
|
||||
by subclasses of whatever class declared the phases.
|
||||
|
||||
It also provides hooks to execute prerequisite and sanity checks.
|
||||
|
@ -116,31 +116,63 @@ class PackageMeta(type):
|
|||
"""
|
||||
phase_fmt = '_InstallPhase_{0}'
|
||||
|
||||
def __init__(cls, name, bases, attr_dict):
|
||||
super(PackageMeta, cls).__init__(name, bases, attr_dict)
|
||||
# Parse if phases is in attr dict, then set
|
||||
_InstallPhase_sanity_checks = {}
|
||||
_InstallPhase_preconditions = {}
|
||||
|
||||
def __new__(meta, name, bases, attr_dict):
|
||||
# Check if phases is in attr dict, then set
|
||||
# install phases wrappers
|
||||
if 'phases' in attr_dict:
|
||||
cls.phases = [PackageMeta.phase_fmt.format(name) for name in attr_dict['phases']]
|
||||
for phase_name, callback_name in zip(cls.phases, attr_dict['phases']):
|
||||
setattr(cls, phase_name, InstallPhase(callback_name))
|
||||
phases = [PackageMeta.phase_fmt.format(x) for x in attr_dict['phases']]
|
||||
for phase_name, callback_name in zip(phases, attr_dict['phases']):
|
||||
attr_dict[phase_name] = InstallPhase(callback_name)
|
||||
attr_dict['phases'] = phases
|
||||
|
||||
def _transform_checks(check_name):
|
||||
def _append_checks(check_name):
|
||||
# Name of the attribute I am going to check it exists
|
||||
attr_name = PackageMeta.phase_fmt.format(check_name)
|
||||
checks = getattr(cls, attr_name, None)
|
||||
checks = getattr(meta, attr_name)
|
||||
if checks:
|
||||
for phase_name, funcs in checks.items():
|
||||
phase = getattr(cls, PackageMeta.phase_fmt.format(phase_name))
|
||||
phase = attr_dict.get(PackageMeta.phase_fmt.format(phase_name))
|
||||
getattr(phase, check_name).extend(funcs)
|
||||
# TODO : this should delete the attribute, as it is just a placeholder
|
||||
# TODO : to know what to do at class definition time. Clearing it is fine
|
||||
# TODO : too, but it just leaves an empty dictionary in place
|
||||
setattr(cls, attr_name, {})
|
||||
# Clear the attribute for the next class
|
||||
setattr(meta, attr_name, {})
|
||||
|
||||
@classmethod
|
||||
def _register_checks(cls, check_type, *args):
|
||||
def _register_sanity_checks(func):
|
||||
attr_name = PackageMeta.phase_fmt.format(check_type)
|
||||
sanity_checks = getattr(meta, attr_name)
|
||||
for item in args:
|
||||
checks = sanity_checks.setdefault(item, [])
|
||||
checks.append(func)
|
||||
setattr(meta, attr_name, sanity_checks)
|
||||
return func
|
||||
return _register_sanity_checks
|
||||
|
||||
@classmethod
|
||||
def precondition(cls, *args):
|
||||
return cls._register_checks('preconditions', *args)
|
||||
|
||||
@classmethod
|
||||
def sanity_check(cls, *args):
|
||||
return cls._register_checks('sanity_checks', *args)
|
||||
|
||||
if all([not hasattr(x, '_register_checks') for x in bases]):
|
||||
attr_dict['_register_checks'] = _register_checks
|
||||
|
||||
if all([not hasattr(x, 'sanity_check') for x in bases]):
|
||||
attr_dict['sanity_check'] = sanity_check
|
||||
|
||||
if all([not hasattr(x, 'precondition') for x in bases]):
|
||||
attr_dict['precondition'] = precondition
|
||||
|
||||
# Preconditions
|
||||
_transform_checks('preconditions')
|
||||
_append_checks('preconditions')
|
||||
# Sanity checks
|
||||
_transform_checks('sanity_checks')
|
||||
_append_checks('sanity_checks')
|
||||
return super(PackageMeta, meta).__new__(meta, name, bases, attr_dict)
|
||||
|
||||
|
||||
class PackageBase(object):
|
||||
|
@ -993,7 +1025,7 @@ def do_install(self,
|
|||
|
||||
# Ensure package is not already installed
|
||||
# FIXME : skip condition : if any is True skip the installation
|
||||
if 'install' in self.phases and spack.install_layout.check_installed(self.spec):
|
||||
if spack.install_layout.check_installed(self.spec):
|
||||
tty.msg("%s is already installed in %s" % (self.name, self.prefix))
|
||||
rec = spack.installed_db.get_record(self.spec)
|
||||
if (not rec.explicit) and explicit:
|
||||
|
@ -1499,26 +1531,6 @@ def rpath_args(self):
|
|||
"""
|
||||
return " ".join("-Wl,-rpath,%s" % p for p in self.rpath)
|
||||
|
||||
@classmethod
|
||||
def _register_checks(cls, check_type, *args):
|
||||
def _register_sanity_checks(func):
|
||||
attr_name = PackageMeta.phase_fmt.format(check_type)
|
||||
sanity_checks = getattr(cls, attr_name, {})
|
||||
for item in args:
|
||||
checks = sanity_checks.setdefault(item, [])
|
||||
checks.append(func)
|
||||
setattr(cls, attr_name, sanity_checks)
|
||||
return func
|
||||
return _register_sanity_checks
|
||||
|
||||
@classmethod
|
||||
def precondition(cls, *args):
|
||||
return cls._register_checks('preconditions', *args)
|
||||
|
||||
@classmethod
|
||||
def sanity_check(cls, *args):
|
||||
return cls._register_checks('sanity_checks', *args)
|
||||
|
||||
|
||||
class Package(PackageBase):
|
||||
phases = ['install', 'log']
|
||||
|
@ -1527,6 +1539,36 @@ class Package(PackageBase):
|
|||
PackageBase.sanity_check('install')(PackageBase.sanity_check_prefix)
|
||||
|
||||
|
||||
class AutotoolsPackage(PackageBase):
|
||||
phases = ['autoreconf', 'configure', 'build', 'install', 'log']
|
||||
|
||||
def autoreconf(self, spec, prefix):
|
||||
"""Not needed usually, configure should be already there"""
|
||||
pass
|
||||
|
||||
@PackageBase.sanity_check('autoreconf')
|
||||
def is_configure_or_die(self):
|
||||
if not os.path.exists('configure'):
|
||||
raise RuntimeError('configure script not found in {0}'.format(os.getcwd()))
|
||||
|
||||
def configure_args(self):
|
||||
return list()
|
||||
|
||||
def configure(self, spec, prefix):
|
||||
options = ['--prefix={0}'.format(prefix)] + self.configure_args()
|
||||
inspect.getmodule(self).configure(*options)
|
||||
|
||||
def build(self, spec, prefix):
|
||||
inspect.getmodule(self).make()
|
||||
|
||||
def install(self, spec, prefix):
|
||||
inspect.getmodule(self).make('install')
|
||||
|
||||
# This will be used as a registration decorator in user
|
||||
# packages, if need be
|
||||
PackageBase.sanity_check('install')(PackageBase.sanity_check_prefix)
|
||||
|
||||
|
||||
def install_dependency_symlinks(pkg, spec, prefix):
|
||||
"""Execute a dummy install and flatten dependencies"""
|
||||
flatten_dependencies(spec, prefix)
|
||||
|
@ -1637,7 +1679,7 @@ def _hms(seconds):
|
|||
|
||||
|
||||
class CMakePackage(PackageBase):
|
||||
phases = ['setup', 'configure', 'build', 'install', 'provenance']
|
||||
phases = ['configure', 'build', 'install', 'provenance']
|
||||
|
||||
def make_make(self):
|
||||
import multiprocessing
|
||||
|
@ -1657,7 +1699,7 @@ def configure_args(self):
|
|||
|
||||
def configure_env(self):
|
||||
"""Returns package-specific environment under which the configure command should be run."""
|
||||
# FIXME : Why not EnvironmentModules
|
||||
# FIXME : Why not EnvironmentModules and the hooks that PackageBase already provides ?
|
||||
return dict()
|
||||
|
||||
def spack_transitive_include_path(self):
|
||||
|
@ -1720,7 +1762,6 @@ def cmdlist(str):
|
|||
fout.write('\nproc = subprocess.Popen(cmd, env=env)\nproc.wait()\n')
|
||||
set_executable(setup_fname)
|
||||
|
||||
|
||||
def configure(self, spec, prefix):
|
||||
cmake = which('cmake')
|
||||
with working_dir(self.build_directory, create=True):
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
import llnl.util.tty as tty
|
||||
|
||||
|
||||
class Swiftsim(Package):
|
||||
class Swiftsim(AutotoolsPackage):
|
||||
"""
|
||||
SPH With Inter-dependent Fine-grained Tasking (SWIFT) provides
|
||||
astrophysicists with a state of the art framework to perform
|
||||
|
@ -59,19 +59,15 @@ def setup_environment(self, spack_env, run_env):
|
|||
tty.warn('This is needed to clone SWIFT repository')
|
||||
spack_env.set('GIT_SSL_NO_VERIFY', 1)
|
||||
|
||||
def install(self, spec, prefix):
|
||||
# Generate configure from configure.ac
|
||||
# and Makefile.am
|
||||
def autoreconf(self, spec, prefix):
|
||||
libtoolize()
|
||||
aclocal()
|
||||
autoconf()
|
||||
autogen = Executable('./autogen.sh')
|
||||
autogen()
|
||||
|
||||
# Configure and install
|
||||
options = ['--prefix=%s' % prefix,
|
||||
def config_args(self):
|
||||
return ['--prefix=%s' % prefix,
|
||||
'--enable-mpi' if '+mpi' in spec else '--disable-mpi',
|
||||
'--with-metis={0}'.format(self.spec['metis'].prefix),
|
||||
'--enable-optimization']
|
||||
configure(*options)
|
||||
make()
|
||||
make("install")
|
||||
|
|
|
@ -24,26 +24,22 @@
|
|||
##############################################################################
|
||||
from spack import *
|
||||
|
||||
class Szip(Package):
|
||||
"""Szip is an implementation of the extended-Rice lossless compression algorithm.
|
||||
It provides lossless compression of scientific data, and is provided with HDF
|
||||
software products."""
|
||||
|
||||
class Szip(AutotoolsPackage):
|
||||
"""Szip is an implementation of the extended-Rice lossless
|
||||
compression algorithm.
|
||||
|
||||
It provides lossless compression of scientific data, and is
|
||||
provided with HDF software products.
|
||||
"""
|
||||
|
||||
homepage = "https://www.hdfgroup.org/doc_resource/SZIP/"
|
||||
url = "http://www.hdfgroup.org/ftp/lib-external/szip/2.1/src/szip-2.1.tar.gz"
|
||||
|
||||
version('2.1', '902f831bcefb69c6b635374424acbead')
|
||||
|
||||
@Package.sanity_check('install')
|
||||
def always_raise(self):
|
||||
raise RuntimeError('Precondition not respected')
|
||||
|
||||
def install(self, spec, prefix):
|
||||
configure('--prefix=%s' % prefix,
|
||||
'--enable-production',
|
||||
def configure_args(self):
|
||||
return ['--enable-production',
|
||||
'--enable-shared',
|
||||
'--enable-static',
|
||||
'--enable-encoding')
|
||||
|
||||
make()
|
||||
make("install")
|
||||
'--enable-encoding']
|
||||
|
|
Loading…
Reference in a new issue