doc/api/libbabeltrace2/DoxygenLayout.xml: use `topics` tab
[babeltrace.git] / src / bindings / python / bt2 / setup.py.in
index 0a94d1f3bb9424efb8fb6cbb13cabf35db341134..3c81447ea80a2d8dd928f43aba69feea2bf7f980 100644 (file)
@@ -1,28 +1,43 @@
-# The MIT License (MIT)
+# SPDX-License-Identifier: MIT
 #
-# Copyright (C) 2017 - Francis Deslauriers <francis.deslauriers@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.
+# Copyright (C) 2017 Francis Deslauriers <francis.deslauriers@efficios.com>
+# Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
 
 import sys
+import os
+import shutil
+import subprocess
+
+# Distutils was removed in Python 3.12, use setuptools as an alternative.
+if sys.version_info >= (3, 12):
+    from setuptools import setup, Extension
+else:
+    from distutils.core import setup, Extension
+
+# Starting with Debian's Python 3.10, the default install scheme is
+# 'posix_local' which is a Debian specific scheme based on 'posix_prefix' but
+# with an added 'local' prefix. This is the default so users doing system wide
+# manual installations of python modules end up in '/usr/local'. This
+# interferes with our autotools based install which already defaults to
+# '/usr/local' and expect a provided prefix to be used verbatim.
+#
+# Monkeypatch sysconfig to override this scheme and use 'posix_prefix' instead.
+if sys.version_info >= (3, 10):
+    import sysconfig
+
+    original_get_preferred_scheme = sysconfig.get_preferred_scheme
+
+    def our_get_preferred_scheme(key):
+        scheme = original_get_preferred_scheme(key)
+        if scheme == "posix_local":
+            return "posix_prefix"
+        else:
+            return scheme
+
+    sysconfig.get_preferred_scheme = our_get_preferred_scheme
 
-from distutils.core import setup, Extension
+else:
+    import distutils.sysconfig as sysconfig
 
 PY_PATH_WARN_MSG = """
 -------------------------------------WARNING------------------------------------
@@ -34,38 +49,139 @@ following command to your .bashrc/.zshrc:
 --------------------------------------------------------------------------------
 """
 
+original_get_config_vars = sysconfig.get_config_vars
+
+
+def get_cflags():
+    cflags = os.environ.get("CFLAGS")
+
+    if cflags is None:
+        [cflags] = original_get_config_vars("CFLAGS")
+
+    return cflags
+
+
+# distutils performs a similar transformation step on LDSHARED on
+# darwin to use the overridden CC as the default command for LDSHARED
+# (see distutils' customize_compiler() step in the sysconfig module).
+#
+# This takes it a step further by using our own LDFLAGS (when available)
+# along with the overridden compiler and ensure that flags that are unsupported
+# by either the Python interprter's CC or the overridden CC don't cause a
+# build failure.
+def get_ldshared():
+    cc = os.environ.get("CC")
+    ldflags = os.environ.get("LDFLAGS")
+    [py_cc] = original_get_config_vars("CC")
+    [py_ldshared] = original_get_config_vars("LDSHARED")
+
+    if not py_ldshared.startswith(py_cc):
+        return py_ldshared
+
+    if cc and ldflags:
+        return "{} -shared {}".format(cc, ldflags)
+    elif cc:
+        return cc + py_ldshared[len(py_cc) :]
+    elif ldflags:
+        return py_cc + py_ldshared[len(py_cc) :]
+    else:
+        return py_ldshared
+
+
+def our_get_config_vars(*args):
+    overridden_config_vars_funcs = {
+        "CFLAGS": get_cflags,
+        "LDSHARED": get_ldshared,
+    }
+
+    if len(args) == 0:
+        # Return a dict with all config vars.
+        all_config_vars = original_get_config_vars()
+        for name in overridden_config_vars_funcs:
+            all_config_vars[name] = overridden_config_vars_funcs[name]()
+
+        return all_config_vars
+    else:
+        # Return a list with the requested config vars.
+        subset_config_vars = []
+        for name in args:
+            if name in overridden_config_vars_funcs:
+                subset_config_vars.append(overridden_config_vars_funcs[name]())
+            else:
+                subset_config_vars.append(original_get_config_vars(name)[0])
+
+        return subset_config_vars
+
+
+sysconfig.get_config_vars = our_get_config_vars
+
+
+# Returns 'True' when running on a MinGW system.
+def is_mingw():
+    return sys.platform == "win32" and shutil.which("cygpath") != None
+
+
+# On MinGW systems run 'cygpath -m' on 'path', on other systems return 'path' as-is.
+def cygpath_m(path: str):
+    if is_mingw():
+        return subprocess.check_output(
+            'cygpath -m "{}"'.format(path), shell=True, encoding="utf-8"
+        ).strip("\n")
+
+    return path
+
+
+# On MinGW systems, check CFLAGS and CPPFLAGS for absolute include paths
+# (starts with '-I/') and convert them to valid Windows paths using cygpath.
+if is_mingw():
+    for flagvar in ["CFLAGS", "CPPFLAGS"]:
+        cur_flags = os.getenv(flagvar)
+        if cur_flags != None:
+            new_flags = ""
+            for flag in cur_flags.split():
+                if flag.startswith("-I/"):
+                    flag = "-I{}".format(cygpath_m(flag[2:]))
+
+                new_flags += " {}".format(flag)
+
+            os.environ[flagvar] = new_flags
+
 
 def main():
     babeltrace_ext = Extension(
-        'bt2._native_bt',
-        sources=['bt2/native_bt.c', '@srcdir@/bt2/logging.c'],
-        libraries=['babeltrace2', 'glib-2.0'],
+        "bt2._native_bt",
+        sources=[
+            "bt2/native_bt.c",
+            cygpath_m("@srcdir@/bt2/logging.c"),
+        ],
+        libraries=["babeltrace2", "glib-2.0"],
         extra_objects=[
-            '@top_builddir@/src/autodisc/.libs/libbabeltrace2-autodisc.a',
-            '@top_builddir@/src/logging/.libs/libbabeltrace2-logging.a',
-            '@top_builddir@/src/common/.libs/libbabeltrace2-common.a',
-            '@top_builddir@/src/py-common/.libs/libbabeltrace2-py-common.a',
+            "@top_builddir@/src/autodisc/.libs/libautodisc.a",
+            "@top_builddir@/src/logging/.libs/liblogging.a",
+            "@top_builddir@/src/common/.libs/libcommon.a",
+            "@top_builddir@/src/py-common/.libs/libpy-common.a",
+            "@top_builddir@/src/string-format/.libs/libstring-format.a",
         ],
     )
 
     dist = setup(
-        name='bt2',
-        version='@PACKAGE_VERSION@',
-        description='Babeltrace 2 Python Bindings',
-        packages=['bt2'],
-        package_dir={'bt2': 'bt2'},
+        name="bt2",
+        version="@PACKAGE_VERSION@",
+        description="Babeltrace 2 Python Bindings",
+        packages=["bt2"],
+        package_dir={"bt2": "bt2"},
         options={
-            'build': {'build_base': 'build', 'build_lib': 'build/build_lib'},
-            'build_ext': {'build_lib': 'build/build_lib'},
+            "build": {"build_base": "build", "build_lib": "build/build_lib"},
+            "build_ext": {"build_lib": "build/build_lib"},
         },
-        url='http://diamon.org/babeltrace',
+        url="https://babeltrace.org/",
         ext_modules=[babeltrace_ext],
-        license='MIT',
+        license="MIT",
         classifiers=[
-            'Development Status :: 5 - Production/Stable',
-            'Intended Audience :: Developers',
-            'License :: OSI Approved :: The MIT License',
-            'Programming Language :: Python :: 3' 'Topic :: System :: Logging',
+            "Development Status :: 5 - Production/Stable",
+            "Intended Audience :: Developers",
+            "License :: OSI Approved :: The MIT License",
+            "Programming Language :: Python :: 3" "Topic :: System :: Logging",
         ],
     )
 
@@ -76,8 +192,8 @@ def main():
     # 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" 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
This page took 0.025264 seconds and 4 git commands to generate.