--- /dev/null
+.. highlight:: c
+
+.. _abi3t-migration-howto:
+
+******************************************************
+Migrating to Stable ABI for free threading (``abi3t``)
+******************************************************
+
+Starting with the 3.15 release, CPython supports a variant of the Stable ABI
+that supports :term:`free-threaded <free threading>` Python:
+Stable ABI for Free-Threaded Builds, or ``abi3t`` for short.
+This document describes how to adapt C API extensions to support free threading.
+
+Why do this
+===========
+
+The typical reason to use Stable ABI is to reduce the number of artifacts that
+you need to build and distribute for each version of your library.
+
+Without the Stable ABI, you must build a separate shared library, and typically
+a *wheel* distribution, for each feature version of CPython you wish
+to support.
+For example, each tag in the following table represents a separate
+library/wheel:
+
++-----------------+-----------------------+------------------------+
+| CPython version | Non-free-threaded | Free-threaded |
++=================+=======================+========================+
+| 3.12 | ``cpython-312`` | --- |
++-----------------+-----------------------+------------------------+
+| 3.13 | ``cpython-313`` | ``cpython-313t`` |
++-----------------+-----------------------+------------------------+
+| 3.14 | ``cpython-314`` | ``cpython-314t`` |
++-----------------+-----------------------+------------------------+
+| 3.15 | ``cpython-315`` | ``cpython-315t`` |
++-----------------+-----------------------+------------------------+
+| 3.16 | ``cpython-316`` | ``cpython-316t`` |
++-----------------+-----------------------+------------------------+
+| Later versions | :samp:`cpython-3{XX}` | :samp:`cpython-3{XX}t` |
++-----------------+-----------------------+------------------------+
+
+That's a lot of builds, especially when multiplied by the number
+of supported platforms.
+
+With the Stable ABI (``abi3``, introduced in CPython 3.2), a single extension
+(per platform) can cover all *non-free-threaded* builds of CPython:
+
++-----------------+-------------------+------------------------+
+| CPython version | Non-free-threaded | Free-threaded |
++=================+===================+========================+
+| 3.12 | ``abi3`` | --- |
++-----------------+ +------------------------+
+| 3.13 | | ``cpython-313t`` |
++-----------------+ +------------------------+
+| 3.14 | | ``cpython-314t`` |
++-----------------+ +------------------------+
+| 3.15 | | ``cpython-315t`` |
++-----------------+ +------------------------+
+| 3.16 | | ``cpython-316t`` |
++-----------------+ +------------------------+
+| Later versions | | :samp:`cpython-3{XX}t` |
++-----------------+-------------------+------------------------+
+
+The Stable ABI for free-threaded builds (``abi3t``), introduced in
+CPython 3.15, does the same for free-threaded builds.
+And it's compatible with non-free-threaded ones as well:
+
++-----------------+-------------------+------------------+
+| CPython version | Non-free-threaded | Free-threaded |
++=================+===================+==================+
+| 3.12 | ``abi3`` * | --- |
++-----------------+ +------------------+
+| 3.13 | | ``cpython-313t`` |
++-----------------+ +------------------+
+| 3.14 | | ``cpython-314t`` |
++-----------------+-------------------+------------------+
+| 3.15 | ``abi3t`` |
++-----------------+ +
+| 3.16 | |
++-----------------+ +
+| Later versions | |
++-----------------+-------------------+------------------+
+
+\* (As above, the ``abi3`` extension is compatible with all non-free-threaded
+builds; even the 3.15+ ones that this table "attributes" to ``abi3t``.)
+
+Why *not* do this
+-----------------
+
+There are two main downsides to Stable ABI.
+
+First, you extension may become slower, since Stable ABI prioritizes
+compatibility over performance.
+The difference is usually not noticeable, and often can be mitigated by
+using the same source to build both a Stable ABI build and a few
+version-specific ones for "tier 1" CPython versions.
+
+Second, not all of the C API is available.
+Extensions need to be ported to build for Stable ABI, which may be difficult
+or, in rare cases, impossible.
+
+Specifically, ``abi3t`` requires APIs added in CPython 3.15.
+If you want to build your extension for older versions of CPython from the
+same source, you have two main options:
+
+- Use preprocessor conditionals.
+
+ When following this guide, use ``#ifdef Py_TARGET_ABI3T`` blocks whenever
+ you are told to do a change that breaks the build on CPython versions you
+ care about. Keep the pre-existing code in ``#else`` blocks.
+
+ For hand-written C extensions, this approach is reasonable down to
+ CPython 3.12, due to additions introduced in :pep:`697`.
+ Keeping compatibility with 3.11 and below may be worth it for code
+ generators (for example, Cython).
+
+- Do not port to ``abi3t``, and continue building separate extensions for
+ each version of CPython, until you can drop support for the older versions.
+
+ This is a valid approach. Not all extensions need to switch to ``abi3t``
+ right now.
+
+
+Prerequisites
+=============
+
+This guide assumes that you have an extension written directly in C (or C++),
+which you want to port to ``abi3t``.
+
+If your extenstion uses a code generator (like Cython) or language binding
+(like PyO3), it's best to wait until that tool has support for ``abi3t``.
+If you maintain such a tool, you might be able to adapt the instructions
+here for your tool.
+
+Non-free-threaded Stable ABI
+----------------------------
+
+Your extension should support the Stable ABI (``abi3t``).
+If not, either port it first, or follow this guide but be prepared to fix
+issues it does not mention.
+
+Free-threading support
+----------------------
+
+While it's technically not a hard prerequisite, you will most likely want to
+prepare your extension for free threading before you port it to ``abi3t``.
+See :ref:`freethreading-extensions-howto` for instructions.
+
+.. seealso::
+
+ `Porting Extension Modules to Support Free-Threading
+ <https://py-free-threading.github.io/porting/>`__:
+ A community-maintained porting guide for extension authors.
+
+Isolating extension modules
+---------------------------
+
+Your module should use :ref:`multi-phase initialization <multi-phase-initialization>`,
+and it should either be isolated or limit itself to be loaded at most once
+per process.
+If it is not your case, follow :ref:`isolating-extensions-howto` first.
+(See the :ref:`opt-out section <isolating-extensions-optout>` for a shortcut.)
+
+Avoiding variable-sized types
+-----------------------------
+
+If your extension defines variable-sized types (using :c:macro:`Py_tp_itemsize`
+or :c:member:`PyTypeObject.tp_itemsize`), it cannot be ported to
+``abi3t`` 3.15.
+
+
+Setting up the build
+====================
+
+If you use a build tool (such as setuptools, meson-python, scikit-build-core),
+search its documentation for a way to select ``abi3t``.
+At the time of writing, not all of them have this; but if your tool does,
+use it.
+You may want to verify that it set the right flag by temporarily adding the
+following just after ``#include <Python.h>``::
+
+ #if Py_TARGET_ABI3T+0 <= 0x30f0000
+ #error "abi3t define is not set!"
+ #endif
+
+This should result in a different error than "``abt3t`` define is not set".
+
+.. note::
+
+ If your build tool doesn't support ``abi3t`` yet, set the following macro
+ before including ``Python.h``::
+
+ #define Py_TARGET_ABI3T 0x30f0000
+
+ or specify it as a compiler flag, for example::
+
+ -DPy_TARGET_ABI3T=0x30f0000
+
+ Once your extension builds with this setting, it will be compatible with
+ CPython 3.15 and above.
+
+ If you set this macro manually, you will later need to name and tag the
+ resulting extension manually as well.
+ This is covered in :ref:`abi3t-migration-tagging` below.
+
+This guide will ask you to make a series of changes.
+After each one, verify that your extension still builds in the original
+(non-``abi3t``) configuration, and ideally run tests on all Python
+versions you support.
+This will ensure that nothing breaks as you are porting.
+
+
+Module export hook
+==================
+
+Unless you've done this step already, your extension module defines a
+:ref:`module initialization function <extension-pyinit>`
+named :samp:`PyInit_{<module_name>}`.
+You will need to port it to a :ref:`module export hook <extension-export-hook>`,
+:samp:`PyModExport_{<module name>}`, a feature added in CPython 3.15 in
+:pep:`793`.
+
+Your existing init function should look like this (with your own names
+for ``<modname>`` and ``<moddef>``):
+
+.. code-block::
+ :class: bad
+
+ PyMODINIT_FUNC
+ PyInit_<modname>(void)
+ {
+ return PyModuleDef_Init(&<moddef>);
+ }
+
+If there is some code before the ``return``, move it to
+a :c:macro:`Py_mod_create` or :c:macro:`Py_mod_exec` slot function.
+See the :ref:`PyInit documentation <extension-pyinit>` for related information.
+
+The function references a ``PyModuleDef`` object (``<moddef>`` in the code
+above).
+Its definition should be similar to the following, with different values
+and perhaps some fields unnnamed or left out:
+
+.. code-block::
+ :class: bad
+
+ static PyModuleDef <moddef> = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "my_module",
+ .m_doc = "my docstring",
+ .m_size = sizeof(my_state_struct),
+ .m_methods = my_methods,
+ .m_slots = my_slots,
+ .m_traverse = my_traverse,
+ .m_clear = my_clear,
+ .m_free = my_free,
+ };
+
+Remove this definition and the ``PyInit`` function (or put them in
+an ``#ifndef Py_TARGET_ABI3T`` block, to retain backwards compatibility),
+and replace them with the following:
+
+.. code-block::
+ :class: good
+
+ PyABIInfo_VAR(abi_info);
+
+ static PySlot my_slot_array[] = {
+ PySlot_STATIC_DATA(Py_mod_abi, &abi_info),
+ PySlot_STATIC_DATA(Py_mod_name, "my_module"),
+ PySlot_STATIC_DATA(Py_mod_doc, "my docstring"),
+ PySlot_SIZE(Py_mod_state_size, sizeof(my_state_struct)),
+ PySlot_STATIC_DATA(Py_mod_methods, my_methods),
+ PySlot_STATIC_DATA(Py_mod_slots, my_slots),
+ PySlot_FUNC(Py_mod_state_traverse, my_traverse),
+ PySlot_FUNC(Py_mod_state_clear, my_clear),
+ PySlot_FUNC(Py_mod_state_free, my_free),
+ PySlot_END
+ };
+
+ PyMODEXPORT_FUNC
+ PyModExport_<modname>(void)
+ {
+ return my_slot_array;
+ }
+
+Leave out any fields that were missing (except the new :c:macro:`Py_mod_abi`),
+and substitute your own values.
+
+See the :c:type:`PySlot` and :c:ref:`export hook <extension-export-hook>`
+documentation for details on this API.
+
+Associated ``PyModuleDef``
+--------------------------
+
+Since the new API does not use a :c:type:`!PyModuleDef` structure, a definition
+will not be associated with the resulting module.
+This changes the behavior of the following functions:
+
+- :c:func:`PyModule_GetDef`
+- :c:func:`PyType_GetModuleByDef`
+
+Check your code for these.
+If you do not use them, you can skip this section.
+
+These functions are typically used for two purposes:
+
+1. To get the definition the module was created with.
+ This is no longer possible using the new API.
+ Modules no longer keep a reference to the definition, so you will need to
+ figure out a different way to pass the relevant data around.
+
+.. _abi3t-migration-module-token:
+
+2. To check if a given module object is “yours”.
+ This use case is now served by :ref:`module tokens <ext-module-token>` --
+ opaque pointers that identify a module.
+ To use a token, declare (or reuse) a unique static variable, for example:
+
+ .. code-block::
+ :class: good
+
+ static char my_token;
+
+ and add a pointer to it in a new entry to your module's ``PySlot`` array:
+
+ .. code-block::
+ :class: good
+ :emphasize-lines: 3
+
+ static PySlot my_slot_array[] = {
+ ...
+ PySlot_STATIC_DATA(Py_mod_token, &my_token),
+ PySlot_END
+ }
+
+ Then, switch from :c:func:`PyModule_GetDef` calls such as:
+
+ .. code-block::
+ :class: bad
+
+ PyModuleDef *def = PyModule_GetDef(module);
+
+ to :c:func:`PyModule_GetToken` (which uses an output argument and may fail
+ with an exception):
+
+ .. code-block::
+ :class: good
+
+ void *token;
+ if (PyModule_GetToken(module, &token) < 0) {
+ /* handle error */
+ }
+
+ and from :c:func:`PyType_GetModuleByDef` calls such as:
+
+ .. code-block::
+ :class: bad
+
+ PyObject *module = PyType_GetModuleByDef(type, my_def);
+ /* handle error; use module */
+
+ to :c:func:`PyType_GetModuleByToken` (which returns a strong reference):
+
+ .. code-block::
+ :class: good
+
+ PyObject *module = PyType_GetModuleByToken(type, my_token);
+ /* handle error; use module */
+ Py_XDECREF(module);
+
+``PyObject`` opaqueness
+=======================
+
+The :c:type:`PyObject` and :c:type:`PyVarObject` structures are opaque
+in ``abi3t``.
+
+Accessing their members is prohibited.
+If you do this, switch to getter/setter functions mentioned in
+their documentation:
+
+- :c:member:`PyObject.ob_type`
+- :c:member:`PyObject.ob_refcnt`
+- :c:member:`PyVarObject.ob_size`
+
+Also, the *size* of the :c:type:`PyObject` structures is
+unknown to the compiler.
+It can -- and *does* -- change between different CPython builds.
+
+.. note::
+
+ While the size is available at runtime (for example as
+ ``sys.getsizeof(object())`` in Python code), you should resist the
+ temptation to calculate pointer offsets from it.
+ The object memory layout is subject to change in future
+ ``abi3t`` implementations.
+
+
+Custom type definitions
+-----------------------
+
+Since :c:type:`!PyObject` is opaque, the traditional way of defining
+custom types no longer works:
+
+.. code-block::
+ :class: bad
+
+ typedef struct {
+ PyObject_HEAD // expands to `PyObject ob_base;` which has unknown size
+
+ int my_data;
+ } CustomObject;
+
+ static PyType_Spec CustomType_spec = {
+ ...
+ .basicsize = sizeof(CustomObject),
+ ...
+ };
+
+Most likely, all your class definitions, *and* all code that accesses
+your classes' data, will need to be rewritten.
+This will probably be the biggest change you need to support ``abi3t``.
+
+For each such type, instead of defining a ``struct`` for the entire instance,
+define one with only the “additional” fields -- ones specific to your class,
+not its superclasses:
+
+.. code-block::
+ :class: good
+
+ typedef struct {
+ int my_data;
+ } CustomObjectData;
+
+Change the name.
+Almost all code that uses the struct will need to change
+(notably, pointers to the new structure cannot be cast to/from ``PyObject*``),
+and changing the name will highlight the usages as compiler errors.
+(If you use ``typeof``, C++ ``auto``, or similar ways to avoid
+typing the type name, this won't work. Be extra careful, and consider running
+tools to detect undefined behavior.)
+
+Then, to create the class, use *negative* ``basicsize`` to indicate
+“extra” storage space rather than *total* instance size:
+
+.. code-block::
+ :class: good
+
+ static PyType_Spec CustomType_spec = {
+ ...
+ .basicsize = -sizeof(CustomObjectData), /* note the minus sign */
+ ...
+ };
+
+If you use :c:macro:`Py_tp_members`, set the :c:macro:`Py_RELATIVE_OFFSET`
+flag on each member and specify the :c:member:`~PyMemberDef.offset`
+relative to your new struct.
+
+
+Custom type data access
+-----------------------
+
+Then comes the hard part: in all code that needs to access this struct,
+you will need an additional :c:func:`PyObject_GetTypeData` call to
+retrieve a ``CustomObjectData *`` pointer from ``PyObject *``:
+
+.. code-block::
+ :class: good
+
+ PyObject *obj = ...;
+ CustomObjectData *data = PyObject_GetTypeData(obj, cls);
+
+Note that this call requires the *type object* for your class (``cls``).
+
+If your class is not subclassable (that is, it does not use the
+:c:macro:`Py_TPFLAGS_BASETYPE` flag), ``cls`` will be ``Py_TYPE(obj)``.
+Otherwise, **DO NOT USE** ``Py_TYPE`` with :c:func:`!PyObject_GetTypeData`:
+it might return memory reserved to an unrelated subclass!
+For example, if a user makes a subclass like this:
+
+.. code-block:: python
+
+ class Sub(YourCustomClass):
+ __slots__ = ('a', 'b')
+
+then ``Py_TYPE(obj)`` is ``YourCustomClass``, and the underlying memory may
+look like this:
+
+.. code-block:: text
+
+ ╭─ PyObject *obj
+ │ ╭─ the pointer you want
+ │ │ ╭─ PyObject_GetTypeData(obj, Py_TYPE(obj))
+ ▼ ▼ ▼
+ ┌──────────┬───┬────────────────┬───┬─────────────┬───┬─────────────┐
+ │ PyObject │...│ CustomTypeData │...│ PyObject *a │...│ PyObject *b │
+ └──────────┴───┴────────────────┴───┴─────────────┴───┴─────────────┘
+
+(Ellipses indicate possible padding.
+Note that this memory layout is not guaranteed: future versions of Python may
+add different padding or even switch the order of the structures.)
+
+There are two main ways to get the right class:
+
+- In instance methods, your implementation may use the :c:type:`PyCMethod`
+ signature (and the :c:macro:`METH_METHOD` bit in
+ :c:member:`PyMethodDef.ml_flags`),
+ and get the class as the ``defining_class`` argument.
+- Otherwise, give your class a unique static token using the
+ :c:macro:`Py_tp_token` slot, and use:
+
+ .. code-block::
+ :class: good
+
+ PyTypeObject cls;
+ if (PyType_GetBaseByToken(Py_TYPE(obj), my_tp_token, &cls) < 0) {
+ /* handle error */
+ }
+ CustomObjectData *data = PyObject_GetTypeData(obj, cls);
+
+ Type tokens work similarly to module tokens covered :ref:`earlier in this
+ guide <abi3t-migration-module-token>`.
+
+
+
+Avoid build-time conditionals
+=============================
+
+Check your code for API that identifies the version of Python used to
+*build* your extension.
+This no longer corresponds to the Python your extension runs on, so code
+that uses this information often needs changing.
+The macros to check for are:
+
+- :c:macro:`PY_VERSION_HEX`, :c:macro:`PY_MAJOR_VERSION`,
+ :c:macro:`PY_MINOR_VERSION`:
+
+ - to get the run-time version, use :c:data:`Py_Version`;
+ - to determine what C API is available, use :c:macro:`Py_TARGET_ABI3T`.
+ This macro is set to the minimum supported version.
+
+- :c:macro:`Py_GIL_DISABLED`: under ``abi3t``, this macro is always defined.
+ Code that works with free-threaded Python *should* also work with
+ the GIL enabled (since the GIL can be enabled at run time),
+ and usually *does* (unless it, for some reason, requires more than one
+ :term:`attached thread state <attached thread state>` at one time).
+
+
+Further code changes
+====================
+
+If you are still left with compiler errors or warnings, find a way to fix them.
+Alas, this guide is limited, and cannot cover all possible code
+changes extensions may need.
+
+If you find a problem that other extension authors might run into,
+consider :ref:`reporting an issue <reporting-documentation-bugs>` (or sending
+a pull request) for this guide.
+
+It is possible your issue cannot be fixed for the current version of ``abi3t``.
+In that case, reporting it may help it get prioritized for the next version
+of CPython.
+
+
+.. _abi3t-migration-tagging:
+
+Tagging and distribution
+========================
+
+If you are using a build tool with ``abi3t`` support, your extension is ready,
+but you might want to check that it was built correctly.
+
+Extensions built with ``abi3t`` should have the following extension:
+
+- On Windows: ``.pyd`` (like any other extension);
+- Linux, macOS, and other systems that use the ``.so`` suffix: ``.abi3t.so``
+ (**not** ``.cpython-315t.so`` or ``.abi3.so``).
+ Note that both free-threaded and non-free-threaded builds will
+ load ``.abi3t.so`` extensions;
+- Other systems: consult your distributor, and perhaps update this guide.
+
+If you distribute the extension as a *wheel*, use the following tags:
+
+* Python tag: :samp:`cp3{XX}`, where *XX* is the minimum Python version
+ the extension is built for.
+ (For example, ``cp315`` if you set ``Py_TARGET_ABI3T`` to ``0x30f0000``.
+ See :ref:`abi3-compiling` for more values.)
+* ABI tag: ``abi3.abi3t``. This is a *compressed tag set* that indicates
+ support for both non-free-threaded and free-threaded builds.
+
+For example, the wheel filename may look like this:
+
+.. code-block:: text
+
+ myproject-1.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl
+
+.. seealso:: `Platform Compatibility Tags <https://packaging.python.org/en/latest/specifications/platform-compatibility-tags/>`__ in the PyPA package distribution metadata.
+
+If the filename or tags are incorrect, fix them.
+
+
+Testing
+=======
+
+Note that when you build an extension compatible with multiple versions of
+CPython, you should always *test* it with each version it supports (for
+example, 3.15, 3.16, and so on).
+Stable ABI only guarantees *ABI* compatibility; there may also be behavior
+changes -- both intentional ones (covered by :pep:`387`) and bugs.
+
+Be sure to run tests on both free-threaded and non-free-threaded builds
+of CPython.
+
+If they pass, congratulations! You have an ``abi3t`` extension.