# uv_build: Build Backend Reference


uv_build is the [build backend](https://pydevtools.com/handbook/explanation/what-is-a-build-backend.md) maintained by the [uv](https://pydevtools.com/handbook/reference/uv.md) team. It implements the [PEP 517](https://pydevtools.com/handbook/explanation/what-is-pep-517.md) hook API, builds pure Python source trees into [wheels](https://pydevtools.com/handbook/reference/wheel.md) and [source distributions](https://pydevtools.com/handbook/reference/sdist.md), and is the backend `uv init` declares for packaged projects.

This page is the configuration lookup. [What is the uv build backend?](https://pydevtools.com/handbook/explanation/what-is-the-uv-build-backend.md) covers what the backend puts in each artifact, what it refuses to build, and when [Hatchling](https://pydevtools.com/handbook/reference/hatch.md) remains the better choice.

## Declare the backend

```toml {filename="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](https://pydevtools.com/handbook/reference/scikit-build-core.md).

## Configure the backend

All settings live under `[tool.uv.build-backend]` in [pyproject.toml](https://pydevtools.com/handbook/reference/pyproject.toml.md).

| 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](https://peps.python.org/pep-0639/), 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](https://peps.python.org/pep-0561/)) 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](https://peps.python.org/pep-0420/) 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](https://www.maturin.rs/), [scikit-build-core](https://pydevtools.com/handbook/reference/scikit-build-core.md), or [setuptools](https://pydevtools.com/handbook/reference/setuptools.md)
- No plugin system, so [Hatchling](https://pydevtools.com/handbook/reference/hatch.md) 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`
