From c274b4e02c75fd8295218da7a4b89c8baa0d7bbc Mon Sep 17 00:00:00 2001 From: Henry Schreiner Date: Fri, 15 May 2026 23:47:20 -0700 Subject: [PATCH] feat: add CPython 3.15 support for Android (#2858) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add CPython 3.15 support for iOS and Android Add cp315 identifiers to build-platforms.toml for both iOS (arm64_iphoneos, x86_64_iphonesimulator, arm64_iphonesimulator) and Android (arm64_v8a, x86_64). Update bin/update_pythons.py to route iOS 3.15+ to python.org instead of BeeWare GitHub releases. Update README.md platform table to show Android and iOS as supported for 3.15. Add cp315-cp315 to expected_wheels test defaults for android and ios platforms. Assisted-by: OpenCode:Kimi-K2.6 Signed-off-by: Henry Schreiner * fix: adjust expectations All changes made and linting passes. Here's a summary of what was done: 1. test/utils.py:390-394 — Added "cp315-cp315": 24 to the Android API level mapping, fixing the KeyError: 'cp315-cp315' in test_android.py::test_expected_wheels. 2. cibuildwheel/resources/build-platforms.toml:247 — Removed the cp315-ios_x86_64_iphonesimulator entry since CPython 3.15 dropped Intel iOS simulator support. 3. test/utils.py:397-405 — Updated the iOS expected wheels logic to return an empty platform_tags list for x86_64 when the Python version is 3.15+, so no x86_64_iphonesimulator wheels are expected for cp315+ on Intel Macs. The XCframework slice name (ios-arm64_x86_64-simulator) stays the same in ios.py — I verified the 3.15 tarball still uses that name. The target_python.exists() iOS ARM64 failure on the feature branch is a separate issue (the 3.15 python.org distribution has a different structure than the beeware distributions used for 3.13/3.14) — left alone per your request. Signed-off-by: Henry Schreiner Assisted-by: OpenCode:glm-5.1 * revert: x86 is still supposed to exist Signed-off-by: Henry Schreiner * docs: fix readme for Pyodide Signed-off-by: Henry Schreiner * docs: mention eol Signed-off-by: Henry Schreiner * fix: drop assert Signed-off-by: Henry Schreiner * feat: add CPython 3.15 support for Android only Cherry-picked all changes from henryiii/feat/cp315-ios-android, then reverted iOS-specific parts (iOS 3.15 build configs, ios.py assert removal, update_pythons.py iOS URL logic, iOS test expectations, and README iOS column for 3.15). Android cp315 entries, test expectations, and README Android column remain. Assisted-by: OpenCode:glm-5 --------- Signed-off-by: Henry Schreiner --- README.md | 26 +++++++++++---------- cibuildwheel/resources/build-platforms.toml | 2 ++ test/utils.py | 9 ++++--- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 7a212d77..62d3c73a 100644 --- a/README.md +++ b/README.md @@ -24,13 +24,13 @@ While cibuildwheel itself requires a recent Python version to run (we support th | | macOS Intel | macOS Apple Silicon | Windows 64bit | Windows 32bit | Windows Arm64 | manylinux
musllinux x86_64 | manylinux
musllinux i686 | manylinux
musllinux aarch64 | manylinux
musllinux ppc64le | manylinux
musllinux s390x | manylinux
musllinux armv7l | Android | iOS | Pyodide | | ------------------------ | ----------- | ------------------- | ------------- | ------------- | -------------- | ------------------------------ | ---------------------------- | ------------------------------- | ------------------------------- | ----------------------------- | ------------------------------ | ------- | --- | -------------- | -| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A | -| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A | -| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A | -| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | ✅3 | -| CPython 3.13 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | ✅ | ✅ | ✅3 | -| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | ✅ | ✅ | N/A | -| CPython 3.155 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅4 | N/A | N/A | N/A | +| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅5 | N/A | N/A | N/A | +| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅5 | N/A | N/A | N/A | +| CPython 3.11 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅5 | N/A | N/A | N/A | +| CPython 3.12 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅5 | N/A | N/A | ✅3 | +| CPython 3.13 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅5 | ✅ | ✅ | ✅ | +| CPython 3.14 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅5 | ✅ | ✅ | ✅4 | +| CPython 3.156 | ✅ | ✅ | ✅ | ✅ | ✅2 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅5 | ✅ | N/A | N/A | | PyPy 3.9 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A | | PyPy 3.10 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A | | PyPy 3.11 v7.3 | ✅ | ✅ | ✅ | N/A | N/A | ✅1 | ✅1 | ✅1 | N/A | N/A | N/A | N/A | N/A | N/A | @@ -39,13 +39,15 @@ While cibuildwheel itself requires a recent Python version to run (we support th **1** PyPy & GraalPy are only supported for manylinux wheels.
**2** Windows arm64 support is experimental.
-**3** Experimental, not yet supported on PyPI, but can be used directly in web deployment. Use `--platform pyodide` to build.
-**4** manylinux armv7l support is experimental. As there are no RHEL based image for this architecture, it's using an Ubuntu based image instead.
-**5** Python 3.15 requires opt-in using [`enable`](https://cibuildwheel.pypa.io/en/stable/options/#enable).
+**3** Not supported on PyPI, uses old `pyodide` tag instead of `pyemscripten`. Requires `pyodide-eol` [`enable`](https://cibuildwheel.pypa.io/en/stable/options/#enable).
+**4** Experimental alpha ABI, do not upload to PyPI yet.
+**5** manylinux armv7l support is experimental. As there are no RHEL based image for this architecture, it's using an Ubuntu based image instead.
+**6** Python 3.15 requires opt-in using [`enable`](https://cibuildwheel.pypa.io/en/stable/options/#enable).
-- Builds manylinux, musllinux, macOS, and Windows wheels for CPython, PyPy, and GraalPy +- Builds manylinux, musllinux, macOS, Windows, pyemscripten, iOS, and Android wheels +- Supports CPython, PyPy, and GraalPy - Works on GitHub Actions, Azure Pipelines, CircleCI, and GitLab CI -- Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate) +- Bundles shared library dependencies on Linux through [auditwheel](https://github.com/pypa/auditwheel), macOS through [delocate](https://github.com/matthew-brett/delocate), and Windows through [delvewheel](https://github.com/adang1345/delvewheel) - Runs your library's tests against the wheel-installed version of your library See the [cibuildwheel 1 documentation](https://cibuildwheel.pypa.io/en/1.x/) if you need to build unsupported versions of Python, such as Python 2. diff --git a/cibuildwheel/resources/build-platforms.toml b/cibuildwheel/resources/build-platforms.toml index 8348fe7c..701f191d 100644 --- a/cibuildwheel/resources/build-platforms.toml +++ b/cibuildwheel/resources/build-platforms.toml @@ -231,6 +231,8 @@ python_configurations = [ { identifier = "cp313-android_x86_64", version = "3.13", url = "https://repo.maven.apache.org/maven2/com/chaquo/python/python/3.13.13/python-3.13.13-x86_64-linux-android.tar.gz" }, { identifier = "cp314-android_arm64_v8a", version = "3.14", url = "https://www.python.org/ftp/python/3.14.5/python-3.14.5-aarch64-linux-android.tar.gz" }, { identifier = "cp314-android_x86_64", version = "3.14", url = "https://www.python.org/ftp/python/3.14.5/python-3.14.5-x86_64-linux-android.tar.gz" }, + { identifier = "cp315-android_arm64_v8a", version = "3.15", url = "https://www.python.org/ftp/python/3.15.0/python-3.15.0b1-aarch64-linux-android.tar.gz" }, + { identifier = "cp315-android_x86_64", version = "3.15", url = "https://www.python.org/ftp/python/3.15.0/python-3.15.0b1-x86_64-linux-android.tar.gz" }, ] [ios] diff --git a/test/utils.py b/test/utils.py index 209b7f5d..d451f750 100644 --- a/test/utils.py +++ b/test/utils.py @@ -263,16 +263,20 @@ def _expected_wheels( if musllinux_versions is None: musllinux_versions = ["musllinux_1_2"] + enable_groups = get_enable_groups() + # To be kept in sync with Python versions for Pyodide identifiers in cibuildwheel/selector.py. if platform == "pyodide" and python_abi_tags is None: python_abi_tags = ["cp313-cp313"] if EnableGroup.PyodidePrerelease in enable_groups: python_abi_tags.append("cp314-cp314") - elif platform == "android" and python_abi_tags is None: # noqa: SIM114 + elif platform == "android" and python_abi_tags is None: python_abi_tags = [ "cp313-cp313", "cp314-cp314", ] + if EnableGroup.CPythonPrerelease in enable_groups: + python_abi_tags += ["cp315-cp315"] elif platform == "ios" and python_abi_tags is None: python_abi_tags = [ "cp313-cp313", @@ -289,8 +293,6 @@ def _expected_wheels( "cp314-cp314t", ] - enable_groups = get_enable_groups() - if EnableGroup.CPythonPrerelease in enable_groups: python_abi_tags += [ "cp315-cp315", @@ -386,6 +388,7 @@ def _expected_wheels( api_level = { "cp313-cp313": 21, "cp314-cp314": 24, + "cp315-cp315": 24, }[python_abi_tag] platform_tags = [f"android_{api_level}_{machine_arch}"]