Rust使用musl静态编译
Rust默认运行时环境¶
- Linux 下 rust 默认使用 gcc 作为链接器, 编译后的文件在运行时需要glibc 运行库和其他的一些库
- 这就导致在某个Linux版本下编译的执行文件, 无法在另一个Linux版本上顺利运行, 而且, 如果你的程序还使用了OpenSSL动态库,, 那这样的问题会更加突出
-
下面, 我们做个最简单的实验
-
用Cargo创建一个可执行项目
- 编译这个项目
- 用ldd命令查看编译出来的执行文件依赖了哪些动态链接库
$ cargo new --bin hello && cd hello && cargo build && ldd target/debug/hello
linux-vdso.so.1 (0x00007ffdc47e4000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f6db611a000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f6db5f12000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f6db5cf3000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f6db5adb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6db56ea000)
/lib64/ld-linux-x86-64.so.2 (0x00007f6db6587000)
可以看到这个执行文件依赖了多个.so的动态链接库, 而且这种依赖是基于绝对路径的, 一旦运行时环境下没有这些动态库文件,那程序执行的结果就只有一个: 报错!
使用MUSL进行静态编译¶
- 使用MUSL编译, 首先需要安装musl环境, 命令如下:
$ rustup target add x86_64-unknown-linux-musl
$ rustup target add x86_64-unknown-linux-musl --toolchain=nightly
- 尝试编译前面创建的hello工程
$ cd hello
$ cargo build --release --target=x86_64-unknown-linux-musl
$ ldd target/x86_64-unknown-linux-musl/release/hello
not a dynamic executable
可以看到新的可执行文件已经不再依赖任何动态链接库, 我们可以将这个文件放到任何一个Linux操作系统里运行了
使用预置好的Docker容器进行MUSL编译¶
- 为解决使用MUSL编译配置繁琐的问题,国外的开发者贡献了一个预置好的容器。用这个容器来进行MUSL编译会非常方便快捷