-
Notifications
You must be signed in to change notification settings - Fork 448
Expand file tree
/
Copy pathcreate-appimage.sh
More file actions
executable file
·491 lines (430 loc) · 19.1 KB
/
Copy pathcreate-appimage.sh
File metadata and controls
executable file
·491 lines (430 loc) · 19.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
#!/bin/sh
set -e
# Parse command line arguments
ARCH=$(uname -m) # Default to current architecture
CLEAN_BUILD=1
QT_ROOT_ARG=""
TRY_BUILD_QT=0
usage() {
echo "Usage: $0 [options]"
echo "Options:"
echo " --arch=ARCH Target architecture (x86_64, aarch64, armhf)"
echo " --qt-root=PATH Path to Qt installation directory"
echo " --try-build-qt Run debian/ensure-qt.sh if Qt is missing (best-effort)"
echo " --no-clean Don't clean build directory"
echo " -h, --help Show this help message"
exit 1
}
for arg in "$@"; do
case $arg in
--arch=*)
ARCH="${arg#*=}"
;;
--qt-root=*)
QT_ROOT_ARG="${arg#*=}"
;;
--try-build-qt)
TRY_BUILD_QT=1
;;
--no-clean)
CLEAN_BUILD=0
;;
--packaging=*)
APPIMAGE_PACKAGING="${arg#*=}"
;;
-h|--help)
usage
;;
*)
echo "Unknown option: $arg"
usage
;;
esac
done
# Resolve Qt root path argument if provided (expand ~ and convert to absolute path)
if [ -n "$QT_ROOT_ARG" ]; then
# Expand tilde if present at the start
case "$QT_ROOT_ARG" in
"~"/*) QT_ROOT_ARG="$HOME/${QT_ROOT_ARG#\~/}" ;;
"~") QT_ROOT_ARG="$HOME" ;;
esac
# Convert to absolute path if it exists
if [ -e "$QT_ROOT_ARG" ]; then
QT_ROOT_ARG=$(cd "$QT_ROOT_ARG" && pwd)
else
echo "Warning: Specified Qt root path does not exist: $QT_ROOT_ARG"
echo "Will attempt to use it anyway, but this may fail..."
fi
fi
# Normalise 32-bit Pi kernel names to Debian armhf.
case "$ARCH" in
armv6l|armv7l) ARCH=armhf ;;
esac
if [ "$ARCH" != "x86_64" ] && [ "$ARCH" != "aarch64" ] && [ "$ARCH" != "armhf" ]; then
echo "Error: Architecture must be one of: x86_64, aarch64, armhf" >&2
exit 1
fi
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TOP="$SCRIPT_DIR"
# shellcheck disable=SC1091
. "$TOP/debian/lib.sh"
export_cmake_parallel
sh "$TOP/debian/fetch-vendor-deps.sh"
# shellcheck source=debian/qt-resolve.sh
. "$TOP/debian/qt-resolve.sh"
APPIMAGE_PACKAGING=${APPIMAGE_PACKAGING:-all}
TOOL_ARCH=$(appimage_resolve_tool_arch)
echo "Building for architecture: $ARCH (packaging tools: $TOOL_ARCH, mode: $APPIMAGE_PACKAGING)"
if [ "$ARCH" != "$TOOL_ARCH" ]; then
echo "create-appimage: cross packaging — build target binaries for $ARCH, run linuxdeploy/appimagetool for $TOOL_ARCH on the host"
fi
# Extract project information from CMakeLists.txt
SOURCE_DIR="src/"
CMAKE_FILE="${SOURCE_DIR}CMakeLists.txt"
# Get version from git tag (same approach as CMake)
GIT_VERSION=$(git describe --tags --always --dirty 2>/dev/null || echo "0.0.0-unknown")
# Extract numeric version components for compatibility
# Match versions like: v1.2.3, 1.2.3, v1.2.3-extra, etc.
MAJOR=$(echo "$GIT_VERSION" | sed -n 's/^v\{0,1\}\([0-9]\{1,\}\)\.[0-9]\{1,\}\.[0-9]\{1,\}.*/\1/p')
MINOR=$(echo "$GIT_VERSION" | sed -n 's/^v\{0,1\}[0-9]\{1,\}\.\([0-9]\{1,\}\)\.[0-9]\{1,\}.*/\1/p')
PATCH=$(echo "$GIT_VERSION" | sed -n 's/^v\{0,1\}[0-9]\{1,\}\.[0-9]\{1,\}\.\([0-9]\{1,\}\).*/\1/p')
if [ -n "$MAJOR" ] && [ -n "$MINOR" ] && [ -n "$PATCH" ]; then
PROJECT_VERSION="$MAJOR.$MINOR.$PATCH"
else
MAJOR="0"
MINOR="0"
PATCH="0"
PROJECT_VERSION="0.0.0"
echo "Warning: Could not parse version from git tag: $GIT_VERSION"
fi
# Extract project name (lowercase for AppImage naming convention)
PROJECT_NAME=$(grep "project(" "$CMAKE_FILE" | head -1 | sed 's/project(\([^[:space:]]*\).*/\1/' | tr '[:upper:]' '[:lower:]')
echo "Building $PROJECT_NAME version $GIT_VERSION (numeric: $PROJECT_VERSION)"
# Resolve Qt (vendored cache, /opt/Qt, or system qmake6).
# The pack stage only wraps an AppDir built earlier, so it never needs Qt — even
# when target arch == tool arch (host-arch chroot build packed on the host).
QT_DIR=""
if [ "$APPIMAGE_PACKAGING" != pack ]; then
if ! QT_DIR=$(qt_resolve_desktop_dir "$ARCH"); then
if [ "$TRY_BUILD_QT" -eq 1 ] && [ -x "$SCRIPT_DIR/debian/ensure-qt.sh" ]; then
_deb_arch=$ARCH
case "$ARCH" in
x86_64) _deb_arch=amd64 ;;
aarch64) _deb_arch=arm64 ;;
esac
echo "create-appimage: attempting Qt build via ensure-qt.sh $_deb_arch..."
if "$SCRIPT_DIR/debian/ensure-qt.sh" "$_deb_arch"; then
QT_DIR=$(qt_resolve_desktop_dir "$ARCH") || true
fi
fi
fi
if [ -z "$QT_DIR" ]; then
echo "Error: No suitable Qt6 installation found for $ARCH" >&2
echo " Vendored: debian/ensure-qt.sh <arch> or ./qt/build-qt.sh" >&2
echo " System: apt install qt6-base-dev qt6-declarative-dev" >&2
echo " Or: $0 --qt-root=/path/to/qt6 --try-build-qt" >&2
exit 1
fi
if [ -f "$QT_DIR/bin/qmake" ]; then
QT_VERSION=$("$QT_DIR/bin/qmake" -query QT_VERSION)
echo "Using Qt $QT_VERSION from $QT_DIR (source: ${QT_RESOLVE_SOURCE:-unknown})"
elif _qmake=$(qt6_qmake); then
QT_VERSION=$("$_qmake" -query QT_VERSION)
echo "Using system Qt $QT_VERSION (prefix $QT_DIR)"
fi
fi
# Configuration
BUILD_TYPE="MinSizeRel"
QML_SOURCES_PATH="$PWD/src/qmlcomponents/"
# Location of AppDir and output file
APPDIR="$PWD/AppDir-$ARCH"
OUTPUT_FILE="$PWD/Raspberry_Pi_Imager-${GIT_VERSION}-desktop-${ARCH}.AppImage"
# Tools directory for downloaded binaries
TOOLS_DIR="$PWD/appimage-tools"
mkdir -p "$TOOLS_DIR"
# Download linuxdeploy and plugins if they don't exist
echo "Ensuring linuxdeploy tools are available..."
# Pin to specific stable versions
LINUXDEPLOY_VERSION="1-alpha-20250213-2"
LINUXDEPLOY_PLUGIN_QT_VERSION="1-alpha-20250213-1"
# Choose packaging tools for the machine running this script (TOOL_ARCH), not the
# target AppImage CPU architecture (ARCH).
LINUXDEPLOY=""
LINUXDEPLOY_QT=""
APPIMAGETOOL=""
# linuxdeploy has no armhf build; those targets fall back to appimagetool below.
if [ "$ARCH" = "$TOOL_ARCH" ] && { [ "$TOOL_ARCH" = "x86_64" ] || [ "$TOOL_ARCH" = "aarch64" ]; }; then
LINUXDEPLOY="$TOOLS_DIR/linuxdeploy-$TOOL_ARCH.AppImage"
LINUXDEPLOY_QT="$TOOLS_DIR/linuxdeploy-plugin-qt-$TOOL_ARCH.AppImage"
appimage_download_tool "$LINUXDEPLOY" \
"https://github.com/linuxdeploy/linuxdeploy/releases/download/$LINUXDEPLOY_VERSION/linuxdeploy-$TOOL_ARCH.AppImage"
appimage_download_tool "$LINUXDEPLOY_QT" \
"https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/$LINUXDEPLOY_PLUGIN_QT_VERSION/linuxdeploy-plugin-qt-$TOOL_ARCH.AppImage"
fi
APPIMAGETOOL="$TOOLS_DIR/appimagetool-$TOOL_ARCH.AppImage"
appimage_download_tool "$APPIMAGETOOL" \
"https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-$TOOL_ARCH.AppImage"
if [ "$APPIMAGE_PACKAGING" = pack ] && [ ! -d "$APPDIR/usr/bin" ]; then
echo "Error: AppDir missing for pack stage: $APPDIR" >&2
echo "Run the build stage first (APPIMAGE_PACKAGING=build)." >&2
exit 1
fi
if [ "$APPIMAGE_PACKAGING" != pack ]; then
# Set up build directory
BUILD_DIR="build-$ARCH"
# Clean up previous builds if requested
if [ "$CLEAN_BUILD" -eq 1 ]; then
echo "Cleaning previous build..."
rm -rf "$APPDIR" "$BUILD_DIR"
fi
mkdir -p "$APPDIR"
mkdir -p "$BUILD_DIR"
echo "Building rpi-imager for $ARCH..."
# Configure and build with CMake
cd "$BUILD_DIR"
# Set architecture-specific CMake flags
CMAKE_EXTRA_FLAGS=""
if [ "$ARCH" = "aarch64" ] && [ "$(uname -m)" = "x86_64" ]; then
echo "Cross-compiling from $(uname -m) to $ARCH"
CMAKE_EXTRA_FLAGS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_SYSTEM_PROCESSOR=aarch64"
elif [ "$ARCH" = "armhf" ] && [ "$(uname -m)" = "x86_64" ]; then
echo "Cross-compiling from $(uname -m) to $ARCH"
CMAKE_EXTRA_FLAGS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_SYSTEM_PROCESSOR=arm"
fi
# Add Qt path to CMake flags
CMAKE_EXTRA_FLAGS="$CMAKE_EXTRA_FLAGS -DQt6_ROOT=$QT_DIR"
# shellcheck disable=SC2086
cmake -G Ninja "../$SOURCE_DIR" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX=/usr $CMAKE_EXTRA_FLAGS
cmake --build . --parallel "$(cmake_build_jobs)"
echo "Creating AppDir..."
# Install to AppDir
DESTDIR="$APPDIR" cmake --install .
cd ..
# Copy the desktop file from debian directory
if [ ! -f "$APPDIR/usr/share/applications/com.raspberrypi.rpi-imager.desktop" ]; then
mkdir -p "$APPDIR/usr/share/applications"
cp "debian/com.raspberrypi.rpi-imager.desktop" "$APPDIR/usr/share/applications/"
# Update the Exec line to match the AppImage requirements (preserve %F for file arguments)
sed -i 's|Exec=.*|Exec=rpi-imager %F|' "$APPDIR/usr/share/applications/com.raspberrypi.rpi-imager.desktop"
fi
# Create the AppRun file if not created by the install process
if [ ! -f "$APPDIR/AppRun" ]; then
cat > "$APPDIR/AppRun" << 'EOF'
#!/bin/sh
HERE="$(dirname "$(readlink -f "${0}")")"
export PATH="${HERE}/usr/bin:${PATH}"
export LD_LIBRARY_PATH="${HERE}/usr/lib:${LD_LIBRARY_PATH}"
export QT_PLUGIN_PATH="${HERE}/usr/plugins"
export QML_IMPORT_PATH="${HERE}/usr/qml"
export QT_QPA_PLATFORM_PLUGIN_PATH="${HERE}/usr/plugins/platforms"
# Handle X11 authorization when running as root (via sudo or pkexec)
# This fixes "Authorization required, but no authorization protocol specified" errors
if [ "$(id -u)" = "0" ]; then
# Determine original user from sudo or pkexec
ORIGINAL_USER=""
ORIGINAL_UID=""
ORIGINAL_HOME=""
if [ -n "$SUDO_USER" ]; then
ORIGINAL_USER="$SUDO_USER"
ORIGINAL_UID="$SUDO_UID"
ORIGINAL_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6)
elif [ -n "$PKEXEC_UID" ]; then
ORIGINAL_UID="$PKEXEC_UID"
ORIGINAL_USER=$(getent passwd "$PKEXEC_UID" | cut -d: -f1)
ORIGINAL_HOME=$(getent passwd "$PKEXEC_UID" | cut -d: -f6)
fi
if [ -n "$ORIGINAL_USER" ] && [ -n "$ORIGINAL_HOME" ]; then
# Try to grant root access to the X display using xhost
# This must be run as the original user who owns the display
if command -v xhost >/dev/null 2>&1; then
if [ -n "$DISPLAY" ]; then
# Run xhost as the original user to grant root access
su "$ORIGINAL_USER" -c "xhost +SI:localuser:root" >/dev/null 2>&1 || true
fi
fi
# Set XAUTHORITY to the original user's .Xauthority if not already set
if [ -z "$XAUTHORITY" ]; then
if [ -f "$ORIGINAL_HOME/.Xauthority" ]; then
export XAUTHORITY="$ORIGINAL_HOME/.Xauthority"
fi
fi
# Ensure DISPLAY is set (for pkexec which may not preserve it)
if [ -z "$DISPLAY" ]; then
# Try common X11 display socket
if [ -S "/tmp/.X11-unix/X0" ]; then
export DISPLAY=":0"
fi
fi
fi
fi
# The binary handles privilege elevation internally via pkexec if needed
exec "${HERE}/usr/bin/rpi-imager" "$@"
EOF
chmod +x "$APPDIR/AppRun"
fi
fi
# Deploy Qt dependencies (build stage, or native all-in-one). The pack stage
# reuses the AppDir produced by the build stage and only wraps it.
if [ "$APPIMAGE_PACKAGING" = pack ]; then
echo "create-appimage: using AppDir from build stage (pack)"
else
echo "Deploying Qt dependencies using $QT_DIR..."
export QML_SOURCES_PATHS="$QML_SOURCES_PATH"
export LD_LIBRARY_PATH="$QT_DIR/lib:$LD_LIBRARY_PATH"
if [ -n "$LINUXDEPLOY" ] && [ -f "$LINUXDEPLOY" ] && [ "$ARCH" = "$TOOL_ARCH" ] && [ "$APPIMAGE_PACKAGING" = all ]; then
export APPIMAGE_EXTRACT_AND_RUN=1
export QMAKE="$QT_DIR/bin/qmake"
export LINUXDEPLOY_PLUGIN_QT_IGNORE_GLOB="*/translations/*"
"$LINUXDEPLOY" --appdir="$APPDIR" --plugin=qt --exclude-library="libwayland-*" --exclude-library="libsystemd*" --exclude-library="libdbus-*" --exclude-library="libcap*" --verbosity=0
else
echo "Manual Qt deployment for $ARCH..."
mkdir -p "$APPDIR/usr/lib" "$APPDIR/usr/plugins" "$APPDIR/usr/qml"
# Deliberately not a blanket glob: the Qt build now includes testlib so
# the suite can use QtTest/QtQuickTest, and nothing in the application
# links it. linuxdeploy resolves libraries from the binary and so never
# picks it up; this path copies whatever is present, so it has to say
# what it does not want.
for _lib in "$QT_DIR/lib/libQt6"*.so*; do
case "$(basename "$_lib")" in
libQt6Test.so*|libQt6QuickTest.so*) continue ;;
esac
cp -d "$_lib" "$APPDIR/usr/lib/" 2>/dev/null || true
done
cp -d "$QT_DIR/lib/libicu"*.so* "$APPDIR/usr/lib/" 2>/dev/null || true
for _plug in platforms imageformats tls iconengines xcbglintegrations; do
if [ -d "$QT_DIR/plugins/$_plug" ]; then
mkdir -p "$APPDIR/usr/plugins/$_plug"
cp -a "$QT_DIR/plugins/$_plug/." "$APPDIR/usr/plugins/$_plug/"
fi
done
# "Qt" carries Qt.labs.* (e.g. Qt.labs.folderlistmodel used by ImFileDialog.qml);
# the native linuxdeploy path resolves these from QML imports automatically.
for _qml in Qt QtCore QtGui QtQml QtQuick QtQuickControls2 QML; do
if [ -d "$QT_DIR/qml/$_qml" ]; then
mkdir -p "$APPDIR/usr/qml/$_qml"
cp -a "$QT_DIR/qml/$_qml/." "$APPDIR/usr/qml/$_qml/"
fi
done
fi
# Qt Wayland plugins, deployed for both paths above: linuxdeploy-plugin-qt does
# not ship these directories, and the manual list above does not either.
#
# libQt6WaylandClient looks for a shell integration under
# plugins/wayland-shell-integration; without libxdg-shell.so the "wayland" QPA
# plugin loads, connects to the compositor, then aborts with "Loading shell
# integration failed." Qt then falls back to "xcb", so every session -- Wayland
# included -- ends up on XWayland and needs libxcb-cursor. That library is now
# bundled (see appimage_lib_excluded() in debian/lib.sh, #1719), so the fallback
# no longer depends on the host shipping it; deploying these plugins is still
# what keeps a Wayland session off XWayland in the first place.
#
# These are Qt's own plugins and belong with the bundled Qt, unlike the wayland
# *system* libraries: libwayland-client/-cursor stay host-provided via
# --exclude-library above and libwayland-client0/libwayland-cursor0 in
# debian/control. libxdg-shell.so links only those two plus libQt6WaylandClient,
# which is already bundled, so this adds no new host dependency.
#
# wayland-graphics-integration-client carries libqt-plugin-wayland-egl.so, which
# is what gets GPU-accelerated Wayland rather than software shm buffers.
for _plug in wayland-shell-integration wayland-graphics-integration-client \
wayland-decoration-client; do
if [ -d "$QT_DIR/plugins/$_plug" ]; then
mkdir -p "$APPDIR/usr/plugins/$_plug"
cp -a "$QT_DIR/plugins/$_plug/." "$APPDIR/usr/plugins/$_plug/"
fi
done
fi
# Hook for removing files before AppImage creation
echo "Pre-packaging hook - opportunity to remove unwanted files"
# Remove host-coupled libraries that linuxdeploy-plugin-qt deploys despite --exclude-library
# These must come from the host system:
# libsystemd: works with lsblk/libmount/DBus (see #1304, #1577)
# libdbus-1: communicates with host session bus, NEEDED libsystemd which we exclude
# libcap: kernel capabilities interface, orphaned transitive dep of libsystemd
rm -f "$APPDIR/usr/lib/libsystemd"*
rm -f "$APPDIR/usr/lib/libdbus-1"*
rm -f "$APPDIR/usr/lib/libcap"*
rm -rf "$APPDIR/usr/share/doc/libsystemd"*
rm -rf "$APPDIR/usr/share/doc/libdbus"*
rm -rf "$APPDIR/usr/share/doc/libcap"*
# Prune the QML tree, style libraries and tooling to what the UI imports.
# Shared with the embedded packaging path -- see prune_qml_to_imports() in
# debian/lib.sh for the import list and how to re-derive it.
prune_qml_to_imports "$APPDIR/usr/qml" "$APPDIR/usr/lib" "$APPDIR/usr/plugins"
# Remove Qt translations (we excluded them but remove any that might have slipped through)
rm -rf "$APPDIR/usr/translations"
rm -rf "$APPDIR/usr/share/qt6/translations"
# Remove unnecessary image format plugins (consistency with all platforms)
# Excludes: TIFF, WebP, GIF, JPEG 2000 (less common formats)
# Keeps: JPEG, PNG, SVG (common formats + icons)
# libqjp2 additionally pulls in libjasper, which is not in the build chroot.
rm -f "$APPDIR/usr/plugins/imageformats/libqtiff.so"
rm -f "$APPDIR/usr/plugins/imageformats/libqwebp.so"
rm -f "$APPDIR/usr/plugins/imageformats/libqgif.so"
rm -f "$APPDIR/usr/plugins/imageformats/libqjp2.so"
# Bundle the non-host-coupled dependency closure of whatever survived pruning.
# The manual deployment branch above copies only Qt itself, so without this the
# AppImage relies on the host for ICU, PCRE2, zstd and friends -- ICU in
# particular is soname-pinned per Debian release (libicu72 on bookworm), which
# would tie the package to a single distro version.
if [ "$APPIMAGE_PACKAGING" != pack ]; then
appimage_deploy_lib_closure "$APPDIR" "$QT_DIR/lib" || exit 1
fi
if [ "$APPIMAGE_PACKAGING" = build ]; then
prepare_appdir_for_appimagetool "$APPDIR" com.raspberrypi.rpi-imager
echo "create-appimage: build stage complete (AppDir at $APPDIR)"
exit 0
fi
# Create the AppImage
echo "Creating AppImage..."
rm -f "$PWD/rpi-imager-desktop-$ARCH.AppImage"
rm -f "$PWD/rpi-imager-$ARCH.AppImage"
export LD_LIBRARY_PATH="$QT_DIR/lib:$LD_LIBRARY_PATH"
if [ -n "$LINUXDEPLOY" ] && [ -f "$LINUXDEPLOY" ] && [ "$ARCH" = "$TOOL_ARCH" ] && [ "$APPIMAGE_PACKAGING" = all ]; then
export APPIMAGE_EXTRACT_AND_RUN=1
"$LINUXDEPLOY" --appdir="$APPDIR" \
--desktop-file="$APPDIR/usr/share/applications/com.raspberrypi.rpi-imager.desktop" \
--exclude-library="libsystemd*" \
--exclude-library="libdbus-*" \
--exclude-library="libcap*" \
--exclude-library="libwayland-*" \
--output=appimage \
--verbosity=0
LINUXDEPLOY_OUTPUT="Raspberry_Pi_Imager-${ARCH}.AppImage"
if [ -f "$LINUXDEPLOY_OUTPUT" ]; then
echo "Renaming '$LINUXDEPLOY_OUTPUT' to '$(basename "$OUTPUT_FILE")'"
mv "$LINUXDEPLOY_OUTPUT" "$OUTPUT_FILE"
elif [ -f "$OUTPUT_FILE" ]; then
echo "Output file already exists: $OUTPUT_FILE"
else
echo "Warning: Expected linuxdeploy output '$LINUXDEPLOY_OUTPUT' not found"
ls -la ./*.AppImage 2>/dev/null || true
fi
elif [ -n "${APPIMAGETOOL:-}" ] && [ -f "$APPIMAGETOOL" ]; then
appimage_pack_with_tool "$APPIMAGETOOL" "$APPDIR" "$OUTPUT_FILE" \
"$ARCH" "$TOOL_ARCH" com.raspberrypi.rpi-imager || exit 1
else
echo "Error: no AppImage tooling available for $ARCH" >&2
exit 1
fi
echo "AppImage created at $OUTPUT_FILE"
if [ ! -f "$OUTPUT_FILE" ]; then
echo "Error: AppImage was not created at $OUTPUT_FILE" >&2
exit 1
fi
# Create symlinks for debian packaging and user convenience
# Primary symlink matches debian/rpi-imager.install expectations
DEBIAN_SYMLINK="$PWD/rpi-imager-$ARCH.AppImage"
if [ -L "$DEBIAN_SYMLINK" ] || [ -f "$DEBIAN_SYMLINK" ]; then
rm -f "$DEBIAN_SYMLINK"
fi
ln -s "$(basename "$OUTPUT_FILE")" "$DEBIAN_SYMLINK"
echo "Created symlink: $DEBIAN_SYMLINK -> $(basename "$OUTPUT_FILE")"
# Additional descriptive symlink for clarity when multiple variants exist
DESCRIPTIVE_SYMLINK="$PWD/rpi-imager-desktop-$ARCH.AppImage"
if [ -L "$DESCRIPTIVE_SYMLINK" ] || [ -f "$DESCRIPTIVE_SYMLINK" ]; then
rm -f "$DESCRIPTIVE_SYMLINK"
fi
ln -s "$(basename "$OUTPUT_FILE")" "$DESCRIPTIVE_SYMLINK"
echo "Created symlink: $DESCRIPTIVE_SYMLINK -> $(basename "$OUTPUT_FILE")"
echo "Build completed successfully for $ARCH architecture."