The content of the article
Many Linux users prefer to install programs from repositories using the built-in package manager, and all other methods are considered as a necessary measure. However, the developers of distributions, obviously, cannot include in the repositories all the programs in the world, and the authors of the programs themselves also cannot or want to support packages for many distributions and their versions.
In recent years, distribution-agnostic package installation solutions have been gaining popularity, with the long-standing addition of the newer Flatpak and Snap to 0install, and more Linux games on Steam.
It may be most convenient to do without installation at all – just download the file, make it executable using
chmod +x and run. In this article, we'll look at why this is possible and how to implement it.
Binary compatibility on Linux based systems
You often hear that Linux is bad for binary compatibility. In this case, people mean that a package from one version of a Linux distribution can sometimes not be installed on another, and in this they are right. However, the very statement about poor binary compatibility of Linux versions is incorrect.
Remember that Linux is only the kernel, and the entire operating system consists of the kernel, shared libraries and programs. Libraries can be divided into standard language libraries (eg libc, libstd ++) and third party libraries (eg GTK, Qt). So, as a rule, third-party libraries are the cause of broken binary compatibility.
ABI boundaries, that is, places where something might break, depend on the linking method: static or dynamic.
With dynamic linking, the ABI of all involved libraries must remain stable. However, the kernel ABI can change if the libraries compensate for this. With static linking, only the stability of the kernel ABI is important. Let's see how with this in Linux.
The ABI of a library is the set of symbols that it exports. Can it be stable? Yes, format implementation ELF on Linux supports character versioning… With this mechanism, libraries can provide multiple versions of the same function with different signatures and behavior.
The obvious drawback of this approach is that it is impossible to remove old code from the library without risking breaking compatibility. Every time the signature or behavior of a function changes, the author must create a copy of the old function. Also, specify the correspondence of the function names in the source code and the symbol versions of these functions in binary – developer duty…
Not every developer has the time and ability to maintain compatibility this way. In addition, radical changes to the internals of the library can make this approach completely impractical – you will, in fact, have to compile one binary file from several versions of the source code.
It is precisely because of the idea of making as many libraries as possible common to all packages that we cannot put a package from Debian 9 to 10 or from CentOS 6 to 8 – third-party libraries are not included in the package, and their ABI does not remain the same between versions.
However, the GNU libc developers take compatibility seriously and version all symbols. Because of this, if you build a program on a machine with an older version of glibc, it will work with newer ones (but not vice versa).
Kernel version compatibility
The kernel ABI represents the system call convention and the argument numbers and ordering of individual calls. For example, to ask the kernel to execute
write – a system call to write data to a file, you need to put the number of this call in one register of the processor, and the number of the file descriptor, a pointer to the data buffer and the size of the data in bytes in the other three registers. Any function for writing to a file or displaying text on the screen (that is, writing to files stdout and stderr with descriptors 1 and 2, respectively) is a wrapper around this call.
The lowest level of the standard library of any language is a set of wrappers for system calls. If the kernel ABI changes, all libraries will stop working. Fortunately, this doesn't happen on Linux — the system call interface is extremely stable. Linus Torvalds strictly enforces compatibility and swears anyone who tries to break it by accident or intentionally.
Thanks to this policy, any program from the 2.6 kernel will work fine on 5.x as long as it does not use any shared libraries.
Moreover, new programs can run on older kernels if they only use old system calls.
What about other systems?
Of the common free Unix-like systems, Linux is the only one with such kernel ABI compatibility guarantees.
That is why there are many alternative standard C libraries for Linux (musl, dietlibc, uclibc, newlib …). For the same reason, FreeBSD implements binary compatibility with Linux, but not vice versa – FreeBSD does not guarantee ABI stability between releases.
GNU libc's symbol versioning support is also atypical for standard library implementations.
Thus, there are more possibilities for binary compatibility in Linux than in many other systems – you just need to use them.
From all that has been said, it is clear that static assembly is a guarantee of compatibility with any Linux-based system, and with both newer kernels and older ones.
An alternative approach is AppImage also allows you to collect everything into one file, but this file is actually a compressed SquashFS image with an executable file and dynamic libraries inside. Alas, the tools for automatic search and packaging of all the necessary libraries are capricious, and a detailed consideration of this approach will not fit into the scope of our article. We will focus on static linking.
As an example, we will use a simple program that checks whether a string matches a regular expression. We'll put it together in a few different ways and see how to make sure the file comes out really static.
Continuation is available only to participants
Materials from the latest issues become available separately only two months after publication. To continue reading, you must become a member of the "Xakep.ru" community.
Join the Xakep.ru community!
Membership in the community during the specified period will open you access to ALL Hacker materials, increase your personal cumulative discount and allow you to accumulate a professional Xakep Score!
I am already a member of "Xakep.ru"