分类

使用 musl 库静态编译 rust 程序

2019-08-01 09:08 rust

rust 提供了很简单的方式调用外部的 C 库, 但是它默认是以动态链接的方式链到外部库, 这增加了部署时的复杂性.

musl 是一个轻量级的 libc 库, 与 glibc 相比, 它的代码比较简洁, 体积也更小, 更方便 静态编译到程序中.

我们可以将 musl 以及第三方的 C 库静态链接到 rust 程序可执行文件中.

下面以链接到 openssllibsodium 这两个库为例, 来演示一下.

其中 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-gccmusl-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 镜像来编译的, 里面还附带了额外的组件, 不妨一试.

参考