Skip to content

Bundling GTK3 apps

Xorg edited this page Jan 18, 2021 · 10 revisions

Overview

Please consider using linuxdeploy-plugin-gtk (this Wiki tends to be out of date).

Bundle from a RPM package (Transmission)

Use this to bundle a simple GTK app:

#!/bin/bash

function make_dirs {
  mkdir -p "${1}"/"${1}.AppDir" || echo ""
}

function extract_packages {
  FILES=$(find ../ -name *rpm)
  for FILE in $FILES ; do
    rpm2cpio "${FILE}" | cpio -i --make-directories
  done
}

function copy_desktop {
  find . -name *desktop -exec cp {} . \;
}

function make_apprun_skel {
cat > ./AppRun <<\EOF
#!/bin/sh
HERE=$(dirname $(readlink -f "${0}"))
echo "${HERE}"
export PATH="${HERE}/usr/bin/":$PATH
export LD_LIBRARY_PATH="${HERE}/usr/lib/":$LD_LIBRARY_PATH
cd "${HERE}/usr"
EOF
chmod a+x ./AppRun
}

function patch_usr {
  find . -type f -exec sed -i -e 's|/usr|././|g' {} \;
}

function get_assistant {
  wget -c "https://downloads.sourceforge.net/project/portable/64bit/AppImageAssistant%200.9.3-64bit"
  chmod a+x ./AppImageAssistant*
}

function make_appdir {
  ./AppImageAssistant* "${1}.AppDir" "${1}_${2}.AppImage"
}

APPNAME=Transmission
make_dirs "${APPNAME}"
cd "${APPNAME}"
wget -c -r -l1 -np "http://dl.fedoraproject.org/pub/epel/beta/7/x86_64/" -A transmission-*.rpm -P download
find ./download/ -name *qt* -exec rm {} \;
VERSION=$(find download/ -name transmission-gtk* | grep -Poe transmission-.*?.el7 | sed -e 's|.el7||g' | sed -e 's|transmission-gtk-||g')
cd "${APPNAME}.AppDir"
extract_packages
patch_usr
copy_desktop
make_apprun_skel
echo "./bin/transmission-gtk $@" >> AppRun
cd -
get_assistant
make_appdir "${APPNAME}" "${VERSION}"

Standalone AppRun (Pitivi)

The following is likely outdated, but has been used once to bundle Pitivi and the entire GTK stack:

#!/bin/bash

# Base environment variables
export LD_LIBRARY_PATH=${APPDIR}/lib:${LD_LIBRARY_PATH}
export PATH=${APPDIR}/bin:${PATH}
export XDG_DATA_DIRS=${APPDIR}/share:${XDG_DATA_DIRS}
# GTK+/GIO/GdkPixbuf environment variables
# http://askubuntu.com/questions/251712/how-can-i-install-a-gsettings-schema-without-root-privileges
export GSETTINGS_SCHEMA_DIR=${APPDIR}/share/glib-2.0/schemas/:${GSETTINGS_SCHEMA_DIR}
export GDK_PIXBUF_MODULE_FILE=${APPDIR}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
export GTK_PATH=${APPDIR}/lib/gtk-3.0
export GTK_DATA_PREFIX=${APPDIR}
export GTK_THEME=Adwaita
# GStreamer environment variables
export GST_PLUGIN_SCANNER=${APPDIR}/libexec/gstreamer-1.0/gst-plugin-scanner
export GST_PLUGIN_SYSTEM_PATH=

# Try to discover plugins only once
PLUGINS_SYMLINK=${HOME}/.cache/gstreamer-1.0/pitivi-gstplugins
ln -s ${APPDIR}/lib/gstreamer-1.0/ ${PLUGINS_SYMLINK}
if [ $? -ne 0 ]; then
    export GST_PLUGIN_PATH=${APPDIR}/lib/gstreamer-1.0/
else
    export GST_PLUGIN_PATH=${PLUGINS_SYMLINK}
fi

export GST_REGISTRY=${HOME}/.cache/gstreamer-1.0/pitivi-bundle-registry
# Python
export PYTHONPATH=${APPDIR}/lib/python2.7/site-packages${PYTHONPATH:+:$PYTHONPATH}
export GI_TYPELIB_PATH=${APPDIR}/lib/girepository-1.0

# Currently we change into the APPDIR directory, this only because of gdk-pixbuf
# and pango cache files which need to specify relative paths.
cd ${APPDIR}

if test -z ${APP_IMAGE_TEST}; then
    # Invoke the app with the arguments passed
    ${APPDIR}/bin/pitivi $*
else
    # Run a shell in test mode
    bash;
fi

# Cleaning up the link to gstplugins
rm ${PLUGINS_SYMLINK}

Fully automated deployment from sources with GitHub Actions (CPU-X)

CPU-X is a GTK application which continuously delivers an AppImage. This is given as an example to help you to save time, but keep in mind adaptations are required.

Workflows

There are two configuration files:

Build process

Disclaimer: following scripts work for Ubuntu 16.04, they will not work out of the box for distributions not based on Debian derivatives.

Build sources

First of all, sources are build as usual; it this case, CMake and Ninja build systems are used. The script is called build_ubuntu.sh.

Note the DESTDIR="$DST_DIR" ninja -C build install at the end of the script: it installs files in AppDir.

Build AppImage

Use linuxdeploy to turn your AppDir into an AppImage, together with linuxdeploy-plugin-gtk. This part is done in build_appimage.sh script.
The default AppRun script do the job. Consider writing new plugins to linuxdeploy to add features to your AppImage.

As you can see, set the UPDATE_INFORMATION variable to allow users to update the AppImage later.

Debug AppImage

Export some environments variables:

  • VERBOSE=1
  • DEBUG=1

Also you can start your binary with GDB to understand why the application crashes (remember to build your application with debug symbols). Look the backtrace on crash (type bt in GDB), it can be useful to understand the root cause of a problem.

Limitations
  1. You can not use pkexec from AppImage, because the root user is not allowed to access to the FUSE mount point (but it works if you extract the AppImage with --appimage-extract and you run the extracted AppRun file).
  2. GTK crashes when Wayland backend is used, hence the GDK_BACKEND=x11 in linuxdeploy-plugin-gtk.
Clone this wiki locally