diff --git a/docs/how-to-guides/limited-api.rst b/docs/how-to-guides/limited-api.rst new file mode 100644 index 000000000..1c85ce146 --- /dev/null +++ b/docs/how-to-guides/limited-api.rst @@ -0,0 +1,125 @@ +.. SPDX-FileCopyrightText: 2026 The meson-python developers +.. +.. SPDX-License-Identifier: MIT + +.. _howto-limited-api: + +*********************************** +Targeting the CPython Limited C API +*********************************** + +This page describes how to configure your project to build against the +CPython `limited API`_ and build `stable ABI`_ wheels. Limited API builds +target a minimum interpreter version and produce a single wheel that +can support newer interpreter versions. + +Enabling the :option:`tool.meson-python.limited-api` setting declares that all +the extension modules in the package target the limited API and adjusts the +wheel filename ABI tag accordingly: + +.. code-block:: meson + + py = import('python').find_installation(pure: false) + + py.extension_module( + '_core', + '_core.c', + limited_api: '3.10', + install: true, + subdir: 'example', + ) + +.. code-block:: toml + + [tool.meson-python] + limited-api = true + +Build with the minimum CPython interpreter version you wish to +support. ``meson-python`` verifies that all the extension modules +included in the wheel use the stable ABI filename suffix and fails the +build otherwise. PyPy does not support the limited API thus this setting +has no effect when building with PyPy. + + +The ``abi3t`` stable ABI +------------------------ + +CPython 3.15 introduces the ``abi3t`` stable ABI, see :pep:`803` and the +`abi3t migration guide`_. Extension modules built for ``abi3t`` can be +loaded by both the GIL-enabled and the free-threaded builds of CPython +3.15 and later: a single wheel tagged ``abi3.abi3t`` supports all +CPython interpreters from version 3.15 on. + +``abi3t`` extension modules require limited API version 3.15 or later and a +free-threaded interpreter for the build. Building abi3t extensions using a +GIL-enabled interpreter is not currently support. Nothing else is required: the +CPython headers select ``abi3t`` when ``Py_LIMITED_API`` is defined while +compiling for a free-threaded interpreter. + +Meson refuses a ``limited_api`` version newer than the interpreter used +for the build. Projects that build ``abi3`` wheels for older CPython +versions and ``abi3.abi3t`` wheels for CPython 3.15 and later can select +the limited API version querying the ``Py_GIL_DISABLED`` sysconfig +variable, which is 1 for free-threaded builds: + +.. code-block:: meson + + py = import('python').find_installation(pure: false) + + limited_api = '3.10' + if py.language_version().version_compare('>=3.15') + if py.get_variable('Py_GIL_DISABLED') == 1 + limited_api = '3.15' + endif + endif + + py.extension_module( + '_core', + '_core.c', + limited_api: limited_api, + install: true, + subdir: 'example', + ) + +Disable the Limited API +----------------------- + +Projects that enable the :option:`tool.meson-python.limited-api` setting in +their ``pyproject.toml`` opt into limited API builds by default. Passing the +``-Dpython.allow_limited_api=false`` option to ``meson setup`` disables +this default. Instead, extension modules are compiled for the ABI +specific to the Python version used for the build and the wheel is tagged +accordingly. This is required to build wheels for free-threaded CPython 3.13 +and 3.14. Opting out of limited API builds may also `improve performance`_. + +To disable limited API builds temporarily at build-time: + +.. tab-set:: + + .. tab-item:: pypa/build + :sync: key_pypa_build + + .. code-block:: console + + $ python -m build --wheel -Csetup-args="-Dpython.allow_limited_api=false" . + + .. tab-item:: pip + :sync: key_pip + + .. code-block:: console + + $ python -m pip wheel -Csetup-args="-Dpython.allow_limited_api=false" . + +To set this option only when building wheels for free-threaded CPython +3.14 in CI using cibuildwheel: + +.. code-block:: toml + + [[tool.cibuildwheel.overrides]] + select = "cp314t-*" + config-settings = { setup-args = ["-Dpython.allow_limited_api=false"] } + +.. _limited API: https://docs.python.org/3/c-api/stable.html#limited-c-api +.. _stable ABI: https://docs.python.org/3/c-api/stable.html#stable-application-binary-interface +.. _abi3t migration guide: https://docs.python.org/3.15/howto/abi3t-migration.html +.. _improve performance: https://docs.python.org/3/c-api/stable.html#limited-api-scope-and-performance diff --git a/docs/index.rst b/docs/index.rst index f56b7ebc0..2bbc407ee 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -83,6 +83,7 @@ the use of ``meson-python`` and Meson for Python packaging. how-to-guides/meson-args how-to-guides/debug-builds how-to-guides/shared-libraries + how-to-guides/limited-api reference/limitations projects-using-meson-python diff --git a/docs/reference/pyproject-settings.rst b/docs/reference/pyproject-settings.rst index 6a7177c10..ee73a36ff 100644 --- a/docs/reference/pyproject-settings.rst +++ b/docs/reference/pyproject-settings.rst @@ -33,11 +33,9 @@ use them and examples. modules can be compiled for the Python limited API specifying the ``limited_api`` argument to the |extension_module()|_ function in the Meson Python module. When this setting is set to true, the - value ``abi3`` is used for the Python wheel filename ABI tag. - - This setting is automatically reverted to false when the - ``-Dpython.allow_limited_api=false`` option is passed to ``meson - setup``. + Python wheel filename ABI tag is set to ``abi3``, or ``abi3.abi3t`` + when building with free-threaded CPython 3.15 or later. See + :ref:`howto-limited-api` for details. .. option:: tool.meson-python.meson @@ -91,7 +89,7 @@ use them and examples. glob pattern is useful exclusively to limit the effect of an exclude pattern that matches too many files. -.. _python limited api: https://docs.python.org/3/c-api/stable.html?highlight=limited%20api#stable-application-binary-interface +.. _python limited api: https://docs.python.org/3/c-api/stable.html#stable-application-binary-interface .. _extension_module(): `https://mesonbuild.com/Python-module.html#extension_module .. _meson introspection data: https://mesonbuild.com/IDE-integration.html#install-plan