Skip to content

uv_build: Build Backend Reference

uv_build is the build backend maintained by the uv team. It implements the PEP 517 hook API, builds pure Python source trees into wheels and source distributions, and is the backend uv init declares for packaged projects.

This page is the configuration lookup. What is the uv build backend? covers what the backend puts in each artifact, what it refuses to build, and when Hatchling remains the better choice.

Declare the backend

pyproject.toml
[build-system]
requires = ["uv_build>=0.12.0,<0.13.0"]
build-backend = "uv_build"

uv_build ships in lockstep with uv, which reserves breaking changes for minor releases, so the constraint excludes the next minor version (<0.13.0). uv build nonetheless prefers the backend compiled into the running uv executable over the pinned version, warning only when the pin excludes it; uv build --force-pep517 installs the pinned version instead.

uv init --build-backend accepts uv, hatch, flit, pdm, poetry, setuptools, maturin, and scikit for projects that need a different backend from the start. hatch selects Hatchling and scikit selects scikit-build-core.

Configure the backend

All settings live under [tool.uv.build-backend] in pyproject.toml.

Key Type Default Effect
module-name string or list project name, normalized Module directory to package; dotted for a namespace package
module-root string "src" Directory containing the module; "" for a flat layout
namespace boolean false Treats the module root as a PEP 420 namespace directory with no __init__.py; multiple roots must still be listed in module-name
data table {} Directories copied into the wheel’s .data tree
default-excludes boolean true Drops __pycache__, *.pyc, *.pyo
source-include list [] Extra globs for the sdist
source-exclude list [] Globs dropped from the sdist and the wheel
wheel-exclude list [] Globs dropped from the wheel

Patterns use the reduced portable glob syntax that PEP 639, the license-metadata standard, defines for license files, plus backslash escaping: * matches within one path segment, ** matches across segments, ? matches a single character, and [] matches a character class. Includes are matched from the project root, so pyproject.toml matches only the top-level file. Excludes match at any depth unless the pattern starts with /.

data maps a source directory into the wheel’s <name>-<version>.data/ tree, from which the installer copies it into the target environment:

Key Installs into
scripts the environment’s bin/, or Scripts\ on Windows
headers the environment’s include directory for the distribution
data the environment prefix itself
purelib, platlib site-packages

Astral’s settings reference advises against purelib and platlib, and warns that data writes into the environment prefix, where it can overwrite existing files.

Name the module

The packaged module defaults to src/<name>/__init__.py, with <name> the project name lowercased and dots and dashes converted to underscores, so Foo.Bar-Baz resolves to foo_bar_baz. A mismatch fails the build with Expected a Python module at: src/<name>/__init__.py.

Type stub packages (PEP 561) keep the -stubs suffix unnormalized and are found through __init__.pyi, so a foo-stubs distribution ships a foo-stubs/ directory. A dotted module-name builds a PEP 420 implicit namespace package, whose shared directory carries no __init__.py.

Use uv_build when

  • Declared automatically by uv init, so packaged projects build with no backend configuration
  • No Python dependencies in the build environment beyond the backend itself
  • Narrow artifact defaults keep unrelated project files out of wheels
  • Standard PEP 517 interface, so pip and python -m build work against it unchanged

Choose another backend when

  • Pure Python only; extension modules need maturin, scikit-build-core, or setuptools
  • No plugin system, so Hatchling extensions have no equivalent
  • No dynamic versioning; dynamic = ["version"] fails with missing field version
  • No build hooks or build scripts, so generated files must exist before the build starts
  • uv build ignores the pinned backend version in favor of its own bundled copy, so a build reproducible against a specific backend release needs --force-pep517
Last updated on