I use rust 1.34 and 1.35. Currently it links to GLIBC_2.18
.
How can I limit cargo build
to link GLIBC
up to version 2.14
?
I use rust 1.34 and 1.35. Currently it links to GLIBC_2.18
.
How can I limit cargo build
to link GLIBC
up to version 2.14
?
Unfortunately, you can't. Not really, and not consistently. This is a problem with any binary that dynamically links to GLIBC. You can try setting up multiple GLIBC versions and linking to one, or you can try patching the resulting binary, but it's inconsistent and impractical.
So what are some practical options?
By using MUSL instead of GLIBC we can compile statically.
To install the MUSL target with rustup
(assuming x86_64 architecture):
$ rustup component add rust-std-x86_64-unknown-linux-musl
And to use it when compiling:
$ cargo build --target x86_64-unknown-linux-musl
This is the easiest method by far, but won't always work, especially when using native libraries, unless they can also be compiled statically.
This is a common approach. By using an OS with an outdated, GLIBC the binary will have GLIBC symbols that are compatible with it.
This is probably the most convenient method, in my opinion. If you have Docker, you can just compile your project with a container that contains an old GLIBC. View the Rust contianer's README for compilation instructions. The command below will compile a project using Rust 1.67 and GLIBC 2.28 (which comes with 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
I compiled this on Ubuntu 22.04 and tested it on Ubuntu 20.04.
To test further, I made sure the binary relied on another dynamic library (OpenSSL) and here's the result of ldd ./mybinary
after compiling with the Docker container:
$ 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)
And this is what it looks like without the container:
$ 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)