diff --git a/cibuildwheel/platforms/android.py b/cibuildwheel/platforms/android.py index 229401e4f..f8444648a 100644 --- a/cibuildwheel/platforms/android.py +++ b/cibuildwheel/platforms/android.py @@ -7,7 +7,7 @@ import shutil import subprocess import sysconfig -from collections.abc import Iterable, Iterator +from collections.abc import Iterable, Iterator, MutableMapping from dataclasses import dataclass from os.path import relpath from pathlib import Path @@ -390,6 +390,11 @@ def setup_android_env( for key in ["CFLAGS", "CXXFLAGS"]: android_env[key] += " " + opt + # Cargo target linker need to be specified after CC is set + setup_rust_cross_compile(config, android_env) + + setup_PYO3_cross_compile(python_dir, android_env) + # Format the environment so it can be pasted into a shell when debugging. for key, value in sorted(android_env.items()): if os.environ.get(key) != value: @@ -398,6 +403,47 @@ def setup_android_env( return android_env +def setup_rust_cross_compile( + python_configuration: PythonConfiguration, + env: MutableMapping[str, str], +) -> None: + cargo_target = android_triplet(python_configuration.identifier) + call("rustup", "target", "add", cargo_target) + + # CARGO_BUILD_TARGET is the variable used by Cargo and setuptools_rust + if env.get("CARGO_BUILD_TARGET"): + if env["CARGO_BUILD_TARGET"] != cargo_target: + log.notice("Not overriding CARGO_BUILD_TARGET as it has already been set") + # No message if it was set to what we were planning to set it to + elif cargo_target: + cargo_target_linker_env_name = ( + f"CARGO_TARGET_{cargo_target.upper().replace('-', '_')}_LINKER" + ) + log.notice( + f"Setting CARGO_BUILD_TARGET={cargo_target} and {cargo_target_linker_env_name} for cross-compilation" + ) + env["CARGO_BUILD_TARGET"] = cargo_target + # CC has already been set by calling android.py (it calls android-env.sh) + env[f"{cargo_target_linker_env_name}"] = env["CC"] + else: + log.warning(f"Unable to configure Rust cross-compilation for architecture {cargo_target}") + + +def setup_PYO3_cross_compile( + python_dir: Path, + env: MutableMapping[str, str], +) -> None: + # All Python extension modules must therefore be explicitly linked against libpython3.x.so when building for Android. + # See: https://peps.python.org/pep-0738/#linkage + # For projects using PyO3, this requires setting PYO3_CROSS_LIB_DIR to the directory containing libpython3.x.so. + # See: https://pyo3.rs/v0.27.1/building-and-distribution.html#cross-compiling + if env.get("PYO3_CROSS_LIB_DIR"): + log.notice("Not overriding PYO3_CROSS_LIB_DIR as it has already been set") + else: + env["PYO3_CROSS_LIB_DIR"] = str(python_dir / "prefix" / "lib") + log.notice("Setting PYO3_CROSS_LIB_DIR for PyO3 cross-compilation") + + def before_build(state: BuildState) -> None: if state.options.before_build: log.step("Running before_build...")