From c994c8fc196a167c57c8850e8abdee170d366eec Mon Sep 17 00:00:00 2001 From: "E. M. Bray" Date: Fri, 24 May 2019 17:33:47 +0200 Subject: [PATCH] bpo-21536: On Cygwin, C extensions must be linked with libpython (GH-13549) It is also possible to link against a library or executable with a statically linked libpython, but not both with the same DLL. In fact building a statically linked python is currently broken on Cygwin for other (related) reasons. The same problem applies to other POSIX-like layers over Windows (MinGW, MSYS) but Python's build system does not seem to attempt to support those platforms at the moment. --- Doc/distutils/apiref.rst | 2 +- Doc/whatsnew/3.8.rst | 17 +++++++------- Lib/distutils/command/build_ext.py | 36 ++++++++++++++++++++---------- Misc/NEWS.d/3.8.0a4.rst | 3 ++- configure | 4 ++-- configure.ac | 4 ++-- 6 files changed, 40 insertions(+), 26 deletions(-) diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index cbeedab5bb1..2601d30f63e 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -290,7 +290,7 @@ the full reference. .. versionchanged:: 3.8 On Unix, C extensions are no longer linked to libpython except on - Android. + Android and Cygwin. .. class:: Distribution diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index b91f7bca63c..b5d70b5a2ec 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -138,7 +138,8 @@ environment variable, can be set using the new ``./configure --with-trace-refs`` build option. (Contributed by Victor Stinner in :issue:`36465`.) -On Unix, C extensions are no longer linked to libpython except on Android. +On Unix, C extensions are no longer linked to libpython except on Android +and Cygwin. It is now possible for a statically linked Python to load a C extension built using a shared library Python. @@ -163,8 +164,8 @@ previous command fails (replace ``X.Y`` with the Python version). On the other hand, ``pkg-config python3.8 --libs`` no longer contains ``-lpython3.8``. C extensions must not be linked to libpython (except on -Android, case handled by the script); this change is backward incompatible on -purpose. +Android and Cygwin, whose cases are handled by the script); +this change is backward incompatible on purpose. (Contributed by Victor Stinner in :issue:`36721`.) f-strings now support = for quick and easy debugging @@ -1061,12 +1062,12 @@ Changes in the C API instead. (Contributed by Victor Stinner in :issue:`36728`.) -* On Unix, C extensions are no longer linked to libpython except on - Android. When Python is embedded, ``libpython`` must not be loaded with +* On Unix, C extensions are no longer linked to libpython except on Android + and Cygwin. When Python is embedded, ``libpython`` must not be loaded with ``RTLD_LOCAL``, but ``RTLD_GLOBAL`` instead. Previously, using - ``RTLD_LOCAL``, it was already not possible to load C extensions which were - not linked to ``libpython``, like C extensions of the standard library built - by the ``*shared*`` section of ``Modules/Setup``. + ``RTLD_LOCAL``, it was already not possible to load C extensions which + were not linked to ``libpython``, like C extensions of the standard + library built by the ``*shared*`` section of ``Modules/Setup``. * Use of ``#`` variants of formats in parsing or building value (e.g. :c:func:`PyArg_ParseTuple`, :c:func:`Py_BuildValue`, :c:func:`PyObject_CallFunction`, diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ext.py index c3b9602461f..2d7cdf063f0 100644 --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py @@ -714,20 +714,32 @@ class build_ext(Command): # don't extend ext.libraries, it may be shared with other # extensions, it is a reference to the original list return ext.libraries + [pythonlib] - # On Android only the main executable and LD_PRELOADs are considered - # to be RTLD_GLOBAL, all the dependencies of the main executable - # remain RTLD_LOCAL and so the shared libraries must be linked with - # libpython when python is built with a shared python library (issue - # bpo-21536). else: + # On Android only the main executable and LD_PRELOADs are considered + # to be RTLD_GLOBAL, all the dependencies of the main executable + # remain RTLD_LOCAL and so the shared libraries must be linked with + # libpython when python is built with a shared python library (issue + # bpo-21536). + # On Cygwin (and if required, other POSIX-like platforms based on + # Windows like MinGW) it is simply necessary that all symbols in + # shared libraries are resolved at link time. from distutils.sysconfig import get_config_var + link_libpython = False if get_config_var('Py_ENABLE_SHARED'): - # Either a native build on an Android device or the - # cross-compilation of Python. - if (hasattr(sys, 'getandroidapilevel') or - ('_PYTHON_HOST_PLATFORM' in os.environ and - get_config_var('ANDROID_API_LEVEL') != 0)): - ldversion = get_config_var('LDVERSION') - return ext.libraries + ['python' + ldversion] + # A native build on an Android device or on Cygwin + if hasattr(sys, 'getandroidapilevel'): + link_libpython = True + elif sys.platform == 'cygwin': + link_libpython = True + elif '_PYTHON_HOST_PLATFORM' in os.environ: + # We are cross-compiling for one of the relevant platforms + if get_config_var('ANDROID_API_LEVEL') != 0: + link_libpython = True + elif get_config_var('MACHDEP') == 'cygwin': + link_libpython = True + + if link_libpython: + ldversion = get_config_var('LDVERSION') + return ext.libraries + ['python' + ldversion] return ext.libraries diff --git a/Misc/NEWS.d/3.8.0a4.rst b/Misc/NEWS.d/3.8.0a4.rst index b92e60a9269..80e01d97a04 100644 --- a/Misc/NEWS.d/3.8.0a4.rst +++ b/Misc/NEWS.d/3.8.0a4.rst @@ -1052,7 +1052,8 @@ Remove the stale scriptsinstall Makefile target. .. nonce: ACQkiC .. section: Build -On Unix, C extensions are no longer linked to libpython except on Android. +On Unix, C extensions are no longer linked to libpython except on Android +and Cygwin. It is now possible for a statically linked Python to load a C extension built using a shared library Python. diff --git a/configure b/configure index 9f2007fed32..c76eb7affe5 100755 --- a/configure +++ b/configure @@ -15129,9 +15129,9 @@ LDVERSION='$(VERSION)$(ABIFLAGS)' { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LDVERSION" >&5 $as_echo "$LDVERSION" >&6; } -# On Android the shared libraries must be linked with libpython. +# On Android and Cygwin the shared libraries must be linked with libpython. -if test -z "$ANDROID_API_LEVEL"; then +if test -z "$ANDROID_API_LEVEL" -o "$MACHDEP" != "cygwin"; then LIBPYTHON='' else LIBPYTHON="-lpython${VERSION}${ABIFLAGS}" diff --git a/configure.ac b/configure.ac index 0baf0d6660a..99d99ae55c1 100644 --- a/configure.ac +++ b/configure.ac @@ -4620,9 +4620,9 @@ AC_MSG_CHECKING(LDVERSION) LDVERSION='$(VERSION)$(ABIFLAGS)' AC_MSG_RESULT($LDVERSION) -# On Android the shared libraries must be linked with libpython. +# On Android and Cygwin the shared libraries must be linked with libpython. AC_SUBST(LIBPYTHON) -if test -z "$ANDROID_API_LEVEL"; then +if test -z "$ANDROID_API_LEVEL" -o "$MACHDEP" != "cygwin"; then LIBPYTHON='' else LIBPYTHON="-lpython${VERSION}${ABIFLAGS}"