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

Jérémie Galarneau jeremie.galarneau at efficios.com
Fri May 26 13:36:50 UTC 2017


Merged in stable-1.4 and stable-1.5. Thanks!

Jérémie

On 11 April 2017 at 15:27, Francis Deslauriers
<francis.deslauriers at efficios.com> wrote:
> v5: Manually load shared objects used by the Babeltrace Python module
>
> 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 (PYTHONPATH), we print a warning explaining what
> can be done to include it.
> It uses Distutils which is part of the Python standard library.
>
> Signed-off-by: Francis Deslauriers <francis.deslauriers at efficios.com>
> ---
>  .gitignore                                    | 10 +++-
>  bindings/python/Makefile.am                   | 57 +++++++++++++++++-
>  bindings/python/babeltrace/Makefile.am        | 30 ++--------
>  bindings/python/babeltrace/__init__.py.in     | 25 ++++++++
>  bindings/python/setup.py.in                   | 84 +++++++++++++++++++++++++++
>  configure.ac                                  | 14 +++--
>  m4/python_modules.m4                          | 23 --------
>  tests/bin/intersection/bt_python_helper.py.in | 17 +++---
>  8 files changed, 195 insertions(+), 65 deletions(-)
>  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..9e44127 100644
> --- a/bindings/python/Makefile.am
> +++ b/bindings/python/Makefile.am
> @@ -1,3 +1,58 @@
>  if USE_PYTHON
> -SUBDIRS = babeltrace
> +SUBDIRS = babeltrace .
> +
> +INSTALLED_FILES=$(builddir)/installed_files.txt
> +
> +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
> +all-local: build-python-bindings.stamp
> +
> +$(builddir)/babeltrace/__init__.py: $(srcdir)/babeltrace/__init__.py.in
> +       cd babeltrace && $(MAKE) __init__.py
> +
> +$(builddir)/babeltrace/babeltrace.i: $(srcdir)/babeltrace/babeltrace.i.in
> +       cd babeltrace && $(MAKE) babeltrace.i
> +
> +BINDINGS_DEPS=setup.py \
> +               babeltrace/__init__.py \
> +               babeltrace/babeltrace.i \
> +               babeltrace/python-complements.c \
> +               babeltrace/python-complements.h
> +
> +BUILD_FLAGS=CC="$(CC)" \
> +               CFLAGS="$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(GLIB_CFLAGS) $(AM_CFLAGS)" \
> +               CPPFLAGS="$(AM_CPPFLAGS) $(CPPFLAGS)" \
> +               LDFLAGS="$(AM_LDFLAGS) $(LDFLAGS)"
> +
> +build-python-bindings.stamp: $(BINDINGS_DEPS)
> +       $(BUILD_FLAGS) $(PYTHON) $(builddir)/setup.py build_ext
> +       $(BUILD_FLAGS) $(PYTHON) $(builddir)/setup.py build
> +       touch $@
> +
> +install-exec-local: build-python-bindings.stamp
> +       @opts="--prefix=$(prefix) --record $(INSTALLED_FILES) --verbose --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 save the path of the files that were installed during the install target
> +# and delete them during the uninstallation.
> +uninstall-local:
> +       if [ "$(DESTDIR)" != "" ]; then \
> +               $(SED) -i "s|^|$(DESTDIR)/|g" $(INSTALLED_FILES); \
> +       fi
> +       cat $(INSTALLED_FILES) | xargs rm -rf || true
> +       $(GREP) "__init__.py" $(INSTALLED_FILES) | xargs dirname | xargs rm -rf || true
> +       rm -f $(INSTALLED_FILES)
> +
> +CLEANFILES = babeltrace/babeltrace_wrap.c babeltrace/babeltrace.py build-python-bindings.stamp
> +DISTCLEANFILES = setup.py
>  endif
> diff --git a/bindings/python/babeltrace/Makefile.am b/bindings/python/babeltrace/Makefile.am
> index 11dcdf0..f612aa6 100644
> --- a/bindings/python/babeltrace/Makefile.am
> +++ b/bindings/python/babeltrace/Makefile.am
> @@ -1,31 +1,9 @@
> +if USE_PYTHON
>  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
> +#the __init__.py target is generated by the automake
> +DISTCLEANFILES = __init__.py babeltrace.i
> +endif
> 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..9baa062
> --- /dev/null
> +++ b/bindings/python/setup.py.in
> @@ -0,0 +1,84 @@
> +# 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 PYTHONPATH.
> +
> +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',
> +                    'build_lib': 'build/build_lib'
> +                },
> +                'build_ext':
> +                {
> +                    'build_lib': 'build/build_lib'
> +                }
> +            },
> +            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 2382e53..a117229 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -241,11 +241,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"], [
> @@ -333,7 +328,9 @@ AC_CONFIG_FILES([
>         include/Makefile
>         bindings/Makefile
>         bindings/python/Makefile
> +       bindings/python/setup.py
>         bindings/python/babeltrace/Makefile
> +       bindings/python/babeltrace/__init__.py
>         tests/Makefile
>         tests/bin/Makefile
>         tests/bin/intersection/Makefile
> @@ -357,6 +354,13 @@ 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
> +       bindings/python/babeltrace/python-complements.h:bindings/python/babeltrace/python-complements.h
> +       bindings/python/babeltrace/babeltrace.i.in:bindings/python/babeltrace/babeltrace.i.in
> +])
> +
>  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"`])
> diff --git a/tests/bin/intersection/bt_python_helper.py.in b/tests/bin/intersection/bt_python_helper.py.in
> index 11b4ab1..747f0e7 100644
> --- a/tests/bin/intersection/bt_python_helper.py.in
> +++ b/tests/bin/intersection/bt_python_helper.py.in
> @@ -23,15 +23,18 @@
>  # SOFTWARE.
>
>  import sys
> +import ctypes
>
>  # Point the Python interpreter to the builddir's library and Babeltrace
>  # bindings
> -bt_module_path = '@abs_top_builddir@/bindings/python/babeltrace'
> -bt_lib_py_path = '@abs_top_builddir@/bindings/python/babeltrace/.libs'
> -bt_lib_bt_path = '@abs_top_builddir@/lib/.libs'
> -bt_lib_ctf_path = '@abs_top_builddir@/format/ctf/.libs'
> +bt_module_path = '@abs_top_builddir@/bindings/python/build/build_lib/'
>
>  sys.path.insert(0, bt_module_path)
> -sys.path.insert(1, bt_lib_py_path)
> -sys.path.insert(2, bt_lib_bt_path)
> -sys.path.insert(3, bt_lib_ctf_path)
> +
> +# Manually load the shared libraries used by the Babeltrace module during the
> +# tests
> +bt_lib_ctf_path = '@abs_top_builddir@/formats/ctf/.libs/libbabeltrace-ctf.so'
> +bt_lib_bt_path = '@abs_top_builddir@/lib/.libs/libbabeltrace.so'
> +
> +ctypes.cdll.LoadLibrary(bt_lib_ctf_path)
> +ctypes.cdll.LoadLibrary(bt_lib_bt_path)
> --
> 2.7.4
>



-- 
Jérémie Galarneau
EfficiOS Inc.
http://www.efficios.com


More information about the lttng-dev mailing list