折腾了一阵 Rust + Cosmopolitan, 搭了套工具链,现在能把一些常用的 cli 工具编译到 APE 了

发布于

先解释一下,[jart/cosmopolitan](https://github.com/jart/cosmopolitan) 项目实现了一套 libc, 用了一些 trick 将 c 编译成在各个平台都能运行的单个二进制程序(真·一次编译到处运行)。ape(actually portable executable)指的就是这种格式。

其实很早之前就有人写了一个实验性质的项目尝试与 Rust 打通,但是遇到了很多问题。最主要的就是 Rust 标准库在编译期就写死了一些平台相关的 flag 常量,导致运行的时候其他系统识别不了就莫名崩掉或者行为不一致,而且后者这种最难查了。

我早期也探索过,办法是到处 patch 标准库和第三方库里的常量,一边读 std 一边读 cosmo 的实现一边 gdb ,勉强把同步网络那块调通就没精力了。这次有了 AI 的帮助,重新捡起来,加了一层 shim 把 Linux 语义翻译成宿主语义,虽然还是要 patch ,但不用再满世界改值了(结果越深入越发现 cosmo 少了很多东西,导致现在项目里写的适配 c 代码比 rust 代码都多了。。),异步那块也一起搞定了。

**项目在这里:** [starccy/rust-ape](https://github.com/starccy/rust-ape)

如果您有兴趣尝试的话:

**前置条件:**
一个 Linux 环境,用于编译;
Rust Nightly 工具链

**用在现成的项目:**

pin 住 Rust 版本(把本项目里的 rust-toolchain.toml cp 到 目标项目里),在 Cargo.toml 中我项目提供的 patch 段,然后 `cargo xtask build /path/to/project`。

目前我测试了 rg 、fd 、hyperfine 、eza, yazi 等一些常用的 cli ,都不需要特意去改 rs 代码就能编译出来。不过有网络请求的项目还是要改:得使用 rustls, 而且必须把证书打包进二进制。

不过这些还算能绕过,还有一些绕不过的,完整的内容可以阅读项目内 README

**用在新项目:**

直接 `cargo xtask generate /path/to/project` 生成新的项目,用 `cargo xtask build /path/to/project` 来编译。也可以试试直接编译 examples 下的代码,我都是当作测试来用的。

---

目前这个项目其实也是实验性的,我只修了自己撞到的问题,之外都是没探过的地方。现在还在摸它的上限在哪,有兴趣的可以拿 examples 里那些场景先试试,那是我目前能担保的范围。踩到新坑欢迎开 issue ,我也想知道还剩多少。

---

原文链接:[点击查看](https://www.v2ex.com/t/1233535)

评论

暂无评论。

0.055853s