Bumping glibc requirements for the Rust toolchain

As CentOS 5 is now EOL, I’m proposing to bump the minimum glibc requirements with the build image upgrade to CentOS 6.

I have opened a PR to upgrade the x86_64 image. This is feature complete, but let’s discuss here before merging them.

See my previous PR description for a table of glibc versions of major distros.

Is there a significant maintenance burden imposed by sticking with CentOS 5?

I don’t see many.

However, we don’t know when LLVM will bump the requirements, and adopting the modern toolchain surely makes the maintenance easier. This is an example.

If there is no significant maintenance burden, what is the concrete benefit of bumping our glibc version?

First of all, there’s no concrete benefit. I’m just keeping it up to date.

I hate EOL things. Things including the base Docker image could be dropped without notice.

I have no idea why glibc changes across version, but there should be some reasons to make ABI incompatible changes.

If bumping the version doesn’t break things for most people (I even don’t think a person who can continue to use CentOS 5), what’s the problem there?

But there's a potential downside of breaking users who rely on the status quo. We don't know how many those users are, but unknown cost for no benefit doesn't weigh in your favor.

You seem to be arguing against changes while proposing an incompatible change...

Glibc is one of the most ABI-compatible projects out there. Yet it's still an active project, and symbol versioning is the means to add new things while keeping the old around for compatibility.

JFYI, we are still using RHEL5 in a $BIGCORP. It is deprecated and on the way out but it’ll stick around for some time yet.

But are you using rust on RHEL5?

We are also using RHEL5 in $DAY_JOB, and I can certainly see Rust being used in some of our more-open-to-changes teams.

I think it would be useful to quantify what’s happening here as well.

If you believe that you require an old version of glibc, then it’d be great if you could run ldd --version locally. If it is 2.12 or after then you’re guaranteed to be ok if we move to CentOS 6. If you’re before 2.12 then you may break if we move to CentOS 6.

Note that if we compile against glibc 2.12 the resulting binary may not actually require glibc 2.12. Depending on what symbols end up being linked we may still only require 2.3.4. We should test to see what happens, but I would regardless not want to silently rely on building against glibc 2.12 and just happening to continue to require glibc 2.3.4.

3 Likes

SLES 11, glibc 2.11 reporting in.

1 Like

You scanned lib/*.so, but don't forget bin/ too. rustc and rustdoc are trivial, but cargo and rustup have significant contents. They don't seem to add anything in this case though. This still doesn't tell us what dependencies glibc-2.12 will introduce, nor how our use may expand in the future. We should still assume that anything less than the glibc we build with is unsupported.

We should also watch for libgcc GCC_X.Y versions. RHEL5 has gcc-4.1.2, but in fact we do have a link to _Unwind_GetIPInfo@GCC_4.2.0. This one works though, because that exact symbol was also backported between 4.1.1 and 4.1.2.

It's also worth noting that the devtoolset-gcc on RHEL6 (that @ishitatsuyuki is proposing to use) is specifically crafted to remain ABI compatible with the base-OS's gcc-4.4.7 for libgcc etc. That's something to be careful about when we build custom GCCs for our build containers.

Yes, in some minor applications.

I was a bit shocked by the people talking about RHEL 5 being in use so I looked it up and yes, it is still alive and supported (ish):

Red Hat Enterprise Linux Life Cycle - Red Hat Customer Portal (also search for "Life-cycle Dates")

In addition, for Red Hat Enterprise Linux 5, customers may purchase annual Add-on subscriptions called Extended Life-cycle Support (ELS) that provide similar support to Production Phase 3 through November 30, 2020.

Only 3.5 years to go, I'll note it down in my calendar now! (I also note that RHEL 4 support only ended three weeks ago...)

Really though, I don't think sticking with Centos 5 is great. We already build half of userland and that's not going to get better in the next 3.5 years...after which we jump forwards to the positively futuristic Centos 6, which was old enough to be awkward to develop on at times 3 years ago. Nor is moving to Centos 6 ideal since we make anyone on RHEL 5 unhappy. Static linking isn't really viable due to compiler plugins and cargo hitting the network.

So if we're serious about RHEL 5, my dream solution is to bump the Docker image to use the latest Ubuntu LTS, build the older stuff that's necessary to get the right environment for creating a portable rustc and run a checker to verify that we're only linking to expected symbols. Probably not easy (there's a reason everyone just uses the CentOS images), but possible. And the thought of 'upgrading' from CentOS 5 to 6 in 3.5 years is depressing - we'll optimistically get rid of the userland compilation scripts, then incrementally add them back over time as we discover bugs in the versions from the package manager.

p.s. glibc is only one part of the story, since we can't use most/all of these highlighted syscalls (sendmmsg surprised me too), but that's a more tractable libraries problem rather than a "I can't run rustc" problem.

That's basically what we have for all of the cross-arch builds, sans checker, using crosstool-ng in most cases to build the compatible toolchain. But you really end up building almost everything for this case, so there's little advantage to using a newer Ubuntu as the base image. Native x86 builds can only loosely be called "cross", but when you're targeting a glibc different than the host, it's essentially the same situation.

I think this is a fine plan. There is no reason for Rust to pin to an arbitrarily new GLIBC version, except if LLVM requires it.

Also see https://web-beta.archive.org/web/20100613022915/http://www.autopackage.org/apbuild-apgcc.php

Rust doesn't make syscalls manually. The libc that comes with your OS should know which syscalls to call for your kernel.

(below I'm going to make a fake distinction between 'userland' (bash, python) and 'toolchain' (compilers))

Well, you end up building the toolchain. Things that you don't end up building (I think?) include curl, python, cmake and git (more things to be added over time I'm sure), so I'm not sure "almost everything" is quite right. At the moment we're building both the userland miscellanea and bits of the toolchain - why not just build the toolchain? (yes, I'm simplifying just a little for effect :slight_smile:)

In the end, we will move off CentOS 5 at some point. I see the options as 1) CentOS 6 now/later and we get a new toolchain/environment with a new set of bugs and, independently, we're adding new necessary hacks to both toolchain and userland as technology changes over time) or 2) get us off CentOS 5 now, make the dist builders look like the other builders, give us a rolling userland environment (so we don't have to caretake) independent of the actual toolchain and make the toolchain version choices more explicit and controlled.

The only reason I can really see to avoid 2 is if you want to build rustc on RHEL 5. Right now you can just follow the dockerfile instructions and it'll probably work. Given a world where 2 is implemented, you're probably out of luck. I don't find this particularly compelling given you'll be able to build anywhere you have Docker and send it to your RHEL 5 machine, but I could be convinced.

I'm more referring to crates in the wider ecosystem that may (I don't really know how much it happens) use interesting syscalls for performance, not expecting to be run on old Linuxes. It'll just need PRs, but it's still a speedbump.

1 Like

Point taken about building the toolchain vs other programs.

And FWIW, while I work for Red Hat, I’m not declaring a need on our part for continued Rust support on RHEL5. We certainly don’t ship any new software ourselves in the extended life-cycle.

But I do favor the conservative attitude, not to rock the boat here without reason. It works, and a few users have spoken up that they want it, so I think it needs stronger motivation to change.

Of course, their old rustc will keep working too…

Some arguments:

  • There’s no need to support bleeding edge things for ancient distributions. They just don’t want to migrate, then a stable and out-of-date version will keep the old things (such like an unmaintained crate) working. Rust sometimes includes changes that reject old code.

  • For extremists, the musl toolchain is to the rescue. They can compile things independently from the ABI.

None of those arguments cover why it’s actually beneficial to make this change.

IIRC you can’t build rustc against MUSL anyway since plugins won’t work.