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