Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/scripts/appimage/make-cross-appimage.sh
10595 views
1
#!/usr/bin/env bash
2
3
# SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>
4
# SPDX-License-Identifier: CC-BY-NC-ND-4.0
5
6
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
7
8
function retry_command {
9
# Package servers tend to be unreliable at times..
10
# Retry a bunch of times.
11
local RETRIES=10
12
13
for i in $(seq 1 "$RETRIES"); do
14
"$@" && break
15
if [ "$i" == "$RETRIES" ]; then
16
echo "Command \"$@\" failed after ${RETRIES} retries."
17
exit 1
18
fi
19
done
20
}
21
22
if [ "$#" -ne 3 ]; then
23
echo "Syntax: $0 <target arch> <path to build directory> <chroot dir>"
24
exit 1
25
fi
26
27
ARCH=$1
28
BUILDDIR=$2
29
CHROOTDIR=$3
30
31
STRIP=llvm-strip
32
33
if [ "$ARCH" == "arm64" ]; then
34
DEBARCH="arm64"
35
RUNTIMEARCH="aarch64"
36
TRIPLE="aarch64-linux-gnu"
37
elif [ "$ARCH" == "armhf" ]; then
38
DEBARCH="armhf"
39
RUNTIMEARCH="armhf"
40
TRIPLE="arm-linux-gnueabihf"
41
else
42
echo "Unknown arch ${ARCH}."
43
exit 1
44
fi
45
46
APPIMAGENAME="DuckStation-${ARCH}"
47
APPDIRNAME="${APPIMAGENAME}.AppDir"
48
49
declare -a SYSLIBS=(
50
"libbrotlicommon.so.1"
51
"libbrotlidec.so.1"
52
"libbsd.so.0"
53
"libcom_err.so.2"
54
"libcrypto.so.3"
55
"libcurl.so.4"
56
"libffi.so.8"
57
"libgnutls.so.30"
58
"libgssapi_krb5.so.2"
59
"libhogweed.so.6"
60
"libidn2.so.0"
61
"libk5crypto.so.3"
62
"libkeyutils.so.1"
63
"libkrb5.so.3"
64
"libkrb5support.so.0"
65
"liblber-2.5.so.0"
66
"libldap-2.5.so.0"
67
"libnettle.so.8"
68
"libnghttp2.so.14"
69
"libp11-kit.so.0"
70
"libpsl.so.5"
71
"librtmp.so.1"
72
"libsasl2.so.2"
73
"libssh.so.4"
74
"libssl.so.3"
75
"libtasn1.so.6"
76
"libudev.so.1"
77
"libunistring.so.2"
78
)
79
80
declare -a DEPLIBS=(
81
"libbacktrace.so.0"
82
"libfreetype.so.6"
83
"libharfbuzz.so"
84
"libjpeg.so.62"
85
"libpng16.so.16"
86
"libSDL3.so.0"
87
"libsharpyuv.so.0"
88
"libwebpdemux.so.2"
89
"libwebpmux.so.3"
90
"libwebp.so.7"
91
"libzip.so.5"
92
"libzstd.so.1"
93
94
"libcpuinfo.so"
95
"libdiscord-rpc.so"
96
"libplutosvg.so.0"
97
"libshaderc_shared.so"
98
"libsoundtouch.so.2"
99
"libspirv-cross-c-shared.so.0"
100
101
#"libavcodec.so.61"
102
#"libavformat.so.61"
103
#"libavutil.so.59"
104
#"libswscale.so.8"
105
#"libswresample.so.5"
106
#"libva-drm.so.2"
107
#"libva.so.2"
108
)
109
110
SYSLIBS+=(
111
"libatk-1.0.so.0"
112
"libatk-bridge-2.0.so.0"
113
"libatspi.so.0"
114
"libblkid.so.1"
115
"libcairo-gobject.so.2"
116
"libcairo.so.2"
117
"libcap.so.2"
118
"libdatrie.so.1"
119
"libdeflate.so.0"
120
"libdbus-1.so.3"
121
"libepoxy.so.0"
122
"libgcrypt.so.20"
123
"libgdk-3.so.0"
124
"libgdk_pixbuf-2.0.so.0"
125
"libgio-2.0.so.0"
126
"libglib-2.0.so.0"
127
"libgmodule-2.0.so.0"
128
"libgobject-2.0.so.0"
129
"libgraphite2.so.3"
130
"libgtk-3.so.0"
131
"libjbig.so.0"
132
"liblz4.so.1"
133
"liblzma.so.5"
134
"libmd.so.0"
135
"libmount.so.1"
136
"libpango-1.0.so.0"
137
"libpangocairo-1.0.so.0"
138
"libpangoft2-1.0.so.0"
139
"libpcre2-16.so.0"
140
"libpcre2-8.so.0"
141
"libpcre.so.3"
142
"libpixman-1.so.0"
143
"libselinux.so.1"
144
"libsystemd.so.0"
145
"libtiff.so.5"
146
"libXau.so.6"
147
"libxcb-cursor.so.0"
148
"libxcb-glx.so.0"
149
"libxcb-icccm.so.4"
150
"libxcb-image.so.0"
151
"libxcb-keysyms.so.1"
152
"libxcb-randr.so.0"
153
"libxcb-render.so.0"
154
"libxcb-render-util.so.0"
155
"libxcb-shape.so.0"
156
"libxcb-shm.so.0"
157
"libxcb-sync.so.1"
158
"libxcb-util.so.1"
159
"libxcb-xfixes.so.0"
160
"libxcb-xkb.so.1"
161
"libXcomposite.so.1"
162
"libXcursor.so.1"
163
"libXdamage.so.1"
164
"libXdmcp.so.6"
165
"libXext.so.6"
166
"libXfixes.so.3"
167
"libXinerama.so.1"
168
"libXi.so.6"
169
"libxkbcommon.so.0"
170
"libxkbcommon-x11.so.0"
171
"libXrandr.so.2"
172
"libXrender.so.1"
173
)
174
175
declare -a QTLIBS=(
176
"libQt6Core.so.6"
177
"libQt6DBus.so.6"
178
"libQt6Gui.so.6"
179
"libQt6OpenGL.so.6"
180
"libQt6Svg.so.6"
181
"libQt6WaylandClient.so.6"
182
"libQt6Widgets.so.6"
183
"libQt6XcbQpa.so.6"
184
)
185
186
declare -a QTPLUGINS=(
187
"plugins/iconengines"
188
"plugins/imageformats"
189
"plugins/platforminputcontexts"
190
"plugins/platforms"
191
"plugins/platformthemes"
192
"plugins/wayland-decoration-client"
193
"plugins/wayland-graphics-integration-client"
194
"plugins/wayland-shell-integration"
195
"plugins/xcbglintegrations"
196
)
197
198
set -e
199
IFS="
200
"
201
202
DEPSDIR=$(realpath "$SCRIPTDIR/../../dep/prebuilt/linux-cross-$ARCH")
203
APPIMAGETOOL=./appimagetool-x86_64
204
APPIMAGERUNTIME=./runtime-${RUNTIMEARCH}
205
PATCHELF=patchelf
206
207
if [ ! -f "$APPIMAGETOOL" ]; then
208
retry_command wget -O "$APPIMAGETOOL" https://github.com/duckstation/dependencies/releases/download/appimage-tools/appimagetool-x86_64.AppImage
209
chmod +x "$APPIMAGETOOL"
210
fi
211
212
if [ ! -f "$APPIMAGERUNTIME" ]; then
213
retry_command wget -O "$APPIMAGERUNTIME" https://github.com/stenzek/type2-runtime/releases/download/continuous/runtime-${RUNTIMEARCH}
214
fi
215
216
OUTDIR=$(realpath "./$APPDIRNAME")
217
rm -fr "$OUTDIR"
218
mkdir "$OUTDIR"
219
mkdir -p "$OUTDIR/usr/bin" "$OUTDIR/usr/lib"
220
221
echo "Copying binary and resources..."
222
cp -a "$BUILDDIR/bin/duckstation-qt" "$BUILDDIR/bin/resources" "$BUILDDIR/bin/translations" "$OUTDIR/usr/bin"
223
224
# Patch RPATH so the binary goes hunting for shared libraries in the AppDir instead of system.
225
echo "Patching RPATH in duckstation-qt..."
226
patchelf --set-rpath '$ORIGIN/../lib' "$OUTDIR/usr/bin/duckstation-qt"
227
228
# Libraries we pull in from the system.
229
echo "Copying system libraries..."
230
for lib in "${SYSLIBS[@]}"; do
231
blib=$(basename "$lib")
232
echo "$CHROOTDIR/lib/$TRIPLE/$lib"
233
if [ -f "$CHROOTDIR/lib/$TRIPLE/$lib" ]; then
234
cp "$CHROOTDIR/lib/$TRIPLE/$lib" "$OUTDIR/usr/lib/$blib"
235
elif [ -f "$CHROOTDIR/usr/lib/$TRIPLE/$lib" ]; then
236
cp "$CHROOTDIR/usr/lib/$TRIPLE/$lib" "$OUTDIR/usr/lib/$blib"
237
elif [ -f "$CHROOTDIR/lib/$lib" ]; then
238
cp "$CHROOTDIR/lib/$lib" "$OUTDIR/usr/lib/$blib"
239
elif [ -f "$CHROOTDIR/usr/lib/$lib" ]; then
240
cp "$CHROOTDIR/usr/lib/$lib" "$OUTDIR/usr/lib/$blib"
241
else
242
echo "*** Failed to find '$blib'"
243
exit 1
244
fi
245
246
"$STRIP" $OUTDIR/usr/lib/$blib
247
done
248
249
echo "Copying local libraries..."
250
for lib in "${DEPLIBS[@]}"; do
251
blib=$(basename "$lib")
252
echo "$DEPSDIR/lib/$lib"
253
if [ -f "$DEPSDIR/lib/$lib" ]; then
254
cp "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib/$blib"
255
else
256
echo "*** Failed to find '$blib'"
257
exit 1
258
fi
259
260
"$STRIP" "$OUTDIR/usr/lib/$blib"
261
done
262
263
echo "Copying Qt libraries..."
264
for lib in "${QTLIBS[@]}"; do
265
cp -avL "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib"
266
"$STRIP" "$OUTDIR/usr/lib/$lib"
267
done
268
269
echo "Copying Qt plugins..."
270
mkdir -p $OUTDIR/usr/lib/plugins
271
for plugin in "${QTPLUGINS[@]}"; do
272
mkdir -p "$OUTDIR/usr/lib/$plugin"
273
cp -avL "$DEPSDIR/$plugin/"*.so "$OUTDIR/usr/lib/$plugin/"
274
done
275
276
for so in $(find $OUTDIR/usr/lib/plugins -iname '*.so'); do
277
# This is ../../ because it's usually plugins/group/name.so
278
echo "Patching RPATH in ${so}..."
279
patchelf --set-rpath '$ORIGIN/../..' "$so"
280
"$STRIP" "$so"
281
done
282
283
echo "Creating qt.conf..."
284
cat > "$OUTDIR/usr/bin/qt.conf" << EOF
285
[Paths]
286
Plugins = ../lib/plugins
287
EOF
288
289
290
for so in $(find $OUTDIR/usr/lib -maxdepth 1); do
291
if [ -f "$so" ]; then
292
echo "Patching RPATH in ${so}"
293
patchelf --set-rpath '$ORIGIN' "$so"
294
fi
295
done
296
297
# Copy desktop/icon
298
echo "Copying desktop/icon..."
299
mkdir -p "$OUTDIR/usr/share/applications"
300
mkdir -p "$OUTDIR/usr/share/icons/hicolor/512x512/apps"
301
cp -v "$SCRIPTDIR/org.duckstation.DuckStation.desktop" "$OUTDIR/usr/share/applications"
302
cp -v "$SCRIPTDIR/org.duckstation.DuckStation.png" "$OUTDIR/usr/share/icons/hicolor/512x512/apps"
303
ln -s "usr/share/applications/org.duckstation.DuckStation.desktop" "$OUTDIR"
304
ln -s "usr/share/icons/hicolor/512x512/apps/org.duckstation.DuckStation.png" "$OUTDIR"
305
306
# Generate AppStream meta-info.
307
echo "Generating AppStream metainfo..."
308
mkdir -p "$OUTDIR/usr/share/metainfo"
309
"$SCRIPTDIR/generate-metainfo.sh" "$OUTDIR/usr/share/metainfo"
310
311
# Link AppRun to main binary.
312
ln -s "usr/bin/duckstation-qt" "$OUTDIR/AppRun"
313
314
echo "Generating AppImage..."
315
rm -f "$APPIMAGENAME.AppImage"
316
317
# Can't run the appimage in a docker container because no fuse, so extract it first.
318
"$APPIMAGETOOL" --appimage-extract
319
"$PWD/squashfs-root/AppRun" -v --runtime-file "$APPIMAGERUNTIME" "$OUTDIR" "$APPIMAGENAME.AppImage"
320
321