From 254b309c801f82509597e3d7d4be56885ef94c11 Mon Sep 17 00:00:00 2001 From: xdegaye Date: Mon, 29 Apr 2019 09:27:40 +0200 Subject: [PATCH] bpo-21536: On Android, C extensions are linked to libpython (GH-12989) --- Doc/distutils/apiref.rst | 3 ++- Doc/whatsnew/3.8.rst | 12 ++++++------ Lib/distutils/command/build_ext.py | 15 +++++++++++++++ Makefile.pre.in | 1 + .../2019-04-25-01-51-52.bpo-21536.ACQkiC.rst | 2 +- Misc/python-config.in | 5 ++++- Misc/python-config.sh.in | 2 +- configure | 9 +++++++++ configure.ac | 8 ++++++++ 9 files changed, 47 insertions(+), 10 deletions(-) diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index c3cdfc8a0a8..1facc0408d5 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -279,7 +279,8 @@ the full reference. .. versionchanged:: 3.8 - On Unix, C extensions are no longer linked to libpython. + On Unix, C extensions are no longer linked to libpython except on + Android. .. class:: Distribution diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 8d94a9ff544..8df7538f1c4 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -883,12 +883,12 @@ Changes in the Python API Changes in the C API -------------------- -* On Unix, C extensions are no longer linked to libpython. 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``. +* On Unix, C extensions are no longer linked to libpython except on + Android. 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``. * 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 1672d02acf1..c3b9602461f 100644 --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py @@ -714,5 +714,20 @@ 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: + from distutils.sysconfig import get_config_var + 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] return ext.libraries diff --git a/Makefile.pre.in b/Makefile.pre.in index 89479ee7f1a..7f0d8d44b3d 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -41,6 +41,7 @@ AR= @AR@ READELF= @READELF@ SOABI= @SOABI@ LDVERSION= @LDVERSION@ +LIBPYTHON= @LIBPYTHON@ GITVERSION= @GITVERSION@ GITTAG= @GITTAG@ GITBRANCH= @GITBRANCH@ diff --git a/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst b/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst index 8cfad76ab17..59efab83265 100644 --- a/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst +++ b/Misc/NEWS.d/next/Build/2019-04-25-01-51-52.bpo-21536.ACQkiC.rst @@ -1,4 +1,4 @@ -On Unix, C extensions are no longer linked to libpython. +On Unix, C extensions are no longer linked to libpython except on Android. It is now possible for a statically linked Python to load a C extension built using a shared library Python. diff --git a/Misc/python-config.in b/Misc/python-config.in index 31ad55822e5..1df30d261d8 100644 --- a/Misc/python-config.in +++ b/Misc/python-config.in @@ -47,7 +47,10 @@ for opt in opt_flags: print(' '.join(flags)) elif opt in ('--libs', '--ldflags'): - libs = getvar('LIBS').split() + getvar('SYSLIBS').split() + libpython = getvar('LIBPYTHON') + libs = [libpython] if libpython else [] + libs.extend(getvar('LIBS').split() + getvar('SYSLIBS').split()) + # add the prefix/lib/pythonX.Y/config dir, but only if there is no # shared library in prefix/lib/. if opt == '--ldflags': diff --git a/Misc/python-config.sh.in b/Misc/python-config.sh.in index ac1a467678e..33991ef0c5d 100644 --- a/Misc/python-config.sh.in +++ b/Misc/python-config.sh.in @@ -41,7 +41,7 @@ LIBM="@LIBM@" LIBC="@LIBC@" SYSLIBS="$LIBM $LIBC" ABIFLAGS="@ABIFLAGS@" -LIBS="@LIBS@ $SYSLIBS" +LIBS="@LIBPYTHON@ @LIBS@ $SYSLIBS" BASECFLAGS="@BASECFLAGS@" LDLIBRARY="@LDLIBRARY@" OPT="@OPT@" diff --git a/configure b/configure index 7f26fab81fe..8d9c73d1c38 100755 --- a/configure +++ b/configure @@ -631,6 +631,7 @@ SRCDIRS THREADHEADERS LIBPL PY_ENABLE_SHARED +LIBPYTHON EXT_SUFFIX ALT_SOABI SOABI @@ -15154,6 +15155,14 @@ 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. + +if test -z "$ANDROID_API_LEVEL"; then + LIBPYTHON='' +else + LIBPYTHON="-lpython${VERSION}${ABIFLAGS}" +fi + if test x$PLATFORM_TRIPLET = x; then LIBPL='$(prefix)'"/lib/python${VERSION}/config-${LDVERSION}" diff --git a/configure.ac b/configure.ac index 157e9bf4067..7d2eff0d94c 100644 --- a/configure.ac +++ b/configure.ac @@ -4648,6 +4648,14 @@ AC_MSG_CHECKING(LDVERSION) LDVERSION='$(VERSION)$(ABIFLAGS)' AC_MSG_RESULT($LDVERSION) +# On Android the shared libraries must be linked with libpython. +AC_SUBST(LIBPYTHON) +if test -z "$ANDROID_API_LEVEL"; then + LIBPYTHON='' +else + LIBPYTHON="-lpython${VERSION}${ABIFLAGS}" +fi + dnl define LIBPL after ABIFLAGS and LDVERSION is defined. AC_SUBST(PY_ENABLE_SHARED) if test x$PLATFORM_TRIPLET = x; then