diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/__init__.py | 4 | ||||
-rw-r--r-- | lib/spack/spack/build_systems/__init__.py | 0 | ||||
-rw-r--r-- | lib/spack/spack/build_systems/autotools.py | 106 | ||||
-rw-r--r-- | lib/spack/spack/build_systems/cmake.py | 143 | ||||
-rw-r--r-- | lib/spack/spack/build_systems/editable_makefile.py | 77 | ||||
-rw-r--r-- | lib/spack/spack/package.py | 155 |
6 files changed, 329 insertions, 156 deletions
diff --git a/lib/spack/spack/__init__.py b/lib/spack/spack/__init__.py index c7d592befb..918e17323b 100644 --- a/lib/spack/spack/__init__.py +++ b/lib/spack/spack/__init__.py @@ -196,7 +196,9 @@ __all__ = ['Package', 'alldeps', 'nolink'] from spack.package import Package, ExtensionConflictError -from spack.package import CMakePackage, AutotoolsPackage, EditableMakefile +from spack.build_systems.editable_makefile import EditableMakefile +from spack.build_systems.autotools import AutotoolsPackage +from spack.build_systems.cmake import CMakePackage from spack.version import Version, ver from spack.spec import DependencySpec, alldeps, nolink from spack.multimethod import when diff --git a/lib/spack/spack/build_systems/__init__.py b/lib/spack/spack/build_systems/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/spack/spack/build_systems/__init__.py diff --git a/lib/spack/spack/build_systems/autotools.py b/lib/spack/spack/build_systems/autotools.py new file mode 100644 index 0000000000..0bb5576708 --- /dev/null +++ b/lib/spack/spack/build_systems/autotools.py @@ -0,0 +1,106 @@ +############################################################################## +# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://github.com/llnl/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License (as +# published by the Free Software Foundation) version 2.1, February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## + +import inspect +import os.path + +import llnl.util.tty as tty +from spack.package import PackageBase + + +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 + + They all have sensible defaults and for many packages the only thing + necessary will be to override `configure_args` + """ + phases = ['autoreconf', 'configure', 'build', 'install'] + # To be used in UI queries that require to know which + # build-system class we are using + build_system_class = 'AutotoolsPackage' + + def autoreconf(self, spec, prefix): + """Not needed usually, configure should be already there""" + pass + + @PackageBase.sanity_check('autoreconf') + def is_configure_or_die(self): + """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())) + + def configure_args(self): + """Method to be overridden. Should return an iterable containing + 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` + and an appropriately set prefix + """ + options = ['--prefix={0}'.format(prefix)] + self.configure_args() + inspect.getmodule(self).configure(*options) + + def build(self, spec, prefix): + """The usual `make` after configure""" + inspect.getmodule(self).make() + + def install(self, spec, prefix): + """...and the final `make install` after configure""" + inspect.getmodule(self).make('install') + + @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 + + It will search for a method named `check` and run it. A sensible + default is provided in the base class. + """ + try: + fn = getattr(self, 'check') + tty.msg('Trying default sanity checks [check]') + fn() + except AttributeError: + 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` + and run them if found. + """ + 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 new file mode 100644 index 0000000000..cb1076d7b7 --- /dev/null +++ b/lib/spack/spack/build_systems/cmake.py @@ -0,0 +1,143 @@ +############################################################################## +# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://github.com/llnl/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License (as +# published by the Free Software Foundation) version 2.1, February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## + +import inspect +import os +import platform + +import llnl.util.tty as tty +import spack.build_environment +from llnl.util.filesystem import working_dir, join_path +from spack.package import PackageBase + + +class CMakePackage(PackageBase): + """Specialized class for packages that are built using cmake + + This class provides three phases that can be overridden: + - cmake + - build + - install + + They all have sensible defaults and for many packages the only thing + necessary will be to override `cmake_args` + """ + 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' + + def build_type(self): + """Override to provide the correct build_type in case a complex + logic is needed + """ + return 'RelWithDebInfo' + + def root_cmakelists_dir(self): + """Directory where to find the root CMakeLists.txt""" + return self.stage.source_path + + @property + def std_cmake_args(self): + """Standard cmake arguments provided as a property for + convenience of package writers + """ + # standard CMake arguments + return CMakePackage._std_args(self) + + @staticmethod + def _std_args(pkg): + """Computes the standard cmake arguments for a generic package""" + try: + build_type = pkg.build_type() + except AttributeError: + build_type = 'RelWithDebInfo' + + args = ['-DCMAKE_INSTALL_PREFIX:PATH={0}'.format(pkg.prefix), + '-DCMAKE_BUILD_TYPE:STRING={0}'.format(build_type), + '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON'] + if platform.mac_ver()[0]: + args.append('-DCMAKE_FIND_FRAMEWORK:STRING=LAST') + + # Set up CMake rpath + args.append('-DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=FALSE') + rpaths = ':'.join(spack.build_environment.get_rpaths(pkg)) + args.append('-DCMAKE_INSTALL_RPATH:STRING={0}'.format(rpaths)) + return args + + def build_directory(self): + """Override to provide another place to build the package""" + return join_path(self.stage.source_path, 'spack-build') + + 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 + """ + return [] + + 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): + inspect.getmodule(self).cmake(*options) + + def build(self, spec, prefix): + """The usual `make` after cmake""" + with working_dir(self.build_directory()): + inspect.getmodule(self).make() + + def install(self, spec, prefix): + """...and the final `make install` after cmake""" + with working_dir(self.build_directory()): + inspect.getmodule(self).make('install') + + @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 + + It will search for a method named `check` and run it. A sensible + default is provided in the base class. + """ + try: + fn = getattr(self, 'check') + tty.msg('Trying default build sanity checks [check]') + fn() + except AttributeError: + 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` + and run them if found. + """ + with working_dir(self.build_directory()): + self._if_make_target_execute('test') + + # Check that self.prefix is there after installation + PackageBase.sanity_check('install')(PackageBase.sanity_check_prefix) diff --git a/lib/spack/spack/build_systems/editable_makefile.py b/lib/spack/spack/build_systems/editable_makefile.py new file mode 100644 index 0000000000..e3adea8363 --- /dev/null +++ b/lib/spack/spack/build_systems/editable_makefile.py @@ -0,0 +1,77 @@ +############################################################################## +# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://github.com/llnl/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License (as +# published by the Free Software Foundation) version 2.1, February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## + +import inspect + +from llnl.util.filesystem import working_dir +from spack.package import PackageBase + + +class EditableMakefile(PackageBase): + """Specialized class for packages that are built using editable Makefiles + + This class provides three phases that can be overridden: + - edit + - build + - install + + It is necessary to override the 'edit' phase, while 'build' and 'install' + have sensible defaults. + """ + phases = ['edit', 'build', 'install'] + # To be used in UI queries that require to know which + # build-system class we are using + build_system_class = 'EditableMakefile' + + def build_directory(self): + """Directory where the main Makefile is located""" + return self.stage.source_path + + def build_args(self): + """List of arguments that should be passed to make at build time""" + return [] + + def install_args(self): + """List of arguments that should be passed to make at install time""" + return [] + + def edit(self, spec, prefix): + """This phase cannot be defaulted for obvious reasons...""" + raise NotImplementedError('\'edit\' function not implemented') + + def build(self, spec, prefix): + """Default build phase : call make passing build_args""" + args = self.build_args() + with working_dir(self.build_directory()): + inspect.getmodule(self).make(*args) + + def install(self, spec, prefix): + """Default install phase : call make passing install_args""" + args = self.install_args() + ['install'] + with working_dir(self.build_directory()): + inspect.getmodule(self).make(*args) + + # Check that self.prefix is there after installation + PackageBase.sanity_check('install')(PackageBase.sanity_check_prefix) diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py index 9483f370dd..52dbd40f6f 100644 --- a/lib/spack/spack/package.py +++ b/lib/spack/spack/package.py @@ -38,7 +38,6 @@ import copy import functools import inspect import os -import platform import re import sys import textwrap @@ -48,7 +47,6 @@ from StringIO import StringIO import llnl.util.lock import llnl.util.tty as tty import spack -import spack.build_environment import spack.compilers import spack.directives import spack.error @@ -1698,159 +1696,6 @@ class Package(PackageBase): PackageBase.sanity_check('install')(PackageBase.sanity_check_prefix) -class EditableMakefile(PackageBase): - phases = ['edit', 'build', 'install'] - # To be used in UI queries that require to know which - # build-system class we are using - build_system_class = 'EditableMakefile' - - def wdir(self): - return self.stage.source_path - - def build_args(self): - return [] - - def install_args(self): - return [] - - 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'] - # To be used in UI queries that require to know which - # build-system class we are using - build_system_class = 'AutotoolsPackage' - - 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 [] - - 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') - - @PackageBase.sanity_check('build') - @PackageBase.on_package_attributes(run_tests=True) - def _run_default_function(self): - try: - fn = getattr(self, 'check') - tty.msg('Trying default sanity checks [check]') - fn() - except AttributeError: - tty.msg('Skipping default sanity checks [method `check` not implemented]') # NOQA: ignore=E501 - - def check(self): - self._if_make_target_execute('test') - self._if_make_target_execute('check') - - # This will be used as a registration decorator in user - # packages, if need be - PackageBase.sanity_check('install')(PackageBase.sanity_check_prefix) - - -class CMakePackage(PackageBase): - 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' - - def build_type(self): - return 'RelWithDebInfo' - - def root_cmakelists_dir(self): - return self.stage.source_path - - @property - def std_cmake_args(self): - # standard CMake arguments - return CMakePackage._std_args(self) - - @staticmethod - def _std_args(pkg): - try: - build_type = pkg.build_type() - except AttributeError: - build_type = 'RelWithDebInfo' - - args = ['-DCMAKE_INSTALL_PREFIX:PATH={0}'.format(pkg.prefix), - '-DCMAKE_BUILD_TYPE:STRING={0}'.format(build_type), - '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON'] - if platform.mac_ver()[0]: - args.append('-DCMAKE_FIND_FRAMEWORK:STRING=LAST') - - # Set up CMake rpath - args.append('-DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=FALSE') - rpaths = ':'.join(spack.build_environment.get_rpaths(pkg)) - args.append('-DCMAKE_INSTALL_RPATH:STRING={0}'.format(rpaths)) - return args - - def build_directory(self): - return join_path(self.stage.source_path, 'spack-build') - - def cmake_args(self): - return [] - - def cmake(self, spec, prefix): - 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): - inspect.getmodule(self).cmake(*options) - - def build(self, spec, prefix): - with working_dir(self.build_directory()): - inspect.getmodule(self).make() - - def install(self, spec, prefix): - with working_dir(self.build_directory()): - inspect.getmodule(self).make('install') - - @PackageBase.sanity_check('build') - @PackageBase.on_package_attributes(run_tests=True) - def _run_default_function(self): - try: - fn = getattr(self, 'check') - tty.msg('Trying default build sanity checks [check]') - fn() - except AttributeError: - tty.msg('Skipping default build sanity checks [method `check` not implemented]') # NOQA: ignore=E501 - - def check(self): - with working_dir(self.build_directory()): - self._if_make_target_execute('test') - - 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) |