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)

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

2 Likes

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).

1 Like

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.

1 Like

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).

2 Likes

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!

1 Like