https://github.com/python/cpython/commit/7961bbf2bbbd96679eba89419c34128481b9b0ff
commit: 7961bbf2bbbd96679eba89419c34128481b9b0ff
branch: main
author: Stefano Rivera <[email protected]>
committer: encukou <[email protected]>
date: 2026-07-27T15:05:40+02:00
summary:

gh-122931: Allow stable abi3 API extensions to include a multiarch tuple in the 
filename (GH-152461)

This permits stable ABI extensions for multiple architectures to be
co-installed into the same directory, without clashing with each other,
the same way (non-stable ABI) regular extensions can.

It is listed before the current platform-less suffixes since it's more
specific.

The platform is stored in a new pyconfig.h define & sysconfig
variable, SOABI_PLATFORM.
On some known architectures (FreeBSD, Windows), this
will be undefined/zero; these won't have the new tag (yet).

Add SOABI_PLATFORM & ALT_SOABI the info to
`make pythoninfo` as well.

Co-authored-by: Petr Viktorin <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>

files:
A Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.x435Mb.rst
M Doc/whatsnew/3.15.rst
M Lib/test/pythoninfo.py
M Lib/test/test_importlib/extension/test_finder.py
M Lib/test/test_sysconfig.py
M Python/dynload_shlib.c
M configure
M configure.ac
M pyconfig.h.in

diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst
index df2ca138db32b50..250558dd1341a49 100644
--- a/Doc/whatsnew/3.15.rst
+++ b/Doc/whatsnew/3.15.rst
@@ -873,6 +873,14 @@ Other language changes
   imports ``pkg.sub.mod``.
   (Contributed by Gregory P. Smith in :gh:`83065`.)
 
+* File names of Stable ABI extensions that use the ``.so`` suffix may now
+  include a multiarch tuple, for example, ``foo.abi3-x86-64-linux-gnu.so``.
+  This permits stable ABI extensions for multiple architectures to be
+  co-installed into the same directory, without clashing with each
+  other, as regular dynamic extensions do.
+  (Contributed by Stefano Rivera in :gh:`122931`.)
+
+
 
 Default interactive shell
 =========================
diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py
index 13a3199b1f1267b..ea7edb798051567 100644
--- a/Lib/test/pythoninfo.py
+++ b/Lib/test/pythoninfo.py
@@ -570,6 +570,7 @@ def collect_sysconfig(info_add):
 
     for name in (
         'ABIFLAGS',
+        'ALT_SOABI',
         'ANDROID_API_LEVEL',
         'CC',
         'CCSHARED',
@@ -595,6 +596,7 @@ def collect_sysconfig(info_add):
         'Py_REMOTE_DEBUG',
         'SHELL',
         'SOABI',
+        'SOABI_PLATFORM',
         'TEST_MODULES',
         'VAPTH',
         'abs_builddir',
@@ -1315,6 +1317,12 @@ def collect_system(info_add):
             info_add('system.hardware', hardware)
 
 
+def collect_importlib(info_add):
+    import importlib.machinery
+    info_add('importlib.extension_suffixes',
+             importlib.machinery.EXTENSION_SUFFIXES)
+
+
 def collect_info(info):
     error = False
     info_add = info.add
@@ -1357,6 +1365,7 @@ def collect_info(info):
         collect_zstd,
         collect_libregrtest_utils,
         collect_system,
+        collect_importlib,
 
         # Collecting from tests should be last as they have side effects.
         collect_test_socket,
diff --git a/Lib/test/test_importlib/extension/test_finder.py 
b/Lib/test/test_importlib/extension/test_finder.py
index dc77fa78a203fdb..e33c0465654607f 100644
--- a/Lib/test/test_importlib/extension/test_finder.py
+++ b/Lib/test/test_importlib/extension/test_finder.py
@@ -5,6 +5,7 @@
 
 import unittest
 import sys
+import sysconfig
 
 
 class FinderTests(abc.FinderTests):
@@ -61,6 +62,7 @@ def test_failure(self):
 
     def test_abi3_extension_suffixes(self):
         suffixes = self.machinery.EXTENSION_SUFFIXES
+        platform = sysconfig.get_config_var("SOABI_PLATFORM")
         if 'win32' in sys.platform:
             # Either "_d.pyd" or ".pyd" must be in suffixes
             self.assertTrue({"_d.pyd", ".pyd"}.intersection(suffixes))
@@ -73,6 +75,13 @@ def test_abi3_extension_suffixes(self):
                 self.assertIn(".abi3.so", suffixes)
             self.assertIn(".abi3t.so", suffixes)
 
+            if platform:
+                if Py_GIL_DISABLED:
+                    self.assertNotIn(f".abi3-{platform}.so", suffixes)
+                else:
+                    self.assertIn(f".abi3-{platform}.so", suffixes)
+                self.assertIn(f".abi3t-{platform}.so", suffixes)
+
 
 (Frozen_FinderTests,
  Source_FinderTests
diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
index e6f99581f0b7a66..9bb3e326ff3e952 100644
--- a/Lib/test/test_sysconfig.py
+++ b/Lib/test/test_sysconfig.py
@@ -457,6 +457,15 @@ def test_soabi(self):
         soabi = sysconfig.get_config_var('SOABI')
         self.assertIn(soabi, _imp.extension_suffixes()[0])
 
+    @unittest.skipIf(not _imp.extension_suffixes(), "stub loader has no 
suffixes")
+    @unittest.skipIf(sys.platform == "win32", "Does not apply to Windows")
+    @unittest.skipIf(sysconfig.get_config_var('SOABI_PLATFORM') == 0,
+                     "SOABI_PLATFORM is undefined")
+    def test_soabi_platform(self):
+        soabi_platform = sysconfig.get_config_var('SOABI_PLATFORM')
+        soabi = sysconfig.get_config_var('SOABI')
+        self.assertIn(soabi_platform, soabi)
+
     def test_library(self):
         library = sysconfig.get_config_var('LIBRARY')
         ldlibrary = sysconfig.get_config_var('LDLIBRARY')
diff --git 
a/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.x435Mb.rst 
b/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.x435Mb.rst
new file mode 100644
index 000000000000000..ff972aaefc74268
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.x435Mb.rst
@@ -0,0 +1 @@
+Allow importing stable ABI C extensions that include a multiarch tuple in 
their filename, e.g. ``foo.abi3-x86-64-linux-gnu.so``.
diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c
index 0ff88ad330fd09c..f7f7c9229200857 100644
--- a/Python/dynload_shlib.c
+++ b/Python/dynload_shlib.c
@@ -46,8 +46,14 @@ const char *_PyImport_DynLoadFiletab[] = {
     "." ALT_SOABI ".so",
 #endif
 #ifndef Py_GIL_DISABLED
+#ifdef SOABI_PLATFORM
+    ".abi" PYTHON_ABI_STRING "-" SOABI_PLATFORM ".so",
+#endif  /* SOABI_PLATFORM */
     ".abi" PYTHON_ABI_STRING ".so",
 #endif  /* Py_GIL_DISABLED */
+#ifdef SOABI_PLATFORM
+    ".abi" PYTHON_ABI_STRING "t-" SOABI_PLATFORM ".so",
+#endif  /* SOABI_PLATFORM */
     ".abi" PYTHON_ABI_STRING "t.so",
     ".so",
 #endif  /* __CYGWIN__ */
diff --git a/configure b/configure
index dc23b9f7c20da2f..69d76f7b9f2dba2 100755
--- a/configure
+++ b/configure
@@ -7395,6 +7395,12 @@ case $ac_sys_system in #(
  ;;
 esac
 
+if test x$SOABI_PLATFORM != x; then
+
+printf "%s\n" "#define SOABI_PLATFORM \"${SOABI_PLATFORM}\"" >>confdefs.h
+
+fi
+
 if test x$MULTIARCH != x; then
   MULTIARCH_CPPFLAGS="-DMULTIARCH=\\\"$MULTIARCH\\\""
 fi
diff --git a/configure.ac b/configure.ac
index 5a59e70d64bab31..93b211eef749880 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1221,6 +1221,10 @@ AS_CASE([$ac_sys_system],
   [SOABI_PLATFORM=$PLATFORM_TRIPLET]
 )
 
+if test x$SOABI_PLATFORM != x; then
+    AC_DEFINE_UNQUOTED([SOABI_PLATFORM], ["${SOABI_PLATFORM}"], [Platform tag, 
used in binary module extension filenames.])
+fi
+
 if test x$MULTIARCH != x; then
   MULTIARCH_CPPFLAGS="-DMULTIARCH=\\\"$MULTIARCH\\\""
 fi
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 25c4842d25e8a67..2658fe8116781db 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -1968,6 +1968,9 @@
 /* The size of '_Bool', as computed by sizeof. */
 #undef SIZEOF__BOOL
 
+/* Platform tag, used in binary module extension filenames. */
+#undef SOABI_PLATFORM
+
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to