2 min read
Linux Application Distribution

I think the best way to package an application on Linux is as a statically linked single executable.

However, not all libraries are suitable for static linking. For example, glibc. Even if you force glibc to be statically linked, some operations will still load dynamic libraries through dlopen, which means there will be two versions of glibc in the process’s address space.

So, sometimes you have to use dynamic linking, but only for very basic libraries like glibc. For everything else, it’s better to use static libraries.

Not all applications stick to only dynamically linking these basic libraries, though. Updating the build method for different kinds of applications can be inconvenient. When this happens, I usually follow what Python C extensions do.

When distributing Python wheels, we typically use auditwheel to copy the necessary dynamic libraries into a separate folder and then use patchelf to update the RPATH.

Another common issue is glibc compatibility. If you build an application on a system with a newer version of glibc, it will link to the newer symbols, which means it won’t run on systems with an older version of glibc. The solution is pretty straightforward: just build the application on an older system, like Ubuntu 16.04.