@@ -196,6 +196,8 @@ def build_in_container(
196
196
log .build_start (config .identifier )
197
197
build_options = options .build_options (config .identifier )
198
198
build_frontend = build_options .build_frontend or BuildFrontendConfig ("pip" )
199
+ use_uv = build_frontend .name == "build[uv]" and Version (config .version ) >= Version ("3.8" )
200
+ pip = ["uv" , "pip" ] if use_uv else ["pip" ]
199
201
200
202
dependency_constraint_flags : list [PathOrStr ] = []
201
203
@@ -229,13 +231,22 @@ def build_in_container(
229
231
)
230
232
sys .exit (1 )
231
233
232
- which_pip = container .call (["which" , "pip" ], env = env , capture_output = True ).strip ()
233
- if PurePosixPath (which_pip ) != python_bin / "pip" :
234
- print (
235
- "cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it." ,
236
- file = sys .stderr ,
237
- )
238
- sys .exit (1 )
234
+ if use_uv :
235
+ which_uv = container .call (["which" , "uv" ], env = env , capture_output = True ).strip ()
236
+ if not which_uv :
237
+ print (
238
+ "cibuildwheel: uv not found on PATH. You must use a supported manylinux or musllinux environment with uv." ,
239
+ file = sys .stderr ,
240
+ )
241
+ sys .exit (1 )
242
+ else :
243
+ which_pip = container .call (["which" , "pip" ], env = env , capture_output = True ).strip ()
244
+ if PurePosixPath (which_pip ) != python_bin / "pip" :
245
+ print (
246
+ "cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it." ,
247
+ file = sys .stderr ,
248
+ )
249
+ sys .exit (1 )
239
250
240
251
compatible_wheel = find_compatible_wheel (built_wheels , config .identifier )
241
252
if compatible_wheel :
@@ -279,10 +290,12 @@ def build_in_container(
279
290
],
280
291
env = env ,
281
292
)
282
- elif build_frontend .name == "build" :
293
+ elif build_frontend .name == "build" or build_frontend . name == "build[uv]" :
283
294
if not 0 <= build_options .build_verbosity < 2 :
284
295
msg = f"build_verbosity { build_options .build_verbosity } is not supported for build frontend. Ignoring."
285
296
log .warning (msg )
297
+ if use_uv :
298
+ extra_flags += ["--installer=uv" ]
286
299
container .call (
287
300
[
288
301
"python" ,
@@ -327,26 +340,32 @@ def build_in_container(
327
340
328
341
# set up a virtual environment to install and test from, to make sure
329
342
# there are no dependencies that were pulled in at build time.
330
- container .call (["pip" , "install" , "virtualenv" , * dependency_constraint_flags ], env = env )
343
+ if not use_uv :
344
+ container .call (
345
+ ["pip" , "install" , "virtualenv" , * dependency_constraint_flags ], env = env
346
+ )
331
347
332
348
testing_temp_dir = PurePosixPath (
333
349
container .call (["mktemp" , "-d" ], capture_output = True ).strip ()
334
350
)
335
351
venv_dir = testing_temp_dir / "venv"
336
352
337
- # Use embedded dependencies from virtualenv to ensure determinism
338
- venv_args = ["--no-periodic-update" , "--pip=embed" ]
339
- # In Python<3.12, setuptools & wheel are installed as well
340
- if Version (config .version ) < Version ("3.12" ):
341
- venv_args .extend (("--setuptools=embed" , "--wheel=embed" ))
342
- container .call (["python" , "-m" , "virtualenv" , * venv_args , venv_dir ], env = env )
353
+ if use_uv :
354
+ container .call (["uv" , "venv" , venv_dir ], env = env )
355
+ else :
356
+ # Use embedded dependencies from virtualenv to ensure determinism
357
+ venv_args = ["--no-periodic-update" , "--pip=embed" ]
358
+ # In Python<3.12, setuptools & wheel are installed as well
359
+ if Version (config .version ) < Version ("3.12" ):
360
+ venv_args .extend (("--setuptools=embed" , "--wheel=embed" ))
361
+ container .call (["python" , "-m" , "virtualenv" , * venv_args , venv_dir ], env = env )
343
362
344
363
virtualenv_env = env .copy ()
345
364
virtualenv_env ["PATH" ] = f"{ venv_dir / 'bin' } :{ virtualenv_env ['PATH' ]} "
346
365
virtualenv_env ["VIRTUAL_ENV" ] = str (venv_dir )
347
366
348
367
# TODO remove me once virtualenv provides pip>=24.1b1
349
- if config .version == "3.13" :
368
+ if config .version == "3.13" and not use_uv :
350
369
container .call (["pip" , "install" , "pip>=24.1b1" ], env = virtualenv_env )
351
370
352
371
if build_options .before_test :
@@ -365,13 +384,13 @@ def build_in_container(
365
384
# Let's just pick the first one.
366
385
wheel_to_test = repaired_wheels [0 ]
367
386
container .call (
368
- [" pip" , "install" , str (wheel_to_test ) + build_options .test_extras ],
387
+ [* pip , "install" , str (wheel_to_test ) + build_options .test_extras ],
369
388
env = virtualenv_env ,
370
389
)
371
390
372
391
# Install any requirements to run the tests
373
392
if build_options .test_requires :
374
- container .call ([" pip" , "install" , * build_options .test_requires ], env = virtualenv_env )
393
+ container .call ([* pip , "install" , * build_options .test_requires ], env = virtualenv_env )
375
394
376
395
# Run the tests from a different directory
377
396
test_command_prepared = prepare_command (
0 commit comments