Linux ARM跑macOS应用:166票热榜的Rust翻译层项目
一个名叫 Kakehashi 的项目悄悄冲上了 Hacker News 热榜第三,166 票,34 条评论。它的定位很直接:在 Linux ARM64 上运行 macOS 二进制文件。
wie-project/kakehashi: Userspace macOS translation layer for Linux ARM64,Rust 编写,已获 162 星。
Kakehashi 项目示意:Linux 与 macOS 之间的翻译层
这事有点意思。在 Linux 上跑 macOS 程序不是什么新鲜想法,Darling 项目干了十几年,但目标一直是 x86_64。把这条路平移到 ARM64 上,技术难度完全不是一个量级。
怎么做到
核心思路和 Wine 类似:不模拟硬件,不跑虚拟机,直接在用户态翻译系统调用。
macOS 和 Linux 的 syscall 编号完全不同。macOS 用的是 XNU 内核的 syscall 表,Linux 用的是自己的。Kakehashi 做的事情是在中间加一层翻译层。macOS 二进制文件发出 mach_port 请求,Kakehashi 拦截后翻译成对应的 Linux 系统调用,再把结果包装回 macOS ABI 格式返回给程序。
这里面最难的是 Mach-O 二进制格式处理。
Mach-O 二进制格式解析示意
macOS 的可执行文件结构和 ELF 不一样,动态链接方式也不一样。Kakehashi 需要自己实现一个 Mach-O loader,处理 dyld 的行为,搞定 rebase 和 bind 操作。这些在 x86 上已经有 Darling 踩过的坑,但 ARM64 上几乎是空白。
项目还用了 hypercall 机制来处理那些 Linux 没有直接等价物的 macOS 特性。hypercall 原本虚拟机里的概念,这里被借用来做用户态的功能桥接。当 macOS 程序调用了 Linux 不存在的 API 时,Kakehashi 提供一个模拟实现,而不是直接崩溃。
为什么是现在?
Apple Silicon 出货量已经非常大了。大量开发者手里有 M 系列芯片的 Mac,同时也有 ARM Linux 服务器或开发板(树莓派、NVIDIA Jetson 等)。两边都是 ARM64 架构,指令集兼容,但系统调用和 ABI 完全不同。
理论上,架构相同意味着翻译层只需要处理系统调用差异,不需要做指令集翻译(Rosetta 2 那种复杂度的工作)。这大大降低了可行性。Kakehashi 选在这个时间点出现,正是利用了 ARM64 生态两边都在成熟这个窗口期。
说句实在话,这个项目离能跑日常应用还差得远。它目前还是 experimental 阶段,大概率只能跑一些简单的命令行工具。但这和 2000 年代初的 Wine 一样,一开始只能跑记事本,十几年后能跑 Photoshop。
有三点值得关注。
Rust 内存安全示意
Rust 实现是关键。内存安全在这个场景下不是锦上添花,是必需品。翻译层直接处理二进制文件的内存布局,用 C 写的话一个指针偏移错误就是 segfault。Rust 的 borrow checker 在这里是实打实的安全网。
syscall translation 是项目的核心工作量。macOS 有 700+ 个 syscall,每个都需要找到 Linux 的对应实现或者提供 stub。
与 Darling 的关系也需要说清楚。项目文档提到了 Darling,但这是独立实现,不是 Darling 的 ARM 移植。两者架构思路相似,但代码库完全不同。
这个项目能不能成,取决于社区贡献者的数量。系统调用翻译是体力活,一个两个开发者搞不定全部 700+ 个 syscall。但如果能像 Wine 那样建立起成熟的贡献者生态,十年后回头看今天,可能就是 ARM 桌面生态融合的开始。
GitHub: wie-project/kakehashi