|
7 | 7 | When preview mode is not enabled, uv uses [hatchling](https://pypi.org/project/hatchling/) as the default build backend. |
8 | 8 |
|
9 | 9 | A build backend transforms a source tree (i.e., a directory) into a source distribution or a wheel. |
10 | | -While uv supports all build backends (as specified by PEP 517), it includes a `uv_build` backend |
11 | | -that integrates tightly with uv to improve performance and user experience. |
12 | 10 |
|
13 | | -The uv build backend currently only supports Python code. An alternative backend is required if you |
14 | | -want to create a |
15 | | -[library with extension modules](../concepts/projects/init.md#projects-with-extension-modules). |
| 11 | +uv supports all build backends (as specified by [PEP 517](https://peps.python.org/pep-0517/)), but |
| 12 | +also provides a native build backend (`uv_build`) that integrates tightly with uv to improve |
| 13 | +performance and user experience. |
16 | 14 |
|
17 | | -To use the uv build backend as [build system](../concepts/projects/config.md#build-systems) in an |
18 | | -existing project, add it to the `[build-system]` section in your `pyproject.toml`: |
| 15 | +## Using the uv build backend |
19 | 16 |
|
20 | | -```toml |
| 17 | +!!! important |
| 18 | + |
| 19 | + The uv build backend currently **only supports pure Python code**. An alternative backend is to |
| 20 | + build a [library with extension modules](../concepts/projects/init.md#projects-with-extension-modules). |
| 21 | + |
| 22 | +To use uv as a build backend in an existing project, add `uv_build` to the |
| 23 | +[`[build-system]`](../concepts/projects/config.md#build-systems) section in your `pyproject.toml`: |
| 24 | + |
| 25 | +```toml title="pyproject.toml" |
21 | 26 | [build-system] |
22 | 27 | requires = ["uv_build>=0.7.17,<0.8.0"] |
23 | 28 | build-backend = "uv_build" |
24 | 29 | ``` |
25 | 30 |
|
26 | | -!!! important |
| 31 | +!!! note |
27 | 32 |
|
28 | | - The uv build backend follows the same [versioning policy](../reference/policies/versioning.md), |
29 | | - setting an upper bound on the `uv_build` version ensures that the package continues to build in |
30 | | - the future. |
| 33 | + The uv build backend follows the same [versioning policy](../reference/policies/versioning.md) |
| 34 | + as uv. Including an upper bound on the `uv_build` version ensures that your package continues to |
| 35 | + build correctly as new versions are released. |
31 | 36 |
|
32 | | -You can also create a new project that uses the uv build backend with `uv init`: |
| 37 | +To create a new project that uses the uv build backend, use `uv init`: |
33 | 38 |
|
34 | | -```shell |
35 | | -uv init --build-backend uv |
| 39 | +```console |
| 40 | +$ uv init --build-backend uv |
36 | 41 | ``` |
37 | 42 |
|
38 | | -`uv_build` is a separate package from uv, optimized for portability and small binary size. The `uv` |
39 | | -command includes a copy of the build backend, so when running `uv build`, the same version will be |
40 | | -used for the build backend as for the uv process. Other build frontends, such as `python -m build`, |
41 | | -will choose the latest compatible `uv_build` version. |
| 43 | +When the project is built, e.g., with [`uv build`](../guides/package.md), the uv build backend will |
| 44 | +be used to create the source distribution and wheel. |
| 45 | + |
| 46 | +## Bundled build backend |
| 47 | + |
| 48 | +The build backend is published as a separate package (`uv_build`) that is optimized for portability |
| 49 | +and small binary size. However, the `uv` executable also includes a copy of the build backend, which |
| 50 | +will be used during builds performed by uv, e.g., during `uv build`, if its version is compatible |
| 51 | +with the `uv_build` requirement. If it's not compatible, a compatible version of the `uv_build` |
| 52 | +package will be used. Other build frontends, such as `python -m build`, will always use the |
| 53 | +`uv_build` package, typically choosing the latest compatible version. |
42 | 54 |
|
43 | 55 | ## Modules |
44 | 56 |
|
45 | | -The default module name is the package name in lower case with dots and dashes replaced by |
46 | | -underscores, and the default module location is under the `src` directory, i.e., the build backend |
47 | | -expects to find `src/<package_name>/__init__.py`. These defaults can be changed with the |
48 | | -`module-name` and `module-root` setting. The example below expects a module in the project root with |
49 | | -`PIL/__init__.py` instead: |
| 57 | +Python packages are expected to contain one or more Python modules, which are directories containing |
| 58 | +an `__init__.py`. By default, a single root module is expected at `src/<package_name>/__init__.py`. |
| 59 | + |
| 60 | +For example, the structure for a project named `foo` would be: |
| 61 | + |
| 62 | +```text |
| 63 | +pyproject.toml |
| 64 | +src |
| 65 | +└── foo |
| 66 | + └── __init__.py |
| 67 | +``` |
| 68 | + |
| 69 | +uv normalizes the package name to determine the default module name: the package name is lowercased |
| 70 | +and dots and dashes are replaced with underscores, e.g., `Foo-Bar` would be converted to `foo_bar`. |
| 71 | + |
| 72 | +The `src/` directory is the default directory for module discovery. |
| 73 | + |
| 74 | +These defaults can be changed with the `module-name` and `module-root` settings. For example, to use |
| 75 | +a `FOO` module in the root directory, as in the project structure: |
| 76 | + |
| 77 | +```text |
| 78 | +pyproject.toml |
| 79 | +FOO |
| 80 | +└── __init__.py |
| 81 | +``` |
| 82 | + |
| 83 | +The correct build configuration would be: |
50 | 84 |
|
51 | | -```toml |
| 85 | +```toml title="pyproject.toml" |
52 | 86 | [tool.uv.build-backend] |
53 | | -module-name = "PIL" |
| 87 | +module-name = "FOO" |
54 | 88 | module-root = "" |
55 | 89 | ``` |
56 | 90 |
|
57 | | -For a namespace packages, the path can be dotted. The example below expects to find a |
58 | | -`src/cloud/db/schema/__init__.py`: |
| 91 | +## Namespace packages |
59 | 92 |
|
60 | | -```toml |
| 93 | +Namespace packages are intended for use-cases where multiple packages write modules into a shared |
| 94 | +namespace. |
| 95 | + |
| 96 | +Namespace package modules are identified by a `.` in the `module-name`. For example, to package the |
| 97 | +module `bar` in the shared namespace `foo`, the project structure would be: |
| 98 | + |
| 99 | +```text |
| 100 | +pyproject.toml |
| 101 | +src |
| 102 | +└── foo |
| 103 | + └── bar |
| 104 | + └── __init__.py |
| 105 | +``` |
| 106 | + |
| 107 | +And the `module-name` configuration would be: |
| 108 | + |
| 109 | +```toml title="pyproject.toml" |
61 | 110 | [tool.uv.build-backend] |
62 | | -module-name = "cloud.db.schema" |
| 111 | +module-name = "foo.bar" |
63 | 112 | ``` |
64 | 113 |
|
65 | | -Complex namespaces with more than one root module can be built by setting the `namespace` option, |
66 | | -which allows more than one root `__init__.py`: |
| 114 | +!!! important |
| 115 | + |
| 116 | + The `__init__.py` file is not included in `foo`, since it's the shared namespace module. |
67 | 117 |
|
68 | | -```toml |
| 118 | +It's also possible to have a complex namespace package with more than one root module, e.g., with |
| 119 | +the project structure: |
| 120 | + |
| 121 | +```text |
| 122 | +pyproject.toml |
| 123 | +src |
| 124 | +├── foo |
| 125 | +│ └── __init__.py |
| 126 | +└── bar |
| 127 | + └── __init__.py |
| 128 | +``` |
| 129 | + |
| 130 | +While we do not recommend this structure (i.e., you should use a workspace with multiple packages |
| 131 | +instead), it is supported via the `namespace` option: |
| 132 | + |
| 133 | +```toml title="pyproject.toml" |
69 | 134 | [tool.uv.build-backend] |
70 | 135 | namespace = true |
71 | 136 | ``` |
72 | 137 |
|
73 | | -The build backend supports building stubs packages with a `-stubs` suffix on the package or module |
74 | | -name, including for namespace packages. |
| 138 | +## Stub packages |
| 139 | + |
| 140 | +The build backend also supports building type stub packages, which are identified by the `-stubs` |
| 141 | +suffix on the package or module name, e.g., `foo-stubs`. The module name for type stub packages must |
| 142 | +end in `-stubs`, so uv will not normalize the `-` to an underscore. Additionally, uv will search for |
| 143 | +a `__init__.pyi` file. For example, the project structure would be: |
| 144 | + |
| 145 | +```text |
| 146 | +pyproject.toml |
| 147 | +src |
| 148 | +└── foo-stubs |
| 149 | + └── __init__.pyi |
| 150 | +``` |
| 151 | + |
| 152 | +Type stub modules are also supported for [namespace packages](#namespace-packages). |
75 | 153 |
|
76 | | -## Include and exclude configuration |
| 154 | +## File inclusion and exclusion |
77 | 155 |
|
78 | | -To select which files to include in the source distribution, uv first adds the included files and |
| 156 | +The build backend is responsible for determining which files in a source tree should be packaged |
| 157 | +into the distributions. |
| 158 | + |
| 159 | +To determine which files to include in a source distribution, uv first adds the included files and |
79 | 160 | directories, then removes the excluded files and directories. This means that exclusions always take |
80 | 161 | precedence over inclusions. |
81 | 162 |
|
82 | | -When building the source distribution, the following files and directories are included: |
| 163 | +By default, uv excludes `__pycache__`, `*.pyc`, and `*.pyo`. |
| 164 | + |
| 165 | +When building a source distribution, the following files and directories are included: |
83 | 166 |
|
84 | | -- `pyproject.toml` |
85 | | -- The module under `tool.uv.build-backend.module-root`, by default |
86 | | - `src/<module-name or project_name_with_underscores>/**`. |
87 | | -- `project.license-files` and `project.readme`. |
88 | | -- All directories under `tool.uv.build-backend.data`. |
89 | | -- All patterns from `tool.uv.build-backend.source-include`. |
| 167 | +- The `pyproject.toml` |
| 168 | +- The [module](#modules) under |
| 169 | + [`tool.uv.build-backend.module-root`](../reference/settings.md#build-backend_module-root). |
| 170 | +- The files referenced by `project.license-files` and `project.readme`. |
| 171 | +- All directories under [`tool.uv.build-backend.data`](../reference/settings.md#build-backend_data). |
| 172 | +- All files matching patterns from |
| 173 | + [`tool.uv.build-backend.source-include`](../reference/settings.md#build-backend_source-include). |
90 | 174 |
|
91 | | -From these, `tool.uv.build-backend.source-exclude` and the default excludes are removed. |
| 175 | +From these, items matching |
| 176 | +[`tool.uv.build-backend.source-exclude`](../reference/settings.md#build-backend_source-exclude) and |
| 177 | +the [default excludes](../reference/settings.md#build-backend_default-excludes) are removed. |
92 | 178 |
|
93 | | -When building the wheel, the following files and directories are included: |
| 179 | +When building a wheel, the following files and directories are included: |
94 | 180 |
|
95 | | -- The module under `tool.uv.build-backend.module-root`, by default |
96 | | - `src/<module-name or project_name_with_underscores>/**`. |
97 | | -- `project.license-files` and `project.readme`, as part of the project metadata. |
98 | | -- Each directory under `tool.uv.build-backend.data`, as data directories. |
| 181 | +- The [module](#modules) under |
| 182 | + [`tool.uv.build-backend.module-root`](../reference/settings.md#build-backend_module-root) |
| 183 | +- The files referenced by `project.license-files`, which are copied into the `.dist-info` directory. |
| 184 | +- The `project.readme`, which is copied into the project metadata. |
| 185 | +- All directories under [`tool.uv.build-backend.data`](../reference/settings.md#build-backend_data), |
| 186 | + which are copied into the `.data` directory. |
99 | 187 |
|
100 | | -From these, `tool.uv.build-backend.source-exclude`, `tool.uv.build-backend.wheel-exclude` and the |
101 | | -default excludes are removed. The source dist excludes are applied to avoid source tree to wheel |
| 188 | +From these, |
| 189 | +[`tool.uv.build-backend.source-exclude`](../reference/settings.md#build-backend_source-exclude), |
| 190 | +[`tool.uv.build-backend.wheel-exclude`](../reference/settings.md#build-backend_wheel-exclude) and |
| 191 | +the default excludes are removed. The source dist excludes are applied to avoid source tree to wheel |
102 | 192 | source builds including more files than source tree to source distribution to wheel build. |
103 | 193 |
|
104 | 194 | There are no specific wheel includes. There must only be one top level module, and all data files |
105 | 195 | must either be under the module root or in the appropriate |
106 | 196 | [data directory](../reference/settings.md#build-backend_data). Most packages store small data in the |
107 | 197 | module root alongside the source code. |
108 | 198 |
|
109 | | -## Include and exclude syntax |
| 199 | +### Include and exclude syntax |
110 | 200 |
|
111 | | -Includes are anchored, which means that `pyproject.toml` includes only |
112 | | -`<project root>/pyproject.toml`. For example, `assets/**/sample.csv` includes all `sample.csv` files |
113 | | -in `<project root>/assets` or any child directory. To recursively include all files under a |
114 | | -directory, use a `/**` suffix, e.g. `src/**`. |
| 201 | +Includes are anchored, which means that `pyproject.toml` includes only `<root>/pyproject.toml` and |
| 202 | +not `<root>/bar/pyproject.toml`. To recursively include all files under a directory, use a `/**` |
| 203 | +suffix, e.g. `src/**`. Recursive inclusions are also anchored, e.g., `assets/**/sample.csv` includes |
| 204 | +all `sample.csv` files in `<root>/assets` or any of its children. |
115 | 205 |
|
116 | 206 | !!! note |
117 | 207 |
|
118 | 208 | For performance and reproducibility, avoid patterns without an anchor such as `**/sample.csv`. |
119 | 209 |
|
120 | 210 | Excludes are not anchored, which means that `__pycache__` excludes all directories named |
121 | | -`__pycache__` and its children anywhere. To anchor a directory, use a `/` prefix, e.g., `/dist` will |
122 | | -exclude only `<project root>/dist`. |
| 211 | +`__pycache__` regardless of its parent directory. All children of an exclusion are excluded as well. |
| 212 | +To anchor a directory, use a `/` prefix, e.g., `/dist` will exclude only `<root>/dist`. |
123 | 213 |
|
124 | 214 | All fields accepting patterns use the reduced portable glob syntax from |
125 | 215 | [PEP 639](https://peps.python.org/pep-0639/#add-license-FILES-key), with the addition that |
|
0 commit comments