diff --git a/peps/pep-0738.rst b/peps/pep-0738.rst index 03e452111..0c7040171 100644 --- a/peps/pep-0738.rst +++ b/peps/pep-0738.rst @@ -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 library implementation called Bionic. As a result, it is generally not 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, 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 minimal patching. +.. _738-os-versions: OS versions ----------- @@ -89,11 +91,9 @@ version still receiving security updates was API level 30, but according to `__, only 60% of devices were on that version or newer. -For Python 3.13 we therefore propose the minimum Android version to be 6.0 -(API level 23). This would support 98% of active devices, and would -allow us to rely on a number of `dynamic linker improvements -`__ -which simplify the use of dynamic libraries. +For Python 3.13 we therefore propose the minimum Android version to be 5.0 +(API level 21), which was released in 2014. According to the statistics above, +this would cover 99% of active devices. Development tools @@ -107,14 +107,15 @@ are: linker (lld), and headers for all the system libraries. 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 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. - For example, NDK r26 supports API levels 21 to 34. However, binaries compiled - for an older Android version will usually keep on working indefinitely on - newer versions; exceptions to this rule are only made for security reasons. + For example, NDK r26 supports :ref:`API levels <738-os-versions>` 21 to 34. + However, binaries compiled for an older Android version will usually keep on + 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. @@ -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 `__. - 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 support for ARM32 code). Although cross-architecture emulation is possible, it 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 developers, and is not available to the typical end user. -For these reasons, the primary way of running Python on Android will be by -loading ``libpython3.x.so`` into the main app process. Although there will also -be a ``python3.x`` executable linked against ``libpython3.x.so``, this is only -for debugging, not production use. +For these reasons, the recommended way of running Python on Android will be by +loading ``libpython3.x.so`` into the main app process. A ``python3.x`` +executable will not be officially supported on this platform. Specification @@ -215,16 +215,23 @@ Linkage ------- 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 -be linked against this library. This allows using the -``-Wl,--no-undefined`` option to detect missing symbols at build time, which can -be a significant time-saver. +app as a dynamic ``libpython3.x.so`` library which can be loaded into an app +using ``dlopen``. + +Unlike Linux, Android does not implicitly use a dlopened library to resolve +relocations in subsequently-loaded libraries, `even if RTLD_GLOBAL is used +`__. 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 executable that has been statically linked against ``libpython3.x.a``. Therefore, a static ``libpython3.x.a`` library will not be supported on Android. 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 a directory tree containing co-located .py, .pyc and .so files can be handled by Python's standard importer. @@ -233,28 +240,33 @@ Python's standard importer. Standard library ---------------- +Unsupported modules +''''''''''''''''''' + A number of standard library modules will not be supported on Android because the underlying C APIs are not available: * ``curses`` and ``readline`` * ``dbm.gnu`` and ``dbm.ndbm`` -* ``grp`` and ``spwd`` +* ``grp`` * ``multiprocessing`` – although subprocesses in general are allowed (see `App lifecycle`_), Android does not support any part of the `System V IPC API `__. * ``tkinter`` and ``turtle`` – these would require an Android build of Tk itself, which is not officially supported. - -Platform identification ------------------------ - ``sys`` ''''''' ``sys.platform`` will return ``"android"``. Although Android is based on Linux, 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 `__, +which can be viewed with the Android development tools. ``sys.stdin`` will +always return EOF. + ``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 namedtuple containing the following: -* ``release`` - Android version, as a string (e.g. ``"14"``) -* ``api_level`` - Android API level, as an integer (e.g. ``34``) +* ``release`` - Android version of the device, as a string (e.g. ``"14"``) +* ``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 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 + `__ of + the device, as a string (e.g. ``"Google"``) +* ``model`` - `model name + `__ of the + device, as a string (e.g. ``"Pixel 7"``) +* ``device`` - `device name + `__ 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`` '''''' @@ -313,8 +338,8 @@ Packaging Android wheels will use tags in the format ``android__``. For example: -* ``android_23_arm64_v8a`` -* ``android_23_x86_64`` +* ``android_21_arm64_v8a`` +* ``android_21_x86_64`` For the meaning of ````, see `OS versions`_. In the context of the wheel tag, it indicates the minimum Android version that was selected when