Comment by Onavo
6 months ago
Go especially, on some platforms they go straight to syscalls and bypass libc entirely. They even bring their own network stack. It's the maximalist plan 9 philosophy in action.
6 months ago
Go especially, on some platforms they go straight to syscalls and bypass libc entirely. They even bring their own network stack. It's the maximalist plan 9 philosophy in action.
I don't really like Go as a language, but this decision to skip libc and go directly with syscalls is genius. I wish Rust could do the same. More languages should skip libc. Glibc is the main reason Linux software is binary non-portable between distros (of course not the only reason, but most of the problems come from glibc).
> Glibc is the main reason Linux software is binary non-portable between distros
Linux software is binary portable between distros as long as the binary was compiled using a Glibc version that is either the same or older than the distros you are trying to target. The lack of "portability" is because of symbol versioning so that the library can expose different versions of the same symbol, exactly so that it can preserve backwards compatibility without breaking working programs.
And this is not unique to Glibc, other libraries do the same thing too.
The solution is to build your software in the minimum version of libraries you are supposed to support. Nowadays with docker you can set it up in a matter of minutes (and automate it with a dockerfile) - e.g. you can use -say- Ubuntu 22 to build your program and it'll work in most modern Linux OSes (or at least glibc wont be the problem if it doesn't).
> Linux software is binary portable between distros as long as the binary was compiled using a Glibc version that is either the same or older than the distros you are trying to target.
Well, duh? "Property A is possible if we match all requirements of property A".
Yes, using older distro is the de facto method of resolving this problem. Sometimes it's easy, sometimes it's hard, especially when we want to support older distros and using a new compiler version and fairly fresh large libraries (e.g. Qt). Compiling everything on older distro is possible, but sometimes it's hell.
> And this is not unique to Glibc, other libraries do the same thing too.
This only means that it is a very good idea to drop dependency on glibc if it's feasible.
macOS has a "minimum macos required" option in the compiler. Windows controls this with manifests. It's easy on other systems.
1 reply →
The consequences of this genius decision were stuff like this:
https://github.com/golang/go/issues/16570
Which is why they have already backpedalled on this decision on most platforms. Linux is pretty much the only OS where the syscall ABI can be considered stable.
Yes, Linux is reversed in this aspect -- glibc is not really binary friendly, but kernel syscalls are. On other systems, kernel syscalls are not binary friendly at all, but libc is friendly.
I'm fine with using libc on other systems than Linux, because toolchains on other systems actually support backward compatibility. Not on Linux.
You can only skip libc on Linux. Other unices and Windows don’t let you.
You can skip libc on Windows - you can't skip the system DLLs like kernel32. (In fact, Microsoft provided several mutually incompatible libcs in the past.)
Well, you can non-portably skip kernel32, and use ntdll, but then your program won't work in the next Windows version (same as on any platform really - you can include the topmost API layers in your code, but they won't match the layers underneath of the next version).
But system DLLs are DLLs, so also don't cause your .exe to get bloated.
4 replies →