Alexander Gromnitsky's Blog<br>:: 2026-06-13<br>:: Linux Apps That Maybe Run
Linux Apps That Maybe Run
Latest update: 2026-06-16 20:13:26
According to some prominent fellows, whom I won't name to protect the<br>guilty, the only viable way to distribute software for Linux is to<br>ship a container. Not to make an rpm/deb & serve it from a repo, like<br>some insignificant companies that control half of the Internet do, but<br>to collect all (or most) dependencies & put them alongside the<br>application. Only this way, experts say, guarantees a high probability<br>of surviving in the Linux wilderness.
Another set of leading figures argue that shipping a container is<br>necessary but not sufficient: in the days of rogue AI agents &<br>catastrophic vulnerabilities hiding in every software corner, an<br>application should (some insists on the word must) be incapable of<br>doing anything without the user's permission.
I thought about that a little, & came to the conclusion that a<br>layperson couldn't care less. I'm not talking about a guy who feels<br>personally offended when an ntp client dares to send a udp packet<br>without asking first, I'm talking about an individual who downloads an<br>"app" not to enjoy perusing a granular permission model, but to<br>accomplish a task.
I noticed how not a few Windows developers are at a loss to what to make<br>of Linux software distribution models. This post is for them.
Not a GUI
Theoretically, if you write simple network microservices, you can<br>abandon all 3rd-party libraries, even libc itself, & stick to syscalls<br>of the Linux kernel ABI. As long as Linus is in charge, your programs<br>will always work.
Out of curiosity, I once tried to write a simple nolibc TCP server &<br>described the<br>experience. (For<br>convenience, the text is in Ukrainian.)
Now, let's get back to real life.
DLLs & sonames
In the Linux world a DLL is called a shared library. A plain stock<br>Fedora Live ISO with no developer tools installed, contains thousands<br>(3977 in f44) of them.
The 2 major Linux GUI toolkits (GTK & Qt) use a multitude of 3rd-party<br>shared libraries that they don't control, & when you link against a<br>GUI library in a particular distro, there is 0 guarantees that your<br>program will work in the next distro release. Even if the shared<br>libraries of the GUI toolkit stay the same, some transitive dependency<br>may acquire a soname bump, & a dynamic linker will refuse to run<br>your program.
A shared library named foo has actually several names, that look<br>different to various library consumers:
you use -lfoo argument when you invoke a linker to link your<br>program against the foo library;
during that building step, the linker searches for libfoo.so file<br>(in a set of known directories);
while the source code of the library could live across many files of<br>arbitrary names, a build step that produces the library itself, puts<br>the result in libfoo.so.x.y.z file.
when you invoke your program, the dynamic linker searches for<br>libfoo.so.x file (in a set of known directories).
The last name, libfoo.so.x, e.g., libfoo.so.3, is called the<br>soname, & contains the major version number. Thus, the infamous<br>soname bump means an increment of that number, due to incompatible<br>changes in ABI. As soon as it happens, you're required to rebuild your<br>program. On certain occasions you may cheat, symlinking libfoo.so.3<br>to a new libfoo.so.4, but no user does that, your application just<br>stops working after an OS update.
Here is an example for giflib package on Fedora. As usual, to<br>irritate newcomers, the library is split between 2 packages:
$ rpm -ql giflib giflib-devel | grep .so | xargs stat -c %N<br>'/usr/lib64/libgif.so.7' -> 'libgif.so.7.1.0'<br>'/usr/lib64/libgif.so.7.1.0'<br>'/usr/lib64/libgif.so' -> 'libgif.so.7'
$ objdump -p /usr/lib64/libgif.so.7.1.0 | grep -i soname<br>SONAME libgif.so.7
The program ld.so (the dynamic linker, at the time of writing<br>/lib64/ld-linux-x86-64.so.2) looks for libgif.so.7. A linker,<br>during a build step, uses libgif.so (no version number). The latter<br>file is absent in the user-faced giflib package.
Living on the edge
If you listen to proponents of assorted form of containerisation long<br>enough, you may think that soname bumps (or other events of ruinous<br>nature) happen every week. In reality, even rather old versions of<br>fairly complex programs like Google Chrome, despite being designed to<br>be updated daily, run ~fine on current Linux.
E.g., I fished out a .deb variant of Chrome 71 (Dec of 2018), unpacked<br>it & successfully ran1 the ancient browser on Fedora 44. It<br>was linked against GTK3 (modern Chrome doesn't use GTK), a toolkit<br>that any distro will continue to ship for at least 20 years.
Not all applications are that lucky, though. If you have a program<br>compiled during the forgotten v1.0.x OpenSSL years, chances that a<br>regular user would have skills to find (or more precisely, bother to<br>look for, unless extremely motivated) a compatible .so file is<br>practically nil.
Here comes a point, where 2 schools of thought appear:
You rely on...