mold 通过 C++20 重写、robin-hood hash、并行 I/O 和多线程显著加速链接,中大型项目可从 12s 降至 1.8s,但仅支持 Linux/FreeBSD,需在 CMake 中显式配置 -fuse-ld=mold 并验证生效。

为什么用 mold 替换 ld 或 lld 能明显提速
链接阶段慢,往往不是编译器的问题,而是传统链接器(ld.bfd)在符号解析、重定位、段合并时做大量重复扫描和哈希查找。mold 用 C++20 重写,内存布局更紧凑,符号表用 robin-hood hash,支持并行 I/O 和多线程处理,实测中大型 C++ 项目(如含 500+ 目标文件的构建)链接耗时可从 12s 降到 1.8s 左右。但它不兼容所有 GNU ld 特性,比如部分 --wrap 行为或某些 .so 版本脚本语法。
如何让 CMake 项目真正用上 mold
CMake 默认不会自动选 mold,即使它已安装在 PATH。必须显式指定链接器路径,并确保 C++ 链接器和 C 链接器一致(否则混合链接会失败):
- 在
CMakeLists.txt最顶部加:set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=mold" CACHE STRING "") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=mold" CACHE STRING "") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fuse-ld=mold" CACHE STRING "") - 或者更稳妥的方式:在命令行传入(避免污染缓存):
cmake -DCMAKE_CXX_FLAGS="-fuse-ld=mold" -DCMAKE_C_FLAGS="-fuse-ld=mold" ..
- 验证是否生效:编译后运行
readelf -l your_binary | grep interpreter,输出里应含/lib64/ld-mold.so.1(Linux x86_64);若仍见ld-linux-x86-64.so.2,说明没生效
mold 在 macOS 和 Windows 上能用吗
不能。mold 当前只支持 Linux(x86-64、aarch64、riscv64)和 FreeBSD。macOS 的默认链接器是 ld64(LLVM 系),Windows 是 link.exe 或 lld-link,二者都不支持 -fuse-ld=mold。尝试在非 Linux 平台硬配会导致 clang: error: invalid linker name in argument '-fuse-ld=mold'。CI 流水线若跨平台,需加条件判断,例如在 GitHub Actions 中只对 ubuntu-latest 环境启用该 flag。
哪些 C++ 项目配置会让 mold 失效或报错
mold 对链接脚本、弱符号、版本控制等处理比 ld.bfd 更严格,以下情况容易出问题:
- 使用自定义
.lds链接脚本:若含INSERT AFTER、SECTIONS { *(.init) }这类模糊通配,mold可能报undefined symbol: _start或段顺序错误;建议改用mold --print-script输出默认脚本再微调 - 启用了
-Wl,--no-as-needed但依赖库未显式列出:mold默认更激进地裁剪未引用的库,漏写target_link_libraries(...)会导致链接失败而非静默忽略 - 使用了 GCC 的
-fsanitize=address:需确保libasan是 mold 编译的版本(通常系统自带的没问题),否则可能报cannot find -lasan;可用mold --help | grep asan查看是否内置支持
真正卡住的点往往是链接器标志传递链断裂——比如父项目的 CMAKE_EXE_LINKER_FLAGS 没 propagate 到子目录,或 Ninja 缓存了旧的 linker 参数。遇到“明明配了却还是用 ld.bfd”,第一反应不是重装 mold,而是检查 compile_commands.json 里实际生成的链接命令行有没有 -fuse-ld=mold。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











