The uv 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 byPEP 517), butalso provides a native build backend (uv_build) that integrates tightly with uv to improveperformance and user experience.
Choosing a build backend
The uv build backend is a great choice for most Python projects. It has reasonable defaults, withthe goal of requiring zero configuration for most users, but provides flexible configuration toaccommodate most Python project structures. It integrates tightly with uv, to improve messaging anduser experience. It validates project metadata and structures, preventing common mistakes. And,finally, it's very fast.
The uv build backend currentlyonly supports pure Python code. An alternative backend isrequired to build alibrary with extension modules.
Tip
While the backend supports a number of options for configuring your project structure, when build scripts ora more flexible project layout are required, consider using thehatchling build backend instead.
Using the uv build backend
To use uv as a build backend in an existing project, adduv_build to the[build-system] section in yourpyproject.toml:
Note
The uv build backend follows the sameversioning policyas uv. Including an upper bound on theuv_build version ensures that your package continues tobuild correctly as new versions are released.
To create a new project that uses the uv build backend, useuv init:
When the project is built, e.g., withuv build, the uv build backend willbe 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 portabilityand small binary size. However, theuv executable also includes a copy of the build backend, whichwill be used during builds performed by uv, e.g., duringuv build, if its version is compatiblewith theuv_build requirement. If it's not compatible, a compatible version of theuv_buildpackage will be used. Other build frontends, such aspython -m build, will always use theuv_build package, typically choosing the latest compatible version.
Modules
Python packages are expected to contain one or more Python modules, which are directories containingan__init__.py. By default, a single root module is expected atsrc/<package_name>/__init__.py.
For example, the structure for a project namedfoo would be:
uv normalizes the package name to determine the default module name: the package name is lowercasedand dots and dashes are replaced with underscores, e.g.,Foo-Bar would be converted tofoo_bar.
Thesrc/ directory is the default directory for module discovery.
These defaults can be changed with themodule-name andmodule-root settings. For example, to useaFOO module in the root directory, as in the project structure:
The correct build configuration would be:
Namespace packages
Namespace packages are intended for use-cases where multiple packages write modules into a sharednamespace.
Namespace package modules are identified by a. in themodule-name. For example, to package themodulebar in the shared namespacefoo, the project structure would be:
And themodule-name configuration would be:
Important
The__init__.py file is not included infoo, 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., withthe project structure:
While we do not recommend this structure (i.e., you should use a workspace with multiple packagesinstead), it is supported by settingmodule-name to a list of names:
For packages with many modules or complex namespaces, thenamespace = true option can be used toavoid explicitly declaring each module name, e.g.:
Warning
Usingnamespace = true disables safety checks. Using an explicit list of module names isstrongly recommended outside of legacy projects.
Thenamespace option can also be used withmodule-name to explicitly declare the root, e.g., forthe project structure:
The recommended configuration would be:
Stub packages
The build backend also supports building type stub packages, which are identified by the-stubssuffix on the package or module name, e.g.,foo-stubs. The module name for type stub packages mustend in-stubs, so uv will not normalize the- to an underscore. Additionally, uv will search fora__init__.pyi file. For example, the project structure would be:
Type stub modules are also supported fornamespace packages.
File inclusion and exclusion
The build backend is responsible for determining which files in a source tree should be packagedinto the distributions.
To determine which files to include in a source distribution, uv first adds the included files anddirectories, then removes the excluded files and directories. This means that exclusions always takeprecedence over inclusions.
By default, uv excludes__pycache__,*.pyc, and*.pyo.
When building a source distribution, the following files and directories are included:
- The
pyproject.toml - Themodule under
tool.uv.build-backend.module-root. - The files referenced by
project.license-filesandproject.readme. - All directories under
tool.uv.build-backend.data. - All files matching patterns from
tool.uv.build-backend.source-include.
From these, items matchingtool.uv.build-backend.source-exclude andthedefault excludes are removed.
When building a wheel, the following files and directories are included:
- Themodule under
tool.uv.build-backend.module-root - The files referenced by
project.license-files, which are copied into the.dist-infodirectory. - The
project.readme, which is copied into the project metadata. - All directories under
tool.uv.build-backend.data, which are copied into the.datadirectory.
From these,tool.uv.build-backend.source-exclude,tool.uv.build-backend.wheel-exclude andthe default excludes are removed. The source dist excludes are applied to avoid source tree to wheelsource 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 filesmust either be under the module root or in the appropriatedata directory. Most packages store small data in themodule root alongside the source code.
Tip
When using the uv build backend through a frontend that is not uv, such as pip orpython -m build, debug logging can be enabled through environment variables withRUST_LOG=uv=debug orRUST_LOG=uv=verbose. When used through uv, the uv build backend sharesthe verbosity level of uv.
Include and exclude syntax
Includes are anchored, which means thatpyproject.toml includes only<root>/pyproject.toml andnot<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 includesallsample.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 fromPEP 639, with the addition thatcharacters can be escaped with a backslash.
November 7, 2025