5.6.1 构建失败

原文链接: https://docs.astral.sh/uv/reference/troubleshooting/build-failures/

5.6.1 构建失败

当没有兼容的 wheel(包的预构建分发)可用时,uv 需要构建包。构建包可能因许多原因失败,其中一些可能与 uv 本身无关。

识别构建失败

在新版、不受支持的 Python 版本上尝试安装旧版 numpy 可以产生一个构建失败示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
$ uv pip install -p 3.13 'numpy<1.20'
Resolved 1 package in 62ms
  × Failed to build `numpy==1.19.5`
  ├─▶ The build backend returned an error
  ╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel()` failed (exit status: 1)

      [stderr]
      Traceback (most recent call last):
        File "<string>", line 8, in <module>
          from setuptools.build_meta import __legacy__ as backend
        File "/home/konsti/.cache/uv/builds-v0/.tmpi4bgKb/lib/python3.13/site-packages/setuptools/__init__.py", line 9, in <module>
          import distutils.core
      ModuleNotFoundError: No module named 'distutils'

      hint: `distutils` was removed from the standard library in Python 3.12. Consider adding a constraint (like `numpy >1.19.5`) to avoid building a version of `numpy` that depends
      on `distutils`.

注意错误信息以 “The build backend returned an error” 开头。

构建失败中包含用于构建的构建后端输出的 [stderr](以及 [stdout],如果有)。这些错误日志并非来自 uv 本身。

╰─▶ 之后的信息是 uv 提供的提示,用于帮助解决常见构建失败。并非所有构建失败都会有提示。

确认构建失败是 uv 特有的

构建失败通常与你的系统和构建后端有关。构建失败是 uv 特有的情况很少见。你可以通过用 pip 尝试复现来确认该构建失败与 uv 无关:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ uv venv -p 3.13 --seed
$ source .venv/bin/activate
$ pip install --use-pep517 --no-cache --force-reinstall 'numpy==1.19.5'
Collecting numpy==1.19.5
  Using cached numpy-1.19.5.zip (7.3 MB)
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
ERROR: Exception:
Traceback (most recent call last):
  ...
  File "/Users/example/.cache/uv/archive-v0/3783IbOdglemN3ieOULx2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_impl.py", line 321, in _call_hook
    raise BackendUnavailable(data.get('traceback', ''))
pip._vendor.pyproject_hooks._impl.BackendUnavailable: Traceback (most recent call last):
  File "/Users/example/.cache/uv/archive-v0/3783IbOdglemN3ieOULx2/lib/python3.13/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py", line 77, in _build_backend
    obj = import_module(mod_path)
  File "/Users/example/.local/share/uv/python/cpython-3.13.0-macos-aarch64-none/lib/python3.13/importlib/__init__.py", line 88, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1310, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 1022, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/private/var/folders/6p/k5sd5z7j31b31pq4lhn0l8d80000gn/T/pip-build-env-vdpjme7d/overlay/lib/python3.13/site-packages/setuptools/__init__.py", line 9, in <module>
    import distutils.core
ModuleNotFoundError: No module named 'distutils'

重要

pip install 调用中应包含 --use-pep517 标志,以确保相同的构建隔离行为。uv 始终默认使用构建隔离。

复现失败时我们还建议加上 --force-reinstall 和 --no-cache 选项。

由于该构建失败在 pip 中也会出现,它不太可能是 uv 的缺陷。

如果构建失败能用其他安装器复现,你应当向上游排查(在本例中是 numpy 或 setuptools),想办法避免构建该包,或者对系统做必要调整以使构建成功。

为什么 uv 会构建包?

生成跨平台锁文件时,uv 需要确定所有包的依赖,即使那些只在其他平台上安装的包也不例外。uv 会尽量避免在解析期间构建包。它会使用该版本已有的任何 wheel,然后尝试在源码分发中查找静态元数据(主要是带静态 project.version、project.dependencies 和 project.optional-dependencies 的 pyproject.toml,或 METADATA v2.2+)。只有这些全都失败时,它才会构建该包。

安装时,uv 需要为当前平台的每个包准备一个 wheel。如果索引中没有匹配的 wheel,uv 会尝试构建源码分发。

你可以在 PyPI 项目的 “Download Files” 下查看存在哪些 wheel,例如 https://pypi.org/project/numpy/2.1.1.md#files。文件名形如 ...-py3-none-any.whl 的 wheel 在任何平台都可用,其他 wheel 的文件名中包含操作系统和平台。在上面链接的 numpy 示例中,可以看到 macOS、Linux 和 Windows 上都有 Python 3.10 到 3.13 的预构建分发。

常见构建失败

下面的示例展示常见的构建失败及其解决方法。

找不到命令

如果构建错误提到缺少某个命令,例如 gcc:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
× Failed to build `pysha3==1.0.2`
├─▶ The build backend returned an error
╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit status: 1)

    [stdout]
    running bdist_wheel
    running build
    running build_py
    creating build/lib.linux-x86_64-cpython-310
    copying sha3.py -> build/lib.linux-x86_64-cpython-310
    running build_ext
    building '_pysha3' extension
    creating build/temp.linux-x86_64-cpython-310/Modules/_sha3
    gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -DPY_WITH_KECCAK=1 -I/root/.cache/uv/builds-v0/.tmp8V4iEk/include -I/usr/local/include/python3.10 -c
    Modules/_sha3/sha3module.c -o build/temp.linux-x86_64-cpython-310/Modules/_sha3/sha3module.o

    [stderr]
    error: command 'gcc' failed: No such file or directory

那么你需要用系统包管理器安装它,例如要解决上面的错误:

1
$ apt install gcc

提示

使用 uv 管理的 Python 版本时,常见的情况是需要安装 clang 而不是 gcc。

许多 Linux 发行版都提供一个包含所有常见构建依赖的包。安装它就能满足大多数构建要求,例如对 Debian 或 Ubuntu:

1
$ apt install build-essential

缺少头文件或库

如果构建错误提到缺少头文件或库,例如 .h 文件,那么你需要用系统包管理器安装它。

例如,安装 pygraphviz 需要先安装 Graphviz:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
× Failed to build `pygraphviz==1.14`
├─▶ The build backend returned an error
╰─▶ Call to `setuptools.build_meta.build_wheel` failed (exit status: 1)

  [stdout]
  running bdist_wheel
  running build
  running build_py
  ...
  gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC -DSWIG_PYTHON_STRICT_BYTE_CHAR -I/root/.cache/uv/builds-v0/.tmpgLYPe0/include -I/usr/local/include/python3.12 -c pygraphviz/graphviz_wrap.c -o
  build/temp.linux-x86_64-cpython-312/pygraphviz/graphviz_wrap.o

  [stderr]
  ...
  pygraphviz/graphviz_wrap.c:9: warning: "SWIG_PYTHON_STRICT_BYTE_CHAR" redefined
      9 | #define SWIG_PYTHON_STRICT_BYTE_CHAR
        |
  <command-line>: note: this is the location of the previous definition
  pygraphviz/graphviz_wrap.c:3023:10: fatal error: graphviz/cgraph.h: No such file or directory
    3023 | #include "graphviz/cgraph.h"
        |          ^~~~~~~~~~~~~~~~~~~
  compilation terminated.
  error: command '/usr/bin/gcc' failed with exit code 1

  hint: This error likely indicates that you need to install a library that provides "graphviz/cgraph.h" for `pygraphviz@1.14`

要在 Debian 上解决该错误,你应安装 libgraphviz-dev 包:

1
$ apt install libgraphviz-dev

注意只安装 graphviz 包是不够的,还需要安装开发头文件。

提示

要解决缺少 Python.h 的错误,请安装 python3-dev 包。

缺少模块或无法导入模块

如果构建错误提到导入失败,可以考虑禁用构建隔离。

例如,某些包假定 pip 可用,却没有把它声明为构建依赖:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  × Failed to build `chumpy==0.70`
  ├─▶ The build backend returned an error
  ╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit status: 1)

    [stderr]
    Traceback (most recent call last):
      File "<string>", line 9, in <module>
    ModuleNotFoundError: No module named 'pip'

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "<string>", line 14, in <module>
      File "/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py", line 334, in get_requires_for_build_wheel
        return self._get_build_requires(config_settings, requirements=[])
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py", line 304, in _get_build_requires
        self.run_setup()
      File "/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py", line 522, in run_setup
        super().run_setup(setup_script=setup_script)
      File "/root/.cache/uv/builds-v0/.tmpvvHaxI/lib/python3.12/site-packages/setuptools/build_meta.py", line 320, in run_setup
        exec(code, locals())
      File "<string>", line 11, in <module>
    ModuleNotFoundError: No module named 'pip'

要解决该错误,请预先安装构建依赖,然后为该包禁用构建隔离:

1
2
$ uv pip install pip setuptools
$ uv pip install chumpy --no-build-isolation-package chumpy

注意你需要安装缺失的包(例如 pip)以及该包的所有其他构建依赖(例如 setuptools)。

构建了旧版本的包

如果某个包在解析期间构建失败,而构建失败的版本比你想要使用的版本更旧,请尝试添加带下界的约束(例如 numpy>=1.17)。有时由于算法限制,uv 解析器会尝试用不合理地旧的包来寻找合适的版本,使用下界可以避免这种情况。

例如,在 Python 3.10 上解析下面的依赖时,uv 会尝试构建旧版本的 apache-beam。

1
2
3
# requirements.txt
dill<0.3.9,>=0.2.2
apache-beam<=2.49.0
1
2
3
4
5
6
× Failed to build `apache-beam==2.0.0`
├─▶ The build backend returned an error
╰─▶ Call to `setuptools.build_meta:__legacy__.build_wheel` failed (exit status: 1)

    [stderr]
    ...

添加下界约束(例如 apache-beam<=2.49.0,>2.30.0)可以解决该构建失败,因为 uv 会避免使用旧版本的 apache-beam。

对于间接依赖,也可以通过 constraints.txt 文件或 constraint-dependencies 设置定义约束。

使用了旧版本的构建依赖

如果某个包因为 uv 选择了不兼容或过时的构建期依赖版本而构建失败,你可以专门为构建依赖强制约束。build-constraint-dependencies 设置(或类似的 build-constraints.txt 文件)可用于确保 uv 为给定构建 requirement 选择合适的版本。

例如,#5551 中描述的问题可以通过指定排除 setuptools 72.0.0 版本的构建约束来解决:

1
2
3
4
# pyproject.toml
[tool.uv]
# 防止 setuptools 72.0.0 版本被用作构建依赖。
build-constraint-dependencies = ["setuptools!=72.0.0"]

这样该构建约束就能确保任何在构建过程中需要 setuptools 的包都避免使用有问题的版本,从而防止由不兼容构建依赖导致的构建失败。

包只在不需要的平台上被需要

如果锁定失败是因为构建某个你不需要支持的平台上的包,可以考虑把解析限制到你支持的平台。

包不支持所有 Python 版本

如果你支持的 Python 版本范围很大,可以考虑使用标记,让较旧的 Python 版本使用较旧的包版本、较新的 Python 版本使用较新的包版本。例如 numpy 一次只支持四个 Python 次要版本,因此要支持从 Python 3.8 到 3.13 这样更宽的范围,需要拆分 numpy requirement:

numpy>=1.23; python_version >= "3.10"
numpy<1.23; python_version < "3.10"

包只能在特定平台上使用

如果锁定失败是因为构建一个只能在其他平台上使用的包,你可以手动提供依赖元数据以跳过构建。uv 无法校验这些信息,因此使用该覆盖时提供正确的元数据很重要。

最后修改 September 25, 2026: 更新 (221c74c33)