PEP: 739
Title: ``build-details.json`` 1.0 — a static description file for Python build details
Author: Filipe Laíns <lains@python.org>
PEP-Delegate: Paul Moore <p.f.moore@gmail.com>
Discussions-To: https://discuss.python.org/t/pep-739-static-description-file-for-build-details-of-python-installations/44572
Status: Accepted
Type: Standards Track
Topic: Packaging
Created: 19-Dec-2023
Python-Version: 3.14
Resolution: https://discuss.python.org/t/44572/90


Abstract
========

This PEP introduces ``build-details.json``, a static description file containing
build details of Python installations.

It includes the definition of version 1.0 of the file format, and defines the
standard location for this file.


Rationale
=========

When introspecting a Python installation, running code is often undesirable or
impossible. Having a static description file makes various build details of the
Python installation available without having to run the interpreter.

This is helpful for use-cases such as cross-compilation, Python launchers, etc.


Scope
=====

``build-details.json`` is an installation-wide file, meaning that it **MUST**
only contain information that is constant across all environments of the Python
installation.

Information specific to a Python environment, such as the ``site-packages``
path, is outside the scope for this file, and the PEP authors expect that a
static environment description file will be introduced via a future PEP.


Specification
=============

Starting from Python 3.14, a file named ``build-details.json`` following the
format specified in this PEP, or a future version, **MUST** be installed in the
platform-independent standard library directory (``stdlib``, eg.
``/usr/lib/python3.14/build-details.json``), **UNLESS** unfeasible due to
technical limitations.


.. attention::

  In addition to the standard location specified by this PEP, the
  ``build-details.json`` file **MAY** also be installed into **additional**
  locations, and under a different name. Notwithstanding, the file **SHOULD**
  still be available at the standard location.

  In actuality, the PEP authors expect future PEPs to define additional
  install locations with better discoverability.


Format
======

The format specification is defined by the JSON Schema definition provided
below, which is rendered in an human-readable format here.

..
    Rendered with https://gist.github.com/FFY00/eb02d9da2870aae547bc579b7e17a145

.. _spec-start:

.. list-table::
    :widths: 25 75

    * - ``$schema``
      - https://json-schema.org/draft/2020-12/schema
    * - ``$id``
      - https://github.com/python/peps/blob/main/peps/pep-0739/python-build-info-v1.0.schema.json
    * - Title
      - build-details.json — a static description file with build
        details of Python installations
    * - Type
      - ``object``
    * - Additional properties
      - **Not allowed**

``schema_version``
------------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``string`` (constant — ``1.0``)
    * - Description
      - Schema version.

        This is a string following the format ``<MAJOR>.<MINOR>``, where
        ``<MAJOR>`` and ``<MINOR>`` are unpadded numbers and represent
        the **major** and **minor** components of the version. Versions
        may be arithmetically compared by interpreting the version
        string as a decimal number.

        For this specification version, this value is constant and
        **MUST** be ``1.0``.

        Future versions of this schema **MUST** use a higher version
        number. Future versions of this schema **MUST NOT** use the same
        **major** version component as other schema version unless its
        specification is deemed backwards-compatible with them — it
        can't change, or extend, any parts of the current specification
        in such a way as the semantics of the interpreted data differ,
        or that data valid under the new specification is invalid under
        the older specification, with the exception of additional
        properties (errors caused by ``additionalProperties``).
    * - Required
      - **True**

``base_prefix``
---------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - Base prefix of the Python installation.

        Either an absolute path, or a path relative to directory where
        this file is contained.
    * - Examples
      - ``/usr``, ``../..``, etc.
    * - Required
      - **True**

``base_interpreter``
--------------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the Python interpreter of the base installation.

        Either an absolute path, or a path relative to ``base_prefix``.

        This field **MUST** be present if the installation provides an
        interpreter executable.
    * - Examples
      - - ``/usr/bin/python``
        - ``bin/python``
        - etc.
    * - Required
      - **False**

``platform``
------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - System platform string.

        This field **SHOULD** be equivalent to
        ``sysconfig.get_platform()``.
    * - Examples
      - - ``linux-x86_64``
        - etc.
    * - Required
      - **True**

``language``
------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details related to the Python language
        specification.
    * - Required
      - **True**
    * - Additional properties
      - **Not allowed**

``language.version``
~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - String representation the Python language version — a version
        string consisting only of the *major* and *minor* components.

        This field **SHOULD** be equivalent to
        ``sysconfig.get_python_version()``.
    * - Examples
      - ``3.14``, etc.
    * - Required
      - **True**

``language.version_info``
~~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object in the format of :py:data:`sys.version_info`.

        This section **SHOULD** be equivalent to
        :py:data:`sys.version_info`.
    * - Examples
      - - ``{'major': 3, 'minor': 14, 'micro': 1, 'releaselevel': 'final', 'serial': 0}``
        - etc.
    * - Required
      - **False**
    * - Additional properties
      - **Not allowed**

``language.version_info.major``
+++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``language.version_info.minor``
+++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``language.version_info.micro``
+++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``language.version_info.releaselevel``
++++++++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``string`` (enum — ``alpha``, ``beta``, ``candidate``, ``final``)
    * - Required
      - **True**

``language.version_info.serial``
++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``implementation``
------------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details related to the Python implementation.

        This section **SHOULD** be equivalent to
        :py:data:`sys.implementation`. It follows the specification defined
        in :pep:`421`, meaning that in addition to the required keys,
        implementation-specific keys can also exist, but must be
        prefixed with an underscore.
    * - Required
      - **True**
    * - Additional properties
      - **Allowed**

``implementation.name``
~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - Lower-case name of the Python implementation.
    * - Examples
      - ``cpython``, ``pypy``, etc.
    * - Required
      - **True**

``implementation.version``
~~~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object in the format of :py:data:`sys.version_info`, containing
        the implementation version.
    * - Examples
      - - ``{'major': 3, 'minor': 14, 'micro': 1, 'releaselevel': 'final', 'serial': 0}``
        - ``{'major': 7, 'minor': 3, 'micro': 16, 'releaselevel': 'final', 'serial': 0}``
        - etc.
    * - Required
      - **True**
    * - Additional properties
      - **Not allowed**

``implementation.version.major``
++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``implementation.version.minor``
++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``implementation.version.micro``
++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``implementation.version.releaselevel``
+++++++++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``string`` (enum — ``alpha``, ``beta``, ``candidate``, ``final``)
    * - Required
      - **True**

``implementation.version.serial``
+++++++++++++++++++++++++++++++++

.. list-table::
    :widths: 25 75

    * - Type
      - ``number``
    * - Required
      - **True**

``abi``
-------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details related to ABI.
    * - Required
      - **False**
    * - Additional properties
      - **Not allowed**

``abi.flags``
~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``array``
    * - Description
      - Build configuration flags, used to calculate the extension
        suffix.

        The flags **MUST** be defined in the order they appear on the
        extension suffix.
    * - Examples
      - ``['t', 'd']``, etc.
    * - Required
      - **True**

``abi.extension_suffix``
~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - Suffix used for extensions built against the current
        implementation version.

        This field **MUST** be present if the Python implementation
        supports extensions, otherwise this entry will be missing.
    * - Examples
      - - ``.cpython-314-x86_64-linux-gnu.so``
        - etc.
    * - Required
      - **False**

``abi.stable_abi_suffix``
~~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - Suffix used for extensions built against the `stable ABI
        <https://docs.python.org/3/c-api/stable.html#stable-abi>`_.

        This field **MUST** be present if the Python implementation has
        a stable ABI extension suffix, otherwise this entry will be
        missing.
    * - Examples
      - ``.abi3.so``, etc.
    * - Required
      - **False**

``suffixes``
------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Valid module suffixes grouped by type.

        This section **MUST** be present if the Python installation
        supports importing external files, and it **SHOULD** be
        equivalent to the ``importlib.machinery.*_SUFFIXES`` attributes.

        Additionally, if a Python implementation provides extension
        kinds other than the ones listed on ``importlib.machinery``
        module, they **MAY** add a sub-section for them.
    * - Examples
      - - ``{'source': ['.py'], 'bytecode': ['.pyc'], 'optimized_bytecode': ['.pyc'], 'debug_bytecode': ['.pyc'], 'extensions': ['.cpython-313-x86_64-linux-gnu.so', '.abi3.so', '.so']}``
        - etc.
    * - Required
      - **False**
    * - Additional properties
      - **Allowed**

``libpython``
-------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details related to the ``libpython`` library.

        This section **MUST** by present if Python installation provides
        a ``libpython`` library, otherwise this section will be missing.
    * - Required
      - **False**
    * - Additional properties
      - **Not allowed**

``libpython.dynamic``
~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the dynamic ``libpython`` library.

        Either an absolute path, or a path relative to ``base_prefix``.

        This field **MUST** be present if the Python installation
        provides a dynamic ``libpython`` library, otherwise this entry
        will be missing.
    * - Examples
      - - ``/usr/lib/libpython3.14.so.1.0``
        - ``lib/libpython3.14.so.1.0``
        - etc.
    * - Required
      - **False**

``libpython.dynamic_stableabi``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the dynamic ``libpython`` library for the stable
        ABI.

        Either an absolute path, or a path relative to ``base_prefix``.

        This field **MUST** be present if the Python installation
        provides a dynamic ``libpython`` library targetting the Stable
        ABI, otherwise this entry will be missing.

        If this key is present ``dynamic`` **MUST** also be set.
    * - Examples
      - - ``/usr/lib/libpython3.so``
        - ``lib/libpython3.so``
        - etc.
    * - Required
      - **False**

``libpython.static``
~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the static ``libpython`` library.

        Either an absolute path, or a path relative to ``base_prefix``.

        This field **MUST** be present if the Python installation
        provides a static ``libpython`` library, otherwise this entry
        will be missing.
    * - Examples
      - - ``/usr/lib/python3.14/config-3.14-x86_64-linux-gnu/libpython3.14.a``
        - ``lib/python3.14/config-3.14-x86_64-linux-gnu/libpython3.14.a``
        - etc.
    * - Required
      - **False**

``libpython.link_extensions``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``boolean``
    * - Description
      - Should extensions built against a dynamic ``libpython`` link to
        it?

        This field **MUST** be present if the Python installation
        provides a dynamic ``libpython`` library, otherwise this entry
        will be missing.
    * - Required
      - **False**

``c_api``
---------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing details related to the Python C API.

        This section **MUST** be present if the Python implementation
        provides a C API, otherwise this section will be missing.
    * - Required
      - **False**
    * - Additional properties
      - **Not allowed**

``c_api.headers``
~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the C API headers.

        Either an absolute path, or a path relative to ``base_prefix``.
    * - Examples
      - - ``/usr/include/python3.14``
        - ``include/python3.14``
        - etc.
    * - Required
      - **True**

``c_api.pkgconfig_path``
~~~~~~~~~~~~~~~~~~~~~~~~

.. list-table::
    :widths: 25 75

    * - Type
      - ``string``
    * - Description
      - The path to the pkg-config definition files.

        Either an absolute path, or a path relative to ``base_prefix``.

        This field **MUST** be present if the Python implementation
        provides pkg-config definition files, otherwise this section
        will be missing.
    * - Examples
      - - ``/usr/lib/pkgconfig``
        - ``lib/pkgconfig``
        - etc.
    * - Required
      - **False**

``arbitrary_data``
------------------

.. list-table::
    :widths: 25 75

    * - Type
      - ``object``
    * - Description
      - Object containing extra arbitrary data.

        This is meant to be used as an escape-hatch, to include any
        relevant data that is not covered by this specification.
        Implementations may choose what data to provide in this section.
    * - Required
      - **False**
    * - Additional properties
      - **Allowed**


.. _spec-end:


Example
=======


.. literalinclude:: pep-0739/example.json
   :language: json
   :linenos:


JSON Schema
===========

.. literalinclude:: pep-0739/python-build-info-v1.0.schema.json
   :language: json
   :linenos:


Rejected Ideas
==============

Including environment-specific data
-----------------------------------

One of the main requests in the discussion of this PEP was the inclusion of
other kind of information, such as the ``site-packages`` path. It is the opinion
of the PEP authors that information regarding the Python environment should be
provided by a separate file.

Including environment-specific data in the config file means that it would be
environment-specific, so virtual environments would need their own config file.
This is problematic because virtual environments survive updates of the base
Python installation, creating the possibily for the static config file to be
outdated, and making its data unreliable, which defeats its purpose.

The proposed solution, partially implemented in this PEP, is to have a
``build-details.json`` file, referent to the base Python installation, and a
``environment.json`` file, referent to the specific environment.

With ``build-details.json`` being part of the Python distribution, when the base
Python installation gets updated, ``build-details.json`` does too, ensuring the
static description files are never outdated.


Copyright
=========

This document is placed in the public domain or under the
CC0-1.0-Universal license, whichever is more permissive.
