feat: add support for building Android wheels (#2349)

* Add Android to resource files

* Add Android to miscellaneous places

* Add Android documentation

* Docs cleanups

* Add Android platform module; implement top-level structure and target Python installation

* Implement setup_env and build_wheel

* lru-dict build working

* Alter prefix in sysconfigdata file; fix various issues with FLAGS variables

* Implement Android testing

* Add type annotations to _cross_venv

* Revert Python 3.8 to pip 25.0.1

* Make test-sources required on Android

* Add Android integration tests

* Test cleanups

* Add test of all available Python versions

* Update test-sources and test-command behavior to match iOS

* Documentation cleanups

* Replace Builder class with a set of global functions

* Rename "env" to "build_env"

* Remove Chaquopy repository from default pip command line

* Move native_platform to platforms module

* Fix parse_config_settings

Co-authored-by: Joe Rickerby <joerick@mac.com>

* Add unit tests for parse_config_settings and arch_synonym

* Make `shell_prepared` arguments keyword-only, and add tests for the commands that use it

* Replace `importlib.util.spec_from_file_location` with `runpy.run_path`

* Use python-build-standalone

* Update Android Python

* Enable KVM in Linux CI

* Move KVM code to test_android.py

* Use Java 17 on Azure

* Install emulator if necessary before running -accel-check

* Free up additional disk space on Linux runners

* Add sudo

* Skip emulator tests on CI platforms that don't support it

* Download Android Python from Maven Central

* Free up more disk space on Linux runners

* fix: minor fixups

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* Set sysconfig._BASE_PREFIX to support sysconfig.get_path("include")

* Get ANDROID_API_LEVEL from the build environment, not cibuildwheel's own environment

* Correct relative path of test-sources

* Pass a CMake toolchain file to the build

* Add "repair" step which adds libc++ to the wheel when necessary

* Add missing needs_emulator decorator

* Provide useful error message if ANDROID_HOME is not set

* Remove use of HOST environment variable

* Update to Python 3.15.5

* Fix PyLint warnings, clarify comment

* Group common arguments into a dataclass

* Handle environment variables containing newlines

* Discourage the use of `pytest` test commands without `python -m`

* Use single quotes in user-visible messages

* Improve testing documentation

* Pass wheel filename to `log.build_end`

* In GitHub Actions example, skip Android tests on macOS

* Correct relative paths in `patchelf --set-rpath`

* Clarify `test-sources` docs

* Update to Python 3.13.5+20250722.214220

---------

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: Joe Rickerby <joerick@mac.com>
Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
This commit is contained in:
Malcolm Smith
2025-07-23 17:18:33 -04:00
committed by GitHub
co-authored by Joe Rickerby Henry Schreiner
parent e2e24882d8
commit 0f487ee2cb
38 changed files with 1548 additions and 160 deletions
+18 -1
View File
@@ -5,7 +5,7 @@ import sys
import pytest
import cibuildwheel.architecture
from cibuildwheel.architecture import Architecture
from cibuildwheel.architecture import Architecture, arch_synonym
@pytest.fixture(
@@ -115,3 +115,20 @@ def test_arch_auto_on_ios(monkeypatch):
monkeypatch.setattr(platform_module, "machine", lambda: "arm64")
arch_set = Architecture.parse_config("auto", platform="ios")
assert arch_set == {Architecture.arm64_iphonesimulator, Architecture.arm64_iphoneos}
@pytest.mark.parametrize(
("arch", "from_platform", "to_platform", "expected"),
[
("x86_64", "linux", "macos", "x86_64"),
("x86_64", "macos", "linux", "x86_64"),
("x86_64", "linux", "windows", "AMD64"),
("AMD64", "windows", "linux", "x86_64"),
("x86_64", "linux", "nonexistent", "x86_64"),
("x86_64", "nonexistent", "linux", "x86_64"),
("nonexistent", "linux", "windows", "nonexistent"),
("x86", "windows", "macos", None),
],
)
def test_arch_synonym(arch, from_platform, to_platform, expected):
assert arch_synonym(arch, from_platform, to_platform) == expected