From a7a7b95e8c2db27522aa489bef596bbca0fe4294 Mon Sep 17 00:00:00 2001 From: TGP17 Date: Mon, 2 Oct 2023 12:06:46 +0200 Subject: [PATCH] Add scripts and files for AppImage packaging in dist folder --- dist/appimage/AppRun-hook.sh | 9 + dist/appimage/AppRun.sh | 10 ++ dist/appimage/AppRun.wrapped.sh | 43 +++++ dist/appimage/deploy-linux.sh | 212 ++++++++++++++++++++++++ dist/appimage/exec-aarch64.so | Bin 0 -> 10264 bytes dist/appimage/package-appimage-arm64.sh | 79 +++++++++ 6 files changed, 353 insertions(+) create mode 100755 dist/appimage/AppRun-hook.sh create mode 100755 dist/appimage/AppRun.sh create mode 100755 dist/appimage/AppRun.wrapped.sh create mode 100755 dist/appimage/deploy-linux.sh create mode 100755 dist/appimage/exec-aarch64.so create mode 100755 dist/appimage/package-appimage-arm64.sh diff --git a/dist/appimage/AppRun-hook.sh b/dist/appimage/AppRun-hook.sh new file mode 100755 index 000000000..f85fcb32a --- /dev/null +++ b/dist/appimage/AppRun-hook.sh @@ -0,0 +1,9 @@ +# try to make Qt apps more "native looking" on Gtk-based desktops, if possible +# see https://github.com/AppImage/AppImageKit/issues/977#issue-462374883 +case "${XDG_CURRENT_DESKTOP}" in + *GNOME*|*gnome*|*X-Cinnamon*|*XFCE*) + export QT_QPA_PLATFORMTHEME=gtk3 + ;; +esac +export GDK_BACKEND=x11 +export QT_QPA_PLATFORM=xcb diff --git a/dist/appimage/AppRun.sh b/dist/appimage/AppRun.sh new file mode 100755 index 000000000..c777a8f9d --- /dev/null +++ b/dist/appimage/AppRun.sh @@ -0,0 +1,10 @@ +#! /usr/bin/env bash + +# make sure errors in sourced scripts will cause this script to stop +set -e + +this_dir="$(readlink -f "$(dirname "$0")")" + +source "$this_dir"/apprun-hooks/"AppRun-hook" + +exec "$this_dir"/AppRun.wrapped "$@" diff --git a/dist/appimage/AppRun.wrapped.sh b/dist/appimage/AppRun.wrapped.sh new file mode 100755 index 000000000..6d72fa1de --- /dev/null +++ b/dist/appimage/AppRun.wrapped.sh @@ -0,0 +1,43 @@ +#!/bin/sh -e + +appdir=$(readlink -f ${APPDIR:-$(dirname "$0")}) + +desktopfile=$(ls -1 "$appdir"/*.desktop | head -n1) + +if [ ! -f "$desktopfile" ]; then + echo "No desktop file found!" + exit 1 +fi + +library_path="" +library_type= + +binary="$appdir"/usr/bin/$(sed -n 's|^Exec=||p' "$desktopfile" | cut -d' ' -f1) + +for lib_tuple in libstdc++.so.6:'^GLIBCXX_[0-9]' libgcc_s.so.1:'^GCC_[0-9]'; do + lib_filename=$(echo "$lib_tuple" | cut -d: -f1) + version_prefix=$(echo "$lib_tuple" | cut -d: -f2) + lib_dir="$appdir"/usr/optional/"$lib_filename"/ + lib_path="$lib_dir"/"$lib_filename" + if [ -e "$lib_path" ]; then + lib=$(PATH="/sbin:$PATH" ldconfig -p | grep "$lib_filename" | awk 'NR==1 {print $NF}') + sym_sys=$(tr '\0' '\n' < "$lib" | grep -e "$version_prefix" | sort --version-sort | tail -n1) + sym_app=$(tr '\0' '\n' < "$lib_path" | grep -e "$version_prefix" | sort --version-sort | tail -n1) + if [ z$(printf "${sym_sys}\n${sym_app}" | sort --version-sort | tail -n1) != z"$sym_sys" ]; then + export library_path="$lib_dir"/:"$library_path" + fi + fi +done + +export LD_LIBRARY_PATH="$library_path:$LD_LIBRARY_PATH" + +if [ -n "$cxxpath" ] || [ -n "$gccpath" ]; then + if [ -e "$appdir"/usr/optional/exec.so ]; then + export LD_PRELOAD="$appdir"/usr/optional/exec.so:"$LD_PRELOAD" + fi +fi + +#echo ">>>>> $LD_LIBRARY_PATH" +#echo ">>>>> $LD_PRELOAD" + +exec "$binary" "$@" diff --git a/dist/appimage/deploy-linux.sh b/dist/appimage/deploy-linux.sh new file mode 100755 index 000000000..4b3f61daa --- /dev/null +++ b/dist/appimage/deploy-linux.sh @@ -0,0 +1,212 @@ +#!/bin/bash +# [DEPLOY_QT=1] deploy-linux.sh +# (Simplified) bash re-implementation of [linuxdeploy](https://github.com/linuxdeploy). +# Reads [executable] and copies required libraries to [AppDir]/usr/lib +# Copies the desktop and svg icon to [AppDir] +# Respects the AppImage excludelist +# +# Unlike linuxdeploy, this does not: +# - Copy any icon other than svg (too lazy to add that without a test case) +# - Do any verification on the desktop file +# - Run any linuxdeploy plugins +# - *Probably other things I didn't know linuxdeploy can do* +# +#~ set -x +export _PREFIX="/usr" +export _LIB_DIRS="lib64 lib" +export _QT_PLUGIN_PATH="${_PREFIX}/lib64/qt6/plugins" +export _EXCLUDES="ld-linux.so.2 \ +ld-linux-x86-64.so.2 \ +ld-linux-aarch64.so.1 \ +libasound.so.2 \ +libc.so.6 \ +libdl.so.2 \ +libgcc_s.so.1 \ +libm.so.6 \ +libpthread.so.0 \ +librt.so.1 \ +libstdc++.so.6 \ +libEGL.so.1 \ +libfreetype.so.6 \ +libGL.so.1 \ +libfribidi.so.0 \ +libGLX.so.0 \ +libgbm.so.1 \ +libGLdispatch.so.0 \ +libgdk-3.so.0 \ +libICE.so.6 \ +libgdk_pixbuf-2.0.so.0 \ +libOpenGL.so.0 \ +libgio-2.0.so.0 \ +libQt6EglFSDeviceIntegration.so.6 \ +libgpg-error.so.0 \ +libQt6OpenGL.so.6 \ +libgtk-3.so.0 \ +libSM.so.6 \ +libharfbuzz.so.0 \ +libX11.so.6 \ +libXcomposite.so.1 \ +libXcursor.so.1 \ +libXdamage.so.1 \ +libinput.so.10 \ +libXext.so.6 \ +libmount.so.1 \ +libXfixes.so.3 \ +libmtdev.so.1 \ +libXi.so.6 \ +libpango-1.0.so.0 \ +libXinerama.so.1 \ +libpangocairo-1.0.so.0 \ +libXrandr.so.2 \ +libpangoft2-1.0.so.0 \ +libXrender.so.1 \ +libpcre2-8.so.0 \ +libatk-1.0.so.0 \ +libpixman-1.so.0 \ +libatk-bridge-2.0.so.0 \ +libresolv.so.2 \ +libatspi.so.0 \ +libselinux.so.1 \ +libblkid.so.1 \ +libcairo-gobject.so.2 \ +libuuid.so.1 \ +libcairo.so.2 \ +libthai.so.0 \ +libcom_err.so.2 \ +libts.so.0 \ +libdatrie.so.1 \ +libwacom.so.2 \ +libdrm.so.2 \ +libxcb-icccm.so.4 \ +libepoxy.so.0 \ +libxcb-randr.so.0 \ +libevdev.so.2 \ +libxcb.so.1 \ +libexpat.so.1 \ +libfontconfig.so.1 \ +libz.so.1" + +export _EXECUTABLE="$1" + +# Get possible system library paths +export _SYSTEM_PATHS=$(echo -n $PATH | tr ":" " ") +export _SEARCH_PATHS= +for i in ${_LIB_DIRS}; do + for j in ${_SYSTEM_PATHS}; do + _TRY_PATH="$(readlink -e "$j/../$i" || true)" + if [[ -n "${_TRY_PATH}" ]]; then + _SEARCH_PATHS="${_SEARCH_PATHS} ${_TRY_PATH}" + fi + done +done +_SEARCH_PATHS="${_SEARCH_PATHS} $(patchelf --print-rpath $_EXECUTABLE | tr ':' ' ')" +# Get a list of only unique ones +_SEARCH_PATHS=$(echo -n "${_SEARCH_PATHS}" | sed 's/ /\n/g' | sort -u) + +# find_library [library] +# Finds the full path of partial name [library] in _SEARCH_PATHS +# This is a time-consuming function. +_NOT_FOUND="" +function find_library { + local _PATH="" + for i in ${_SEARCH_PATHS}; do + _PATH=$(find $i -regex ".*$(echo -n $1 | tr '+' '.')" -print -quit) + if [ "$_PATH" != "" ]; then + break + fi + done + if [ "$_PATH" != "" ]; then + echo -n $(readlink -e $_PATH) + fi +} + +# get_dep_names [object] +# Returns a space-separated list of all required libraries needed by [object]. +function get_dep_names { + echo -n $(patchelf --print-needed $1) +} + +# get_deps [object] [library_path] +# Finds and installs all libraries required by [object] to [library_path]. +# This is a recursive function that also depends on find_library. +function get_deps { + local _DEST=$2 + for i in $(get_dep_names $1); do + _EXCL=`echo "$_EXCLUDES" | tr ' ' '\n' | grep $i` + if [ "$_EXCL" != "" ]; then + #>&2 echo "$i is on the exclude list... skipping" + continue + fi + if [ -f $_DEST/$i ]; then + continue + fi + local _LIB=$(find_library $i) + if [ -z $_LIB ]; then + echo -n "$i:" + continue + fi + >&2 cp -v $_LIB $_DEST/$i & + get_deps $_LIB $_DEST + done +} + +export -f get_deps +export -f get_dep_names +export -f find_library + +_ERROR=0 +if [ -z "$_EXECUTABLE" ]; then + _ERROR=1 +fi + +if [ "$_ERROR" -eq 1 ]; then + >&2 echo "usage: $0 [AppDir]" + exit 1 +fi + +LIB_DIR="$(readlink -m $(dirname $_EXECUTABLE)/../lib)" +mkdir -p $LIB_DIR +_NOT_FOUND=$(get_deps $_EXECUTABLE $LIB_DIR) + +if [ "${DEPLOY_QT}" == "1" ]; then + # Find Qt path from search paths + for i in ${_SEARCH_PATHS}; do + _QT_CORE_LIB=$(find ${i} -type f -regex '.*/libQt6Core\.so.*' | head -n 1) + if [ -n "${_QT_CORE_LIB}" ]; then + _QT_PATH=$(dirname ${_QT_CORE_LIB})/../ + break + fi + done + + _QT_PLUGIN_PATH=$(readlink -e $(find ${_QT_PATH} -type d -regex '.*/plugins/platforms' | head -n 1)/../) + + for i in audio bearer imageformats mediaservice platforminputcontexts platformthemes xcbglintegrations platforms wayland-decoration-client wayland-graphics-integration-client wayland-graphics-integration-server wayland-shell-integration; do + mkdir -p ${LIB_DIR}/../plugins/${i} + cp -rnv ${_QT_PLUGIN_PATH}/${i}/*.so ${LIB_DIR}/../plugins/${i} + find ${LIB_DIR}/../plugins/ -type f -regex '.*\.so' -exec patchelf --set-rpath '$ORIGIN/../../lib:$ORIGIN' {} ';' + # Find any remaining libraries needed for Qt libraries + _NOT_FOUND+=$(find ${LIB_DIR}/../plugins/${i} -type f -exec bash -c "get_deps {} $LIB_DIR" ';') + done + + _QT_CONF=${LIB_DIR}/../bin/qt.conf + echo "[Paths]" > ${_QT_CONF} + echo "Prefix = ../" >> ${_QT_CONF} + echo "Plugins = plugins" >> ${_QT_CONF} + echo "Imports = qml" >> ${_QT_CONF} + echo "Qml2Imports = qml" >> ${_QT_CONF} +fi + +# Fix rpath of libraries and executable so they can find the packaged libraries +find ${LIB_DIR} -type f -exec patchelf --set-rpath '$ORIGIN' {} ';' +patchelf --set-rpath '$ORIGIN/../lib' $_EXECUTABLE + +_APPDIR=$2 +cd ${_APPDIR} + +cp -nvs $(find -type f -regex '.*/icons/.*\.svg' || head -n 1) ./ +cp -nvs $(find -type f -regex '.*/applications/.*\.desktop' || head -n 1) ./ + +if [ "${_NOT_FOUND}" != "" ]; then + >&2 echo "WARNING: failed to find the following libraries:" + >&2 echo "$(echo -n $_NOT_FOUND | tr ':' '\n' | sort -u)" +fi diff --git a/dist/appimage/exec-aarch64.so b/dist/appimage/exec-aarch64.so new file mode 100755 index 0000000000000000000000000000000000000000..2548b858f126d5aa78b952e433db567059f7fb7f GIT binary patch literal 10264 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 bQ(^mCi*UBrDaY1T-!&cXbsa>V?HK+i(dKcv literal 0 HcmV?d00001 diff --git a/dist/appimage/package-appimage-arm64.sh b/dist/appimage/package-appimage-arm64.sh new file mode 100755 index 000000000..bcb51ee09 --- /dev/null +++ b/dist/appimage/package-appimage-arm64.sh @@ -0,0 +1,79 @@ +mv ./linux-arm64-appimage/AppDir.7z ./AppDir.7z +7z x AppDir.7z + +# Seperate AppDir for all Citra executables +cp -r AppDir AppDir-qt +cp -r AppDir AppDir-room + +rm -vf AppDir/usr/bin/citra-qt AppDir/usr/bin/citra-room +rm -vf AppDir-room/usr/bin/citra AppDir-room/usr/bin/citra-qt +rm -vf AppDir-qt/usr/bin/citra AppDir-qt/usr/bin/citra-room + +mv ./AppDir/usr/share/applications/citra-qt.desktop ./AppDir/usr/share/applications/citra.desktop +mv ./AppDir-room/usr/share/applications/citra-qt.desktop ./AppDir-room/usr/share/applications/citra-room.desktop + +# Download appimagetool, needed to build an AppImage +wget https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage + +# Set executable bit +chmod a+x appimagetool-x86_64.AppImage + +# Workaround for https://github.com/AppImage/AppImageKit/issues/828 +export APPIMAGE_EXTRACT_AND_RUN=1 + +# Deploy Citra's needed dependencies +DEPLOY_QT=0 ./dist/appimage/deploy-linux.sh AppDir/usr/bin/citra AppDir +DEPLOY_QT=0 ./dist/appimage/deploy-linux.sh AppDir-room/usr/bin/citra-room AppDir-room +DEPLOY_QT=1 ./dist/appimage/deploy-linux.sh AppDir-qt/usr/bin/citra-qt AppDir-qt + +mkdir AppDir/apprun-hooks +mkdir -p AppDir/usr/optional +mkdir -p AppDir/usr/optional/libstdc++ +mkdir -p AppDir/usr/optional/libgcc_s + +mkdir AppDir-room/apprun-hooks +mkdir -p AppDir-room/usr/optional +mkdir -p AppDir-room/usr/optional/libstdc++ +mkdir -p AppDir-room/usr/optional/libgcc_s + +mkdir AppDir-qt/apprun-hooks +mkdir -p AppDir-qt/usr/optional +mkdir -p AppDir-qt/usr/optional/libstdc++ +mkdir -p AppDir-qt/usr/optional/libgcc_s + +cp ./dist/appimage/AppRun.sh AppDir/AppRun +cp ./dist/appimage/AppRun.wrapped.sh AppDir/AppRun.wrapped +cp ./dist/appimage/AppRun-hook.sh AppDir/apprun-hooks/AppRun-hook +cp ./dist/appimage/exec-aarch64.so AppDir/usr/optional/exec.so +cp --dereference /usr/lib/aarch64-linux-gnu/libstdc++.so.6 AppDir/usr/optional/libstdc++/libstdc++.so.6 +cp --dereference /lib/aarch64-linux-gnu/libgcc_s.so.1 AppDir/usr/optional/libgcc_s/libgcc_s.so.1 + +cp ./dist/appimage/AppRun.sh AppDir-room/AppRun +cp ./dist/appimage/AppRun.wrapped.sh AppDir-room/AppRun.wrapped +cp ./dist/appimage/AppRun-hook.sh AppDir-room/apprun-hooks/AppRun-hook +cp ./dist/appimage/exec-aarch64.so AppDir-room/usr/optional/exec.so +cp --dereference /usr/lib/aarch64-linux-gnu/libstdc++.so.6 AppDir-room/usr/optional/libstdc++/libstdc++.so.6 +cp --dereference /lib/aarch64-linux-gnu/libgcc_s.so.1 AppDir-room/usr/optional/libgcc_s/libgcc_s.so.1 + +cp ./dist/appimage/AppRun.sh AppDir-qt/AppRun +cp ./dist/appimage/AppRun.wrapped.sh AppDir-qt/AppRun.wrapped +cp ./dist/appimage/AppRun-hook.sh AppDir-qt/apprun-hooks/AppRun-hook +cp ./dist/appimage/exec-aarch64.so AppDir-qt/usr/optional/exec.so +cp --dereference /usr/lib/aarch64-linux-gnu/libstdc++.so.6 AppDir-qt/usr/optional/libstdc++/libstdc++.so.6 +cp --dereference /lib/aarch64-linux-gnu/libgcc_s.so.1 AppDir-qt/usr/optional/libgcc_s/libgcc_s.so.1 + +# Build an AppImage +ARCH=aarch64 ./appimagetool-x86_64.AppImage AppDir citra.AppImage +ARCH=aarch64 ./appimagetool-x86_64.AppImage AppDir-room citra-room.AppImage +ARCH=aarch64 ./appimagetool-x86_64.AppImage AppDir-qt citra-qt.AppImage + +mkdir -p ./build/bundle +mv citra.AppImage ./build/bundle +mv citra-room.AppImage ./build/bundle +mv citra-qt.AppImage ./build/bundle + +mkdir ./build/bundle/dist +cp ./dist/icon.png ./build/bundle/dist/citra.png +cp ./license.txt ./build/bundle +cp ./README.md ./build/bundle +cp -r ./dist/scripting ./build/bundle/scripting