@@ -81,6 +81,28 @@ the same platform the lockfile was created on. To solve this problem, platform-i
81
81
uv supports both [ platform-specific] ( #platform-specific-resolution ) and
82
82
[ universal] ( #universal-resolution ) resolution.
83
83
84
+ ## Platform-specific resolution
85
+
86
+ By default, uv's pip interface, i.e., [ ` uv pip compile ` ] ( ../pip/compile.md ) , produces a resolution
87
+ that is platform-specific, like ` pip-tools ` . There is no way to use platform-specific resolution in
88
+ the uv's project interface.
89
+
90
+ uv also supports resolving for specific, alternate platforms and Python versions with the
91
+ ` --python-platform ` and ` --python-version ` options. For example, if using Python 3.12 on macOS,
92
+ ` uv pip compile --python-platform linux --python-version 3.10 requirements.in ` can be used to
93
+ produce a resolution for Python 3.10 on Linux instead. Unlike universal resolution, during
94
+ platform-specific resolution, the provided ` --python-version ` is the exact python version to use,
95
+ not a lower bound.
96
+
97
+ !!! note
98
+
99
+ Python's environment markers expose far more information about the current machine
100
+ than can be expressed by a simple `--python-platform` argument. For example, the `platform_version` marker
101
+ on macOS includes the time at which the kernel was built, which can (in theory) be encoded in
102
+ package requirements. uv's resolver makes a best-effort attempt to generate a resolution that is
103
+ compatible with any machine running on the target `--python-platform`, which should be sufficient for
104
+ most use cases, but may lose fidelity for complex package and platform combinations.
105
+
84
106
## Universal resolution
85
107
86
108
uv's lockfile (` uv.lock ` ) is created with a universal resolution and is portable across platforms.
@@ -117,27 +139,80 @@ bounds on `requires-python` often leads to formally correct but practically inco
117
139
as, e.g., resolvers will backtrack to the first published version that omits the upper bound (see:
118
140
[ ` Requires-Python ` upper limits] ( https://discuss.python.org/t/requires-python-upper-limits/12663 ) ).
119
141
120
- ## Platform-specific resolution
142
+ ### Limited resolution environments
121
143
122
- By default, uv's pip interface, i.e., [ ` uv pip compile ` ] ( ../pip/compile.md ) , produces a resolution
123
- that is platform-specific, like ` pip-tools ` . There is no way to use platform-specific resolution in
124
- the uv's project interface.
144
+ By default, the universal resolver attempts to solve for all platforms and Python versions.
125
145
126
- uv also supports resolving for specific, alternate platforms and Python versions with the
127
- ` --python-platform ` and ` --python-version ` options. For example, if using Python 3.12 on macOS,
128
- ` uv pip compile --python-platform linux --python-version 3.10 requirements.in ` can be used to
129
- produce a resolution for Python 3.10 on Linux instead. Unlike universal resolution, during
130
- platform-specific resolution, the provided ` --python-version ` is the exact python version to use,
131
- not a lower bound.
146
+ If your project supports only a limited set of platforms or Python versions, you can constrain the
147
+ set of solved platforms via the ` environments ` setting, which accepts a list of PEP 508 environment
148
+ markers. In other words, you can use the ` environments ` setting to _ reduce_ the set of supported
149
+ platforms.
132
150
133
- !!! note
151
+ For example, to constrain the lockfile to macOS and Linux, and avoid solving for Windows:
134
152
135
- Python's environment markers expose far more information about the current machine
136
- than can be expressed by a simple `--python-platform` argument. For example, the `platform_version` marker
137
- on macOS includes the time at which the kernel was built, which can (in theory) be encoded in
138
- package requirements. uv's resolver makes a best-effort attempt to generate a resolution that is
139
- compatible with any machine running on the target `--python-platform`, which should be sufficient for
140
- most use cases, but may lose fidelity for complex package and platform combinations.
153
+ ``` toml title="pyproject.toml"
154
+ [tool .uv ]
155
+ environments = [
156
+ " sys_platform == 'darwin'" ,
157
+ " sys_platform == 'linux'" ,
158
+ ]
159
+ ```
160
+
161
+ Or, to avoid solving for alternative Python implementations:
162
+
163
+ ``` toml title="pyproject.toml"
164
+ [tool .uv ]
165
+ environments = [
166
+ " implementation_name == 'cpython'"
167
+ ]
168
+ ```
169
+
170
+ Entries in the ` environments ` setting must be disjoint (i.e., they must not overlap). For example,
171
+ ` sys_platform == 'darwin' ` and ` sys_platform == 'linux' ` are disjoint, but
172
+ ` sys_platform == 'darwin' ` and ` python_version >= '3.9' ` are not, since both could be true at the
173
+ same time.
174
+
175
+ ### Required environments
176
+
177
+ In the Python ecosystem, packages can be published as source distributions, built distributions
178
+ (wheels), or both; but to install a package, a built distribution is required. If a package lacks a
179
+ built distribution, or lacks a distribution for the current platform or Python version (built
180
+ distributions are often platform-specific), uv will attempt to build the package from source, then
181
+ install the resulting built distribution.
182
+
183
+ Some packages (like PyTorch) publish built distributions, but omit a source distribution. Such
184
+ packages are _ only_ installable on platforms for which a built distribution is available. For
185
+ example, if a package publishes built distributions for Linux, but not macOS or Windows, then that
186
+ package will _ only_ be installable on Windows.
187
+
188
+ Packages that lack source distributions cause problems for universal resolution, since there will
189
+ typically be at least one platform or Python version for which the package is not installable.
190
+
191
+ By default, uv requires each such package to include at least one wheel that is compatible with the
192
+ target Python version. The ` required-environments ` setting can be used to ensure that the resulting
193
+ resolution contains wheels for specific platforms, or fails if no such wheels are available.
194
+
195
+ While the ` environments ` setting _ limits_ the set of environments that uv will consider when
196
+ resolving dependencies, ` required-environments ` _ expands_ the set of platforms that uv _ must_
197
+ support when resolving dependencies.
198
+
199
+ For example, ` environments = ["sys_platform == 'darwin'"] ` would limit uv to solving for macOS (and
200
+ ignoring Linux and Windows). On the other hand,
201
+ ` required-environments = ["sys_platform == 'darwin'"] ` would _ require_ that any package without a
202
+ source distribution include a wheel for macOS in order to be installable (and would fail if no such
203
+ wheel is available).
204
+
205
+ In practice, ` required-environments ` can be useful for declaring explicit support for non-latest
206
+ platforms, since this often requires backtracking past the latest published versions of those
207
+ packages. For example, to guarantee that any built distribution-only packages includes support for
208
+ Intel macOS:
209
+
210
+ ``` toml title="pyproject.toml"
211
+ [tool .uv ]
212
+ required-environments = [
213
+ " sys_platform == 'darwin' and platform_machine == 'x86_64'"
214
+ ]
215
+ ```
141
216
142
217
## Dependency preferences
143
218
0 commit comments