How to compile a Rust program (written in version 1.82) into a dynamic library that can run on Linux systems with low glibc versions (e.g., 2.12, 2.5)?
We currently use Rust 1.82 to develop a program and compile it into a dynamic library, but deployment targets have older glibc versions. We need to ensure compatibility without downgrading the Rust version.
you can link libc
statically with the crt-static
target feature, e.g. use RUSTFLAGS
or set build.rustflags
in .cargo/config.toml
note, musl
is typically used for statically linked programs, but you can link glibc
statically as well, but the static library files for glibc
is usually not installed by default, so you may need to install it first.
for instance, on opensuse, you need to install the glibc-devel-static
package, on ubuntu, I believe it's libc6-dev
. if in doubt, search which package contains the file libc.a
If you want to dynamically link to older glibcs, you can build a cross-compilation toolchain targeting that version. crosstool-ng can help with that.
The zig compiler also has support to act as a linker against arbitrary glibc versions (with some caveats).
Can using the crt-static feature to statically link with glibc generate a shared library? When I use this feature, I receive an error stating 'cannot produce cdylib for xxx as the target doesn't support these crate types'.
Most platforms do not allows dylibs to statically link against libc to prevent internal state of libc from getting duplicated. The only exception I know of is Windows where a fair part of this state is actually in system libraries that are always dynamically linked rather than in libc.
Also you should avoid statically linking glibc. It actually males your program less portable as glibc still depends on some dylibs when statically linked for things like NSS. The paths to those dylibs vary between distros, but a statically linked glibc hard codes the paths for the distro it originated from.
The most reliable answer is to use a container or VM matching the old glibc you want to compile against.
If that glibc is older than what Rustc supports, then you need to use a cross compiling tool.
I had a similar issue a few months ago, and managed to get it to compile and run by using cargo zigbuild
-- specifying the glibc version is part of the target triple, so it should be pretty seamless (I've linked to the part of the readme with details on that).
I used cargo zigbuild to compile a dynamic library targeting a lower version of GLIBC. The compilation succeeded without errors, but the resulting library lacked certain symbols available only in higher GLIBC versions. After identifying these missing symbols, I found that they were either unused in the project or involved low-risk usage. I then manually implemented those symbols myself. Now, the library works as expected.Thank you!