Skip to content

Commit 39c94ce

Browse files
committed
fix: set explicit lib_name in pyo3 config for Android cross-compilation
On Android, pyo3 forces linking libpython. When abi3 is enabled, pyo3's fixup_for_abi3_version downgrades the version to the abi3 minimum (e.g. 3.7) and derives a wrong lib_name like 'python3.7m'. Set lib_name explicitly in the pyo3 config file: 'python3' for abi3 builds (stable ABI) and 'python{major}.{minor}' for non-abi3 builds. See PyO3/pyo3#5960
1 parent b27b7e1 commit 39c94ce

2 files changed

Lines changed: 76 additions & 26 deletions

File tree

src/compile.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ fn configure_pyo3_env(
842842
// and legacy pyo3 versions
843843
build_command.env("PYTHON_SYS_EXECUTABLE", &interpreter.executable);
844844
} else if bridge_model.is_pyo3() && env::var_os("PYO3_CONFIG_FILE").is_none() {
845-
let pyo3_config = interpreter.pyo3_config_file();
845+
let pyo3_config = interpreter.pyo3_config_file(target, bridge_model.is_abi3());
846846
let maturin_target_dir = ensure_target_maturin_dir(&context.project.target_dir);
847847
let config_file = maturin_target_dir.join(format!(
848848
"pyo3-config-{}-{}.{}.txt",

src/python_interpreter/config.rs

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ impl InterpreterConfig {
457457
}
458458

459459
/// Generate pyo3 config file content
460-
pub fn pyo3_config_file(&self) -> String {
460+
pub fn pyo3_config_file(&self, target: &Target, abi3: bool) -> String {
461461
let build_flags = if self.gil_disabled {
462462
"Py_GIL_DISABLED"
463463
} else {
@@ -474,6 +474,29 @@ suppress_build_script_link_lines=false"#,
474474
major = self.major,
475475
minor = self.minor,
476476
);
477+
// On Android, pyo3 forces linking libpython. When abi3 is enabled,
478+
// pyo3's fixup_for_abi3_version downgrades the version to the abi3
479+
// minimum (e.g. 3.7) and derives a wrong lib_name like "python3.7m".
480+
// Set lib_name explicitly so pyo3 uses the correct library.
481+
// For abi3, link against libpython3.so (stable ABI); otherwise use
482+
// the version-specific libpython3.X.so.
483+
// See https://github.com/PyO3/pyo3/issues/5960
484+
if target.is_android() {
485+
let lib_name = if abi3 && matches!(self.interpreter_kind, InterpreterKind::CPython) {
486+
"python3".to_string()
487+
} else {
488+
match self.interpreter_kind {
489+
InterpreterKind::CPython => {
490+
format!("python{}.{}{}", self.major, self.minor, self.abiflags)
491+
}
492+
InterpreterKind::PyPy => {
493+
format!("pypy{}.{}-c", self.major, self.minor)
494+
}
495+
InterpreterKind::GraalPy => "python-native".to_string(),
496+
}
497+
};
498+
write!(content, "\nlib_name={lib_name}").unwrap();
499+
}
477500
if let Some(pointer_width) = self.pointer_width {
478501
write!(content, "\npointer_width={pointer_width}").unwrap();
479502
}
@@ -869,14 +892,10 @@ mod tests {
869892

870893
#[test]
871894
fn test_pyo3_config_file() {
872-
let sysconfig = InterpreterConfig::lookup_one(
873-
&Target::from_resolved_target_triple("x86_64-unknown-linux-gnu").unwrap(),
874-
InterpreterKind::CPython,
875-
(3, 10),
876-
"",
877-
)
878-
.unwrap();
879-
let config_file = sysconfig.pyo3_config_file();
895+
let target = Target::from_resolved_target_triple("x86_64-unknown-linux-gnu").unwrap();
896+
let sysconfig =
897+
InterpreterConfig::lookup_one(&target, InterpreterKind::CPython, (3, 10), "").unwrap();
898+
let config_file = sysconfig.pyo3_config_file(&target, false);
880899
let expected = expect![[r#"
881900
implementation=CPython
882901
version=3.10
@@ -890,15 +909,11 @@ mod tests {
890909

891910
#[test]
892911
fn test_pyo3_config_file_free_threaded_python_3_13() {
893-
let sysconfig = InterpreterConfig::lookup_one(
894-
&Target::from_resolved_target_triple("x86_64-unknown-linux-gnu").unwrap(),
895-
InterpreterKind::CPython,
896-
(3, 13),
897-
"t",
898-
)
899-
.unwrap();
912+
let target = Target::from_resolved_target_triple("x86_64-unknown-linux-gnu").unwrap();
913+
let sysconfig =
914+
InterpreterConfig::lookup_one(&target, InterpreterKind::CPython, (3, 13), "t").unwrap();
900915
assert_eq!(sysconfig.ext_suffix, ".cpython-313t-x86_64-linux-gnu.so");
901-
let config_file = sysconfig.pyo3_config_file();
916+
let config_file = sysconfig.pyo3_config_file(&target, false);
902917
let expected = expect![[r#"
903918
implementation=CPython
904919
version=3.13
@@ -912,15 +927,11 @@ mod tests {
912927

913928
#[test]
914929
fn test_pyo3_config_file_musl_python_3_11() {
915-
let sysconfig = InterpreterConfig::lookup_one(
916-
&Target::from_resolved_target_triple("x86_64-unknown-linux-musl").unwrap(),
917-
InterpreterKind::CPython,
918-
(3, 11),
919-
"",
920-
)
921-
.unwrap();
930+
let target = Target::from_resolved_target_triple("x86_64-unknown-linux-musl").unwrap();
931+
let sysconfig =
932+
InterpreterConfig::lookup_one(&target, InterpreterKind::CPython, (3, 11), "").unwrap();
922933
assert_eq!(sysconfig.ext_suffix, ".cpython-311-x86_64-linux-musl.so");
923-
let config_file = sysconfig.pyo3_config_file();
934+
let config_file = sysconfig.pyo3_config_file(&target, false);
924935
let expected = expect![[r#"
925936
implementation=CPython
926937
version=3.11
@@ -931,4 +942,43 @@ mod tests {
931942
pointer_width=64"#]];
932943
expected.assert_eq(&config_file);
933944
}
945+
946+
#[test]
947+
fn test_pyo3_config_file_android() {
948+
let target = Target::from_resolved_target_triple("aarch64-linux-android").unwrap();
949+
let config = InterpreterConfig {
950+
major: 3,
951+
minor: 14,
952+
interpreter_kind: InterpreterKind::CPython,
953+
abiflags: String::new(),
954+
ext_suffix: ".cpython-314-aarch64-linux-android.so".to_string(),
955+
pointer_width: Some(64),
956+
gil_disabled: false,
957+
};
958+
// Non-abi3: links against version-specific libpython3.14.so
959+
let config_file = config.pyo3_config_file(&target, false);
960+
let expected = expect![[r#"
961+
implementation=CPython
962+
version=3.14
963+
shared=true
964+
abi3=false
965+
build_flags=
966+
suppress_build_script_link_lines=false
967+
lib_name=python3.14
968+
pointer_width=64"#]];
969+
expected.assert_eq(&config_file);
970+
971+
// Abi3: links against stable ABI libpython3.so
972+
let config_file = config.pyo3_config_file(&target, true);
973+
let expected = expect![[r#"
974+
implementation=CPython
975+
version=3.14
976+
shared=true
977+
abi3=false
978+
build_flags=
979+
suppress_build_script_link_lines=false
980+
lib_name=python3
981+
pointer_width=64"#]];
982+
expected.assert_eq(&config_file);
983+
}
934984
}

0 commit comments

Comments
 (0)