README.md 33.7 KB
Newer Older
probonopd's avatar
probonopd committed
1 2
![issues](/uploads/b13b76420d9b982cd08b9cd649ebabfd/issues.png)

probonopd's avatar
probonopd committed
3
### [Download All Systems Go! 2018 slides (PDF)](https://transfer.sh/vkSwL/2018_ASGConf_Desktop_Linux_Platform_Issues_v1.odp.pdf)
probonopd's avatar
probonopd committed
4

5 6 7 8
### [Watch the talk at All Systems Go! 2018 conference (Video)](https://media.ccc.de/v/ASG2018-174-2018_desktop_linux_platform_issues#)

### [Listen to the talk at All Systems Go! 2018 conference (Audio)](https://media.ccc.de/v/ASG2018-174-2018_desktop_linux_platform_issues/audio)

probonopd's avatar
probonopd committed
9 10
Listen to Linus Torvalds: https://www.youtube.com/watch?v=5PmHRSeA2c8&t=5m57s

probonopd's avatar
probonopd committed
11
TL;DR: Stop making "Desktop Linux" a _moving target_ by agreeing on a minimal baseline that third-party application can _take for granted_ to exist on each Desktop Linux system.
probonopd's avatar
probonopd committed
12 13 14 15 16

To make "Desktop Linux" a viable platform (as in: Windows, macOS) to develop against, we need to insist on [backward compatibility](https://abi-laboratory.pro/index.php?view=binary-compatibility) and either need to find the "least common denominator" by experimentation (as we have done for over a decade now), or get the main Linux distributions (Ubuntu, Fedora, openSUSE, Debian, etc.) to agree on a certain set of infrastructure that can be expected to be "there", in a consistant way, without unnecessary differences.

__TL;DR:__ A guaranteed minimal set of infrastructure (available in the default installation of all distributions) with guaranteed backward compatibility is required for "Desktop Linux" to become viable as a platform.

17
Your thoughts are highly welcome. Please join the discussion [here](https://gitlab.com/probono/platformissues/issues). However, __please do not make substantial edits to this page before reaching consensus in the discussion on https://gitlab.com/probono/platformissues/issues.__
probonopd's avatar
probonopd committed
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

![](https://c1.staticflickr.com/9/8704/16793281720_49418bc05d.jpg)

Credit: [MuseScore (CC BY 2.0)](https://www.flickr.com/photos/musescore/16793281720)

openSUSE Chairman Richard Brown pointed out the need for this in a [talk](https://speakerdeck.com/sysrich/opensuse-conference-2017-the-t-rex-was-the-hero-of-jurassic-park) at openSUSE Conference 2017:

![](https://speakerd.s3.amazonaws.com/presentations/bd181e22b0f9417f983c600747c1b708/slide_50.jpg)

This is not to say that the "least common denominator" approach does not work. In fact, the arguably two most successful "Desktop Linux" applications, LibreOffice and Firefox, are built on old build systems and bundle many libraries in order to be able to deliver one set of binaries to (almost) all "Desktop Linux" systems, independent of distributions, and have been doing this for quite some time now. But given some sane platform decisions, life could be made much easier for application developers who want to target the "Desktop Linux" platform.

This page is here to collect ideas on what would be worthwhile to standardize on. It is meant as a basis to get the discussion started rather than finalized recommendations. You are welcome to edit this page to add factual information, but  if you fundamentally disagree with the direction of this page please [talk to us first](https://github.com/AppImage/AppImageKit/wiki/Chat) before editing this page.

## Kernel

In the over a decade experience with application bundles the kernel has proven never to be an issue, since the interface between the kernel and userland is stable, and Linus Torvalds is heavily defending a stable userland interface. So no action required as far as AppImage is concerned. Applications should ensure they can run on a vanilla kernel without extra patches.

## Paths

### Library filenames

The names of libraries should reflect the version as given by upstream. Currently it is not, resulting in the necessity for each application using it to bundle a private version, since the application cannot rely on the system-provided one. 

Example:
* Ubuntu 12.04 has `libarchive.so.12` desipte it being version 3.x
* Ubuntu 14.04 has `libarchive.so.13` desipte it being version 3.x

This should be changed so that every distribution that carries any version of libarchive version 3.x would contain `libarchive.so.3.xxx` and a symlink to `libarchive.so.3`, so that applications could rely on being able to link against `libarchive.so.3`.
 
The libarchive upstream developers say they can do nothing about this since the library filename is decided by distributions.

> We might be able to make the number more consistent across platforms, but it would require someone to do the research into how cmake and autoconf generate build numbers on the many different platforms.

References:
* https://github.com/libarchive/libarchive/issues/817
* https://abi-laboratory.pro/tracker/timeline/libarchive/

Other example:
* Mageia has `/usr/lib/pulseaudio/libpulsecommon-10.0.so`
* App wants `libpulsecommon-4.0.so`

### Library paths

Aleksei Kovura's avatar
Aleksei Kovura committed
61
Despite there being the FHS, filesystem paths are different on different distributions for no apparent reason. They should be standardized between all distributions.
probonopd's avatar
probonopd committed
62 63 64 65 66 67 68 69 70 71 72 73 74

Example:
* Debian, Ubuntu: `/lib/i386-linux-gnu/`, `/lib/x86_64-linux-gnu/`
* openSUSE: `/lib/`, `/lib64/`

References:
* https://wiki.debian.org/Multiarch

### Certificates

Should be installed to a standard location that is the same in all distributions. Currently this is not the case and where certificates go is apparently entirely random by distribution, as of mid-2017:

```
probonopd's avatar
probonopd committed
75 76 77 78 79 80 81 82 83
"/etc/ssl/certs/ca-certificates.crt",                // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt",                  // Fedora/RHEL
"/etc/ssl/ca-bundle.pem",                            // OpenSUSE
"/etc/pki/tls/cacert.pem",                           // OpenELEC
"/etc/ssl/certs",                                    // SLES10/SLES11, https://golang.org/issue/12139
"/usr/share/ca-certs/.prebuilt-store/",              // Clear Linux OS; https://github.com/knapsu/plex-media-player-appimage/issues/17#issuecomment-437710032
"/system/etc/security/cacerts",                      // Android
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
"/etc/ssl/cert.pem",                                 // Alpine Linux
probonopd's avatar
probonopd committed
84 85 86 87 88 89 90 91
```
Source: https://serverfault.com/questions/62496/ssl-certificate-location-on-unix-linux

The result is that if we bundle something like `libgnutls`, then it fails to find the certificates if the target system happens to store them in a different place. 

Workaround:
Patch whatever consumes certificates (e.g., `libgnutls`) to look in all known places. Example: https://github.com/darealshinji/vlc-AppImage/issues/1#issuecomment-321041496

probonopd's avatar
probonopd committed
92 93 94 95 96 97 98
Update: Can `SSL_CERT_FILE` and/or `SSL_CERT_DIR` be used to point to the location of the certificates?

According to [the documentation](https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set_default_verify_paths.html),

> Alternatively the `SSL_CERT_DIR` environment variable can be defined to override this location. The default CA certificates file is called `cert.pem` in the default OpenSSL directory. Alternatively the `SSL_CERT_FILE` environment variable can be defined to override this location.

In this case, we would need to check all possible locations where the different distributions tend to place those files, and then export the one where they have actually be found, prior to launching the payload executable.
99

probonopd's avatar
probonopd committed
100
More information:
101
* https://www.happyassassin.net/2015/01/12/a-note-about-ssltls-trusted-certificate-stores-and-platforms/
probonopd's avatar
probonopd committed
102
* https://github.com/openssl/openssl/issues/7481#issuecomment-583719914 (`SSL_CERT_FILE` and `SSL_CERT_DIR`)
probonopd's avatar
probonopd committed
103

probonopd's avatar
probonopd committed
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
## Basic libraries

Applications should be able to rely on certain basic infrastructure libraries to be provided by all distributions in the default installation. They should be standardized between all distributions.

### glibc

Ideally this library would be frozen indefinitely. Why is it necessary to still keep adding symbols to it, making software compiled against later versions fail on earlier versions? If freezing this is not realistic, then at least build systems should use older versions than what is available in the oldest still-supported available distributions, and the library should be only very infrequently and only if there are severe reasons that really require an update. Applications written against earlier versions of these should be guaranteed to still run with later versions of these.

* ld-linux.so.2
* ld-linux-x86-64.so.2
* libanl.so.1
* libBrokenLocale.so.1
* libcidn.so.1
* libcrypt.so.1
* libc.so.6
* libdl.so.2
* libm.so.6
* libmvec.so.1
* libnsl.so.1
* libnss_compat.so.2
* libnss_db.so.2
* libnss_dns.so.2
* libnss_files.so.2
* libnss_hesiod.so.2
* libnss_nisplus.so.2
* libnss_nis.so.2
* libpthread.so.0
* libresolv.so.2
* librt.so.1
* libthread_db.so.1
* libutil.so.1

These files are all part of the GNU C Library which should never be bundled. List was generated from a fresh build of glibc 2.25.

References:
https://www.gnu.org/software/libc/

But seemingly not all distribution can even seem to agree what is part of glibc and can be taken for granted, vs. what is not. As this example shows:

`libnsl.so.1` is part of `glibc` (and hence can be assumed to be "just there") in Fedora 27 but not in Fedora 28!


`libnsl.so.1` is part of `glibc` in Fedora 27:

```
podman run -it fedora:27 /bin/bash                                                                
[[email protected] /]# dnf provides libnsl.so.1
Fedora 27 - x86_64 - Updates                                                    992 kB/s |  24 MB     00:24    
Fedora 27 - x86_64                                                               19 MB/s |  58 MB     00:03    
Last metadata expiration check: 0:00:18 ago on Tue Jun  5 21:02:14 2018.
glibc-2.26-28.fc27.i686 : The GNU libc libraries
Repo        : updates
Matched from:
Provide    : libnsl.so.1
```

`libnsl.so.1` is __not__ part of `glibc` in Fedora 28 (and hence we cannot be sure that it will be installed by default on _every_ Fedora 28 system):

```
glibc-2.26-15.fc27.i686 : The GNU libc libraries
Repo        : fedora
Matched from:
Provide    : libnsl.so.1
podman run -it fedora:28 /bin/bash
[[email protected] /]# dnf provides libnsl.so.1
Fedora 28 - x86_64 - Updates                                                     11 MB/s |  14 MB     00:01    
Fedora 28 - x86_64                                                               29 MB/s |  60 MB     00:02    
Last metadata expiration check: 0:00:04 ago on Tue Jun  5 21:02:31 2018.
libnsl-2.27-15.fc28.i686 : Legacy support library for NIS
Repo        : updates
Matched from:
Provide    : libnsl.so.1

libnsl-2.27-8.fc28.i686 : Legacy support library for NIS
Repo        : fedora
Matched from:
Provide    : libnsl.so.1
```

Distributions should agree on what is part of the GNU C Library and can be taken for granted, vs. what is not. Distributions should not make parts of what could be taken for granted optional (and, as a result, missing from e.g., Fedora 28 Atomic Workstation) all of a sudden.

### libstdc++.so.6

Ideally this library would be frozen indefinitely. Why is it necessary to still keep adding symbols to it, making software compiled against later versions fail on earlier versions? If freezing this is not realistic, then at least build systems should use older versions than what is available in the oldest still-supported available distributions, and the library should be only very infrequently and only if there are severe reasons that really require an update. Applications written against earlier versions of it should be guaranteed to still run with later versions of this.

* libstdc++.so.6

References:
https://gcc.gnu.org/wiki/Libstdc++

### OpenSSL

This should be abstracted in a way so that software compiled against OpenSSL would work against whatever version of OpenSSL comes with the system. Currently software compiled against a certain "letter" version (e.g., "f", "l") of OpenSSL will fail when another version of OpenSSL is available on the system. Applications written against earlier versions of it should be guaranteed to still run with later versions of this.

Take Firefox, for example. Mozilla distributes binaries that are supposed to run on most systems. If they cannot trust that whatever OpenSSL is in the operating system will continue to work, they are essentially forced to bundle a private copy, which means that a) there is more duplication, eating more system resources b) Firefox will not benefit from security updates in OpenSSL that the operating system might do. Same for Chrome and any other application that a) uses OpenSSL and b) is distributed outside of the Linux distribution.

Currently applications cannot rely on these:
* libssl.so.1
* libssl.so.1.0.0
* libcrypto.so.1
* libcrypto.so.1.0.0

They should be standardized across all distributions. Then applications could rely on these from the system rather than having to privately bundle their own copies.

References:
* https://github.com/probonopd/AppImages/commit/6c7473d8cdaaa2572248dcc53d7f617a577ade6b
* http://stackoverflow.com/questions/32644157/forcing-a-binary-to-use-a-specific-newer-version-of-a-shared-library-so
* https://abi-laboratory.pro/tracker/timeline/openssl/

According to https://twitter.com/Det_Conan_Kudo/status/896508995044880384 OpenSSL, the upstream project "bumps the soname on every version release". According to the source, "Downstream, we fix this. This provides the added value of literally being able to upgrade OpenSSL in a relatively safe way without busting the world in the process".

Especially worrisome: upstream seems to be fully aware that going from 1.0 to 1.1 they broke applications compiled for 1.0, yet they don't seem to care: https://wiki.openssl.org/index.php/OpenSSL_1.1.0_Changes#No_longer_works. Newer versions of openSSL (or any library for that matter) _should never break applications compiled against older versions_ - at least within the same major version of the library.

Looking at the [Qt source code](https://github.com/qt/qtbase/blob/50deb8cf70f61e21fb0c35182341477af11adbc1/src/network/ssl/qsslsocket_openssl_symbols.cpp#L745-L765) confirms that there are issues:

>  // (...) OpenSSL is a well-known case of binary-compatibility breakage. To
// avoid such problems, many system integrators and Linux distributions change
// the soname of the binary, letting the full version number be the soname. So
// we'll find libssl.so.0.9.7, libssl.so.0.9.8, etc. in the system. For that
// reason, we will search a few common paths (see findAllLibSsl() above) in hopes
// we find one that works.

### libgnutls

An application compiled against `libgnutls26` should continue to work on systems that are using subsequent versions, such as `libgnutls28` and `libgnutls30`. Possibly the versioning scheme of libgnutls would have to be changed for this, with new major versions (with ABI-breaking changes) coming out as rarely as possible (every 5-7 years or less frequently), and distributions should carry not only the recent version but also the version before to give sufficient time to developers to update.

Currently it looks like `libgnutls26`, `libgnutls28` and `libgnutls30` are all in use and not compatible.

### Kerberos

The following libraries currently cannot be safely assumed to be part of every distribution:
* libkrb5.so.26
* libkrb5.so.3
* libkrb5support.so.0

Distributions should agree on `libkrb.so.5` being the name for Kerberos 5. Then applications could rely on these from the system rather than having to privately bundle their own copies.

Workaround:
Patch `libcurl` so that it does not need Kerberos. https://github.com/AppImage/AppImages/blob/c9e6b6b365fcd97e2980c0844c478904c030a25a/recipes/meta/Recipe#L194

### X11 libraries, Xlib, XCB

X11 libraries, Xlib, and the X protocol C-language Binding (XCB) should be handled by the distribution and they should provide a clearly defined interface for applications to develop against. Build systems should use older versions than what is available in the oldest still-supported available distributions. Applications written against earlier versions of these should be guaranteed to still run with later versions of these.

* libX11.so.6 (uncertain if really all distributions bundle it)
* libxcb.so.1 (uncertain if really all distributions bundle it)
* libxcb-dri3.so.0 (uncertain if really all distributions bundle it)
* libSM.so.6
* libXp.so.6 (currently not available on Fedora default installations)
* Many other libX...

### OpenGL and Direct Rendering Manager (DRM)

OpenGL and the and Direct Rendering Manager (DRM) should be handled by the distribution and they should provide a clearly defined interface for applications to develop against. Build systems should use older versions than what is available in the oldest still-supported available distributions. Applications written against earlier versions of these should be guaranteed to still run with later versions of these.

* libGL.so.1
* libdrm.so.2

probonopd's avatar
probonopd committed
262 263 264
libglvnd is a vendor-neutral dispatch layer for arbitrating OpenGL API calls between multiple vendors. It allows multiple drivers from different vendors to coexist on the same filesystem, and determines which vendor to dispatch each API call to at runtime.
How does it play into this?

probonopd's avatar
probonopd committed
265 266
References:
* https://dri.freedesktop.org/wiki/DRM/
probonopd's avatar
probonopd committed
267
* https://github.com/NVIDIA/libglvnd
probonopd's avatar
probonopd committed
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302

### ALSA and PulseAudio

Sound should be handled by the distribution and they should provide a clearly defined interface for applications to develop against. Build systems should use older versions than what is available in the oldest still-supported available distributions. Applications written against earlier versions of these should be guaranteed to still run with later versions of these.

* libasound.so.2
* PulseAudio libraries (tbd)

Example:
* Mageia has `/usr/lib/pulseaudio/libpulsecommon-10.0.so`
* App wants `libpulsecommon-4.0.so`

### Gtk+ and Gdk

Gtk+ and Gdk should be handled by the distribution and they should provide a clearly defined interface for applications to develop against. Build systems should use older versions than what is available in the oldest still-supported available distributions. Applications written against earlier versions of these should be guaranteed to still run with later versions of these.

Ideally, there would be a defined library to develop against, e.g., `libgtk.so.2` for Gtk+2 and `libgtk.so.3` and applications would be compiled against those instead of a multitude of individual libraries that make up "Gtk+".

Example:
* libgdk_pixbuf-2.0.so.0
* Many more (are they defined somewhere)


#### Versioning scheme

GTK+ should follow [semver](http://semver.org).

According to https://blog.gtk.org/2016/09/01/versioning-and-long-term-stability-promise-in-gtk/, "Updates within long-term stable series will be ABI stable". This is good, but in order to minimize developer confusion about which GTK+ version can be relied on, only such long-term stable series should get major version numbers.

nkiesel nails it in https://lwn.net/Articles/691131/

> However, there is the psychological problem of such applications always using the "previous" release. So innocent bystanders will see "GTK 5.0 released with all those new cool features", followed by "app FOO upgraded from GTK 3 to GTK 4". Therefore, GTK should make it very clear in it's press release that GTK 5.0 is just the _first release candidate_ of GTK 5 and not intended to be used by external applications.

In this example, I would propose "GTK 5" to be called that only after it has a stable API and _should_ be used by external applications. This would be more in line with the idea of a sane, dependable platform to build on. Everything that is still a moving target and has no API guarantees should not be worthy of a new major version number.

probonopd's avatar
probonopd committed
303 304 305 306 307 308 309 310 311 312
Real-world example at https://github.com/solvespace/solvespace/issues/336#issuecomment-405004990:

> this is completely broken in case of GTK, because the GTK developers do not maintain a stable ABI since version 3 (which I can only explain either with incompetence or with complete disregard to the needs of developers distributing software other than through a distribution package manager, go figure which option is worse

The Gtk+ team should have called it "3" only _after_ it had a stable ABI (i.e., when developers already work on what will eventually become "4"). Yet the Gtk+ team seems to make the same mistake of not using semantic versioning in Gtk+ 4 again, as is explained in https://blogs.gnome.org/desrt/2016/06/13/gtk-4-0-is-not-gtk-4/

> Meanwhile, Gtk 4.0 will not be the final stable API of what we would call “Gtk 4”. Each 6 months, the new release (Gtk 4.2, Gtk 4.4, Gtk 4.6) will break API and ABI vs. the release that came before it. (...) Each successive minor version will be growing toward a new stable API. Before each new “dot 0” release, the last minor release on the previous major version will be designated as this “API stable” release. For Gtk 4, for example, we will aim for this to be 4.6 (and so on for future major releases). Past this point there will not be disruptions; this “stable API” will be very stable. (...) In this way, “Gtk 4.0” is not “Gtk 4”. “Gtk 4.0” is the first raw version of what will eventually grow into “Gtk 4”, sometime around Gtk 4.6 (18 months later).

The Gtk+ team should only call 4.6 "4.0" to indicate that only once the oldest target systems (distributions) have that version by default, third-party developers can rely on it and start to use it.

probonopd's avatar
probonopd committed
313 314 315 316 317
They seem to disagree:
https://blogs.gnome.org/desrt/2016/06/14/gtk-5-0-is-not-gtk-5/

That is bad, because third-party application developers will develop against .0 versions just to then be disappointed that distribution applications built against a moving target is a nightmare.

probonopd's avatar
probonopd committed
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
### GLib

GLib should be handled by the distribution and they should provide a clearly defined interface for applications to develop against. Build systems should use older version than what is available in the oldest still-supported available distributions, and the library should be only very infrequently and only if there are severe reasons that really require an update. Applications written against earlier versions of this should be guaranteed to still run with later versions of this.

* libglib-2.0.so.0

### Fonts and font rendering

Fonts and font rendering libraries should be handled by the distribution and they should provide a clearly defined interface for applications to develop against. Build systems should use older versions than what is available in the oldest still-supported available distributions. Applications written against earlier versions of these should be guaranteed to still run with later versions of these.

* libfontconfig.so.1

These would ideally never have to be linked against directly:
* libpangoft2-1.0.so.0
* libpangocairo-1.0.so.0
* libpango-1.0.so.0
* libpangomm-1.4.so.1

With increasing frequency, we are running into `symbol lookup error: /usr/lib64/libpangoft2-1.0.so.0: undefined symbol: hb_buffer_set_cluster_level`. Why?

### HarfBuzz

Bundling HarfBuzz seems to cause `symbol lookup error: /usr/lib64/libpangoft2-1.0.so.0: undefined symbol: hb_buffer_set_cluster_level` (suggesting that the version of HarfBuzz that is being bundled is too old for the lib64/libpangoft2-1.0.so.0 on the system; which means that we need to bundle HarfBuzz then we also must bundle libpangoft2-1.0.so.0).
Not bundling HarfBuzz seems to cause `symbol lookup error: /lib64/libharfbuzz.so.0: undefined symbol: FT_Get_Var_Blend_Coordinates` on Solus 3, indicating that the HarfBuzz from the system needs a newer FreeType than what we are bundling

HarfBuzz should be handled by the distribution and they should provide a clearly defined interface for applications to develop against. Build systems should use older versions than what is available in the oldest still-supported available distributions. Applications written against earlier versions of these should be guaranteed to still run with later versions of these.

References:
* https://www.freedesktop.org/wiki/Software/HarfBuzz/
* https://abi-laboratory.pro/tracker/timeline/harfbuzz/
* https://abi-laboratory.pro/index.php?view=navigator&symbol=hb_buffer_set_cluster_level#result
* https://github.com/AppImage/AppImages/issues/110#issuecomment-345295909
* https://abi-laboratory.pro/index.php?view=navigator&symbol=FT_Get_Var_Blend_Coordinates

### Image formats

Currently every distribution names these differently:
* libtiff (Fedora and openSUSE lack `libtiff.so.4`)
* libpng
* libjpeg

They should be named the same in all distributions. Then applications could rely on these from the system rather than having to privately bundle their own copies.

### NSS

Currently distributions ship no or incompatible versions of:
* libnss3.so
* libnssutil3.so
* libsmime3.so
* libssl3.so
* libfreebl3.so
* libfreeblpriv3.so
* libnssckbi.so
* libnssdbm3.so
* libnsssysinit.so
* libsoftokn3.so

They should be standardized across all distributions. Then applications could rely on these from the system rather than having to privately bundle their own copies.

References:
* https://github.com/probonopd/linuxdeployqt/issues/35#issuecomment-256213517
* https://github.com/probonopd/AppImages/pull/114

Also, some distributions (e.g., Debian/Ubuntu-type distributions) put these libraries into non-standard locations such as `/usr/lib/x86_64-linux-gnu/nss/` (notice the extra last component of the path) which applications/libraries compiled on other distributions have no idea exists. This results e.g., in Qt applications built using the official Qt binary distribution from qt.io being unable to run on Debian/Ubuntu-type distributions.

They should be placed into the same locations (ideally, `/usr/lib/x86_64-linux-gnu/`) in all distributions. Then applications could rely on these from the system rather than having to privately bundle their own copies or search in "arbitrary" subdirectories.

Reference:
https://github.com/probonopd/linuxdeployqt/issues/281#issuecomment-382983171

### PCRE

libpcre should be handled by the distribution and they should provide a clearly defined interface for applications to develop against. Build systems should use older versions than what is available in the oldest still-supported available distributions. Applications written against earlier versions of this should be guaranteed to still run with later versions of this

* openSUSE (as of 2017) lacks libpcre.so.3 but provides libpcre.so.1
* Ubuntu (as of 2017) lacks libpcre.so.1 but provides libpcre.so.3

According to https://twitter.com/Det_Conan_Kudo/status/896508995044880384 PCRE sonames are wrong in debian, and hence, probably Ubuntu. According to the source, it cannot be fixed "because now it's the ABI contract of Debian." According to https://github.com/AppImage/AppImages/issues/83#issuecomment-322044692, "`libpcre.so.3` is a historical Debian/Ubuntu screwup. Everywhere else it is `libpcre.so.1`."

## Weak dependencies

Certain distribution functionality/libraries should be purely optional. Software compiled on distributions should never require these as hard dependencies, but should rather check whether these are available, and fall back gracefully if they are not there.

* `libselinux.so.1`. Currently some software compiled on CentOS requires `libselinux.so.1` even if SELinux is not used or wanted
* `libapparmor.so.1`. According to https://twitter.com/Det_Conan_Kudo/status/896733648619270144, this equally applies to AppArmor. According to the source, apparently binaries on Ubuntu, SUSE and Debian link to it

Workaround: dummy libraries that resolves all of their symbols but just do nothing, e.g., https://github.com/AppImage/AppImages/issues/83#issuecomment-321966519

## ELF handling in desktop environments

Desktop environments should handle ELF files with missing executable bits more gracefully.
https://github.com/AppImage/AppImageKit/issues/374

## SELinux

In the realm of security, distribution vendors are going different paths (Red Hat using NSA-originated SELinux and others using AppArmor or other technologies. Which is fine, as long as these systems don't spill over into each and every application, as is the case with `libselinux.so.1`, which gets linked into each application compiled on Red Hat based systems like CentOS, while it is not available on some other systems.

Security enhancements in the operating system should not require applications to link to libraries like `libselinux.so.1`.

Workaround: Bundle `libselinux.so.1` with every application that needs it (but since it depends on `libpcre.so.3` we need also bundle that because distributions can't be relied on to ship the correct version under the same name). Or, better, replace it by a dummy library that resolves all of its symbols but just does nothing, e.g., https://github.com/AppImage/AppImages/issues/83#issuecomment-321966519

## FUSE

Although working out-of-the box in >95% of desktop distributions in the default installation, there are still 5% where this is not the case.

Distributions should ensure that FUSE is working out of the box and that all permissions are set correctly for regular users.

## Compilers

Ideally, which version of a compiler was used to compile a binary should not determine which version of libraries the compiled binaries need. However, according to https://stackoverflow.com/a/42705277, the GCC version used determines the minimum version of `libstdc++.so.6`:

>  Sometimes you don't control the target machine (e.g. your library  needs to run on a locked-down enterprise system). In such a case you  will need to recompile your code using the version of GCC that  corresponds to their GLIBCXX version. In that case, you can do the following:  
> 1.  Look up the latest version of GLIBCXX supported by the target machine: strings /usr/lib/libstdc++.so.6 \| grep GLIBC ... Say the version is 3.4.19. 
> 2. Use https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html to find the corresponding GCC version. In our case, this is [4.8.3, 4.9.0).

So, in practice, if you want your binary to run on say, all still-supported Ubuntu LTS releases (14.04 at the point of this writing), then you _must not_ use a compiler newer than GCC 4.8.3. 

Question: Can the compiler version be decoupled from the libraries used by the resulting binaries by using a cross-compiler? If so, how?

## GStreamer

GStreamer is a library for constructing graphs of media-handling components. Ideally we could rely on this being "there" in the base operating system. However, different distributions insist on scattering around its files in the filesystem at different and crazy looking paths:

* Debian, Ubuntu: Some parts (e.g., `gst-plugin-scanner`) in `/usr/lib/x86_64-linux-gnu/gstreamer1.0/gstreamer-1.0`, other parts (e.g., plugins) in `/usr/lib/x86_64-linux-gnu/gstreamer1.0/`
* Red Hat, CentOS, Fedora: Some parts (e.g., `gst-plugin-scanner`) in `/usr/libexec/gstreamer-1.0/`, other parts (e.g., plugins) in `/usr/lib64/gstreamer-1.0`

Distributions should ensure that GStreamer is working out of the box and is installed in the same, upstream-determined, location on every distribution.

## Xorg and Wayland

Some distributions are beginning to ship Wayland as the default display server in place of the older Xorg. Distributions should ensure that X11 applications run without manual intervention, e.g., by installing and configuring XWayland by default. Workaround: Install and configure XWayland manually, see https://github.com/AppImage/AppImageKit/wiki/Wayland

probonopd's avatar
probonopd committed
450 451 452 453 454 455 456 457 458 459
## Desktop infrastructure

### Icons

Many applications have different icons for different versions of the same application. Firefox, for example, has constantly been evolving their icon.

![Firefox icons over time](https://user-images.githubusercontent.com/2480569/42704269-bf0ec010-86be-11e8-846d-95dfa034a451.png)

The XDG standard is entirely ignorant of this, assuming all Firefox instances on the system are sharing the same Firefox icon. macOS does a much better job because icons are stored inside each application, rather than at one central place in the filesystem.

probonopd's avatar
probonopd committed
460 461
Desktop environments should define a way to bundle icons for applications and their documents, and there should be a system that uses this information (similar to LaunchServices on macOS) that does not a) require one to copy around desktop files and icon files into the filesystem (outside of the application), and b) that allows for multiple versions of the same applciation to co-exist seamlessly.

probonopd's avatar
probonopd committed
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
## Individual distributions' platform promises

Some distributions make their own platform promises. Whether this can be part of the solution or adds to the complexity remains to be determined. Of course, this is insufficient. We need platform promises for "Desktop Linux".

### Red Hat Enterprise Linux

https://access.redhat.com/articles/rhel-abi-compatibility describes the Red Hat Enterprise Linux platform guarantees.

> Limit linking applications to the core libraries at compatibility level 1. The core libraries (see Appendix A) are intended to preserve binary compatibility across three consecutive major releases.
> 
> Provide compatibility libraries for applications that have been built with libraries that are not at the desired compatibility level, provided the bundled libraries themselves only use the interfaces provided by the core libraries.
> 
> Compatibility level 1: APIs and ABIs are stable across three major releases (starting with RHEL 7)
> 
> alsa-lib elfutils-libelf glibc glibc-utils gtk2 hesiod krb5-libs libgcc libgfortran libgomp libstdc++ libtbbmalloc_proxy.so libtbbmalloc.so libtbb.so libusb libvirt-client libxml2 libxslt mesa-libGL mesa-libGLU motif pam SDL

This means that we can trust that if you build against these libraries and bundle everything else privately, then your application is expected to work at least in RHEL 7, 8, and 9.

Note that gtk3 at this point is in "Compatibility level 2: APIs and ABIs are stable within one major release (RHEL 7)". Which means that a gtk3 application might break in RHEL 8. Which also means that application developers should not use it before it also enters compatibility level 1, or else they cannot be sure that their application will continue working in the foreseeable future.

## Relevant forums

Where should we discuss this? Please add ideas here.

* https://cfp.all-systems-go.io/en/ASG2017/cfp/session/new

## References

Aleksei Kovura's avatar
Aleksei Kovura committed
490
* https://github.com/ebassi/halting_problem/blob/master/content/gnome/dev-v-ops.md