diff mbox

[babeltrace,v5] Build Python bindings with distutils for consistent installs

Message ID 1491938857-3525-1-git-send-email-francis.deslauriers@efficios.com
State Accepted, archived
Delegated to: Jérémie Galarneau
Headers show

Commit Message

Francis Deslauriers April 11, 2017, 7:27 p.m. UTC
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

Comments

Jérémie Galarneau May 26, 2017, 1:36 p.m. UTC | #1
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
>
diff mbox

Patch

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)