PEP: 720 Title: Cross-compiling Python packages Author: Filipe Laíns
<lains@riseup.net> PEP-Delegate: Status: Draft Type: Informational
Content-Type: text/x-rst Created: 01-Jul-2023 Python-Version: 3.12

Abstract

This PEP attempts to document the status of cross-compilation of
downstream projects.

It should give an overview of the approaches currently used by
distributors (Linux distros, WASM environment providers, etc.) to
cross-compile downstream projects (3rd party extensions, etc.).

Motivation

We write this PEP to express the challenges in cross-compilation and act
as a supporting document in future improvement proposals.

Analysis

Introduction

There are a couple different approaches being used to tackle this, with
different levels of interaction required from the user, but they all
require a significant amount of effort. This is due to the lack of
standardized cross-compilation infrastructure on the Python packaging
ecosystem, which itself stems from the complexity of cross-builds,
making it a huge undertaking.

Upstream support

Some major projects like CPython, setuptools, etc. provide some support
to help with cross-compilation, but it's unofficial and at a best-effort
basis. For example, the sysconfig module allows overwriting the data
module name via the _PYTHON_SYSCONFIGDATA_NAME environment variable,
something that is required for cross-builds, and setuptools accepts
patches[1] to tweak/fix its logic to be compatible with popular
"environment faking" workflows[2].

The lack of first-party support in upstream projects leads to
cross-compilation being fragile and requiring a significant effort from
users, but at the same time, the lack of standardization makes it harder
for upstreams to improve support as there's no clarity on how this
feature should be provided.

Projects with decent cross-build support

It seems relevant to point out that there are a few modern Python
package build-backends with, at least, decent cross-compilation support,
those being scikit-build and meson-python. Both these projects integrate
external mature build-systems into Python packaging — CMake and Meson,
respectively — so cross-build support is inherited from them.

Downstream approaches

Cross-compilation approaches fall in a spectrum that goes from, by
design, requiring extensive user interaction to (ideally) almost none.
Usually, they'll be based on one of two main strategies, using a
cross-build environment, or faking the target environment.

Cross-build environment

This consists of running the Python interpreter normally and utilizing
the cross-build provided by the projects' build-system. However, as we
saw above, upstream support is lacking, so this approach only works for
a small-ish set of projects. When this fails, the usual strategy is to
patch the build-system code to build use the correct toolchain, system
details, etc.[3].

Since this approach often requires package-specific patching, it
requires a lot of user interaction.

Examples

python-for-android, kivy-ios, etc.

Faking the target environment

Aiming to drop the requirement for user input, a popular approach is
trying to fake the target environment. It generally consists of
monkeypatching the Python interpreter to get it to mimic the interpreter
on the target system, which constitutes of changing many of the sys
module attributes, the sysconfig data, etc. Using this strategy,
build-backends do not need to have any cross-build support, and should
just work without any code changes.

Unfortunately, though, it isn't possible to truly fake the target
environment. There are many reasons for this, one of the main ones being
that it breaks code that actually needs to introspect the running
interpreter. As a result, monkeypatching Python to look like target is
very tricky — to achieve the less amount of breakage, we can only patch
certain aspects of the interpreter. Consequently, build-backends may
need some code changes, but these are generally much smaller than the
previous approach. This is an inherent limitation of the technique,
meaning this strategy still requires some user interaction.

Nonetheless, this strategy still works out-of-the-box with significantly
more projects than the approach above, and requires much less effort in
these cases. It is successful in decreasing the amount of user
interaction needed, even though it doesn't succeed in being generic.

Examples

crossenv, conda-forge, etc.

Environment introspection

As explained above, most build system code is written with the
assumption that the target system is the same as where the build is
occurring, so introspection is usually used to guide the build.

In this section, we try to document most of the ways this is
accomplished. It should give a decent overview of of environment details
that are required by build systems.

+----------------------+----------------------+----------------------+
| Snippet              | Description          | Variance             |
+======================+======================+======================+
|     >>               | Extension (native    | This is              |
| > importlib.machiner | module) suffixes     | imp                  |
| y.EXTENSION_SUFFIXES | supported by this    | lementation-defined, |
|     [                | interpreter.         | but it usually       |
|                      |                      | differs based on the |
|      '.cpython-311-x |                      | implementation,      |
| 86_64-linux-gnu.so', |                      | system architecture, |
|        '.abi3.so',   |                      | build configuration, |
|        '.so',        |                      | Python language      |
|     ]                |                      | version, and         |
|                      |                      | implementation       |
|                      |                      | version — if one     |
|                      |                      | exists.              |
+----------------------+----------------------+----------------------+
|                      | Source (pure-Python) | This is              |
|  >>> importlib.machi | suffixes supported   | imp                  |
| nery.SOURCE_SUFFIXES | by this interpreter. | lementation-defined, |
|     ['.py']          |                      | but it usually       |
|                      |                      | doesn't differ       |
|                      |                      | (outside exotic      |
|                      |                      | implementations or   |
|                      |                      | systems).            |
+----------------------+----------------------+----------------------+
|                      | All module file      | This is              |
|   >>> importlib.mach | suffixes supported   | imp                  |
| inery.all_suffixes() | by this interpreter. | lementation-defined, |
|     [                | It should be the     | but it usually       |
|        '.py',        | union of all         | differs based on the |
|        '.pyc',       | importlib.           | implementation,      |
|                      | machinery.*_SUFFIXES | system architecture, |
|      '.cpython-311-x | attributes.          | build configuration, |
| 86_64-linux-gnu.so', |                      | Python language      |
|        '.abi3.so',   |                      | version, and         |
|        '.so',        |                      | implementation       |
|     ]                |                      | version — if one     |
|                      |                      | exists. See the      |
|                      |                      | entries above for    |
|                      |                      | more information.    |
+----------------------+----------------------+----------------------+
|     >>> sys.abiflags | ABI flags, as        | Differs based on the |
|     ''               | specified in PEP     | build configuration. |
|                      | 3149.                |                      |
+----------------------+----------------------+----------------------+
|                      | C API version.       | Differs based on the |
|  >>> sys.api_version |                      | Python installation. |
|     1013             |                      |                      |
+----------------------+----------------------+----------------------+
|                      | Prefix of the        | Differs based on the |
|  >>> sys.base_prefix | installation-wide    | platform, and        |
|     /usr             | directories where    | installation.        |
|                      | platform independent |                      |
|                      | files are installed. |                      |
+----------------------+----------------------+----------------------+
|     >>>              | Prefix of the        | Differs based on the |
| sys.base_exec_prefix | installation-wide    | platform, and        |
|     /usr             | directories where    | installation.        |
|                      | platform dependent   |                      |
|                      | files are installed. |                      |
+----------------------+----------------------+----------------------+
|                      | Native byte order.   | Differs based on the |
|    >>> sys.byteorder |                      | platform.            |
|     'little'         |                      |                      |
+----------------------+----------------------+----------------------+
|     >>> sys.         | Names of all modules | Differs based on the |
| builtin_module_names | that are compiled    | platform, system     |
|     ('_abc', '_a     | into the Python      | architecture, and    |
| st', '_codecs', ...) | interpreter.         | build configuration. |
+----------------------+----------------------+----------------------+
|                      | Prefix of the        | Differs based on the |
|  >>> sys.exec_prefix | site-specific        | platform,            |
|     /usr             | directories where    | installation, and    |
|                      | platform independent | environment.         |
|                      | files are installed. |                      |
|                      | Because it concerns  |                      |
|                      | the site-specific    |                      |
|                      | directories, in      |                      |
|                      | standard virtual     |                      |
|                      | environment          |                      |
|                      | implementation, it   |                      |
|                      | will be a            |                      |
|                      | virtual-             |                      |
|                      | environment-specific |                      |
|                      | path.                |                      |
+----------------------+----------------------+----------------------+
|                      | Path of the Python   | Differs based on the |
|   >>> sys.executable | interpreter being    | installation.        |
|                      | used.                |                      |
|    '/usr/bin/python' |                      |                      |
+----------------------+----------------------+----------------------+
|     >                | Whether the Python   | Differs based on the |
| >> with open(sys.exe | interpreter is an    | installation.        |
| cutable, 'rb') as f: | ELF file, and the    |                      |
|     ...              | ELF header. This     |                      |
|   header = f.read(4) | approach is          |                      |
|     ..               | something used to    |                      |
| .   if is_elf := (he | identify the target  |                      |
| ader == b'\x7fELF'): | architecture of the  |                      |
|     ...     elf_cl   | installation         |                      |
| ass = int(f.read(1)) | (example).           |                      |
|     ...              |                      |                      |
|     size = {1: 52, 2 |                      |                      |
| : 64}.get(elf_class) |                      |                      |
|                      |                      |                      |
|    ...     elf_heade |                      |                      |
| r = f.read(size - 5) |                      |                      |
+----------------------+----------------------+----------------------+
|                      | Low level            | Differs based on the |
|   >>> sys.float_info | information about    | architecture, and    |
|     sys.float_info(  | the float type, as   | platform.            |
|        max=1.79      | defined by float.h.  |                      |
| 76931348623157e+308, |                      |                      |
|        max_exp=1024, |                      |                      |
|                      |                      |                      |
|      max_10_exp=308, |                      |                      |
|        min=2.22      |                      |                      |
| 50738585072014e-308, |                      |                      |
|                      |                      |                      |
|       min_exp=-1021, |                      |                      |
|                      |                      |                      |
|     min_10_exp=-307, |                      |                      |
|        dig=15,       |                      |                      |
|        mant_dig=53,  |                      |                      |
|        epsilon=2.    |                      |                      |
| 220446049250313e-16, |                      |                      |
|        radix=2,      |                      |                      |
|        rounds=1,     |                      |                      |
|     )                |                      |                      |
+----------------------+----------------------+----------------------+
|     >>> sys.         | Integer representing | Differs based on the |
| getandroidapilevel() | the Android API      | platform.            |
|     21               | level.               |                      |
+----------------------+----------------------+----------------------+
|     >>> sys          | Windows version of   | Differs based on the |
| .getwindowsversion() | the system.          | platform.            |
|     sy               |                      |                      |
| s.getwindowsversion( |                      |                      |
|        major=10,     |                      |                      |
|        minor=0,      |                      |                      |
|        build=19045,  |                      |                      |
|        platform=2,   |                      |                      |
|                      |                      |                      |
|     service_pack='', |                      |                      |
|     )                |                      |                      |
+----------------------+----------------------+----------------------+
|                      | Python version       | Differs based on the |
|   >>> sys.hexversion | encoded as an        | Python language      |
|     0x30b03f0        | integer.             | version.             |
+----------------------+----------------------+----------------------+
|     >>               | Interpreter          | Differs based on the |
| > sys.implementation | implementation       | interpreter          |
|     namespace(       | details.             | implementation,      |
|                      |                      | Python language      |
|      name='cpython', |                      | version, and         |
|        cach          |                      | implementation       |
| e_tag='cpython-311', |                      | version — if one     |
|        versi         |                      | exists. It may also  |
| on=sys.version_info( |                      | include              |
|           major=3,   |                      | ar                   |
|           minor=11,  |                      | chitecture-dependent |
|           micro=3,   |                      | information, so it   |
|           r          |                      | may also differ      |
| eleaselevel='final', |                      | based on the system  |
|           serial=0,  |                      | architecture.        |
|        ),            |                      |                      |
|        h             |                      |                      |
| exversion=0x30b03f0, |                      |                      |
|        _multiarch    |                      |                      |
| ='x86_64-linux-gnu', |                      |                      |
|     )                |                      |                      |
+----------------------+----------------------+----------------------+
|     >>> sys.int_info | Low level            | Differs based on the |
|     sys.int_info(    | information about    | architecture,        |
|                      | Python's internal    | platform,            |
|   bits_per_digit=30, | integer              | implementation,      |
|                      | representation.      | build, and runtime   |
|      sizeof_digit=4, |                      | flags.               |
|        default_      |                      |                      |
| max_str_digits=4300, |                      |                      |
|        str_digits_   |                      |                      |
| check_threshold=640, |                      |                      |
|     )                |                      |                      |
+----------------------+----------------------+----------------------+
|     >>> sys.maxsize  | Maximum value a      | Differs based on the |
|                      | variable of type     | architecture,        |
|   0x7fffffffffffffff | Py_ssize_t can take. | platform, and        |
|                      |                      | implementation.      |
+----------------------+----------------------+----------------------+
|                      | Value of the largest | Differs based on the |
|   >>> sys.maxunicode | Unicode code point.  | implementation, and  |
|     0x10ffff         |                      | on Python versions   |
|                      |                      | older than 3.3, the  |
|                      |                      | build.               |
+----------------------+----------------------+----------------------+
|     >>> sys.platform | Platform identifier. | Differs based on the |
|     linux            |                      | platform.            |
+----------------------+----------------------+----------------------+
|     >>> sys.prefix   | Prefix of the        | Differs based on the |
|     /usr             | site-specific        | platform,            |
|                      | directories where    | installation, and    |
|                      | platform dependent   | environment.         |
|                      | files are installed. |                      |
|                      | Because it concerns  |                      |
|                      | the site-specific    |                      |
|                      | directories, in      |                      |
|                      | standard virtual     |                      |
|                      | environment          |                      |
|                      | implementation, it   |                      |
|                      | will be a            |                      |
|                      | virtual-             |                      |
|                      | environment-specific |                      |
|                      | path.                |                      |
+----------------------+----------------------+----------------------+
|                      | Platform-specific    | Differs based on the |
|   >>> sys.platlibdir | library directory.   | platform, and        |
|     lib              |                      | vendor.              |
+----------------------+----------------------+----------------------+
|                      | Python language      | Differs if the       |
| >>> sys.version_info | version implemented  | target Python        |
|                      | by the interpreter.  | version is not the   |
|    sys.version_info( |                      | same[8].             |
|        major=3,      |                      |                      |
|        minor=11,     |                      |                      |
|        micro=3,      |                      |                      |
|        r             |                      |                      |
| eleaselevel='final', |                      |                      |
|        serial=0,     |                      |                      |
|     )                |                      |                      |
+----------------------+----------------------+----------------------+
|                      | Information about    | Differs based on the |
|  >>> sys.thread_info | the thread           | platform, and        |
|     sys.thread_info( | implementation.      | implementation.      |
|                      |                      |                      |
|      name='pthread', |                      |                      |
|                      |                      |                      |
|    lock='semaphore', |                      |                      |
|                      |                      |                      |
| version='NPTL 2.37', |                      |                      |
|     )                |                      |                      |
+----------------------+----------------------+----------------------+
|     >>> sys.winver   | Version number used  | Differs based on the |
|     3.8-32           | to form Windows      | platform, and        |
|                      | registry keys.       | implementation.      |
+----------------------+----------------------+----------------------+
|     >>> sysconf      | Python distribution  | This is              |
| ig.get_config_vars() | configuration        | imp                  |
|     { ... }          | variables. It        | lementation-defined, |
|     >>> sysconfig    | includes a set of    | but it usually       |
| .get_config_var(...) | variables[9] — like  | differs between      |
|     ...              | prefix, exec_prefix, | non-identical        |
|                      | etc. — based on the  | builds. Please refer |
|                      | running context[10], | to the sysconfig     |
|                      | and may include some | configuration        |
|                      | extra variables      | variables table for  |
|                      | based on the Python  | a overview of the    |
|                      | implementation and   | different            |
|                      | system.              | configuration        |
|                      |                      | variable that are    |
|                      | In CPython and most  | usually present.     |
|                      | other                |                      |
|                      | implementations that |                      |
|                      | use the same         |                      |
|                      | build-system, the    |                      |
|                      | "extra" variables    |                      |
|                      | mention above are:   |                      |
|                      | on POSIX, all        |                      |
|                      | variables from the   |                      |
|                      | Makefile used to     |                      |
|                      | build the            |                      |
|                      | interpreter, and on  |                      |
|                      | Windows, it usually  |                      |
|                      | only includes a      |                      |
|                      | small subset of the  |                      |
|                      | those[11] — like     |                      |
|                      | EXT_SUFFIX, BINDIR,  |                      |
|                      | etc.                 |                      |
+----------------------+----------------------+----------------------+

CPython (and similar)

  --------------------------------------------------------------------------------------------------------
  Name                 Example Value                      Description                Variance
  -------------------- ---------------------------------- -------------------------- ---------------------
  SOABI                cpython-311-x86_64-linux-gnu       ABI string — defined by    Differs based on the
                                                          PEP 3149.                  implementation,
                                                                                     system architecture,
                                                                                     Python language
                                                                                     version, and
                                                                                     implementation
                                                                                     version — if one
                                                                                     exists.

  SHLIB_SUFFIX         .so                                Shared library suffix.     Differs based on the
                                                                                     platform.

  EXT_SUFFIX           .cpython-311-x86_64-linux-gnu.so   Interpreter-specific       Differs based on the
                                                          Python extension (native   implementation,
                                                          module) suffix — generally system architecture,
                                                          defined as                 Python language
                                                          .{SOABI}.{SHLIB_SUFFIX}.   version, and
                                                                                     implementation
                                                                                     version — if one
                                                                                     exists.

  LDLIBRARY            libpython3.11.so                   Shared libpython library   Differs based on the
                                                          name — if available. If    implementation,
                                                          unavailable[12], the       system architecture,
                                                          variable will be empty, if build configuration,
                                                          available, the library     Python language
                                                          should be located in       version, and
                                                          LIBDIR.                    implementation
                                                                                     version — if one
                                                                                     exists.

  PY3LIBRARY           libpython3.so                      Shared Python 3 only       Differs based on the
                                                          (major version bound       implementation,
                                                          only)[13] libpython        system architecture,
                                                          library name — if          build configuration,
                                                          available. If              Python language
                                                          unavailable[14], the       version, and
                                                          variable will be empty, if implementation
                                                          available, the library     version — if one
                                                          should be located in       exists.
                                                          LIBDIR.                    

  LIBRARY              libpython3.11.a                    Static libpython library   Differs based on the
                                                          name — if available. If    implementation,
                                                          unavailable[15], the       system architecture,
                                                          variable will be empty, if build configuration,
                                                          available, the library     Python language
                                                          should be located in       version, and
                                                          LIBDIR.                    implementation
                                                                                     version — if one
                                                                                     exists.

  Py_DEBUG             0                                  Whether this is a debug    Differs based on the
                                                          build.                     build configuration.

  WITH_PYMALLOC        1                                  Whether this build has     Differs based on the
                                                          pymalloc support.          build configuration.

  Py_TRACE_REFS        0                                  Whether reference tracing  Differs based on the
                                                          (debug build only) is      build configuration.
                                                          enabled.                   

  Py_UNICODE_SIZE                                         Size of the Py_UNICODE     Differs based on the
                                                          object, in bytes. This     build configuration.
                                                          variable is only present   
                                                          in CPython versions older  
                                                          than 3.3, and was commonly 
                                                          used to detect if the      
                                                          build uses UCS2 or UCS4    
                                                          for unicode objects —      
                                                          before PEP 393.            

  Py_ENABLE_SHARED     1                                  Whether a shared libpython Differs based on the
                                                          is available.              build configuration.

  PY_ENABLE_SHARED     1                                  Whether a shared libpython Differs based on the
                                                          is available.              build configuration.

  CC                   gcc                                The C compiler used to     Differs based on the
                                                          build the Python           build configuration.
                                                          distribution.              

  CXX                  g++                                The C compiler used to     Differs based on the
                                                          build the Python           build configuration.
                                                          distribution.              

  CFLAGS               -DNDEBUG -g -fwrapv ...            The C compiler flags used  Differs based on the
                                                          to build the Python        build configuration.
                                                          distribution.              

  py_version           3.11.3                             Full form of the Python    Differs based on the
                                                          version.                   Python language
                                                                                     version.

  py_version_short     3.11                               Custom form of the Python  Differs based on the
                                                          version, containing only   Python language
                                                          the major and minor        version.
                                                          numbers.                   

  py_version_nodot     311                                Custom form of the Python  Differs based on the
                                                          version, containing only   Python language
                                                          the major and minor        version.
                                                          numbers, and no dots.      

  prefix               /usr                               Same as sys.prefix, please Differs based on the
                                                          refer to the entry in      platform,
                                                          table above.               installation, and
                                                                                     environment.

  base                 /usr                               Same as sys.prefix, please Differs based on the
                                                          refer to the entry in      platform,
                                                          table above.               installation, and
                                                                                     environment.

  exec_prefix          /usr                               Same as sys.exec_prefix,   Differs based on the
                                                          please refer to the entry  platform,
                                                          in table above.            installation, and
                                                                                     environment.

  platbase             /usr                               Same as sys.exec_prefix,   Differs based on the
                                                          please refer to the entry  platform,
                                                          in table above.            installation, and
                                                                                     environment.

  installed_base       /usr                               Same as sys.base_prefix,   Differs based on the
                                                          please refer to the entry  platform, and
                                                          in table above.            installation.

  installed_platbase   /usr                               Same as                    Differs based on the
                                                          sys.base_exec_prefix,      platform, and
                                                          please refer to the entry  installation.
                                                          in table above.            

  platlibdir           lib                                Same as sys.platlibdir,    Differs based on the
                                                          please refer to the entry  platform, and vendor.
                                                          in table above.            

  SIZEOF_*             4                                  Size of a certain C type   Differs based on the
                                                          (double, float, etc.).     system architecture,
                                                                                     and build details.
  --------------------------------------------------------------------------------------------------------

  : sysconfig configuration variables

Relevant Information

There are some bits of information required by build systems — eg.
platform particularities — scattered across many places, and it often is
difficult to identify code with assumptions based on them. In this
section, we try to document the most relevant cases.

When should extensions be linked against libpython?

Short answer

    Yes, on Windows. No on POSIX platforms, except Android, Cygwin, and
    other Windows-based POSIX-like platforms.

When building extensions for dynamic loading, depending on the target
platform, they may need to be linked against libpython.

On Windows, extensions need to link against libpython, because all
symbols must be resolvable at link time. POSIX-like platforms based on
Windows — like Cygwin, MinGW, or MSYS — will also require linking
against libpython.

On most POSIX platforms, it is not necessary to link against libpython,
as the symbols will already be available in the due to the interpreter —
or, when embedding, the executable/library in question — already linking
to libpython. Not linking an extension module against libpython will
allow it to be loaded by static Python builds, so when possible, it is
desirable to do so (see GH-65735).

This might not be the case on all POSIX platforms, so make sure you
check. One example is Android, where only the main executable and
LD_PRELOAD entries are considered to be RTLD_GLOBAL (meaning
dependencies are RTLD_LOCAL) [16], which causes the libpython symbols be
unavailable when loading the extension.

What are prefix, exec_prefix, base_prefix, and base_exec_prefix?

These are sys attributes set in the Python initialization that describe
the running environment. They refer to the prefix of directories where
installation/environment files are installed, according to the table
below.

  Name               Target files                             Environment Scope
  ------------------ ---------------------------------------- -------------------
  prefix             platform independent (eg. pure Python)   site-specific
  exec_prefix        platform dependent (eg. native code)     site-specific
  base_prefix        platform independent (eg. pure Python)   installation-wide
  base_exec_prefix   platform dependent (eg. native code)     installation-wide

Because the site-specific prefixes will be different inside virtual
environments, checking sys.prexix != sys.base_prefix is commonly used to
check if we are in a virtual environment.

Case studies

crossenv

Description

    Virtual Environments for Cross-Compiling Python Extension Modules.

URL

    https://github.com/benfogle/crossenv

crossenv is a tool to create a virtual environment with a monkeypatched
Python installation that tries to emulate the target machine in certain
scenarios. More about this approach can be found in the Faking the
target environment section.

conda-forge

Description

    A community-led collection of recipes, build infrastructure and
    distributions for the conda package manager.

URL

    https://conda-forge.org/

XXX: Jaime will write a quick summary once the PEP draft is public.

XXX Uses a modified crossenv.

Yocto Project

Description

    The Yocto Project is an open source collaboration project that helps
    developers create custom Linux-based systems regardless of the
    hardware architecture.

URL

    https://www.yoctoproject.org/

XXX: Sent email to the mailing list.

TODO

Buildroot

Description

    Buildroot is a simple, efficient and easy-to-use tool to generate
    embedded Linux systems through cross-compilation.

URL

    https://buildroot.org/

TODO

Pyodide

Description

    Pyodide is a Python distribution for the browser and Node.js based
    on WebAssembly.

URL

    https://pyodide.org/en/stable/

XXX: Hood should review/expand this section.

Pyodide is a provides a Python distribution compiled to WebAssembly
using the Emscripten toolchain.

It patches several aspects of the CPython installation and some external
components. A custom package manager — micropip — supporting both Pure
and wasm32/Emscripten wheels, is also provided as a part of the
distribution. On top of this, a repo with a selected set of 3rd party
packages is also provided and enabled by default.

Beeware

Description

    BeeWare allows you to write your app in Python and release it on
    multiple platforms.

URL

    https://beeware.org/

TODO

python-for-android

Description

    Turn your Python application into an Android APK.

URL

    https://github.com/kivy/python-for-android

resource https://github.com/Android-for-Python/Android-for-Python-Users

python-for-android is a tool to package Python apps on Android. It
creates a Python distribution with your app and its dependencies.

Pure-Python dependencies are handled automatically and in a generic way,
but native dependencies need recipes. A set of recipes for popular
dependencies is provided, but users need to provide their own recipes
for any other native dependencies.

kivy-ios

Description

    Toolchain for compiling Python / Kivy / other libraries for iOS.

URL

    https://github.com/kivy/kivy-ios

kivy-ios is a tool to package Python apps on iOS. It provides a
toolchain to build a Python distribution with your app and its
dependencies, as well as a CLI to create and manage Xcode projects that
integrate with the toolchain.

It uses the same approach as python-for-android (also maintained by the
Kivy project) for app dependencies — pure-Python dependencies are
handled automatically, but native dependencies need recipes, and the
project provides recipes for popular dependencies.

AidLearning

Description

    AI, Android, Linux, ARM: AI application development platform based
    on Android+Linux integrated ecology.

URL

    https://github.com/aidlearning/AidLearning-FrameWork

TODO

QPython

Description

    QPython is the Python engine for android.

URL

    https://github.com/qpython-android/qpython

TODO

pyqtdeploy

Description

    pyqtdeploy is a tool for deploying PyQt applications.

URL

    https://www.riverbankcomputing.com/software/pyqtdeploy/

contact
https://www.riverbankcomputing.com/pipermail/pyqt/2023-May/thread.html
contacted Phil, the maintainer

TODO

Chaquopy

Description

    Chaquopy provides everything you need to include Python components
    in an Android app.

URL

    https://chaquo.com/chaquopy/

TODO

EDK II

Description

    EDK II is a modern, feature-rich, cross-platform firmware
    development environment for the UEFI and PI specifications.

URL

    https://github.com/tianocore/edk2-libc/tree/master/AppPkg/Applications/Python

TODO

ActivePython

Description

    Commercial-grade, quality-assured Python distribution focusing on
    easy installation and cross-platform compatibility on Windows,
    Linux, Mac OS X, Solaris, HP-UX and AIX.

URL

    https://www.activestate.com/products/python/

TODO

Termux

Description

    Termux is an Android terminal emulator and Linux environment app
    that works directly with no rooting or setup required.

URL

    https://termux.dev/en/

TODO

[1] At the time of writing (Jun 2023), setuptools' compiler interface
code, the component that most of affects cross-compilation, is developed
on the pypa/distutils repository, which gets periodically synced to the
setuptools repository.

[2] We specifically mention popular workflows, because this is not
standardized. Though, many of the most popular implementations
(crossenv, conda-forge's build system, etc.) work similarly, and this is
what we are referring to here. For clarity, the implementations we are
referring to here could be described as crossenv-style.

[3] The scope of the build-system patching varies between users and
usually depends on the their goal — some (eg. Linux distributions) may
patch the build-system to support cross-builds, while others might
hardcode compiler paths and system information in the build-system, to
simply make the build work.

[4] Ideally, you want to perform cross-builds with the same Python
version and implementation, however, this is often not the case. It
should not be very problematic as long as the major and minor versions
don't change.

[5] The set of config variables that will always be present mostly
consists of variables needed to calculate the installation scheme paths.

[6] The context we refer here consists of the "path initialization",
which is a process that happens in the interpreter startup and is
responsible for figuring out which environment it is being run — eg.
global environment, virtual environment, etc. — and setting sys.prefix
and other attributes accordingly.

[7] This is because Windows builds may not use the Makefile, and instead
use the Visual Studio build system. A subset of the most relevant
Makefile variables is provided to make user code that uses them simpler.

[8] Ideally, you want to perform cross-builds with the same Python
version and implementation, however, this is often not the case. It
should not be very problematic as long as the major and minor versions
don't change.

[9] The set of config variables that will always be present mostly
consists of variables needed to calculate the installation scheme paths.

[10] The context we refer here consists of the "path initialization",
which is a process that happens in the interpreter startup and is
responsible for figuring out which environment it is being run — eg.
global environment, virtual environment, etc. — and setting sys.prefix
and other attributes accordingly.

[11] This is because Windows builds may not use the Makefile, and
instead use the Visual Studio build system. A subset of the most
relevant Makefile variables is provided to make user code that uses them
simpler.

[12] Due to Python bring compiled without shared or static libpython
support, respectively.

[13] This is the libpython library that users of the stable ABI should
link against, if they need to link against libpython.

[14] Due to Python bring compiled without shared or static libpython
support, respectively.

[15] Due to Python bring compiled without shared or static libpython
support, respectively.

[16] Refer to dlopen's man page for more information.