PEP 738: Android support, draft 2 (GH-3651)
This commit is contained in:
parent
53c3d1a703
commit
fda02b5757
|
@ -52,7 +52,8 @@ Android is broadly a POSIX platform, based on a Linux kernel and the
|
||||||
ELF binary format. It does not use glibc, instead providing its own C
|
ELF binary format. It does not use glibc, instead providing its own C
|
||||||
library implementation called Bionic. As a result, it is generally not
|
library implementation called Bionic. As a result, it is generally not
|
||||||
binary-compatible with any other Linux distribution, even if the architecture
|
binary-compatible with any other Linux distribution, even if the architecture
|
||||||
matches.
|
matches. It also has its own filesystem layout which doesn't resemble any other
|
||||||
|
Unix.
|
||||||
|
|
||||||
However, Android's source-compatibility with Linux is quite good. In its early years,
|
However, Android's source-compatibility with Linux is quite good. In its early years,
|
||||||
the C library was very incomplete, but most of the gaps were filled by around
|
the C library was very incomplete, but most of the gaps were filled by around
|
||||||
|
@ -64,6 +65,7 @@ This is also true of CPython. Although it has never officially supported
|
||||||
Android, recent versions (since 3.6) can already be compiled for Android with
|
Android, recent versions (since 3.6) can already be compiled for Android with
|
||||||
minimal patching.
|
minimal patching.
|
||||||
|
|
||||||
|
.. _738-os-versions:
|
||||||
|
|
||||||
OS versions
|
OS versions
|
||||||
-----------
|
-----------
|
||||||
|
@ -89,11 +91,9 @@ version still receiving security updates was API level 30, but according to
|
||||||
<https://dl.google.com/android/studio/metadata/distributions.json>`__, only 60%
|
<https://dl.google.com/android/studio/metadata/distributions.json>`__, only 60%
|
||||||
of devices were on that version or newer.
|
of devices were on that version or newer.
|
||||||
|
|
||||||
For Python 3.13 we therefore propose the minimum Android version to be 6.0
|
For Python 3.13 we therefore propose the minimum Android version to be 5.0
|
||||||
(API level 23). This would support 98% of active devices, and would
|
(API level 21), which was released in 2014. According to the statistics above,
|
||||||
allow us to rely on a number of `dynamic linker improvements
|
this would cover 99% of active devices.
|
||||||
<https://android.googlesource.com/platform/bionic/+/refs/heads/master/android-changes-for-ndk-developers.md>`__
|
|
||||||
which simplify the use of dynamic libraries.
|
|
||||||
|
|
||||||
|
|
||||||
Development tools
|
Development tools
|
||||||
|
@ -107,14 +107,15 @@ are:
|
||||||
linker (lld), and headers for all the system libraries.
|
linker (lld), and headers for all the system libraries.
|
||||||
|
|
||||||
Binary compatibility between libraries compiled with different versions of the
|
Binary compatibility between libraries compiled with different versions of the
|
||||||
NDK is generally very good, but for reproducbility it would be best for each
|
NDK is generally very good, but for reproducibility it would be best for each
|
||||||
Python version to stick with one NDK version throughout its life. For Python
|
Python version to stick with one NDK version throughout its life. For Python
|
||||||
3.13, this would be the current NDK long-term support version, r26.
|
3.13, this would be the current NDK long-term support version, r26.
|
||||||
|
|
||||||
Each NDK version can be set to target any of a wide range of Android versions.
|
Each NDK version can be set to target any of a wide range of Android versions.
|
||||||
For example, NDK r26 supports API levels 21 to 34. However, binaries compiled
|
For example, NDK r26 supports :ref:`API levels <738-os-versions>` 21 to 34.
|
||||||
for an older Android version will usually keep on working indefinitely on
|
However, binaries compiled for an older Android version will usually keep on
|
||||||
newer versions; exceptions to this rule are only made for security reasons.
|
working indefinitely on newer versions; exceptions to this rule are only made
|
||||||
|
for security reasons.
|
||||||
|
|
||||||
* Gradle is the tool used to build complete, deployable apps.
|
* Gradle is the tool used to build complete, deployable apps.
|
||||||
|
|
||||||
|
@ -150,7 +151,7 @@ For Python 3.13 we propose that Tier 3 support will only cover the 64-bit platfo
|
||||||
`less than 10% and steadily falling
|
`less than 10% and steadily falling
|
||||||
<https://github.com/chaquo/chaquopy/issues/709#issuecomment-1744541892>`__.
|
<https://github.com/chaquo/chaquopy/issues/709#issuecomment-1744541892>`__.
|
||||||
|
|
||||||
It would also be more difficult to cover with an automated test, since there
|
It would also be more difficult to cover with a reliable buildbot, since there
|
||||||
are no native hosts available for the emulator (ARM64 Macs don't have hardware
|
are no native hosts available for the emulator (ARM64 Macs don't have hardware
|
||||||
support for ARM32 code). Although cross-architecture emulation is possible, it
|
support for ARM32 code). Although cross-architecture emulation is possible, it
|
||||||
has much worse performance and stability, which is why the ``armeabi-v7a``
|
has much worse performance and stability, which is why the ``armeabi-v7a``
|
||||||
|
@ -182,10 +183,9 @@ guaranteed to be supported in future Android versions.
|
||||||
Android does provide a command-line shell, but this is intended only for use by
|
Android does provide a command-line shell, but this is intended only for use by
|
||||||
developers, and is not available to the typical end user.
|
developers, and is not available to the typical end user.
|
||||||
|
|
||||||
For these reasons, the primary way of running Python on Android will be by
|
For these reasons, the recommended way of running Python on Android will be by
|
||||||
loading ``libpython3.x.so`` into the main app process. Although there will also
|
loading ``libpython3.x.so`` into the main app process. A ``python3.x``
|
||||||
be a ``python3.x`` executable linked against ``libpython3.x.so``, this is only
|
executable will not be officially supported on this platform.
|
||||||
for debugging, not production use.
|
|
||||||
|
|
||||||
|
|
||||||
Specification
|
Specification
|
||||||
|
@ -215,16 +215,23 @@ Linkage
|
||||||
-------
|
-------
|
||||||
|
|
||||||
For the reasons discussed in `App lifecycle`_, Python will be included in the
|
For the reasons discussed in `App lifecycle`_, Python will be included in the
|
||||||
app as a dynamic ``libpython3.x.so`` library. All Android extension modules should
|
app as a dynamic ``libpython3.x.so`` library which can be loaded into an app
|
||||||
be linked against this library. This allows using the
|
using ``dlopen``.
|
||||||
``-Wl,--no-undefined`` option to detect missing symbols at build time, which can
|
|
||||||
be a significant time-saver.
|
Unlike Linux, Android does not implicitly use a dlopened library to resolve
|
||||||
|
relocations in subsequently-loaded libraries, `even if RTLD_GLOBAL is used
|
||||||
|
<https://github.com/android/ndk/issues/1244#issuecomment-620310397>`__. All
|
||||||
|
Python extension modules must therefore be explicitly linked against
|
||||||
|
``libpython3.x.so`` when building for Android.
|
||||||
|
|
||||||
An extension module linked against ``libpython3.x.so`` cannot be loaded by an
|
An extension module linked against ``libpython3.x.so`` cannot be loaded by an
|
||||||
executable that has been statically linked against ``libpython3.x.a``.
|
executable that has been statically linked against ``libpython3.x.a``.
|
||||||
Therefore, a static ``libpython3.x.a`` library will not be supported on Android.
|
Therefore, a static ``libpython3.x.a`` library will not be supported on Android.
|
||||||
This is the same pattern used by CPython on Windows.
|
This is the same pattern used by CPython on Windows.
|
||||||
|
|
||||||
|
This approach also allows using the ``-Wl,--no-undefined`` option to detect
|
||||||
|
missing symbols at build time, which can be a significant time-saver.
|
||||||
|
|
||||||
Unlike iOS, Android allows dynamic libraries to be loaded from any location, so
|
Unlike iOS, Android allows dynamic libraries to be loaded from any location, so
|
||||||
a directory tree containing co-located .py, .pyc and .so files can be handled by
|
a directory tree containing co-located .py, .pyc and .so files can be handled by
|
||||||
Python's standard importer.
|
Python's standard importer.
|
||||||
|
@ -233,28 +240,33 @@ Python's standard importer.
|
||||||
Standard library
|
Standard library
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
Unsupported modules
|
||||||
|
'''''''''''''''''''
|
||||||
|
|
||||||
A number of standard library modules will not be supported on Android because
|
A number of standard library modules will not be supported on Android because
|
||||||
the underlying C APIs are not available:
|
the underlying C APIs are not available:
|
||||||
|
|
||||||
* ``curses`` and ``readline``
|
* ``curses`` and ``readline``
|
||||||
* ``dbm.gnu`` and ``dbm.ndbm``
|
* ``dbm.gnu`` and ``dbm.ndbm``
|
||||||
* ``grp`` and ``spwd``
|
* ``grp``
|
||||||
* ``multiprocessing`` – although subprocesses in general are allowed (see `App
|
* ``multiprocessing`` – although subprocesses in general are allowed (see `App
|
||||||
lifecycle`_), Android does not support any part of the `System V IPC API
|
lifecycle`_), Android does not support any part of the `System V IPC API
|
||||||
<https://man7.org/linux/man-pages/man7/sysvipc.7.html>`__.
|
<https://man7.org/linux/man-pages/man7/sysvipc.7.html>`__.
|
||||||
* ``tkinter`` and ``turtle`` – these would require an Android build of Tk
|
* ``tkinter`` and ``turtle`` – these would require an Android build of Tk
|
||||||
itself, which is not officially supported.
|
itself, which is not officially supported.
|
||||||
|
|
||||||
|
|
||||||
Platform identification
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
``sys``
|
``sys``
|
||||||
'''''''
|
'''''''
|
||||||
|
|
||||||
``sys.platform`` will return ``"android"``. Although Android is based on Linux,
|
``sys.platform`` will return ``"android"``. Although Android is based on Linux,
|
||||||
it differs in enough significant ways that a separate name is justified.
|
it differs in enough significant ways that a separate name is justified.
|
||||||
|
|
||||||
|
When embedded in an Android app, the C-level stdio streams are not connected to
|
||||||
|
anything. So in this mode, ``sys.stdout`` and ``sys.stderr`` will be redirected
|
||||||
|
to the system `Logcat <https://developer.android.com/studio/debug/logcat>`__,
|
||||||
|
which can be viewed with the Android development tools. ``sys.stdin`` will
|
||||||
|
always return EOF.
|
||||||
|
|
||||||
``platform``
|
``platform``
|
||||||
''''''''''''
|
''''''''''''
|
||||||
|
|
||||||
|
@ -269,11 +281,24 @@ by ``os.uname()``, with the exception of:
|
||||||
In addition, a ``platform.android_ver()`` method will be added, which returns a
|
In addition, a ``platform.android_ver()`` method will be added, which returns a
|
||||||
namedtuple containing the following:
|
namedtuple containing the following:
|
||||||
|
|
||||||
* ``release`` - Android version, as a string (e.g. ``"14"``)
|
* ``release`` - Android version of the device, as a string (e.g. ``"14"``)
|
||||||
* ``api_level`` - Android API level, as an integer (e.g. ``34``)
|
* ``api_level`` - :ref:`API level <738-os-versions>` of the device, as an
|
||||||
|
integer (e.g. ``34``)
|
||||||
* ``min_api_level`` - Minimum API level this build of Python can run on, as
|
* ``min_api_level`` - Minimum API level this build of Python can run on, as
|
||||||
an integer (e.g. ``23``). This is the same as ``sys.getandroidapilevel``.
|
an integer (e.g. ``23``). This is the same as ``sys.getandroidapilevel``.
|
||||||
* ``model`` - the model name of the device, as a string (e.g. ``"Pixel 7"``).
|
* ``manufacturer`` - `manufacturer
|
||||||
|
<https://developer.android.com/reference/android/os/Build#MANUFACTURER>`__ of
|
||||||
|
the device, as a string (e.g. ``"Google"``)
|
||||||
|
* ``model`` - `model name
|
||||||
|
<https://developer.android.com/reference/android/os/Build#MODEL>`__ of the
|
||||||
|
device, as a string (e.g. ``"Pixel 7"``)
|
||||||
|
* ``device`` - `device name
|
||||||
|
<https://developer.android.com/reference/android/os/Build#DEVICE>`__ of the
|
||||||
|
device, as a string (e.g. ``"panther"``)
|
||||||
|
|
||||||
|
Which one of ``model`` and ``device`` is more likely to be unique, and which one
|
||||||
|
is more likely to resemble the marketing name, varies between different
|
||||||
|
manufacturers.
|
||||||
|
|
||||||
``os``
|
``os``
|
||||||
''''''
|
''''''
|
||||||
|
@ -313,8 +338,8 @@ Packaging
|
||||||
Android wheels will use tags in the format ``android_<api-level>_<abi>``. For
|
Android wheels will use tags in the format ``android_<api-level>_<abi>``. For
|
||||||
example:
|
example:
|
||||||
|
|
||||||
* ``android_23_arm64_v8a``
|
* ``android_21_arm64_v8a``
|
||||||
* ``android_23_x86_64``
|
* ``android_21_x86_64``
|
||||||
|
|
||||||
For the meaning of ``<api-level>``, see `OS versions`_. In the context of
|
For the meaning of ``<api-level>``, see `OS versions`_. In the context of
|
||||||
the wheel tag, it indicates the minimum Android version that was selected when
|
the wheel tag, it indicates the minimum Android version that was selected when
|
||||||
|
|
Loading…
Reference in New Issue