diff --git a/lib/spack/spack/build_systems/autotools.py b/lib/spack/spack/build_systems/autotools.py index dea4ae002f0e5..78a4df5e11708 100644 --- a/lib/spack/spack/build_systems/autotools.py +++ b/lib/spack/spack/build_systems/autotools.py @@ -31,6 +31,7 @@ from subprocess import check_call import llnl.util.tty as tty +from llnl.util.filesystem import working_dir from spack.package import PackageBase @@ -38,16 +39,17 @@ class AutotoolsPackage(PackageBase): """Specialized class for packages that are built using GNU Autotools This class provides four phases that can be overridden: - - autoreconf - - configure - - build - - install + + * autoreconf + * configure + * build + * install 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 - phases by overriding `build_targets` and `install_targets` + phases by overriding ``build_targets`` and ``install_targets`` """ phases = ['autoreconf', 'configure', 'build', 'install'] # To be used in UI queries that require to know which @@ -124,6 +126,10 @@ def do_patch_config_guess(self): return False + def build_directory(self): + """Override to provide another place to build the package""" + return self.stage.source_path + def patch(self): """Perform any required patches.""" @@ -138,39 +144,44 @@ def autoreconf(self, spec, prefix): @PackageBase.sanity_check('autoreconf') 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""" - if not os.path.exists('configure'): - raise RuntimeError( - 'configure script not found in {0}'.format(os.getcwd())) + with working_dir(self.build_directory()): + if not os.path.exists('configure'): + raise RuntimeError( + 'configure script not found in {0}'.format(os.getcwd())) def configure_args(self): """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 [] 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 """ options = ['--prefix={0}'.format(prefix)] + self.configure_args() - inspect.getmodule(self).configure(*options) + + with working_dir(self.build_directory()): + inspect.getmodule(self).configure(*options) def build(self, spec, prefix): """Make the build targets""" - inspect.getmodule(self).make(*self.build_targets) + with working_dir(self.build_directory()): + inspect.getmodule(self).make(*self.build_targets) def install(self, spec, prefix): """Make the install targets""" - inspect.getmodule(self).make(*self.install_targets) + with working_dir(self.build_directory()): + inspect.getmodule(self).make(*self.install_targets) @PackageBase.sanity_check('build') @PackageBase.on_package_attributes(run_tests=True) 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. """ try: @@ -181,11 +192,12 @@ def _run_default_function(self): tty.msg('Skipping default sanity checks [method `check` not implemented]') # NOQA: ignore=E501 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. """ - self._if_make_target_execute('test') - self._if_make_target_execute('check') + with working_dir(self.build_directory()): + self._if_make_target_execute('test') + self._if_make_target_execute('check') # Check that self.prefix is there after installation PackageBase.sanity_check('install')(PackageBase.sanity_check_prefix) diff --git a/lib/spack/spack/build_systems/cmake.py b/lib/spack/spack/build_systems/cmake.py index e097f7e44f1da..61d45784e8fca 100644 --- a/lib/spack/spack/build_systems/cmake.py +++ b/lib/spack/spack/build_systems/cmake.py @@ -24,7 +24,6 @@ ############################################################################## import inspect -import os import platform import llnl.util.tty as tty @@ -35,21 +34,28 @@ 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: - - cmake - - build - - install + + * cmake + * build + * install 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'] # To be used in UI queries that require to know which # build-system class we are using build_system_class = 'CMakePackage' + build_targets = [] + install_targets = ['install'] + depends_on('cmake', type='build') def build_type(self): @@ -97,8 +103,9 @@ def build_directory(self): def cmake_args(self): """Method to be overridden. Should return an iterable containing all the arguments that must be passed to configure, except: - - CMAKE_INSTALL_PREFIX - - CMAKE_BUILD_TYPE + + * CMAKE_INSTALL_PREFIX + * CMAKE_BUILD_TYPE """ return [] @@ -106,26 +113,25 @@ def cmake(self, spec, prefix): """Run cmake in the build directory""" options = [self.root_cmakelists_dir()] + self.std_cmake_args + \ self.cmake_args() - create = not os.path.exists(self.build_directory()) - with working_dir(self.build_directory(), create=create): + with working_dir(self.build_directory(), create=True): inspect.getmodule(self).cmake(*options) def build(self, spec, prefix): - """The usual `make` after cmake""" + """Make the build targets""" with working_dir(self.build_directory()): - inspect.getmodule(self).make() + inspect.getmodule(self).make(*self.build_targets) def install(self, spec, prefix): - """...and the final `make install` after cmake""" + """Make the install targets""" with working_dir(self.build_directory()): - inspect.getmodule(self).make('install') + inspect.getmodule(self).make(*self.install_targets) @PackageBase.sanity_check('build') @PackageBase.on_package_attributes(run_tests=True) 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. """ try: @@ -136,7 +142,7 @@ def _run_default_function(self): tty.msg('Skipping default build sanity checks [method `check` not implemented]') # NOQA: ignore=E501 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. """ with working_dir(self.build_directory()): diff --git a/lib/spack/spack/build_systems/makefile.py b/lib/spack/spack/build_systems/makefile.py index fcc7ed2c995b3..a56f316109ad4 100644 --- a/lib/spack/spack/build_systems/makefile.py +++ b/lib/spack/spack/build_systems/makefile.py @@ -34,9 +34,10 @@ class MakefilePackage(PackageBase): """Specialized class for packages that are built using editable Makefiles This class provides three phases that can be overridden: - - edit - - build - - install + + * edit + * build + * install It is necessary to override the 'edit' phase, while 'build' and 'install' have sensible defaults. @@ -58,12 +59,12 @@ def edit(self, spec, prefix): tty.msg('Using default implementation: skipping edit phase.') def build(self, spec, prefix): - """Default build phase : call make passing build_args""" + """Make the build targets""" with working_dir(self.build_directory()): inspect.getmodule(self).make(*self.build_targets) def install(self, spec, prefix): - """Default install phase : call make passing install_args""" + """Make the install targets""" with working_dir(self.build_directory()): inspect.getmodule(self).make(*self.install_targets) diff --git a/lib/spack/spack/build_systems/r.py b/lib/spack/spack/build_systems/r.py index 52b3d82c601b0..f642f2dfd8241 100644 --- a/lib/spack/spack/build_systems/r.py +++ b/lib/spack/spack/build_systems/r.py @@ -33,6 +33,7 @@ class RPackage(PackageBase): """Specialized class for packages that are built using R This class provides a single phase that can be overridden: + * install It has sensible defaults and for many packages the only thing diff --git a/var/spack/repos/builtin/packages/espressopp/package.py b/var/spack/repos/builtin/packages/espressopp/package.py index 21e1cc1317827..2903a02f7de7e 100644 --- a/var/spack/repos/builtin/packages/espressopp/package.py +++ b/var/spack/repos/builtin/packages/espressopp/package.py @@ -36,7 +36,7 @@ class Espressopp(CMakePackage): url = "https://github.com/espressopp/espressopp/tarball/v1.9.4.1" version('develop', git='https://github.com/espressopp/espressopp.git', branch='master') - version('1.9.4.1', '0da74a6d4e1bfa6a2a24fca354245a4f') + version('1.9.4.1', '0da74a6d4e1bfa6a2a24fca354245a4f') version('1.9.4', 'f2a27993a83547ad014335006eea74ea') variant('debug', default=False, description='Build debug version') @@ -54,20 +54,23 @@ class Espressopp(CMakePackage): depends_on("fftw") depends_on("py-sphinx", when="+ug", 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("doxygen", when="+dg", type='build') - def cmake_args(self): + def build_type(self): spec = self.spec - options = [] - options.extend(['-DEXTERNAL_MPI4PY=ON', '-DEXTERNAL_BOOST=ON']) if '+debug' in spec: - options.extend(['-DCMAKE_BUILD_TYPE:STRING=Debug']) + return 'Debug' else: - options.extend(['-DCMAKE_BUILD_TYPE:STRING=Release']) - - return options - + return 'Release' + + def cmake_args(self): + return ['-DEXTERNAL_MPI4PY=ON', '-DEXTERNAL_BOOST=ON'] + def build(self, spec, prefix): with working_dir(self.build_directory()): make() diff --git a/var/spack/repos/builtin/packages/tcl/package.py b/var/spack/repos/builtin/packages/tcl/package.py index 16d896acc6c0a..d9b535305dba7 100644 --- a/var/spack/repos/builtin/packages/tcl/package.py +++ b/var/spack/repos/builtin/packages/tcl/package.py @@ -25,7 +25,7 @@ from spack import * -class Tcl(Package): +class Tcl(AutotoolsPackage): """Tcl (Tool Command Language) is a very powerful but easy to learn dynamic programming language, suitable for a very wide 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( self.spec.version.up_to(2)))) - def install(self, spec, prefix): - with working_dir('unix'): - configure("--prefix={0}".format(prefix)) - make() - make("install") - with working_dir(prefix.bin): + def build_directory(self): + return 'unix' + + @AutotoolsPackage.sanity_check('install') + def symlink_tclsh(self): + with working_dir(self.prefix.bin): symlink('tclsh{0}'.format(self.version.up_to(2)), 'tclsh') diff --git a/var/spack/repos/builtin/packages/tk/package.py b/var/spack/repos/builtin/packages/tk/package.py index 1abcd26a24075..071db04e63520 100644 --- a/var/spack/repos/builtin/packages/tk/package.py +++ b/var/spack/repos/builtin/packages/tk/package.py @@ -25,7 +25,7 @@ from spack import * -class Tk(Package): +class Tk(AutotoolsPackage): """Tk is a graphical user interface toolkit that takes developing desktop applications to a higher level than conventional 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" 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 # 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( - self.spec.version.up_to(2)))) - - def install(self, spec, prefix): - with working_dir('unix'): - configure("--prefix={0}".format(prefix), - "--with-tcl={0}".format(spec['tcl'].prefix.lib)) - make() - make("install") + run_env.set('TK_LIBRARY', join_path(self.prefix.lib, 'tk{0}'.format( + self.spec.version.up_to(2)))) + + def build_directory(self): + return 'unix' + + def configure_args(self): + spec = self.spec + return ['--with-tcl={0}'.format(spec['tcl'].prefix.lib)] diff --git a/var/spack/repos/builtin/packages/zlib/package.py b/var/spack/repos/builtin/packages/zlib/package.py index a20f6ff802b0a..ea758e01889f3 100644 --- a/var/spack/repos/builtin/packages/zlib/package.py +++ b/var/spack/repos/builtin/packages/zlib/package.py @@ -23,7 +23,6 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## from spack import * -from os import environ class Zlib(AutotoolsPackage): @@ -35,17 +34,13 @@ class Zlib(AutotoolsPackage): version('1.2.10', 'd9794246f853d15ce0fcbf79b9a3cf13') # author had this to say about 1.2.9.... - # Due to the bug fixes, any installations of 1.2.9 should be immediately + # Due to the bug fixes, any installations of 1.2.9 should be immediately # replaced with 1.2.10. version('1.2.8', '44d667c142d7cda120332623eab69f40') variant('pic', default=True, description='Produce position-independent code (for shared libs)') - def configure(self, spec, prefix): - - if '+pic' in spec: - environ['CFLAGS'] = self.compiler.pic_flag - - config_args = ['--prefix', prefix] - configure(*config_args) + def setup_environment(self, spack_env, run_env): + if '+pic' in self.spec: + spack_env.set('CFLAGS', self.compiler.pic_flag)