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.deslauri...@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.deslauri...@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.deslauri...@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.galarn...@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 _______________________________________________ lttng-dev mailing list lttng-dev@lists.lttng.org https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev