package : added a stub for AutotoolsPackage, examples in szip and swiftsim
This commit is contained in:
		| @@ -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, | ||||
|                    '--enable-mpi' if '+mpi' in spec else '--disable-mpi', | ||||
|                    '--enable-optimization'] | ||||
|         configure(*options) | ||||
|         make() | ||||
|         make("install") | ||||
|     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'] | ||||
|   | ||||
| @@ -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" | ||||
|     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', | ||||
|                   '--enable-shared', | ||||
|                   '--enable-static', | ||||
|                   '--enable-encoding') | ||||
|  | ||||
|         make() | ||||
|         make("install") | ||||
|     def configure_args(self): | ||||
|         return ['--enable-production', | ||||
|                 '--enable-shared', | ||||
|                 '--enable-static', | ||||
|                 '--enable-encoding'] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 alalazo
					alalazo