├── containers ├── gtk4 │ ├── Dockerfile.fedora │ ├── Dockerfile.opensuse │ ├── Dockerfile.ubuntu │ └── Dockerfile.debian └── gtk3 │ ├── Dockerfile.opensuse │ ├── Dockerfile.fedora │ ├── Dockerfile.ubuntu │ └── Dockerfile.debian ├── LICENSE.txt ├── .github └── workflows │ ├── main.yml │ └── containers.yml ├── README.md └── linuxdeploy-plugin-gtk.sh /containers/gtk4/Dockerfile.fedora: -------------------------------------------------------------------------------- 1 | FROM docker.io/fedora:latest AS build-stage 2 | WORKDIR /linuxdeploy 3 | ENV APPIMAGE_EXTRACT_AND_RUN=1 4 | ARG MACHINE=x86_64 5 | ARG APPDIR=/AppDir 6 | RUN dnf install -y wget librsvg2-devel file findutils pkgconfig gtk4 gtk4-devel gtk4-devel-tools \ 7 | gobject-introspection-devel 8 | COPY . . 9 | ADD "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${MACHINE}.AppImage" . 10 | RUN chmod --verbose +x *.sh *.AppImage 11 | RUN ./linuxdeploy-${MACHINE}.AppImage \ 12 | --appdir ${APPDIR} \ 13 | --plugin gtk \ 14 | --output appimage \ 15 | --executable /usr/bin/gtk4-widget-factory \ 16 | --desktop-file /usr/share/applications/org.gtk.WidgetFactory4.desktop \ 17 | --icon-file /usr/share/icons/hicolor/scalable/apps/org.gtk.WidgetFactory4.svg 18 | 19 | FROM docker.io/fedora:latest 20 | VOLUME ["/AppImage"] 21 | WORKDIR /AppImage 22 | ENV APPIMAGE_EXTRACT_AND_RUN=1 23 | ARG MACHINE=x86_64 24 | COPY --from=build-stage "/linuxdeploy/Widget_Factory-${MACHINE}.AppImage" "./Widget_Factory.AppImage" 25 | ENTRYPOINT ["./Widget_Factory.AppImage"] 26 | -------------------------------------------------------------------------------- /containers/gtk3/Dockerfile.opensuse: -------------------------------------------------------------------------------- 1 | FROM docker.io/opensuse/leap:15 AS build-stage 2 | WORKDIR /linuxdeploy 3 | ENV APPIMAGE_EXTRACT_AND_RUN=1 4 | ARG MACHINE=x86_64 5 | ARG APPDIR=/AppDir 6 | RUN zypper install -y wget librsvg2-devel file findutils pkg-config gtk3 gtk3-devel \ 7 | typelib-1_0-Gtk-3_0 gobject-introspection-devel 8 | COPY . . 9 | ADD "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${MACHINE}.AppImage" . 10 | RUN chmod --verbose +x *.sh *.AppImage 11 | RUN ./linuxdeploy-${MACHINE}.AppImage \ 12 | --appdir ${APPDIR} \ 13 | --plugin gtk \ 14 | --output appimage \ 15 | --executable /usr/bin/gtk3-widget-factory \ 16 | --desktop-file /usr/share/applications/gtk3-widget-factory.desktop \ 17 | --icon-file /usr/share/icons/hicolor/256x256/apps/gtk3-widget-factory.png 18 | 19 | FROM docker.io/opensuse/leap:15 20 | VOLUME ["/AppImage"] 21 | WORKDIR /AppImage 22 | ENV APPIMAGE_EXTRACT_AND_RUN=1 23 | ARG MACHINE=x86_64 24 | COPY --from=build-stage "/linuxdeploy/Widget_Factory-${MACHINE}.AppImage" "./Widget_Factory.AppImage" 25 | ENTRYPOINT ["./Widget_Factory.AppImage"] 26 | -------------------------------------------------------------------------------- /containers/gtk3/Dockerfile.fedora: -------------------------------------------------------------------------------- 1 | FROM docker.io/fedora:latest AS build-stage 2 | WORKDIR /linuxdeploy 3 | ENV APPIMAGE_EXTRACT_AND_RUN=1 4 | ARG MACHINE=x86_64 5 | ARG APPDIR=/AppDir 6 | RUN dnf install -y wget librsvg2-devel file findutils pkgconfig gtk3 gtk3-devel \ 7 | gobject-introspection-devel 8 | COPY . . 9 | ADD "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${MACHINE}.AppImage" . 10 | RUN chmod --verbose +x *.sh *.AppImage 11 | RUN gtk-query-immodules-3.0-64 --update-cache 12 | RUN ./linuxdeploy-${MACHINE}.AppImage \ 13 | --appdir ${APPDIR} \ 14 | --plugin gtk \ 15 | --output appimage \ 16 | --executable /usr/bin/gtk3-widget-factory \ 17 | --desktop-file /usr/share/applications/gtk3-widget-factory.desktop \ 18 | --icon-file /usr/share/icons/hicolor/256x256/apps/gtk3-widget-factory.png 19 | 20 | FROM docker.io/fedora:latest 21 | VOLUME ["/AppImage"] 22 | WORKDIR /AppImage 23 | ENV APPIMAGE_EXTRACT_AND_RUN=1 24 | ARG MACHINE=x86_64 25 | COPY --from=build-stage "/linuxdeploy/Widget_Factory-${MACHINE}.AppImage" "./Widget_Factory.AppImage" 26 | ENTRYPOINT ["./Widget_Factory.AppImage"] 27 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2018-2019 TheAssassin and the linuxdeploy contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /containers/gtk4/Dockerfile.opensuse: -------------------------------------------------------------------------------- 1 | # GTK4 is not yet supported on openSUSE Leap 2 | FROM docker.io/opensuse/tumbleweed:latest AS build-stage 3 | WORKDIR /linuxdeploy 4 | ENV APPIMAGE_EXTRACT_AND_RUN=1 5 | ARG MACHINE=x86_64 6 | ARG APPDIR=/AppDir 7 | RUN zypper install -y wget librsvg2-devel file findutils pkg-config gtk4 gtk4-devel \ 8 | typelib-1_0-Gtk-4_0 gobject-introspection-devel 9 | COPY . . 10 | ADD "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${MACHINE}.AppImage" . 11 | RUN chmod --verbose +x *.sh *.AppImage 12 | RUN ./linuxdeploy-${MACHINE}.AppImage \ 13 | --appdir ${APPDIR} \ 14 | --plugin gtk \ 15 | --output appimage \ 16 | --executable /usr/bin/gtk4-widget-factory \ 17 | --desktop-file /usr/share/applications/org.gtk.WidgetFactory4.desktop \ 18 | --icon-file /usr/share/icons/hicolor/scalable/apps/org.gtk.WidgetFactory4.svg 19 | 20 | FROM docker.io/opensuse/tumbleweed:latest 21 | VOLUME ["/AppImage"] 22 | WORKDIR /AppImage 23 | ENV APPIMAGE_EXTRACT_AND_RUN=1 24 | ARG MACHINE=x86_64 25 | COPY --from=build-stage "/linuxdeploy/Widget_Factory-${MACHINE}.AppImage" "./Widget_Factory.AppImage" 26 | ENTRYPOINT ["./Widget_Factory.AppImage"] 27 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Test plugin 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test-plugin: 7 | name: Linux x64_64 8 | runs-on: ubuntu-latest 9 | 10 | env: 11 | REPODIR: "${{ github.workspace }}" 12 | APPDIR: "/tmp/AppDir" 13 | DEPLOY_GTK_VERSION: 3 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | 18 | - name: Setup dependencies 19 | run: | 20 | sudo apt-get update -y -qq 21 | sudo apt-get install -y -qq dpkg-dev libgtk-3-0 libgtk-3-dev gir1.2-gtk-3.0 wget tree libgirepository1.0-dev libfuse2 22 | 23 | - name: Download external binairies 24 | run: | 25 | wget -qc "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" 26 | wget -qc "https://raw.githubusercontent.com/linuxdeploy/misc-plugins/master/tests/test-plugins.sh" 27 | echo "LINUXDEPLOY=$(readlink -f linuxdeploy-x86_64.AppImage)" >> $GITHUB_ENV 28 | chmod +x *.AppImage *.sh 29 | 30 | - name: Run test script 31 | run: | 32 | mkdir -pv "$APPDIR/usr/bin" 33 | ./test-plugins.sh 34 | 35 | - name: Display files inside AppDir 36 | run: tree "$APPDIR" 37 | -------------------------------------------------------------------------------- /containers/gtk3/Dockerfile.ubuntu: -------------------------------------------------------------------------------- 1 | FROM docker.io/ubuntu:focal AS build-stage 2 | WORKDIR /linuxdeploy 3 | ENV APPIMAGE_EXTRACT_AND_RUN=1 4 | ENV DEBIAN_FRONTEND=noninteractive 5 | ARG MACHINE=x86_64 6 | ARG APPDIR=/AppDir 7 | ARG TZ=UTC 8 | RUN ln -snf "/usr/share/zoneinfo/$TZ" "/etc/localtime" && echo "$TZ" > /etc/timezone 9 | RUN apt-get update && \ 10 | apt-get install -y dpkg-dev wget librsvg2-dev file findutils pkg-config libgtk-3-0 \ 11 | libgtk-3-dev gtk-3-examples gir1.2-gtk-3.0 libgirepository1.0-dev libfuse2 12 | COPY . . 13 | ADD "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${MACHINE}.AppImage" . 14 | RUN chmod --verbose +x *.sh *.AppImage 15 | RUN ./linuxdeploy-${MACHINE}.AppImage \ 16 | --appdir ${APPDIR} \ 17 | --plugin gtk \ 18 | --output appimage \ 19 | --executable /usr/bin/gtk3-widget-factory \ 20 | --desktop-file /usr/share/applications/gtk3-widget-factory.desktop \ 21 | --icon-file /usr/share/icons/hicolor/256x256/apps/gtk3-widget-factory.png 22 | 23 | FROM docker.io/ubuntu:focal 24 | VOLUME ["/AppImage"] 25 | WORKDIR /AppImage 26 | ENV APPIMAGE_EXTRACT_AND_RUN=1 27 | ARG MACHINE=x86_64 28 | COPY --from=build-stage "/linuxdeploy/Widget_Factory-${MACHINE}.AppImage" "./Widget_Factory.AppImage" 29 | ENTRYPOINT ["./Widget_Factory.AppImage"] 30 | -------------------------------------------------------------------------------- /containers/gtk4/Dockerfile.ubuntu: -------------------------------------------------------------------------------- 1 | FROM docker.io/ubuntu:jammy AS build-stage 2 | WORKDIR /linuxdeploy 3 | ENV APPIMAGE_EXTRACT_AND_RUN=1 4 | ENV DEBIAN_FRONTEND=noninteractive 5 | ARG MACHINE=x86_64 6 | ARG APPDIR=/AppDir 7 | ARG TZ=UTC 8 | RUN ln -snf "/usr/share/zoneinfo/$TZ" "/etc/localtime" && echo "$TZ" > /etc/timezone 9 | RUN apt-get update && \ 10 | apt-get install -y dpkg-dev wget librsvg2-dev file findutils pkg-config libgtk-4-1 \ 11 | libgtk-4-dev gtk-4-examples gir1.2-gtk-4.0 libgirepository1.0-dev libfuse2 12 | COPY . . 13 | ADD "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${MACHINE}.AppImage" . 14 | RUN chmod --verbose +x *.sh *.AppImage 15 | RUN ./linuxdeploy-${MACHINE}.AppImage \ 16 | --appdir ${APPDIR} \ 17 | --plugin gtk \ 18 | --output appimage \ 19 | --executable /usr/bin/gtk4-widget-factory \ 20 | --desktop-file /usr/share/applications/org.gtk.WidgetFactory4.desktop \ 21 | --icon-file /usr/share/icons/hicolor/scalable/apps/org.gtk.WidgetFactory4.svg 22 | 23 | FROM docker.io/ubuntu:jammy 24 | VOLUME ["/AppImage"] 25 | WORKDIR /AppImage 26 | ENV APPIMAGE_EXTRACT_AND_RUN=1 27 | ARG MACHINE=x86_64 28 | COPY --from=build-stage "/linuxdeploy/Widget_Factory-${MACHINE}.AppImage" "./Widget_Factory.AppImage" 29 | ENTRYPOINT ["./Widget_Factory.AppImage"] 30 | -------------------------------------------------------------------------------- /containers/gtk3/Dockerfile.debian: -------------------------------------------------------------------------------- 1 | FROM docker.io/debian:buster AS build-stage 2 | WORKDIR /linuxdeploy 3 | ENV APPIMAGE_EXTRACT_AND_RUN=1 4 | ENV DEBIAN_FRONTEND=noninteractive 5 | ARG MACHINE=x86_64 6 | ARG APPDIR=/AppDir 7 | ARG TZ=UTC 8 | RUN ln -snf "/usr/share/zoneinfo/$TZ" "/etc/localtime" && echo "$TZ" > /etc/timezone 9 | RUN apt-get update && \ 10 | apt-get install -y dpkg-dev wget librsvg2-dev file findutils pkg-config libgtk-3-0 \ 11 | libgtk-3-dev gtk-3-examples gir1.2-gtk-3.0 libgirepository1.0-dev 12 | COPY . . 13 | ADD "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${MACHINE}.AppImage" "linuxdeploy-${MACHINE}.AppImage" 14 | RUN chmod --verbose +x *.sh *.AppImage 15 | RUN ./linuxdeploy-${MACHINE}.AppImage \ 16 | --appdir ${APPDIR} \ 17 | --plugin gtk \ 18 | --output appimage \ 19 | --executable /usr/bin/gtk3-widget-factory \ 20 | --desktop-file /usr/share/applications/gtk3-widget-factory.desktop \ 21 | --icon-file /usr/share/icons/hicolor/256x256/apps/gtk3-widget-factory.png 22 | 23 | FROM docker.io/debian:buster 24 | VOLUME ["/AppImage"] 25 | WORKDIR /AppImage 26 | ENV APPIMAGE_EXTRACT_AND_RUN=1 27 | ARG MACHINE=x86_64 28 | COPY --from=build-stage "/linuxdeploy/Widget_Factory-${MACHINE}.AppImage" "./Widget_Factory.AppImage" 29 | ENTRYPOINT ["./Widget_Factory.AppImage"] 30 | -------------------------------------------------------------------------------- /containers/gtk4/Dockerfile.debian: -------------------------------------------------------------------------------- 1 | FROM docker.io/debian:bookworm AS build-stage 2 | WORKDIR /linuxdeploy 3 | ENV APPIMAGE_EXTRACT_AND_RUN=1 4 | ENV DEBIAN_FRONTEND=noninteractive 5 | ARG MACHINE=x86_64 6 | ARG APPDIR=/AppDir 7 | ARG TZ=UTC 8 | RUN ln -snf "/usr/share/zoneinfo/$TZ" "/etc/localtime" && echo "$TZ" > /etc/timezone 9 | RUN apt-get update && \ 10 | apt-get install -y dpkg-dev wget librsvg2-dev file findutils pkg-config && \ 11 | apt-get install -y libgtk-4-1 libgtk-4-dev gtk-4-examples gir1.2-gtk-4.0 libgirepository1.0-dev 12 | COPY . . 13 | ADD "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${MACHINE}.AppImage" . 14 | RUN chmod --verbose +x *.sh *.AppImage 15 | RUN ./linuxdeploy-${MACHINE}.AppImage \ 16 | --appdir ${APPDIR} \ 17 | --plugin gtk \ 18 | --output appimage \ 19 | --executable /usr/bin/gtk4-widget-factory \ 20 | --desktop-file /usr/share/applications/org.gtk.WidgetFactory4.desktop \ 21 | --icon-file /usr/share/icons/hicolor/scalable/apps/org.gtk.WidgetFactory4.svg 22 | 23 | FROM docker.io/debian:bookworm 24 | VOLUME ["/AppImage"] 25 | WORKDIR /AppImage 26 | ENV APPIMAGE_EXTRACT_AND_RUN=1 27 | ARG MACHINE=x86_64 28 | COPY --from=build-stage "/linuxdeploy/Widget_Factory-${MACHINE}.AppImage" "./Widget_Factory.AppImage" 29 | ENTRYPOINT ["./Widget_Factory.AppImage"] 30 | -------------------------------------------------------------------------------- /.github/workflows/containers.yml: -------------------------------------------------------------------------------- 1 | name: GTK Widget Factory from containers 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | containers: 7 | strategy: 8 | matrix: 9 | gtk-version: [gtk3, gtk4] 10 | linux-distro: [debian, fedora, opensuse, ubuntu] 11 | arch: [amd64] 12 | include: 13 | - gtk-version: gtk3 14 | linux-distro: debian 15 | arch: 386 16 | - gtk-version: gtk4 17 | linux-distro: debian 18 | arch: 386 19 | 20 | name: ${{ matrix.linux-distro }} ${{ matrix.arch }} ${{ matrix.gtk-version }} 21 | runs-on: ubuntu-latest 22 | 23 | env: 24 | GTK_VERSION: ${{ matrix.gtk-version }} 25 | LINUX_DISTRO: ${{ matrix.linux-distro }} 26 | ARCHITECTURE: ${{ matrix.arch }} 27 | IMAGE_NAME: "linuxdeploy-plugin-${{ matrix.gtk-version }}:${{ matrix.linux-distro }}" 28 | CONTAINER_NAME: "${{ matrix.linux-distro }}-${{ matrix.gtk-version }}" 29 | ARTIFACT_DIR: "${{ github.workspace }}/AppImage" 30 | 31 | steps: 32 | - name: Checkout 33 | uses: actions/checkout@v3 34 | 35 | - name: Set extra environment variables 36 | run: | 37 | case "${ARCHITECTURE}" in 38 | 386) echo MACHINE="i386" >> "$GITHUB_ENV";; 39 | amd64) echo MACHINE="x86_64" >> "$GITHUB_ENV";; 40 | esac 41 | 42 | - name: Build container 43 | run: | 44 | buildah bud --arch="${ARCHITECTURE}" --build-arg MACHINE="${MACHINE}" --tag "${IMAGE_NAME}" --file "containers/${GTK_VERSION}/Dockerfile.${LINUX_DISTRO}" . 45 | 46 | - name: Extract AppImage from container 47 | run: | 48 | mkdir --verbose --parents "${ARTIFACT_DIR}" 49 | podman run --arch="${ARCHITECTURE}" --name "${CONTAINER_NAME}" --interactive --detach --rm --entrypoint /bin/bash "${IMAGE_NAME}" 50 | podman cp "${CONTAINER_NAME}:/AppImage/Widget_Factory.AppImage" "${ARTIFACT_DIR}" 51 | podman stop "${CONTAINER_NAME}" --time 0 52 | 53 | - uses: actions/upload-artifact@v3 54 | with: 55 | name: ${{ matrix.gtk-version }}_${{ matrix.linux-distro }}_${{ env.MACHINE }} 56 | path: ${{ env.ARTIFACT_DIR }}/ 57 | retention-days: 30 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # linuxdeploy-plugin-gtk 2 | 3 | This is an (as of yet experimental) plugin for linuxdeploy. Its job is to bundle additional resources for applications that use GTK, and for common dependencies. Those involve GLib schemas for instance. 4 | 5 | ## Dependencies 6 | 7 | This plugin requires the following dependencies in order to work properly: 8 | 9 | - `file` command 10 | - `find` command 11 | - `pkg-config` or `pkgconf` command 12 | - librsvg2 development files 13 | - GTK development files 14 | - GObject Introspection development files 15 | 16 | ## Usage 17 | 18 | ```bash 19 | # get linuxdeploy and linuxdeploy-plugin-gtk 20 | > wget -c "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh" 21 | > wget -c "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage" 22 | # make them executable so that we can call them (and also, plugins called from linuxdeploy are called like binaries) 23 | > chmod +x linuxdeploy-x86_64.AppImage linuxdeploy-plugin-gtk.sh 24 | 25 | # get list of variables 26 | > ./linuxdeploy-plugin-gtk.sh --help 27 | 28 | # first option: install your app into your AppDir via `make install` etc. 29 | # second option: bundle your app's main executables manually 30 | # see https://docs.appimage.org/packaging-guide/from-source/native-binaries.html for more information 31 | > [...] 32 | 33 | # call through linuxdeploy 34 | > ./linuxdeploy-x86_64.AppImage --appdir AppDir --plugin gtk --output appimage --icon-file mypackage.png --desktop-file mypackage.desktop 35 | ``` 36 | 37 | 38 | ## How it Works 39 | 40 | This plugin is written in bash and goes through a series of steps to make sure 41 | that all the libraries and other files are pulled in for GTK apps to work 42 | properly once in the AppImage. The steps include: 43 | 44 | 1. Detects the GTK version to use 45 | 1. Installs itself as a hook in `$APPDIR/apprun-hooks` 46 | 1. Uses `gsettings` to set a light or dark adwaita theme 47 | 1. Installs the GLib schemas and then runs `glib-compile-schemas` on them 48 | 1. Installs the GIRepository typelibs for gobject-introspection 49 | 1. Copies the GTK libs and sets GTK path related environmental variables to 50 | 1 locations in the APPDIR 51 | 1. Updates the input method module registration (immodules) cache 52 | 1. Installs the GDK Pixbuf libraries and cache, and then updates the cache 53 | 1 using gdk-pixbuf-query-loaders 54 | 1. Installs additional libraries including Gdk, GObject, Gio, librsvg, Pango, 55 | 1 PangoCairo, and PangoFT2 56 | 1. Manually sets the RPATH for the GTK modules 57 | -------------------------------------------------------------------------------- /linuxdeploy-plugin-gtk.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # GTK3 environment variables: https://developer.gnome.org/gtk3/stable/gtk-running.html 4 | # GTK4 environment variables: https://developer.gnome.org/gtk4/stable/gtk-running.html 5 | 6 | # abort on all errors 7 | set -e 8 | 9 | if [ "$DEBUG" != "" ]; then 10 | set -x 11 | verbose="--verbose" 12 | fi 13 | 14 | SCRIPT="$(basename "$(readlink -f "$0")")" 15 | 16 | show_usage() { 17 | echo "Usage: $SCRIPT --appdir " 18 | echo 19 | echo "Bundles resources for applications that use GTK into an AppDir" 20 | echo 21 | echo "Required variables:" 22 | echo " LINUXDEPLOY=\".../linuxdeploy\" path to linuxdeploy (e.g., AppImage); set automatically when plugin is run directly by linuxdeploy" 23 | echo 24 | echo "Optional variables:" 25 | echo " DEPLOY_GTK_VERSION (major version of GTK to deploy, e.g. '2', '3' or '4'; auto-detect by default)" 26 | } 27 | 28 | variable_is_true() { 29 | local var="$1" 30 | 31 | if [ -n "$var" ] && { [ "$var" == "true" ] || [ "$var" -gt 0 ]; } 2> /dev/null; then 32 | return 0 # true 33 | else 34 | return 1 # false 35 | fi 36 | } 37 | 38 | get_pkgconf_variable() { 39 | local variable="$1" 40 | local library="$2" 41 | local default_value="$3" 42 | 43 | pkgconfig_ret="$("$PKG_CONFIG" --variable="$variable" "$library")" 44 | if [ -n "$pkgconfig_ret" ]; then 45 | echo "$pkgconfig_ret" 46 | elif [ -n "$default_value" ]; then 47 | echo "$default_value" 48 | else 49 | echo "$0: there is no '$variable' variable for '$library' library." > /dev/stderr 50 | echo "Please check the '$library.pc' file is present in \$PKG_CONFIG_PATH (you may need to install the appropriate -dev/-devel package)." > /dev/stderr 51 | exit 1 52 | fi 53 | } 54 | 55 | copy_tree() { 56 | local src=("${@:1:$#-1}") 57 | local dst="${*:$#}" 58 | 59 | for elem in "${src[@]}"; do 60 | mkdir -p "${dst::-1}$elem" 61 | cp "$elem" --archive --parents --target-directory="$dst" $verbose 62 | done 63 | } 64 | 65 | copy_lib_tree() { 66 | # The source lib directory could be /usr/lib, /usr/lib64, or /usr/lib/x86_64-linux-gnu 67 | # Therefore, when copying lib directories, we need to transform that target path 68 | # to a consistent /usr/lib 69 | local src=("${@:1:$#-1}") 70 | local dst="${*:$#}" 71 | 72 | for elem in "${src[@]}"; do 73 | mkdir -p "${dst::-1}${elem/$LD_GTK_LIBRARY_PATH//usr/lib}" 74 | pushd "$LD_GTK_LIBRARY_PATH" 75 | cp "$(realpath --relative-to="$LD_GTK_LIBRARY_PATH" "$elem")" --archive --parents --target-directory="$dst/usr/lib" $verbose 76 | popd 77 | done 78 | } 79 | 80 | get_triplet_path() { 81 | if command -v dpkg-architecture > /dev/null; then 82 | echo "/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)" 83 | fi 84 | } 85 | 86 | 87 | 88 | search_library_path() { 89 | PATH_ARRAY=( 90 | "$(get_triplet_path)" 91 | "/usr/lib64" 92 | "/usr/lib" 93 | ) 94 | 95 | for path in "${PATH_ARRAY[@]}"; do 96 | if [ -d "$path" ]; then 97 | echo "$path" 98 | return 0 99 | fi 100 | done 101 | } 102 | 103 | search_tool() { 104 | local tool="$1" 105 | local directory="$2" 106 | 107 | if command -v "$tool"; then 108 | return 0 109 | fi 110 | 111 | PATH_ARRAY=( 112 | "$(get_triplet_path)/$directory/$tool" 113 | "/usr/lib64/$directory/$tool" 114 | "/usr/lib/$directory/$tool" 115 | "/usr/bin/$tool" 116 | "/usr/bin/$tool-64" 117 | "/usr/bin/$tool-32" 118 | ) 119 | 120 | for path in "${PATH_ARRAY[@]}"; do 121 | if [ -x "$path" ]; then 122 | echo "$path" 123 | return 0 124 | fi 125 | done 126 | } 127 | 128 | DEPLOY_GTK_VERSION="${DEPLOY_GTK_VERSION:-0}" # When not set by user, this variable use the integer '0' as a sentinel value 129 | APPDIR= 130 | 131 | while [ "$1" != "" ]; do 132 | case "$1" in 133 | --plugin-api-version) 134 | echo "0" 135 | exit 0 136 | ;; 137 | --appdir) 138 | APPDIR="$2" 139 | shift 140 | shift 141 | ;; 142 | --help) 143 | show_usage 144 | exit 0 145 | ;; 146 | *) 147 | echo "Invalid argument: $1" 148 | echo 149 | show_usage 150 | exit 1 151 | ;; 152 | esac 153 | done 154 | 155 | if [ "$APPDIR" == "" ]; then 156 | show_usage 157 | exit 1 158 | fi 159 | 160 | APPDIR="$(realpath "$APPDIR")" 161 | mkdir -p "$APPDIR" 162 | 163 | . /etc/os-release 164 | if [ "$ID" = "debian" ] || [ "$ID" = "ubuntu" ]; then 165 | if ! command -v dpkg-architecture &>/dev/null; then 166 | echo -e "$0: dpkg-architecture not found.\nInstall dpkg-dev then re-run the plugin." 167 | exit 1 168 | fi 169 | fi 170 | 171 | if command -v pkgconf > /dev/null; then 172 | PKG_CONFIG="pkgconf" 173 | elif command -v pkg-config > /dev/null; then 174 | PKG_CONFIG="pkg-config" 175 | else 176 | echo "$0: pkg-config/pkgconf not found in PATH, aborting" 177 | exit 1 178 | fi 179 | 180 | # GTK's library path *must not* have a trailing slash for later parameter substitution to work properly 181 | LD_GTK_LIBRARY_PATH="$(realpath "${LD_GTK_LIBRARY_PATH:-$(search_library_path)}")" 182 | 183 | if ! command -v find &>/dev/null && ! type find &>/dev/null; then 184 | echo -e "$0: find not found.\nInstall findutils then re-run the plugin." 185 | exit 1 186 | fi 187 | 188 | if [ -z "$LINUXDEPLOY" ]; then 189 | echo -e "$0: LINUXDEPLOY environment variable is not set.\nDownload a suitable linuxdeploy AppImage, set the environment variable and re-run the plugin." 190 | exit 1 191 | fi 192 | 193 | gtk_versions=0 # Count major versions of GTK when auto-detect GTK version 194 | if [ "$DEPLOY_GTK_VERSION" -eq 0 ]; then 195 | echo "Determining which GTK version to deploy" 196 | while IFS= read -r -d '' file; do 197 | if [ "$DEPLOY_GTK_VERSION" -ne 2 ] && ldd "$file" | grep -q "libgtk-x11-2.0.so"; then 198 | DEPLOY_GTK_VERSION=2 199 | gtk_versions="$((gtk_versions+1))" 200 | fi 201 | if [ "$DEPLOY_GTK_VERSION" -ne 3 ] && ldd "$file" | grep -q "libgtk-3.so"; then 202 | DEPLOY_GTK_VERSION=3 203 | gtk_versions="$((gtk_versions+1))" 204 | fi 205 | if [ "$DEPLOY_GTK_VERSION" -ne 4 ] && ldd "$file" | grep -q "libgtk-4.so"; then 206 | DEPLOY_GTK_VERSION=4 207 | gtk_versions="$((gtk_versions+1))" 208 | fi 209 | done < <(find "$APPDIR/usr/bin" -executable -type f -print0) 210 | fi 211 | 212 | if [ "$gtk_versions" -gt 1 ]; then 213 | echo "$0: can not deploy multiple GTK versions at the same time." 214 | echo "Please set DEPLOY_GTK_VERSION to {2, 3, 4}." 215 | exit 1 216 | elif [ "$DEPLOY_GTK_VERSION" -eq 0 ]; then 217 | echo "$0: failed to auto-detect GTK version." 218 | echo "Please set DEPLOY_GTK_VERSION to {2, 3, 4}." 219 | exit 1 220 | fi 221 | 222 | echo "Installing AppRun hook" 223 | HOOKSDIR="$APPDIR/apprun-hooks" 224 | HOOKFILE="$HOOKSDIR/linuxdeploy-plugin-gtk.sh" 225 | mkdir -p "$HOOKSDIR" 226 | cat > "$HOOKFILE" <<\EOF 227 | #! /usr/bin/env bash 228 | 229 | COLOR_SCHEME="$(dbus-send --session --dest=org.freedesktop.portal.Desktop --type=method_call --print-reply --reply-timeout=1000 /org/freedesktop/portal/desktop org.freedesktop.portal.Settings.Read 'string:org.freedesktop.appearance' 'string:color-scheme' 2> /dev/null | tail -n1 | cut -b35- | cut -d' ' -f2 || printf '')" 230 | if [ -z "$COLOR_SCHEME" ]; then 231 | COLOR_SCHEME="$(gsettings get org.gnome.desktop.interface color-scheme 2> /dev/null || printf '')" 232 | fi 233 | case "$COLOR_SCHEME" in 234 | "1"|"'prefer-dark'") GTK_THEME_VARIANT="dark";; 235 | "2"|"'prefer-light'") GTK_THEME_VARIANT="light";; 236 | *) GTK_THEME_VARIANT="light";; 237 | esac 238 | APPIMAGE_GTK_THEME="${APPIMAGE_GTK_THEME:-"Adwaita:$GTK_THEME_VARIANT"}" # Allow user to override theme (discouraged) 239 | 240 | export APPDIR="${APPDIR:-"$(dirname "$(realpath "$0")")"}" # Workaround to run extracted AppImage 241 | export GTK_DATA_PREFIX="$APPDIR" 242 | export GTK_THEME="$APPIMAGE_GTK_THEME" # Custom themes are broken 243 | export GDK_BACKEND=x11 # Crash with Wayland backend on Wayland 244 | export XDG_DATA_DIRS="$APPDIR/usr/share:/usr/share:$XDG_DATA_DIRS" # g_get_system_data_dirs() from GLib 245 | EOF 246 | 247 | echo "Installing GLib schemas" 248 | # Note: schemasdir is undefined on Ubuntu 16.04 249 | glib_schemasdir="$(get_pkgconf_variable "schemasdir" "gio-2.0" "/usr/share/glib-2.0/schemas")" 250 | copy_tree "$glib_schemasdir" "$APPDIR/" 251 | glib-compile-schemas "$APPDIR/$glib_schemasdir" 252 | cat >> "$HOOKFILE" <> "$HOOKFILE" <> "$HOOKFILE" < "$APPDIR/${gtk3_immodules_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" 287 | else 288 | echo "WARNING: gtk-query-immodules-3.0 not found" 289 | fi 290 | if [ ! -f "$APPDIR/${gtk3_immodules_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" ]; then 291 | echo "WARNING: immodules.cache file is missing" 292 | fi 293 | sed -i "s|$gtk3_libdir/3.0.0/immodules/||g" "$APPDIR/${gtk3_immodules_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" 294 | ;; 295 | 4) 296 | echo "Installing GTK 4.0 modules" 297 | gtk4_exec_prefix="$(get_pkgconf_variable "exec_prefix" "gtk4" "/usr")" 298 | gtk4_libdir="$(get_pkgconf_variable "libdir" "gtk4")/gtk-4.0" 299 | gtk4_path="$gtk4_libdir" 300 | copy_lib_tree "$gtk4_libdir" "$APPDIR/" 301 | cat >> "$HOOKFILE" <> "$HOOKFILE" < "$APPDIR/${gdk_pixbuf_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" 326 | else 327 | echo "WARNING: gdk-pixbuf-query-loaders not found" 328 | fi 329 | if [ ! -f "$APPDIR/${gdk_pixbuf_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" ]; then 330 | echo "WARNING: loaders.cache file is missing" 331 | fi 332 | sed -i "s|$gdk_pixbuf_moduledir/||g" "$APPDIR/${gdk_pixbuf_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" 333 | 334 | echo "Copying more libraries" 335 | gobject_libdir="$(get_pkgconf_variable "libdir" "gobject-2.0" "$LD_GTK_LIBRARY_PATH")" 336 | gio_libdir="$(get_pkgconf_variable "libdir" "gio-2.0" "$LD_GTK_LIBRARY_PATH")" 337 | librsvg_libdir="$(get_pkgconf_variable "libdir" "librsvg-2.0" "$LD_GTK_LIBRARY_PATH")" 338 | pango_libdir="$(get_pkgconf_variable "libdir" "pango" "$LD_GTK_LIBRARY_PATH")" 339 | pangocairo_libdir="$(get_pkgconf_variable "libdir" "pangocairo" "$LD_GTK_LIBRARY_PATH")" 340 | pangoft2_libdir="$(get_pkgconf_variable "libdir" "pangoft2" "$LD_GTK_LIBRARY_PATH")" 341 | FIND_ARRAY=( 342 | "$gdk_libdir" "libgdk_pixbuf-*.so*" 343 | "$gobject_libdir" "libgobject-*.so*" 344 | "$gio_libdir" "libgio-*.so*" 345 | "$librsvg_libdir" "librsvg-*.so*" 346 | "$pango_libdir" "libpango-*.so*" 347 | "$pangocairo_libdir" "libpangocairo-*.so*" 348 | "$pangoft2_libdir" "libpangoft2-*.so*" 349 | ) 350 | LIBRARIES=() 351 | for (( i=0; i<${#FIND_ARRAY[@]}; i+=2 )); do 352 | directory=${FIND_ARRAY[i]} 353 | library=${FIND_ARRAY[i+1]} 354 | while IFS= read -r -d '' file; do 355 | LIBRARIES+=( "--library=$file" ) 356 | done < <(find "$directory" \( -type l -o -type f \) -name "$library" -print0) 357 | done 358 | 359 | env LINUXDEPLOY_PLUGIN_MODE=1 "$LINUXDEPLOY" --appdir="$APPDIR" "${LIBRARIES[@]}" 360 | 361 | # Create symbolic links as a workaround 362 | # Details: https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/issues/24#issuecomment-1030026529 363 | echo "Manually setting rpath for GTK modules" 364 | PATCH_ARRAY=( 365 | "$gtk3_immodulesdir" 366 | "$gtk3_printbackendsdir" 367 | "$gdk_pixbuf_moduledir" 368 | ) 369 | for directory in "${PATCH_ARRAY[@]}"; do 370 | while IFS= read -r -d '' file; do 371 | ln $verbose -sf "${file/$LD_GTK_LIBRARY_PATH\//}" "$APPDIR/usr/lib" 372 | done < <(find "$directory" -name '*.so' -print0) 373 | done 374 | --------------------------------------------------------------------------------