一个Rust编译器,用GCC加make就能编译出来——这不是玩笑,是开发者FractalFir刚放出来的东西。他把rustc 1.98.0-nightly整个翻译成了大约4600万行C代码,编译完还能拿这个C版rustc去构建core、alloc、std这些标准库。项目叫crustc,放在GitHub上。
第一次看到这个数字容易觉得离谱,但离谱之处恰恰是重点:这不是重写了一个Rust编译器,而是把现成rustc的产物整体"翻译"成了另一种语言。翻译的工具叫cilly,crustc只是它秀肌肉用的demo。
cilly做了什么
Rust依赖LLVM生成机器码,这也是它常年被诟病"平台支持不如C"的根源——LLVM不支持的老旧或小众硬件,Rust基本上上不去。cilly的思路是反过来用C的普适性:C编译器能跑的地方,理论上就能跑Rust。
具体做法有几个巧思。生成代码前,cilly会先塞一段"探针"程序去试探目标C编译器支持什么特性,比如线程局部变量、特定类型宽度,支持就用,不支持就走兜底方案,几乎不对"现代C"做任何假设,连整数用补码表示这种事都要显式断言。另外它支持网络透明编译——本地机器跑rustc,通过TCP把生成的C代码发给目标平台上的小型编译服务器,作者说已经用这套方式给Plan 9系统编译过程序。
这套机制换来的代价也很直白:生成的C代码是平台绑定的。给ARM64生成的C code,不能直接拿去跑在RISC-V上,每个目标都要单独生成一份。
作者自己划的边界
最值得记下来的一句话,是作者自己说的:这是"我能做的最炫的展示"。不是"可用的工具",是展示。
原文里藏着一处技术硬伤:ARM64平台上,rustc选择的结构体返回ABI没法用标准C完整表达。多数平台上,返回值指针和第一个参数共用寄存器,C编译器能配合;但ARM64的返回指针走独立寄存器,C编译器对小结构体不会主动做这种优化,cilly只能说自己的输出"mostly"兼容,而不是完全兼容。
- 风险.crustc目前只验证了"编译自己"这一件事——检索不到它编译真实第三方crate或在真正冷门硬件上落地的独立案例,4600万行代码的可维护性、随rustc版本迭代的更新成本,也都还是空白。
这不是第一次有人想绕开LLVM
Rust转C、找LLVM/GCC替代路径的尝试,cilly不是第一个,也大概率不是最后一个。
mrustc走的是简化自举路线,目标是用一套精简实现把rustc本身编译出来,社区更看重的是它对信任链和自举安全的价值。gccrs则是在GCC框架里重写一个Rust前端,直接拿到GCC支持的全部目标平台,Hacker News和LWN过去的讨论里,争议焦点一直落在同一个问题上:能不能跟上Rust语言本身的演进速度。语言在往前走,替代实现路线要一直追。
crustc走的是第三条路——不重写编译器,直接把rustc的产出转译一遍。三条路径分工不同,但要过的坎是一样的:能不能长期跟得上、能不能经得起真实场景检验。
FractalFir说这是他三年里的第14次尝试,前一次公开亮相是rustc_codegen_clr。这个数字本身就说明问题:这条路没有捷径,失败是常态,能跑通一次自举已经是运气和积累叠加的结果。
《左传》讲"其兴也勃焉,其亡也忽焉",用在开源实验项目上或许重了,但这类"替代编译器"叙事历史上确实反复上演过同一幕:demo惊艳,叫好声一片,然后消失在"跟不上上游更新"的疲惫里。mrustc和gccrs都还在,但都花了远超一个demo的时间去追赶主线Rust的演进节奏。
crustc目前证明的,只是"这条路理论上走得通"。它能不能真正解决"Rust在冷门硬件上没戏"这个具体问题,得看cilly什么时候开源、有没有人拿真实的no_std嵌入式项目去跑一遍、遇到ARM64那种ABI坑之后代码还能不能正确运行。这些问题,现在都没有答案。
