duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

make-appimage.sh (7055B)


      1 #!/usr/bin/env bash
      2 
      3 # This is free and unencumbered software released into the public domain.
      4 #
      5 # Anyone is free to copy, modify, publish, use, compile, sell, or
      6 # distribute this software, either in source code form or as a compiled
      7 # binary, for any purpose, commercial or non-commercial, and by any
      8 # means.
      9 #
     10 # In jurisdictions that recognize copyright laws, the author or authors
     11 # of this software dedicate any and all copyright interest in the
     12 # software to the public domain. We make this dedication for the benefit
     13 # of the public at large and to the detriment of our heirs and
     14 # successors. We intend this dedication to be an overt act of
     15 # relinquishment in perpetuity of all present and future rights to this
     16 # software under copyright law.
     17 #
     18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     21 # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     22 # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     23 # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     24 # OTHER DEALINGS IN THE SOFTWARE.
     25 #
     26 # For more information, please refer to <http://unlicense.org/>
     27 
     28 SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
     29 
     30 function retry_command {
     31   # Package servers tend to be unreliable at times..
     32   # Retry a bunch of times.
     33   local RETRIES=10
     34 
     35   for i in $(seq 1 "$RETRIES"); do
     36     "$@" && break
     37     if [ "$i" == "$RETRIES" ]; then
     38       echo "Command \"$@\" failed after ${RETRIES} retries."
     39       exit 1
     40     fi
     41   done
     42 }
     43 
     44 if [ "$#" -ne 4 ]; then
     45     echo "Syntax: $0 <path to duckstation directory> <path to build directory> <deps prefix> <output name>"
     46     exit 1
     47 fi
     48 
     49 ROOTDIR=$1
     50 BUILDDIR=$2
     51 DEPSDIR=$3
     52 NAME=$4
     53 
     54 BINARY=duckstation-qt
     55 APPDIRNAME=DuckStation.AppDir
     56 STRIP=strip
     57 
     58 declare -a MANUAL_LIBS=(
     59 	"libdiscord-rpc.so"
     60 	"libfreetype.so.6"
     61 	"libshaderc_shared.so"
     62 	"libspirv-cross-c-shared.so.0"
     63 )
     64 
     65 declare -a MANUAL_QT_LIBS=(
     66 	"libQt6WaylandEglClientHwIntegration.so.6"
     67 )
     68 
     69 declare -a MANUAL_QT_PLUGINS=(
     70 	"wayland-decoration-client"
     71 	"wayland-graphics-integration-client"
     72 	"wayland-shell-integration"
     73 )
     74 
     75 declare -a REMOVE_LIBS=(
     76 	'libwayland-client.so*'
     77 	'libwayland-cursor.so*'
     78 	'libwayland-egl.so*'
     79 )
     80 
     81 set -e
     82 
     83 LINUXDEPLOY=./linuxdeploy-x86_64
     84 LINUXDEPLOY_PLUGIN_QT=./linuxdeploy-plugin-qt-x86_64
     85 APPIMAGETOOL=./appimagetool-x86_64
     86 APPIMAGERUNTIME=./runtime-x86_64
     87 PATCHELF=patchelf
     88 
     89 if [ ! -f "$LINUXDEPLOY" ]; then
     90 	retry_command wget -O "$LINUXDEPLOY" https://github.com/stenzek/duckstation-ext-qt-minimal/releases/download/linux/linuxdeploy-x86_64.AppImage
     91 	chmod +x "$LINUXDEPLOY"
     92 fi
     93 
     94 if [ ! -f "$LINUXDEPLOY_PLUGIN_QT" ]; then
     95 	retry_command wget -O "$LINUXDEPLOY_PLUGIN_QT" https://github.com/stenzek/duckstation-ext-qt-minimal/releases/download/linux/linuxdeploy-plugin-qt-x86_64.AppImage
     96 	chmod +x "$LINUXDEPLOY_PLUGIN_QT"
     97 fi
     98 
     99 if [ ! -f "$APPIMAGETOOL" ]; then
    100 	retry_command wget -O "$APPIMAGETOOL" https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
    101 	chmod +x "$APPIMAGETOOL"
    102 fi
    103 
    104 if [ ! -f "$APPIMAGERUNTIME" ]; then
    105 	retry_command wget -O "$APPIMAGERUNTIME" https://github.com/stenzek/type2-runtime/releases/download/continuous/runtime-x86_64
    106 fi
    107 
    108 OUTDIR=$(realpath "./$APPDIRNAME")
    109 rm -fr "$OUTDIR"
    110 
    111 echo "Locating extra libraries..."
    112 EXTRA_LIBS_ARGS=()
    113 for lib in "${MANUAL_LIBS[@]}"; do
    114 	srcpath=$(find "$DEPSDIR" -name "$lib")
    115 	if [ ! -f "$srcpath" ]; then
    116 		echo "Missinge extra library $lib. Exiting."
    117 		exit 1
    118 	fi
    119 
    120 	echo "Found $lib at $srcpath."
    121 	EXTRA_LIBS_ARGS+=("--library=$srcpath")
    122 done
    123 
    124 # Why the nastyness? linuxdeploy strips our main binary, and there's no option to turn it off.
    125 # It also doesn't strip the Qt libs. We can't strip them after running linuxdeploy, because
    126 # patchelf corrupts the libraries (but they still work), but patchelf+strip makes them crash
    127 # on load. So, make a backup copy, strip the original (since that's where linuxdeploy finds
    128 # the libs to copy), then swap them back after we're done.
    129 # Isn't Linux packaging amazing?
    130 
    131 rm -fr "$DEPSDIR.bak"
    132 cp -a "$DEPSDIR" "$DEPSDIR.bak"
    133 IFS="
    134 "
    135 for i in $(find "$DEPSDIR" -iname '*.so'); do
    136   echo "Stripping deps library ${i}"
    137   strip "$i"
    138 done
    139 
    140 echo "Running linuxdeploy to create AppDir..."
    141 EXTRA_QT_PLUGINS="core;gui;svg;waylandclient;widgets;xcbqpa" \
    142 EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so" \
    143 DEPLOY_PLATFORM_THEMES="1" \
    144 QMAKE="$DEPSDIR/bin/qmake" \
    145 NO_STRIP="1" \
    146 $LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/duckstation-qt" ${EXTRA_LIBS_ARGS[@]} \
    147 --desktop-file="$ROOTDIR/scripts/org.duckstation.DuckStation.desktop" \
    148 --icon-file="$ROOTDIR/scripts/org.duckstation.DuckStation.png" \
    149 
    150 echo "Copying resources into AppDir..."
    151 cp -a "$BUILDDIR/bin/resources" "$OUTDIR/usr/bin"
    152 
    153 # LinuxDeploy's Qt plugin doesn't include Wayland support. So manually copy in the additional Wayland libraries.
    154 echo "Copying Qt Wayland libraries..."
    155 for lib in "${MANUAL_QT_LIBS[@]}"; do
    156 	srcpath="$DEPSDIR/lib/$lib"
    157 	dstpath="$OUTDIR/usr/lib/$lib"
    158 	echo "  $srcpath -> $dstpath"
    159 	cp "$srcpath" "$dstpath"
    160 	$PATCHELF --set-rpath '$ORIGIN' "$dstpath"
    161 done
    162 
    163 # .. and plugins.
    164 echo "Copying Qt Wayland plugins..."
    165 for GROUP in "${MANUAL_QT_PLUGINS[@]}"; do
    166 	srcpath="$DEPSDIR/plugins/$GROUP"
    167 	dstpath="$OUTDIR/usr/plugins/$GROUP"
    168 	echo "  $srcpath -> $dstpath"
    169 	mkdir -p "$dstpath"
    170 
    171 	for srcsopath in $(find "$DEPSDIR/plugins/$GROUP" -iname '*.so'); do
    172 		# This is ../../ because it's usually plugins/group/name.so
    173 		soname=$(basename "$srcsopath")
    174 		dstsopath="$dstpath/$soname"
    175 		echo "    $srcsopath -> $dstsopath"
    176 		cp "$srcsopath" "$dstsopath"
    177 		$PATCHELF --set-rpath '$ORIGIN/../../lib:$ORIGIN' "$dstsopath"
    178 	done
    179 done
    180 
    181 # Why do we have to manually remove these libs? Because the linuxdeploy Qt plugin
    182 # copies them, not the "main" linuxdeploy binary, and plugins don't inherit the
    183 # include list...
    184 for lib in "${REMOVE_LIBS[@]}"; do
    185 	for libpath in $(find "$OUTDIR/usr/lib" -name "$lib"); do
    186 		echo "    Removing problematic library ${libpath}."
    187 		rm -f "$libpath"
    188 	done
    189 done
    190 
    191 # Restore unstripped deps (for cache).
    192 rm -fr "$DEPSDIR"
    193 mv "$DEPSDIR.bak" "$DEPSDIR"
    194 
    195 # Fix up translations.
    196 rm -fr "$OUTDIR/usr/bin/translations"
    197 mv "$OUTDIR/usr/translations" "$OUTDIR/usr/bin"
    198 cp -a "$BUILDDIR/bin/translations" "$OUTDIR/usr/bin"
    199 
    200 # Generate AppStream meta-info.
    201 echo "Generating AppStream metainfo..."
    202 mkdir -p "$OUTDIR/usr/share/metainfo"
    203 "$SCRIPTDIR/../generate-metainfo.sh" "$OUTDIR/usr/share/metainfo"
    204 
    205 # Copy in AppRun hooks.
    206 echo "Copying AppRun hooks..."
    207 mkdir -p "$OUTDIR/apprun-hooks"
    208 for hookpath in "$SCRIPTDIR/apprun-hooks"/*; do
    209 	hookname=$(basename "$hookpath")
    210 	cp -v "$hookpath" "$OUTDIR/apprun-hooks/$hookname"
    211 	sed -i -e 's/exec /source "$this_dir"\/apprun-hooks\/"'"$hookname"'"\nexec /' "$OUTDIR/AppRun"
    212 done
    213 
    214 echo "Generating AppImage..."
    215 rm -f "$NAME.AppImage"
    216 "$APPIMAGETOOL" -v --runtime-file "$APPIMAGERUNTIME" "$OUTDIR" "$NAME.AppImage"