-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rust binaries require a too recent glibc #57497
Comments
AFAIK this is just how linking to glibc works - we talk to the linker the same way you would when building C code. If you want to target old glibc versions, you need to build against an old glibc version. |
Afaik rust is manually linking rust/src/libstd/sys/unix/fast_thread_local.rs Lines 4 to 34 in 79d8a0f
|
There's nothing particularly special about that import (other than being declared weak to support linkage against glibcs without it) - it's still going to be handled by the linker the same way that a reference to |
I also disagree that this is something actionable on our side. Unlike Go, Rust depends on libc and the classic ABI problem needs to be handled just as C programs. And yes, you'll need to build things on an older distro, and that's what we do for rustup. See https://github.com/rust-lang/rust/tree/master/src/ci/docker/dist-x86_64-linux for a reference. |
It's totally possible that rust can't do anything about that, but I'm a bit confused by the following: When I remove diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs
index d48d701dd5..27d3cae5f6 100644
--- a/src/libstd/sys/unix/fast_thread_local.rs
+++ b/src/libstd/sys/unix/fast_thread_local.rs
@@ -12,23 +12,11 @@
// Due to rust-lang/rust#18804, make sure this is not generic!
#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit"))]
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
- use libc;
- use mem;
use sys_common::thread_local::register_dtor_fallback;
extern {
#[linkage = "extern_weak"]
static __dso_handle: *mut u8;
- #[linkage = "extern_weak"]
- static __cxa_thread_atexit_impl: *const libc::c_void;
- }
- if !__cxa_thread_atexit_impl.is_null() {
- type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8),
- arg: *mut u8,
- dso_handle: *mut u8) -> libc::c_int;
- mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl)
- (dtor, t, &__dso_handle as *const _ as *mut _);
- return
}
register_dtor_fallback(t, dtor);
}
|
That's not how extern_weak linkage works, though. The nullability decision is made at link time, not run time:
|
I agree this ideally should be fixed, but I consider this a bug on general Linux ecosystem. macOS doesn't have this problem because you compile with |
I already understood it thus far. What I hope is that there is something like |
Rust programs can link to hundreds of glibc symbols, any of which could have versions that require newer glibcs. There's nothing particularly special about __cxa_thread_atexit_impl except that it happens to be the only one for that specific program. |
Oh that's too bad; I had been under the impression that std links a fixed set of symbols and that we'd only need to work around |
Best bet is to use Docker to compile the release binary. I had this exact problem and luckily, the official rust docker image did it. There's even a command in the readme: If you need a version of libc lower than the version the official docker image has, you will have to build your own image, unfortunately. |
Would something like https://github.com/wheybags/glibc_version_header help? It seems like we need to emit a It looks like gcc also implements a |
It's been a while and this issue is still getting shared, so i'd like to promote cargo-zigbuild, which can build for arbitrary glibc versions. For those who don't need to load dynamic libraries, you can build for |
rust-lang/rust#57497 Seems like we are stuck on this img. We can address this in the next release this is probably going to be a lot of work.
When rustc builds on a system with a recent glibc version, the binaries require a recent glibc version (2.18). When built on an old system however, they will only require glibc 2.3.
To reproduce we can use a simple hello world example, building e.g. on Ubuntu 18.04:
Let's look at the required symbols, filtering out glibc 2.2 and 2.3:
We see that 2.14 and 2.18 seem to be used. We can confirm that those symbols are indeed required using a cent os 5 docker container:
This happens even with cent os 7:
When building inside the cent os 5 container on the other hand, none of the above symbols are used and the binary runs just fine in the container.
Why does this matter?
For my case, it's because I want to produce manylinux compliant libraries and binaries. manylinux is a policy defined by python designed to be compatible with virtual any used linux system, which requires that only symbols from glibc <= 2.5 are used. All packages in the python package index must follow that policy, even though the glibc part is currently not automatically enforced. This affects e.g. milksnake and pyo3. A newer requirement, called manylinux2010 is worked on, but it stills require glibc <= 2.12.
In general it means that you can't use any modern ci server to produce widely compatible linux-gnu binaries. You always have to build in some ancient docker container instead.
Versions
rustc -vV
:rustc 1.33.0-nightly (8e2063d02 2019-01-07)
cargo -V
:cargo 1.33.0-nightly (2cf1f5dda 2018-12-11)
This issue a bit of a follow-up to #36826.
The text was updated successfully, but these errors were encountered: