2026 年 10 月 5 日,由开源编译器专家 Rui Ueyama 主导的高速链接器项目正式发布 Mold 3.0.0。与常规迭代不同,这一大版本彻底终结了 C++ 时代,此前发布的 2.42.1 成为 C++ 分支的绝唱。Mold 3.0.0 并非渐进式修补,而是完全由 Rust 重新实现,同时保持了与旧版一致的命令行参数、目标架构和链接速度,并通过构建 Gentoo 全量软件包完成了零性能倒退的验证。

这场激进重写直指一个明确目标:消弭与 GNU ld 之间最后的兼容缺口,争取在主流 Linux 发行版中取代陈旧的默认链接器。然而,工具链从 C++ 倒向 Rust 在换取内存安全的同时,也触发了基础软件领域致命的自举悖论。当编译器的构建依赖链接器,而链接器本身又强制依赖高版本 Rust 时,这柄为极速而生的手术刀,正陷入系统底座最深层次的依赖泥潭。

性能断层:从本地加速外挂到系统底座的野心

在现代软件工程中,链接器始终是大型代码仓库构建时最漫长的等待点。GNU ld (bfd) 积累了数十年历史包袱,单线程瓶颈显著;曾经被寄予厚望的 GNU gold 性能有限,且在 GNU Binutils 2.44 中已被正式移出常规源码包并标记废弃,Fedora 也正同步弃用 binutils-gold;LLVM 的 lld 虽已成为主流,但在超大规模核心项目的并行扩展上依然存在天花板。

测试多核并发性能所依托的高性能工作站硬件平台
测试多核并发性能所依托的高性能工作站硬件平台

Mold 最初正是凭借极度并发的数据结构和预分配内存布局杀出重围。升级到 3.0.0 后,这种压倒性的性能优势没有发生任何缩水。测试数据显示,在 AMD Threadripper 7980X 平台的 Release 构建中,面对 TensorFlow 链接,lld 耗时 9.62 秒,而 Mold 仅需 0.70 秒;在 Chromium 上,Mold 将耗时从 lld 的 6.48 秒压缩至 0.64 秒,Blender 耗时则从 0.85 秒缩短至 0.20 秒。即便利器换为 Apple M1 Ultra,Mold 处理 TensorFlow 也仅耗时 0.68 秒,相比 lld 的 8.07 秒同样拉开了近 12 倍差距。

大型项目链接耗时对比(64 核工作站测试) Chromium Debug 构建 lld 16.64s Mold 1.65s (快 10 倍) Firefox Debug 构建 lld 5.11s Mold 0.78s (快 6.5 倍) Clang 19 构建 GNU ld 42.07s Mold 1.35s (提速 31 倍) 注:16核与64核测试环境包含实测 Debug 产物生成,极限负载下学术实测加速最高达 112 倍。

在包含庞大符号表的 16 核调试场景中,这种裂缝进一步被撕开。链接 MySQL 8.3 时,GNU ld 耗时 10.84 秒,gold 需 7.47 秒,lld 为 1.64 秒,而 Mold 仅需 0.46 秒;链接 Clang 19 时,GNU ld 耗费了冗长的 42.07 秒,Mold 却在 1.35 秒内完成了交付。在多核满载极限下,Mold 比实验性链接器 wild 还要快 2.3 到 5.0 倍,针对特定极值负载相比 GNU ld 的理论加速甚至达到 112 倍。

然而,此前 Mold 在开发者眼中只是一张“本地特快通行证”。开发者在本地编译 Chromium 或大型 Rust 服务时,手动在配置中注入链接参数以节省等待时间。3.0.0 的野心是走出工作站,补齐对 GNU ld 链接脚本的兼容死角,彻底坐上发行版系统中默认链接器那把交椅。

性能让 Mold 赢得了开发者的终端,但决定它能否接管系统的,是那些数十年未曾变动的古老契约。

安全神话背后:当段错误变成了拒绝服务

官方公告中,改写为 Rust 的最大收益之一被描述为防范恶意损坏的文件。在 C++ 版本中,解析格式损坏的输入文件可能诱发越界内存读取,进而以段错误崩溃退出;而在 Mold 3.0.0 中,所有潜在读取都被内置的边界检查覆盖,遇到非法访问将触发受控的 Rust panic。

内存安全工具难以直接排查二进制机器码地址错位(示意图)
内存安全工具难以直接排查二进制机器码地址错位(示意图)

这一逻辑在工程上确实堵住了未定义行为的利用可能,但并未实质改变链接器的业务处境。链接器并非驻留后台持续解析不可信流量的微服务,而是一个短期执行的命令行工具。无论是段错误退出还是触发 panic 终止,对构建系统而言产生的结果没有任何区别:编译流水线立刻失败中断。

更关键的是,Rust 编译器保证的内存安全,丝毫不能防范二进制语义错误。3.0.0 版本记录里修补的大量缺陷,恰恰是 Rust 无法自发解决的 ELF 规范盲区:

  • 处理不同尺寸的重名公共符号时,如何与 GNU ld 保持一致分配最大尺寸;
  • 修复 --icf=safe 误折叠动态库导出函数的严重逻辑漏洞;
  • 纠正 AArch64、ARM32 与 RISC-V 上特定重定位类型的计算偏差。

这些隐蔽的机器码地址错位与指令破坏,从来不会在 C++ 或 Rust 的内存分配器上报错,却能直接导致最终产物在特定架构下静默崩溃。换言之,语言安全并未能直接抹平向 GNU ld 靠拢所需的脏活与长尾工程量。

自举死结与边缘架构的隐形断层

如果说安全语义的提升属于预期修正,那么构建依赖的剧烈变迁,则直接在 Linux 核心维护团队面前立起了一道高墙。

缺乏旧架构支持导致边缘硬件平台遭遇编译失败
缺乏旧架构支持导致边缘硬件平台遭遇编译失败

从 3.0.0 起,项目彻底废弃了通用的 CMake,全面转向 Cargo 构建,移除了对 Intel oneTBB 的依赖并静态链接 mimalloc 3.5.3,且强制要求环境具备 Rust 1.95 或更高版本以及 C 编译器。这一改动立刻遭到了系统底层维护者的严厉质疑。

底层工具链的「自举死结」逻辑演进 1. 初始编译链 冷启动构建 Rust 编译器 必须先有一个链接器 2. Mold 3.0 限制 编译 Mold 3.0 强制依赖 Rust 1.95+ 3. 自举闭环断裂 没有 Rust 无法编 Mold 没有链接器无法编 Rust 代价:操作系统无法通过最小依赖树从零构建自身,冷启动依赖树陷入死循环。

在极简系统构建社区(如 Stage0 项目)看来,这是一个经典的自举悖论。构建 Rust 编译器本身必须依赖链接器,但如果系统唯一的默认链接器 Mold 又需要高版本的 Rust 才能编译,整个操作系统的冷启动依赖链条就彻底断裂了。以往 C++ 编写的 GNU ld 或老版本 Mold 可以跟随极度精简的 C/C++ 编译器率先诞生,为后续所有大型环境铺路;而 Rust 3.0 的这一飞跃,在事实上关闭了它成为底层通用自举基石的大门。

雪上加霜的是硬件支持的断层。C++ 的跨平台移植性经历了几十年的磨合,而 Rust 生态对非主流架构的 Tier 2、Tier 3 支持仍显薄弱。重写上线后,ArchPOWER 维护者立刻指出 PPC64 大端序 ELFv2 暂不受支持,且新版由于在底层直接使用了 64 位原子操作,初期甚至在 32 位 PowerPC 架构上遭遇了编译失败。

对致力于服务全硬件生态的通用 Linux 发行版而言,这些架构的倒退是致命的。主流发行版之所以至今保持克制,原因正在于此:

  • Debian、Ubuntu、Fedora 和 Arch 的标准 GCC 工具链,系统全局默认链接器至今全量锚定在 GNU ld.bfd 上。
  • Arch 用户如果想体验速度,维基文档至今仍要求开发者手动追加 LDFLAGS=-fuse-ld=mold。
  • 尽管 Fedora 已经为 Fedora 43 至 45 及 Rawhide 打包了 Mold,但没有任何计划将其升格为替换系统底座的默认选项。
  • 风险.如果基础软件无法跨越复杂内核驱动、古怪引导装载程序(Bootloader)以及非标准链接脚本的隐式契约,性能倍数再高,也只能停留在开发机而非生产环境底座。

现实重心的迁移:换不换,如何选

跳出工具链的自洽逻辑,摆在工程师面前的现实选择变得十分清晰。

不同开发阵营在极速管道与稳定基座间分道扬镳(示意图)
不同开发阵营在极速管道与稳定基座间分道扬镳(示意图)

对于日常陷在本地 C++ 或大型 Rust 应用全量编译中的团队而言,Mold 3.0.0 依旧是目前最具性价比的降耗利器。它保持了 2.42.1 的同等极速,并在指令重定位的边界修复上更为完善。将开发环境的全局链接器指向 Mold,能够直接砍掉调试闭环中超过 70% 的等待时间。

  • 建议.应用层与业务研发团队可无缝切入 Mold 3.0.0 获取构建加速;但底层固件研发、跨架构编译集群或定制 Linux 根文件系统的团队,应继续坚守 GNU ld 或在过渡期保留 2.42.1 分支,避开高版本 Rust 的依赖牵连。

Mold 3.0.0 是个人技术英雄主义在系统工程领域的又一次胜利,Rui Ueyama 证明了彻底的语言重构不仅能抹平性能损耗,还能收拢边界缺陷。然而,当它试图迈进系统核心层、改写 /usr/bin/ld 的归属时,它所对抗的不再是旧工具缓慢的代码实现,而是整整一个时代写在 Linux 骨架里的依赖秩序与自举现实。