Reed's News
← 返回精选

Kakehashi:在 Linux ARM 上运行 macOS 二进制的用户态翻译层

Tech 75 vlad_kalinkin 2026/8/2 788 字 原文 ↗

用户态macOS ARM64 → Linux aarch64 翻译层(优先支持命令行,无即时编译JIT)

可在Linux aarch64系统加载Darwin Mach-O文件,映射独立式libSystem库,转换BSD系统调用,运行真实客端程序(如Clang探针、7-Zip 7zzcurl、多线程程序)。

功能场景 支持环境
实时运行 Linux aarch64(裸机、虚拟机、Colima/Docker)
静态加载/程序检查 任意主机(含macOS)
设计文档参考 docs/目录

已在Docker/ColimaUTM(Linux aarch64)环境验证。一键安装:

cargo install kakehashi
# 或从源码编译安装:
cargo install --path crates/kh-cli --force
kh bottle ensure
kh install 7zip # 将Darwin版7zz安装至客端/usr/local/bin/7zz
kh install curl # 将Darwin版curl安装至客端/usr/local/bin/curl

相对路径-o或归档路径以kh进程的**主机当前工作目录(CWD)**为基准(需自行创建父目录,或依赖O_CREAT自动创建)。通过bottle机制,/Volumes/linux/…路径会映射至主机根目录(即客端/对应主机/)。

# 查看版本/帮助信息
kh run 7zz --
kh run 7zz -- --help
# 创建归档文件(相对当前目录)
kh run 7zz -- a demo.7z README.md
kh run 7zz -- t demo.7z
kh run 7zz -- l demo.7z
kh run 7zz -- x -o./out demo.7z
# 多线程压缩(正确性验证)
kh run 7zz -- a -t7z -m0=lzma2 -mx=5 -mmt=4 mt.7z README.md
kh run 7zz -- t mt.7z
# 预期结果:显示Everything is Ok,退出码0

Docker辅助脚本(输出文件存于主机.tmp/kh-out/目录):

./scripts/docker-7zz.sh --help
./scripts/docker-7zz.sh a /Volumes/linux/out/demo.7z /Volumes/linux/src/README.md
ls -lh .tmp/kh-out/demo.7z
KAKEHASHI_HYPERCALL=1 ./scripts/docker-7zz.sh a -t7z -m0=lzma2 -mx=5 -mmt=4 \
/Volumes/linux/out/mt.7z /Volumes/linux/src/README.md
./scripts/docker-7zz.sh t /Volumes/linux/out/mt.7z
# 查看版本标识(G1)
kh run curl -- --version
# HTTP GET请求并保存至文件(G3/G5),-o指定路径的父目录不存在时会自动创建
kh run curl -- -sS -o .tmp/kh-out/body http://example.com/
# 预期结果:退出码0,文件大小约559字节,HTML内容包含"Example Domain"
wc -c .tmp/kh-out/body
head -c 80 .tmp/kh-out/body; echo
# HTTP请求结果输出至标准输出
kh run curl -- -sS http://example.com/ | head -c 80; echo
# HTTPS GET请求(G4)——依赖OpenSSL + bottle证书(取自主机或curl.se下载)
kh run curl -- -sS -o .tmp/kh-out/https-body https://example.com/
wc -c .tmp/kh-out/https-body
# 异常测试:访问存在无效/自签名证书的站点应失败(退出码≠0)
kh run curl -- -sS -o /dev/null https://self-signed.badssl.com/; echo exit:$?

Docker辅助脚本:

./scripts/docker-curl.sh --version
./scripts/docker-curl.sh -sS -o /Volumes/linux/out/body http://example.com/
./scripts/docker-curl.sh -sS -o /Volumes/linux/out/https-body https://example.com/
ls -lh .tmp/kh-out/body .tmp/kh-out/https-body
# 探针日志输出至.tmp/kh-curl-probe/目录
./scripts/docker-curl-probe.sh --version
# 分阶测试curl参数组合(结果存于.tmp/kh-curl-options/)
./scripts/docker-curl-options.sh tier1
./scripts/docker-curl-options.sh tier9-10
./scripts/docker-curl-options.sh all # 测试tier1至tier10所有参数

运行过程中以下提示属于正常现象,不影响功能:

  • kh: open fail ENOENT(openat) path=/etc/ssl/openssl.cnf——OpenSSL配置文件为可选,HTTP/HTTPS仍可通过预置的CA证书包正常工作。
  • WARN … skip dylib … Security/CoreFoundation——Apple框架未包含在bottle中,已通过软桩(soft stubs)处理加载路径。
  • unresolved strong symbol; bound to named missing trampoline——未命中核心执行路径的符号,不影响程序运行。

详细说明与验证标准:docs/curl.md

测试场景 说明
Clang/基准探针测试 测试代码位于tests/clang-probe/tests/fixtures/
多线程7zz -mmt=4测试 已在Docker + UTM环境验证
Bottle + 独立式libSystem kh bottle ensure命令会自动嵌入动态库
单元测试 + clippy检查 执行cargo test/clippy可完成全工作区检查(kh-libsystem除外)

目前已实现curl全功能(POST请求体、代理、端到端HTTP/3、所有协议)、真实Apple Security.framework支持、git/命令行工具(CLT)、图形界面、代码签名(codesign)。下一阶段将支持:通过kh install xcode-tools运行git——详见docs/git.md

包(Crate) 功能定位
kakehashi 二进制程序kh(用户需安装此包)
kh-loader Mach-O文件解析、映射与执行
kh-runtime 内存管理、陷阱捕获、BSD系统调用转换、bottle机制;内置独立式libSystem.B.dylib
kh-libsystem 上述动态库的源码(仅支持aarch64-apple-darwin目标平台,非Linux主机包)

客端动态库预置于crates/kh-runtime/resources/libSystem.B.dylib,通过include_bytes!编译进运行时。发布kh-runtime时会自动包含该动态库,终端用户无需单独下载。

环境要求

  • Rust 1.88及以上版本
  • Linux aarch64系统(用于kh run/kh trace实时运行)
  • 支持的页面大小:4 KiB(容器环境)和16 KiB(Asahi类设备)
  • 可选依赖:curl/wget+tar(用于kh install 7zip/kh install curl命令)
cargo install kakehashi
# 或从源码编译安装:cargo install --path crates/kh-cli
kh bottle ensure
kh install 7zip
kh install curl

默认根目录:~/.local/share/kakehashi/bottle/(可通过KAKEHASHI_DATA_DIR/KAKEHASHI_ROOT环境变量覆盖)

主机路径 客端路径
…/bottle/ /
…/usr/local/bin/7zz /usr/local/bin/7zz
…/usr/local/bin/curl /usr/local/bin/curl
…/usr/lib/libSystem.B.dylib /usr/lib/libSystem.B.dylib
…/private/etc/ssl/cert.pem /etc/ssl/cert.pem(取自主机CA证书或下载的Mozilla证书)
…/Volumes/linux/… /Volumes/linux/…→ 映射至主机文件系统

Kakehashi让客端代码在CPU上原生运行,性能损耗仅来自系统调用边界(TLS切换、备用栈、NEON寄存器保存/恢复、Rust调度),损耗程度取决于客端程序调用系统调用的频率——并非指令级模拟器。

在Ubuntu aarch64裸机(UTM)环境下,对包含约8000个文件、总大小约240 MiB的目录执行多文件7zz归档(参数-t7z -m0=lzma2 -mx=5 -mmt=4):

原生Linux 7zz Kakehashi运行Darwin 7zz 性能比
耗时 ~22.5秒 耗时 ~118秒 ~×5.2

在以压缩为主、文件数量少的测试场景下,性能差距通常小得多(约×1.1–1.2)。多文件场景的性能差距主要由路径遍历+每次系统调用的边界开销导致,与LZMA算法本身无关。

所有客端线程默认启用超级调用(Hypercall),仅在调试时可通过KAKEHASHI_HYPERCALL=0关闭(关闭后会通过svcbrk/SIGTRAP处理)。

本项目针对CI场景的核心目标,并非“达到原生macOS性能”,而是在廉价的Linux aarch64运行器上运行Darwin命令行工具,替代稀缺且昂贵的macOS资源。

GitHub Actions托管运行器(私有仓库超额费率,单位:美元/分钟;详见Actions运行器定价):

运行器类型 每分钟费率
Linux 2核arm64 $0.005
Linux 2核x64 $0.006
macOS 3–4核(M1/Intel) $0.062
macOS高配(如12核/M2 Pro) $0.077–$0.102

macOS标准运行器的费率约为Linux arm64的10–12倍,且未考虑运行时间差异。即使在Linux arm64上通过Kakehashi运行作业的耗时是macOS的5倍,计费成本仍可能更低(示例:5 × $0.005 ≈ $0.025 vs 1 × $0.062)。公共仓库的免费运行时长、自托管Linux运行器会进一步放大这一成本优势;此外macOS托管资源往往排队时间更长,且在GitLab SaaS中仅Premium/Ultimate版本可用或处于测试阶段。

仍需使用macOS运行器的场景:图形界面、代码签名/公证(codesign/notarization)、Xcode UI测试,或任何依赖非纯命令行Darwin二进制文件及非独立式libSystem的工作负载。

正确性优先,性能其次:CI流程的正确性通过cargo test/冒烟测试/7zz -mmt=4验证,而非“匹配原生运行时长”。性能优化进度记录于docs/roadmap.md

docker build -t kakehashi:dev -f Dockerfile.dev .
docker run --rm -v "$PWD":/src -w /src kakehashi:dev \
cargo test --workspace --exclude kh-libsystem
# 完整冒烟测试(编译+clippy检查+测试+微型运行验证)
./scripts/docker-smoke.sh
cargo build -p kakehashi --release
cargo test --workspace --exclude kh-libsystem
cargo clippy --workspace --exclude kh-libsystem --all-targets -- -D warnings
# 维护者注意:独立式ABI变更后需更新内置动态库
cargo build -p kh-libsystem --release --target aarch64-apple-darwin
./scripts/stage-libsystem.sh # 生成文件→crates/kh-runtime/resources/libSystem.B.dylib

libSystem库的查找优先级:--libsystem命令行参数 → KAKEHASHI_LIBSYSTEM环境变量 → kh程序所在目录 → 包资源目录resources/编译进kh-runtime的内置字节码

测试目标 执行命令 输出结果
单元测试 cargo test --workspace --exclude kh-libsystem 终端输出测试结果
Docker冒烟测试 ./scripts/docker-smoke.sh 最终输出smoke ok
基准用例测试 kh run --expect-code … tests/fixtures/… 详见tests/fixtures/README.md
Clang探针测试 kh run --root tests/fixtures/bottle tests/clang-probe/puts_hello 标准输出hello
真实Darwin 7zz测试 ./scripts/docker-7zz.sh … 输出文件存于主机.tmp/kh-out/
真实Darwin curl测试 ./scripts/docker-curl.sh … 输出文件存于主机.tmp/kh-out/;探针日志存于.tmp/kh-curl-probe/
公平CPU性能基准测试 ./scripts/bench-fair-local.sh 结果存于主机.tmp/kh-bench-fair/

.tmp/.kh/target/目录已被加入git忽略列表。

Bottle机制将Linux文件系统映射为客端的/Volumes/linux/…路径:

客端路径 主机对应路径
/Volumes/linux/src/README.md <仓库根目录>/README.md
/Volumes/linux/out/demo.7z <仓库根目录>/.tmp/kh-out/demo.7z(持久化存储;docker-7zz.sh默认输出路径)
/Volumes/linux/tmp/… 容器内/tmp/…——docker run --rm后会被清除
脚本 用途
scripts/stage-libsystem.sh 编译生成动态库并复制至crates/kh-runtime/resources/
scripts/install-linux.sh 本地编译并安装kh+执行bottle ensure
scripts/docker-smoke.sh 在Docker镜像内执行完整冒烟测试套件
scripts/docker-7zz.sh 通过Kakehashi运行Darwin版7zz(输出文件存于.tmp/kh-out
scripts/docker-curl.sh 通过Kakehashi运行Darwin版curl(使用方式与docker-7zz.sh一致)
scripts/docker-curl-probe.sh KH_CURL_PROBE=1模式的封装脚本(日志存于.tmp/kh-curl-probe
scripts/docker-curl-options.sh 分阶测试curl参数组合(tier1tier10tier9-10all,结果存于.tmp/kh-curl-options
scripts/docker-git.sh 通过Kakehashi运行CLT中的Apple版git(包含软件扫描+.kh/data缓存)
scripts/bench-fair-local.sh 对比原生运行与Kakehashi运行的压缩性能(结果存于.tmp/kh-bench-fair

本项目采用Apache License 2.0许可协议。详见LICENSE.txt.

声明:本项目并非基于Darling开发。请勿分发Apple专有SDK或二进制文件。