Rust编译产物吃硬盘:官方今天收官,你的target目录有救了

源自4位全网作者

07:30

先问一个扎心的问题:你机器上的 target 目录,现在多大?

别猜,打开终端敲一句 `du -sh target`。有些人看到结果会沉默——2024年3月,Reddit r/rust 上有过一个名帖:一位工程师的 1TB 硬盘提示"空间不足",罪魁祸首不是电影不是游戏,光一个项目的 target 目录就占了 165GB,全盘编译产物加起来将近 500GB。知乎

Rust编译产物吃硬盘:官方今天收官,你的target目录有救了

帖子底下瞬间变成比惨大会。有人说自己三个项目的 target 加起来超过 100GB,有人说"我的磁盘被 Rust 吃光了"。今年6月又有人晒出 75GB 的 workspace,评论区继续比惨。而就在今天的知乎相关讨论里,还有更狠的:有用户说自己一个科学计算项目的 target 巅峰到过 295GB,一个 web 项目到过 201GB,不得不上 NVMe 存储矩阵,编译慢就不得不上 DDR5 内存盘。知乎

Rust编译产物吃硬盘:官方今天收官,你的target目录有救了

你看,为了编译 Rust,有人已经买到磁盘阵列了。这已经不是编程问题,是消费决策问题。

官方其实早就承认了这件事:2025 年 Rust 官方编译器性能调查里,target 目录体积被列为开发者第三大痛点,仅次于编译慢和调试体验差,甚至有 CI 用户干脆不做缓存——因为 target 目录太大,装不进 CI 平台的缓存限额。知乎

而今天(8月18日),发生了一件值得记下来的事:经过半年公开测试、中间还翻过一次车,Cargo 的构建目录新布局(build-dir v2)正式重新稳定,追踪 issue 收官关闭。官方对 Rust 吃硬盘这件事动刀,终于从画饼走到了交作业。

先搞清楚:target 凭什么这么大

不是你代码多,是三个结构性问题叠出来的。

第一,元数据存了两份。为了让编译更快,Rust 用了"流水线"技术:编译库 A 时先把元数据单独写成 .rmeta 文件,这样依赖 A 的库 B 不用等 A 编完就能开工。代价是编译完成后,A 的元数据在 .rmeta 里有一份,又完整内嵌在 .rlib 里一份。知乎有人分析过那个 165GB 的硬盘,约 70% 的空间是各类 crate 的元数据,而且大多存了两遍。

第二,项目之间互不共享。Cargo 默认给每个项目单独建 target,十个项目都依赖 serde,serde 就被老老实实编译十遍、存十份。2018 年就有人提 issue 求一个用户级共享缓存,八年过去,这个需求今年才真正开始动。

第三,旧产物从不清理。升级工具链后,旧版本产物全部失效,但 Cargo 不删,只在旁边默默堆新的。更讽刺的是:target 里堆几十万个文件后,增量编译反而会变慢,最严重的情况慢 6 倍——空间问题反噬了速度。

编译器团队核心成员 Kobzol 去年做过一个实验:拿他自己的开源项目 hyperqueue,同一版本编译器,只是把调试信息和增量编译这两项打开,target 体积就膨胀到约 3 倍。知乎社区那句经典吐槽总结得很到位:“你基本上是在用磁盘空间换编译性能。我的时间比闲置的 SSD 值钱多了。”

Rust编译产物吃硬盘:官方今天收官,你的target目录有救了

官方这两年动了什么:四条线同时推进

把 2024 到 2026 年 Cargo 团队和编译器团队的动作连起来,其实是四条线在并行。

第一条线:给缓存装"保质期"(Cargo GC)。Cargo 1.78 开始记录缓存文件的最后使用时间,1.88(2025年6月)自动清理正式生效:下载的缓存超过 3 个月没用就删,本地生成的文件超过 1 个月没用就删。注意,目前清理的是 ~/.cargo 下的全局缓存,项目的 target 暂不在此列。知乎但方向已经定了。

第二条线:消灭重复的元数据。去年6月 Kobzol 落地了 -Zembed-metadata=no:既然元数据已有独立的 .rmeta 那份,.rlib 里就只留存根。实测发布模式 target 从 397MB 降到 253MB,省 36%;开发模式省 27%;连标准库的动态库都从 13MB 缩到 3MB。知乎目前还是 nightly 试验开关,官方计划把"不再内嵌元数据"变成默认行为。

第三条线:重构 target 目录本身,就是今天收官的 build-dir v2。分两步走:先把"最终产物目录"(target-dir)和"中间产物目录"(build-dir)分开,从 Cargo 1.91 起用户可以分别指定;再由核心开发者 ranger-ross 把 build-dir 内部布局重做——从"按文件类型堆放"改成"按包名+哈希分房间",每个 crate 的产物自包含。

为什么非要大动干戈?因为只有产物自包含,才可能做跨项目共享缓存和自动垃圾清理——"每个项目各占一份硬盘"的根治方案就在这里。4月官方测试公告里还列了几条附带收益:文件锁粒度更细,cargo build 和 rust-analyzer 不用再互相等待同一把锁;顺手修掉了 Windows 上 PATH 污染和中间产物文件名冲突。知乎

这条路走得并不顺:7月初,最大的 Rust 工作区之一 Zed 用新布局编译直接失败,官方紧急回滚;修完性能问题 7 月底重回 nightly;8月18日正式重新稳定,issue 关闭。知乎

第四条线:少编译一点。空间和速度是同一枚硬币的两面,今年编译器侧的大事也在密集落地,Polonius Alpha 8月初刚上 nightly,并行前端持续推进。用一直跟进此事的博主的话说,过去几年画的大饼,今年开始密集兑现。知乎

Rust编译产物吃硬盘:官方今天收官,你的target目录有救了

那你现在该做什么

先别急着下单 SSD,分情况来。

第一步都一样:`du -sh target`,再看一眼 ~/.cargo。很多人的焦虑来自"感觉越来越大",先把焦虑变成具体数字。

如果你是个人开发、项目不多:老三样还是最好用的——cargo sweep 定期清理久未使用的产物、调试信息调低一档、升级工具链后做一次 cargo clean 仪式。这三招能把大部分水分挤掉。

如果你同时维护多个相关项目:社区老手早年的土办法依然有效——在 ~/.cargo/config.toml 里配置全局 build.target-dir,让所有项目把编译产物扔进同一个池子,先吃到跨项目依赖复用的红利。知乎池子还是会变大,但比每个项目各存一份强得多。

如果你用 CI:target 照常做成缓存,但上传前先 cargo sweep 瘦身,否则缓存上传和恢复的时间会吃掉你省下的编译时间。

如果你在 nightly 上干活:新布局现在就可以试。你的 CI 脚本或测试辅助库如果依赖 target 内部路径,建议先完整跑一遍——Zed 翻车就是前车之鉴,有问题可以先回退,风险可控。

至于"干脆买块大盘一劳永逸"的想法,建议先看一眼 #16147 提案:官方已经在讨论把 build-dir 挪进 ~/.cargo 的全局缓存区,真落地那天,十个项目共享一份编译产物。知乎用跟踪帖的话说,这一步已经从"会不会做"变成了"什么时候做"。硬盘没到爆炸的话,等它落地,比现在下单 2TB 划算得多。

接下来值得盯的三个信号

一是新布局在未来几个版本里进入稳定工具链的节奏;二是 -Zembed-metadata=no 什么时候从 nightly 开关变成默认行为;三是 #16147 全局共享 build-dir 从提案变成实现。前两个落地后,社区里的"几百GB比惨"应该会明显降温。

最后一句总结:Rust 的硬盘问题,本质是"用空间换时间"欠了很多年的账,官方今年开始系统性还账。在账还清之前,先测量、再清理、最后才谈买盘——这个顺序,能省真钱。

你的 target 目录多大?欢迎评论区晒惨。

内容由AI生成
0
扫一下,分享更方便,购买更轻松
0评论

当前文章无评论,是时候发表评论了
提示信息

取消
确认
评论举报

最新文章 热门文章