probonopd/go-appimage

appimagetool don't configure `loaders.cache`

brunvonlope opened this issue · 5 comments

Similar to #282


When bundling GTK apps, appimagetool copy the loaders.cache file required by GdkPixbuf. But inside the file the paths aren't adapted to be relative to AppDir/usr/lib... which makes the system loaders be called by GdkPixbuf.

I suggest changing the paths inside the loaders.cache file when calling deploy in a similar way that we do manually with GIMP: https://gitlab.gnome.org/GNOME/gimp/-/blob/master/build/linux/appimage/bundle-gimp-appimage.sh?ref_type=heads#L170. Otherwise, some apps can even not display the GUI at all.

Hello @brunvonlope, apparently you know a lot about the inner workings of GTK (well, at least compared to me, anyways). Would you be able to send a pull request? Thanks for your suggestion.

Hello @brunvonlope, apparently you know a lot about the inner workings of GTK (well, at least compared to me, anyways). Would you be able to send a pull request? Thanks for your suggestion.

I know almost nothing, specially about Go ☹️. To be fair, this bug was discovered by accident while using testing AppImage in some distros.

We already have some code related to it:

func handleGdk(appdir helpers.AppDir) {
// If there is a .so with the name libgdk_pixbuf inside the AppDir, then we need to
// bundle Gdk pixbuf loaders without which the bundled Gtk does not work
// cp /usr/lib/x86_64-linux-gnu/gdk-pixbuf-*/*/loaders/* usr/lib/x86_64-linux-gnu/gdk-pixbuf-*/*/loaders/
// cp /usr/lib/x86_64-linux-gnu/gdk-pixbuf-*/*/loaders.cache usr/lib/x86_64-linux-gnu/gdk-pixbuf-*/*/ -
// this file must also be patched not to contain paths to the libraries
for _, lib := range allELFs {
if strings.HasPrefix(filepath.Base(lib), "libgdk_pixbuf") {
log.Println("Determining Gdk pixbuf loaders (for GDK_PIXBUF_MODULEDIR and GDK_PIXBUF_MODULE_FILE)...")
locs, err := findWithPrefixInLibraryLocations("gdk-pixbuf")
if err != nil {
log.Println("Could not find Gdk pixbuf loaders")
os.Exit(1)
} else {
for _, loc := range locs {
determineELFsInDirTree(appdir, loc)
// We need to patch away the path to libpixbufloader-png.so from the file loaders.cache, similar to:
// sed -i -e 's|/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0/2.10.0/loaders/||g' usr/lib/x86_64-linux-gnu/gdk-pixbuf-*/*/loaders.cache
// the patched file must not contain paths to the libraries
loadersCaches := helpers.FilesWithSuffixInDirectoryRecursive(loc, "loaders.cache")
if len(loadersCaches) < 1 {
helpers.PrintError("loadersCaches", errors.New("could not find loaders.cache"))
os.Exit(1)
}
err = copy.Copy(loadersCaches[0], appdir.Path+loadersCaches[0])
if err != nil {
helpers.PrintError("Could not copy loaders.cache", err)
os.Exit(1)
}
whatToPatchAway := helpers.FilesWithSuffixInDirectoryRecursive(loc, "libpixbufloader-png.so")
if len(whatToPatchAway) < 1 {
helpers.PrintError("whatToPatchAway", errors.New("could not find directory that contains libpixbufloader-png.so"))
break // os.Exit(1)
}
log.Println("Patching", appdir.Path+loadersCaches[0], "removing", filepath.Dir(whatToPatchAway[0])+"/")
err = PatchFile(appdir.Path+loadersCaches[0], filepath.Dir(whatToPatchAway[0])+"/", "")
if err != nil {
helpers.PrintError("PatchFile loaders.cache", err)
break // os.Exit(1)
}
}
}
break
}
}
}

Maybe it is not working properly?

Indeed it's not working:

ERROR whatToPatchAway: could not find directory that contains libpixbufloader-png.so

My system doesn't even have a libpixbufloader-png.so anymore. PNG support is baked into gdk-pixbuf itself, not implemented as a loader module.

This could either be fixed by assuming the following directory layout

loaders.cache
loaders/
    *.so

so that the loaders can be found from the location of loaders.cache, or searching other formats, e.g. svg, webp, until one succeeds.

Thanks @pbs3141. I'd appreciate code contributions from someone knowledgeable about Gtk here.

Has https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/blob/3b67a1d1c1b0c8268f57f2bce40fe2d33d409cea/linuxdeploy-plugin-gtk.sh#L312-L332 the correct logic?