diff --git a/src/python_interpreter/config.rs b/src/python_interpreter/config.rs index 6f5f17ac3..560c15660 100644 --- a/src/python_interpreter/config.rs +++ b/src/python_interpreter/config.rs @@ -372,57 +372,59 @@ impl InterpreterConfig { }), }; let file_ext = if target.is_windows() { "pyd" } else { "so" }; - let ext_suffix = if target.is_linux() || target.is_macos() || target.is_hurd() { - let target_env = target.get_python_target_env(interpreter_kind, (major, minor)); - match interpreter_kind { - InterpreterKind::CPython => ext_suffix.unwrap_or_else(|| { - // Eg: .cpython-38-x86_64-linux-gnu.so - format!( - ".cpython-{}-{}-{}-{}.{}", - abi_tag, - target.get_python_ext_arch(interpreter_kind), - target.get_python_os(), - target_env, - file_ext, - ) - }), - InterpreterKind::PyPy => ext_suffix.unwrap_or_else(|| { - // Eg: .pypy38-pp73-x86_64-linux-gnu.so + let ext_suffix = + if target.is_linux() || target.is_android() || target.is_macos() || target.is_hurd() { + let target_env = target.get_python_target_env(interpreter_kind, (major, minor)); + match interpreter_kind { + InterpreterKind::CPython => ext_suffix.unwrap_or_else(|| { + // Eg: .cpython-38-x86_64-linux-gnu.so + format!( + ".cpython-{}-{}-{}-{}.{}", + abi_tag, + target.get_python_ext_arch(interpreter_kind), + target.get_python_os(), + target_env, + file_ext, + ) + }), + InterpreterKind::PyPy => ext_suffix.unwrap_or_else(|| { + // Eg: .pypy38-pp73-x86_64-linux-gnu.so + format!( + ".pypy{}{}-{}-{}-{}-{}.{}", + major, + minor, + abi_tag, + target.get_python_ext_arch(interpreter_kind), + target.get_python_os(), + target_env, + file_ext, + ) + }), + InterpreterKind::GraalPy => ext_suffix.unwrap_or_else(|| { + // e.g. .graalpy230-310-native-x86_64-linux.so + format!( + ".{}-{}-{}.{}", + abi_tag.replace('_', "-"), + target.get_python_ext_arch(interpreter_kind), + target.get_python_os(), + file_ext, + ) + }), + } + } else if target.is_emscripten() && matches!(interpreter_kind, InterpreterKind::CPython) + { + ext_suffix.unwrap_or_else(|| { format!( - ".pypy{}{}-{}-{}-{}-{}.{}", - major, - minor, + ".cpython-{}-{}-{}.{}", abi_tag, target.get_python_ext_arch(interpreter_kind), target.get_python_os(), - target_env, - file_ext, + file_ext ) - }), - InterpreterKind::GraalPy => ext_suffix.unwrap_or_else(|| { - // e.g. .graalpy230-310-native-x86_64-linux.so - format!( - ".{}-{}-{}.{}", - abi_tag.replace('_', "-"), - target.get_python_ext_arch(interpreter_kind), - target.get_python_os(), - file_ext, - ) - }), - } - } else if target.is_emscripten() && matches!(interpreter_kind, InterpreterKind::CPython) { - ext_suffix.unwrap_or_else(|| { - format!( - ".cpython-{}-{}-{}.{}", - abi_tag, - target.get_python_ext_arch(interpreter_kind), - target.get_python_os(), - file_ext - ) - }) - } else { - ext_suffix.context("missing value for ext_suffix")? - }; + }) + } else { + ext_suffix.context("missing value for ext_suffix")? + }; let gil_disabled = build_flags .map(|flags| flags.contains("Py_GIL_DISABLED")) .unwrap_or(false); diff --git a/src/python_interpreter/mod.rs b/src/python_interpreter/mod.rs index 780182617..681b48adb 100644 --- a/src/python_interpreter/mod.rs +++ b/src/python_interpreter/mod.rs @@ -295,11 +295,20 @@ fn fun_with_abiflags( && !(target.get_python_os() == "cygwin" && message.system.to_lowercase().starts_with("cygwin")) { - bail!( - "platform.system() in python, {}, and the rust target, {:?}, don't match ಠ_ಠ", - message.system, - target, - ) + // Python versions <= 3.12 used to report platform.system() as "linux". Only on Python versions + // >= 3.13, platform.system() reports as "android". So maintain backwards compatibility with + // Python 3.12 when compiling on Android environment (for e.g. Termux) + let is_android_compat = target.get_python_os() == "android" + && message.system == "linux" + && message.major == 3 + && message.minor <= 12; + if !is_android_compat { + bail!( + "platform.system() in python, {}, and the rust target, {:?}, don't match ಠ_ಠ", + message.system, + target, + ) + } } if message.major != 3 || message.minor < 7 { diff --git a/src/target/mod.rs b/src/target/mod.rs index 8838d84a5..ba0c38110 100644 --- a/src/target/mod.rs +++ b/src/target/mod.rs @@ -44,6 +44,7 @@ pub enum Os { Aix, Hurd, Cygwin, + Android, } impl fmt::Display for Os { @@ -65,6 +66,7 @@ impl fmt::Display for Os { Os::Aix => write!(f, "AIX"), Os::Hurd => write!(f, "Hurd"), Os::Cygwin => write!(f, "Cygwin"), + Os::Android => write!(f, "Android"), } } } @@ -160,6 +162,14 @@ impl Arch { // Returns the set of supported architectures for each operating system fn get_supported_architectures(os: &Os) -> Vec { match os { + Os::Android => vec![ + Arch::Aarch64, + Arch::Armv5teL, + Arch::Armv6L, + Arch::Armv7L, + Arch::X86, + Arch::X86_64, + ], Os::Linux => vec![ Arch::Aarch64, Arch::Armv5teL, @@ -277,7 +287,10 @@ impl Target { .map_err(|_| format_err!("Unknown target triple {}", target_triple))?; let os = match platform.operating_system { - OperatingSystem::Linux => Os::Linux, + OperatingSystem::Linux => match platform.environment { + Environment::Android | Environment::Androideabi => Os::Android, + _ => Os::Linux, + }, OperatingSystem::Windows => Os::Windows, OperatingSystem::MacOSX(_) | OperatingSystem::Darwin(_) => Os::Macos, OperatingSystem::IOS(_) => Os::Ios, @@ -457,6 +470,7 @@ impl Target { /// Returns the name python uses in `sys.platform` for this os pub fn get_python_os(&self) -> &str { match self.os { + Os::Android => "android", Os::Windows => "windows", Os::Linux => "linux", Os::Macos => "darwin", @@ -570,7 +584,8 @@ impl Target { | Os::Wasi | Os::Aix | Os::Hurd - | Os::Cygwin => true, + | Os::Cygwin + | Os::Android => true, } } @@ -670,6 +685,11 @@ impl Target { self.os == Os::Aix } + /// Returns true if we're building a binary for Android + pub fn is_android(&self) -> bool { + self.os == Os::Android + } + /// Returns true if the current platform's target env is Musl #[inline] pub fn is_musl_libc(&self) -> bool { diff --git a/src/target/pypi_tags.rs b/src/target/pypi_tags.rs index 9914ad1e7..040f886c0 100644 --- a/src/target/pypi_tags.rs +++ b/src/target/pypi_tags.rs @@ -51,7 +51,7 @@ pub fn is_arch_supported_by_pypi(target: &Target) -> bool { // PyPI allows iOS with arm64 and x86_64 (simulator) matches!(normalized_arch, "arm64" | "x86_64") } - Os::Linux if target.target_triple().contains("android") => { + Os::Android => { // Android target triples map to specific platform tag architectures let android_arch = match arch.as_str() { "armv7l" => "armeabi_v7a", // armv7 little-endian