A proposal to start “llvm-libc” (2020)
llvm.org
llvm.org
Lack of ABI stability sounds terrifying as an application developer. My other immediate thought was "how will this interact with systems where the OS-provided libc is the only stable way to e.g. make syscalls", and "Layering Over Another libc" addresses this. I guess the idea is you'd link an application against llvm-libc and the system libc, and ship llvm-libc with your application?
If you're providing the packages yourself, it's up to you to do that yourself.
Or yes, you can vendor libc in your package. Not something everyone will like, but it depends on who your users are.
It's not like this is unusual. Binaries compiled against today's glibc can fail to run on a machine that hasn't been updated since last week because they rely on a new / different symbol. Rebuilding the distro's packages when their deps are updated is standard fare.
Note, however, that it is a Glibc bug (modulo Drepper’s temper) if the reverse happens: Glibc symbol versioning ensures that binaries depending on an old Glibc (only) will run on a new one. So the proper way to build a maximally-compatible Linux executable would be to build a cross toolchain targeting an old Glibc and compile your code with it. Unfortunately, the build system is hell and old Glibcs doesn’t compile without backported patches, so while I did try to follow in the footsteps of a couple of people[1–5], I did not succeed.
Mass rebuilds still happen with other ecosystems, though. GHC-compiled Haskell libraries are fine-grained and not ABI-stable across compiler versions, so my Arch box regularly gets hit with a deluge of teensy Haskell library updates, and Arch is currently undergoing a massive Python rebuild (blocking all other Python package updates) behind the scenes as well.
[1]: https://github.com/wheybags/glibc_version_header (hack but easy and will probably work most of the time)
[2]: https://www.lordaro.co.uk/posts/2018-08-26-compiling-glibc.h... (someone’s mostly-nonhackish effort)
[3]: https://github.com/pypa/manylinux (what Python manylinux wheels use, more modern than absolutely necessary)
[4]: https://github.com/FooBarWidget/holy-build-box (ditto and is also a complete opaque cross-toolchain build recipe, but apparently people use that)
[5]: https://casualhacking.io/blog/2018/12/25/create-highly-porta... (missed it last time, so can’t say much)
But only up to a certain point.
Just the other day I wanted to run the old Ballistics game with it's 2007 binary on a modern Ubuntu. All I got was
ballistics/lib/lib1/libm.so.6: version `GLIBC_2.29' not found (required by /usr/lib/i386-linux-gnu/libasound.so.2)The Ballistics packaging people got it exactly backwards, in other words: Glibc is the thing you least want to bundle unless you’re bringing the entirety of the environment with you (including things like libGL and libX11). Try just removing the offending libm, maybe? Then the loader should probably fall back to the system one, given that it’s finding a system libasound, and that’s what you want.
It may have been newer when than the system provided one when it first shipped. Sadly you can't tell the dynamic linker to just load the newest version of a library. It just loads the first it finds and that breaks once the system provided version is newer.
Shared libraries are nice for forward compatibility: see libsdl1.2-compat, libaoss, etc.
If my interpretation is correct, then if it's going to load system libraries, those may require system glibc, and if it's going to use system glibc, it should use all system glibc rather than trying to mix and match.
Right right. I gave that example not as something that people would expect to work, just as something that indicates that users and distros are used to the idea of binaries and libc being revved in sync.
They must be thinking of some very specific functions.
In <stdio.h>, functions that are implemented as macros can peek at the FILE * structure, so if that's not maintained in a backward-compatible way, that would be a problem. (In that case, if you #undef the macros to reveal the real functions, you're almost certainly OK. C programs do not declare or initialize FILE objects.)
struct tm could cause issues; if hidden fields are added to it, which existing binary clients don't define.
Various things in POSIX can have a problem also; it has a lot of structures, the storage for many of which are defined by client programs, and in some cases even initialization.
Linux, macOS, Windows, FreeBSD, and probably OpenBSD seem shoo-in table stakes.
I'm more curious about
- iOS/iPadOS: already have a libc, but... maybe?
- Android: already has bionic/NDK; alternative useful?
- NetBSD: rump kernel/unikernel applications?
- VMS: has x86_64 support now; suddenly less irrelevant than before?
- QNX: IIUC still the best deterministic/hard real time POSIX OS...
- Illumos: not dead yet?
- HP-UX/AIX: still used in certain industrial applications...?
- Serenity: ...oh wait, just realized this isn't full POSIX, woops (would that be a prerequisite?)
- (what obvious thing did I forget? :P)
I ask this question mostly to update my understanding of "the state of kernel/OS interestingness, ~2022", since the process of deciding what targets a new major libc should consider relevant is going to be both well-informed and carefully considered given the anticipated (hoped) timescale of such a project.
Not quite: https://omnios.org
ARM6-ARM8, even older (STM32) in some cases.
Consider the places where libiberty and the now very long in the tooth RedHat Newlib is in use.
There's a lot of places where llvm is used but where a good libc is basically gone or is mostly implemented as a bunch of messy assembly routines.
Case in point; my C compiler. It already was not designed to handle untrusted input well enough and I plan to run multiple instances in parallel, so my kernel should handle COW.
On Windows, it is somewhat laborious and involves some debatable trade-offs, but you can avoid msvcrt/ucrt altogether but you must link with kernel32 for syscalls. I have a very minimal nomsvcrt.h that just defines types and externs for those syscalls defined in kernel32, but it's really incomplete -- it's easy to write your own based on win32 docs anyway. One additional thing you'll need though are all the compiler bits that are now missing, mostly dealing with floating point conversions. https://hero.handmade.network/forums/code-discussion/t/94-gu... provides an excellent guide, but note the trade-offs made. I think the last thing you might want is a routine to turn GetCommandLineA()'s result into argc, *argv[], and if you can use LGPL, that's available in https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/winec...
I don't have a macOS system right now, but I'm willing to bet there's a similar scheme possible there. That covers a lot of systems. OpenBSD is the only system I know of that really enforces system calls to go through their libc, but I'm ignorant.
Unless you want to use graphics acceleration, which is implemented in userspace as harware-specific dynamic libraries. Audio also typically goes through user-space implementations - not sure if the interprocess protocols there are stable enough to statically the client libraries.
I wish one day c/c++ can cross-build just like what rust/golang does today.
That seems like a long ago assumption baked that binaries should only have one program interpreter per system. I don't know enough about configuring a system and the historical decisions around PT_INTERP, but I suspect Andrew is on to something.
If anyone has even done a build of clang with this, I'd love to know!
Clang's in Alpine Linux's repo's, so I guess they have and this is how: https://git.alpinelinux.org/aports/tree/main/clang
nix-build -A pkgsStatic.llvmPackages.clang-unwrapped
Which built all the other deps just fine, but failed buildling LLVM with CONFIGURE_LLVM_NATIVE. That seems easy enough to fix, as that's the regular part, though.No guarantee there wouldn't be other more serious issues lurking beneath, but we've attempted quite a lot of static builds of complicated thing, augmented Musl with various bits and scraps to make it more featureful.
You gave a very nice intro for my talk, saying Nixpkgs could well be the future so check it out. Well, I hope that future can arive more widely soon :).
I don’t know if they’re right, but their arguments did shift my opinion in their direction.
Corporate lawyers seem to love it, though, because of the mutually-assured-patent-destruction clause.
[1]: http://www.openbsd.org/policy.html (see corresponding section)
[2]: https://marc.info/?i=91077.1475036864%20()%20cvs%20!%20openb... (De Raadt rants on openbsd-misc, discussed on HN at https://news.ycombinator.com/item?id=126178810)
[3]: https://lists.llvm.org/pipermail/llvm-dev/2017-April/112300.... (Kettenis objects on behalf of OpenBSD on llvm-dev)
[4]: https://www.cambus.net/the-state-of-toolchains-in-openbsd/ (OpenBSD gives up on staying with old LLVM)
Which is inane because a copyright license is a contract anyways. My understanding is that the number of lawyers who agree with the OpenBSD position is approximately 0, even in jurisdictions that don't have Anglophone interpretations of contracts and copyright--I haven't seen any lawyer come it in favor of the OpenBSD interpretation here. (Note too that criticism of the GPL doesn't include this--and if Apache is too complicated to be a copyright license, the GPL certainly is.)
There is also a certain irony in arguing that clarifying the terms of a license great yields less clarity than not doing so.
It's Apache v2 with a compiler exception--i.e., the compiler linking bits of itself into you doesn't count for license purposes.
LibC++ is licensed that way, too (https://github.com/llvm/llvm-project/blob/main/libcxx/LICENS...)
If I recall correctly from the mailing list when this was first proposed, someone had a use case for custom libc but extending it to a general purpose libc diminished properties that would distinguish it from (e.g.) musl-libc.
Edited to include the link to Scudo: https://github.com/llvm/llvm-project/tree/main/compiler-rt/l...
https://twitter.com/chandlerc1024/status/1464530620416073735
(link to paper as well as code in that tweet).
This point sticks out. Would be nice to get some more details why it would make sense to use C++ for the implementation instead of C.
https://devblogs.microsoft.com/cppblog/the-great-c-runtime-c...
Microsoft has done the same with their new C runtime, and they have written a couple of blog posts exactly about that subject.
From "The Great C Runtime (CRT) Refactoring"
> So, as part of this great refactoring of the CRT, we have done an enormous amount of work to simplify and improve the quality of the code, so that it is easier to add features and fix bugs in the future. We have converted most of the CRT sources to compile as C++, enabling us to replace many ugly C idioms with simpler and more advanced C++ constructs. The publicly callable functions are still declared as C functions, of course (extern "C" in C++), so they can still be called from C. But internally we now take full advantage of the C++ language and its many useful features.
-- https://devblogs.microsoft.com/cppblog/the-great-c-runtime-c...
"C Runtime (CRT) Features, Fixes, and Breaking Changes in Visual Studio 14 CTP1"
https://devblogs.microsoft.com/cppblog/c-runtime-crt-feature...
"Introducing the Universal CRT"
https://devblogs.microsoft.com/cppblog/introducing-the-unive...
I found this internal file that forms the basis of all the atoi and strol family functions. Seems like they do get some nice wins from the C++ language, without needing (e.g.) STL: https://github.com/llvm/llvm-project/blob/main/libc/src/__su...
Merged in 2019-08, and hasn't been edited since.
As linked elsewhere in the thread, https://github.com/llvm/llvm-project/tree/main/libc indicates it's alive and well.
This sounds nice for being able to use newer C/C++ library functions when targeting an older system libc by statically linking the llvm-libc implementation of the missing functions.
There is a bunch of Redox ports of C programs, so it is apparently good enough for a range of software. https://gitlab.redox-os.org/redox-os/cookbook/-/tree/master/...
but take advantage and use C++ language facilities for the core implementation.