Bundling GTK3 dependencies in AppImage

I’m packaging a GTK based application using linuxdeploy on an Ubuntu 18.04 VirtualBox environment. The resulting AppImage runs on Ubuntu 20.10, but all the svg icons are broken. This appears to be because the runtime pixbuf loaders are being picked up from the host and aren’t compatible with some of the AppImage bundled libraries (cairo in particular, with a missing cairo_font_options_get_variations symbol), causing them to fail to load.

This page describes how to manually package GTK2 dependencies. I modified this somewhat for GTK3 (I don’t think theme engines are applicable in my case). The part that is confusing to me is the last section on that page, which says that several run-time variables must be set before running the AppImage, to ensure the AppImage versions of libraries get used. Is there a way to include this in the AppImage itself? I guess I would have to make a shell script in the AppImage to set them and then run my executable?

For testing purposes, I mounted the AppImage with --appimage-mount and set up the runtime variables, but when I ran the application it crashed. A quick gdb session and backtrace showed was being used from the host system. This appears to be blacklisted by linuxdeploy. I copied the libraries from Ubuntu 18.04 to a temporary directory and added it to LD_LIBRARY_PATH. This still failed to load the pixbuf loaders though, since it was still picking up the host librsvg. I added the path to the AppImage /usr/lib to LD_LIBRARY_PATH, ran it again and it worked!

So in summary:

  • How to set environment variables before running executable to override pixbuf loaders?
  • Why is blacklisted and what would be the consequence of including it?
  • Why wasn’t librsvg picked up in the AppImage usr/lib directory? Is this because it is being runtime loaded and thus requires this path to be added to LD_LIBRARY_PATH?

Thanks for any tips on how I can best bundle my GTK application and get it working from Ubuntu 18.04 to current 20.10.

I resolved a few of my questions, though I’m not positive my solutions are proper:

  • Created an AppRun #!/bin/bash script which I pass to linuxdeploy with the --custom-apprun switch
  • The AppRun script uses the following to get the current directory of the script, in order to set environment variables and execute the application (maybe there is a better way?):
    APPDIR="$(dirname "${BASH_SOURCE[0]}")"
  • Ended up just copying* to the AppDir usr/lib, looking at the blacklist, it seems it was blacklisted just to get xpm support for Inkscape, according to the comment in
  • Added AppImage usr/lib to LD_LIBRARY_PATH before executing my program

I still get what seems to be a warning, because it appears to run fine anyways:
/tmp/.mount_AlkimiMFNES2/usr/lib/ no version information available (required by /usr/lib/x86_64-linux-gnu/

Seems to be running great now, though it likely needs more testing on different systems. Any tips on better ways to do things though, would be appreciated.

Sine the linuxdeploy author is not reading here, please ask linuxdeploy related questions over at Issues · linuxdeploy/linuxdeploy · GitHub.

Happy AppImaging!