rui314/mold

GitHub: rui314/mold

mold 是一个使用 C++20 编写的现代链接器,通过并行化与算法优化解决大型项目链接缓慢的问题。

Stars: 16405 | Forks: 534

# mold:现代链接器 mold 是现有 Unix 链接器的更快即插即用替代品。它比 LLVM lld 链接器快数倍,LLVM lld 是第二快的开源链接器, 这是我几年前开发的。mold 通过最小化构建时间来提升开发者 生产力,特别是在快速调试-编辑-重建循环中。 以下是 GNU ld、GNU gold、LLVM lld 和 mold 在模拟 16 核、32 线程机器上链接主要大型程序的最终调试信息可执行文件时的性能对比。 ![链接速度对比](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/75a0754794222015.svg) | 程序(链接输出大小) | GNU ld | GNU gold | LLVM lld | mold |----------------------------|--------|----------|----------|------ | MySQL 8.3(0.47 GiB) | 10.84s | 7.47s | 1.64s | 0.46s | Clang 19(1.56 GiB) | 42.07s | 33.13s | 5.20s | 1.35s | Chromium 124(1.35 GiB) | N/A | 27.40s | 6.10s | 1.52s mold 速度极快,仅比同一机器上的 `cp` 命令慢 2 倍。如果你发现 mold 不比其他链接器更快,请随意 [提交错误报告](https://github.com/rui314/mold/issues)。 mold 支持 x86-64、i386、ARM64、ARM32、64 位/32 位小/大端 RISC-V、32 位 PowerPC、64 位大端 PowerPC ELFv1、64 位小端 PowerPC ELFv2、s390x、64 位/32 位 LoongArch、SPARC64、m68k 和 SH-4。 ## 为什么链接速度很重要? 如果你使用的是 C、C++ 或 Rust 等编译型语言,构建过程 分为两个阶段。在第一阶段,编译器将源文件编译为 目标文件(`.o` 文件)。在第二阶段,链接器将所有目标 文件合并为一个可执行文件或共享库文件。 如果构建输出较大,第二阶段可能会耗时较长。mold 可以 加快这一过程,节省你的时间,并避免在等待长时间构建完成时的分心。 这种差异在快速调试-编辑-重建循环中最为明显。 ## 安装 以下系统的二进制包目前可用: [![Packaging status](https://repology.org/badge/vertical-allrepos/mold.svg)](https://repology.org/project/mold/versions) ## 如何构建 mold 使用 C++20 编写,因此如果你自行构建 mold, 需要一个较新版本的 C++ 编译器和 C++ 标准库。 我们推荐使用 GCC 10.2 或 Clang 16.0.0(或更高版本)以及 libstdc++ 10 或 libc++ 7(或更高版本)。 ### 安装依赖项 要安装构建依赖项,请在此目录中运行 `./install-build-deps.sh`。 它会检测你的 Linux 发行版并尝试安装必要的软件包。 你可能需要以 root 权限运行它。 ### 编译 mold ``` git clone --branch stable https://github.com/rui314/mold.git cd mold ./install-build-deps.sh cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=c++ -B build cmake --build build -j$(nproc) sudo cmake --build build --target install ``` 你可能需要向 `cmake` 传递 C++20 编译器命令名。在 上面的示例中,传递的是 `c++`。如果这对你不起作用,请尝试使用特定 版本的编译器,例如 `g++-10` 或 `clang++-12`。 默认情况下,`mold` 会安装到 `/usr/local/bin`。你可以通过传递 `-DCMAKE_INSTALL_PREFIX=<目录>` 来更改安装位置。 有关其他 cmake 选项,请参见 `CMakeLists.txt` 中的注释。 如果你使用的 Linux 发行版不够新,或者 `cmake` 无法正常工作, 你可以使用 Podman 在容器中构建 mold。为此,请在此目录中运行 `./dist.sh`。 该 shell 脚本将拉取容器镜像,在容器内构建 mold 和辅助文件, 并将其打包为一个名为 `dist/mold-$version-$arch-linux.tar.gz` 的 tar 文件。 你可以解压该 tar 文件到任意位置,并使用其中的 mold 可执行文件。 ## 如何使用
使用 mold 的经典方式 在 Unix 上,链接器命令(通常是 `/usr/bin/ld`)会间接被 编译器驱动程序(通常是 `cc`、`gcc` 或 `clang`)调用, 而编译器驱动程序又被 `make` 或其他构建系统命令间接调用。 如果你可以通过修改构建系统的配置文件来为编译器驱动程序 指定额外的命令行选项,请添加以下标志之一以使用 mold 替代 `/usr/bin/ld`: - 对于 Clang:传递 `-fuse-ld=mold` - 对于 GCC 12.1.0 或更高版本:传递 `-fuse-ld=mold` - 对于 12.1.0 之前的 GCC:`-fuse-ld` 选项不接受 `mold` 作为有效参数, 因此你需要改用 `-B` 选项。该选项告诉 GCC 在何处查找外部命令(如 `ld`)。 如果你已使用 `make install` 安装 mold,应存在一个名为 `/usr/libexec/mold`(或 `/usr/local/libexec/mold`,取决于你的 `$PREFIX`)的目录,其中包含 `ld` 命令。实际上,`ld` 是一个 指向 `mold` 的符号链接。因此,你只需要传递 `-B/usr/libexec/mold`(或 `-B/usr/local/libexec/mold`)给 GCC。 如果你尚未将 `ld.mold` 安装到任何 `$PATH`,你仍然可以传递 `-fuse-ld=/absolute/path/to/mold` 给 clang 来使用 mold。 但 GCC 不接受绝对路径作为 `-fuse-ld` 的参数。
如果你使用 Rust 在项目目录中创建 `.cargo/config.toml`,内容如下: ``` [target.'cfg(target_os = "linux")'] linker = "clang" rustflags = ["-C", "link-arg=-fuse-ld=/path/to/mold"] ``` 其中 `/path/to/mold` 是 mold 可执行文件的绝对路径。 在上面的示例中,我们使用 `clang` 作为链接器驱动程序,因为它始终接受 `-fuse-ld` 选项。如果你的 GCC 足够新以识别该选项, 你可以移除 `linker = "clang"` 这一行。 ``` [target.'cfg(target_os = "linux")'] rustflags = ["-C", "link-arg=-fuse-ld=mold"] ``` 如果你希望对所有项目使用 mold,请将上述片段添加到 `~/.cargo/config.toml`。
如果你使用 Nim 在项目目录中创建 `config.nims`,内容如下: ``` when findExe("mold").len > 0 and defined(linux): switch("passL", "-fuse-ld=mold") ``` 其中 `mold` 必须包含在 `PATH` 环境变量中。在此示例中, 使用 `gcc` 作为链接器驱动程序。如果你的 GCC 足够新以识别 `-fuse-ld` 选项,请使用该选项。 如果你希望对所有项目使用 mold,请将上述片段添加到 `~/.config/config.nims`。
如果你使用 Conan 包管理器 你可以通过 [Conan](https://github.com/conan-io) 配置来下载最新 版本的 `mold` 并在构建依赖项和项目时将其用作链接器。 请参阅[此处](https://conan.io/center/recipes/mold)的说明。
mold -run 有时很难为 `cc` 传递适当的命令行选项来指定替代链接器。 为此,mold 提供了拦截所有对 `ld`、`ld.bfd`、`ld.lld` 或 `ld.gold` 的调用并将其重定向到自身的功能。要使用此功能,请以子命令形式运行 `make`(或其他构建命令)如下: ``` mold -run make ``` 内部地,mold 会使用 `LD_PRELOAD` 环境变量调用给定命令, 并将其配套共享对象文件设置为该环境变量。该共享对象文件会拦截 所有对 `exec(3)` 系列函数的调用,如果 `argv[0]` 是 `ld`、`ld.bfd`、 `ld.gold` 或 `ld.lld`,则将其替换为 `mold`。
GitHub Actions 你可以使用我们的 [setup-mold](https://github.com/rui314/setup-mold) GitHub 操作来加速基于 GitHub 的持续构建。虽然 GitHub Actions 运行在 4 核机器上,但 mold 仍然比默认的 GNU 链接器快得多, 尤其是在链接大型程序时。
验证你正在使用 mold mold 会在输出文件的 `.comment` 段中留下其标识字符串。 你可以通过打印该段来验证你是否确实在使用 mold。 ``` $ readelf -p .comment String dump of section '.comment': [ 0] GCC: (Ubuntu 10.2.0-5ubuntu1~20.04) 10.2.0 [ 2b] mold 9a1679b47d9b22012ec7dfbda97c8983956716f7 ``` 如果 `.comment` 段中包含 `mold`,则该文件是由 mold 创建的。
在线手册 由于 mold 是即插即用替代方案,你应该可以不阅读手册直接使用它。 不过,如果需要,[mold 的手册页](docs/mold.md) 可在线获取。你也可以通过运行 `man mold` 来阅读手册。
## 为什么 mold 如此快速? 原因之一是它使用了比其它链接器更快的算法和更高效的数据结构。 另一个原因是 mold 高度并行化。 以下是 lld(左侧)和 mold(右侧)在链接同一程序(Chromium 可执行文件)时 每个核心的 CPU 使用率对比图。 ![CPU 使用率对比动画](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/8b29d47cd5222017.gif) 你可以看到 mold 在整个执行过程中使用了所有可用核心并快速完成。 相比之下,lld 大部分时间未能充分利用可用核心。在此演示中,最大并行度被 人为限制为 16,以便柱状图适合 GIF。 更多细节请参见[设计说明](docs/design.md)。 ### 个人赞助者 - [Wei Wu](https://github.com/lazyparser) - [kyle-elliott](https://github.com/kyle-elliott) - [Bryant Biggs](https://github.com/bryantbiggs) - [kraptor23](https://github.com/kraptor23) - [Jinkyu Yi](https://github.com/jincreator) - [Pedro Navarro](https://github.com/pedronavf)
标签:ARM64, benchmark, C/C++, debug-edit-rebuild, drop-in replacement, GNU ld, gold, Hakrawler, JA3, lld, LLVM, LoongArch, PowerPC, RISC-V, Rust, S390x, SOC Prime, SPARC64, Unix, x86-64, 事务性I/O, 可视化界面, 多架构支持, 开发工具, 开源, 快速迭代, 性能对比, 数字足迹, 构建加速, 编译优化, 网络流量审计, 调试, 链接器