Edits to the build backend documentation (#14376)
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

Co-authored-by: konstin <konstin@mailbox.org>
This commit is contained in:
Zanie Blue 2025-07-01 03:44:23 -05:00 committed by GitHub
parent a3db9a9ae4
commit b1812d111a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -7,98 +7,188 @@
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.
While uv supports all build backends (as specified by PEP 517), it includes a `uv_build` backend
that integrates tightly with uv to improve performance and user experience.
The uv build backend currently only supports Python code. An alternative backend is required if you
want to create a
[library with extension modules](../concepts/projects/init.md#projects-with-extension-modules).
uv supports all build backends (as specified by [PEP 517](https://peps.python.org/pep-0517/)), but
also provides a native build backend (`uv_build`) that integrates tightly with uv to improve
performance and user experience.
To use the uv build backend as [build system](../concepts/projects/config.md#build-systems) in an
existing project, add it to the `[build-system]` section in your `pyproject.toml`:
## Using the uv build backend
```toml
!!! 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]`](../concepts/projects/config.md#build-systems) section in your `pyproject.toml`:
```toml title="pyproject.toml"
[build-system]
requires = ["uv_build>=0.7.17,<0.8.0"]
build-backend = "uv_build"
```
!!! important
!!! note
The uv build backend follows the same [versioning policy](../reference/policies/versioning.md),
setting an upper bound on the `uv_build` version ensures that the package continues to build in
the future.
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.
You can also create a new project that uses the uv build backend with `uv init`:
To create a new project that uses the uv build backend, use `uv init`:
```shell
uv init --build-backend uv
```console
$ uv init --build-backend uv
```
`uv_build` is a separate package from uv, optimized for portability and small binary size. The `uv`
command includes a copy of the build backend, so when running `uv build`, the same version will be
used for the build backend as for the uv process. Other build frontends, such as `python -m build`,
will choose the latest compatible `uv_build` version.
When the project is built, e.g., with [`uv build`](../guides/package.md), 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
The default module name is the package name in lower case with dots and dashes replaced by
underscores, and the default module location is under the `src` directory, i.e., the build backend
expects to find `src/<package_name>/__init__.py`. These defaults can be changed with the
`module-name` and `module-root` setting. The example below expects a module in the project root with
`PIL/__init__.py` instead:
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`.
```toml
For example, the structure for a project named `foo` would be:
```text
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:
```text
pyproject.toml
FOO
└── __init__.py
```
The correct build configuration would be:
```toml title="pyproject.toml"
[tool.uv.build-backend]
module-name = "PIL"
module-name = "FOO"
module-root = ""
```
For a namespace packages, the path can be dotted. The example below expects to find a
`src/cloud/db/schema/__init__.py`:
## Namespace packages
```toml
[tool.uv.build-backend]
module-name = "cloud.db.schema"
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:
```text
pyproject.toml
src
└── foo
└── bar
└── __init__.py
```
Complex namespaces with more than one root module can be built by setting the `namespace` option,
which allows more than one root `__init__.py`:
And the `module-name` configuration would be:
```toml
```toml title="pyproject.toml"
[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:
```text
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:
```toml title="pyproject.toml"
[tool.uv.build-backend]
namespace = true
```
The build backend supports building stubs packages with a `-stubs` suffix on the package or module
name, including for namespace packages.
## Stub packages
## Include and exclude configuration
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:
To select which files to include in the source distribution, uv first adds the included files and
```text
pyproject.toml
src
└── foo-stubs
└── __init__.pyi
```
Type stub modules are also supported for [namespace packages](#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.
When building the source distribution, the following files and directories are included:
By default, uv excludes `__pycache__`, `*.pyc`, and `*.pyo`.
- `pyproject.toml`
- The module under `tool.uv.build-backend.module-root`, by default
`src/<module-name or project_name_with_underscores>/**`.
- `project.license-files` and `project.readme`.
- All directories under `tool.uv.build-backend.data`.
- All patterns from `tool.uv.build-backend.source-include`.
When building a source distribution, the following files and directories are included:
From these, `tool.uv.build-backend.source-exclude` and the default excludes are removed.
- The `pyproject.toml`
- The [module](#modules) under
[`tool.uv.build-backend.module-root`](../reference/settings.md#build-backend_module-root).
- The files referenced by `project.license-files` and `project.readme`.
- All directories under [`tool.uv.build-backend.data`](../reference/settings.md#build-backend_data).
- All files matching patterns from
[`tool.uv.build-backend.source-include`](../reference/settings.md#build-backend_source-include).
When building the wheel, the following files and directories are included:
From these, items matching
[`tool.uv.build-backend.source-exclude`](../reference/settings.md#build-backend_source-exclude) and
the [default excludes](../reference/settings.md#build-backend_default-excludes) are removed.
- The module under `tool.uv.build-backend.module-root`, by default
`src/<module-name or project_name_with_underscores>/**`.
- `project.license-files` and `project.readme`, as part of the project metadata.
- Each directory under `tool.uv.build-backend.data`, as data directories.
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
- The [module](#modules) under
[`tool.uv.build-backend.module-root`](../reference/settings.md#build-backend_module-root)
- The files referenced by `project.license-files`, which are copied into the `.dist-info` directory.
- The `project.readme`, which is copied into the project metadata.
- All directories under [`tool.uv.build-backend.data`](../reference/settings.md#build-backend_data),
which are copied into the `.data` directory.
From these,
[`tool.uv.build-backend.source-exclude`](../reference/settings.md#build-backend_source-exclude),
[`tool.uv.build-backend.wheel-exclude`](../reference/settings.md#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
@ -106,20 +196,20 @@ must either be under the module root or in the appropriate
[data directory](../reference/settings.md#build-backend_data). Most packages store small data in the
module root alongside the source code.
## Include and exclude syntax
### Include and exclude syntax
Includes are anchored, which means that `pyproject.toml` includes only
`<project root>/pyproject.toml`. For example, `assets/**/sample.csv` includes all `sample.csv` files
in `<project root>/assets` or any child directory. To recursively include all files under a
directory, use a `/**` suffix, e.g. `src/**`.
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__` and its children anywhere. To anchor a directory, use a `/` prefix, e.g., `/dist` will
exclude only `<project root>/dist`.
`__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](https://peps.python.org/pep-0639/#add-license-FILES-key), with the addition that