linuxdeploy / linuxdeploy-plugin-gtk

Gtk+2/3 plugin for linuxdeploy. Bundles Gtk+ resources, GLib schemas, and a lot more.
MIT License
22 stars 13 forks source link

Do not create temp directories and files at runtime #24

Closed probonopd closed 2 years ago

probonopd commented 2 years ago

Currently mktemp is being used. Let's try to avoid creating temp directories and files at runtime if possible.

In go-appimage, we are doing without a temp file for loaders.cache:

  export GDK_PIXBUF_MODULE_FILE=$(find "$HERE" -name loaders.cache -type f -path '*gdk-pixbuf*') # Patched to contain no paths

https://github.com/probonopd/go-appimage/blob/36cf7d1b81a2407aed8e89e03f8a68fb10d4659b/src/appimagetool/appdirtool.go#L114

As you can see, we are using a pre-made loaders.cache file that is contained inside the AppImage.

Can you see any downsides to this approach?

TheTumultuousUnicornOfDarkness commented 2 years ago

Hello @probonopd,

We create a temporary directory for immodules.cache and loaders.cache files for this:

export GTK_IM_MODULE_FILE="\$CACHEDIR/immodules.cache"
sed "s|$gtk3_libdir|\$APPDIR/$gtk3_libdir|g" "\$APPDIR/$gtk3_immodules_cache_file" > "\$GTK_IM_MODULE_FILE"

export GDK_PIXBUF_MODULE_FILE="\$CACHEDIR/loaders.cache"
sed "s|$gdk_pixbuf_moduledir|\$APPDIR/$gdk_pixbuf_moduledir|g" "\$APPDIR/$gdk_pixbuf_cache_file" > "\$GDK_PIXBUF_MODULE_FILE"

The problem is not how to set GDK_PIXBUF_MODULE_FILE to the correct filename, but the content of these files, because they use absolute paths.

That is what we have inside the AppImage: AppImage.loaders.txt And then, at run time, loaders.cache file is patched like this: AppRun.loaders.txt

So the difference between both file is this:

--- AppImage.loaders.txt    2021-12-18 12:16:56.153290951 +0100
+++ AppRun.loaders.txt  2021-12-18 12:17:38.675579789 +0100
@@ -2,52 +2,52 @@
 # Automatically generated file, do not edit
 # Created by gdk-pixbuf-query-loaders from gdk-pixbuf-2.36.11
 #
-# LoaderDir = /usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders
+# LoaderDir = /tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders
 #
-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ani.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ani.so"
 "ani" 4 "gdk-pixbuf" "Windows animated cursor" "LGPL"
 "application/x-navi-animation" ""
 "ani" ""
 "RIFF    ACON" "    xxxx    " 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-bmp.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-bmp.so"
 "bmp" 5 "gdk-pixbuf" "BMP" "LGPL"
 "image/bmp" "image/x-bmp" "image/x-MS-bmp" ""
 "bmp" ""
 "BM" "" 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-gif.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-gif.so"
 "gif" 4 "gdk-pixbuf" "GIF" "LGPL"
 "image/gif" ""
 "gif" ""
 "GIF8" "" 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-icns.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-icns.so"
 "icns" 4 "gdk-pixbuf" "MacOS X icon" "GPL"
 "image/x-icns" ""
 "icns" ""
 "icns" "" 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ico.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ico.so"
 "ico" 5 "gdk-pixbuf" "Windows icon" "LGPL"
 "image/x-icon" "image/x-ico" "image/x-win-bitmap" "image/vnd.microsoft.icon" "application/ico" "image/ico" "image/icon" "text/ico" ""
 "ico" "cur" ""
 "  \001   " "zz znz" 100
 "  \002   " "zz znz" 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-jpeg.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-jpeg.so"
 "jpeg" 5 "gdk-pixbuf" "JPEG" "LGPL"
 "image/jpeg" ""
 "jpeg" "jpe" "jpg" ""
 "\377\330" "" 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so"
 "png" 5 "gdk-pixbuf" "PNG" "LGPL"
 "image/png" ""
 "png" ""
 "\211PNG\r\n\032\n" "" 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-pnm.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-pnm.so"
 "pnm" 4 "gdk-pixbuf" "PNM/PBM/PGM/PPM" "LGPL"
 "image/x-portable-anymap" "image/x-portable-bitmap" "image/x-portable-graymap" "image/x-portable-pixmap" ""
 "pnm" "pbm" "pgm" "ppm" ""
@@ -58,21 +58,21 @@
 "P5" "" 100
 "P6" "" 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-qtif.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-qtif.so"
 "qtif" 4 "gdk-pixbuf" "QuickTime" "LGPL"
 "image/x-quicktime" "image/qtif" ""
 "qtif" "qif" ""
 "abcdidsc" "xxxx    " 100
 "abcdidat" "xxxx    " 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so"
 "svg" 6 "gdk-pixbuf" "Scalable Vector Graphics" "LGPL"
 "image/svg+xml" "image/svg" "image/svg-xml" "image/vnd.adobe.svg+xml" "text/xml-svg" "image/svg+xml-compressed" ""
 "svg" "svgz" "svg.gz" ""
 " <svg" "*    " 100
 " <!DOCTYPE svg" "*             " 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-tga.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-tga.so"
 "tga" 4 "gdk-pixbuf" "Targa" "LGPL"
 "image/x-tga" ""
 "tga" "targa" ""
@@ -83,7 +83,7 @@
 "  \n" "xz " 100
 "  \v" "xz " 100

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-tiff.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-tiff.so"
 "tiff" 5 "gdk-pixbuf" "TIFF" "LGPL"
 "image/tiff" ""
 "tiff" "tif" ""
@@ -91,14 +91,14 @@
 "II* " "   z" 100
 "II* \020   CR\002 " "   z zzz   z" 0

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-xbm.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-xbm.so"
 "xbm" 4 "gdk-pixbuf" "XBM" "LGPL"
 "image/x-xbitmap" ""
 "xbm" ""
 "#define " "" 100
 "/*" "" 50

-"/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-xpm.so"
+"/tmp/.mount_CPU-X-IGsAtR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-xpm.so"
 "xpm" 4 "gdk-pixbuf" "XPM" "LGPL"
 "image/x-xpixmap" ""
 "xpm" ""

In other words, when you do this:

export GDK_PIXBUF_MODULE_FILE=$(find "$HERE" -name loaders.cache -type f -path '*gdk-pixbuf*') # Patched to contain no paths

You are using the pre-made loaders.cache file that is contained inside the AppImage, but this one will use GdkPixbuf Image Loader Modules files on the real host, not those embedded inside the AppImage, so your approach is not portable in fact (it can work on some systems if libraries are the same on both sides, but it will not otherwise).

It should also speed up execution, if only a tiny bit

Replacing a mktemp by a find, I doubt it will speed up execution... For me, it is slower:

$ time mktemp --tmpdir --directory .AppRun.XXXXXXXX
/tmp/.AppRun.hSoabWbN
0,00s user 0,00s system 86% cpu 0,001 total

$ HERE="/tmp/.mount_CPU-X-IGsAtR"
$ time find "$HERE" -name loaders.cache -type f -path '*gdk-pixbuf*'
/tmp/.mount_CPU-X-IGsAtR/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders.cache
0,00s user 0,00s system 49% cpu 0,014 total

It should be easier and more robust to clean up after the application has exited

Cleanup part was proposed in linuxdeploy/linuxdeploy#164 (not merged in fact).

But I agree with you: if we find a proper way to fix paths in immodules.cache and loaders.cache files, then we will be able to get rid of this temporary directory.

probonopd commented 2 years ago

The problem is not how to set GDK_PIXBUF_MODULE_FILE to the correct filename, but the content of these files, because they use absolute paths.

We can patch the paths at AppImage creation time. Seems to work; but I am not a glib/gdk expert by any stretch of the imagination.

TheTumultuousUnicornOfDarkness commented 2 years ago

I tested your workaround in your link:

sed -e "s|/usr||g" "$APPDIR//usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules.cache" > "$GTK_IM_MODULE_FILE"
sed -e "s|/usr||g" "$APPDIR//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders.cache" > "$GDK_PIXBUF_MODULE_FILE"

Removing /usr is not a fix:

cpu-x:623744): Gtk-WARNING **: 16:44:10.019: Could not load a pixbuf from icon theme.
This may indicate that pixbuf loaders or the mime database could not be found.

(cpu-x:623744): Gtk-WARNING **: 16:44:10.019: Error loading theme icon 'gtk-preferences' for stock: Failed to load /usr/share/icons/Delft/categories/16/gtk-preferences.png: Unable to load image-loading module: /lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so: /lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so: cannot open shared object file: No such file or directory

(cpu-x:623744): Gtk-WARNING **: 16:44:10.019: Error loading theme icon 'image-missing' for stock: Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: /lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so: /lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so: cannot open shared object file: No such file or directory

(cpu-x:623744): Gdk-CRITICAL **: 16:44:10.019: gdk_cairo_surface_create_from_pixbuf: assertion 'GDK_IS_PIXBUF (pixbuf)' failed

(cpu-x:623744): GLib-GObject-CRITICAL **: 16:44:10.019: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
**
Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: /lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so: /lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so: cannot open shared object file: No such file or directory (gdk-pixbuf-error-quark, 5)
Bail out! Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: /lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so: /lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so: cannot open shared object file: No such file or directory (gdk-pixbuf-error-quark, 5)

We can patch the paths at AppImage creation time. Seems to work; but I am not a glib/gdk expert by any stretch of the imagination.

I do not get it. How do you want to set proper paths in immodules.cache and loaders.cache files are creation time? The path is known only at run time, when AppRun is executed.

After some look in gdk-pixbuf source code, I found these functions:

/* In case we have a relative module path in the loaders cache
 * prepend the toplevel dir */
static gchar *
build_module_path (const gchar *path)
{
#ifdef GDK_PIXBUF_RELOCATABLE
        if (g_path_is_absolute (path)) {
                return g_strdup (path);
        } else {
                return g_build_filename (gdk_pixbuf_get_toplevel (), path, NULL);
        }
#else
        return g_strdup (path);
#endif

#ifdef GDK_PIXBUF_RELOCATABLE

gchar *
gdk_pixbuf_get_toplevel (void)
{
  static gchar *toplevel = NULL;

  if (toplevel == NULL) {
#if defined(G_OS_WIN32)
    toplevel = g_win32_get_package_installation_directory_of_module (gdk_pixbuf_dll);
#elif defined(OS_DARWIN)
    char pathbuf[PATH_MAX + 1];
    uint32_t  bufsize = sizeof(pathbuf);
    gchar *bin_dir;

    _NSGetExecutablePath(pathbuf, &bufsize);
    bin_dir = g_dirname(pathbuf);
    toplevel = g_build_path (G_DIR_SEPARATOR_S, bin_dir, "..", NULL);
    g_free (bin_dir);
#elif defined (OS_LINUX)
    gchar *exe_path, *bin_dir;

    exe_path = g_file_read_link ("/proc/self/exe", NULL);
    bin_dir = g_dirname(exe_path);
    toplevel = g_build_path (G_DIR_SEPARATOR_S, bin_dir, "..", NULL);
    g_free (exe_path);
    g_free (bin_dir);
#else
#error "Relocations not supported for this platform"
#endif
  }
  return toplevel;
}

#endif  /* GDK_PIXBUF_RELOCATABLE */
}

I found this patch. Unfortunately, what I found is relocations are disabled by default for GNU/Linux, so only absolute paths are supported to load GdkPixbuf Image Loader Modules.

TheAssassin commented 2 years ago

It doesn't look like any file contained in the AppImage can substitute the files generated during runtime. You got to work with what is provided by the libraries, after all.

TheAssassin commented 2 years ago

Actually, I wonder whether we could (or rather, should) monkeypatch the library using some LC_PRELOADed library. That'd depend greatly on how stable those functions are. (They seem to be part of the public API, so the ABI should be stable as well...) Could use some heuristics to validate that the functions can be patched by us at all.

As a fallback, that library could take care of generating those files.

But that seems way more of a hack than the current solution, is a lot more work, and potentially more dangerous overall.

probonopd commented 2 years ago

Interesting idea. I still think I had this whole thing working by just editing the *.cache files and removing the paths entirely (not just /usr) from there and exporting GDK_PIXBUF_MODULE_FILE at runtime, as indicated by the comment in this line:

https://github.com/probonopd/go-appimage/blob/36cf7d1b81a2407aed8e89e03f8a68fb10d4659b/src/appimagetool/appdirtool.go#L114

Imho this would be much easier and cleaner?

TheTumultuousUnicornOfDarkness commented 2 years ago

Interesting idea. I still think I had this whole thing working by just editing the *.cache files and removing the paths entirely (not just /usr) from there and exporting GDK_PIXBUF_MODULE_FILE at runtime, as indicated by the comment in this line:

https://github.com/probonopd/go-appimage/blob/36cf7d1b81a2407aed8e89e03f8a68fb10d4659b/src/appimagetool/appdirtool.go#L114

Even if I patch the loaders.cache file, it fails to open modules:

GDK_PIXBUF_MODULEDIR=/tmp/squashfs-root/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders
GDK_PIXBUF_MODULE_FILE=/tmp/squashfs-root/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders.cache

(cpu-x:324476): Gtk-WARNING **: 14:59:22.694: Could not load a pixbuf from icon theme.
This may indicate that pixbuf loaders or the mime database could not be found.

(cpu-x:324476): Gtk-WARNING **: 14:59:22.694: Error loading theme icon 'gtk-preferences' for stock: Failed to load /usr/share/icons/Delft/categories/16/gtk-preferences.png: Unable to load image-loading module: libpixbufloader-png.so: libpixbufloader-png.so: cannot open shared object file: No such file or directory

(cpu-x:324476): Gtk-WARNING **: 14:59:22.694: Error loading theme icon 'image-missing' for stock: Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: libpixbufloader-svg.so: libpixbufloader-svg.so: cannot open shared object file: No such file or directory

(cpu-x:324476): Gdk-CRITICAL **: 14:59:22.694: gdk_cairo_surface_create_from_pixbuf: assertion 'GDK_IS_PIXBUF (pixbuf)' failed

(cpu-x:324476): GLib-GObject-CRITICAL **: 14:59:22.694: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
**
Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: libpixbufloader-svg.so: libpixbufloader-svg.so: cannot open shared object file: No such file or directory (gdk-pixbuf-error-quark, 5)
Bail out! Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: libpixbufloader-svg.so: libpixbufloader-svg.so: cannot open shared object file: No such file or directory (gdk-pixbuf-error-quark, 5)

So unless gdk-pixbuf is built with GDK_PIXBUF_RELOCATABLE on, I doubt that relative filenames in loaders.cache will work.

I can do a quick test with LD_PRELOAD to see...

TheTumultuousUnicornOfDarkness commented 2 years ago

My issue seems to start from somewhere else, not related to build_module_path()... I was not able to determine which function fails to pixbufs, I give up.

If someone else wants to play with this, here is a source file with instructions on top: gdk-pixbuf-io-patched.c.txt (remove .txt at the end of filename before).

arteme commented 2 years ago

This can be made to work regardless of GDK_PIXBUF_RELOCATABLE. If it is not set, the relative path is relative to the working directory. This is how it works in msys2 on Windows (the paths are already relative in loaders.cache) and that's how a GTK app can be packaged on MacOS (take the absolute paths and make them relative: https://github.com/arteme/pod-ui/blob/master/build/collect-gtk.sh#L100 -- that's my own project and I can confirm it works).

So, if we make the paths relative, this is what we get:

arteme /tmp/TEST $ cat usr/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
... 
"usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so"
"svg" 6 "gdk-pixbuf" "Scalable Vector Graphics" "LGPL"
"image/svg+xml" "image/svg" "image/svg-xml" "image/vnd.adobe.svg+xml" "text/xml-svg" "image/svg+xml-compressed" ""
"svg" "svgz" "svg.gz" ""
" <svg" "*    " 100
" <!DOCTYPE svg" "*             " 100
...

arteme /tmp/TEST $ GDK_PIXBUF_MODULE_FILE=usr/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache strace usr/bin/pod-gui 2>&1 | grep pixbuf
openat(AT_FDCWD, "/tmp/TEST/usr/bin/../lib/libgdk_pixbuf-2.0.so.0", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "usr/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache", O_RDONLY) = 8
read(8, "gdk-pixbuf\" \"Scalable Vector Gra"..., 1024) = 246
newfstatat(AT_FDCWD, "usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so", {st_mode=S_IFREG|0755, st_size=21600, ...}, 0) = 0
openat(AT_FDCWD, "usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = 11
openat(AT_FDCWD, "/tmp/TEST/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/../../../../glibc-hwcaps/x86-64-v3/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp/TEST/usr/lib/gdk-pixbuf-2.0/2.10.0/loaders/../../../../glibc-hwcaps/x86-64-v3", 0x7ffdc4b40a80, 0) = -1 ENOENT (No such file or directory)
...^C

This will work if the working directory is AppDir.

TheAssassin commented 2 years ago

This will work if the working directory is AppDir.

This cannot be enforced, not even for GUI tools. You can't just assume that the application doesn't care about its working directory.

arteme commented 2 years ago

This cannot be enforced, not even for GUI tools. You can't just assume that the application doesn't care about its working directory.

True. I was kinda hoping AppImage stub does something about that, but no...

TheAssassin commented 2 years ago

How could it? It's entirely up to the application whether working dir matters or not. Qt has qt.conf, Gtk still lacks such a very deployment friendly feature...

arteme commented 2 years ago

Another possibility is to strip away paths completely:

"io-wmf.so"
"wmf" 0 "gdk-pixbuf" "Windows Metafile" ""
"image/x-wmf" ""
"wmf" "apm" ""
"\327\315\306\232" "" 100
"\001" "" 100

"libpixbufloader-avif.so"
"avif" 5 "gdk-pixbuf" "AV1 Image File Format" "BSD"
"image/avif" ""
"avif" ""
"    ftypavif" "zzz         " 100

"libpixbufloader-heif.so"
"heif/avif" 4 "pixbufloader-heif" "HEIF/AVIF Image" "LGPL3"
"image/heif" "image/heic" "image/avif" ""
"heif" "heic" "avif" ""
"    ftyp" "xxxx    " 100

"libpixbufloader-jxl.so"
"jxl" 4 "gdk-pixbuf" "JPEG XL image" "BSD-3"
"image/jxl" ""
"jxl" ""
"\377\n" "  " 100
"...\fJXL \r\n\207\n" "zzz         " 100

"libpixbufloader-svg.so"
"svg" 6 "gdk-pixbuf" "Scalable Vector Graphics" "LGPL"
"image/svg+xml" "image/svg" "image/svg-xml" "image/vnd.adobe.svg+xml" "text/xml-svg" "image/svg+xml-compressed" ""
"svg" "svgz" "svg.gz" ""
" <svg" "*    " 100
" <!DOCTYPE svg" "*             " 100

Then, the pixbuf loaders are also searched from $ORIGIN/../lib, so if pixbuf loaders were to be relocated to the lib-directory, this will work correctly without the working directory limitation. It's funny, though, that that's not the executable's rpath as adding more entries with patchelf --add_rpath does not help.

Either way, this feels way too much of a hack.

probonopd commented 2 years ago

Another possibility is to strip away paths completely

Thanks for confirming. This is what I have been trying to say all along :-) And I think I had implemented it this way in go-appimage iirc.

TheAssassin commented 2 years ago

@X0rg what do you think about this stripping? I couldn't find the relevant code using rpaths in a quick search, though.

TheTumultuousUnicornOfDarkness commented 2 years ago

Ok, I think I understand now (thanks @arteme for your commands!).

My current behavior is the following (when I have export GDK_PIXBUF_MODULE_FILE="$CACHEDIR/loaders.cache"):

openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libgdk_pixbuf-2.0.so.0", O_RDONLY|O_CLOEXEC) = 3
read(11, "pixbufloader-tiff.so\"\n\"tiff\" 5 \""..., 1024) = 544
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so", {st_mode=S_IFREG|0644, st_size=30776, ...}, 0) = 0
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so", O_RDONLY|O_CLOEXEC) = 12
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so", {st_mode=S_IFREG|0644, st_size=17392, ...}, 0) = 0
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = 12
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../glibc-hwcaps/x86-64-v3/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../glibc-hwcaps/x86-64-v3", 0x7ffe01b89b10, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../glibc-hwcaps/x86-64-v2/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../glibc-hwcaps/x86-64-v2", 0x7ffe01b89b10, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../tls/x86_64/x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../tls/x86_64/x86_64", 0x7ffe01b89b10, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../tls/x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../tls/x86_64", 0x7ffe01b89b10, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../tls/x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../tls/x86_64", 0x7ffe01b89b10, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../tls/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../tls", 0x7ffe01b89b10, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../x86_64/x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../x86_64/x86_64", 0x7ffe01b89b10, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../x86_64", 0x7ffe01b89b10, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../x86_64", 0x7ffe01b89b10, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = 12
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../libcroco-0.6.so.3", O_RDONLY|O_CLOEXEC) = 12
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../libxml2.so.2", O_RDONLY|O_CLOEXEC) = 12
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../libicuuc.so.60", O_RDONLY|O_CLOEXEC) = 12
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../libicudata.so.60", O_RDONLY|O_CLOEXEC) = 12
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../libstdc++.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root//usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/../../../../libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)

And if I strip path in the loaders.cache file, it does not work because of this:

openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libgdk_pixbuf-2.0.so.0", O_RDONLY|O_CLOEXEC) = 3
newfstatat(AT_FDCWD, "libpixbufloader-png.so", 0x7ffde2353620, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-png.so.so", 0x7ffde2353620, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-png.so.la", 0x7ffde2353620, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libpixbufloader-png.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/libpixbufloader-png.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
(cpu-x:96660): Gtk-WARNING **: 19:53:26.506: Could not load a pixbuf from icon theme.
This may indicate that pixbuf loaders or the mime database could not be found.
(cpu-x:96660): Gtk-WARNING **: 19:53:26.506: Error loading theme icon 'gtk-preferences' for stock: Failed to load /usr/share/icons/Delft/categories/16/gtk-preferences.png: Unable to load image-loading module: libpixbufloader-png.so: libpixbufloader-png.so: cannot open shared object file: No such file or directory
newfstatat(AT_FDCWD, "libpixbufloader-svg.so", 0x7ffde23535d0, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.so", 0x7ffde23535d0, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.la", 0x7ffde23535d0, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
(cpu-x:96660): Gtk-WARNING **: 19:53:26.506: Error loading theme icon 'image-missing' for stock: Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: libpixbufloader-svg.so: libpixbufloader-svg.so: cannot open shared object file: No such file or directory
(cpu-x:96660): Gdk-CRITICAL **: 19:53:26.506: gdk_cairo_surface_create_from_pixbuf: assertion 'GDK_IS_PIXBUF (pixbuf)' failed
newfstatat(AT_FDCWD, "libpixbufloader-svg.so", 0x7ffde23528d0, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.so", 0x7ffde23528d0, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.la", 0x7ffde23528d0, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so", 0x7ffde2352960, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.so", 0x7ffde2352960, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.la", 0x7ffde2352960, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: libpixbufloader-svg.so: libpixbufloader-svg.so: cannot open shared object file: No such file or directory (gdk-pixbuf-error-quark, 5)
write(1, "Bail out! Gtk:ERROR:../../../../"..., 370Bail out! Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: libpixbufloader-svg.so: libpixbufloader-svg.so: cannot open shared object file: No such file or directory (gdk-pixbuf-error-quark, 5)

So, same conclusion as @arteme: libgdk_pixbuf-2.0.so.0 is ignoring RPATH and not loading Pixbuf modules where they are...

If I create symlinks like this:

usr/lib/libpixbufloader-ani.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ani.so
usr/lib/libpixbufloader-bmp.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-bmp.so
usr/lib/libpixbufloader-gif.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-gif.so
usr/lib/libpixbufloader-icns.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-icns.so
usr/lib/libpixbufloader-ico.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ico.so
usr/lib/libpixbufloader-jpeg.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-jpeg.so
usr/lib/libpixbufloader-png.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so
usr/lib/libpixbufloader-pnm.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-pnm.so
usr/lib/libpixbufloader-qtif.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-qtif.so
usr/lib/libpixbufloader-svg.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so
usr/lib/libpixbufloader-tga.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-tga.so
usr/lib/libpixbufloader-tiff.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-tiff.so
usr/lib/libpixbufloader-xbm.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-xbm.so
usr/lib/libpixbufloader-xpm.so -> x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-xpm.so

Still unlucky:

openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libgdk_pixbuf-2.0.so.0", O_RDONLY|O_CLOEXEC) = 3
newfstatat(AT_FDCWD, "libpixbufloader-png.so", 0x7ffc2140aa40, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-png.so.so", 0x7ffc2140aa40, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-png.so.la", 0x7ffc2140aa40, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libpixbufloader-png.so", O_RDONLY|O_CLOEXEC) = 12
newfstatat(AT_FDCWD, "libpixbufloader-svg.so", 0x7ffc21409cf0, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.so", 0x7ffc21409cf0, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.la", 0x7ffc21409cf0, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = 12
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../glibc-hwcaps/x86-64-v3/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../glibc-hwcaps/x86-64-v2/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../tls/x86_64/x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../tls/x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../tls/x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../tls/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../x86_64/x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../x86_64/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = 12
(cpu-x:148075): Gtk-WARNING **: 20:17:15.566: Could not load a pixbuf from icon theme.
This may indicate that pixbuf loaders or the mime database could not be found.
newfstatat(AT_FDCWD, "libpixbufloader-svg.so", 0x7ffc21409d80, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.so", 0x7ffc21409d80, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.la", 0x7ffc21409d80, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = 12
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/../../../../librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = 12
Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: libpixbufloader-svg.so: /usr/lib/librsvg-2.so.2: undefined symbol: pango_coverage_get_type (gdk-pixbuf-error-quark, 5)
write(1, "Bail out! Gtk:ERROR:../../../../"..., 355Bail out! Gtk:ERROR:../../../../gtk/gtkiconhelper.c:494:ensure_surface_for_gicon: assertion failed (error == NULL): Failed to load /usr/share/icons/Delft-Blue-Dark/status/scalable/image-missing.svg: Unable to load image-loading module: libpixbufloader-svg.so: /usr/lib/librsvg-2.so.2: undefined symbol: pango_coverage_get_type (gdk-pixbuf-error-quark, 5)

And here, I see a new issue: the patchelf --set-rpath '$ORIGIN/../../../..' "$APPDIR/$file"

But if I do a patchelf --set-rpath '$ORIGIN' "$APPDIR/$file", that is clearly better!

openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libgdk_pixbuf-2.0.so.0", O_RDONLY|O_CLOEXEC) = 3
newfstatat(AT_FDCWD, "libpixbufloader-png.so", 0x7fffa5ab88a0, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-png.so.so", 0x7fffa5ab88a0, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-png.so.la", 0x7fffa5ab88a0, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libpixbufloader-png.so", O_RDONLY|O_CLOEXEC) = 12
newfstatat(AT_FDCWD, "libpixbufloader-svg.so", 0x7fffa5ab7b50, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.so", 0x7fffa5ab7b50, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "libpixbufloader-svg.so.la", 0x7fffa5ab7b50, 0) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/libpixbufloader-svg.so", O_RDONLY|O_CLOEXEC) = 12
openat(AT_FDCWD, "/tmp/squashfs-root/usr/bin/../lib/librsvg-2.so.2", O_RDONLY|O_CLOEXEC) = 12

I opened #29. Please test and provide feedback.