The horror, I would try to statically link EVERYTHING. At least the syscalls are stable.
Yep, I just use musl libc and static link everything into the binary. Simpler than all the effort here to use a libc designed to be static linked.. Just need to make sure the kernels you run on for threaded stuff is recent enough, iirc 2.6.16-19ish is when those stabilized. But for most stuff its unlikely to matter.
Irony is the binaries are smaller than the glibc binaries linked against libc. glibc is not my favorite libc.
Unfortunately that doesn’t work for games, you can’t statically link things like X/libGL/ALSA.
There’s a blogpost about building bins that only use the system dlopen/dlsym but that seems like a hassle. If you use GLFW and want to try it out you’ll need to modify it to use dlopened X (GLFW did change to do this for many parts of X quite recently), not sure about SDL. On the bright side there are already free tools to generate the dlopen/dlsym mess for OpenGL (glad is the best one), and the code to dlopen ALSA is pretty short.
I assume the glibc dynamic linker is too massive and annoying to statically link, and the musl one can’t load glibc libraries so is useless in practice, so for now you can’t do anything about the libdl dependency. (Now I have the go ahead from my boss to sell my hobby projects, I wonder if people would pay for a solution to this?)
The author of this blog post is a gamedev working on dhewm3 (Doom 3 port) and yquake2 (Quake 2 port). The post itself touches on SDL, OpenGL and X/Wayland. I might be not seeing something but what makes you believe the article can’t be applied to games (I believe the author did this work to build one of the doom/quake ports that way - but I’m only guessing here).
I’m responding to ac, not the article!
My point is that you can’t statically link everything, you have to dynamically load certain things, and to do that you have to dynamically load the dynamic loader.
For dhewm3 and yq2 this is no problem: It’s open source and we don’t provide Linux binaries ourselves (and if we did an old compiler should work just fine).
I’ve needed this for a commercial closed source game that uses some C++11 features and can’t be built with GCC 4.7
(I’m the author of the blog post)
You’re right, statically linking is no option for games (and probably not for anything else that needs to interact with X11 or Wayland).
Also note that glibc is not the problem here - usually linking against an old version of it works just fine, and if you want to optionally use a more recent feature, you can still dlsym() it. (It’s annoying that it’s not easy to just point the compiler/linker to a glibc version to use, but that it uses the system version instead - however using a chroot for building release binaries is workable).
The problems are mostly libstdc++ and libgcc (though maybe that one can actually be statically linked, not sure).
This is because some systemlibs you need to interact with (at least libGL) use libstdc++, and if you statically link a different version than the one on the users system, things explode. Same problem if you just bundle and unconditionally use (e.g. via rpath $ORIGIN) a version of libstdc++ and the libGL (or whatever other lib) needs a newer version than the one you bundled.
Of course all this is detailed in the article.. :-P
By the way, SDL2 indeed uses dlopen() and dlsym() to interact with most system libs (especially the display and audio specific ones, probably not glibc..). This is pretty awesome: The same libSDL2-2.0.so.0 can support X11 and wayland, and so can your game executable (unless you do X11 specific stuff in addition to what SDL2 offers).
That’s what I do using MUSL. Seems to work great.
All of this pain is one big reason why Docker is so popular. It’s so much easier to distribute one Docker image with my binaries than to distribute dozens of distro- and release-specific binaries.