@@ -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, "\n lib_name={lib_name}" ) . unwrap ( ) ;
499+ }
477500 if let Some ( pointer_width) = self . pointer_width {
478501 write ! ( content, "\n pointer_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