[lttng-dev] [PATCH babeltrace v4] Build Python bindings with distutils for consistent installs
Jérémie Galarneau
jeremie.galarneau at efficios.com
Mon Apr 10 20:26:52 UTC 2017
The tests implemented in python don't seem to work with this patch
applied. See if you can reproduce it yourself:
./configure --enable-python-bindings
make check
Thanks,
Jérémie
On 6 March 2017 at 12:19, Francis Deslauriers
<francis.deslauriers at efficios.com> wrote:
> v4: Fix DESTDIR behaviour on (un)install targets.
>
> 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 | 58 +++++++++++++++++-
> 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 | 8 +--
> 8 files changed, 187 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..0009546 100644
> --- a/bindings/python/Makefile.am
> +++ b/bindings/python/Makefile.am
> @@ -1,3 +1,59 @@
> 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 -Wl,-rpath,$(prefix)/lib
> +
> +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..cb53304 100644
> --- a/tests/bin/intersection/bt_python_helper.py.in
> +++ b/tests/bin/intersection/bt_python_helper.py.in
> @@ -26,12 +26,6 @@ import sys
>
> # 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'
>
> 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)
> --
> 2.7.4
>
--
Jérémie Galarneau
EfficiOS Inc.
http://www.efficios.com
More information about the lttng-dev
mailing list