From 989c77951177b92c1a49ed6358f4d79ef0240194 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sun, 11 Aug 2024 10:43:45 +0200 Subject: [PATCH 01/14] gh-122917 Allow stable API extensions to include a multiarch tuple in the filename 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 below the current .abi3 suffix because setuptools will select the first suffix containing .abi3, as the target filename. We do this to protect older Python versions predating this patch. --- Doc/whatsnew/3.16.rst | 8 ++++++++ .../C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst | 2 ++ Python/dynload_shlib.c | 6 ++++++ configure | 4 ++++ configure.ac | 2 ++ pyconfig.h.in | 3 +++ 6 files changed, 25 insertions(+) create mode 100644 Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 80f13e4d759dd30..9169ca76c85bf1c 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -75,6 +75,14 @@ New features Other language changes ====================== +* Stable ABI extensions may now include a multiarch tuple in the + filename, e.g. ``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. Build tools will not generate + these multiarch tagged filenames, by default, while still supporting + older Python versions that don't recognize these filenames. + (Contributed by Stefano Rivera in :gh:`122931`.) New modules diff --git a/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst b/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst new file mode 100644 index 000000000000000..d1caad2e98482d6 --- /dev/null +++ b/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst @@ -0,0 +1,2 @@ +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..e2dc8f9e0fc780d 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -47,8 +47,14 @@ const char *_PyImport_DynLoadFiletab[] = { #endif #ifndef Py_GIL_DISABLED ".abi" PYTHON_ABI_STRING ".so", +#ifdef SOABI_PLATFORM + ".abi" PYTHON_ABI_STRING "-" SOABI_PLATFORM ".so", +#endif /* SOABI_PLATFORM */ #endif /* Py_GIL_DISABLED */ ".abi" PYTHON_ABI_STRING "t.so", +#ifdef SOABI_PLATFORM + ".abi" PYTHON_ABI_STRING "t-" SOABI_PLATFORM ".so", +#endif /* SOABI_PLATFORM */ ".so", #endif /* __CYGWIN__ */ NULL, diff --git a/configure b/configure index e96b87989793a8f..0dc65b339c97611 100755 --- a/configure +++ b/configure @@ -7266,6 +7266,10 @@ case $ac_sys_system in #( ;; esac + +printf "%s\n" "#define SOABI_PLATFORM \"${SOABI_PLATFORM}\"" >>confdefs.h + + if test x$MULTIARCH != x; then MULTIARCH_CPPFLAGS="-DMULTIARCH=\\\"$MULTIARCH\\\"" fi diff --git a/configure.ac b/configure.ac index cd1883f0195c47e..c803c3b9ab8e208 100644 --- a/configure.ac +++ b/configure.ac @@ -1212,6 +1212,8 @@ AS_CASE([$ac_sys_system], [SOABI_PLATFORM=$PLATFORM_TRIPLET] ) +AC_DEFINE_UNQUOTED([SOABI_PLATFORM], ["${SOABI_PLATFORM}"], [Platform tag, used in binary module extension filenames.]) + if test x$MULTIARCH != x; then MULTIARCH_CPPFLAGS="-DMULTIARCH=\\\"$MULTIARCH\\\"" fi diff --git a/pyconfig.h.in b/pyconfig.h.in index a05cd8ecc91e197..b2d343735e87ce6 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1890,6 +1890,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 From 39fb3a413e4da69ffe2c0b12f3b33732a5908537 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Mon, 18 May 2026 17:23:07 -0700 Subject: [PATCH 02/14] Order the multiarch-tagged extensions first --- Doc/whatsnew/3.16.rst | 6 +++--- Python/dynload_shlib.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 9169ca76c85bf1c..36c3e872abe8b5c 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -79,9 +79,9 @@ Other language changes filename, e.g. ``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. Build tools will not generate - these multiarch tagged filenames, by default, while still supporting - older Python versions that don't recognize these filenames. + other, as regular dynamic extensions do. Build may tools will generate + these multiarch tagged filenames, by default, when targeting + compatibility with at least Python 3.15. (Contributed by Stefano Rivera in :gh:`122931`.) diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index e2dc8f9e0fc780d..f7f7c9229200857 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -46,15 +46,15 @@ const char *_PyImport_DynLoadFiletab[] = { "." ALT_SOABI ".so", #endif #ifndef Py_GIL_DISABLED - ".abi" PYTHON_ABI_STRING ".so", #ifdef SOABI_PLATFORM ".abi" PYTHON_ABI_STRING "-" SOABI_PLATFORM ".so", #endif /* SOABI_PLATFORM */ + ".abi" PYTHON_ABI_STRING ".so", #endif /* Py_GIL_DISABLED */ - ".abi" PYTHON_ABI_STRING "t.so", #ifdef SOABI_PLATFORM ".abi" PYTHON_ABI_STRING "t-" SOABI_PLATFORM ".so", #endif /* SOABI_PLATFORM */ + ".abi" PYTHON_ABI_STRING "t.so", ".so", #endif /* __CYGWIN__ */ NULL, From 8324a7f15f8a9d12926df8fdbab4076bd5393782 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Tue, 19 May 2026 23:49:42 -0400 Subject: [PATCH 03/14] Test for presence of multiarch extension suffixes --- Lib/test/test_importlib/extension/test_finder.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py index dc77fa78a203fdb..da7f31d98e4bd46 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): @@ -68,11 +69,22 @@ def test_abi3_extension_suffixes(self): pass else: if Py_GIL_DISABLED: - self.assertNotIn(".abi3.so", suffixes) + self.assertFalse(any(".abi3" in suffix) for suffix in suffixes) else: self.assertIn(".abi3.so", suffixes) self.assertIn(".abi3t.so", suffixes) + @unittest.skipIf( + not sysconfig.get_config_var("SOABI_PLATFORM").strip('"'), + "Linux-only test" + ) + def test_multiarch_abi3_extension_suffixes(self): + suffixes = self.machinery.EXTENSION_SUFFIXES + platform = sysconfig.get_config_var("SOABI_PLATFORM").strip('"') + if Py_GIL_DISABLED: + self.assertIn(f".abi3-{platform}.so", suffixes) + self.assertIn(f".abi3t-{platform}.so", suffixes) + (Frozen_FinderTests, Source_FinderTests From 5684c14b9ed552b704a484490b5ad984a4bcb457 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 20 May 2026 11:10:16 -0400 Subject: [PATCH 04/14] Fix editing error in NEWS and improve clarity --- Doc/whatsnew/3.16.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 36c3e872abe8b5c..bbdd2b87a3c1735 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -75,11 +75,11 @@ New features Other language changes ====================== -* Stable ABI extensions may now include a multiarch tuple in the +* Stable ABI extensions now include a multiarch tuple in the filename, e.g. ``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. Build may tools will generate + other, as regular dynamic extensions do. Build tools will generate these multiarch tagged filenames, by default, when targeting compatibility with at least Python 3.15. (Contributed by Stefano Rivera in :gh:`122931`.) From dfddd07fc5539ae00546108fc516386f498e1a39 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Wed, 20 May 2026 11:41:42 -0400 Subject: [PATCH 05/14] Fix up the test --- Lib/test/test_importlib/extension/test_finder.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py index da7f31d98e4bd46..686f502bf5b3686 100644 --- a/Lib/test/test_importlib/extension/test_finder.py +++ b/Lib/test/test_importlib/extension/test_finder.py @@ -69,19 +69,21 @@ def test_abi3_extension_suffixes(self): pass else: if Py_GIL_DISABLED: - self.assertFalse(any(".abi3" in suffix) for suffix in suffixes) + self.assertNotIn(".abi3.so", suffixes) else: self.assertIn(".abi3.so", suffixes) self.assertIn(".abi3t.so", suffixes) @unittest.skipIf( - not sysconfig.get_config_var("SOABI_PLATFORM").strip('"'), + not (sysconfig.get_config_var("SOABI_PLATFORM") or "").strip('"'), "Linux-only test" ) def test_multiarch_abi3_extension_suffixes(self): suffixes = self.machinery.EXTENSION_SUFFIXES platform = sysconfig.get_config_var("SOABI_PLATFORM").strip('"') 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) From 67e2548a837ee7bff9eeacdcac861ab570a5dbc2 Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Fri, 26 Jun 2026 08:08:56 -0400 Subject: [PATCH 06/14] Only target abi3t (for expediency) --- Doc/whatsnew/3.16.rst | 8 -------- .../test_importlib/extension/test_finder.py | 19 +++++-------------- ...-08-12-09-48-04.gh-issue-122931.QwHc2l.rst | 3 +-- Python/dynload_shlib.c | 6 ++---- 4 files changed, 8 insertions(+), 28 deletions(-) diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index bbdd2b87a3c1735..80f13e4d759dd30 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -75,14 +75,6 @@ New features Other language changes ====================== -* Stable ABI extensions now include a multiarch tuple in the - filename, e.g. ``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. Build tools will generate - these multiarch tagged filenames, by default, when targeting - compatibility with at least Python 3.15. - (Contributed by Stefano Rivera in :gh:`122931`.) New modules diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py index 686f502bf5b3686..c460ff01d9f0d26 100644 --- a/Lib/test/test_importlib/extension/test_finder.py +++ b/Lib/test/test_importlib/extension/test_finder.py @@ -62,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)) @@ -72,20 +73,10 @@ def test_abi3_extension_suffixes(self): self.assertNotIn(".abi3.so", suffixes) else: self.assertIn(".abi3.so", suffixes) - self.assertIn(".abi3t.so", suffixes) - - @unittest.skipIf( - not (sysconfig.get_config_var("SOABI_PLATFORM") or "").strip('"'), - "Linux-only test" - ) - def test_multiarch_abi3_extension_suffixes(self): - suffixes = self.machinery.EXTENSION_SUFFIXES - platform = sysconfig.get_config_var("SOABI_PLATFORM").strip('"') - 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) + if platform: + self.assertIn(f".abi3t-{platform}.so", suffixes) + else: + self.assertIn(".abi3t.so", suffixes) (Frozen_FinderTests, diff --git a/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst b/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst index d1caad2e98482d6..734547c86dbfbda 100644 --- a/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst +++ b/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst @@ -1,2 +1 @@ -Allow importing stable ABI C extensions that include a multiarch tuple -in their filename, e.g. ``foo.abi3-x86-64-linux-gnu.so``. +Linux: Include multiarch tuples in ``abi3t`` stable ABI C extension filenames, e.g. ``foo.abi3t-x86-64-linux-gnu.so``. diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index f7f7c9229200857..a60cd1850c7df14 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -46,15 +46,13 @@ 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 */ +#else ".abi" PYTHON_ABI_STRING "t.so", +#endif /* SOABI_PLATFORM */ ".so", #endif /* __CYGWIN__ */ NULL, From 52e251a5d1f40804eb55ca02b56d8b236a9c607b Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 27 Jun 2026 18:35:16 -0400 Subject: [PATCH 07/14] gh-122931: Allow stable API extensions to include a multiarch tuple in the filename This permits `abi3` 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 .abi3 suffix because .abi3 extensions are only compatible with future Python releases, not older versions. This follows on from #122917 which was reduced down to just targetting `abi3t` --- Doc/whatsnew/3.16.rst | 8 ++++++++ Lib/test/test_importlib/extension/test_finder.py | 10 ++++++---- .../2024-08-12-09-48-04.gh-issue-122931.x435Mb.rst | 1 + Python/dynload_shlib.c | 3 +++ 4 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.x435Mb.rst diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index 80f13e4d759dd30..bbdd2b87a3c1735 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -75,6 +75,14 @@ New features Other language changes ====================== +* Stable ABI extensions now include a multiarch tuple in the + filename, e.g. ``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. Build tools will generate + these multiarch tagged filenames, by default, when targeting + compatibility with at least Python 3.15. + (Contributed by Stefano Rivera in :gh:`122931`.) New modules diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py index c460ff01d9f0d26..8b3452a8a1b1faa 100644 --- a/Lib/test/test_importlib/extension/test_finder.py +++ b/Lib/test/test_importlib/extension/test_finder.py @@ -69,14 +69,16 @@ def test_abi3_extension_suffixes(self): elif 'cygwin' in sys.platform: pass else: - if Py_GIL_DISABLED: - self.assertNotIn(".abi3.so", suffixes) - else: - self.assertIn(".abi3.so", suffixes) if platform: + abi3_suffix = f".abi3-{platform}.so" self.assertIn(f".abi3t-{platform}.so", suffixes) else: + abi3_suffix = ".abi3.so" self.assertIn(".abi3t.so", suffixes) + if Py_GIL_DISABLED: + self.assertNotIn(abi3_suffix, suffixes) + else: + self.assertIn(abi3_suffix, suffixes) (Frozen_FinderTests, 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 a60cd1850c7df14..19f6c852a7980cc 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -46,6 +46,9 @@ 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 From 02ece69a1c61cd77c52489df8c0bcbe0c7a60351 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 18 Jul 2026 15:44:08 +0200 Subject: [PATCH 08/14] Allow bare abi3/abi3t suffix --- .../test_importlib/extension/test_finder.py | 18 ++++++++++-------- Python/dynload_shlib.c | 3 +-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py index 8b3452a8a1b1faa..beafc771e6c0fa9 100644 --- a/Lib/test/test_importlib/extension/test_finder.py +++ b/Lib/test/test_importlib/extension/test_finder.py @@ -69,16 +69,18 @@ def test_abi3_extension_suffixes(self): elif 'cygwin' in sys.platform: pass else: - if platform: - abi3_suffix = f".abi3-{platform}.so" - self.assertIn(f".abi3t-{platform}.so", suffixes) - else: - abi3_suffix = ".abi3.so" - self.assertIn(".abi3t.so", suffixes) if Py_GIL_DISABLED: - self.assertNotIn(abi3_suffix, suffixes) + self.assertNotIn(".abi3.so", suffixes) else: - self.assertIn(abi3_suffix, suffixes) + self.assertIn(".abi3.so", suffixes) + self.assertIn(".abi3t.so", suffixes) + + if platform: + if Py_GIL_DISABLED: + self.assertNotIn(f".abi3.so-{platform}", suffixes) + else: + self.assertIn(f".abi3.so-{platform}", suffixes) + self.assertIn(f".abi3t-{platform}.so", suffixes) (Frozen_FinderTests, diff --git a/Python/dynload_shlib.c b/Python/dynload_shlib.c index 19f6c852a7980cc..f7f7c9229200857 100644 --- a/Python/dynload_shlib.c +++ b/Python/dynload_shlib.c @@ -53,9 +53,8 @@ const char *_PyImport_DynLoadFiletab[] = { #endif /* Py_GIL_DISABLED */ #ifdef SOABI_PLATFORM ".abi" PYTHON_ABI_STRING "t-" SOABI_PLATFORM ".so", -#else - ".abi" PYTHON_ABI_STRING "t.so", #endif /* SOABI_PLATFORM */ + ".abi" PYTHON_ABI_STRING "t.so", ".so", #endif /* __CYGWIN__ */ NULL, From b5ca9ebf0f7c21f0856227ff1027ac4f54497eff Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 18 Jul 2026 15:48:56 +0200 Subject: [PATCH 09/14] Test that SOABI_PLATFORM is in SOABI --- Lib/test/test_sysconfig.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index e6f99581f0b7a66..f45ae7a7ab2dfdd 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -457,6 +457,13 @@ 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") + 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') From cd636729d6c221c31f4dceb0fbe608400139c559 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 18 Jul 2026 16:12:10 +0200 Subject: [PATCH 10/14] Move What's New to 3.15; remove redundant NEWS entry --- Doc/whatsnew/3.15.rst | 8 ++++++++ Doc/whatsnew/3.16.rst | 8 -------- .../C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst | 1 - 3 files changed, 8 insertions(+), 9 deletions(-) delete mode 100644 Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index db6903da9f63444..877842b0c0b669b 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/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst index bbdd2b87a3c1735..80f13e4d759dd30 100644 --- a/Doc/whatsnew/3.16.rst +++ b/Doc/whatsnew/3.16.rst @@ -75,14 +75,6 @@ New features Other language changes ====================== -* Stable ABI extensions now include a multiarch tuple in the - filename, e.g. ``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. Build tools will generate - these multiarch tagged filenames, by default, when targeting - compatibility with at least Python 3.15. - (Contributed by Stefano Rivera in :gh:`122931`.) New modules diff --git a/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst b/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst deleted file mode 100644 index 734547c86dbfbda..000000000000000 --- a/Misc/NEWS.d/next/C_API/2024-08-12-09-48-04.gh-issue-122931.QwHc2l.rst +++ /dev/null @@ -1 +0,0 @@ -Linux: Include multiarch tuples in ``abi3t`` stable ABI C extension filenames, e.g. ``foo.abi3t-x86-64-linux-gnu.so``. From e20b0b2cfbc06e57bd4701458692b36d410efe2e Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Sat, 18 Jul 2026 17:09:39 +0200 Subject: [PATCH 11/14] Fix the embarrassing mistake --- Lib/test/test_importlib/extension/test_finder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_importlib/extension/test_finder.py b/Lib/test/test_importlib/extension/test_finder.py index beafc771e6c0fa9..e33c0465654607f 100644 --- a/Lib/test/test_importlib/extension/test_finder.py +++ b/Lib/test/test_importlib/extension/test_finder.py @@ -77,9 +77,9 @@ def test_abi3_extension_suffixes(self): if platform: if Py_GIL_DISABLED: - self.assertNotIn(f".abi3.so-{platform}", suffixes) + self.assertNotIn(f".abi3-{platform}.so", suffixes) else: - self.assertIn(f".abi3.so-{platform}", suffixes) + self.assertIn(f".abi3-{platform}.so", suffixes) self.assertIn(f".abi3t-{platform}.so", suffixes) From f9e38176aa629298a1b6d710fb9a75d00b00e1a4 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 18 Jul 2026 18:44:14 +0200 Subject: [PATCH 12/14] Add SOABI_PLATFORM to test.pythoninfo Add ALT_SOABI and SOABI_PLATFORM to test.pythoninfo. Add also EXTENSION_SUFFIXES of importlib.machinery. --- Lib/test/pythoninfo.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index 3227b91bd82a863..a870b3e52438697 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', @@ -1316,6 +1318,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 @@ -1358,6 +1366,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, From 0ebab06ed018d116685efe28325ef6c2e91dbfeb Mon Sep 17 00:00:00 2001 From: Stefano Rivera Date: Sat, 18 Jul 2026 16:19:59 -0300 Subject: [PATCH 13/14] Only define SOABI_PLATFORM if it is set --- configure | 2 ++ configure.ac | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/configure b/configure index ba3bfaed7c4772c..2041a15b1a1486c 100755 --- a/configure +++ b/configure @@ -7266,9 +7266,11 @@ 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\\\"" diff --git a/configure.ac b/configure.ac index 2d6672e3231f596..c30d98af28aa07c 100644 --- a/configure.ac +++ b/configure.ac @@ -1212,7 +1212,9 @@ AS_CASE([$ac_sys_system], [SOABI_PLATFORM=$PLATFORM_TRIPLET] ) -AC_DEFINE_UNQUOTED([SOABI_PLATFORM], ["${SOABI_PLATFORM}"], [Platform tag, used in binary module extension filenames.]) +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\\\"" From e59ddbc65fe5841c206d6938cc2e6e44ad727761 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 27 Jul 2026 13:26:02 +0200 Subject: [PATCH 14/14] Skip test if SOABI_PLATFORM is undefined --- Lib/test/test_sysconfig.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index f45ae7a7ab2dfdd..9bb3e326ff3e952 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -459,6 +459,8 @@ def test_soabi(self): @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')