package : added EditableMakefile
Modifications : - added EditableMakefile to PackageBase subclasses - astyle modified as an example - preliminary hook to stop at a certain phase of install
This commit is contained in:
parent
8f75d34331
commit
a43c63f149
@ -179,11 +179,12 @@
|
||||
__all__ = ['Package',
|
||||
'CMakePackage',
|
||||
'AutotoolsPackage',
|
||||
'EditableMakefile',
|
||||
'Version',
|
||||
'when',
|
||||
'ver']
|
||||
from spack.package import Package, ExtensionConflictError
|
||||
from spack.package import CMakePackage, AutotoolsPackage
|
||||
from spack.package import CMakePackage, AutotoolsPackage, EditableMakefile
|
||||
from spack.version import Version, ver
|
||||
from spack.multimethod import when
|
||||
|
||||
|
@ -56,6 +56,9 @@ def setup_parser(subparser):
|
||||
subparser.add_argument(
|
||||
'--dirty', action='store_true', dest='dirty',
|
||||
help="Install a package *without* cleaning the environment.")
|
||||
subparser.add_argument(
|
||||
'--stop-at', help="Stop at a particular phase of installation"
|
||||
)
|
||||
subparser.add_argument(
|
||||
'packages', nargs=argparse.REMAINDER, help="specs of packages to install")
|
||||
subparser.add_argument(
|
||||
@ -88,4 +91,6 @@ def install(parser, args):
|
||||
verbose=args.verbose,
|
||||
fake=args.fake,
|
||||
dirty=args.dirty,
|
||||
explicit=True)
|
||||
explicit=True,
|
||||
stop_at=args.stop_at
|
||||
)
|
||||
|
@ -104,6 +104,10 @@ def phase_wrapper(spec, prefix):
|
||||
# and give them the chance to fail
|
||||
for check in self.sanity_checks:
|
||||
check(instance)
|
||||
# Permit instance to drive the execution
|
||||
if self.name == instance.last_phase:
|
||||
raise StopIteration('Stopping at \'{0}\' phase'.format(self.name))
|
||||
|
||||
|
||||
return phase_wrapper
|
||||
|
||||
@ -123,10 +127,10 @@ def __new__(meta, name, bases, attr_dict):
|
||||
# Check if phases is in attr dict, then set
|
||||
# install phases wrappers
|
||||
if 'phases' in attr_dict:
|
||||
phases = [PackageMeta.phase_fmt.format(x) for x in attr_dict['phases']]
|
||||
for phase_name, callback_name in zip(phases, attr_dict['phases']):
|
||||
_InstallPhase_phases = [PackageMeta.phase_fmt.format(x) for x in attr_dict['phases']]
|
||||
for phase_name, callback_name in zip(_InstallPhase_phases, attr_dict['phases']):
|
||||
attr_dict[phase_name] = InstallPhase(callback_name)
|
||||
attr_dict['phases'] = phases
|
||||
attr_dict['_InstallPhase_phases'] = _InstallPhase_phases
|
||||
|
||||
def _append_checks(check_name):
|
||||
# Name of the attribute I am going to check it exists
|
||||
@ -956,7 +960,8 @@ def namespace(self):
|
||||
return namespace
|
||||
|
||||
def do_fake_install(self):
|
||||
"""Make a fake install directory contaiing a 'fake' file in bin."""
|
||||
"""Make a fake install directory containing a 'fake' file in bin."""
|
||||
# FIXME : Make this part of the 'install' behavior ?
|
||||
mkdirp(self.prefix.bin)
|
||||
touch(join_path(self.prefix.bin, 'fake'))
|
||||
mkdirp(self.prefix.lib)
|
||||
@ -990,7 +995,7 @@ def do_install(self,
|
||||
fake=False,
|
||||
explicit=False,
|
||||
dirty=False,
|
||||
allowed_phases=None):
|
||||
**kwargs):
|
||||
"""Called by commands to install a package and its dependencies.
|
||||
|
||||
Package implementations should override install() to describe
|
||||
@ -1010,9 +1015,13 @@ def do_install(self,
|
||||
make_jobs -- Number of make jobs to use for install. Default is ncpus
|
||||
run_tests -- Runn tests within the package's install()
|
||||
"""
|
||||
# FIXME : we need a better semantic
|
||||
if allowed_phases is None:
|
||||
allowed_phases = self.phases
|
||||
#if allowed_phases is None:
|
||||
# allowed_phases = self.phases
|
||||
# FIXME : Refine the error message
|
||||
last_phase = kwargs.get('stop_at', None)
|
||||
if last_phase is not None and last_phase not in self.phases:
|
||||
raise KeyError('phase {0} is not among the allowed phases for package {1}'.format(last_phase, self))
|
||||
self.last_phase = last_phase
|
||||
|
||||
if not self.spec.concrete:
|
||||
raise ValueError("Can only install concrete packages.")
|
||||
@ -1097,9 +1106,10 @@ def build_process():
|
||||
True):
|
||||
dump_environment(env_path)
|
||||
try:
|
||||
for phase in filter(lambda x: x in allowed_phases, self.phases):
|
||||
for phase in self._InstallPhase_phases:
|
||||
# TODO : Log to screen the various phases
|
||||
getattr(self, phase)(self.spec, self.prefix)
|
||||
self.log()
|
||||
except AttributeError as e:
|
||||
# FIXME : improve error messages
|
||||
raise ProcessError(e.message, long_message='')
|
||||
@ -1126,9 +1136,10 @@ def build_process():
|
||||
# Create the install prefix and fork the build process.
|
||||
spack.install_layout.create_install_directory(self.spec)
|
||||
except directory_layout.InstallDirectoryAlreadyExistsError:
|
||||
# FIXME : refactor this as a prerequisites to configure
|
||||
if 'install' in self.phases:
|
||||
# Abort install if install directory exists.
|
||||
# But do NOT remove it (you'd be overwriting someon else's stuff)
|
||||
# But do NOT remove it (you'd be overwriting someone else's stuff)
|
||||
tty.warn("Keeping existing install prefix in place.")
|
||||
raise
|
||||
else:
|
||||
@ -1154,7 +1165,7 @@ def build_process():
|
||||
# the database, so that we don't need to re-read from file.
|
||||
spack.installed_db.add(self.spec, self.prefix, explicit=explicit)
|
||||
|
||||
def log(self, spec, prefix):
|
||||
def log(self):
|
||||
# Copy provenance into the install directory on success
|
||||
log_install_path = spack.install_layout.build_log_path(
|
||||
self.spec)
|
||||
@ -1533,14 +1544,41 @@ def rpath_args(self):
|
||||
|
||||
|
||||
class Package(PackageBase):
|
||||
phases = ['install', 'log']
|
||||
phases = ['install']
|
||||
# This will be used as a registration decorator in user
|
||||
# packages, if need be
|
||||
PackageBase.sanity_check('install')(PackageBase.sanity_check_prefix)
|
||||
|
||||
|
||||
class EditableMakefile(PackageBase):
|
||||
phases = ['edit', 'build', 'install']
|
||||
|
||||
def wdir(self):
|
||||
return self.stage.source_path
|
||||
|
||||
def build_args(self):
|
||||
return list()
|
||||
|
||||
def install_args(self):
|
||||
return list()
|
||||
|
||||
def edit(self, spec, prefix):
|
||||
raise NotImplementedError('\'edit\' function not implemented')
|
||||
|
||||
def build(self, spec, prefix):
|
||||
args = self.build_args()
|
||||
with working_dir(self.wdir()):
|
||||
inspect.getmodule(self).make(*args)
|
||||
|
||||
def install(self, spec, prefix):
|
||||
args = self.install_args() + ['install']
|
||||
with working_dir(self.wdir()):
|
||||
inspect.getmodule(self).make(*args)
|
||||
|
||||
PackageBase.sanity_check('install')(PackageBase.sanity_check_prefix)
|
||||
|
||||
class AutotoolsPackage(PackageBase):
|
||||
phases = ['autoreconf', 'configure', 'build', 'install', 'log']
|
||||
phases = ['autoreconf', 'configure', 'build', 'install']
|
||||
|
||||
def autoreconf(self, spec, prefix):
|
||||
"""Not needed usually, configure should be already there"""
|
||||
|
@ -25,7 +25,7 @@
|
||||
from spack import *
|
||||
|
||||
|
||||
class Astyle(Package):
|
||||
class Astyle(EditableMakefile):
|
||||
"""
|
||||
A Free, Fast, and Small Automatic Formatter for C, C++, C++/CLI,
|
||||
Objective-C, C#, and Java Source Code.
|
||||
@ -35,18 +35,14 @@ class Astyle(Package):
|
||||
|
||||
version('2.04', '30b1193a758b0909d06e7ee8dd9627f6')
|
||||
|
||||
def install(self, spec, prefix):
|
||||
parallel = False
|
||||
|
||||
with working_dir('src'):
|
||||
# we need to edit the makefile in place to set compiler:
|
||||
make_file = join_path(self.stage.source_path,
|
||||
'build', 'gcc', 'Makefile')
|
||||
filter_file(r'^CXX\s*=.*', 'CXX=%s' % spack_cxx, make_file)
|
||||
def wdir(self):
|
||||
return join_path(self.stage.source_path, 'build', self.compiler.name)
|
||||
|
||||
make('-f',
|
||||
make_file,
|
||||
parallel=False)
|
||||
def edit(self, spec, prefix):
|
||||
makefile = join_path(self.wdir(), 'Makefile')
|
||||
filter_file(r'^CXX\s*=.*', 'CXX=%s' % spack_cxx, makefile)
|
||||
|
||||
mkdirp(self.prefix.bin)
|
||||
install(join_path(self.stage.source_path, 'src', 'bin', 'astyle'),
|
||||
self.prefix.bin)
|
||||
def install_args(self):
|
||||
return ['prefix={0}'.format(prefix)]
|
||||
|
@ -24,16 +24,10 @@
|
||||
##############################################################################
|
||||
from spack import *
|
||||
|
||||
class Blitz(Package):
|
||||
|
||||
class Blitz(AutotoolsPackage):
|
||||
"""N-dimensional arrays for C++"""
|
||||
homepage = "http://github.com/blitzpp/blitz"
|
||||
url = "https://github.com/blitzpp/blitz/tarball/1.0.0"
|
||||
|
||||
version('1.0.0', '9f040b9827fe22228a892603671a77af')
|
||||
|
||||
# No dependencies
|
||||
|
||||
def install(self, spec, prefix):
|
||||
configure('--prefix=%s' % prefix)
|
||||
make()
|
||||
make("install")
|
||||
|
@ -24,7 +24,8 @@
|
||||
##############################################################################
|
||||
from spack import *
|
||||
|
||||
class Gmp(Package):
|
||||
|
||||
class Gmp(AutotoolsPackage):
|
||||
"""GMP is a free library for arbitrary precision arithmetic,
|
||||
operating on signed integers, rational numbers, and
|
||||
floating-point numbers."""
|
||||
@ -36,8 +37,3 @@ class Gmp(Package):
|
||||
version('6.0.0' , '6ef5869ae735db9995619135bd856b84')
|
||||
|
||||
depends_on("m4")
|
||||
|
||||
def install(self, spec, prefix):
|
||||
configure("--prefix=%s" % prefix)
|
||||
make()
|
||||
make("install")
|
||||
|
@ -66,8 +66,8 @@ def autoreconf(self, spec, prefix):
|
||||
autogen = Executable('./autogen.sh')
|
||||
autogen()
|
||||
|
||||
def config_args(self):
|
||||
return ['--prefix=%s' % prefix,
|
||||
'--enable-mpi' if '+mpi' in spec else '--disable-mpi',
|
||||
def configure_args(self):
|
||||
return ['--prefix=%s' % self.prefix,
|
||||
'--enable-mpi' if '+mpi' in self.spec else '--disable-mpi',
|
||||
'--with-metis={0}'.format(self.spec['metis'].prefix),
|
||||
'--enable-optimization']
|
||||
|
Loading…
Reference in New Issue
Block a user