import sys
import os
-import distutils.sysconfig
+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------------------------------------
--------------------------------------------------------------------------------
"""
-original_get_config_vars = distutils.sysconfig.get_config_vars
+original_get_config_vars = sysconfig.get_config_vars
def get_cflags():
- cflags = os.environ.get('CFLAGS')
+ cflags = os.environ.get("CFLAGS")
if cflags is None:
- [cflags] = original_get_config_vars('CFLAGS')
+ [cflags] = original_get_config_vars("CFLAGS")
return cflags
# distutils performs a similar transformation step on LDSHARED on
-# darwin to use the overriden CC as the default command for LDSHARED
+# 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 overriden compiler and ensure that flags that are unsupported
-# by either the Python interprter's CC or the overriden CC don't cause a
+# 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')
+ 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)
+ return "{} -shared {}".format(cc, ldflags)
elif cc:
return cc + py_ldshared[len(py_cc) :]
elif ldflags:
def our_get_config_vars(*args):
- overridden_config_vars = {
- 'CFLAGS': get_cflags(),
- 'LDSHARED': get_ldshared(),
+ 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:
- all_config_vars[name] = overridden_config_vars[name]
+ 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
- subset_config_vars = []
- for name in args:
- if name not in overridden_config_vars:
- [var] = original_get_config_vars(name)
- subset_config_vars.append(var)
- continue
- subset_config_vars.append(overridden_config_vars[name])
+sysconfig.get_config_vars = our_get_config_vars
- return subset_config_vars
+# Returns 'True' when running on a MinGW system.
+def is_mingw():
+ return sys.platform == "win32" and shutil.which("cygpath") != None
-distutils.sysconfig.get_config_vars = our_get_config_vars
+
+# 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/string-format/.libs/libbabeltrace2-string-format.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='https://babeltrace.org/',
+ 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",
],
)
# 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