Skip to content

Commit 8462643

Browse files
encukouwillingcJelleZijlstraAA-Turner
authored
PEP 803: Stable ABI for Free-Threaded Builds (GH-4556)
Co-authored-by: Carol Willing <carolcode@willingconsulting.com> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com> Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
1 parent 0e4aee4 commit 8462643

File tree

2 files changed

+334
-0
lines changed

2 files changed

+334
-0
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,7 @@ peps/pep-0799.rst @pablogsal
678678
peps/pep-0800.rst @JelleZijlstra
679679
peps/pep-0801.rst @warsaw
680680
peps/pep-0802.rst @AA-Turner
681+
peps/pep-0803.rst @encukou
681682
# ...
682683
peps/pep-2026.rst @hugovk
683684
# ...

peps/pep-0803.rst

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
PEP: 803
2+
Title: Stable ABI for Free-Threaded Builds
3+
Author: Petr Viktorin <encukou@gmail.com>
4+
Discussions-To: Pending
5+
Status: Draft
6+
Type: Standards Track
7+
Requires: 703, 793, 697
8+
Created: 19-Aug-2025
9+
Python-Version: 3.15
10+
11+
12+
Abstract
13+
========
14+
15+
Version 3.15 of the Stable ABI will be compatible with both free-threaded and
16+
GIL-enabled builds.
17+
To allow this, the :c:type:`PyObject` internal structure and related APIs
18+
will be removed from version 3.15 of the Limited API, requiring migration to
19+
new API for common tasks like defining modules and most classes.
20+
21+
22+
Terminology
23+
===========
24+
25+
This PEP uses “GIL-enabled build” as an antonym to “free-threaded build”,
26+
that is, an interpreter or extension built without ``Py_GIL_DISABLED``.
27+
28+
29+
Motivation
30+
==========
31+
32+
The Stable ABI is currently not available for free-threaded builds.
33+
Extensions will fail to build when :c:macro:`Py_LIMITED_API` is defined,
34+
and extensions built for GIL-enabled builds of CPython will fail to load
35+
(or crash) on free-threaded builds.
36+
37+
In its `acceptance post <https://discuss.python.org/t/84319/123>`__
38+
for :pep:`779`, the Steering Council stated that it “expects that Stable ABI
39+
for free-threading should be prepared and defined for Python 3.15”.
40+
41+
This PEP proposes the Stable ABI for free-threading.
42+
43+
44+
Background
45+
----------
46+
47+
Python's Stable ABI, as defined in :pep:`384` and :pep:`652`, provides a way to
48+
compile extension modules that can be loaded on multiple minor versions of the
49+
CPython interpreter.
50+
Several projects use this to limit the number of
51+
:ref:`wheels <packaging:binary-distribution-format>` (binary artefacts)
52+
that need to be built and distributed for each release, and/or to make it
53+
easier to test with pre-release versions of Python.
54+
55+
With free-threading builds (:pep:`703`) being on track to eventually become
56+
the default (:pep:`779`), we need a way to make the Stable ABI available
57+
to those builds.
58+
59+
To build against the Stable ABI, the extension must use a *Limited API*,
60+
that is, only a subset of the functions, structures, etc. that CPython
61+
exposes.
62+
The Limited API is versioned, and building against Limited API 3.X
63+
yields an extension that is ABI-compatible with CPython 3.X and *any* later
64+
version (though bugs in CPython sometimes cause incompatibilities in practice).
65+
Also, the Limited API is not “stable”: newer versions may remove API that
66+
were a part of older versions.
67+
68+
This PEP proposes the most significant such removal to date.
69+
70+
71+
Rationale
72+
=========
73+
74+
The design in this PEP makes several assumptions:
75+
76+
One ABI
77+
A single compiled extension module should support both
78+
free-threaded and GIL-enabled builds.
79+
80+
No backwards compatibility
81+
The new limited API will not support CPython 3.14 and below.
82+
Projects that need this support can build separate extensions specifically
83+
for the 3.14 free-threaded interpreter, and for older stable ABI versions.
84+
85+
API changes are OK
86+
The new Limited API may require extension authors to make significant
87+
changes to their code.
88+
Projects that cannot do this (yet) can continue using Limited API 3.14,
89+
which will yield extensions compatible with GIL-enabled builds only.
90+
91+
No extra configuration
92+
We do not introduce new “knobs” that influence what API is available
93+
and what the ABI is compatible with.
94+
95+
96+
Specification
97+
=============
98+
99+
100+
Opaque PyObject
101+
---------------
102+
103+
Version 3.15 of the Limited API will:
104+
105+
- make the following structures *opaque* (or in C terminology, *incomplete
106+
types*):
107+
108+
- :c:type:`PyObject`
109+
- :c:type:`PyVarObject`
110+
- :c:type:`!PyModuleDef_Base`
111+
- :c:type:`PyModuleDef`
112+
113+
- no longer include the following macros:
114+
115+
- :c:macro:`PyObject_HEAD`
116+
- :c:macro:`!_PyObject_EXTRA_INIT`
117+
- :c:macro:`PyObject_HEAD_INIT`
118+
- :c:macro:`PyObject_VAR_HEAD`
119+
120+
- no longer include these function-like macros:
121+
122+
- :c:func:`Py_SIZE`
123+
- :c:func:`Py_SET_SIZE`
124+
- :c:func:`Py_SET_TYPE`
125+
126+
127+
Implications
128+
^^^^^^^^^^^^
129+
130+
Making the ``PyObject``, ``PyVarObject`` and ``PyModuleDef`` structures
131+
opaque means:
132+
133+
- Their fields may not be directly accessed.
134+
135+
For example, instead of ``o->ob_type``, extensions must use
136+
``Py_TYPE(o)``.
137+
This usage has been the preferred practice for some time.
138+
139+
- Their size and alignment will not be available.
140+
Expressions such as ``sizeof(PyObject)`` will no longer work.
141+
142+
- They cannot be embedded in other structures.
143+
This mainly affects instance structs of extension-defined types,
144+
which will need to be defined using API added in :pep:`697` -- that is,
145+
using a ``struct`` *without* ``PyObject`` (or other base class struct) at
146+
the beginning, with :c:func:`PyObject_GetTypeData` calls needed to access
147+
the memory.
148+
149+
- Variables of these types cannot be created.
150+
This mainly affects static ``PyModuleDef`` variables needed to define
151+
extension modules.
152+
Extensions will need to switch to API added in :pep:`793`.
153+
154+
The following functions will become unusable in practice (in the new Limited
155+
API), since an extension cannot create valid, statically allocated, input
156+
for them. To ease the transition for extension developers,
157+
they will not yet be removed from the Limited API:
158+
159+
- :c:func:`PyModuleDef_Init`
160+
- :c:func:`PyModule_Create`, :c:func:`PyModule_Create2`
161+
- :c:func:`PyModule_FromDefAndSpec`, :c:func:`PyModule_FromDefAndSpec2`
162+
163+
164+
New Export Hook (PEP 793)
165+
-------------------------
166+
167+
Implementation of this PEP requires :pep:`793` (``PyModExport``:
168+
A new entry point for C extension modules) to be
169+
accepted, providing a new “export hook” for defining extension modules.
170+
Using the new hook will become mandatory in Limited API 3.15.
171+
172+
173+
Runtime ABI checks
174+
------------------
175+
176+
Users -- or rather the tools they use for building and installing extensions --
177+
will continue to be responsible for not putting incompatible extensions on
178+
Python's import paths.
179+
This decision makes sense since tools typically have much richer metadata than
180+
what CPython can check.
181+
182+
However, CPython will add a line of defense against outdated or misconfigured
183+
tools, or human mistakes, in the form of a new *module slot* containing
184+
basic ABI information.
185+
This information will be checked when a module is loaded, and incompatible
186+
extensions will be rejected.
187+
The specifics are left to the C API working group
188+
(see `issue 72 <https://github.com/capi-workgroup/decisions/issues/72>`__).
189+
190+
This slot will become *mandatory* with the new export hook added in
191+
:pep:`793`.
192+
(That PEP currently says “there are no required slots”; it will be updated.)
193+
194+
195+
Check for older ``abi3``
196+
^^^^^^^^^^^^^^^^^^^^^^^^
197+
198+
Additionally, in free-threaded builds, :c:func:`PyModuleDef_Init` will detect
199+
extensions using the pre-free-threading Stable ABI, emit an informative
200+
message when one is loaded, *and* raise an exception.
201+
(Implementation note: A message will be printed before raising the exception,
202+
because extensions that attempt to handle an exception using incompatible ABI
203+
will likely crash and lose the exception's message.)
204+
205+
This check for older ``abi3`` relies on internal bit patterns and may be
206+
removed in future CPython versions, if the internal object layout needs
207+
to change.
208+
209+
210+
Wheel tags
211+
----------
212+
213+
PyPA build tools should not need changes: if they allow the user to set the
214+
limited API version, setting it to 3.15 should define :c:macro:`Py_LIMITED_API`
215+
to ``0x030f0000``.
216+
The resulting wheel should be tagged with the Python-ABI tag ``cp315-abi3``.
217+
218+
Installers and other tools should assume that wheels with a *python tag*
219+
``cp315`` and above and ABI tag ``abi3`` are compatible with free-threaded
220+
builds.
221+
222+
223+
New API
224+
-------
225+
226+
Implementing this PEP will make it possible to build extensions that
227+
can be successfully loaded on free-threaded Python, but not necessarily ones
228+
that are thread-safe without a GIL.
229+
230+
Limited API to allow thread-safety without a GIL -- presumably ``PyMutex``, ``PyCriticalSection``, and
231+
similar -- will be added via the C API working group, or in a follow-up PEP.
232+
233+
234+
Backwards Compatibility
235+
=======================
236+
237+
Limited API 3.15 will not be backwards-compatible with older CPython releases,
238+
due to removed structs and functions.
239+
240+
Extension authors who cannot switch may continue to use Limited API 3.14
241+
and below.
242+
For compatibility with free-threaded builds, they can compile using
243+
version-specific ABI -- for example, compile on CPython 3.15 without defining
244+
``Py_LIMITED_API``.
245+
246+
247+
Security Implications
248+
=====================
249+
250+
None known.
251+
252+
253+
How to Teach This
254+
=================
255+
256+
A porting guide will need to explain how to move to APIs added in
257+
:pep:`697` (Limited C API for Extending Opaque Types)
258+
and :pep:`793` (``PyModExport``).
259+
260+
261+
Reference Implementation
262+
========================
263+
264+
This PEP combines several pieces, implemented individually:
265+
266+
- Opaque ``PyObject`` is available in CPython main branch after defining the
267+
``_Py_OPAQUE_PYOBJECT`` macro.
268+
Implemented in GitHub pull request `python/cpython#136505
269+
<https://github.com/python/cpython/pull/136505>`__.
270+
- For ``PyModExport``, see :pep:`793`.
271+
- For a version-checking slot, see GitHub pull request `python/cpython#137212
272+
<https://github.com/python/cpython/pull/137212>`__.
273+
- For a check for older ``abi3``, see GitHub pull request `python/cpython#137957
274+
<https://github.com/python/cpython/pull/137957>`__.
275+
- For wheel tags, there is no implementation yet.
276+
- A porting guide is not yet written.
277+
278+
279+
Rejected Ideas
280+
==============
281+
282+
283+
Add an alternative stable ABI for free-threading
284+
------------------------------------------------
285+
286+
It would be possible to:
287+
288+
- Keep the current stable ABI (“``abi3``”) unchanged (except additions, as done
289+
in each release). Extensions would need no code changes and builds would be
290+
compatible with old and new GIL-enabled CPython versions.
291+
- Add a new stable ABI (“``abi3t``”) specifically for free-threading.
292+
Extensions would need no code changes and builds would be
293+
compatible with free-threaded CPython (3.14 and above).
294+
- Defining an additional macro (“``Py_OPAQUE_PYOBJECT``”) would make
295+
``PyObject`` opaque as in this PEP. Extensions would need code changes as in
296+
this PEP, and compiled extensions (“``abi3.abi3t``”) would be compatible with
297+
all builds of CPython 3.15+.
298+
299+
This scheme was rejected as too complex.
300+
It would also make the free-threading memory layout of ``PyObject`` part
301+
of the stable ABI, preventing future adjustments.
302+
303+
304+
Shim for compatibility with CPython 3.14
305+
----------------------------------------
306+
307+
The issue that prevents compatibility with Python 3.14 is that with
308+
opaque ``PyObject`` and ``PyModuleDef``, it is not feasible to initialize
309+
an extension module.
310+
The solution, :pep:`793`, is only being added in Python 3.15.
311+
312+
It is possible to work around this using the fact that the 3.14 ABIs (both
313+
free-threading and GIL-enabled) are “frozen”, so it is possible for an
314+
extension to query the running interpreter, and for 3.14, use
315+
a ``struct`` definition corresponding to the detected build's ``PyModuleDef``.
316+
317+
This is too onerous to support and test in CPython's Limited API.
318+
It would also require adding a new wheel tag (e.g. ``abi3t``) that all install
319+
tools would need to recognize. (This PEP's ``cp315-abi3`` is incompatible
320+
with Python 3.14.)
321+
322+
323+
Open Issues
324+
===========
325+
326+
[See discussion for now.]
327+
328+
329+
Copyright
330+
=========
331+
332+
This document is placed in the public domain or under the
333+
CC0-1.0-Universal license, whichever is more permissive.

0 commit comments

Comments
 (0)