[lttng-dev] [PATCH babeltrace] Build Python bindings with distutils for consistent installs

Francis Deslauriers francis.deslauriers at efficios.com
Mon Feb 20 16:47:36 UTC 2017


I noticed some shortcomings for this patch. I will send an updated
version shortly.

Francis

2017-02-17 15:59 GMT-05:00 Francis Deslauriers
<francis.deslauriers at efficios.com>:
> This patch changes the build system used to compile and install the
> Python Bindings. Distutils is used to find the right install directory.
> When the install directory generated from the install prefix is not in
> the Python search path (PYTHON_PATH), we print a warning explaining what
> can be done to include it.
> It uses Distutils which is part of the Python standard library.
>
> To be applied on top of 1.5.
>
> Signed-off-by: Francis Deslauriers <francis.deslauriers at efficios.com>
> ---
>  .gitignore                                | 10 +++--
>  bindings/python/Makefile.am               | 39 +++++++++++++++-
>  bindings/python/babeltrace/Makefile.am    | 31 -------------
>  bindings/python/babeltrace/__init__.py.in | 25 +++++++++++
>  bindings/python/setup.py.in               | 75 +++++++++++++++++++++++++++++++
>  configure.ac                              | 14 +++---
>  m4/python_modules.m4                      | 23 ----------
>  7 files changed, 153 insertions(+), 64 deletions(-)
>  delete mode 100644 bindings/python/babeltrace/Makefile.am
>  create mode 100644 bindings/python/babeltrace/__init__.py.in
>  create mode 100644 bindings/python/setup.py.in
>  delete mode 100644 m4/python_modules.m4
>
> diff --git a/.gitignore b/.gitignore
> index a7c9e3c..9259b6f 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -47,8 +47,12 @@ converter/babeltrace-log
>  core
>  formats/ctf/metadata/ctf-parser.output
>  stamp-h1
> -bindings/python/babeltrace.i
> -bindings/python/babeltrace.py
> -bindings/python/babeltrace_wrap.c
> +bindings/python/setup.py
> +bindings/python/installed_files.txt
> +bindings/python/build
> +bindings/python/babeltrace/__init__.py
> +bindings/python/babeltrace/babeltrace.i
> +bindings/python/babeltrace/babeltrace.py
> +bindings/python/babeltrace/babeltrace_wrap.c
>  babeltrace.pc
>  babeltrace-ctf.pc
> diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am
> index d6b3648..ab75a3a 100644
> --- a/bindings/python/Makefile.am
> +++ b/bindings/python/Makefile.am
> @@ -1,3 +1,40 @@
>  if USE_PYTHON
> -SUBDIRS = babeltrace
> +
> +SUBDIRS = .
> +
> +AM_CFLAGS = $(PACKAGE_CFLAGS) -I$(top_srcdir)/include -I$(srcdir)/babeltrace/
> +
> +# Since the shared object used by the python bindings is not built with libtool
> +# we need to manually set the `rpath` during linkage
> +AM_LDFLAGS=-L$(top_builddir)/formats/ctf/.libs -L$(top_builddir)/lib/.libs -Wl,-rpath,$(prefix)/lib
> +
> +INSTALLED_FILES=installed_files.txt
> +
> +all-local:
> +       CC="$(CC)" CFLAGS="$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(GLIB_CFLAGS) $(AM_CFLAGS)" CPPFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS)" LDFLAGS="$(AM_LDFLAGS) $(LDFLAGS)" $(PYTHON) $(builddir)/setup.py build_ext --swig-opts="-Wall -I$(top_srcdir)"
> +       $(PYTHON) $(builddir)/setup.py build
> +
> +# This target installs the Python package and saves the path of all the
> +# installed files in the INSTALLED_FILES text file to be used during this
> +# uninstallation
> +install-exec-local:
> +       @opts="--prefix=$(prefix) --verbose --record $(INSTALLED_FILES) --no-compile $(DISTSETUPOPTS)"; \
> +       if [ "$(DESTDIR)" != "" ]; then \
> +               opts="$$opts --root=$(DESTDIR)"; \
> +       fi; \
> +       $(PYTHON) $(builddir)/setup.py install $$opts;
> +
> +clean-local:
> +       rm -rf $(builddir)/build
> +
> +# Distutils' setup.py does not include an uninstall target, we thus need to do it
> +# manually. We use the INSTALLED_FILES file produced during the install to
> +# clean up the install folder and delete the folder it self.
> +uninstall-local:
> +       cat $(INSTALLED_FILES) | xargs rm -rf
> +       cat $(INSTALLED_FILES) | $(GREP) "__init__.py" | xargs dirname | xargs rmdir
> +       rm -f $(INSTALLED_FILES)
> +
> +CLEANFILES = babeltrace/babeltrace_wrap.c babeltrace/babeltrace.py
> +DISTCLEANFILES = babeltrace/__init__.py babeltrace/babeltrace.i
>  endif
> diff --git a/bindings/python/babeltrace/Makefile.am b/bindings/python/babeltrace/Makefile.am
> deleted file mode 100644
> index 11dcdf0..0000000
> --- a/bindings/python/babeltrace/Makefile.am
> +++ /dev/null
> @@ -1,31 +0,0 @@
> -babeltrace.i: babeltrace.i.in
> -       sed "s/BABELTRACE_VERSION_STR/Babeltrace $(PACKAGE_VERSION)/g" < \
> -               $(top_srcdir)/bindings/python/babeltrace/babeltrace.i.in > \
> -               $(top_builddir)/bindings/python/babeltrace/babeltrace.i
> -
> -AM_CFLAGS = $(PYTHON_INCLUDE) -I$(top_srcdir)/include/ \
> -               -I$(top_srcdir)/bindings/python/babeltrace
> -
> -EXTRA_DIST = babeltrace.i.in
> -nodist_python_PYTHON = babeltrace.py
> -pyexec_LTLIBRARIES = _babeltrace.la
> -
> -MAINTAINERCLEANFILES = babeltrace_wrap.c babeltrace.py
> -
> -nodist__babeltrace_la_SOURCES = babeltrace_wrap.c
> -_babeltrace_la_SOURCES = python-complements.h python-complements.c
> -_babeltrace_la_LDFLAGS = -module
> -
> -_babeltrace_la_CFLAGS = $(GLIB_CFLAGS) $(AM_CFLAGS)
> -
> -_babeltrace_la_LIBS = $(GLIB_LIBS)
> -
> -_babeltrace_la_LIBADD = $(top_builddir)/formats/ctf/libbabeltrace-ctf.la \
> -       $(top_builddir)/formats/ctf-text/libbabeltrace-ctf-text.la
> -
> -# SWIG 'warning md variable unused' fixed after SWIG build:
> -babeltrace_wrap.c: babeltrace.i
> -       $(SWIG) -python -Wall -I. -I$(top_srcdir)/include \
> -               $(top_builddir)/bindings/python/babeltrace/babeltrace.i
> -
> -CLEANFILES = babeltrace.i babeltrace.py babeltrace_wrap.c
> diff --git a/bindings/python/babeltrace/__init__.py.in b/bindings/python/babeltrace/__init__.py.in
> new file mode 100644
> index 0000000..eb1e76a
> --- /dev/null
> +++ b/bindings/python/babeltrace/__init__.py.in
> @@ -0,0 +1,25 @@
> +# The MIT License (MIT)
> +#
> +# Copyright (C) 2017 - Francis Deslauriers <francis.deslauriers at efficios.com>
> +#
> +# Permission is hereby granted, free of charge, to any person obtaining a copy
> +# of this software and associated documentation files (the "Software"), to deal
> +# in the Software without restriction, including without limitation the rights
> +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> +# copies of the Software, and to permit persons to whom the Software is
> +# furnished to do so, subject to the following conditions:
> +#
> +# The above copyright notice and this permission notice shall be included in
> +# all copies or substantial portions of the Software.
> +#
> +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> +# THE SOFTWARE.
> +
> +from .babeltrace import *
> +
> +__version__ = '@PACKAGE_VERSION@'
> diff --git a/bindings/python/setup.py.in b/bindings/python/setup.py.in
> new file mode 100644
> index 0000000..7d11cca
> --- /dev/null
> +++ b/bindings/python/setup.py.in
> @@ -0,0 +1,75 @@
> +# The MIT License (MIT)
> +#
> +# Copyright (C) 2017 - Francis Deslauriers <francis.deslauriers at efficios.com>
> +#
> +# Permission is hereby granted, free of charge, to any person obtaining a copy
> +# of this software and associated documentation files (the "Software"), to deal
> +# in the Software without restriction, including without limitation the rights
> +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> +# copies of the Software, and to permit persons to whom the Software is
> +# furnished to do so, subject to the following conditions:
> +#
> +# The above copyright notice and this permission notice shall be included in
> +# all copies or substantial portions of the Software.
> +#
> +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> +# THE SOFTWARE.
> +
> +import sys
> +
> +from distutils.core import setup, Extension
> +
> +PY_PATH_WARN_MSG= """
> +-------------------------------------WARNING------------------------------------
> +The install directory used:\n ({})\nis not included in your PYTHON_PATH.
> +
> +To add this directory to your Python search path permanently you can add the
> +following command to your .bashrc/.zshrc:
> +    export PYTHONPATH="${{PYTHONPATH}}:{}"
> +--------------------------------------------------------------------------------
> +"""
> +
> +def main():
> +    babeltrace_ext = Extension('babeltrace/_babeltrace',
> +                        sources=['babeltrace/babeltrace.i','babeltrace/python-complements.c'],
> +                        libraries=['babeltrace', 'babeltrace-ctf'],)
> +
> +    dist = setup(name='babeltrace',
> +            version='@PACKAGE_VERSION@',
> +            description='Babeltrace Python Bindings',
> +            packages=['babeltrace'],
> +            package_dir={'babeltrace': 'babeltrace'},
> +            options={'build': {'build_base': 'build'}},
> +            url='http://diamon.org/babeltrace',
> +            ext_modules=[babeltrace_ext],
> +            license='MIT',
> +            classifiers=[
> +                'Development Status :: 5 - Production/Stable',
> +                'Intended Audience :: Developers',
> +                'License :: OSI Approved :: The MIT License',
> +                'Programming Language :: Python :: 3'
> +                'Topic :: System :: Logging',
> +                ])
> +
> +# After the installation, we check that the install directory is included in
> +# the Python search path and we print a warning message when it's not.
> +# We need to do this because Python search path differs depending on the distro
> +# and some distros don't include any /usr/local/ in the search path. This is
> +# also useful for out-of-tree installs and tests.
> +# It's only relevant to make this check on the `install` command.
> +
> +    if 'install' in dist.command_obj:
> +        install_dir = dist.command_obj['install'].install_libbase
> +        if install_dir not in sys.path:
> +            # We can't consider this an error because if affects every
> +            # distro differently. We only warn the user that some
> +            # extra configuration is needed to use the bindings
> +            print(PY_PATH_WARN_MSG.format(install_dir, install_dir))
> +
> +if __name__ == "__main__":
> +    main()
> diff --git a/configure.ac b/configure.ac
> index 56255d0..e7d98b9 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -235,11 +235,6 @@ if test "x${enable_python:-yes}" = xyes; then
>    AX_PKG_SWIG($swig_version, [], [ AC_MSG_ERROR([SWIG $swig_version or newer is needed]) ])
>    AM_PATH_PYTHON
>
> -  AM_PATH_PYTHON_MODULES([PYTHON])
> -  # pythondir is the path where extra modules are to be installed
> -  pythondir=$PYTHON_PREFIX/$PYTHON_MODULES_PATH
> -  # pyexecdir is the path that contains shared objects used by the extra modules
> -  pyexecdir=$PYTHON_EXEC_PREFIX/$PYTHON_MODULES_PATH
>    AC_ARG_VAR([PYTHON_INCLUDE], [Include flags for python, bypassing python-config])
>    AC_ARG_VAR([PYTHON_CONFIG], [Path to python-config])
>    AS_IF([test -z "$PYTHON_INCLUDE"], [
> @@ -327,7 +322,9 @@ AC_CONFIG_FILES([
>         include/Makefile
>         bindings/Makefile
>         bindings/python/Makefile
> -       bindings/python/babeltrace/Makefile
> +       bindings/python/setup.py
> +       bindings/python/babeltrace/babeltrace.i
> +       bindings/python/babeltrace/__init__.py
>         tests/Makefile
>         tests/bin/Makefile
>         tests/bin/intersection/Makefile
> @@ -351,6 +348,11 @@ AC_CONFIG_FILES([tests/bin/intersection/test_intersection], [chmod +x tests/bin/
>  AC_CONFIG_FILES([tests/bin/intersection/bt_python_helper.py])
>  AC_CONFIG_FILES([tests/bin/test_packet_seq_num], [chmod +x tests/bin/test_packet_seq_num])
>
> +# Create link for Babeltrace complements files for out-of-tree builds
> +AC_CONFIG_LINKS([
> +       bindings/python/babeltrace/python-complements.c:bindings/python/babeltrace/python-complements.c
> +])
> +
>  AC_OUTPUT
>
>  #
> diff --git a/m4/python_modules.m4 b/m4/python_modules.m4
> deleted file mode 100644
> index 132c4c2..0000000
> --- a/m4/python_modules.m4
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -# python_modules.m4 -- Get the Python modules install path
> -#
> -# Copyright (C) 2014 - Jérémie Galarneau <jeremie.galarneau at efficios.com>
> -#
> -# This file is free software; the Free Software Foundation gives
> -# unlimited permission to copy and/or distribute it, with or without
> -# modifications, as long as this notice is preserved.
> -
> -# While extra Python modules are generaly installed in the Python
> -# interpreter's "site-packages" directory, Debian prefers using the
> -# "dist-packages" nomenclature. This macro uses the interpreter
> -# designated by the PYTHON variable to check the interpreter's PATH
> -# and sets the PYTHON_MODULES_PATH by taking the prefix into account.
> -
> -# AM_PATH_PYTHON_MODULES(PYTHON)
> -# ---------------------------------------------------------------------------
> -AC_DEFUN([AM_PATH_PYTHON_MODULES],
> - [prog="import sys
> -for path in sys.path:
> -    if path.endswith(\"-packages\"):
> -       print(path[[path.find(\"/lib\"):]])
> -       break"
> -  PYTHON_MODULES_PATH=`${$1} -c "$prog"`])
> --
> 2.7.4
>



-- 
Francis Deslauriers
Software developer
EfficiOS inc.


More information about the lttng-dev mailing list