优化 Rust 程序编译体积

体积狂魔の执念, 记录一下以免忘记.

[2018.12.20] 今天测了一下发现体积大幅减小了, 回忆了一下也许是把内存分配器换成了系统自带的原因. 这也提醒了我要记录一下 Rust 版本

1
2
➤ rustc --version
rustc 1.32.0-beta.2 (a01e4761a 2018-12-08)

新建一个项目, 直接编译

1
2
3
4
5
6
7
8
▶ cargo new --bin hello
Created binary (application) `hello` project
▶ cd hello
▶ cargo build --release
Compiling hello v0.1.0 (file:///tmp/hello)
Finished release [optimized] target(s) in 0.45s
▶ du -h target/release/hello
2.3M target/release/hello

一个 hello world 2.3M, 太大了. // 原来是 3.9M

strip 一下.

1
2
3
▶ strip -s target/release/hello
▶ du -h target/release/hello
196K target/release/hello

196K, 这个体积已经可以接受了, 不过我还是想知道还可以有多小. // 原来是 420K

在Cargo.toml中添加

1
2
3
4
[profile.release]
panic = 'abort'
lto = true
opt-level = "z"
1
2
3
4
▶ cargo build --release && strip -s target/release/hello && du -h target/release/hello
Compiling hello v0.1.0 (file:///tmp/hello)
Finished release [optimized] target(s) in 1.73s
164K target/release/hello

164K, 再次进步. 不过这还不够! // 原来是 180K

超必杀技: 注释掉 panic 和 lto 两行, 然后使用动态链接.

1
2
3
4
5
6
7
8
▶ RUSTFLAGS='-C prefer-dynamic' cargo build --release 
Compiling hello v0.1.0 (file:///tmp/hello)
Finished release [optimized] target(s) in 0.14s
▶ du -h target/release/hello
20K target/release/hello
▶ strip -s target/release/hello
▶ du -h target/release/hello
16K target/release/hello

16K!! 非常满意. 除了无法运行之外

(可以看到链接了一个莫名其妙的 libstd-affa4edaee4ff43e.so)

1
2
3
4
5
▶ ldd target/release/hello
linux-vdso.so.1 (0x00007ffd6f4b4000)
libstd-affa4edaee4ff43e.so => not found
libc.so.6 => /usr/lib/libc.so.6 (0x00007f02e5e5a000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f02e6077000)

Google 了一下这个问题已经有人提出了 Avoid the proc_macro crate being dynamically linked.
也已经有人着手修复了 Decouple proc_macro from the rest of the compiler.

坐等

P.S. -C开关可供把玩的选项似乎很多啊, 比如 -C target-cpu=native提高程序本机运行速度

[2018.12.20] 那个 PR 已经合并了, 然而问题还是没有解决...我又探究了一下, 发现我其实可以运行这个 bin

1
2
➤ LD_LIBRARY_PATH=~/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib:. ./target/release/hello
Hello, world!

这玩意儿原来是 runtime...我早该想到的orz

1
2
➤ du -h /home/aloxaf/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/libstd-affa4edaee4ff43e.so
5.4M /home/aloxaf/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/libstd-affa4edaee4ff43e.so

然后, 由于 Rust 还没有稳定的 ABI (RFC#600), 所以这个问题暂时还是无解状态. 如果有稳定 ABI 了, 咱就可以 pacman -S rust-common 啥的, 然后就可以享受超小体积的二进制了!