使用 musl 库静态编译 rust 程序
2019-08-01 09:08 rust
rust 提供了很简单的方式调用外部的 C 库, 但是它默认是以动态链接的方式链到外部库, 这增加了部署时的复杂性.
musl 是一个轻量级的 libc 库, 与 glibc 相比, 它的代码比较简洁, 体积也更小, 更方便 静态编译到程序中.
我们可以将 musl 以及第三方的 C 库静态链接到 rust 程序可执行文件中.
下面以链接到 openssl
和 libsodium
这两个库为例, 来演示一下.
其中 Cargo.toml
代码如下:
[package]
name = "musl-demo"
version = "0.1.0"
authors = ["Xu Shaohua <shaohua@biofan.org>"]
edition = "2018"
[dependencies]
openssl = "0.10.24"
rust_sodium = "0.10.2"
[profile.release]
lto = true
main.rs
的代码如下:
extern crate openssl;
extern crate rust_sodium;
use openssl::ssl::{SslConnector, SslMethod};
fn test_openssl() {
let mut ctx = SslConnector::builder(SslMethod::tls()).unwrap();
// set_ciphersuites was added in OpenSSL 1.1.1, so we can only call it when linking against that version
#[cfg(openssl111)]
ctx.set_ciphersuites("TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256").unwrap();
}
fn test_sodium() {
println!("version of sodium: {}.{}",
rust_sodium::version::version_major(),
rust_sodium::version::version_minor()
);
}
fn main() {
test_openssl();
test_sodium();
}
安装 rust musl 工具链
使用 rustup 安装:
$ rustup target add x86_64-unknown-linux-musl
安装 musl-tool
musl-tool 工具包提供了 musl-gcc
和 musl-ldd
命令:
$ sudo apt install musl-tools
编译并安装 openssl 库
首先, 下载源代码:
$ apt-get source libssl-dev
其次, 安装编译依赖:
$ sudo apt build-dep libssl-dev
进入到 openssl 源码目录, 编译并安装:
$ ./config
$ make depend
$ make -j$(nproc)
$ sudo make install
编译并安装 libsodium 库
下载源码:
$ apt-get source libsodium-dev
安装依赖包:
$ sudo apt build-dep libsodium-dev
编译并安装:
$ ./autogen.sh
$ ./configure
$ make -j$(nproc)
$ sudo make install
编译 rust 程序
编译之前, 先设置一下环境变量:
$ export OPENSSL_STATIC=true
$ export OPENSSL_LIB_DIR=/usr/local/lib
$ export OPENSSL_INCLUDE_DIR=/usr/local/include
$ export SODIUM_STATIC=true
$ export SODIUM_LIB_DIR=/usr/local/lib
$ export SODIUM_INCLUDE_DIR=/usr/local/include
编译时, 要指定 target
:
$ cargo build --release --target=x86_64-unknown-linux-musl
现在查看一下可执行文件的状态:
$ file target/x86_64-unknown-linux-musl/release/musl-demo
musl-demo: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=f0024cc3613140c6b8e9c6a4100aa1d8f5961e9a, with debug_info, not stripped
而之前没有开启静态链接时的文件类型是:
$ file target/release/musl-demo
target/release/musl-demo: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=cccca4589d8c99677c865020c8f6b91b86a3e9bb, for GNU/Linux 3.2.0, with debug_info, not stripped
使用 docker 编译静态的 rust 程序
rust-musl-builder 提供了类似的功能, 而且是基于 docker 镜像来编译的, 里面还附带了额外的组件, 不妨一试.
参考
- https://www.musl-libc.org
- https://github.com/messense/rust-musl-cross
- https://en.wikipedia.org/wiki/Setcontext
- https://github.com/emk/rust-musl-builder