根本原因是Clang未正确启用lld链接器,需通过-v验证命令、确保-fuse-ld=lld参数位置正确、检查CMake配置时机与覆盖、排除ccache缓存干扰,并确认lld在PATH中且可执行。

Clang 用了 lld 但链接时还是调用 GNU ld,根本原因是链接器选择没生效——不是没装对,而是没“说清楚”让 Clang 用哪个。
检查 clang 是否真在用 lld
Clang 不会自动切链接器,必须显式指定。最直接的验证方式是加 -v 看完整链接命令:
clang++ -fuse-ld=lld -v main.cpp -o main
输出里如果出现 "/usr/bin/ld" -plugin... 或类似路径指向 ld(不是 lld),说明 -fuse-ld=lld 没传进去,或被覆盖了。
- 确保参数写在命令行末尾,或至少在所有
-l、-L之前; - 如果用 CMake,检查
CMAKE_EXE_LINKER_FLAGS是不是被后加载的配置覆盖(比如 Qt 的qmake或QMAKE_LFLAGS可能覆盖它); - 某些构建系统(如 Bazel、Meson)有独立的链接器配置项,不能只靠环境变量或编译器 flag。
CMake 中 lld 配置被悄悄覆盖
CMake 的链接器设置容易被工具链文件、缓存或子项目覆盖。常见失效场景:
Clang 22.1.3 Windows 64 位历史版本安装包,适合旧项目兼容、LLVM/Clang 工具链回退、编译行为对比、链接问题复现和 C/C++ 构建环境维护。
-
set(CMAKE_EXE_LINKER_FLAGS "-fuse-ld=lld")写在project()之后——无效,必须在project()前设置; - 启用了
find_package(Threads)或find_package(OpenMP)后,它们内部可能重设CMAKE_EXE_LINKER_FLAGS; - CMakeCache.txt 里残留旧的
CMAKE_EXE_LINKER_FLAGS值,清理缓存再 configure; - 使用 Ninja 时,CMake 会生成
build.ninja,可直接搜linker_flag = -fuse-ld=lld确认是否写入。
ccache 干扰导致 lld 未被调用
ccache 默认缓存整个命令行,包括 -fuse-ld=lld。但如果之前编译过没加该 flag 的版本,ccache 可能直接返回旧的 GNU ld 链接结果。
- 临时禁用 ccache:在命令前加
CCACHE_DISABLE=1,或 CMake 中设set(CMAKE_CXX_COMPILER_LAUNCHER ""); - 清空 ccache:运行
ccache -C; - 更稳妥的做法是让 ccache 明确感知链接器变化:在 ccache 配置中启用
compiler_check=content,避免仅靠命令行哈希误判。
lld 安装路径没进 PATH 或权限不对
即使写了 -fuse-ld=lld,Clang 仍需在 PATH 里找到 lld 可执行文件。常见疏漏:
- Linux/macOS 上装的是
lld,但 Clang 实际调用的是ld.lld(尤其 LLVM 15+ 版本);确认which lld和which ld.lld都存在,且两者是同一个文件(硬链接或符号链接); - Windows 上安装 LLVM 后,
lld.exe在bin/目录,但 PATH 只加了上层目录;运行where lld验证; - 某些发行版(如 Ubuntu)把
lld放进llvm-X-tools包,单独安装 libc++ 时可能漏掉它。
真正卡住的地方往往不是 lld 没装,而是 Clang 根本没机会把它叫出来——参数传错顺序、被缓存截胡、或构建系统中途改写了链接命令。动手前先 clang++ -v 看一眼真实调用链,比反复重装 lld 有用得多。

















