uv/docs/concepts/build-backend.md
Zanie Blue b1812d111a
Some checks are pending
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | aarch64 windows implicit (push) Blocked by required conditions
CI / integration test | aarch64 windows explicit (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | pyodide on ubuntu (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | free-threaded python on github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | registries (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | graalpy on ubuntu (push) Blocked by required conditions
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | aarch64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks | walltime aarch64 linux (push) Blocked by required conditions
CI / benchmarks | instrumented (push) Blocked by required conditions
Edits to the build backend documentation (#14376)
Co-authored-by: konstin <konstin@mailbox.org>
2025-07-01 08:44:23 +00:00

8.1 KiB

The uv build backend

!!! note

The uv build backend is currently in preview and may change without warning.

When preview mode is not enabled, uv uses [hatchling](https://pypi.org/project/hatchling/) as the default build backend.

A build backend transforms a source tree (i.e., a directory) into a source distribution or a wheel.

uv supports all build backends (as specified by PEP 517), but also provides a native build backend (uv_build) that integrates tightly with uv to improve performance and user experience.

Using the uv build backend

!!! important

The uv build backend currently **only supports pure Python code**. An alternative backend is to
build a [library with extension modules](../concepts/projects/init.md#projects-with-extension-modules).

To use uv as a build backend in an existing project, add uv_build to the [build-system] section in your pyproject.toml:

[build-system]
requires = ["uv_build>=0.7.17,<0.8.0"]
build-backend = "uv_build"

!!! note

The uv build backend follows the same [versioning policy](../reference/policies/versioning.md)
as uv. Including an upper bound on the `uv_build` version ensures that your package continues to
build correctly as new versions are released.

To create a new project that uses the uv build backend, use uv init:

$ uv init --build-backend uv

When the project is built, e.g., with uv build, the uv build backend will be used to create the source distribution and wheel.

Bundled build backend

The build backend is published as a separate package (uv_build) that is optimized for portability and small binary size. However, the uv executable also includes a copy of the build backend, which will be used during builds performed by uv, e.g., during uv build, if its version is compatible with the uv_build requirement. If it's not compatible, a compatible version of the uv_build package will be used. Other build frontends, such as python -m build, will always use the uv_build package, typically choosing the latest compatible version.

Modules

Python packages are expected to contain one or more Python modules, which are directories containing an __init__.py. By default, a single root module is expected at src/<package_name>/__init__.py.

For example, the structure for a project named foo would be:

pyproject.toml
src
└── foo
    └── __init__.py

uv normalizes the package name to determine the default module name: the package name is lowercased and dots and dashes are replaced with underscores, e.g., Foo-Bar would be converted to foo_bar.

The src/ directory is the default directory for module discovery.

These defaults can be changed with the module-name and module-root settings. For example, to use a FOO module in the root directory, as in the project structure:

pyproject.toml
FOO
└── __init__.py

The correct build configuration would be:

[tool.uv.build-backend]
module-name = "FOO"
module-root = ""

Namespace packages

Namespace packages are intended for use-cases where multiple packages write modules into a shared namespace.

Namespace package modules are identified by a . in the module-name. For example, to package the module bar in the shared namespace foo, the project structure would be:

pyproject.toml
src
└── foo
    └── bar
        └── __init__.py

And the module-name configuration would be:

[tool.uv.build-backend]
module-name = "foo.bar"

!!! important

The `__init__.py` file is not included in `foo`, since it's the shared namespace module.

It's also possible to have a complex namespace package with more than one root module, e.g., with the project structure:

pyproject.toml
src
├── foo
│   └── __init__.py
└── bar
    └── __init__.py

While we do not recommend this structure (i.e., you should use a workspace with multiple packages instead), it is supported via the namespace option:

[tool.uv.build-backend]
namespace = true

Stub packages

The build backend also supports building type stub packages, which are identified by the -stubs suffix on the package or module name, e.g., foo-stubs. The module name for type stub packages must end in -stubs, so uv will not normalize the - to an underscore. Additionally, uv will search for a __init__.pyi file. For example, the project structure would be:

pyproject.toml
src
└── foo-stubs
    └── __init__.pyi

Type stub modules are also supported for namespace packages.

File inclusion and exclusion

The build backend is responsible for determining which files in a source tree should be packaged into the distributions.

To determine which files to include in a source distribution, uv first adds the included files and directories, then removes the excluded files and directories. This means that exclusions always take precedence over inclusions.

By default, uv excludes __pycache__, *.pyc, and *.pyo.

When building a source distribution, the following files and directories are included:

From these, items matching tool.uv.build-backend.source-exclude and the default excludes are removed.

When building a wheel, the following files and directories are included:

From these, tool.uv.build-backend.source-exclude, tool.uv.build-backend.wheel-exclude and the default excludes are removed. The source dist excludes are applied to avoid source tree to wheel source builds including more files than source tree to source distribution to wheel build.

There are no specific wheel includes. There must only be one top level module, and all data files must either be under the module root or in the appropriate data directory. Most packages store small data in the module root alongside the source code.

Include and exclude syntax

Includes are anchored, which means that pyproject.toml includes only <root>/pyproject.toml and not <root>/bar/pyproject.toml. To recursively include all files under a directory, use a /** suffix, e.g. src/**. Recursive inclusions are also anchored, e.g., assets/**/sample.csv includes all sample.csv files in <root>/assets or any of its children.

!!! note

For performance and reproducibility, avoid patterns without an anchor such as `**/sample.csv`.

Excludes are not anchored, which means that __pycache__ excludes all directories named __pycache__ regardless of its parent directory. All children of an exclusion are excluded as well. To anchor a directory, use a / prefix, e.g., /dist will exclude only <root>/dist.

All fields accepting patterns use the reduced portable glob syntax from PEP 639, with the addition that characters can be escaped with a backslash.