summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAdam J. Stewart <ajstewart426@gmail.com>2019-07-30 17:12:48 -0500
committerGitHub <noreply@github.com>2019-07-30 17:12:48 -0500
commitb34da4e108b7441d26ca6c02871cba65a0530566 (patch)
treee120912824c3cf4929c999ad157a58d1e75910c3 /lib
parentf487f87e3edefdf2a8cffa95d72f2ce44ad5c0e0 (diff)
downloadspack-b34da4e108b7441d26ca6c02871cba65a0530566.tar.gz
spack-b34da4e108b7441d26ca6c02871cba65a0530566.tar.bz2
spack-b34da4e108b7441d26ca6c02871cba65a0530566.tar.xz
spack-b34da4e108b7441d26ca6c02871cba65a0530566.zip
Add SIPPackage base class (#12157)
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/docs/build_systems.rst1
-rw-r--r--lib/spack/docs/build_systems/sippackage.rst135
-rw-r--r--lib/spack/spack/build_systems/sip.py113
-rw-r--r--lib/spack/spack/cmd/build.py2
-rw-r--r--lib/spack/spack/cmd/configure.py2
-rw-r--r--lib/spack/spack/cmd/create.py24
-rw-r--r--lib/spack/spack/pkgkit.py1
-rw-r--r--lib/spack/spack/test/build_system_guess.py1
8 files changed, 279 insertions, 0 deletions
diff --git a/lib/spack/docs/build_systems.rst b/lib/spack/docs/build_systems.rst
index 513082d9b8..93b8e5c7a8 100644
--- a/lib/spack/docs/build_systems.rst
+++ b/lib/spack/docs/build_systems.rst
@@ -40,6 +40,7 @@ on these ideas for each distinct build system that Spack supports:
build_systems/cmakepackage
build_systems/mesonpackage
build_systems/qmakepackage
+ build_systems/sippackage
.. toctree::
:maxdepth: 1
diff --git a/lib/spack/docs/build_systems/sippackage.rst b/lib/spack/docs/build_systems/sippackage.rst
new file mode 100644
index 0000000000..cb744e858f
--- /dev/null
+++ b/lib/spack/docs/build_systems/sippackage.rst
@@ -0,0 +1,135 @@
+.. Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
+ Spack Project Developers. See the top-level COPYRIGHT file for details.
+
+ SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+.. _sippackage:
+
+----------
+SIPPackage
+----------
+
+SIP is a tool that makes it very easy to create Python bindings for C and C++
+libraries. It was originally developed to create PyQt, the Python bindings for
+the Qt toolkit, but can be used to create bindings for any C or C++ library.
+
+SIP comprises a code generator and a Python module. The code generator
+processes a set of specification files and generates C or C++ code which is
+then compiled to create the bindings extension module. The SIP Python module
+provides support functions to the automatically generated code.
+
+^^^^^^
+Phases
+^^^^^^
+
+The ``SIPPackage`` base class comes with the following phases:
+
+#. ``configure`` - configure the package
+#. ``build`` - build the package
+#. ``install`` - install the package
+
+By default, these phases run:
+
+.. code-block:: console
+
+ $ python configure.py --bindir ... --destdir ...
+ $ make
+ $ make install
+
+
+^^^^^^^^^^^^^^^
+Important files
+^^^^^^^^^^^^^^^
+
+Each SIP package comes with a custom ``configure.py`` build script,
+written in Python. This script contains instructions to build the project.
+
+^^^^^^^^^^^^^^^^^^^^^^^^^
+Build system dependencies
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``SIPPackage`` requires several dependencies. Python is needed to run
+the ``configure.py`` build script, and to run the resulting Python
+libraries. Qt is needed to provide the ``qmake`` command. SIP is also
+needed to build the package. All of these dependencies are automatically
+added via the base class
+
+.. code-block:: python
+
+ extends('python')
+
+ depends_on('qt', type='build')
+ depends_on('py-sip', type='build')
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Passing arguments to ``configure.py``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Each phase comes with a ``<phase_args>`` function that can be used to pass
+arguments to that particular phase. For example, if you need to pass
+arguments to the configure phase, you can use:
+
+.. code-block:: python
+
+ def configure_args(self, spec, prefix):
+ return ['--no-python-dbus']
+
+
+A list of valid options can be found by running ``python configure.py --help``.
+
+^^^^^^^
+Testing
+^^^^^^^
+
+Just because a package successfully built does not mean that it built
+correctly. The most reliable test of whether or not the package was
+correctly installed is to attempt to import all of the modules that
+get installed. To get a list of modules, run the following command
+in the site-packages directory:
+
+.. code-block:: console
+
+ $ python
+ >>> import setuptools
+ >>> setuptools.find_packages()
+ ['QtPy5']
+
+
+Large, complex packages like ``QtPy5`` will return a long list of
+packages, while other packages may return an empty list. These packages
+only install a single ``foo.py`` file. In Python packaging lingo,
+a "package" is a directory containing files like:
+
+.. code-block:: none
+
+ foo/__init__.py
+ foo/bar.py
+ foo/baz.py
+
+
+whereas a "module" is a single Python file. Since ``find_packages``
+only returns packages, you'll have to determine the correct module
+names yourself. You can now add these packages and modules to the
+package like so:
+
+.. code-block:: python
+
+ import_modules = ['PyQt5']
+
+
+When you run ``spack install --test=root py-pyqt5``, Spack will attempt
+to import the ``PyQt5`` module after installation.
+
+These tests most often catch missing dependencies and non-RPATHed
+libraries.
+
+^^^^^^^^^^^^^^^^^^^^^^
+External documentation
+^^^^^^^^^^^^^^^^^^^^^^
+
+For more information on the SIP build system, see:
+
+* https://www.riverbankcomputing.com/software/sip/intro
+* https://www.riverbankcomputing.com/static/Docs/sip/
+* https://wiki.python.org/moin/SIP
diff --git a/lib/spack/spack/build_systems/sip.py b/lib/spack/spack/build_systems/sip.py
new file mode 100644
index 0000000000..6d51ff57bd
--- /dev/null
+++ b/lib/spack/spack/build_systems/sip.py
@@ -0,0 +1,113 @@
+# Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+import inspect
+import os
+
+from llnl.util.filesystem import working_dir
+from spack.directives import depends_on, extends
+from spack.package import PackageBase, run_after
+
+
+class SIPPackage(PackageBase):
+ """Specialized class for packages that are built using the
+ SIP build system. See https://www.riverbankcomputing.com/software/sip/intro
+ for more information.
+
+ This class provides the following phases that can be overridden:
+
+ * configure
+ * build
+ * install
+
+ The configure phase already adds a set of default flags. To see more
+ options, run ``python configure.py --help``.
+ """
+ # Default phases
+ phases = ['configure', 'build', 'install']
+
+ # To be used in UI queries that require to know which
+ # build-system class we are using
+ build_system_class = 'SIPPackage'
+
+ #: Callback names for install-time test
+ install_time_test_callbacks = ['import_module_test']
+
+ extends('python')
+
+ depends_on('qt')
+ depends_on('py-sip')
+
+ def configure_file(self):
+ """Returns the name of the configure file to use."""
+ return 'configure.py'
+
+ def python(self, *args, **kwargs):
+ """The python ``Executable``."""
+ inspect.getmodule(self).python(*args, **kwargs)
+
+ def configure(self, spec, prefix):
+ """Configure the package."""
+ configure = self.configure_file()
+
+ args = self.configure_args()
+
+ args.extend([
+ '--verbose',
+ '--confirm-license',
+ '--qmake', spec['qt'].prefix.bin.qmake,
+ '--sip', spec['py-sip'].prefix.bin.sip,
+ '--sip-incdir', os.path.join(
+ spec['py-sip'].prefix,
+ spec['python'].package.python_include_dir
+ ),
+ '--bindir', prefix.bin,
+ '--destdir', inspect.getmodule(self).site_packages_dir,
+ ])
+
+ self.python(configure, *args)
+
+ def configure_args(self):
+ """Arguments to pass to configure."""
+ return []
+
+ def build(self, spec, prefix):
+ """Build the package."""
+ args = self.build_args()
+
+ inspect.getmodule(self).make(*args)
+
+ def build_args(self):
+ """Arguments to pass to build."""
+ return []
+
+ def install(self, spec, prefix):
+ """Install the package."""
+ args = self.install_args()
+
+ inspect.getmodule(self).make('install', parallel=False, *args)
+
+ def install_args(self):
+ """Arguments to pass to install."""
+ return []
+
+ # Testing
+
+ def import_module_test(self):
+ """Attempts to import the module that was just installed.
+
+ This test is only run if the package overrides
+ :py:attr:`import_modules` with a list of module names."""
+
+ # Make sure we are importing the installed modules,
+ # not the ones in the current directory
+ with working_dir('spack-test', create=True):
+ for module in self.import_modules:
+ self.python('-c', 'import {0}'.format(module))
+
+ run_after('install')(PackageBase._run_default_install_time_test_callbacks)
+
+ # 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 bbace88b31..84d8221090 100644
--- a/lib/spack/spack/cmd/build.py
+++ b/lib/spack/spack/cmd/build.py
@@ -13,6 +13,7 @@ from spack.build_systems.waf import WafPackage
from spack.build_systems.python import PythonPackage
from spack.build_systems.perl import PerlPackage
from spack.build_systems.meson import MesonPackage
+from spack.build_systems.sip import SIPPackage
description = 'stops at build stage when installing a package, if possible'
section = "build"
@@ -28,6 +29,7 @@ build_system_to_phase = {
PythonPackage: 'build',
PerlPackage: 'build',
MesonPackage: 'build',
+ SIPPackage: 'build',
}
diff --git a/lib/spack/spack/cmd/configure.py b/lib/spack/spack/cmd/configure.py
index 64608b4643..b06d4edf1c 100644
--- a/lib/spack/spack/cmd/configure.py
+++ b/lib/spack/spack/cmd/configure.py
@@ -16,6 +16,7 @@ from spack.build_systems.waf import WafPackage
from spack.build_systems.perl import PerlPackage
from spack.build_systems.intel import IntelPackage
from spack.build_systems.meson import MesonPackage
+from spack.build_systems.sip import SIPPackage
description = 'stage and configure a package but do not install'
section = "build"
@@ -30,6 +31,7 @@ build_system_to_phase = {
PerlPackage: 'configure',
IntelPackage: 'configure',
MesonPackage: 'meson',
+ SIPPackage: 'configure',
}
diff --git a/lib/spack/spack/cmd/create.py b/lib/spack/spack/cmd/create.py
index 792a437f29..59e3274bdb 100644
--- a/lib/spack/spack/cmd/create.py
+++ b/lib/spack/spack/cmd/create.py
@@ -350,6 +350,28 @@ class IntelPackageTemplate(PackageTemplate):
# FIXME: Override `setup_environment` if necessary."""
+class SIPPackageTemplate(PackageTemplate):
+ """Provides appropriate overrides for SIP packages."""
+
+ base_class_name = 'SIPPackage'
+
+ body = """\
+ def configure_args(self, spec, prefix):
+ # FIXME: Add arguments other than --bindir and --destdir
+ # FIXME: If not needed delete this function
+ args = []
+ return args"""
+
+ def __init__(self, name, *args):
+ # If the user provided `--name py-pyqt4`, don't rename it py-py-pyqt4
+ if not name.startswith('py-'):
+ # Make it more obvious that we are renaming the package
+ tty.msg("Changing package name from {0} to py-{0}".format(name))
+ name = 'py-{0}'.format(name)
+
+ super(SIPPackageTemplate, self).__init__(name, *args)
+
+
templates = {
'autotools': AutotoolsPackageTemplate,
'autoreconf': AutoreconfPackageTemplate,
@@ -366,6 +388,7 @@ templates = {
'makefile': MakefilePackageTemplate,
'intel': IntelPackageTemplate,
'meson': MesonPackageTemplate,
+ 'sip': SIPPackageTemplate,
'generic': PackageTemplate,
}
@@ -440,6 +463,7 @@ class BuildSystemGuesser:
(r'/(GNU)?[Mm]akefile$', 'makefile'),
(r'/DESCRIPTION$', 'octave'),
(r'/meson\.build$', 'meson'),
+ (r'/configure\.py$', 'sip'),
]
# Peek inside the compressed file.
diff --git a/lib/spack/spack/pkgkit.py b/lib/spack/spack/pkgkit.py
index 85c1ee264e..ff3288f48a 100644
--- a/lib/spack/spack/pkgkit.py
+++ b/lib/spack/spack/pkgkit.py
@@ -27,6 +27,7 @@ from spack.build_systems.r import RPackage
from spack.build_systems.perl import PerlPackage
from spack.build_systems.intel import IntelPackage
from spack.build_systems.meson import MesonPackage
+from spack.build_systems.sip import SIPPackage
from spack.mixins import filter_compiler_wrappers
diff --git a/lib/spack/spack/test/build_system_guess.py b/lib/spack/spack/test/build_system_guess.py
index 80dbb35f15..cd6216a907 100644
--- a/lib/spack/spack/test/build_system_guess.py
+++ b/lib/spack/spack/test/build_system_guess.py
@@ -27,6 +27,7 @@ import spack.stage
('makefile', 'makefile'),
('Makefile', 'makefile'),
('meson.build', 'meson'),
+ ('configure.py', 'sip'),
('foobar', 'generic')
]
)