Hacker News new | ask | show | jobs
by gwmnxnp_516a 1824 days ago
It is possible to support a wide range of Linux distributions if one takes proper care such as: use CMake and never use GNU autotools or GNU Make as CMake has the best IDE support among C++ building systems; static link as much as possible avoiding reliance on the package manager for getting dependencies; set RPATH as relative path to executable in CMake building system for dependencies that cannot be statically linked; locate resource files using the relative path to the executable instead of relying on fixed path such as /usr/local, /usr/share, /etc/, ...; distributed the executable and the shared libraries in a zip or tar.gz archive with .desktop file containing an icon, so that the user can launch the application just clicking on it. Most MacOSX applications are already distributed in this way in the app-bundle format a, directory ending with suffix .app, containing, a p-list xml metadata, shared libraries and data. The app bundles can be installed just by dragging and dropping without worrying about dependency hell, enabling root permission and so on. The Linux fragmentation could decrease if Linux distros adopted a MacOSX-like standardized app-bundle format.

The last point of failure is the GlibC (GNU C library), a Linux application, even if fully statically linked against all dependencies or packaged with all shared libraries, may fail to run in another Linux distribution if it is using an older version of the GlibC than the one that the executable was linked against. Therefore, in order to ensure that the application can work in the broadest range of distributions, it is necessary to static link the application against the oldest possible version of GlibC or build the application on the LTS (Long Term Support) version of the supported distribution.

If one does not have enough resources to support Linux, an alternative approach, assuming that is OpenGL is used, may be building the executable for Windows and Wine using MinGW compiler either on Windows or by cross-compiling on Linux using Dockercross-mingw (https://github.com/dockcross/dockcross). At least with Wine, one will not have to deal with Glib-C compatibility issues.

3 comments

> The Linux fragmentation could decrease if Linux distros adopted a MacOSX-like standardized app-bundle format.

Everyone decided this so we got 3 different "standard" formats... (Snap, Flatpak, and AppImage). See: that XKCD about standards.

And macOS has apps that install with .pkg, .app bundles, .dmg, homegrown installers based on shell scripts, zipped archives...

And windows has .msi, whatever is used to install windows store packages, NSIS, Inno Setup...

it's a way overblown complaint. I use AppImages built on centos 7 for my own stuff and never heard anyone having issues with it.

Yep, but the installation is far simpler than the procedure for installing a Linux application not available at repositories or an application that uses unstable libraries likely to change the ABI. All one needs to install an MacOSX app-bundle is to drag and drop the .app folder or .dmg disk image to /Applications. MacOSX reads the plist metadata and finds the icon and the executable path, then renders the icon making easier and intuitive for non technical users to just click and run the application.

On Windows is easier to build self-contained applications as there is no the RPATH issue. All one needs to build a self-contained application that is easier to ship and works everywhere is just add shared libraries at the same directory where is the executable and create a zip archive or a MSI installer. When applications are installed, they are installed in a single folder and files are not scattered across the file systems like binaries in /usr/bin, /usr/local/bin, /libs/, /usr/shared, ..., as in Linux and other unices.

Here's an issue with AppImages: they don't work with musl. Makes me sad.
I mean, targetting musl means pretty much using a different operating system than GNU/Linux. The ELF linking semantics pretty much enforce that you're using the same libc implementation for your whole program.

That's like complaining that, say, a program built against cygwin on windows, can't work on a system without the cygwin dll (and all its dependencies also compiled against the cygwin dll).

Well the problem of Snaps is complex sandbox, lack of user control, forced updates and so on which is disliked on many non-Ubuntu distributions.

Flatpack attempts to solve the dependency hell problem by providing standard runtime, a set of libraries, Glib-C, Gtk or Qt with a fixed version which requires the developer to build an application linking against those runtime, which avoid binary compatibility problems and dependency hell. The trouble of Flatpacks is the integration with the desktop.

AppImage attempts to solve the dependency hell by bundling everything into a single launcher executable with a SquashFs file system image payload. The disadvantage of this approach is that it is only possible to use a single executable. AppImage are also not free from GlibC compatibility issues.

A MacOSx-like app bundle and a changing in Linux development culture to build and design applications as self-contained from inception would strength the Linux desktop and reduce the application packaging work duplication that still affects Linux distributions.

Aren't Linux syscalls backward-compatible? So can't you just static-link your own libc clone (like MUSL or whatever)? (Can't staticaly-link normal libc due to licensing, IIRC)
The system calls are documented and backward compatible. However, Glib-C is only forward compatible, but not forward compatible. An application, built linking against an older version of Glibc than the one found at the deployment machine, is pretty likely to work on this machine, whereas the other way around will result on a linking error.

By using MUSL it is possible to build fully statically linked applications that works everywhere, however dlopen(), dlclose() calls, that are used for loading shared libraries and plugin at runtime on Unix-like systems, do not work with MUSL.

Glibc is LGPL, which makes some exceptions for system libraries, which glibc would fall under. It's been a while since I've read it and IANAL, so I'm not sure what exactly would be allowed.

The bigger problem is that glibc cannot be statically linked properly. It dlopen's some libraries, like for NSS. Maybe games could avoid triggering those cases but musl is definitely better.

While syscalls themselves are backward-compatible (even for faulty behavior), I think I've read somewhere that some parts of DRI are not, but I've lost the source on that.

The bigger problem is that for games you will to interface with OpenGL/Vulkan and probalbly Pulse/ALSA and those are all shared libraries which you cannot use from a completely static executable.
And this still leaves you open to issues with the absolute myriad of driver issues that exist.