Path: blob/master/scripts/appimage/make-cross-appimage.sh
10595 views
#!/usr/bin/env bash12# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>3# SPDX-License-Identifier: CC-BY-NC-ND-4.045SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")67function retry_command {8# Package servers tend to be unreliable at times..9# Retry a bunch of times.10local RETRIES=101112for i in $(seq 1 "$RETRIES"); do13"$@" && break14if [ "$i" == "$RETRIES" ]; then15echo "Command \"$@\" failed after ${RETRIES} retries."16exit 117fi18done19}2021if [ "$#" -ne 3 ]; then22echo "Syntax: $0 <target arch> <path to build directory> <chroot dir>"23exit 124fi2526ARCH=$127BUILDDIR=$228CHROOTDIR=$32930STRIP=llvm-strip3132if [ "$ARCH" == "arm64" ]; then33DEBARCH="arm64"34RUNTIMEARCH="aarch64"35TRIPLE="aarch64-linux-gnu"36elif [ "$ARCH" == "armhf" ]; then37DEBARCH="armhf"38RUNTIMEARCH="armhf"39TRIPLE="arm-linux-gnueabihf"40else41echo "Unknown arch ${ARCH}."42exit 143fi4445APPIMAGENAME="DuckStation-${ARCH}"46APPDIRNAME="${APPIMAGENAME}.AppDir"4748declare -a SYSLIBS=(49"libbrotlicommon.so.1"50"libbrotlidec.so.1"51"libbsd.so.0"52"libcom_err.so.2"53"libcrypto.so.3"54"libcurl.so.4"55"libffi.so.8"56"libgnutls.so.30"57"libgssapi_krb5.so.2"58"libhogweed.so.6"59"libidn2.so.0"60"libk5crypto.so.3"61"libkeyutils.so.1"62"libkrb5.so.3"63"libkrb5support.so.0"64"liblber-2.5.so.0"65"libldap-2.5.so.0"66"libnettle.so.8"67"libnghttp2.so.14"68"libp11-kit.so.0"69"libpsl.so.5"70"librtmp.so.1"71"libsasl2.so.2"72"libssh.so.4"73"libssl.so.3"74"libtasn1.so.6"75"libudev.so.1"76"libunistring.so.2"77)7879declare -a DEPLIBS=(80"libbacktrace.so.0"81"libfreetype.so.6"82"libharfbuzz.so"83"libjpeg.so.62"84"libpng16.so.16"85"libSDL3.so.0"86"libsharpyuv.so.0"87"libwebpdemux.so.2"88"libwebpmux.so.3"89"libwebp.so.7"90"libzip.so.5"91"libzstd.so.1"9293"libcpuinfo.so"94"libdiscord-rpc.so"95"libplutosvg.so.0"96"libshaderc_shared.so"97"libsoundtouch.so.2"98"libspirv-cross-c-shared.so.0"99100#"libavcodec.so.61"101#"libavformat.so.61"102#"libavutil.so.59"103#"libswscale.so.8"104#"libswresample.so.5"105#"libva-drm.so.2"106#"libva.so.2"107)108109SYSLIBS+=(110"libatk-1.0.so.0"111"libatk-bridge-2.0.so.0"112"libatspi.so.0"113"libblkid.so.1"114"libcairo-gobject.so.2"115"libcairo.so.2"116"libcap.so.2"117"libdatrie.so.1"118"libdeflate.so.0"119"libdbus-1.so.3"120"libepoxy.so.0"121"libgcrypt.so.20"122"libgdk-3.so.0"123"libgdk_pixbuf-2.0.so.0"124"libgio-2.0.so.0"125"libglib-2.0.so.0"126"libgmodule-2.0.so.0"127"libgobject-2.0.so.0"128"libgraphite2.so.3"129"libgtk-3.so.0"130"libjbig.so.0"131"liblz4.so.1"132"liblzma.so.5"133"libmd.so.0"134"libmount.so.1"135"libpango-1.0.so.0"136"libpangocairo-1.0.so.0"137"libpangoft2-1.0.so.0"138"libpcre2-16.so.0"139"libpcre2-8.so.0"140"libpcre.so.3"141"libpixman-1.so.0"142"libselinux.so.1"143"libsystemd.so.0"144"libtiff.so.5"145"libXau.so.6"146"libxcb-cursor.so.0"147"libxcb-glx.so.0"148"libxcb-icccm.so.4"149"libxcb-image.so.0"150"libxcb-keysyms.so.1"151"libxcb-randr.so.0"152"libxcb-render.so.0"153"libxcb-render-util.so.0"154"libxcb-shape.so.0"155"libxcb-shm.so.0"156"libxcb-sync.so.1"157"libxcb-util.so.1"158"libxcb-xfixes.so.0"159"libxcb-xkb.so.1"160"libXcomposite.so.1"161"libXcursor.so.1"162"libXdamage.so.1"163"libXdmcp.so.6"164"libXext.so.6"165"libXfixes.so.3"166"libXinerama.so.1"167"libXi.so.6"168"libxkbcommon.so.0"169"libxkbcommon-x11.so.0"170"libXrandr.so.2"171"libXrender.so.1"172)173174declare -a QTLIBS=(175"libQt6Core.so.6"176"libQt6DBus.so.6"177"libQt6Gui.so.6"178"libQt6OpenGL.so.6"179"libQt6Svg.so.6"180"libQt6WaylandClient.so.6"181"libQt6Widgets.so.6"182"libQt6XcbQpa.so.6"183)184185declare -a QTPLUGINS=(186"plugins/iconengines"187"plugins/imageformats"188"plugins/platforminputcontexts"189"plugins/platforms"190"plugins/platformthemes"191"plugins/wayland-decoration-client"192"plugins/wayland-graphics-integration-client"193"plugins/wayland-shell-integration"194"plugins/xcbglintegrations"195)196197set -e198IFS="199"200201DEPSDIR=$(realpath "$SCRIPTDIR/../../dep/prebuilt/linux-cross-$ARCH")202APPIMAGETOOL=./appimagetool-x86_64203APPIMAGERUNTIME=./runtime-${RUNTIMEARCH}204PATCHELF=patchelf205206if [ ! -f "$APPIMAGETOOL" ]; then207retry_command wget -O "$APPIMAGETOOL" https://github.com/duckstation/dependencies/releases/download/appimage-tools/appimagetool-x86_64.AppImage208chmod +x "$APPIMAGETOOL"209fi210211if [ ! -f "$APPIMAGERUNTIME" ]; then212retry_command wget -O "$APPIMAGERUNTIME" https://github.com/stenzek/type2-runtime/releases/download/continuous/runtime-${RUNTIMEARCH}213fi214215OUTDIR=$(realpath "./$APPDIRNAME")216rm -fr "$OUTDIR"217mkdir "$OUTDIR"218mkdir -p "$OUTDIR/usr/bin" "$OUTDIR/usr/lib"219220echo "Copying binary and resources..."221cp -a "$BUILDDIR/bin/duckstation-qt" "$BUILDDIR/bin/resources" "$BUILDDIR/bin/translations" "$OUTDIR/usr/bin"222223# Patch RPATH so the binary goes hunting for shared libraries in the AppDir instead of system.224echo "Patching RPATH in duckstation-qt..."225patchelf --set-rpath '$ORIGIN/../lib' "$OUTDIR/usr/bin/duckstation-qt"226227# Libraries we pull in from the system.228echo "Copying system libraries..."229for lib in "${SYSLIBS[@]}"; do230blib=$(basename "$lib")231echo "$CHROOTDIR/lib/$TRIPLE/$lib"232if [ -f "$CHROOTDIR/lib/$TRIPLE/$lib" ]; then233cp "$CHROOTDIR/lib/$TRIPLE/$lib" "$OUTDIR/usr/lib/$blib"234elif [ -f "$CHROOTDIR/usr/lib/$TRIPLE/$lib" ]; then235cp "$CHROOTDIR/usr/lib/$TRIPLE/$lib" "$OUTDIR/usr/lib/$blib"236elif [ -f "$CHROOTDIR/lib/$lib" ]; then237cp "$CHROOTDIR/lib/$lib" "$OUTDIR/usr/lib/$blib"238elif [ -f "$CHROOTDIR/usr/lib/$lib" ]; then239cp "$CHROOTDIR/usr/lib/$lib" "$OUTDIR/usr/lib/$blib"240else241echo "*** Failed to find '$blib'"242exit 1243fi244245"$STRIP" $OUTDIR/usr/lib/$blib246done247248echo "Copying local libraries..."249for lib in "${DEPLIBS[@]}"; do250blib=$(basename "$lib")251echo "$DEPSDIR/lib/$lib"252if [ -f "$DEPSDIR/lib/$lib" ]; then253cp "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib/$blib"254else255echo "*** Failed to find '$blib'"256exit 1257fi258259"$STRIP" "$OUTDIR/usr/lib/$blib"260done261262echo "Copying Qt libraries..."263for lib in "${QTLIBS[@]}"; do264cp -avL "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib"265"$STRIP" "$OUTDIR/usr/lib/$lib"266done267268echo "Copying Qt plugins..."269mkdir -p $OUTDIR/usr/lib/plugins270for plugin in "${QTPLUGINS[@]}"; do271mkdir -p "$OUTDIR/usr/lib/$plugin"272cp -avL "$DEPSDIR/$plugin/"*.so "$OUTDIR/usr/lib/$plugin/"273done274275for so in $(find $OUTDIR/usr/lib/plugins -iname '*.so'); do276# This is ../../ because it's usually plugins/group/name.so277echo "Patching RPATH in ${so}..."278patchelf --set-rpath '$ORIGIN/../..' "$so"279"$STRIP" "$so"280done281282echo "Creating qt.conf..."283cat > "$OUTDIR/usr/bin/qt.conf" << EOF284[Paths]285Plugins = ../lib/plugins286EOF287288289for so in $(find $OUTDIR/usr/lib -maxdepth 1); do290if [ -f "$so" ]; then291echo "Patching RPATH in ${so}"292patchelf --set-rpath '$ORIGIN' "$so"293fi294done295296# Copy desktop/icon297echo "Copying desktop/icon..."298mkdir -p "$OUTDIR/usr/share/applications"299mkdir -p "$OUTDIR/usr/share/icons/hicolor/512x512/apps"300cp -v "$SCRIPTDIR/org.duckstation.DuckStation.desktop" "$OUTDIR/usr/share/applications"301cp -v "$SCRIPTDIR/org.duckstation.DuckStation.png" "$OUTDIR/usr/share/icons/hicolor/512x512/apps"302ln -s "usr/share/applications/org.duckstation.DuckStation.desktop" "$OUTDIR"303ln -s "usr/share/icons/hicolor/512x512/apps/org.duckstation.DuckStation.png" "$OUTDIR"304305# Generate AppStream meta-info.306echo "Generating AppStream metainfo..."307mkdir -p "$OUTDIR/usr/share/metainfo"308"$SCRIPTDIR/generate-metainfo.sh" "$OUTDIR/usr/share/metainfo"309310# Link AppRun to main binary.311ln -s "usr/bin/duckstation-qt" "$OUTDIR/AppRun"312313echo "Generating AppImage..."314rm -f "$APPIMAGENAME.AppImage"315316# Can't run the appimage in a docker container because no fuse, so extract it first.317"$APPIMAGETOOL" --appimage-extract318"$PWD/squashfs-root/AppRun" -v --runtime-file "$APPIMAGERUNTIME" "$OUTDIR" "$APPIMAGENAME.AppImage"319320321