我使用 Rust 1.34 和 1.35。目前它链接到
GLIBC_2.18
。
如何限制
cargo build
链接 GLIBC
至版本 2.14
?
不幸的是,你不能。不是真的,而且不一致。这是任何动态链接到 GLIBC 的二进制文件都会遇到的问题。您可以尝试设置多个 GLIBC 版本并链接到一个,或者您可以尝试修补生成的二进制文件,但这是不一致且不切实际的。
那么有哪些实用的选择呢?
通过使用 MUSL 而不是 GLIBC,我们可以静态编译。
要使用
rustup
安装 MUSL 目标(假设 x86_64 架构):
$ rustup component add rust-std-x86_64-unknown-linux-musl
并在编译时使用它:
$ cargo build --target x86_64-unknown-linux-musl
这是迄今为止最简单的方法,但并不总是有效,特别是在使用本机库时,除非它们也可以静态编译。
这是一种常见的方法。通过使用过时的操作系统,GLIBC 二进制文件将具有与其兼容的 GLIBC 符号。
在我看来,这可能是最方便的方法。如果您有 Docker,则可以使用包含旧 GLIBC 的容器来编译您的项目。查看 Rust 容器的 README 以获取编译说明。下面的命令将使用 Rust 1.67 和 GLIBC 2.28(buster 自带)编译一个项目:
$ docker run --rm --user "$(id -u)":"$(id -g)" -v "$PWD":/usr/src/myapp -w /usr/src/myapp rust:1.67-buster cargo build --release
我在 Ubuntu 22.04 上编译了这个,并在 Ubuntu 20.04 上测试了它。
为了进一步测试,我确保二进制文件依赖于另一个动态库(OpenSSL),这是使用 Docker 容器编译后
ldd ./mybinary
的结果:
$ ldd ./mybinary
linux-vdso.so.1 (0x00007ffd98fdf000)
libcrypto.so.1.1 => /lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007fe49e248000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe49e22d000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fe49e223000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe49e200000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe49e0b1000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe49e0ab000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe49deb7000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe49ea30000)
这就是没有容器的情况:
$ ldd ./mybinary
linux-vdso.so.1 (0x00007ffd5d7b7000)
libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x00007fe85564c000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe85562c000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe855545000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe85531d000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe855f98000)