Added customization for make targets in 'build' and 'install' phases for CMakePackage (#2742)
* Added customization for make targets in 'build' and 'install' phases for CMakePackage * Use rst in build system docs so that Sphinx generates nice API docs * Allow AutotoolsPackages to be built in a different directory * Flake8 * Fix missing import * Allow configure to be located in different directory * Update espressopp to use build targets * Flake8 * Sphinx fix, lists must be a new paragraph * Back out change that allowed a configure script in a different directory than build_directory * Add missing deps, build in parallel * Missing space for rst list
This commit is contained in:
parent
4b7b595e3c
commit
f480e3449e
@ -31,6 +31,7 @@
|
|||||||
from subprocess import check_call
|
from subprocess import check_call
|
||||||
|
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
from llnl.util.filesystem import working_dir
|
||||||
from spack.package import PackageBase
|
from spack.package import PackageBase
|
||||||
|
|
||||||
|
|
||||||
@ -38,16 +39,17 @@ class AutotoolsPackage(PackageBase):
|
|||||||
"""Specialized class for packages that are built using GNU Autotools
|
"""Specialized class for packages that are built using GNU Autotools
|
||||||
|
|
||||||
This class provides four phases that can be overridden:
|
This class provides four phases that can be overridden:
|
||||||
- autoreconf
|
|
||||||
- configure
|
* autoreconf
|
||||||
- build
|
* configure
|
||||||
- install
|
* build
|
||||||
|
* install
|
||||||
|
|
||||||
They all have sensible defaults and for many packages the only thing
|
They all have sensible defaults and for many packages the only thing
|
||||||
necessary will be to override `configure_args`
|
necessary will be to override ``configure_args``
|
||||||
|
|
||||||
Additionally, you may specify make targets for build and install
|
Additionally, you may specify make targets for build and install
|
||||||
phases by overriding `build_targets` and `install_targets`
|
phases by overriding ``build_targets`` and ``install_targets``
|
||||||
"""
|
"""
|
||||||
phases = ['autoreconf', 'configure', 'build', 'install']
|
phases = ['autoreconf', 'configure', 'build', 'install']
|
||||||
# To be used in UI queries that require to know which
|
# To be used in UI queries that require to know which
|
||||||
@ -124,6 +126,10 @@ def do_patch_config_guess(self):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def build_directory(self):
|
||||||
|
"""Override to provide another place to build the package"""
|
||||||
|
return self.stage.source_path
|
||||||
|
|
||||||
def patch(self):
|
def patch(self):
|
||||||
"""Perform any required patches."""
|
"""Perform any required patches."""
|
||||||
|
|
||||||
@ -138,39 +144,44 @@ def autoreconf(self, spec, prefix):
|
|||||||
|
|
||||||
@PackageBase.sanity_check('autoreconf')
|
@PackageBase.sanity_check('autoreconf')
|
||||||
def is_configure_or_die(self):
|
def is_configure_or_die(self):
|
||||||
"""Checks the presence of a `configure` file after the
|
"""Checks the presence of a ``configure`` file after the
|
||||||
autoreconf phase"""
|
autoreconf phase"""
|
||||||
|
with working_dir(self.build_directory()):
|
||||||
if not os.path.exists('configure'):
|
if not os.path.exists('configure'):
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
'configure script not found in {0}'.format(os.getcwd()))
|
'configure script not found in {0}'.format(os.getcwd()))
|
||||||
|
|
||||||
def configure_args(self):
|
def configure_args(self):
|
||||||
"""Method to be overridden. Should return an iterable containing
|
"""Method to be overridden. Should return an iterable containing
|
||||||
all the arguments that must be passed to configure, except --prefix
|
all the arguments that must be passed to configure, except ``--prefix``
|
||||||
"""
|
"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def configure(self, spec, prefix):
|
def configure(self, spec, prefix):
|
||||||
"""Runs configure with the arguments specified in `configure_args`
|
"""Runs configure with the arguments specified in ``configure_args``
|
||||||
and an appropriately set prefix
|
and an appropriately set prefix
|
||||||
"""
|
"""
|
||||||
options = ['--prefix={0}'.format(prefix)] + self.configure_args()
|
options = ['--prefix={0}'.format(prefix)] + self.configure_args()
|
||||||
|
|
||||||
|
with working_dir(self.build_directory()):
|
||||||
inspect.getmodule(self).configure(*options)
|
inspect.getmodule(self).configure(*options)
|
||||||
|
|
||||||
def build(self, spec, prefix):
|
def build(self, spec, prefix):
|
||||||
"""Make the build targets"""
|
"""Make the build targets"""
|
||||||
|
with working_dir(self.build_directory()):
|
||||||
inspect.getmodule(self).make(*self.build_targets)
|
inspect.getmodule(self).make(*self.build_targets)
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def install(self, spec, prefix):
|
||||||
"""Make the install targets"""
|
"""Make the install targets"""
|
||||||
|
with working_dir(self.build_directory()):
|
||||||
inspect.getmodule(self).make(*self.install_targets)
|
inspect.getmodule(self).make(*self.install_targets)
|
||||||
|
|
||||||
@PackageBase.sanity_check('build')
|
@PackageBase.sanity_check('build')
|
||||||
@PackageBase.on_package_attributes(run_tests=True)
|
@PackageBase.on_package_attributes(run_tests=True)
|
||||||
def _run_default_function(self):
|
def _run_default_function(self):
|
||||||
"""This function is run after build if self.run_tests == True
|
"""This function is run after build if ``self.run_tests == True``
|
||||||
|
|
||||||
It will search for a method named `check` and run it. A sensible
|
It will search for a method named ``check`` and run it. A sensible
|
||||||
default is provided in the base class.
|
default is provided in the base class.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
@ -181,9 +192,10 @@ def _run_default_function(self):
|
|||||||
tty.msg('Skipping default sanity checks [method `check` not implemented]') # NOQA: ignore=E501
|
tty.msg('Skipping default sanity checks [method `check` not implemented]') # NOQA: ignore=E501
|
||||||
|
|
||||||
def check(self):
|
def check(self):
|
||||||
"""Default test : search the Makefile for targets `test` and `check`
|
"""Default test: search the Makefile for targets ``test`` and ``check``
|
||||||
and run them if found.
|
and run them if found.
|
||||||
"""
|
"""
|
||||||
|
with working_dir(self.build_directory()):
|
||||||
self._if_make_target_execute('test')
|
self._if_make_target_execute('test')
|
||||||
self._if_make_target_execute('check')
|
self._if_make_target_execute('check')
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
@ -35,21 +34,28 @@
|
|||||||
|
|
||||||
|
|
||||||
class CMakePackage(PackageBase):
|
class CMakePackage(PackageBase):
|
||||||
"""Specialized class for packages that are built using cmake
|
"""Specialized class for packages that are built using CMake
|
||||||
|
|
||||||
This class provides three phases that can be overridden:
|
This class provides three phases that can be overridden:
|
||||||
- cmake
|
|
||||||
- build
|
* cmake
|
||||||
- install
|
* build
|
||||||
|
* install
|
||||||
|
|
||||||
They all have sensible defaults and for many packages the only thing
|
They all have sensible defaults and for many packages the only thing
|
||||||
necessary will be to override `cmake_args`
|
necessary will be to override ``cmake_args``
|
||||||
|
|
||||||
|
Additionally, you may specify make targets for build and install
|
||||||
|
phases by overriding ``build_targets`` and ``install_targets``
|
||||||
"""
|
"""
|
||||||
phases = ['cmake', 'build', 'install']
|
phases = ['cmake', 'build', 'install']
|
||||||
# To be used in UI queries that require to know which
|
# To be used in UI queries that require to know which
|
||||||
# build-system class we are using
|
# build-system class we are using
|
||||||
build_system_class = 'CMakePackage'
|
build_system_class = 'CMakePackage'
|
||||||
|
|
||||||
|
build_targets = []
|
||||||
|
install_targets = ['install']
|
||||||
|
|
||||||
depends_on('cmake', type='build')
|
depends_on('cmake', type='build')
|
||||||
|
|
||||||
def build_type(self):
|
def build_type(self):
|
||||||
@ -97,8 +103,9 @@ def build_directory(self):
|
|||||||
def cmake_args(self):
|
def cmake_args(self):
|
||||||
"""Method to be overridden. Should return an iterable containing
|
"""Method to be overridden. Should return an iterable containing
|
||||||
all the arguments that must be passed to configure, except:
|
all the arguments that must be passed to configure, except:
|
||||||
- CMAKE_INSTALL_PREFIX
|
|
||||||
- CMAKE_BUILD_TYPE
|
* CMAKE_INSTALL_PREFIX
|
||||||
|
* CMAKE_BUILD_TYPE
|
||||||
"""
|
"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@ -106,26 +113,25 @@ def cmake(self, spec, prefix):
|
|||||||
"""Run cmake in the build directory"""
|
"""Run cmake in the build directory"""
|
||||||
options = [self.root_cmakelists_dir()] + self.std_cmake_args + \
|
options = [self.root_cmakelists_dir()] + self.std_cmake_args + \
|
||||||
self.cmake_args()
|
self.cmake_args()
|
||||||
create = not os.path.exists(self.build_directory())
|
with working_dir(self.build_directory(), create=True):
|
||||||
with working_dir(self.build_directory(), create=create):
|
|
||||||
inspect.getmodule(self).cmake(*options)
|
inspect.getmodule(self).cmake(*options)
|
||||||
|
|
||||||
def build(self, spec, prefix):
|
def build(self, spec, prefix):
|
||||||
"""The usual `make` after cmake"""
|
"""Make the build targets"""
|
||||||
with working_dir(self.build_directory()):
|
with working_dir(self.build_directory()):
|
||||||
inspect.getmodule(self).make()
|
inspect.getmodule(self).make(*self.build_targets)
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def install(self, spec, prefix):
|
||||||
"""...and the final `make install` after cmake"""
|
"""Make the install targets"""
|
||||||
with working_dir(self.build_directory()):
|
with working_dir(self.build_directory()):
|
||||||
inspect.getmodule(self).make('install')
|
inspect.getmodule(self).make(*self.install_targets)
|
||||||
|
|
||||||
@PackageBase.sanity_check('build')
|
@PackageBase.sanity_check('build')
|
||||||
@PackageBase.on_package_attributes(run_tests=True)
|
@PackageBase.on_package_attributes(run_tests=True)
|
||||||
def _run_default_function(self):
|
def _run_default_function(self):
|
||||||
"""This function is run after build if self.run_tests == True
|
"""This function is run after build if ``self.run_tests == True``
|
||||||
|
|
||||||
It will search for a method named `check` and run it. A sensible
|
It will search for a method named ``check`` and run it. A sensible
|
||||||
default is provided in the base class.
|
default is provided in the base class.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
@ -136,7 +142,7 @@ def _run_default_function(self):
|
|||||||
tty.msg('Skipping default build sanity checks [method `check` not implemented]') # NOQA: ignore=E501
|
tty.msg('Skipping default build sanity checks [method `check` not implemented]') # NOQA: ignore=E501
|
||||||
|
|
||||||
def check(self):
|
def check(self):
|
||||||
"""Default test : search the Makefile for the target `test`
|
"""Default test: search the Makefile for the target ``test``
|
||||||
and run them if found.
|
and run them if found.
|
||||||
"""
|
"""
|
||||||
with working_dir(self.build_directory()):
|
with working_dir(self.build_directory()):
|
||||||
|
@ -34,9 +34,10 @@ class MakefilePackage(PackageBase):
|
|||||||
"""Specialized class for packages that are built using editable Makefiles
|
"""Specialized class for packages that are built using editable Makefiles
|
||||||
|
|
||||||
This class provides three phases that can be overridden:
|
This class provides three phases that can be overridden:
|
||||||
- edit
|
|
||||||
- build
|
* edit
|
||||||
- install
|
* build
|
||||||
|
* install
|
||||||
|
|
||||||
It is necessary to override the 'edit' phase, while 'build' and 'install'
|
It is necessary to override the 'edit' phase, while 'build' and 'install'
|
||||||
have sensible defaults.
|
have sensible defaults.
|
||||||
@ -58,12 +59,12 @@ def edit(self, spec, prefix):
|
|||||||
tty.msg('Using default implementation: skipping edit phase.')
|
tty.msg('Using default implementation: skipping edit phase.')
|
||||||
|
|
||||||
def build(self, spec, prefix):
|
def build(self, spec, prefix):
|
||||||
"""Default build phase : call make passing build_args"""
|
"""Make the build targets"""
|
||||||
with working_dir(self.build_directory()):
|
with working_dir(self.build_directory()):
|
||||||
inspect.getmodule(self).make(*self.build_targets)
|
inspect.getmodule(self).make(*self.build_targets)
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def install(self, spec, prefix):
|
||||||
"""Default install phase : call make passing install_args"""
|
"""Make the install targets"""
|
||||||
with working_dir(self.build_directory()):
|
with working_dir(self.build_directory()):
|
||||||
inspect.getmodule(self).make(*self.install_targets)
|
inspect.getmodule(self).make(*self.install_targets)
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ class RPackage(PackageBase):
|
|||||||
"""Specialized class for packages that are built using R
|
"""Specialized class for packages that are built using R
|
||||||
|
|
||||||
This class provides a single phase that can be overridden:
|
This class provides a single phase that can be overridden:
|
||||||
|
|
||||||
* install
|
* install
|
||||||
|
|
||||||
It has sensible defaults and for many packages the only thing
|
It has sensible defaults and for many packages the only thing
|
||||||
|
@ -54,19 +54,22 @@ class Espressopp(CMakePackage):
|
|||||||
depends_on("fftw")
|
depends_on("fftw")
|
||||||
depends_on("py-sphinx", when="+ug", type='build')
|
depends_on("py-sphinx", when="+ug", type='build')
|
||||||
depends_on("py-sphinx", when="+pdf", type='build')
|
depends_on("py-sphinx", when="+pdf", type='build')
|
||||||
|
depends_on('py-numpy', when="+ug", type='build')
|
||||||
|
depends_on('py-numpy', when="+pdf", type='build')
|
||||||
|
depends_on('py-matplotlib', when="+ug", type='build')
|
||||||
|
depends_on('py-matplotlib', when="+pdf", type='build')
|
||||||
depends_on("texlive", when="+pdf", type='build')
|
depends_on("texlive", when="+pdf", type='build')
|
||||||
depends_on("doxygen", when="+dg", type='build')
|
depends_on("doxygen", when="+dg", type='build')
|
||||||
|
|
||||||
def cmake_args(self):
|
def build_type(self):
|
||||||
spec = self.spec
|
spec = self.spec
|
||||||
options = []
|
|
||||||
options.extend(['-DEXTERNAL_MPI4PY=ON', '-DEXTERNAL_BOOST=ON'])
|
|
||||||
if '+debug' in spec:
|
if '+debug' in spec:
|
||||||
options.extend(['-DCMAKE_BUILD_TYPE:STRING=Debug'])
|
return 'Debug'
|
||||||
else:
|
else:
|
||||||
options.extend(['-DCMAKE_BUILD_TYPE:STRING=Release'])
|
return 'Release'
|
||||||
|
|
||||||
return options
|
def cmake_args(self):
|
||||||
|
return ['-DEXTERNAL_MPI4PY=ON', '-DEXTERNAL_BOOST=ON']
|
||||||
|
|
||||||
def build(self, spec, prefix):
|
def build(self, spec, prefix):
|
||||||
with working_dir(self.build_directory()):
|
with working_dir(self.build_directory()):
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
from spack import *
|
from spack import *
|
||||||
|
|
||||||
|
|
||||||
class Tcl(Package):
|
class Tcl(AutotoolsPackage):
|
||||||
"""Tcl (Tool Command Language) is a very powerful but easy to
|
"""Tcl (Tool Command Language) is a very powerful but easy to
|
||||||
learn dynamic programming language, suitable for a very wide
|
learn dynamic programming language, suitable for a very wide
|
||||||
range of uses, including web and desktop applications,
|
range of uses, including web and desktop applications,
|
||||||
@ -52,10 +52,10 @@ def setup_environment(self, spack_env, env):
|
|||||||
env.set('TCL_LIBRARY', join_path(self.prefix.lib, 'tcl{0}'.format(
|
env.set('TCL_LIBRARY', join_path(self.prefix.lib, 'tcl{0}'.format(
|
||||||
self.spec.version.up_to(2))))
|
self.spec.version.up_to(2))))
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def build_directory(self):
|
||||||
with working_dir('unix'):
|
return 'unix'
|
||||||
configure("--prefix={0}".format(prefix))
|
|
||||||
make()
|
@AutotoolsPackage.sanity_check('install')
|
||||||
make("install")
|
def symlink_tclsh(self):
|
||||||
with working_dir(prefix.bin):
|
with working_dir(self.prefix.bin):
|
||||||
symlink('tclsh{0}'.format(self.version.up_to(2)), 'tclsh')
|
symlink('tclsh{0}'.format(self.version.up_to(2)), 'tclsh')
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
from spack import *
|
from spack import *
|
||||||
|
|
||||||
|
|
||||||
class Tk(Package):
|
class Tk(AutotoolsPackage):
|
||||||
"""Tk is a graphical user interface toolkit that takes developing
|
"""Tk is a graphical user interface toolkit that takes developing
|
||||||
desktop applications to a higher level than conventional
|
desktop applications to a higher level than conventional
|
||||||
approaches. Tk is the standard GUI not only for Tcl, but for
|
approaches. Tk is the standard GUI not only for Tcl, but for
|
||||||
@ -46,15 +46,15 @@ def url_for_version(self, version):
|
|||||||
base_url = "http://prdownloads.sourceforge.net/tcl"
|
base_url = "http://prdownloads.sourceforge.net/tcl"
|
||||||
return "{0}/tk{1}-src.tar.gz".format(base_url, version)
|
return "{0}/tk{1}-src.tar.gz".format(base_url, version)
|
||||||
|
|
||||||
def setup_environment(self, spack_env, env):
|
def setup_environment(self, spack_env, run_env):
|
||||||
# When using Tkinter from within spack provided python+tk, python
|
# When using Tkinter from within spack provided python+tk, python
|
||||||
# will not be able to find Tcl/Tk unless TK_LIBRARY is set.
|
# will not be able to find Tcl/Tk unless TK_LIBRARY is set.
|
||||||
env.set('TK_LIBRARY', join_path(self.prefix.lib, 'tk{0}'.format(
|
run_env.set('TK_LIBRARY', join_path(self.prefix.lib, 'tk{0}'.format(
|
||||||
self.spec.version.up_to(2))))
|
self.spec.version.up_to(2))))
|
||||||
|
|
||||||
def install(self, spec, prefix):
|
def build_directory(self):
|
||||||
with working_dir('unix'):
|
return 'unix'
|
||||||
configure("--prefix={0}".format(prefix),
|
|
||||||
"--with-tcl={0}".format(spec['tcl'].prefix.lib))
|
def configure_args(self):
|
||||||
make()
|
spec = self.spec
|
||||||
make("install")
|
return ['--with-tcl={0}'.format(spec['tcl'].prefix.lib)]
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
##############################################################################
|
##############################################################################
|
||||||
from spack import *
|
from spack import *
|
||||||
from os import environ
|
|
||||||
|
|
||||||
|
|
||||||
class Zlib(AutotoolsPackage):
|
class Zlib(AutotoolsPackage):
|
||||||
@ -42,10 +41,6 @@ class Zlib(AutotoolsPackage):
|
|||||||
variant('pic', default=True,
|
variant('pic', default=True,
|
||||||
description='Produce position-independent code (for shared libs)')
|
description='Produce position-independent code (for shared libs)')
|
||||||
|
|
||||||
def configure(self, spec, prefix):
|
def setup_environment(self, spack_env, run_env):
|
||||||
|
if '+pic' in self.spec:
|
||||||
if '+pic' in spec:
|
spack_env.set('CFLAGS', self.compiler.pic_flag)
|
||||||
environ['CFLAGS'] = self.compiler.pic_flag
|
|
||||||
|
|
||||||
config_args = ['--prefix', prefix]
|
|
||||||
configure(*config_args)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user