summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMilton Woods <miltonjwoods@gmail.com>2017-03-31 09:38:58 +1000
committerTodd Gamblin <tgamblin@llnl.gov>2017-03-30 16:38:58 -0700
commit9e43ff821c1549d5813eebd5a9ca81a7869786e7 (patch)
treec7f4ad5e12302acae6ebc1a286e384b5b0ae617c /lib
parent9e1abb13dcc4fb21042c6ca3b2e5c445811d6c15 (diff)
downloadspack-9e43ff821c1549d5813eebd5a9ca81a7869786e7.tar.gz
spack-9e43ff821c1549d5813eebd5a9ca81a7869786e7.tar.bz2
spack-9e43ff821c1549d5813eebd5a9ca81a7869786e7.tar.xz
spack-9e43ff821c1549d5813eebd5a9ca81a7869786e7.zip
Extendable Perl (#3614)
* perl: make extendable and add Module::Build package * perl: allow 'spack create' to identify perl packages from their contents * perl-module-build: fix indenting of package docstring * perl: split install() method for extensions into phases * perl: auto-detect build method (Makefile.PL vs Build.PL) and define a 'check' method * PerlPackage: use import statements similar to those in AutotoolsPackage * PerlModule: fix detection of Build.PL * PerlPackageTemplate: remove extraneous lines to avoid flake8 warnings * PerlPackageTemplate: split into separate templates for Makefile.PL and Build.PL * PerlPackage: add cross-references to docstrings * AutotoolsPackage: fix ambiguous cross-references to avoid errors in doc tests * PerlbuildPackageTemplate: depend on perl-module-build if Build.PL exists
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/docs/packaging_guide.rst4
-rw-r--r--lib/spack/spack/__init__.py4
-rw-r--r--lib/spack/spack/build_systems/autotools.py8
-rw-r--r--lib/spack/spack/build_systems/perl.py117
-rw-r--r--lib/spack/spack/cmd/build.py3
-rw-r--r--lib/spack/spack/cmd/configure.py3
-rw-r--r--lib/spack/spack/cmd/create.py45
-rw-r--r--lib/spack/spack/test/build_system_guess.py2
8 files changed, 179 insertions, 7 deletions
diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst
index 729ea5d656..1a64c7db4a 100644
--- a/lib/spack/docs/packaging_guide.rst
+++ b/lib/spack/docs/packaging_guide.rst
@@ -2043,6 +2043,10 @@ The classes that are currently provided by Spack are:
| :py:class:`.PythonPackage` | Specialized class for |
| | :py:class:`.Python` extensions |
+------------------------------------+----------------------------------+
+ | :py:class:`.PerlPackage` | Specialized class for |
+ | | :py:class:`.Perl` extensions |
+ +------------------------------------+----------------------------------+
+
diff --git a/lib/spack/spack/__init__.py b/lib/spack/spack/__init__.py
index 6a28fbb2b0..b0f2faed76 100644
--- a/lib/spack/spack/__init__.py
+++ b/lib/spack/spack/__init__.py
@@ -162,6 +162,7 @@ from spack.build_systems.autotools import AutotoolsPackage
from spack.build_systems.cmake import CMakePackage
from spack.build_systems.python import PythonPackage
from spack.build_systems.r import RPackage
+from spack.build_systems.perl import PerlPackage
__all__ += [
'run_before',
@@ -172,7 +173,8 @@ __all__ += [
'AutotoolsPackage',
'MakefilePackage',
'PythonPackage',
- 'RPackage'
+ 'RPackage',
+ 'PerlPackage'
]
from spack.version import Version, ver
diff --git a/lib/spack/spack/build_systems/autotools.py b/lib/spack/spack/build_systems/autotools.py
index a11a84acd0..76dfd0d16f 100644
--- a/lib/spack/spack/build_systems/autotools.py
+++ b/lib/spack/spack/build_systems/autotools.py
@@ -49,7 +49,8 @@ class AutotoolsPackage(PackageBase):
4. :py:meth:`~.AutotoolsPackage.install`
They all have sensible defaults and for many packages the only thing
- necessary will be to override the helper method :py:meth:`.configure_args`.
+ necessary will be to override the helper method
+ :py:meth:`~.AutotoolsPackage.configure_args`.
For a finer tuning you may also override:
+-----------------------------------------------+--------------------+
@@ -234,7 +235,7 @@ class AutotoolsPackage(PackageBase):
appropriately, otherwise raises an error.
:raises RuntimeError: if a configure script is not found in
- :py:meth:`~.configure_directory`
+ :py:meth:`~AutotoolsPackage.configure_directory`
"""
# Check if a configure script is there. If not raise a RuntimeError.
if not os.path.exists(self.configure_abs_path):
@@ -255,7 +256,8 @@ class AutotoolsPackage(PackageBase):
return []
def configure(self, spec, prefix):
- """Runs configure with the arguments specified in :py:meth:`.configure_args`
+ """Runs configure with the arguments specified in
+ :py:meth:`~.AutotoolsPackage.configure_args`
and an appropriately set prefix.
"""
options = ['--prefix={0}'.format(prefix)] + self.configure_args()
diff --git a/lib/spack/spack/build_systems/perl.py b/lib/spack/spack/build_systems/perl.py
new file mode 100644
index 0000000000..78184c85dc
--- /dev/null
+++ b/lib/spack/spack/build_systems/perl.py
@@ -0,0 +1,117 @@
+##############################################################################
+# 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
+
+from llnl.util.filesystem import join_path
+from spack.directives import extends
+from spack.package import PackageBase, run_after
+from spack.util.executable import Executable
+
+
+class PerlPackage(PackageBase):
+ """Specialized class for packages that are built using Perl.
+
+ This class provides four phases that can be overridden if required:
+
+ 1. :py:meth:`~.PerlPackage.configure`
+ 2. :py:meth:`~.PerlPackage.build`
+ 3. :py:meth:`~.PerlPackage.check`
+ 4. :py:meth:`~.PerlPackage.install`
+
+ The default methods use, in order of preference:
+ (1) Makefile.PL,
+ (2) Build.PL.
+
+ Some packages may need to override
+ :py:meth:`~.PerlPackage.configure_args`,
+ which produces a list of arguments for
+ :py:meth:`~.PerlPackage.configure`.
+ Arguments should not include the installation base directory.
+ """
+ #: Phases of a Perl package
+ phases = ['configure', 'build', 'install']
+
+ #: This attribute is used in UI queries that need to know the build
+ #: system base class
+ build_system_class = 'PerlPackage'
+
+ #: Callback names for build-time test
+ build_time_test_callbacks = ['check']
+
+ extends('perl')
+
+ def configure_args(self):
+ """Produces a list containing the arguments that must be passed to
+ :py:meth:`~.PerlPackage.configure`. Arguments should not include
+ the installation base directory, which is prepended automatically.
+
+ :return: list of arguments for Makefile.PL or Build.PL
+ """
+ return []
+
+ def configure(self, spec, prefix):
+ """Runs Makefile.PL or Build.PL with arguments consisting of
+ an appropriate installation base directory followed by the
+ list returned by :py:meth:`~.PerlPackage.configure_args`.
+
+ :raise RuntimeError: if neither Makefile.PL or Build.PL exist
+ """
+ if os.path.isfile('Makefile.PL'):
+ self.build_method = 'Makefile.PL'
+ self.build_executable = inspect.getmodule(self).make
+ elif os.path.isfile('Build.PL'):
+ self.build_method = 'Build.PL'
+ self.build_executable = Executable(
+ join_path(self.stage.source_path, 'Build'))
+ else:
+ raise RuntimeError('Unknown build_method for perl package')
+
+ if self.build_method == 'Makefile.PL':
+ options = ['Makefile.PL', 'INSTALL_BASE={0}'.format(prefix)]
+ elif self.build_method == 'Build.PL':
+ options = ['Build.PL', '--install_base', prefix]
+ options += self.configure_args()
+
+ inspect.getmodule(self).perl(*options)
+
+ def build(self, spec, prefix):
+ """Builds a Perl package."""
+ self.build_executable()
+
+ # Ensure that tests run after build (if requested):
+ run_after('build')(PackageBase._run_default_build_time_test_callbacks)
+
+ def check(self):
+ """Runs built-in tests of a Perl package."""
+ self.build_executable('test')
+
+ def install(self, spec, prefix):
+ """Installs a Perl package."""
+ self.build_executable('install')
+
+ # Check that self.prefix is there after installation
+ run_after('install')(PackageBase.sanity_check_prefix)
diff --git a/lib/spack/spack/cmd/build.py b/lib/spack/spack/cmd/build.py
index 6a90af907d..90157a85af 100644
--- a/lib/spack/spack/cmd/build.py
+++ b/lib/spack/spack/cmd/build.py
@@ -31,7 +31,8 @@ description = 'stops at build stage when installing a package, if possible'
build_system_to_phase = {
CMakePackage: 'build',
AutotoolsPackage: 'build',
- PythonPackage: 'build'
+ PythonPackage: 'build',
+ PerlPackage: 'build'
}
diff --git a/lib/spack/spack/cmd/configure.py b/lib/spack/spack/cmd/configure.py
index 7b1ef04522..b6669f33a2 100644
--- a/lib/spack/spack/cmd/configure.py
+++ b/lib/spack/spack/cmd/configure.py
@@ -36,7 +36,8 @@ description = 'stops at configuration stage when installing a package, if possib
build_system_to_phase = {
CMakePackage: 'cmake',
- AutotoolsPackage: 'configure'
+ AutotoolsPackage: 'configure',
+ PerlPackage: 'configure'
}
diff --git a/lib/spack/spack/cmd/create.py b/lib/spack/spack/cmd/create.py
index 14b213a756..cc90669158 100644
--- a/lib/spack/spack/cmd/create.py
+++ b/lib/spack/spack/cmd/create.py
@@ -268,6 +268,45 @@ class RPackageTemplate(PackageTemplate):
super(RPackageTemplate, self).__init__(name, *args)
+class PerlmakePackageTemplate(PackageTemplate):
+ """Provides appropriate overrides for Perl extensions
+ that come with a Makefile.PL"""
+ base_class_name = 'PerlPackage'
+
+ dependencies = """\
+ # FIXME: Add dependencies if required:
+ # depends_on('perl-foo')
+ # depends_on('barbaz', type=('build', 'link', 'run'))"""
+
+ body = """\
+ # FIXME: If non-standard arguments are used for configure step:
+ # def configure_args(self):
+ # return ['my', 'configure', 'args']
+
+ # FIXME: in unusual cases, it may be necessary to override methods for
+ # configure(), build(), check() or install()."""
+
+ def __init__(self, name, *args):
+ # If the user provided `--name perl-cpp`, don't rename it perl-perl-cpp
+ if not name.startswith('perl-'):
+ # Make it more obvious that we are renaming the package
+ tty.msg("Changing package name from {0} to perl-{0}".format(name))
+ name = 'perl-{0}'.format(name)
+
+ super(PerlmakePackageTemplate, self).__init__(name, *args)
+
+
+class PerlbuildPackageTemplate(PerlmakePackageTemplate):
+ """Provides appropriate overrides for Perl extensions
+ that come with a Build.PL instead of a Makefile.PL"""
+ dependencies = """\
+ depends_on('perl-module-build', type='build')
+
+ # FIXME: Add additional dependencies if required:
+ # depends_on('perl-foo')
+ # depends_on('barbaz', type=('build', 'link', 'run'))"""
+
+
class OctavePackageTemplate(PackageTemplate):
"""Provides appropriate overrides for octave packages"""
@@ -305,6 +344,8 @@ templates = {
'bazel': BazelPackageTemplate,
'python': PythonPackageTemplate,
'r': RPackageTemplate,
+ 'perlmake': PerlmakePackageTemplate,
+ 'perlbuild': PerlbuildPackageTemplate,
'octave': OctavePackageTemplate,
'generic': PackageTemplate
}
@@ -363,7 +404,9 @@ class BuildSystemGuesser:
(r'/SConstruct$', 'scons'),
(r'/setup.py$', 'python'),
(r'/NAMESPACE$', 'r'),
- (r'/WORKSPACE$', 'bazel')
+ (r'/WORKSPACE$', 'bazel'),
+ (r'/Build.PL$', 'perlbuild'),
+ (r'/Makefile.PL$', 'perlmake'),
]
# Peek inside the compressed file.
diff --git a/lib/spack/spack/test/build_system_guess.py b/lib/spack/spack/test/build_system_guess.py
index 82bf1964b2..e6fb84b37d 100644
--- a/lib/spack/spack/test/build_system_guess.py
+++ b/lib/spack/spack/test/build_system_guess.py
@@ -38,6 +38,8 @@ import spack.stage
('setup.py', 'python'),
('NAMESPACE', 'r'),
('WORKSPACE', 'bazel'),
+ ('Makefile.PL', 'perlmake'),
+ ('Build.PL', 'perlbuild'),
('foobar', 'generic')
]
)