# Technical Documentation: astral-sh/python-build-standalone

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/astral-sh/python-build-standalone)

### Overview (`README.md`)

# Python Build Standalone

[](https://github.com/astral-sh/python-build-standalone/releases)

[**Docs**](https://docs.astral.sh/python-build-standalone/) | [**Releases**](https://github.com/astral-sh/python-build-standalone/releases)

Self-contained, portable, high-performance Python distributions.

## Highlights

- [High performance](https://github.com/astral-sh/python-build-standalone/blob/main/BENCHMARKS.md),
  as fast or faster than other CPython distributions.
- Portable, can be installed into any path.
- Self-contained, extension modules and dependencies included.
- Python 3.10-3.15.
- Standard and free-threaded builds.
- Linux, macOS, and Windows.
- Multiple [platforms and architectures](https://docs.astral.sh/python-build-standalone/running/#obtaining-distributions)
  supported.
- Ready to use with [uv](https://docs.astral.sh/uv/) or directly from
  [release archives](https://github.com/astral-sh/python-build-standalone/releases).

Python Build Standalone is maintained by [Astral](https://astral.sh), the team
behind [uv](https://github.com/astral-sh/uv), [ruff](https://github.com/astral-sh/ruff),
and [ty](https://github.com/astral-sh/ty).

## Getting started

The most common way to use these distributions is with
[uv](https://docs.astral.sh/uv/). Run a managed Python installation with:

```shell
uvx --managed-python python
```

Choose a specific Python version or a free-threaded build:

```shell
uvx --managed-python python@3.13
uvx --managed-python python@3.14+freethreaded
```

See the [documentation](https://docs.astral.sh/python-build-standalone/) for more,
including [running distributions](https://docs.astral.sh/python-build-standalone/running/)
and [behavior quirks](https://docs.astral.sh/python-build-standalone/quirks/).

## Downloads

Prebuilt distributions are available on
[GitHub Releases](https://github.com/astral-sh/python-build-standalone/releases).
Choose an archive for your Python version, operating system, and architecture.
Most users should choose an `install_only` archive; `full` archives also contain
build artifacts for creating custom Python distributions.

See [distribution archives](https://docs.astral.sh/python-build-standalone/distributions/)
for details on the available formats.

---

### Building (`docs/building.md`)

<a id="building"></a>

# Building

A Python distribution can be built on a Linux, macOS, or Windows host.
Regardless of the operating system, [uv](https://docs.astral.sh/uv/)
must be installed. Additional operating system requirements are outlined
in the following sections.

Regardless of the host, to build a Python distribution:

```
$ uv run --no-dev build.py
```

On Linux and macOS, `./build.py` can also be used; it uses
`uv run --no-dev` via its shebang.

To build a different version of Python:

```
$ uv run --no-dev build.py --python cpython-3.14
```

Various build options can be specified:

```
# With profile-guided optimizations (generated code should be faster)
$ uv run --no-dev build.py --options pgo
# Produce a debug build.
$ uv run --no-dev build.py --options debug
# Produce a free-threaded build without extra optimizations
$ uv run --no-dev build.py --options freethreaded+noopt
```

Different platforms support different build options.
`uv run --no-dev build.py --help` will show the available build options
and other usage information.

## Linux

The host system must be x86-64 or aarch64. The execution environment must
have access to a Docker daemon (all build operations are performed in
Docker containers for isolation from the host system). Docker Buildx must
be installed and available as `docker buildx`.

`build.py` accepts a `--target-triple` argument to support building
for non-native targets (i.e., cross-compiling).

This option can be used to build for musl libc:

```
$ ./build.py --target-triple x86_64-unknown-linux-musl
```

Or on an x86-64 host for different architectures:

```
$ ./build.py --target-triple armv7-unknown-linux-gnueabi
$ ./build.py --target-triple armv7-unknown-linux-gnueabihf
$ ./build.py --target-triple ppc64le-unknown-linux-gnu
$ ./build.py --target-triple riscv64-unknown-linux-gnu
$ ./build.py --target-triple s390x-unknown-linux-gnu
```

### Jessie image package authentication

The `build`, `gcc`, and `rust` Dockerfiles include
`cpython-unix/base.Dockerfile`. These amd64 images use Debian Jessie
for build compatibility. Cross-compilation targets also use the `gcc`
image for toolchain builds.

Building these images requires Docker Buildx with support for Dockerfile
1.6's `ADD --checksum` instruction.

The base Dockerfile pins the SHA-256 digests of the three archived
`Packages.gz` indexes because Jessie's archive signing keys have expired.
Docker fetches them over HTTPS and verifies their digests before APT uses
them. APT then verifies downloaded packages against the hashes in these
fixed indexes. `trusted=yes` permits this separate trust root;
`apt-get update` is blocked to prevent replacing the pinned indexes with
unauthenticated metadata.

The pinned base image lacks both `apt-transport-https` and
`ca-certificates`. Their bootstrap download uses HTTP, authenticated by
the pinned package hashes. Once they are installed, subsequent package
downloads use HTTPS with certificate verification.

The index digests come from the SHA256 sections of the archived
[Jessie Release](https://snapshot.debian.org/archive/debian/20230322T152120Z/dists/jessie/Release),
[Jessie updates Release](https://snapshot.debian.org/archive/debian/20230322T152120Z/dists/jessie-updates/Release), and
[Jessie security Release](https://snapshot.debian.org/archive/debian-security/20230322T152120Z/dists/jessie/updates/Release)
files. The corresponding archive key fingerprints in the digest-pinned
base image are `126C0D24BD8A2942CC7DF8AC7638D0442B90D010`
for Jessie and Jessie updates, and
`D21169141CECD440F2EB8DDA9D6D8F6BC857C906` for Jessie security. Any change
to the snapshot or index digests requires independently authenticating the
replacement metadata.

## macOS

The Xcode command-line tools must be installed.
`/usr/bin/clang` must exist.

macOS SDK headers must be installed. If you see errors such as `stdio.h`
not being found, try running `xcode-select --install` to install them.
Verify they are installed by running `xcrun --show-sdk-path`. It should
print something like
`/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk`
on modern versions of macOS.

The `--target-triple` argument can be used to build for an Intel Mac on
an arm64 (Apple Silicon) host:

```
$ ./build.py --target-triple x86_64-apple-darwin
```

Additionally, an arm64 macOS host can be used to build Linux aarch64 and x86-64
targets using Docker:

```
$ ./build.py --target-triple aarch64-unknown-linux-gnu
$ ./build.py --target-triple x86_64-unknown-linux-gnu
```

The `APPLE_SDK_PATH` environment variable is recognized as the path
to the Apple SDK to use. If not defined, the build will attempt to find
an SDK by running `xcrun --show-sdk-path`.

`aarch64-apple-darwin` builds require a macOS 11.0+ SDK.
It should be possible to build for `aarch64-apple-darwin` from
an Intel 10.15 machine (as long as the 11.0+ SDK is used).

## Windows

Visual Studio 2022 (or later) is required. For `x86_64-pc-windows-msvc`
targets, use Visual Studio 2026 when building CPython 3.15 or newer. The
`i686-pc-windows-msvc` and `aarch64-pc-windows-msvc` targets continue
to use Visual Studio 2022.
A compatible Windows SDK is required (10.0.26100.0 as of CPython 3.10).
A `git.exe` must be on `PATH` (to clone `libffi` from source).
Cygwin must be installed with the `autoconf`, `automake`, `libtool`,
and `make` packages, which are required to build `libffi`.

Building can be done from the `x64 Native Tools Command Prompt`, by calling
the vcvars batch file, or by adjusting the `PATH` and environment variables.

You will need to specify the path to `sh.exe` from Cygwin:

```
$ uv run --no-dev build.py --sh c:\cygwin\bin\sh.exe
```

When using a version of Visual Studio other than 2022, the version must
be specified with the `--vs` option. For example, to build CPython 3.15
with Visual Studio 2026:

```
$ uv run --no-dev build.py --sh c:\cygwin\bin\sh.exe --vs 2026 --python cpython-3.15
```

To produce a debug build, pass `--options debug` or `freethreaded+debug`:

```
$ uv run --no-dev build.py --sh c:\cygwin\bin\sh.exe --options debug
```

The artifacts carry the `_d` suffix of CPython's Debug configuration
(`python_d.exe`, `python314_d.dll`, `_asyncio_d.pyd`) and link against
the debug C runtime (`ucrtbased.dll` and `vcruntime*d.dll`). That
runtime ships with Visual Studio and [is not redistributable](https://learn.microsoft.com/en-us/cpp/windows/determining-which-dlls-to-redistribute),
so a debug distribution only runs on a machine with Visual Studio installed.

To build a 32-bit x86 binary, simply use an
`x86 Native Tools Command Prompt` instead of `x64`.

---

### Building (`docs/building.rst`)

.. _building:

========
Building
========

A Python distribution can be built on a Linux, macOS, or Windows host.
Regardless of the operating system, `uv <https://docs.astral.sh/uv/>`_
must be installed. Additional operating system requirements are outlined
in the following sections.

Regardless of the host, to build a Python distribution::

    $ uv run --no-dev build.py

On Linux and macOS, ``./build.py`` can also be used; it uses
``uv run --no-dev`` via its shebang.

To build a different version of Python::

    $ uv run --no-dev build.py --python cpython-3.14

Various build options can be specified::

    # With profile-guided optimizations (generated code should be faster)
    $ uv run --no-dev build.py --options pgo
    # Produce a debug build.
    $ uv run --no-dev build.py --options debug
    # Produce a free-threaded build without extra optimizations
    $ uv run --no-dev build.py --options freethreaded+noopt

Different platforms support different build options.
``uv run --no-dev build.py --help`` will show the available build options
and other usage information.

Linux
=====

The host system must be x86-64 or aarch64. The execution environment must
have access to a Docker daemon (all build operations are performed in
Docker containers for isolation from the host system). Docker Buildx must
be installed and available as ``docker buildx``.

``build.py`` accepts a ``--target-triple`` argument to support building
for non-native targets (i.e., cross-compiling).

This option can be used to build for musl libc::

    $ ./build.py --target-triple x86_64-unknown-linux-musl

Or on an x86-64 host for different architectures::

    $ ./build.py --target-triple armv7-unknown-linux-gnueabi
    $ ./build.py --target-triple armv7-unknown-linux-gnueabihf
    $ ./build.py --target-triple ppc64le-unknown-linux-gnu
    $ ./build.py --target-triple riscv64-unknown-linux-gnu
    $ ./build.py --target-triple s390x-unknown-linux-gnu

Jessie image package authentication
-----------------------------------

The ``build``, ``gcc``, and ``rust`` Dockerfiles include
``cpython-unix/base.Dockerfile``. These amd64 images use Debian Jessie
for build compatibility. Cross-compilation targets also use the ``gcc``
image for toolchain builds.

Building these images requires Docker Buildx with support for Dockerfile
1.6's ``ADD --checksum`` instruction.

The base Dockerfile pins the SHA-256 digests of the three archived
``Packages.gz`` indexes because Jessie's archive signing keys have expired.
Docker fetches them over HTTPS and verifies their digests before APT uses
them. APT then verifies downloaded packages against the hashes in these
fixed indexes. ``trusted=yes`` permits this separate trust root;
``apt-get update`` is blocked to prevent replacing the pinned indexes with
unauthenticated metadata.

The pinned base image lacks both ``apt-transport-https`` and
``ca-certificates``. Their bootstrap download uses HTTP, authenticated by
the pinned package hashes. Once they are installed, subsequent package
downloads use HTTPS with certificate verification.

The index digests come from the SHA256 sections of the archived
`Jessie Release <https://snapshot.debian.org/archive/debian/20230322T152120Z/dists/jessie/Release>`_,
`Jessie updates Release <https://snapshot.debian.org/archive/debian/20230322T152120Z/dists/jessie-updates/Release>`_, and
`Jessie security Release <https://snapshot.debian.org/archive/debian-security/20230322T152120Z/dists/jessie/updates/Release>`_
files. The corresponding archive key fingerprints in the digest-pinned
base image are ``126C0D24BD8A2942CC7DF8AC7638D0442B90D010``
for Jessie and Jessie updates, and
``D21169141CECD440F2EB8DDA9D6D8F6BC857C906`` for Jessie security. Any change
to the snapshot or index digests requires independently authenticating the
replacement metadata.

macOS
=====

The Xcode command-line tools must be installed.
``/usr/bin/clang`` must exist.

macOS SDK headers must be installed. If you see errors such as ``stdio.h``
not being found, try running ``xcode-select --install`` to install them.
Verify they are installed by running ``xcrun --show-sdk-path``. It should
print something like
``/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk``
on modern versions of macOS.

The ``--target-triple`` argument can be used to build for an Intel Mac on
an arm64 (Apple Silicon) host::

    $ ./build.py --target-triple x86_64-apple-darwin

Additionally, an arm64 macOS host can be used to build Linux aarch64 and x86-64
targets using Docker::

    $ ./build.py --target-triple aarch64-unknown-linux-gnu
    $ ./build.py --target-triple x86_64-unknown-linux-gnu

The ``APPLE_SDK_PATH`` environment variable is recognized as the path
to the Apple SDK to use. If not defined, the build will attempt to find
an SDK by running ``xcrun --show-sdk-path``.

``aarch64-apple-darwin`` builds require a macOS 11.0+ SDK.
It should be possible to build for ``aarch64-apple-darwin`` from
an Intel 10.15 machine (as long as the 11.0+ SDK is used).

Windows
=======

Visual Studio 2022 (or later) is required. For ``x86_64-pc-windows-msvc``
targets, use Visual Studio 2026 when building CPython 3.15 or newer. The
``i686-pc-windows-msvc`` and ``aarch64-pc-windows-msvc`` targets continue
to use Visual Studio 2022.
A compatible Windows SDK is required (10.0.26100.0 as of CPython 3.10).
A ``git.exe`` must be on ``PATH`` (to clone ``libffi`` from source).
Cygwin must be installed with the ``autoconf``, ``automake``, ``libtool``,
and ``make`` packages, which are required to build ``libffi``.

Building can be done from the ``x64 Native Tools Command Prompt``, by calling
the vcvars batch file, or by adjusting the ``PATH`` and environment variables.

You will need to specify the path to ``sh.exe`` from Cygwin::

   $ uv run --no-dev build.py --sh c:\cygwin\bin\sh.exe

When using a version of Visual Studio other than 2022, the version must
be specified with the ``--vs`` option. For example, to build CPython 3.15
with Visual Studio 2026::

   $ uv run --no-dev build.py --sh c:\cygwin\bin\sh.exe --vs 2026 --python cpython-3.15

To produce a debug build, pass ``--options debug`` or ``freethreaded+debug``::

   $ uv run --no-dev build.py --sh c:\cygwin\bin\sh.exe --options debug

The artifacts carry the ``_d`` suffix of CPython's Debug configuration
(``python_d.exe``, ``python314_d.dll``, ``_asyncio_d.pyd``) and link against
the debug C runtime (``ucrtbased.dll`` and ``vcruntime*d.dll``). That
runtime ships with Visual Studio and `is not redistributable
<https://learn.microsoft.com/en-us/cpp/windows/determining-which-dlls-to-redistribute>`_,
so a debug distribution only runs on a machine with Visual Studio installed.

To build a 32-bit x86 binary, simply use an
``x86 Native Tools Command Prompt`` instead of ``x64``.

---

### Distributions (`docs/distributions.md`)

<a id="distributions"></a>

# Distribution Archives

This project produces tarball archives containing Python distributions.

## Full Archive

The canonical output of this project's build system are `.tar.zst`
(zstandard compressed tarballs) files.

All files within the tar are prefixed with `python/`.

Within the `python/` directory are the following well-known paths:

PYTHON.json

: Machine readable file describing this Python distribution.

    See the `PYTHON.json File` section for the format of this file.

By convention, the `build/` directory contains artifacts from building
this distribution (object files, libraries, etc) and the `install/` directory
contains a working, self-contained Python installation of this distribution.
The `PYTHON.json` file should be read to determine where specific entities
are located within the archive.

### PYTHON.json File

The `PYTHON.json` file describes the Python distribution in a machine
readable manner. This file is meant to be opened by downstream consumers
of this distribution so that they may learn things about the distribution
without having to resort to heuristics.

The file contains a JSON map. This map has the following keys:

version

: Version number of the file format. Currently `8`.

target_triple

: A target triple defining the platform and architecture of the machine
    that binaries target. We use Rust's set of defined targets for values.
    Run `rustup target list` to see potential values.

    Example values are `x86_64-unknown-linux-gnu`,
    `x86_64-unknown-linux-musl`, `x86_64-pc-windows-msvc`,
    and `x86_64-apple-darwin`.

    (Version 5 or above only.)

optimizations

: String indicating what optimization profile has been applied to the
    build.

    Known values include `debug`, `noopt`, `pgo`, `lto`, and
    `pgo+lto`.

    (Deprecated in version 8 in favor of `build_options`.)

build_options

: String indicating what build options were used. Options are separated
    by a `+`.

    Known values include `debug`, `noopt`, `pgo`, `lto`, `static`,
    and `freethreaded`.

    (Version 8 or above only.)

os

: Target operating system for the distribution. e.g. `linux`, `macos`,
    or `windows`.

    (Deprecated in version 5 in favor of `target_triple`.)

arch

: Target architecture for the distribution. e.g. `x86` (32-bit) or
    `x86_64` (64-bit).

    (Deprecated in version 5 in favor of `target_triple`.)

python_tag

: The PEP 425 *Python Tag* value. e.g. `cp313`.

    (Version 5 or above only.)

python_abi_tag

: The PEP 425 *ABI Tag* value. e.g. `cp313m`.

    This may be null if the distribution's platform doesn't expose the concept
    of an ABI tag.

    (Version 5 or above only.)

python_platform_tag

: The PEP 425 *Platform Tag* value. e.g. `linux_x86_64`.

    (Version 5 or above only.)

python_flavor

: Type of Python distribution. e.g. `cpython`.

    (Deprecated in version 5 in favor of PEP 425 tags.)

python_implementation_cache_tag

: Tag used by import machinery to derive filenames for bytecode files.

    This is the value exposed by `sys.implementation.cache_tag`

    (Version 5 or above only.)

python_implementation_hex_version

: Hexadecimal expression of implementation version.

    This is the value exposed by `sys.implementation.hexversion`.

    (Version 5 or above only.)

python_implementation_name

: Name of Python implementation.

    This is the value exposed by `sys.implementation.name`.

    (Version 5 or above only.)

python_implementation_version

: Array of version components of Python implementation.

    This is the value exposed by `sys.implementation.version`.

    Unlike `sys.implementation.version`, all elements are strings,
    not a mix of numbers and strings.

    (Version 5 or above only.)

python_version

: Version of Python distribution. e.g. `3.13.0`.

python_major_minor_version

: `X.Y` version string consisting of Python major and minor version.

    (Version 5 or above only.)

python_paths

: Mapping of `sysconfig` path names to paths in the distribution.

    Keys are values like `stdlib` and `include`. Values are relative
    paths within the distribution.

    See <https://docs.python.org/3/library/sysconfig.html#installation-paths>
    for the meaning of keys.

    (Version 5 or above only.)

python_paths_abstract

: Mapping of `sysconfig` path names with placeholder values.

    See <https://docs.python.org/3/library/sysconfig.html#installation-paths>
    for the meaning of keys.

    This is equivalent to calling `sysconfig.get_paths(expand=False)`.

    (Version 6 or above only.)

python_config_vars

: Mapping of string configuration names to string values.

    This is equivalent to `sysconfig.get_config_vars()` with all values
    normalized to strings.

    Many configuration values may represent state as it existed in the
    build environment and aren't appropriate for the run-time environment
    on a different system.

    (Version 6 or above only.)

python_exe

: Relative path to main Python interpreter executable.

python_include

: Relative path to include path for Python headers. If this path is on
    the compiler's include path, `#include <Python.h>` should work.

    (Deprecated in version 5 in favor of `python_paths`.)

python_stdlib

: Relative path to Python's standard library (where `.py` and resource
    files are located).

    (Deprecated in version 5 in favor of `python_paths`.)

python_stdlib_platform_config

: Relative path to a `config-<platform>` directory in the standard
    library containing files used to embed Python in a binary.

    This is a standard directory present in POSIX Python installations
    and is not specific to this project.

    The key may be absent if no platform config directory exists.

    (Version 5 or above only.)

python_stdlib_test_packages

: Array of strings of Python packages that define tests. (Version 4 or above
    only.)

python_suffixes

: A map defining file suffixes for various Python file types. Each entry
    in the map is an array of strings.

    The map has the following keys.

    `bytecode`

    : Suffixes for bytecode modules. Corresponds to
        `importlib.machinery.BYTECODE_SUFFIXES`. e.g. `[".pyc"]`.

    `debug_bytecode`

    : Suffixes for debug bytecode modules. Corresponds to
        `importlib.machinery.DEBUG_BYTECODE_SUFFIXES`. e.g. `[".pyc"]`.

    `extension`

    : Suffixes for extension modules. Corresponds to
        `importlib.machinery.EXTENSION_SUFFIXES`. e.g.
        `[".cpython-313-x86_64-linux-gnu.so", ".abi3.so", ".so"]`.

    `optimized_bytecode`

    : Suffixes for optimized bytecode modules. Corresponds to
        `importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES`. e.g.
        `[".pyc"]`.

    `source`

    : Suffixes for source modules. Corresponds to
        `importlib.machinery.SOURCE_SUFFIXES`. e.g. `[".py"]`.

    (Version 5 or above only.)

python_bytecode_magic_number

: Magic number to use for bytecode files, expressed as a hexadecimal
    string.

    (Version 5 or above only.)

libpython_link_mode

: How `libpython` is linked. Values can be one of the following:

    `static`

    : Statically linked.

    `shared`

    : Dynamically linked. (A `libpythonXY` shared library will be part
        of the distribution.)

    (Version 5 or above only.)

link_mode

: Alias of `libpython_link_mode`.

    (Version 4 or above only. Deprecated in version 5.)

python_symbol_visibility

: Defines how Python symbols are defined in binaries.

    `global-default`

    : (UNIX only.) Symbols are defined as *global* and have *default*
        binding, making them visible outside their defining component.

    `dllexport`

    : (Windows only.) Symbols are exported via `__declspec(dllexport)`,
        making them visible to external libraries.

    (Version 5 or above only.)

python_extension_module_loading

: Defines support for loading Python extension modules.

    The value is an array of strings denoting support for various
    loading mechanisms.

    Note that downstream consumers reconstructing a new binary from
    object files or a static library can alter support depending on
    how that binary is linked.

    The special values are as follows.

    `builtin`

    : Supports loading of *builtin* extension modules compiled into
        the binary. (This should always be present.)

    `shared-library`

    : Supports loading of extension modules defined as shared
        libraries. e.g. from `.so` or `.pyd` files.

    (Version 5 or above only.)

apple_sdk_canonical_name

: Optional canonical name of Apple SDK used to build.

    Should only be present for target triples with `apple` in them.

    The canonical name can be used to find a copy of this SDK on another
    machine.

    (Version 7 or above only.)

apple_sdk_platform

: Optional name of the platform of the Apple SDK used to build.

    Should only be present for target triples with `apple` in them.

    e.g. `macosx`

    (Version 7 or above only.)

apple_sdk_version

: Optional version of the Apple SDK used to build.

    Should only be present for target triples with `apple` in them.

    If relinking build artifacts, ideally this exact SDK version is used.
    Newer versions will likely work. Older versions or Clang toolchains
    associated with older versions may not.

    (Version 7 or above only.)

apple_sdk_deployment_target

: Optional version of the Apple SDK deployment target used to build.

    This effectively establishes a minimum version of the target operating
    system this binary is purportedly compatible with.

    (Version 7 or above only.)

crt_features

: Describes C Runtime features/requirements for binaries.

    The value is an array of strings denoting various properties.

    The special string values are as follows.

    `glibc-dynamic`

    : Binaries link dynamically against glibc.

    `glibc-max-symbol-version:N`

    : Denotes the max symbol version seen in glibc versioned symbols.

        This effectively advertises the oldest version of glibc that
        binaries support and indirectly advertises the oldest Linux
        distributions binaries can run on.

    `static`

    : Binaries link the CRT statically.

    `vcruntime:N`

    : Binaries link against the Microsoft Visual C++ Redistributable Runtime,
        version `N`. `N` is a string like `140`, which denotes the
        version component in a `vcruntimeXYZ.dll` file.

    `libSystem`

    : Binaries link against `libSystem.B.dylib`, which is the mega
        library backing a lot of systems-level functionality in macOS.

    (Version 5 or above only.)

run_tests

: The path to a Python script to run the test harness for this
    distribution.

    (Version 5 or above only.)

build_info

: A map describing build configuration and artifacts for this distribution.

    See the `build_info Data` section below.

licenses

: > Array of strings containing the license shortname identifiers from the
    > SPDX license list (<https://spdx.org/licenses/>) for the Python distribution.

    (Version 2 or above only.)

license_path

: Path to a text file containing the license for this Python distribution.

    (Version 2 or above only.)

tcl_library_path

: Relative path to location of tcl library files. The path should be a
    directory tree containing tcl files to support the tkinter extension.
    This will include a subset of the library files provided by the tcl
    and tk packages.

    This points to the root directory containing tcl resources. Actual
    tcl resources are in sub-directories underneath, as identified by
    `tcl_library_paths`.

    (Version 3 or above only.)

tcl_library_paths

: Array of relative paths holding tcl library files relative to
    `tcl_library_path`.

    Because `tcl_library_path` can be shared with other resources
    (e.g. on UNIX the path is typically `install/lib`, which holds
    system libraries as well), distributions may advertise the list
    of directories under `tcl_library_path` actually containing
    tcl resources.

    (Version 5 or above only.)

### build_info Data

The `build_info` key in the `PYTHON.json` file describes build artifacts
in the Python distribution. The primary goal of the data is to give downstream
distribution consumers enough details to integrate build artifacts into their
own build systems. This includes the ability to produce a Python binary with a
custom set of built-in extension modules.

This map has the following keys:

core

: A map describing the core Python distribution (essentially `libpython`).

    objs

    : An array of paths to object files constituting the Python core distribution.

        Core object files are typically object files that are linked together to
        create libpython.

    links

    : An array of linking requirement maps. (See below for data format.)

    shared_lib

    : Path to a shared library representing `libpython`. May not be defined.
        (Version 4 or above only.)

    static_lib

    : Path to a static library representing `libpython`. May not be defined.
        (Version 4 or above only.)

    inittab_object

    : Path to object file defining `_PyImport_Inittab`, which defines
        built-in extension modules.

        (Version 5 or above only.)

    inittab_source

    : Path to source code file that defines `_PyImport_Inittab`. On
        CPython, this will point to a `config.c` file.

        (Version 5 or above only.)

    inittab_cflags

    : Array of strings constituting compiler flags to use when compiling
        `inittab_source`.

        (Version 5 or above only.)

extensions

: A map of extension names to an array of maps describing candidate extensions.

    Extensions are non-core/non-essential parts of the Python distribution that
    are frequently built as standalone entities.

    Names in this map denote the name of the extension module.

    Values are arrays of maps. Each map represents a potential candidate
    providing the extension. There is frequently only a single extension
    candidate. Multiple candidates can occur if there are e.g. varying
    libraries an extension can be linked against to supply underlying
    functionality.

    Each map has the following keys:

    in_core

    : Boolean indicating if this extension is defined by the core distribution.

        If true, object files should be in the `['core']['objs']` array, not the
        `objs` array in this map.

        Downstream consumers should key off this value to determine how to
        assemble this extension's code into a new distribution.

        This field was introduced to support Windows, where CPython's Visual
        Studio project files define various extensions as part of the project
        providing libpython. This is in contrast to make-based builds, where
        the `Modules/Setup.*` files treat each extension as separate entities.

    init_fn

    : The name of the extension module initialization function for this
        extension.

        The string value may be `NULL`, which may need special handling by
        consumers.

    licenses

    : Array of strings containing the license shortname identifiers from the
        SPDX license list (<https://spdx.org/licenses/>).

        If this field is missing, licenses are unknown. Empty array denotes no known
        licenses.

        The license applies to additional libraries needed by this extension, not
        the extension itself, as extensions should be licensed the same as the
        Python distribution.

        (Version 2 or above only.)

    license_path

    : Paths to text files containing the licenses for this extension.

        (Version 2 or above only.)

    license_public_domain

    : Bool indicating that the license for the extension is in the public
        domain.

        There is no SPDX identifier for public domain. And we want to be explicit
        about something being in the public domain because of the legal implications.

        (Version 2 or above only.)

    links

    : An array of linking requirement maps. (See below for data format.)

    objs

    : An array of paths to object files constituting this extension module.

    required

    : Boolean indicating if this extension is required to initialize the Python
        interpreter.

    shared_lib

    : The path to a shared library defining this extension module. May not
        be defined. (Version 4 or above only.)

    static_lib

    : The path to a static library defining this extension module. May not
        be defined.

    variant

    : String describing this extension variant. Downstream consumers can key off
        this value to choose an appropriate extension variant when there are
        multiple options.

object_file_format

: Denotes the data format for object files. Can be one of the following
    values.

    `elf`

    : Standard object file format for Linux.

    `llvm-bitcode:N`

    : Files are LLVM bitcode produced with LLVM version `N`. e.g.
        `llvm-bitcode:10.0.0`.

        This variant is typically seen for builds using LTO.

    `coff`

    : Standard object file format for Windows.

    `mach-o`

    : Standard object file format for macOS.

    (Version 5 or newer only.)

Each entry in a `links` array is a map with the following keys:

name

: Name of the library being linked against.

path_static

: Path to the static version of this library, if available in the
    distribution.

path_dynamic

: Path to the dynamic version of this library, if available in the
    distribution.

framework

: Denotes that the link target is a macOS framework.

system

: Denotes that the link target is a system library.

    System libraries are typically passed into the linker by name only and
    found using default library search paths.

## Install Only Archive

At release time, this project produces tar files containing just the
Python installation, without the `PYTHON.json` or build files from
the full `.tar.zst` archives. These are referred to as *install only*
archives.

An *install only* archive is created by taking a `.tar.zst` and
rewriting `python/install/*` to `python/*`. All files not under
`python/install/*` are not carried forward to the *install only*
archive.

For each Python version, target, and threading variant, the fastest
available build is selected for the *install only* archive. Builds are
generally preferred in the following order: `pgo+lto`, `pgo`,
`lto`, `noopt`.

An *install only stripped* archive is also available. This archive is
equivalent to *install only*, but without debug symbols, which results in a
smaller download and on-disk footprint.

For CPython 3.13 and newer, *install only* and *install only stripped*
archives are created separately for the GIL-enabled and free-threaded
variants. Free-threaded archives include `freethreaded` in the filename.

For musl targets, *install only* archives use dynamically linked builds.
Fully static musl builds are only available as *full* archives with
`+static` in their build options.

For maximum compatibility, *install only* and *install only stripped*
archives use gzip compression.

---

### Distributions (`docs/distributions.rst`)

.. _distributions:

=====================
Distribution Archives
=====================

This project produces tarball archives containing Python distributions.

Full Archive
============

The canonical output of this project's build system are ``.tar.zst``
(zstandard compressed tarballs) files.

All files within the tar are prefixed with ``python/``.

Within the ``python/`` directory are the following well-known paths:

PYTHON.json
   Machine readable file describing this Python distribution.

   See the ``PYTHON.json File`` section for the format of this file.

By convention, the ``build/`` directory contains artifacts from building
this distribution (object files, libraries, etc) and the ``install/`` directory
contains a working, self-contained Python installation of this distribution.
The ``PYTHON.json`` file should be read to determine where specific entities
are located within the archive.

PYTHON.json File
----------------

The ``PYTHON.json`` file describes the Python distribution in a machine
readable manner. This file is meant to be opened by downstream consumers
of this distribution so that they may learn things about the distribution
without having to resort to heuristics.

The file contains a JSON map. This map has the following keys:

version
   Version number of the file format. Currently ``8``.

target_triple
   A target triple defining the platform and architecture of the machine
   that binaries target. We use Rust's set of defined targets for values.
   Run ``rustup target list`` to see potential values.

   Example values are ``x86_64-unknown-linux-gnu``,
   ``x86_64-unknown-linux-musl``, ``x86_64-pc-windows-msvc``,
   and ``x86_64-apple-darwin``.

   (Version 5 or above only.)

optimizations
   String indicating what optimization profile has been applied to the
   build.

   Known values include ``debug``, ``noopt``, ``pgo``, ``lto``, and
   ``pgo+lto``.

   (Deprecated in version 8 in favor of ``build_options``.)

build_options
   String indicating what build options were used. Options are separated
   by a ``+``.

   Known values include ``debug``, ``noopt``, ``pgo``, ``lto``, ``static``,
   and ``freethreaded``.

   (Version 8 or above only.)

os
   Target operating system for the distribution. e.g. ``linux``, ``macos``,
   or ``windows``.

   (Deprecated in version 5 in favor of ``target_triple``.)

arch
   Target architecture for the distribution. e.g. ``x86`` (32-bit) or
   ``x86_64`` (64-bit).

   (Deprecated in version 5 in favor of ``target_triple``.)

python_tag
   The PEP 425 *Python Tag* value. e.g. ``cp313``.

   (Version 5 or above only.)

python_abi_tag
   The PEP 425 *ABI Tag* value. e.g. ``cp313m``.

   This may be null if the distribution's platform doesn't expose the concept
   of an ABI tag.

   (Version 5 or above only.)

python_platform_tag
   The PEP 425 *Platform Tag* value. e.g. ``linux_x86_64``.

   (Version 5 or above only.)

python_flavor
   Type of Python distribution. e.g. ``cpython``.

   (Deprecated in version 5 in favor of PEP 425 tags.)

python_implementation_cache_tag
   Tag used by import machinery to derive filenames for bytecode files.

   This is the value exposed by ``sys.implementation.cache_tag``

   (Version 5 or above only.)

python_implementation_hex_version
   Hexadecimal expression of implementation version.

   This is the value exposed by ``sys.implementation.hexversion``.

   (Version 5 or above only.)

python_implementation_name
   Name of Python implementation.

   This is the value exposed by ``sys.implementation.name``.

   (Version 5 or above only.)

python_implementation_version
   Array of version components of Python implementation.

   This is the value exposed by ``sys.implementation.version``.

   Unlike ``sys.implementation.version``, all elements are strings,
   not a mix of numbers and strings.

   (Version 5 or above only.)

python_version
   Version of Python distribution. e.g. ``3.13.0``.

python_major_minor_version
   ``X.Y`` version string consisting of Python major and minor version.

   (Version 5 or above only.)

python_paths
   Mapping of ``sysconfig`` path names to paths in the distribution.

   Keys are values like ``stdlib`` and ``include``. Values are relative
   paths within the distribution.

   See https://docs.python.org/3/library/sysconfig.html#installation-paths
   for the meaning of keys.

   (Version 5 or above only.)

python_paths_abstract
   Mapping of ``sysconfig`` path names with placeholder values.

   See https://docs.python.org/3/library/sysconfig.html#installation-paths
   for the meaning of keys.

   This is equivalent to calling ``sysconfig.get_paths(expand=False)``.

   (Version 6 or above only.)

python_config_vars
   Mapping of string configuration names to string values.

   This is equivalent to ``sysconfig.get_config_vars()`` with all values
   normalized to strings.

   Many configuration values may represent state as it existed in the
   build environment and aren't appropriate for the run-time environment
   on a different system.

   (Version 6 or above only.)

python_exe
   Relative path to main Python interpreter executable.

python_include
   Relative path to include path for Python headers. If this path is on
   the compiler's include path, ``#include <Python.h>`` should work.

   (Deprecated in version 5 in favor of ``python_paths``.)

python_stdlib
   Relative path to Python's standard library (where ``.py`` and resource
   files are located).

   (Deprecated in version 5 in favor of ``python_paths``.)

python_stdlib_platform_config
   Relative path to a ``config-<platform>`` directory in the standard
   library containing files used to embed Python in a binary.

   This is a standard directory present in POSIX Python installations
   and is not specific to this project.

   The key may be absent if no platform config directory exists.

   (Version 5 or above only.)

python_stdlib_test_packages
   Array of strings of Python packages that define tests. (Version 4 or above
   only.)

python_suffixes
   A map defining file suffixes for various Python file types. Each entry
   in the map is an array of strings.

   The map has the following keys.

   ``bytecode``
      Suffixes for bytecode modules. Corresponds to
      ``importlib.machinery.BYTECODE_SUFFIXES``. e.g. ``[".pyc"]``.

   ``debug_bytecode``
      Suffixes for debug bytecode modules. Corresponds to
      ``importlib.machinery.DEBUG_BYTECODE_SUFFIXES``. e.g. ``[".pyc"]``.

   ``extension``
      Suffixes for extension modules. Corresponds to
      ``importlib.machinery.EXTENSION_SUFFIXES``. e.g.
      ``[".cpython-313-x86_64-linux-gnu.so", ".abi3.so", ".so"]``.

   ``optimized_bytecode``
      Suffixes for optimized bytecode modules. Corresponds to
      ``importlib.machinery.OPTIMIZED_BYTECODE_SUFFIXES``. e.g.
      ``[".pyc"]``.

   ``source``
      Suffixes for source modules. Corresponds to
      ``importlib.machinery.SOURCE_SUFFIXES``. e.g. ``[".py"]``.

   (Version 5 or above only.)

python_bytecode_magic_number
   Magic number to use for bytecode files, expressed as a hexadecimal
   string.

   (Version 5 or above only.)

libpython_link_mode
   How `libpython` is linked. Values can be one of the following:

   `static`
      Statically linked.

   `shared`
      Dynamically linked. (A `libpythonXY` shared library will be part
      of the distribution.)

   (Version 5 or above only.)

link_mode
   Alias of ``libpython_link_mode``.

   (Version 4 or above only. Deprecated in version 5.)

python_symbol_visibility
   Defines how Python symbols are defined in binaries.

   ``global-default``
      (UNIX only.) Symbols are defined as *global* and have *default*
      binding, making them visible outside their defining component.

   ``dllexport``
      (Windows only.) Symbols are exported via ``__declspec(dllexport)``,
      making them visible to external libraries.

   (Version 5 or above only.)

python_extension_module_loading
   Defines support for loading Python extension modules.

   The value is an array of strings denoting support for various
   loading mechanisms.

   Note that downstream consumers reconstructing a new binary from
   object files or a static library can alter support depending on
   how that binary is linked.

   The special values are as follows.

   ``builtin``
       Supports loading of *builtin* extension modules compiled into
       the binary. (This should always be present.)

   ``shared-library``
       Supports loading of extension modules defined as shared
       libraries. e.g. from ``.so`` or ``.pyd`` files.

   (Version 5 or above only.)

apple_sdk_canonical_name
   Optional canonical name of Apple SDK used to build.

   Should only be present for target triples with ``apple`` in them.

   The canonical name can be used to find a copy of this SDK on another
   machine.

   (Version 7 or above only.)

apple_sdk_platform
   Optional name of the platform of the Apple SDK used to build.

   Should only be present for target triples with ``apple`` in them.

   e.g. ``macosx``

   (Version 7 or above only.)

apple_sdk_version
   Optional version of the Apple SDK used to build.

   Should only be present for target triples with ``apple`` in them.

   If relinking build artifacts, ideally this exact SDK version is used.
   Newer versions will likely work. Older versions or Clang toolchains
   associated with older versions may not.

   (Version 7 or above only.)

apple_sdk_deployment_target
   Optional version of the Apple SDK deployment target used to build.

   This effectively establishes a minimum version of the target operating
   system this binary is purportedly compatible with.

   (Version 7 or above only.)

crt_features
   Describes C Runtime features/requirements for binaries.

   The value is an array of strings denoting various properties.

   The special string values are as follows.

   ``glibc-dynamic``
      Binaries link dynamically against glibc.

   ``glibc-max-symbol-version:N``
      Denotes the max symbol version seen in glibc versioned symbols.

      This effectively advertises the oldest version of glibc that
      binaries support and indirectly advertises the oldest Linux
      distributions binaries can run on.

   ``static``
      Binaries link the CRT statically.

   ``vcruntime:N``
      Binaries link against the Microsoft Visual C++ Redistributable Runtime,
      version ``N``. ``N`` is a string like ``140``, which denotes the
      version component in a ``vcruntimeXYZ.dll`` file.

   ``libSystem``
      Binaries link against ``libSystem.B.dylib``, which is the mega
      library backing a lot of systems-level functionality in macOS.

   (Version 5 or above only.)

run_tests
   The path to a Python script to run the test harness for this
   distribution.

   (Version 5 or above only.)

build_info
   A map describing build configuration and artifacts for this distribution.

   See the ``build_info Data`` section below.

licenses
   Array of strings containing the license shortname identifiers from the
   SPDX license list (https://spdx.org/licenses/) for the Python distribution.

  (Version 2 or above only.)

license_path
   Path to a text file containing the license for this Python distribution.

   (Version 2 or above only.)

tcl_library_path
   Relative path to location of tcl library files. The path should be a
   directory tree containing tcl files to support the tkinter extension.
   This will include a subset of the library files provided by the tcl
   and tk packages.

   This points to the root directory containing tcl resources. Actual
   tcl resources are in sub-directories underneath, as identified by
   ``tcl_library_paths``.

   (Version 3 or above only.)

tcl_library_paths
   Array of relative paths holding tcl library files relative to
   ``tcl_library_path``.

   Because ``tcl_library_path`` can be shared with other resources
   (e.g. on UNIX the path is typically ``install/lib``, which holds
   system libraries as well), distributions may advertise the list
   of directories under ``tcl_library_path`` actually containing
   tcl resources.

   (Version 5 or above only.)

build_info Data
---------------

The ``build_info`` key in the ``PYTHON.json`` file describes build artifacts
in the Python distribution. The primary goal of the data is to give downstream
distribution consumers enough details to integrate build artifacts into their
own build systems. This includes the ability to produce a Python binary with a
custom set of built-in extension modules.

This map has the following keys:

core
   A map describing the core Python distribution (essentially `libpython`).

   objs
      An array of paths to object files constituting the Python core distribution.

      Core object files are typically object files that are linked together to
      create libpython.

   links
      An array of linking requirement maps. (See below for data format.)

   shared_lib
      Path to a shared library representing `libpython`. May not be defined.
      (Version 4 or above only.)

   static_lib
      Path to a static library representing `libpython`. May not be defined.
      (Version 4 or above only.)

   inittab_object
      Path to object file defining ``_PyImport_Inittab``, which defines
      built-in extension modules.

      (Version 5 or above only.)

   inittab_source
      Path to source code file that defines ``_PyImport_Inittab``. On
      CPython, this will point to a ``config.c`` file.

      (Version 5 or above only.)

   inittab_cflags
      Array of strings constituting compiler flags to use when compiling
      ``inittab_source``.

      (Version 5 or above only.)

extensions
   A map of extension names to an array of maps describing candidate extensions.

   Extensions are non-core/non-essential parts of the Python distribution that
   are frequently built as standalone entities.

   Names in this map denote the name of the extension module.

   Values are arrays of maps. Each map represents a potential candidate
   providing the extension. There is frequently only a single extension
   candidate. Multiple candidates can occur if there are e.g. varying
   libraries an extension can be linked against to supply underlying
   functionality.

   Each map has the following keys:

   in_core
      Boolean indicating if this extension is defined by the core distribution.

      If true, object files should be in the ``['core']['objs']`` array, not the
      ``objs`` array in this map.

      Downstream consumers should key off this value to determine how to
      assemble this extension's code into a new distribution.

      This field was introduced to support Windows, where CPython's Visual
      Studio project files define various extensions as part of the project
      providing libpython. This is in contrast to make-based builds, where
      the ``Modules/Setup.*`` files treat each extension as separate entities.

   init_fn
      The name of the extension module initialization function for this
      extension.

      The string value may be ``NULL``, which may need special handling by
      consumers.

   licenses
      Array of strings containing the license shortname identifiers from the
      SPDX license list (https://spdx.org/licenses/).

      If this field is missing, licenses are unknown. Empty array denotes no known
      licenses.

      The license applies to additional libraries needed by this extension, not
      the extension itself, as extensions should be licensed the same as the
      Python distribution.

      (Version 2 or above only.)

   license_path
      Paths to text files containing the licenses for this extension.

      (Version 2 or above only.)

   license_public_domain
      Bool indicating that the license for the extension is in the public
      domain.

      There is no SPDX identifier for public domain. And we want to be explicit
      about something being in the public domain because of the legal implications.

      (Version 2 or above only.)

   links
      An array of linking requirement maps. (See below for data format.)

   objs
      An array of paths to object files constituting this extension module.

   required
      Boolean indicating if this extension is required to initialize the Python
      interpreter.

   shared_lib
      The path to a shared library defining this extension module. May not
      be defined. (Version 4 or above only.)

   static_lib
      The path to a static library defining this extension module. May not
      be defined.

   variant
      String describing this extension variant. Downstream consumers can key off
      this value to choose an appropriate extension variant when there are
      multiple options.

object_file_format
   Denotes the data format for object files. Can be one of the following
   values.

   ``elf``
       Standard object file format for Linux.

   ``llvm-bitcode:N``
       Files are LLVM bitcode produced with LLVM version ``N``. e.g.
       ``llvm-bitcode:10.0.0``.

       This variant is typically seen for builds using LTO.

   ``coff``
       Standard object file format for Windows.

   ``mach-o``
       Standard object file format for macOS.

   (Version 5 or newer only.)

Each entry in a ``links`` array is a map with the following keys:

name
   Name of the library being linked against.

path_static
   Path to the static version of this library, if available in the
   distribution.

path_dynamic
   Path to the dynamic version of this library, if available in the
   distribution.

framework
   Denotes that the link target is a macOS framework.

system
   Denotes that the link target is a system library.

   System libraries are typically passed into the linker by name only and
   found using default library search paths.

Install Only Archive
====================

At release time, this project produces tar files containing just the
Python installation, without the ``PYTHON.json`` or build files from
the full ``.tar.zst`` archives. These are referred to as *install only*
archives.

An *install only* archive is created by taking a ``.tar.zst`` and
rewriting ``python/install/*`` to ``python/*``. All files not under
``python/install/*`` are not carried forward to the *install only*
archive.

For each Python version, target, and threading variant, the fastest
available build is selected for the *install only* archive. Builds are
generally preferred in the following order: ``pgo+lto``, ``pgo``,
``lto``, ``noopt``.

An *install only stripped* archive is also available. This archive is
equivalent to *install only*, but without debug symbols, which results in a
smaller download and on-disk footprint.

For CPython 3.13 and newer, *install only* and *install only stripped*
archives are created separately for the GIL-enabled and free-threaded
variants. Free-threaded archives include ``freethreaded`` in the filename.

For musl targets, *install only* archives use dynamically linked builds.
Fully static musl builds are only available as *full* archives with
``+static`` in their build options.

For maximum compatibility, *install only* and *install only stripped*
archives use gzip compression.

---

### Index (`docs/index.rst`)

Python Standalone Builds
========================

This project produces self-contained, highly portable, high-performance
Python distributions. These Python distributions contain a fully usable,
full-featured Python installation: most extension modules from the Python
standard library are present, and their library dependencies are either
distributed with the distribution or are statically linked.

The Python distributions are built in a manner to minimize
run-time dependencies. This includes limiting the CPU instructions
that can be used and limiting the set of shared libraries required
at run-time. The goal is for the produced distribution to work on
any system for the targeted architecture.

The builds incorporate compiler optimizations such as profile-guided
optimization (PGO), link-time optimization (LTO), and, where appropriate,
BOLT post-link binary optimization. Together, these techniques improve
runtime performance while preserving portability.

The most common method of using these distributions is with
`uv <https://docs.astral.sh/uv/>`_.

To run a particular distribution using ``uv``::

    uvx --managed-python python

A Python version or another specifier can be included::

    uvx --managed-python python@3.13
    uvx --managed-python python@3.14+freethreaded

.. toctree::
   :maxdepth: 2
   :caption: Contents:

   running
   building
   quirks
   technotes
   distributions
   status

Indices and tables
==================

* :ref:`genindex`
* :ref:`search`

---

### Quirks (`docs/quirks.md`)

<a id="quirks"></a>

# Behavior Quirks

While these Python distributions are intended to be broadly compatible
with the Python ecosystem, there are a few known behavior quirks that
affect specific environments, packages, or use cases.

<a id="quirk-backspace-key"></a>

## If special keys do not work in the Python REPL

If you attempt to run `python` and the backspace key doesn't
erase characters or the arrow keys don't work as expected, this
is because the executable can't find the *terminfo database*.

If this happens, the Python REPL will print the following warning
message on startup:

```
Cannot read termcap database;
using dumb terminal settings.
```

When you type a special key like the backspace key, this is
registered as a key press. There is special software (typically
`readline` or `libedit`) that most interactive programs use
that intercepts these special key presses and converts them into
special behavior, such as moving the cursor back instead of
forward. But because computer environments are different,
there needs to be some definition of how these special
behaviors are performed. This is the *terminfo database*.

When `readline` and `libedit` are compiled, there is
typically a hard-coded set of search locations for the
*terminfo database* baked into the built library. And when
you build a program (like Python) locally, you link against
`readline` or `libedit` and get these default locations
*for free*.

These Python distributions compile and use their own version of
`libedit` to avoid a dependency on what is (or isn't) installed on
your system. This means that they do not use your system-provided
libraries for reading the *terminfo database*. This version of
`libedit` is configured to look for in locations that should work for
most OSes (specifically, `/usr/share/terminfo` on macOS, and
`/etc/terminfo`, `/lib/terminfo`, and `/usr/share/terminfo` on
Linux, which should cover all major Linux distributions), but it is
possible that your environment has it somewhere else. If your OS stores
the *terminfo database* in an uncommon location, you can set the
`TERMINFO_DIRS` environment variable so that `libedit` can find it.

For instance, you may need to do something like:

> $ TERMINFO_DIRS=/uncommon/place/terminfo install/bin/python3.10

If you are running on a relatively standard OS and this does not work
out of the box, please file a bug report so we can add the location of
the *terminfo database* to the build.

For convenience, a relatively recent copy of the terminfo database
is distributed in the `share/terminfo` directory (`../../share/terminfo`
relative to the `bin/python3` executable) in Linux distributions. Note
that ncurses and derived libraries don't know how to find this directory
since they are configured to use absolute paths to the terminfo database
and the absolute path of the Python distribution is obviously not known
at build time! So actually using this bundled terminfo database will
require custom code setting `TERMINFO_DIRS` before
ncurses/libedit/readline are loaded.

<a id="quirk-macos-no-tix"></a>

## No tix on UNIX

Tix is an old widget library for Tcl/Tk. Python previously had a wrapper
for it in `tkinter.tix`, but it was deprecated in Python 3.6 (the
recommendation is to use `tkinter.ttk`) and removed in Python 3.13.

The macOS and Linux distributions from this project do not build and
ship Tix, even for Python versions 3.12 and below.

We had previously attempted to ship Tix support on Linux, but it was
broken and nobody reported an issue about it. The macOS distributions
from this project never shipped support for Tix. The official Python.org
macOS installers and Apple's build of Python do not ship support for
Tix, either, so this project behaves similarly to those distributions.

<a id="quirk-windows-no-pip"></a>

## No `pip.exe` on Windows

The Windows distributions have `pip` installed however no `Scripts/pip.exe`,
`Scripts/pip3.exe`, and `Scripts/pipX.Y.exe` files are provided because
the way these executables are built isn't portable. (It might be possible to
change how these are built to make them portable.)

To use pip, run `python.exe -m pip`. (It is generally a best practice to
invoke pip via `python -m pip` on all platforms so you can be explicit
about the `python` executable that pip uses.)

<a id="quirk-macos-linking"></a>

## Linking Static Library on macOS

Python 3.10+ makes use of the `__builtin_available()` compiler feature.
This functionality requires a symbol from `libclang_rt`, which may not
be linked by default. Failure to link against `libclang_rt` could result
in a linker error due to an undefined symbol `___isOSVersionAtLeast`.

To work around this linker failure, link against the static library
`libclang_rt.<platform>.a` present in the Clang installation. e.g.
`libclang_rt.osx.a`. You can find this library by invoking
`clang --print-search-dirs` and looking in the `lib/darwin` directory
under the printed `libraries` directory. An example path is
`/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/lib/darwin/libclang_rt.osx.a`.

A copy of the `libclang_rt.<platform>.a` from the Clang used to build
the distribution is included in the archive. However, it isn't annotated
in `PYTHON.json` because we're unsure if using the file with another
build/version of Clang is supported. Use at your own risk.

See <https://jonnyzzz.com/blog/2018/06/05/link-error-2/> and
<https://jonnyzzz.com/blog/2018/06/13/link-error-3/> for more on this topic.

<a id="quirk-linux-libedit"></a>

## Use of `libedit` on Linux

Python 3.10+ Linux distributions link against `libedit` (as opposed to
`readline`) by default, as `libedit` is supported on 3.10+ outside of
macOS.

Most Python builds on Linux will link against `readline` because `readline`
is the dominant library on Linux.

Some functionality may behave subtly differently as a result of our choice
to link `libedit` by default. (We choose `libedit` by default to
avoid GPL licensing requirements of `readline`.)

<a id="quirk-references-to-build-paths"></a>

## References to Build-Time Paths

The built Python distribution captures some absolute paths and other
build-time configuration in a handful of files:

- In a `_sysconfigdata_*.py` file in the standard library. e.g.
  `lib/python3.10/_sysconfigdata__linux_x86_64-linux-gnu.py`.
- In a `Makefile` under a `config-*` directory in the standard library.
  e.g. `lib/python3.10/config-3.10-x86_64-linux-gnu/Makefile`.
- In python-build-standalone's metadata file `PYTHON.json` (mostly
  reflected values from `_sysconfigdata_*.py`).

Each of these serves a different use case. But the general theme is various
aspects of the Python distribution attempt to capture how Python was built.
The most common use of these values is to facilitate compiling or linking
other software against this Python build. For example, the `_sysconfigdata*`
module is loaded by the [sysconfig](https://docs.python.org/3/library/sysconfig.html)
module. `sysconfig` in turn is used by packaging tools like `setuptools`
and `pip` to figure out how to invoke a compiler for e.g. compiling C
extensions from source.

When installed by [uv](https://docs.astral.sh/uv/), these absolute
paths are fixed up to point to the actual location on your system where
the distribution was installed, so **this quirk generally does not
affect uv users**. The third-party tool [sysconfigpatcher](https://github.com/bluss/sysconfigpatcher) also does this and might
be helpful to use or reference if you are installing these distributions
on your own.

In particular, you may see references to our install-time paths on the
build infrastructure, e.g., `/build` and `/install` on Linux, a
particular SDK in `/Applications/Xcode.app` on macOS, and temporary
directories on Windows.

Also, Python reports the compiler and flags in use, just in case it is
needed to make binary-compatible extensions. On Linux, for instance, we
use our own builds of Clang and potentially some flags (warnings,
optimizations, locations of the build environment) that do not work or
apply in other environments. We try to configure Python to remove
unneeded flags and absolute paths to files in the build environment.
references to build-time paths. Python's `sysconfig` system requires
listing a compiler, so we leave it set to `clang` without the absolute
path, but you should be able to use another compiler like `gcc` to
compile extensions, too.

If there is a build time normalization that you think should be performed to
make distributions more portable, please file a GitHub issue.

<a id="quirk-former"></a>

<a id="quirk-missing-libcrypt"></a>

<a id="quirk-linux-libx11"></a>

## Former quirks

The following quirks were previously listed on this page but have since
been resolved.

- "Static Linking of musl libc Prevents Extension Module Library
  Loading": Starting with the 20250311 release, the default musl
  distributions are dynamically linked by default, so extension modules
  should work properly. Note that these now require a system-wide
  installation of the musl C library. (This is present by default on
  musl-based OSes like Alpine, and many glibc-based distros have a
  `musl` package you can safely co-install with glibc, too.) If you
  specifically need a statically-linked binary, variants with the
  `+static` build option are available, but these retain the quirk
  that compiled extension modules (e.g., `musllinux` wheels) cannot be
  loaded.
- "Missing `libcrypt.so.1`": The 20230507 release and earlier required
  the system library `libcrypt.so.1`, which stopped being shipped by
  default in several Linux distributions around 2022. Starting with the
  20230726 release, this dependency is now only needed by the deprecated
  `crypt` module, which only exists on Python 3.12 and lower. If you
  still need this module, your OS may offer a `libxcrypt` package to
  provide this library. Alternatively, there are suggestions in [What's
  New in Python 3.13][what's new in python 3.13] about third-party replacements for the `crypt`
  module.
- "Static Linking of `libX11` / Incompatibility with PyQt on Linux":
  The 20220318 release and earlier exported dynamic symbols for the
  internal, statically-linked build of `libX11` and other libraries.
  These would cause conflicts and potential crashes when using
  third-party extension modules such as PyQt that load an actual shared
  `libX11` library (usually provided by your OS). Starting with the
  20220502 release, symbols from internal dependencies are no longer
  exported.

[what's new in python 3.13]: https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-pep594

---

### Quirks (`docs/quirks.rst`)

.. _quirks:

===============
Behavior Quirks
===============

While these Python distributions are intended to be broadly compatible
with the Python ecosystem, there are a few known behavior quirks that
affect specific environments, packages, or use cases.

.. _quirk_backspace_key:

If special keys do not work in the Python REPL
==============================================

If you attempt to run ``python`` and the backspace key doesn't
erase characters or the arrow keys don't work as expected, this
is because the executable can't find the *terminfo database*.

If this happens, the Python REPL will print the following warning
message on startup::

   Cannot read termcap database;
   using dumb terminal settings.

When you type a special key like the backspace key, this is
registered as a key press. There is special software (typically
``readline`` or ``libedit``) that most interactive programs use
that intercepts these special key presses and converts them into
special behavior, such as moving the cursor back instead of
forward. But because computer environments are different,
there needs to be some definition of how these special
behaviors are performed. This is the *terminfo database*.

When ``readline`` and ``libedit`` are compiled, there is
typically a hard-coded set of search locations for the
*terminfo database* baked into the built library. And when
you build a program (like Python) locally, you link against
``readline`` or ``libedit`` and get these default locations
*for free*.

These Python distributions compile and use their own version of
``libedit`` to avoid a dependency on what is (or isn't) installed on
your system. This means that they do not use your system-provided
libraries for reading the *terminfo database*.  This version of
``libedit`` is configured to look for in locations that should work for
most OSes (specifically, ``/usr/share/terminfo`` on macOS, and
``/etc/terminfo``, ``/lib/terminfo``, and ``/usr/share/terminfo`` on
Linux, which should cover all major Linux distributions), but it is
possible that your environment has it somewhere else. If your OS stores
the *terminfo database* in an uncommon location, you can set the
``TERMINFO_DIRS`` environment variable so that ``libedit`` can find it.

For instance, you may need to do something like:

   $ TERMINFO_DIRS=/uncommon/place/terminfo install/bin/python3.10

If you are running on a relatively standard OS and this does not work
out of the box, please file a bug report so we can add the location of
the *terminfo database* to the build.

For convenience, a relatively recent copy of the terminfo database
is distributed in the ``share/terminfo`` directory (``../../share/terminfo``
relative to the ``bin/python3`` executable) in Linux distributions. Note
that ncurses and derived libraries don't know how to find this directory
since they are configured to use absolute paths to the terminfo database
and the absolute path of the Python distribution is obviously not known
at build time! So actually using this bundled terminfo database will
require custom code setting ``TERMINFO_DIRS`` before
ncurses/libedit/readline are loaded.

.. _quirk_macos_no_tix:

No tix on UNIX
==============

Tix is an old widget library for Tcl/Tk. Python previously had a wrapper
for it in ``tkinter.tix``, but it was deprecated in Python 3.6 (the
recommendation is to use ``tkinter.ttk``) and removed in Python 3.13.

The macOS and Linux distributions from this project do not build and
ship Tix, even for Python versions 3.12 and below.

We had previously attempted to ship Tix support on Linux, but it was
broken and nobody reported an issue about it. The macOS distributions
from this project never shipped support for Tix. The official Python.org
macOS installers and Apple's build of Python do not ship support for
Tix, either, so this project behaves similarly to those distributions.

.. _quirk_windows_no_pip:

No ``pip.exe`` on Windows
=========================

The Windows distributions have ``pip`` installed however no ``Scripts/pip.exe``,
``Scripts/pip3.exe``, and ``Scripts/pipX.Y.exe`` files are provided because
the way these executables are built isn't portable. (It might be possible to
change how these are built to make them portable.)

To use pip, run ``python.exe -m pip``. (It is generally a best practice to
invoke pip via ``python -m pip`` on all platforms so you can be explicit
about the ``python`` executable that pip uses.)

.. _quirk_macos_linking:

Linking Static Library on macOS
===============================

Python 3.10+ makes use of the ``__builtin_available()`` compiler feature.
This functionality requires a symbol from ``libclang_rt``, which may not
be linked by default. Failure to link against ``libclang_rt`` could result
in a linker error due to an undefined symbol ``___isOSVersionAtLeast``.

To work around this linker failure, link against the static library
``libclang_rt.<platform>.a`` present in the Clang installation. e.g.
``libclang_rt.osx.a``. You can find this library by invoking
``clang --print-search-dirs`` and looking in the ``lib/darwin`` directory
under the printed ``libraries`` directory. An example path is
``/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/lib/darwin/libclang_rt.osx.a``.

A copy of the ``libclang_rt.<platform>.a`` from the Clang used to build
the distribution is included in the archive. However, it isn't annotated
in ``PYTHON.json`` because we're unsure if using the file with another
build/version of Clang is supported. Use at your own risk.

See https://jonnyzzz.com/blog/2018/06/05/link-error-2/ and
https://jonnyzzz.com/blog/2018/06/13/link-error-3/ for more on this topic.

.. _quirk_linux_libedit:

Use of ``libedit`` on Linux
===========================

Python 3.10+ Linux distributions link against ``libedit`` (as opposed to
``readline``) by default, as ``libedit`` is supported on 3.10+ outside of
macOS.

Most Python builds on Linux will link against ``readline`` because ``readline``
is the dominant library on Linux.

Some functionality may behave subtly differently as a result of our choice
to link ``libedit`` by default. (We choose ``libedit`` by default to
avoid GPL licensing requirements of ``readline``.)


.. _quirk_references_to_build_paths:

References to Build-Time Paths
==============================

The built Python distribution captures some absolute paths and other
build-time configuration in a handful of files:

* In a ``_sysconfigdata_*.py`` file in the standard library. e.g.
  ``lib/python3.10/_sysconfigdata__linux_x86_64-linux-gnu.py``.
* In a ``Makefile`` under a ``config-*`` directory in the standard library.
  e.g. ``lib/python3.10/config-3.10-x86_64-linux-gnu/Makefile``.
* In python-build-standalone's metadata file ``PYTHON.json`` (mostly
  reflected values from ``_sysconfigdata_*.py``).

Each of these serves a different use case. But the general theme is various
aspects of the Python distribution attempt to capture how Python was built.
The most common use of these values is to facilitate compiling or linking
other software against this Python build. For example, the ``_sysconfigdata*``
module is loaded by the `sysconfig <https://docs.python.org/3/library/sysconfig.html>`_
module. ``sysconfig`` in turn is used by packaging tools like ``setuptools``
and ``pip`` to figure out how to invoke a compiler for e.g. compiling C
extensions from source.

When installed by `uv <https://docs.astral.sh/uv/>`_, these absolute
paths are fixed up to point to the actual location on your system where
the distribution was installed, so **this quirk generally does not
affect uv users**.  The third-party tool `sysconfigpatcher
<https://github.com/bluss/sysconfigpatcher>`_ also does this and might
be helpful to use or reference if you are installing these distributions
on your own.

In particular, you may see references to our install-time paths on the
build infrastructure, e.g., ``/build`` and ``/install`` on Linux, a
particular SDK in ``/Applications/Xcode.app`` on macOS, and temporary
directories on Windows.

Also, Python reports the compiler and flags in use, just in case it is
needed to make binary-compatible extensions. On Linux, for instance, we
use our own builds of Clang and potentially some flags (warnings,
optimizations, locations of the build environment) that do not work or
apply in other environments.  We try to configure Python to remove
unneeded flags and absolute paths to files in the build environment.
references to build-time paths.  Python's ``sysconfig`` system requires
listing a compiler, so we leave it set to ``clang`` without the absolute
path, but you should be able to use another compiler like ``gcc`` to
compile extensions, too.

If there is a build time normalization that you think should be performed to
make distributions more portable, please file a GitHub issue.

.. _quirk_former:
.. _quirk_missing_libcrypt:
.. _quirk_linux_libx11:

Former quirks
=============

The following quirks were previously listed on this page but have since
been resolved.

* "Static Linking of musl libc Prevents Extension Module Library
  Loading": Starting with the 20250311 release, the default musl
  distributions are dynamically linked by default, so extension modules
  should work properly. Note that these now require a system-wide
  installation of the musl C library. (This is present by default on
  musl-based OSes like Alpine, and many glibc-based distros have a
  ``musl`` package you can safely co-install with glibc, too.) If you
  specifically need a statically-linked binary, variants with the
  ``+static`` build option are available, but these retain the quirk
  that compiled extension modules (e.g., ``musllinux`` wheels) cannot be
  loaded.

* "Missing ``libcrypt.so.1``": The 20230507 release and earlier required
  the system library ``libcrypt.so.1``, which stopped being shipped by
  default in several Linux distributions around 2022. Starting with the
  20230726 release, this dependency is now only needed by the deprecated
  ``crypt`` module, which only exists on Python 3.12 and lower. If you
  still need this module, your OS may offer a ``libxcrypt`` package to
  provide this library. Alternatively, there are suggestions in `What's
  New in Python 3.13`_ about third-party replacements for the ``crypt``
  module.

* "Static Linking of ``libX11`` / Incompatibility with PyQt on Linux":
  The 20220318 release and earlier exported dynamic symbols for the
  internal, statically-linked build of ``libX11`` and other libraries.
  These would cause conflicts and potential crashes when using
  third-party extension modules such as PyQt that load an actual shared
  ``libX11`` library (usually provided by your OS). Starting with the
  20220502 release, symbols from internal dependencies are no longer
  exported.

.. _What's New in Python 3.13: https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-pep594

---

### Running (`docs/running.md`)

<a id="running"></a>

# Running Distributions

## Using uv

The most common method of using the prebuilt distributions from this
project is with [uv](https://docs.astral.sh/uv/). By default, uv will
download, install, and use an appropriate distribution if the system does
not provide a compatible Python installation that uv can discover. These
downloaded distributions are referred to as *managed* Python installations,
as compared to *system* Python installations. You can configure uv to
always use a *managed* Python installation, for example by using the
`--managed-python` flag.

To run a particular distribution using `uv`:

```
uvx --managed-python python
```

A Python version or another specifier can be included:

```
uvx --managed-python python@3.13
uvx --managed-python python@3.14+freethreaded
```

The uv documentation on
[installing Python](https://docs.astral.sh/uv/guides/install-python/)
and [Python versions](https://docs.astral.sh/uv/concepts/python-versions/)
provides more information and examples.

## Obtaining Distributions

Prebuilt distributions are published as releases on GitHub at
<https://github.com/astral-sh/python-build-standalone/releases>.
Simply go to that page and find the latest release along with
its release notes.

Machines can find the latest release by querying the GitHub releases
API. Alternatively, a JSON file publishing metadata about the latest
release can be fetched from
<https://raw.githubusercontent.com/astral-sh/python-build-standalone/latest-release/latest-release.json>.
The JSON format is simple and hopefully self-descriptive.

Published distributions vary by their:

- Python version
- Target machine architecture
- Build configuration
- Archive flavor

The Python version is hopefully pretty obvious.

The target machine architecture defines the CPU type and operating
system the distribution runs on. We use LLVM target triples.
Distributions are produced for the following target triples:

`aarch64-apple-darwin`

: macOS ARM CPUs, i.e., Apple Silicon.

`x86_64-apple-darwin`

: macOS Intel CPUs.

`x86_64-pc-windows-msvc`

: Windows 64-bit Intel/AMD CPUs.

`i686-pc-windows-msvc`

: Windows 32-bit Intel/AMD CPUs.

`aarch64-pc-windows-msvc`

: Windows 64-bit ARM CPUs. Available for CPython 3.11 and newer.

`x86_64-unknown-linux-gnu`

: Linux 64-bit Intel/AMD CPUs linking against GNU libc.

`x86_64-unknown-linux-musl`

: Linux 64-bit Intel/AMD CPUs linking against musl libc.

    Distributions are provided that dynamically link musl or are fully static
    (`+static`). Dynamically linked distributions require musl to be installed
    on the host. Fully static distributions have no shared library dependencies,
    but cannot load Python `.so` extensions.

`aarch64-unknown-linux-*`

: Similar to above except targeting Linux on ARM64 CPUs. Distributions
    are provided for GNU libc, musl, and static musl.

    For example, this target supports AWS Graviton EC2 instances. Many
    Linux ARM devices are also `aarch64`.

`x86_64_v2-*`

: Targets 64-bit Intel/AMD CPUs approximately newer than
    [Nehalem](<https://en.wikipedia.org/wiki/Nehalem_(microarchitecture)>)
    (released in 2008).

    Binaries will have SSE3, SSE4, and other CPU instructions added after the
    ~initial x86-64 CPUs were launched in 2003.

    Binaries will crash if you attempt to run them on an older CPU not
    supporting the newer instructions.

`x86_64_v3-*`

: Targets 64-bit Intel/AMD CPUs approximately newer than
    [Haswell](<https://en.wikipedia.org/wiki/Haswell_(microarchitecture)>)
    (released in 2013) and
    [Excavator](<https://en.wikipedia.org/wiki/Excavator_(microarchitecture)>)
    (released in 2015).

    Binaries will have AVX, AVX2, MOVBE and other newer CPU instructions.

    Binaries will crash if you attempt to run them on an older CPU not
    supporting the newer instructions.

    Most x86-64 CPUs manufactured after 2013 (Intel) or 2015 (AMD) support
    this microarchitecture level. An exception is Intel Atom P processors,
    which Intel released in 2020 but did not include AVX.

`x86_64_v4-*`

: Targets 64-bit Intel/AMD CPUs with some AVX-512 instructions.

    Requires Intel CPUs manufactured after ~2017. But many Intel CPUs don't
    have AVX-512.

The `x86_64_v2`, `x86_64_v3`, and `x86_64_v4` binaries usually crash
on startup when run on an incompatible CPU. We don't recommend running the
`x86_64_v4` builds in production because they likely don't yield a reliable
performance benefit. Unless you are executing these binaries on a CPU older
than ~2008 or ~2013, we recommend running the `x86_64_v2` or `x86_64_v3`
binaries, as these should be slightly faster since they take advantage
of more modern CPU instructions which are more efficient. But if you want
maximum portability, stick with the baseline `x86_64` builds.

`armv7-unknown-linux-gnueabi`

: Linux 32-bit ARM CPUs without hardware floating-point instructions,
    linking against GNU libc.

    This is an uncommon platform. In most cases, the hardware floating-point
    target should be used. These distributions can be used on Debian's
    `armel` port.

`armv7-unknown-linux-gnueabihf`

: Linux 32-bit ARM CPUs with hardware floating-point instructions,
    linking against GNU libc.

    This is a common 32-bit ARM platform. Raspberry Pi model 2 and later
    can use these distributions on many 32-bit Linux distributions.

`ppc64le-unknown-linux-gnu`

: Linux 64-bit POWER8+ CPUs linking against GNU libc.

`riscv64-unknown-linux-gnu`

: Linux 64-bit RISC-V CPUs linking against GNU libc.

`s390x-unknown-linux-gnu`

: Linux 64-bit IBM Z (s390x) CPUs linking against GNU libc.

We recommend using the `*-unknown-linux-gnu` builds on Linux, since they
are able to load compiled Python extensions. The non-static
`*-unknown-linux-musl` builds should be used on musl-based Linux
distributions like Alpine Linux. If you don't need to load compiled
extensions not provided by the standard library, or you are willing to
compile and link third-party extensions into a custom binary, the static
`*-unknown-linux-musl` builds should work just fine.

The build configuration denotes how Python and its dependencies were built.
Common configurations include:

`pgo+lto`

: Profile-guided optimization and link-time optimization. **These should be
    the fastest distributions since they have the most build-time
    optimizations.**

`pgo`

: Profile-guided optimization.

    Starting with CPython 3.12, BOLT is also applied alongside traditional
    PGO on platforms supporting BOLT. (Currently just Linux x86-64.)

`lto`

: Link-time optimization.

`noopt`

: A regular optimized build without PGO or LTO.

`debug`

: A debug build. No optimizations.

    On Windows, a debug build links against the debug C runtime
    (`ucrtbased.dll` and `vcruntime*d.dll`). That runtime ships with Visual
    Studio and is not redistributable, so a Windows debug distribution only
    runs on a machine with Visual Studio installed.

`freethreaded`

: A free-threaded build, available for CPython 3.13 and newer. This
    option is combined with an optimization option, such as
    `freethreaded+pgo+lto` or `freethreaded+lto`.

`static`

: A fully static musl build. Has no shared library dependencies and
    cannot load dynamically linked Python extensions.

The archive flavor denotes the content in the archive. See
[Distribution Archives](distributions.md#distributions) for more.

Casual users will likely want to use the `install_only` archive, as most
users do not need the build artifacts present in the `full` archive.
The `install_only` archive does not include the optimization options in
its filename. For each Python version, target, and threading variant,
it uses the fastest available build configuration.

An `install_only_stripped` archive is also available. This archive is
equivalent to `install_only`, but without debug symbols, which results
in a smaller download and on-disk footprint. For CPython 3.13 and newer,
free-threaded archives are identified by `freethreaded` in the filename.

Fully static musl builds are only available as `full` archives with
`+static` in their build options. The `install_only` and
`install_only_stripped` musl archives use dynamically linked builds.

## Extracting Distributions

Distributions are defined as zstandard or gzip compressed tarballs.

Modern versions of `tar` support zstandard and you can extract
like any normal archive:

```
$ tar -axvf path/to/distribution.tar.zstd
```

(The `-a` argument tells tar to guess the compression format by
the file extension.)

If your `tar` doesn't support `-a` (e.g. the default macOS `tar`),
try:

```
$ tar xvf path/to/distribution.tar.zstd
```

If you do not have `tar`, you can install and use the `zstd`
tool (typically available via a `zstd` or `zstandard` system
package):

```
$ zstd -d path/to/distribution.tar.zstd
$ tar -xvf path/to/distribution.tar
```

If you want to extract the distribution with Python, use the
`zstandard` Python package:

```python
import tarfile
import zstandard

with open("path/to/distribution.tar.zstd", "rb") as ifh:
    dctx = zstandard.ZstdDecompressor()
    with dctx.stream_reader(ifh) as reader:
        with tarfile.open(mode="r|", fileobj=reader) as tf:
            tf.extractall("path/to/output/directory")
```

## Runtime Requirements

### Linux

The produced Linux binaries have minimal references to shared
libraries and thus can be executed on most Linux systems.

Distributions linked against glibc may reference the following shared
libraries:

- linux-vdso.so.1
- libpthread.so.0
- libdl.so.2 (required by ctypes extension)
- libutil.so.1
- librt.so.1
- libm.so.6
- libc.so.6
- ld-linux-x86-64.so.2

On Python 3.12 and earlier, the deprecated `crypt` module additionally
requires `libcrypt.so.1`.

The minimum glibc version required for most targets is 2.17. This should make
binaries compatible with the following Linux distributions:

- Fedora 21+
- RHEL/CentOS 7+
- openSUSE 13.2+
- Debian 8+ (Jessie)
- Ubuntu 14.04+

For the `riscv64-unknown-linux-gnu` target, the minimum glibc version is
2.28.

Distributions linked against musl do not depend on glibc. By default, musl
distributions are dynamically linked and require musl to be installed on the
host. Fully static distributions use the `+static` build option and have
no shared library dependencies, but cannot load dynamically linked Python
extension modules.

### Windows

Windows distributions model the requirements of the official Python
distributions:

- CPython 3.14 and newer: Windows 10 or newer.
- CPython 3.13 and earlier: Windows 8.1 or newer.

Windows Server support follows the corresponding CPython release's
upstream platform policy.

## Extra Python Software

Python installations have some additional software pre-installed:

- [pip](https://pypi.org/project/pip/)
- [setuptools](https://pypi.org/project/setuptools/) (for Python 3.11 and older)

The intent of the pre-installed software is to facilitate end-user
package installation without having to first bootstrap a packaging
tool via an insecure installation technique (such as `curl | sh`
patterns).

## Licensing

Python and its various dependencies are governed by varied software use
licenses. This impacts the rights and requirements of downstream consumers.

Most licenses are fairly permissive. Notable exceptions to this are GDBM and
readline, which are both licensed under GPL Version 3.

We build CPython against libedit - as opposed to readline - to avoid this
GPL dependency. This requires patches on CPython < 3.10. Distribution releases
before 2023 may link against readline and are therefore subject to the GPL.

We globally disable the `_gdbm` extension module to avoid linking against
GDBM and introducing a GPL dependency. Distribution releases before 2023 may
link against GDBM and be subject to the GPL.

**It is important to understand the licensing requirements when integrating
the output of this project into derived works.** To help with this, the
JSON document describing the Python distribution contains licensing metadata
and the archive contains copies of license texts.

## Reconsuming Build Artifacts

Produced Python distributions contain object files and libraries for the
built Python and its dependencies. It is possible for downstream consumers
to take these build artifacts and link them into a new binary.

Reconsuming the build artifacts this way can be a bit fragile due to
incompatibilities between the host that generated them and the target that
is consuming them.

To ensure optimal compatibility, it is highly recommended to use the same
toolchain for all operations.

This is often harder than it sounds. For example, if these build artifacts
were to be combined into a Rust binary, the version of LLVM that the Rust
compiler itself was built against can matter. As a concrete example, the
Rust 1.31 compiler will produce LLVM intrinsics that vary from intrinsics
that would be produced with LLVM/Clang 7. At linking time, you would get
errors like the following:

```
Intrinsic has incorrect argument type!
void (i8*, i8, i64, i1)* @llvm.memset.p0i8.i64
```

The distributions that contain object files are useful for
embedding Python in a larger binary. See the
[PyOxidizer](https://github.com/indygreg/PyOxidizer) sister project
for such a downstream repackager.

Some users of these distributions might be better served by the
[PyOxy](https://pyoxidizer.readthedocs.io/en/latest/pyoxy.html)
sister project. PyOxy takes these Python distributions and adds Rust code
to enhance the functionality of the Python interpreter. The official
PyOxy release binaries are single-file executables providing
a full-featured Python interpreter.

---

### Running (`docs/running.rst`)

.. _running:

=====================
Running Distributions
=====================

Using uv
========

The most common method of using the prebuilt distributions from this
project is with `uv <https://docs.astral.sh/uv/>`_. By default, uv will
download, install, and use an appropriate distribution if the system does
not provide a compatible Python installation that uv can discover. These
downloaded distributions are referred to as *managed* Python installations,
as compared to *system* Python installations. You can configure uv to
always use a *managed* Python installation, for example by using the
``--managed-python`` flag.

To run a particular distribution using ``uv``::

    uvx --managed-python python

A Python version or another specifier can be included::

    uvx --managed-python python@3.13
    uvx --managed-python python@3.14+freethreaded

The uv documentation on
`installing Python <https://docs.astral.sh/uv/guides/install-python/>`_
and `Python versions <https://docs.astral.sh/uv/concepts/python-versions/>`_
provides more information and examples.

Obtaining Distributions
=======================

Prebuilt distributions are published as releases on GitHub at
https://github.com/astral-sh/python-build-standalone/releases.
Simply go to that page and find the latest release along with
its release notes.

Machines can find the latest release by querying the GitHub releases
API. Alternatively, a JSON file publishing metadata about the latest
release can be fetched from
https://raw.githubusercontent.com/astral-sh/python-build-standalone/latest-release/latest-release.json.
The JSON format is simple and hopefully self-descriptive.

Published distributions vary by their:

* Python version
* Target machine architecture
* Build configuration
* Archive flavor

The Python version is hopefully pretty obvious.

The target machine architecture defines the CPU type and operating
system the distribution runs on. We use LLVM target triples.
Distributions are produced for the following target triples:

``aarch64-apple-darwin``
   macOS ARM CPUs, i.e., Apple Silicon.

``x86_64-apple-darwin``
   macOS Intel CPUs.

``x86_64-pc-windows-msvc``
   Windows 64-bit Intel/AMD CPUs.

``i686-pc-windows-msvc``
   Windows 32-bit Intel/AMD CPUs.

``aarch64-pc-windows-msvc``
   Windows 64-bit ARM CPUs. Available for CPython 3.11 and newer.

``x86_64-unknown-linux-gnu``
   Linux 64-bit Intel/AMD CPUs linking against GNU libc.

``x86_64-unknown-linux-musl``
   Linux 64-bit Intel/AMD CPUs linking against musl libc.

   Distributions are provided that dynamically link musl or are fully static
   (``+static``). Dynamically linked distributions require musl to be installed
   on the host. Fully static distributions have no shared library dependencies,
   but cannot load Python ``.so`` extensions.

``aarch64-unknown-linux-*``
   Similar to above except targeting Linux on ARM64 CPUs. Distributions
   are provided for GNU libc, musl, and static musl.

   For example, this target supports AWS Graviton EC2 instances. Many
   Linux ARM devices are also ``aarch64``.

``x86_64_v2-*``
   Targets 64-bit Intel/AMD CPUs approximately newer than
   `Nehalem <https://en.wikipedia.org/wiki/Nehalem_(microarchitecture)>`_
   (released in 2008).

   Binaries will have SSE3, SSE4, and other CPU instructions added after the
   ~initial x86-64 CPUs were launched in 2003.

   Binaries will crash if you attempt to run them on an older CPU not
   supporting the newer instructions.

``x86_64_v3-*``
   Targets 64-bit Intel/AMD CPUs approximately newer than
   `Haswell <https://en.wikipedia.org/wiki/Haswell_(microarchitecture)>`_
   (released in 2013) and
   `Excavator <https://en.wikipedia.org/wiki/Excavator_(microarchitecture)>`_
   (released in 2015).

   Binaries will have AVX, AVX2, MOVBE and other newer CPU instructions.

   Binaries will crash if you attempt to run them on an older CPU not
   supporting the newer instructions.

   Most x86-64 CPUs manufactured after 2013 (Intel) or 2015 (AMD) support
   this microarchitecture level. An exception is Intel Atom P processors,
   which Intel released in 2020 but did not include AVX.

``x86_64_v4-*``
   Targets 64-bit Intel/AMD CPUs with some AVX-512 instructions.

   Requires Intel CPUs manufactured after ~2017. But many Intel CPUs don't
   have AVX-512.

The ``x86_64_v2``, ``x86_64_v3``, and ``x86_64_v4`` binaries usually crash
on startup when run on an incompatible CPU. We don't recommend running the
``x86_64_v4`` builds in production because they likely don't yield a reliable
performance benefit. Unless you are executing these binaries on a CPU older
than ~2008 or ~2013, we recommend running the ``x86_64_v2`` or ``x86_64_v3``
binaries, as these should be slightly faster since they take advantage
of more modern CPU instructions which are more efficient. But if you want
maximum portability, stick with the baseline ``x86_64`` builds.

``armv7-unknown-linux-gnueabi``
   Linux 32-bit ARM CPUs without hardware floating-point instructions,
   linking against GNU libc.

   This is an uncommon platform. In most cases, the hardware floating-point
   target should be used. These distributions can be used on Debian's
   ``armel`` port.

``armv7-unknown-linux-gnueabihf``
   Linux 32-bit ARM CPUs with hardware floating-point instructions,
   linking against GNU libc.

   This is a common 32-bit ARM platform. Raspberry Pi model 2 and later
   can use these distributions on many 32-bit Linux distributions.

``ppc64le-unknown-linux-gnu``
   Linux 64-bit POWER8+ CPUs linking against GNU libc.

``riscv64-unknown-linux-gnu``
   Linux 64-bit RISC-V CPUs linking against GNU libc.

``s390x-unknown-linux-gnu``
   Linux 64-bit IBM Z (s390x) CPUs linking against GNU libc.

We recommend using the ``*-unknown-linux-gnu`` builds on Linux, since they
are able to load compiled Python extensions. The non-static
``*-unknown-linux-musl`` builds should be used on musl-based Linux
distributions like Alpine Linux. If you don't need to load compiled
extensions not provided by the standard library, or you are willing to
compile and link third-party extensions into a custom binary, the static
``*-unknown-linux-musl`` builds should work just fine.

The build configuration denotes how Python and its dependencies were built.
Common configurations include:

``pgo+lto``
   Profile-guided optimization and link-time optimization. **These should be
   the fastest distributions since they have the most build-time
   optimizations.**

``pgo``
   Profile-guided optimization.

   Starting with CPython 3.12, BOLT is also applied alongside traditional
   PGO on platforms supporting BOLT. (Currently just Linux x86-64.)

``lto``
   Link-time optimization.

``noopt``
   A regular optimized build without PGO or LTO.

``debug``
   A debug build. No optimizations.

``freethreaded``
   A free-threaded build, available for CPython 3.13 and newer. This
   option is combined with an optimization option, such as
   ``freethreaded+pgo+lto`` or ``freethreaded+lto``.

``static``
   A fully static musl build. Has no shared library dependencies and
   cannot load dynamically linked Python extensions.

The archive flavor denotes the content in the archive. See
:ref:`distributions` for more.

Casual users will likely want to use the ``install_only`` archive, as most
users do not need the build artifacts present in the ``full`` archive.
The ``install_only`` archive does not include the optimization options in
its filename. For each Python version, target, and threading variant,
it uses the fastest available build configuration.

An ``install_only_stripped`` archive is also available. This archive is
equivalent to ``install_only``, but without debug symbols, which results
in a smaller download and on-disk footprint. For CPython 3.13 and newer,
free-threaded archives are identified by ``freethreaded`` in the filename.

Fully static musl builds are only available as ``full`` archives with
``+static`` in their build options. The ``install_only`` and
``install_only_stripped`` musl archives use dynamically linked builds.

Extracting Distributions
========================

Distributions are defined as zstandard or gzip compressed tarballs.

Modern versions of ``tar`` support zstandard and you can extract
like any normal archive::

   $ tar -axvf path/to/distribution.tar.zstd

(The ``-a`` argument tells tar to guess the compression format by
the file extension.)

If your ``tar`` doesn't support ``-a`` (e.g. the default macOS ``tar``),
try::

   $ tar xvf path/to/distribution.tar.zstd

If you do not have ``tar``, you can install and use the ``zstd``
tool (typically available via a ``zstd`` or ``zstandard`` system
package)::

   $ zstd -d path/to/distribution.tar.zstd
   $ tar -xvf path/to/distribution.tar

If you want to extract the distribution with Python, use the
``zstandard`` Python package:

.. code-block:: python

   import tarfile
   import zstandard

   with open("path/to/distribution.tar.zstd", "rb") as ifh:
       dctx = zstandard.ZstdDecompressor()
       with dctx.stream_reader(ifh) as reader:
           with tarfile.open(mode="r|", fileobj=reader) as tf:
               tf.extractall("path/to/output/directory")

Runtime Requirements
====================

Linux
-----

The produced Linux binaries have minimal references to shared
libraries and thus can be executed on most Linux systems.

Distributions linked against glibc may reference the following shared
libraries:

* linux-vdso.so.1
* libpthread.so.0
* libdl.so.2 (required by ctypes extension)
* libutil.so.1
* librt.so.1
* libm.so.6
* libc.so.6
* ld-linux-x86-64.so.2

On Python 3.12 and earlier, the deprecated ``crypt`` module additionally
requires ``libcrypt.so.1``.

The minimum glibc version required for most targets is 2.17. This should make
binaries compatible with the following Linux distributions:

* Fedora 21+
* RHEL/CentOS 7+
* openSUSE 13.2+
* Debian 8+ (Jessie)
* Ubuntu 14.04+

For the ``riscv64-unknown-linux-gnu`` target, the minimum glibc version is
2.28.

Distributions linked against musl do not depend on glibc. By default, musl
distributions are dynamically linked and require musl to be installed on the
host. Fully static distributions use the ``+static`` build option and have
no shared library dependencies, but cannot load dynamically linked Python
extension modules.

Windows
-------

Windows distributions model the requirements of the official Python
distributions:

* CPython 3.14 and newer: Windows 10 or newer.
* CPython 3.13 and earlier: Windows 8.1 or newer.

Windows Server support follows the corresponding CPython release's
upstream platform policy.

Extra Python Software
=====================

Python installations have some additional software pre-installed:

* `pip <https://pypi.org/project/pip/>`_
* `setuptools <https://pypi.org/project/setuptools/>`_ (for Python 3.11 and older)

The intent of the pre-installed software is to facilitate end-user
package installation without having to first bootstrap a packaging
tool via an insecure installation technique (such as `curl | sh`
patterns).

Licensing
=========

Python and its various dependencies are governed by varied software use
licenses. This impacts the rights and requirements of downstream consumers.

Most licenses are fairly permissive. Notable exceptions to this are GDBM and
readline, which are both licensed under GPL Version 3.

We build CPython against libedit - as opposed to readline - to avoid this
GPL dependency. This requires patches on CPython < 3.10. Distribution releases
before 2023 may link against readline and are therefore subject to the GPL.

We globally disable the ``_gdbm`` extension module to avoid linking against
GDBM and introducing a GPL dependency. Distribution releases before 2023 may
link against GDBM and be subject to the GPL.

**It is important to understand the licensing requirements when integrating
the output of this project into derived works.** To help with this, the
JSON document describing the Python distribution contains licensing metadata
and the archive contains copies of license texts.

Reconsuming Build Artifacts
===========================

Produced Python distributions contain object files and libraries for the
built Python and its dependencies. It is possible for downstream consumers
to take these build artifacts and link them into a new binary.

Reconsuming the build artifacts this way can be a bit fragile due to
incompatibilities between the host that generated them and the target that
is consuming them.

To ensure optimal compatibility, it is highly recommended to use the same
toolchain for all operations.

This is often harder than it sounds. For example, if these build artifacts
were to be combined into a Rust binary, the version of LLVM that the Rust
compiler itself was built against can matter. As a concrete example, the
Rust 1.31 compiler will produce LLVM intrinsics that vary from intrinsics
that would be produced with LLVM/Clang 7. At linking time, you would get
errors like the following::

    Intrinsic has incorrect argument type!
    void (i8*, i8, i64, i1)* @llvm.memset.p0i8.i64

The distributions that contain object files are useful for
embedding Python in a larger binary. See the
`PyOxidizer <https://github.com/indygreg/PyOxidizer>`_ sister project
for such a downstream repackager.

Some users of these distributions might be better served by the
`PyOxy <https://pyoxidizer.readthedocs.io/en/latest/pyoxy.html>`_
sister project. PyOxy takes these Python distributions and adds Rust code
to enhance the functionality of the Python interpreter. The official
PyOxy release binaries are single-file executables providing
a full-featured Python interpreter.

---

### Status (`docs/status.md`)

<a id="status"></a>

# Project Status

There is support for producing CPython distributions for Windows,
macOS, and Linux. All distributions are highly self-contained and have
limited shared library dependencies.

## Target Notes

Linux x86_64 and aarch64 targets (`x86_64-*` and `aarch64-*`) are built on
native hardware using a modern LLVM toolchain.

All other architectures are cross-compiled on x86_64 using Debian-provided
cross-compilation tools. As a result, these targets are not as highly
optimized as aarch64 and x86_64 targets.

## Test Failures

This repository contains a `test-distribution.py` script that can be
used to run the Python test harness from a distribution archive.

Currently, this script is only used to validate a limited set of
functionality for each distribution. The entire Python test harness is
not run on a regular basis. Work is ongoing to perform this type of
testing on a regular basis.

The details below on known failing and skipped tests are out of date. In
the future, this information will be updated and presented elsewhere.

Here, we track the various known failures when running
`test-distribution.py --stdlib -- /path/to/distribution.tar.zst -u all`.

### `test__locale`

Known failing on: Windows

This test fails as follows:

```
======================================================================
ERROR: test_float_parsing (test.test__locale._LocaleTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\gps\AppData\Local\Temp\tmpjx7a33kd\python\install\lib\test\test__locale.py", line 184, in test_float_parsing
    if localeconv()['decimal_point'] != '.':
UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error

======================================================================
ERROR: test_lc_numeric_localeconv (test.test__locale._LocaleTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\gps\AppData\Local\Temp\tmpjx7a33kd\python\install\lib\test\test__locale.py", line 130, in test_lc_numeric_localeconv
    formatting = localeconv()
UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error

----------------------------------------------------------------------
```

### `test_locale`

Known failing on: Windows

This test fails on Windows:

```
======================================================================
ERROR: test_getsetlocale_issue1813 (test.test_locale.TestMiscellaneous)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_locale.py", line 567, in test_getsetlocale_issue1813
    locale.setlocale(locale.LC_CTYPE, loc)
  File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\locale.py", line 608, in setlocale
    return _setlocale(category, locale)
locale.Error: unsupported locale setting

----------------------------------------------------------------------
```

### `test_subprocess`

Known Failing on: Linux

This fails in the following manner:

```
test_executable_without_cwd (test.test_subprocess.ProcessTestCaseNoPoll) ... Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
Fatal Python error: initfsencoding: Unable to get the locale encoding
ModuleNotFoundError: No module named 'encodings'

Current thread 0x00007fd77c231740 (most recent call first):
FAIL

======================================================================
FAIL: test_executable_without_cwd (test.test_subprocess.ProcessTestCaseNoPoll)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/tmp8hef0kr4/python/install/lib/python3.7/test/test_subprocess.py", line 436, in test_executable_without_cwd
    executable=sys.executable)
  File "/tmp/tmp8hef0kr4/python/install/lib/python3.7/test/test_subprocess.py", line 355, in _assert_cwd
    self.assertEqual(47, p.returncode)
AssertionError: 47 != -6
```

We're unsure what is going on here. The error from `initfsencoding`
is what happens when the first `import` during `Py_Initialize()`
fails. So it appears the test somehow can't locate the Python
standard library.

### `test_tk`

Known Failing on: Linux

This fails in the following manner:

```
======================================================================
FAIL: test_from (tkinter.test.test_tkinter.test_widgets.ScaleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/test_tkinter/test_widgets.py", line 867, in test_from
    self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=float_round)
  File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 106, in checkFloatParam
    self.checkParam(widget, name, value, conv=conv, **kwargs)
  File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 63, in checkParam
    self.assertEqual2(widget[name], expected, eq=eq)
  File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 47, in assertEqual2
    self.assertEqual(actual, expected, msg)
AssertionError: 14.9 != 15.0
```

This seems like a minor issue and might be a bug in the test itself.

### `test_winconsoleio`

This fails as follows:

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Test Skips

### Linux

The following tests are skipped on Linux:

test_asdl_parser

: test irrelevant for an installed Python

test_clinic

: install/lib/Tools/clinic' path does not exist

test_dbm_gnu

: No module named '\_gdbm'

test_devpoll

: test works only on Solaris OS family

test_gdb

: test_gdb only works on source builds at the moment.

test_kqueue

: test works only on BSD

test_msilib

: No module named 'msilib'

test_ossaudiodev

: [Errno 2] No such file or directory: '/dev/dsp'

test_startfile

: object `<module 'os' from '.../install/lib/python3.7/os.py'>` has no attribute 'startfile'

test_winconsoleio

: test only relevant on win32

test_winreg

: No module named 'winreg'

test_winsound

: No module named 'winsound'

test_zipfile64

: test requires loads of disk-space bytes and a long time to run

### macOS

The following tests are skipped on macOS:

test_asdl_parser

: test irrelevant for an installed Python

test_clinic

: python/install/lib/Tools/clinic' path does not exist

test_dbm_gnu

: No module named '\_gdbm'

test_devpoll

: test works only on Solaris OS family

test_epoll

: test works only on Linux 2.6

test_gdb

: Couldn't find gdb on the path

test_msilib

: No module named 'msilib'

test_multiprocessing_fork

: test may crash on macOS (bpo-33725)

test_nis

: No module named 'nis'

test_ossaudiodev

: No module named 'ossaudiodev'

test_spwd

: No module named 'spwd'

test_startfile

: object `<module 'os' from '.../install/lib/python3.7/os.py'>` has no attribute 'startfile'

test_tix

: tix is not built by this project

test_tk

: cannot run without OS X gui process

test_ttk_guionly

: cannot run without OS X gui process

test_winconsoleio

: test only relevant on win32

test_winreg

: No module named 'winreg'

test_winsound

: No module named 'winsound'

test_zipfile64

: test requires loads of disk-space bytes and a long time to run

---

### Status (`docs/status.rst`)

.. _status:

==============
Project Status
==============

There is support for producing CPython distributions for Windows,
macOS, and Linux. All distributions are highly self-contained and have
limited shared library dependencies.

Target Notes
============

Linux x86_64 and aarch64 targets (``x86_64-*`` and ``aarch64-*``) are built on
native hardware using a modern LLVM toolchain.

All other architectures are cross-compiled on x86_64 using Debian-provided
cross-compilation tools. As a result, these targets are not as highly
optimized as aarch64 and x86_64 targets.

Test Failures
=============

This repository contains a ``test-distribution.py`` script that can be
used to run the Python test harness from a distribution archive.

Currently, this script is only used to validate a limited set of
functionality for each distribution. The entire Python test harness is
not run on a regular basis. Work is ongoing to perform this type of
testing on a regular basis.

The details below on known failing and skipped tests are out of date. In
the future, this information will be updated and presented elsewhere.

Here, we track the various known failures when running
``test-distribution.py --stdlib -- /path/to/distribution.tar.zst -u all``.

``test__locale``
----------------

Known failing on: Windows

This test fails as follows::

    ======================================================================
    ERROR: test_float_parsing (test.test__locale._LocaleTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\Users\gps\AppData\Local\Temp\tmpjx7a33kd\python\install\lib\test\test__locale.py", line 184, in test_float_parsing
        if localeconv()['decimal_point'] != '.':
    UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error

    ======================================================================
    ERROR: test_lc_numeric_localeconv (test.test__locale._LocaleTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\Users\gps\AppData\Local\Temp\tmpjx7a33kd\python\install\lib\test\test__locale.py", line 130, in test_lc_numeric_localeconv
        formatting = localeconv()
    UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error

    ----------------------------------------------------------------------

``test_locale``
---------------

Known failing on: Windows

This test fails on Windows::

    ======================================================================
    ERROR: test_getsetlocale_issue1813 (test.test_locale.TestMiscellaneous)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_locale.py", line 567, in test_getsetlocale_issue1813
        locale.setlocale(locale.LC_CTYPE, loc)
      File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\locale.py", line 608, in setlocale
        return _setlocale(category, locale)
    locale.Error: unsupported locale setting

    ----------------------------------------------------------------------

``test_subprocess``
-------------------

Known Failing on: Linux

This fails in the following manner::

    test_executable_without_cwd (test.test_subprocess.ProcessTestCaseNoPoll) ... Could not find platform independent libraries <prefix>
    Could not find platform dependent libraries <exec_prefix>
    Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
    Fatal Python error: initfsencoding: Unable to get the locale encoding
    ModuleNotFoundError: No module named 'encodings'

    Current thread 0x00007fd77c231740 (most recent call first):
    FAIL

    ======================================================================
    FAIL: test_executable_without_cwd (test.test_subprocess.ProcessTestCaseNoPoll)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/tmp/tmp8hef0kr4/python/install/lib/python3.7/test/test_subprocess.py", line 436, in test_executable_without_cwd
        executable=sys.executable)
      File "/tmp/tmp8hef0kr4/python/install/lib/python3.7/test/test_subprocess.py", line 355, in _assert_cwd
        self.assertEqual(47, p.returncode)
    AssertionError: 47 != -6

We're unsure what is going on here. The error from ``initfsencoding``
is what happens when the first ``import`` during ``Py_Initialize()``
fails. So it appears the test somehow can't locate the Python
standard library.

``test_tk``
-----------

Known Failing on: Linux

This fails in the following manner::

    ======================================================================
    FAIL: test_from (tkinter.test.test_tkinter.test_widgets.ScaleTest)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/test_tkinter/test_widgets.py", line 867, in test_from
        self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=float_round)
      File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 106, in checkFloatParam
        self.checkParam(widget, name, value, conv=conv, **kwargs)
      File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 63, in checkParam
        self.assertEqual2(widget[name], expected, eq=eq)
      File "/tmp/tmpoqqjd5gi/python/install/lib/python3.7/tkinter/test/widget_tests.py", line 47, in assertEqual2
        self.assertEqual(actual, expected, msg)
    AssertionError: 14.9 != 15.0

This seems like a minor issue and might be a bug in the test itself.

``test_winconsoleio``
---------------------

This fails as follows::

    ======================================================================
    ERROR: test_ctrl_z (test.test_winconsoleio.WindowsConsoleIOTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 190, in test_ctrl_z
        a, b = stdin.read(1), stdin.readall()
    OSError: [WinError 87] The parameter is incorrect

    ======================================================================
    ERROR: test_input (test.test_winconsoleio.WindowsConsoleIOTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 144, in test_input
        self.assertStdinRoundTrip('abc123')
      File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 137, in assertStdinRoundTrip
        actual = input()
    OSError: [WinError 87] The parameter is incorrect

    ======================================================================
    FAIL: test_partial_reads (test.test_winconsoleio.WindowsConsoleIOTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 166, in test_partial_reads
        self.assertEqual(actual, expected, 'stdin.read({})'.format(read_count))
    AssertionError: b'\r\n' != b'\xcf\xbc\xd1\x9e\xd0\xa2\xce\xbb\xd0\xa4\xd0\x99\r\n' : stdin.read(1)

    ======================================================================
    FAIL: test_partial_surrogate_reads (test.test_winconsoleio.WindowsConsoleIOTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test_winconsoleio.py", line 183, in test_partial_surrogate_reads
        self.assertEqual(actual, expected, 'stdin.read({})'.format(read_count))
    AssertionError: b'\xc3\x84\r\n' != b'\xf4\x81\xbf\xbf\xf4\x81\x80\x81\r\n' : stdin.read(1)

    ----------------------------------------------------------------------

    Ran 10 tests in 0.006s

    FAILED (failures=2, errors=2)
    test test_winconsoleio failed
    0:00:00 Re-running test__locale in verbose mode
    test_float_parsing (test.test__locale._LocaleTests) ... ERROR
    test_lc_numeric_basic (test.test__locale._LocaleTests) ... skipped 'nl_langinfo is not available'
    test_lc_numeric_localeconv (test.test__locale._LocaleTests) ... ERROR
    test_lc_numeric_nl_langinfo (test.test__locale._LocaleTests) ... skipped 'nl_langinfo is not available'

    ======================================================================
    ERROR: test_float_parsing (test.test__locale._LocaleTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test__locale.py", line 184, in test_float_parsing
        if localeconv()['decimal_point'] != '.':
    UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error

    ======================================================================
    ERROR: test_lc_numeric_localeconv (test.test__locale._LocaleTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\Users\gps\AppData\Local\Temp\tmp8m94v2m5\python\install\lib\test\test__locale.py", line 130, in test_lc_numeric_localeconv
        formatting = localeconv()
    UnicodeDecodeError: 'locale' codec can't decode byte 0xa0 in position 0: decoding error

    ----------------------------------------------------------------------


Test Skips
==========

Linux
-----

The following tests are skipped on Linux:

test_asdl_parser
   test irrelevant for an installed Python
test_clinic
   install/lib/Tools/clinic' path does not exist
test_dbm_gnu
   No module named '_gdbm'
test_devpoll
   test works only on Solaris OS family
test_gdb
   test_gdb only works on source builds at the moment.
test_kqueue
   test works only on BSD
test_msilib
   No module named 'msilib'
test_ossaudiodev
   [Errno 2] No such file or directory: '/dev/dsp'
test_startfile
   object <module 'os' from '.../install/lib/python3.7/os.py'> has no attribute 'startfile'
test_winconsoleio
   test only relevant on win32
test_winreg
   No module named 'winreg'
test_winsound
   No module named 'winsound'
test_zipfile64
   test requires loads of disk-space bytes and a long time to run

macOS
-----

The following tests are skipped on macOS:

test_asdl_parser
   test irrelevant for an installed Python
test_clinic
   python/install/lib/Tools/clinic' path does not exist
test_dbm_gnu
   No module named '_gdbm'
test_devpoll
   test works only on Solaris OS family
test_epoll
   test works only on Linux 2.6
test_gdb
   Couldn't find gdb on the path
test_msilib
   No module named 'msilib'
test_multiprocessing_fork
   test may crash on macOS (bpo-33725)
test_nis
   No module named 'nis'
test_ossaudiodev
   No module named 'ossaudiodev'
test_spwd
   No module named 'spwd'
test_startfile
   object <module 'os' from '.../install/lib/python3.7/os.py'> has no attribute 'startfile'
test_tix
   tix is not built by this project
test_tk
   cannot run without OS X gui process
test_ttk_guionly
   cannot run without OS X gui process
test_winconsoleio
   test only relevant on win32
test_winreg
   No module named 'winreg'
test_winsound
   No module named 'winsound'
test_zipfile64
   test requires loads of disk-space bytes and a long time to run

---

### Technotes (`docs/technotes.md`)

<a id="technotes"></a>

# Technical Notes

## How It Works

The first thing the `build.py` scripts do is bootstrap an environment
for building Python. Linux builds use Docker images based on deterministic
Debian snapshots selected for each target:

- x86-64 targets use Debian Jessie and a prebuilt Clang toolchain.
- aarch64 targets use Debian Stretch and a prebuilt Clang toolchain.
- Other cross-compiled targets generally use Debian Stretch and
  Debian-provided GCC cross-compilers.
- riscv64 targets use Debian Buster and a Debian-provided GCC
  cross-compiler.

The selected toolchain is used to build Python's dependencies (OpenSSL,
ncurses, libedit, SQLite, etc.). Finally, Python itself is built.

Python is built in such a way that extensions are statically linked
against their dependencies. For example, instead of the `sqlite3` Python
extension having a run-time dependency against `libsqlite3.so`, the
SQLite symbols are statically inlined into the Python extension object
file. Extension modules are statically linked into `python` rather than
provided as shared extensions in the `lib-dynload` directory.

`_dbm` and `_tkinter` are handled differently. On dynamically linked
Linux builds, `_dbm` is provided as a shared extension with Berkeley DB
statically linked. This allows the module to be easily removed when the
Berkeley DB license is undesired (see the DBM section below). On macOS,
`_dbm` instead uses the system NDBM implementation. `_tkinter` is
also provided as a shared extension, with Tcl and Tk dynamically linked,
on builds that support shared extensions.

From the built Python, we produce an archive containing the raw Python
distribution (as if you had run `make install`) as well as other files
useful for downstream consumers.

## Setup.local Hackery

Starting with Python 3.12, C extension modules are configured and built
using `configure`, `Modules/Setup.stdlib`, and `Makefile`. A
generated `Modules/Setup.local` file disables selected modules and
overrides whether others are linked statically or built as shared
libraries.

Prior to 3.12, many extensions were configured and built using `setup.py`
scripts. These scripts do not provide much flexibility and rely on default
behaviors in `distutils`, as well as other inline code in `setup.py`.
This default behavior is often undesirable for our desired outcome of
producing a standalone Python distribution.

Because of this, when building Python prior to 3.12, a custom `Setup.local`
file is generated that builds all C extensions in a specific manner.
The undesirable behavior of `setup.py` is bypassed and the Python C
extensions are compiled just the way we want.

## Dependency Notes

### DBM

Python has the option of building its `_dbm` extension against NDBM,
GDBM, and Berkeley DB. GDBM and its NDBM compatibility libraries are
licensed under GNU GPL Version 3. Modern versions of Berkeley DB are
licensed under GNU AGPL v3. Versions 6.0.19 and older are licensed under
the more permissive Sleepycat License.

On Linux, we build the `_dbm` extension against Berkeley DB 6.0.19. On
macOS, `_dbm` uses the NDBM implementation provided by the system
`libSystem` library instead.

We explicitly disable the `_gdbm` extension on all targets to avoid
the GPL dependency.

### readline / libedit / ncurses

Python has the option of building its `readline` extension against
either `libreadline` or `libedit`. `libreadline` is licensed under
GNU GPL Version 3, and `libedit` has a more permissive license.

`libedit`/`libreadline` link against a curses library, most likely
`ncurses`. And `ncurses` has tie-ins with a terminal database. This
is a thorny situation, as terminal databases can be difficult to
distribute because end-users often want software to respect their
terminal databases. But for that to work, `ncurses` needs to be compiled
in a way that respects the user's environment.

On macOS, we use the system `libedit` and `libncurses`, which is
typically provided in `/usr/lib`.

On Linux, we build `libedit` and `ncurses` from source and statically
link against their respective libraries. Project releases before 2023 linked
against `readline` on Linux.

### gettext / locale Module

The `locale` Python module exposes some functionality from the `gettext`
software (specifically `libintl`). (Technically, this functionality is exposed
from the `_locale` C extension module and `locale` re-exports symbols.)

`gettext` is GPL version 3 or later licensed. And having it statically linked
in the Python distribution via the `_locale` module can have licensing
implications.

Python's configure script probes for the ability to compile/link with
`-lintl`. If it works, Python is linked against `libintl`. If it doesn't,
`libintl` is omitted. (Search `configure` for `ac_cv_lib_intl_textdomain`
and `-lintl` references.)

With the container based build environment on Linux, presence of `gettext`
and `libintl` is deterministic. However, on macOS where there is no
sandboxing of the build environment, Python's configure script can find and
use a `gettext`/`libintl` installed outside the system default (e.g. via
Homebrew or MacPorts). This can result in the built Python referencing a shared
library not reliably present on every macOS machine. So our build system
disables the configure check.

This means that the `gettext`/`libintl` features in the Python distribution
are not available.

### libnsl / nis Module

The `nis` Python extension module has a dependency on `libnsl`.

`libnsl` has historically been in base Linux distribution installations.
But it is being phased away, with it being an optional install in modern
versions of Fedora and RHEL.

Because the `nis` extension is perceived to be likely unused functionality,
we've decided to not build it instead of adding complexity to deal with
the `libnsl` dependency. See further discussion in
<https://github.com/astral-sh/python-build-standalone/issues/51>.

The `nis` module was deprecated in Python 3.11 and removed in 3.13.

## Upgrading CPython

This section documents some of the work that needs to be performed
when upgrading CPython major versions.

### Review Release Notes

CPython's release notes often have a section on build system changes.
e.g. <https://docs.python.org/3/whatsnew/3.13.html#build-changes>.
These are a must review.

### `Modules/Setup`

The `Modules/Setup` file defines the default extension build settings.

We need to audit it for differences such as added/removed extensions,
changes to compile settings, etc just in case we have special code
handling an extension defined in this file.

See code in `cpython.py` dealing with this file.

---

### Technotes (`docs/technotes.rst`)

.. _technotes:

===============
Technical Notes
===============

How It Works
============

The first thing the ``build.py`` scripts do is bootstrap an environment
for building Python. Linux builds use Docker images based on deterministic
Debian snapshots selected for each target:

* x86-64 targets use Debian Jessie and a prebuilt Clang toolchain.
* aarch64 targets use Debian Stretch and a prebuilt Clang toolchain.
* Other cross-compiled targets generally use Debian Stretch and
  Debian-provided GCC cross-compilers.
* riscv64 targets use Debian Buster and a Debian-provided GCC
  cross-compiler.

The selected toolchain is used to build Python's dependencies (OpenSSL,
ncurses, libedit, SQLite, etc.). Finally, Python itself is built.

Python is built in such a way that extensions are statically linked
against their dependencies. For example, instead of the ``sqlite3`` Python
extension having a run-time dependency against ``libsqlite3.so``, the
SQLite symbols are statically inlined into the Python extension object
file. Extension modules are statically linked into ``python`` rather than
provided as shared extensions in the ``lib-dynload`` directory.

``_dbm`` and ``_tkinter`` are handled differently. On dynamically linked
Linux builds, ``_dbm`` is provided as a shared extension with Berkeley DB
statically linked. This allows the module to be easily removed when the
Berkeley DB license is undesired (see the DBM section below). On macOS,
``_dbm`` instead uses the system NDBM implementation. ``_tkinter`` is
also provided as a shared extension, with Tcl and Tk dynamically linked,
on builds that support shared extensions.

From the built Python, we produce an archive containing the raw Python
distribution (as if you had run ``make install``) as well as other files
useful for downstream consumers.

Setup.local Hackery
===================

Starting with Python 3.12, C extension modules are configured and built
using ``configure``, ``Modules/Setup.stdlib``, and ``Makefile``. A
generated ``Modules/Setup.local`` file disables selected modules and
overrides whether others are linked statically or built as shared
libraries.

Prior to 3.12, many extensions were configured and built using ``setup.py``
scripts. These scripts do not provide much flexibility and rely on default
behaviors in ``distutils``, as well as other inline code in ``setup.py``.
This default behavior is often undesirable for our desired outcome of
producing a standalone Python distribution.

Because of this, when building Python prior to 3.12, a custom ``Setup.local``
file is generated that builds all C extensions in a specific manner.
The undesirable behavior of ``setup.py`` is bypassed and the Python C
extensions are compiled just the way we want.

Dependency Notes
================

DBM
---

Python has the option of building its ``_dbm`` extension against NDBM,
GDBM, and Berkeley DB. GDBM and its NDBM compatibility libraries are
licensed under GNU GPL Version 3. Modern versions of Berkeley DB are
licensed under GNU AGPL v3. Versions 6.0.19 and older are licensed under
the more permissive Sleepycat License.

On Linux, we build the ``_dbm`` extension against Berkeley DB 6.0.19. On
macOS, ``_dbm`` uses the NDBM implementation provided by the system
``libSystem`` library instead.

We explicitly disable the ``_gdbm`` extension on all targets to avoid
the GPL dependency.

readline / libedit / ncurses
----------------------------

Python has the option of building its ``readline`` extension against
either ``libreadline`` or ``libedit``. ``libreadline`` is licensed under
GNU GPL Version 3, and ``libedit`` has a more permissive license.

``libedit``/``libreadline`` link against a curses library, most likely
``ncurses``. And ``ncurses`` has tie-ins with a terminal database. This
is a thorny situation, as terminal databases can be difficult to
distribute because end-users often want software to respect their
terminal databases. But for that to work, ``ncurses`` needs to be compiled
in a way that respects the user's environment.

On macOS, we use the system ``libedit`` and ``libncurses``, which is
typically provided in ``/usr/lib``.

On Linux, we build ``libedit`` and ``ncurses`` from source and statically
link against their respective libraries. Project releases before 2023 linked
against ``readline`` on Linux.

gettext / locale Module
-----------------------

The ``locale`` Python module exposes some functionality from the ``gettext``
software (specifically ``libintl``). (Technically, this functionality is exposed
from the ``_locale`` C extension module and ``locale`` re-exports symbols.)

``gettext`` is GPL version 3 or later licensed. And having it statically linked
in the Python distribution via the ``_locale`` module can have licensing
implications.

Python's configure script probes for the ability to compile/link with
``-lintl``. If it works, Python is linked against ``libintl``. If it doesn't,
``libintl`` is omitted. (Search ``configure`` for ``ac_cv_lib_intl_textdomain``
and ``-lintl`` references.)

With the container based build environment on Linux, presence of ``gettext``
and ``libintl`` is deterministic. However, on macOS where there is no
sandboxing of the build environment, Python's configure script can find and
use a ``gettext``/``libintl`` installed outside the system default (e.g. via
Homebrew or MacPorts). This can result in the built Python referencing a shared
library not reliably present on every macOS machine. So our build system
disables the configure check.

This means that the ``gettext``/``libintl`` features in the Python distribution
are not available.

libnsl / nis Module
-------------------

The ``nis`` Python extension module has a dependency on ``libnsl``.

``libnsl`` has historically been in base Linux distribution installations.
But it is being phased away, with it being an optional install in modern
versions of Fedora and RHEL.

Because the ``nis`` extension is perceived to be likely unused functionality,
we've decided to not build it instead of adding complexity to deal with
the ``libnsl`` dependency. See further discussion in
https://github.com/astral-sh/python-build-standalone/issues/51.

The ``nis`` module was deprecated in Python 3.11 and removed in 3.13.

Upgrading CPython
=================

This section documents some of the work that needs to be performed
when upgrading CPython major versions.

Review Release Notes
--------------------

CPython's release notes often have a section on build system changes.
e.g. https://docs.python.org/3/whatsnew/3.13.html#build-changes.
These are a must review.

``Modules/Setup``
-----------------

The ``Modules/Setup`` file defines the default extension build settings.

We need to audit it for differences such as added/removed extensions,
changes to compile settings, etc just in case we have special code
handling an extension defined in this file.

See code in ``cpython.py`` dealing with this file.

---

--- METRICS ---
- Files Extracted: 14
- Estimated Token Budget: ~34587 tokens
- Canonical Reference: https://codewiki.google/github.com/astral-sh/python-build-standalone
