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
|
# 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.
|
# should live. This file is overloaded for spack core vs. for packages.
|
||||||
#
|
#
|
||||||
__all__ = ['Package', 'CMakePackage', \
|
__all__ = ['Package',
|
||||||
'Version', 'when', 'ver']
|
'CMakePackage',
|
||||||
|
'AutotoolsPackage',
|
||||||
|
'Version',
|
||||||
|
'when',
|
||||||
|
'ver']
|
||||||
from spack.package import Package, ExtensionConflictError
|
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.version import Version, ver
|
||||||
from spack.multimethod import when
|
from spack.multimethod import when
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@
|
||||||
import string
|
import string
|
||||||
import textwrap
|
import textwrap
|
||||||
import time
|
import time
|
||||||
import inspect
|
|
||||||
import functools
|
import functools
|
||||||
|
import inspect
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
from urlparse import urlparse
|
from urlparse import urlparse
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ class InstallPhase(object):
|
||||||
"""Manages a single phase of the installation
|
"""Manages a single phase of the installation
|
||||||
|
|
||||||
This descriptor stores at creation time the name of the method it should search
|
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.
|
by subclasses of whatever class declared the phases.
|
||||||
|
|
||||||
It also provides hooks to execute prerequisite and sanity checks.
|
It also provides hooks to execute prerequisite and sanity checks.
|
||||||
|
@ -116,31 +116,63 @@ class PackageMeta(type):
|
||||||
"""
|
"""
|
||||||
phase_fmt = '_InstallPhase_{0}'
|
phase_fmt = '_InstallPhase_{0}'
|
||||||
|
|
||||||
def __init__(cls, name, bases, attr_dict):
|
_InstallPhase_sanity_checks = {}
|
||||||
super(PackageMeta, cls).__init__(name, bases, attr_dict)
|
_InstallPhase_preconditions = {}
|
||||||
# Parse if phases is in attr dict, then set
|
|
||||||
|
def __new__(meta, name, bases, attr_dict):
|
||||||
|
# Check if phases is in attr dict, then set
|
||||||
# install phases wrappers
|
# install phases wrappers
|
||||||
if 'phases' in attr_dict:
|
if 'phases' in attr_dict:
|
||||||
cls.phases = [PackageMeta.phase_fmt.format(name) for name in attr_dict['phases']]
|
phases = [PackageMeta.phase_fmt.format(x) for x in attr_dict['phases']]
|
||||||
for phase_name, callback_name in zip(cls.phases, attr_dict['phases']):
|
for phase_name, callback_name in zip(phases, attr_dict['phases']):
|
||||||
setattr(cls, phase_name, InstallPhase(callback_name))
|
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)
|
attr_name = PackageMeta.phase_fmt.format(check_name)
|
||||||
checks = getattr(cls, attr_name, None)
|
checks = getattr(meta, attr_name)
|
||||||
if checks:
|
if checks:
|
||||||
for phase_name, funcs in checks.items():
|
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)
|
getattr(phase, check_name).extend(funcs)
|
||||||
# TODO : this should delete the attribute, as it is just a placeholder
|
# Clear the attribute for the next class
|
||||||
# TODO : to know what to do at class definition time. Clearing it is fine
|
setattr(meta, attr_name, {})
|
||||||
# TODO : too, but it just leaves an empty dictionary in place
|
|
||||||
setattr(cls, 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
|
# Preconditions
|
||||||
_transform_checks('preconditions')
|
_append_checks('preconditions')
|
||||||
# Sanity checks
|
# Sanity checks
|
||||||
_transform_checks('sanity_checks')
|
_append_checks('sanity_checks')
|
||||||
|
return super(PackageMeta, meta).__new__(meta, name, bases, attr_dict)
|
||||||
|
|
||||||
|
|
||||||
class PackageBase(object):
|
class PackageBase(object):
|
||||||
|
@ -993,7 +1025,7 @@ def do_install(self,
|
||||||
|
|
||||||
# Ensure package is not already installed
|
# Ensure package is not already installed
|
||||||
# FIXME : skip condition : if any is True skip the installation
|
# 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))
|
tty.msg("%s is already installed in %s" % (self.name, self.prefix))
|
||||||
rec = spack.installed_db.get_record(self.spec)
|
rec = spack.installed_db.get_record(self.spec)
|
||||||
if (not rec.explicit) and explicit:
|
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)
|
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):
|
class Package(PackageBase):
|
||||||
phases = ['install', 'log']
|
phases = ['install', 'log']
|
||||||
|
@ -1527,6 +1539,36 @@ class Package(PackageBase):
|
||||||
PackageBase.sanity_check('install')(PackageBase.sanity_check_prefix)
|
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):
|
def install_dependency_symlinks(pkg, spec, prefix):
|
||||||
"""Execute a dummy install and flatten dependencies"""
|
"""Execute a dummy install and flatten dependencies"""
|
||||||
flatten_dependencies(spec, prefix)
|
flatten_dependencies(spec, prefix)
|
||||||
|
@ -1637,7 +1679,7 @@ def _hms(seconds):
|
||||||
|
|
||||||
|
|
||||||
class CMakePackage(PackageBase):
|
class CMakePackage(PackageBase):
|
||||||
phases = ['setup', 'configure', 'build', 'install', 'provenance']
|
phases = ['configure', 'build', 'install', 'provenance']
|
||||||
|
|
||||||
def make_make(self):
|
def make_make(self):
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
@ -1657,7 +1699,7 @@ def configure_args(self):
|
||||||
|
|
||||||
def configure_env(self):
|
def configure_env(self):
|
||||||
"""Returns package-specific environment under which the configure command should be run."""
|
"""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()
|
return dict()
|
||||||
|
|
||||||
def spack_transitive_include_path(self):
|
def spack_transitive_include_path(self):
|
||||||
|
@ -1720,7 +1762,6 @@ def cmdlist(str):
|
||||||
fout.write('\nproc = subprocess.Popen(cmd, env=env)\nproc.wait()\n')
|
fout.write('\nproc = subprocess.Popen(cmd, env=env)\nproc.wait()\n')
|
||||||
set_executable(setup_fname)
|
set_executable(setup_fname)
|
||||||
|
|
||||||
|
|
||||||
def configure(self, spec, prefix):
|
def configure(self, spec, prefix):
|
||||||
cmake = which('cmake')
|
cmake = which('cmake')
|
||||||
with working_dir(self.build_directory, create=True):
|
with working_dir(self.build_directory, create=True):
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
|
|
||||||
class Swiftsim(Package):
|
class Swiftsim(AutotoolsPackage):
|
||||||
"""
|
"""
|
||||||
SPH With Inter-dependent Fine-grained Tasking (SWIFT) provides
|
SPH With Inter-dependent Fine-grained Tasking (SWIFT) provides
|
||||||
astrophysicists with a state of the art framework to perform
|
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')
|
tty.warn('This is needed to clone SWIFT repository')
|
||||||
spack_env.set('GIT_SSL_NO_VERIFY', 1)
|
spack_env.set('GIT_SSL_NO_VERIFY', 1)
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def autoreconf(self, spec, prefix):
|
||||||
# Generate configure from configure.ac
|
|
||||||
# and Makefile.am
|
|
||||||
libtoolize()
|
libtoolize()
|
||||||
aclocal()
|
aclocal()
|
||||||
autoconf()
|
autoconf()
|
||||||
autogen = Executable('./autogen.sh')
|
autogen = Executable('./autogen.sh')
|
||||||
autogen()
|
autogen()
|
||||||
|
|
||||||
# Configure and install
|
def config_args(self):
|
||||||
options = ['--prefix=%s' % prefix,
|
return ['--prefix=%s' % prefix,
|
||||||
'--enable-mpi' if '+mpi' in spec else '--disable-mpi',
|
'--enable-mpi' if '+mpi' in spec else '--disable-mpi',
|
||||||
'--enable-optimization']
|
'--with-metis={0}'.format(self.spec['metis'].prefix),
|
||||||
configure(*options)
|
'--enable-optimization']
|
||||||
make()
|
|
||||||
make("install")
|
|
||||||
|
|
|
@ -24,26 +24,22 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
from spack import *
|
from spack import *
|
||||||
|
|
||||||
class Szip(Package):
|
|
||||||
"""Szip is an implementation of the extended-Rice lossless compression algorithm.
|
class Szip(AutotoolsPackage):
|
||||||
It provides lossless compression of scientific data, and is provided with HDF
|
"""Szip is an implementation of the extended-Rice lossless
|
||||||
software products."""
|
compression algorithm.
|
||||||
|
|
||||||
|
It provides lossless compression of scientific data, and is
|
||||||
|
provided with HDF software products.
|
||||||
|
"""
|
||||||
|
|
||||||
homepage = "https://www.hdfgroup.org/doc_resource/SZIP/"
|
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"
|
url = "http://www.hdfgroup.org/ftp/lib-external/szip/2.1/src/szip-2.1.tar.gz"
|
||||||
|
|
||||||
version('2.1', '902f831bcefb69c6b635374424acbead')
|
version('2.1', '902f831bcefb69c6b635374424acbead')
|
||||||
|
|
||||||
@Package.sanity_check('install')
|
def configure_args(self):
|
||||||
def always_raise(self):
|
return ['--enable-production',
|
||||||
raise RuntimeError('Precondition not respected')
|
'--enable-shared',
|
||||||
|
'--enable-static',
|
||||||
def install(self, spec, prefix):
|
'--enable-encoding']
|
||||||
configure('--prefix=%s' % prefix,
|
|
||||||
'--enable-production',
|
|
||||||
'--enable-shared',
|
|
||||||
'--enable-static',
|
|
||||||
'--enable-encoding')
|
|
||||||
|
|
||||||
make()
|
|
||||||
make("install")
|
|
||||||
|
|
Loading…
Reference in a new issue