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
[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 buildwork 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 withmissing field version - No build hooks or build scripts, so generated files must exist before the build starts
uv buildignores the pinned backend version in favor of its own bundled copy, so a build reproducible against a specific backend release needs--force-pep517