-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbuild.sh
More file actions
executable file
·674 lines (575 loc) · 19.8 KB
/
Copy pathbuild.sh
File metadata and controls
executable file
·674 lines (575 loc) · 19.8 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
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
#!/bin/bash
# Unified build script for Chuk Chat
# Usage: ./build.sh [target]
# Targets: linux, deb, rpm, apk, apk-desktop, appimage, all
#
# IMPORTANT: Requires .env file with SUPABASE_URL and SUPABASE_ANON_KEY.
#
# Tree-shaking optimization:
# - Desktop builds exclude mobile code, mobile builds exclude desktop code
# - --tree-shake-icons removes unused Material/Cupertino icons
# - --split-debug-info separates debug symbols for smaller binaries
# - --obfuscate obfuscates Dart code
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
NC='\033[0m'
# Print functions
print_header() { echo -e "${PURPLE}$1${NC}"; }
print_info() { echo -e "${BLUE}$1${NC}"; }
print_success() { echo -e "${GREEN}$1${NC}"; }
print_warning() { echo -e "${YELLOW}$1${NC}"; }
print_error() { echo -e "${RED}$1${NC}"; }
# Display name (shown in desktop launchers, etc.)
DISPLAY_NAME="Chuk Chat"
# Load environment variables
load_env() {
if [ -f ".env" ]; then
# shellcheck disable=SC2046
export $(grep -v '^#' .env | xargs)
fi
if [ -z "$SUPABASE_URL" ] || [ -z "$SUPABASE_ANON_KEY" ]; then
print_error "SUPABASE_URL and SUPABASE_ANON_KEY must be set."
print_error "Create .env file from .env.example or set environment variables."
exit 1
fi
print_success "Supabase credentials loaded"
}
# Common dart-define flags for all builds
dart_defines_desktop() {
local linux_keyring="${FEATURE_LINUX_KEYRING:-true}"
echo "--dart-define=SUPABASE_URL=$SUPABASE_URL \
--dart-define=SUPABASE_ANON_KEY=$SUPABASE_ANON_KEY \
--dart-define=PLATFORM_DESKTOP=true \
--dart-define=FEATURE_PROJECTS=false \
--dart-define=FEATURE_IMAGE_GEN=true \
--dart-define=FEATURE_VOICE_MODE=false \
--dart-define=FEATURE_SERVER_TOOLS=false \
--dart-define=FEATURE_LINUX_KEYRING=$linux_keyring"
}
dart_defines_mobile() {
local linux_keyring="${FEATURE_LINUX_KEYRING:-true}"
echo "--dart-define=SUPABASE_URL=$SUPABASE_URL \
--dart-define=SUPABASE_ANON_KEY=$SUPABASE_ANON_KEY \
--dart-define=PLATFORM_MOBILE=true \
--dart-define=FEATURE_PROJECTS=false \
--dart-define=FEATURE_IMAGE_GEN=true \
--dart-define=FEATURE_VOICE_MODE=false \
--dart-define=FEATURE_SERVER_TOOLS=false \
--dart-define=FEATURE_LINUX_KEYRING=$linux_keyring"
}
# Extract app information
extract_app_info() {
print_info "Extracting app information from pubspec.yaml..."
APP_NAME=$(grep '^name:' pubspec.yaml | sed 's/^name:[[:space:]]*//' | sed 's/[[:space:]]*$//')
VERSION=$(grep '^version:' pubspec.yaml | sed 's/^version:[[:space:]]*//' | sed 's/+.*//' | sed 's/[[:space:]]*$//')
if [ -z "$APP_NAME" ] || [ -z "$VERSION" ]; then
print_error "Could not extract app name or version from pubspec.yaml"
exit 1
fi
# Package name uses hyphens (chuk-chat), binary name uses underscores (chuk_chat)
PACKAGE_NAME=$(echo "$APP_NAME" | sed 's/_/-/g')
# Android build number from the whole semantic version, not just the patch:
# 1.0.109 -> 100109. A patch-only number goes backwards on a minor bump
# (1.1.0 would be 0), which Android refuses to install over.
# --split-per-abi multiplies this by 1000 and Android caps versionCode at
# 2100000000, so it must stay under 2100000. Same formula in
# android/fastlane/Fastfile and .github/workflows/build-cross-platform.yml.
BUILD_NUMBER=$(echo "$VERSION" | awk -F. '{print ($1*100000)+($2*1000)+$3}')
if [ -z "$BUILD_NUMBER" ] || [ "$BUILD_NUMBER" -lt 1 ] 2>/dev/null; then
BUILD_NUMBER=1
fi
print_success "App: $APP_NAME v$VERSION (package: $PACKAGE_NAME, build: $BUILD_NUMBER)"
}
# Find the best app icon
find_app_icon() {
print_info "Finding app icon..."
ICON_PATH=""
# Prefer web 512px icon (best quality for desktop)
if [ -f "web/icons/Icon-512.png" ]; then
ICON_PATH="web/icons/Icon-512.png"
else
# Fall back to Android mipmap icons
for size in xxxhdpi xxhdpi xhdpi hdpi mdpi; do
if [ -f "android/app/src/main/res/mipmap-${size}/ic_launcher.png" ]; then
ICON_PATH="android/app/src/main/res/mipmap-${size}/ic_launcher.png"
break
fi
done
fi
if [ -n "$ICON_PATH" ]; then
print_success "Found icon: $ICON_PATH"
else
print_warning "No app icon found"
fi
}
# Clean up previous builds
cleanup() {
print_info "Cleaning up previous builds..."
flutter clean
rm -rf debian rpm build/linux build/app AppDir
mkdir -p releases/linux releases/android
}
# Build Linux app
build_linux() {
local arch=$1
print_info "Building Linux app for $arch..."
local defines
defines=$(dart_defines_desktop)
case $arch in
"amd64")
eval flutter build linux --release --target-platform linux-x64 \
$defines \
--tree-shake-icons \
--split-debug-info=build/debug-info \
--obfuscate
;;
"arm64")
if ! eval flutter build linux --release --target-platform linux-arm64 \
$defines \
--tree-shake-icons \
--split-debug-info=build/debug-info \
--obfuscate 2>/dev/null; then
print_warning "ARM64 build not supported on this system, skipping..."
return 1
fi
;;
*)
print_error "Unsupported Linux architecture: $arch"
exit 1
;;
esac
print_success "Linux build completed for $arch"
return 0
}
# Get the bundle directory for a given arch
bundle_dir() {
local arch=$1
if [ "$arch" = "amd64" ]; then
echo "build/linux/x64/release/bundle"
else
echo "build/linux/arm64/release/bundle"
fi
}
# Create deb package
create_deb() {
local arch=$1
local bundle
bundle=$(bundle_dir "$arch")
print_info "Creating .deb package for $arch..."
# Create directory structure — install to /opt/chuk-chat/
mkdir -p "debian/DEBIAN"
mkdir -p "debian/opt/$PACKAGE_NAME"
mkdir -p "debian/usr/bin"
mkdir -p "debian/usr/share/applications"
mkdir -p "debian/usr/share/icons/hicolor/512x512/apps"
# Copy Flutter bundle
cp -r "$bundle"/* "debian/opt/$PACKAGE_NAME/"
chmod +x "debian/opt/$PACKAGE_NAME/$APP_NAME"
# Create symlink so 'chuk-chat' works from command line
ln -s "/opt/$PACKAGE_NAME/$APP_NAME" "debian/usr/bin/$PACKAGE_NAME"
# Copy icon
if [ -n "$ICON_PATH" ] && [ -f "$ICON_PATH" ]; then
cp "$ICON_PATH" "debian/usr/share/icons/hicolor/512x512/apps/$PACKAGE_NAME.png"
fi
# Desktop entry
cat > "debian/usr/share/applications/$PACKAGE_NAME.desktop" <<EOF
[Desktop Entry]
Version=1.0
Type=Application
Name=$DISPLAY_NAME
GenericName=Chat Application
Comment=Privacy-focused AI chat with end-to-end encryption
Exec=/opt/$PACKAGE_NAME/$APP_NAME
Icon=$PACKAGE_NAME
Terminal=false
Categories=Network;InstantMessaging;Chat;
StartupWMClass=$APP_NAME
Keywords=chat;ai;encrypted;privacy;
EOF
# Control file
cat > "debian/DEBIAN/control" <<EOF
Package: $PACKAGE_NAME
Version: $VERSION
Section: net
Priority: optional
Architecture: $arch
Maintainer: Chuk Development <support@chuk.dev>
Homepage: https://chuk.chat
Description: Privacy-focused AI chat with end-to-end encryption
$DISPLAY_NAME is a cross-platform chat application that uses
open-weight AI models with AES-256-GCM end-to-end encryption.
Your messages are encrypted on your device before leaving it.
Depends: libgtk-3-0, libblkid1, liblzma5
EOF
# Post-install script
cat > "debian/DEBIAN/postinst" <<'EOF'
#!/bin/bash
update-desktop-database /usr/share/applications 2>/dev/null || true
gtk-update-icon-cache -f -t /usr/share/icons/hicolor 2>/dev/null || true
EOF
# Pre-remove script
cat > "debian/DEBIAN/prerm" <<'EOF'
#!/bin/bash
update-desktop-database /usr/share/applications 2>/dev/null || true
gtk-update-icon-cache -f -t /usr/share/icons/hicolor 2>/dev/null || true
EOF
chmod +x "debian/DEBIAN/postinst"
chmod +x "debian/DEBIAN/prerm"
# Build
dpkg-deb --build debian "releases/linux/${PACKAGE_NAME}_${VERSION}_${arch}.deb"
print_success "Created ${PACKAGE_NAME}_${VERSION}_${arch}.deb"
}
# Create rpm package
create_rpm() {
local arch=$1
local bundle
bundle=$(bundle_dir "$arch")
print_info "Creating .rpm package for $arch..."
if ! command -v rpmbuild &> /dev/null; then
print_warning "rpmbuild not found. Install with: sudo apt install rpm"
return 0
fi
# Map Debian arch to RPM arch
local rpm_arch="x86_64"
[ "$arch" = "arm64" ] && rpm_arch="aarch64"
# Create directory structure
mkdir -p rpm/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
mkdir -p "rpm/SOURCES/$PACKAGE_NAME-$VERSION"
cp -r "$bundle"/* "rpm/SOURCES/$PACKAGE_NAME-$VERSION/"
# Create tarball
(cd rpm/SOURCES && tar -czf "$PACKAGE_NAME-$VERSION.tar.gz" "$PACKAGE_NAME-$VERSION")
# Spec file
cat > "rpm/SPECS/$PACKAGE_NAME.spec" <<EOF
Name: $PACKAGE_NAME
Version: $VERSION
Release: 1%{?dist}
Summary: Privacy-focused AI chat with end-to-end encryption
License: BSL-1.1
URL: https://chuk.chat
Source0: %{name}-%{version}.tar.gz
BuildArch: $rpm_arch
Requires: gtk3, libblkid, xz-libs
%description
$DISPLAY_NAME is a cross-platform chat application that uses
open-weight AI models with AES-256-GCM end-to-end encryption.
Your messages are encrypted on your device before leaving it.
%prep
%setup -q
%build
%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/opt/%{name}
mkdir -p %{buildroot}/usr/bin
mkdir -p %{buildroot}/usr/share/applications
mkdir -p %{buildroot}/usr/share/icons/hicolor/512x512/apps
cp -r * %{buildroot}/opt/%{name}/
chmod +x %{buildroot}/opt/%{name}/$APP_NAME
ln -s /opt/%{name}/$APP_NAME %{buildroot}/usr/bin/%{name}
EOF
# Copy icon into rpm build
if [ -n "$ICON_PATH" ] && [ -f "$ICON_PATH" ]; then
cp "$ICON_PATH" "rpm/BUILD/$PACKAGE_NAME.png"
echo "cp $PWD/rpm/BUILD/$PACKAGE_NAME.png %{buildroot}/usr/share/icons/hicolor/512x512/apps/%{name}.png" >> "rpm/SPECS/$PACKAGE_NAME.spec"
fi
# Desktop entry and file list
cat >> "rpm/SPECS/$PACKAGE_NAME.spec" <<EOF
cat > %{buildroot}/usr/share/applications/%{name}.desktop <<'DESKTOP'
[Desktop Entry]
Version=1.0
Type=Application
Name=$DISPLAY_NAME
GenericName=Chat Application
Comment=Privacy-focused AI chat with end-to-end encryption
Exec=/opt/$PACKAGE_NAME/$APP_NAME
Icon=$PACKAGE_NAME
Terminal=false
Categories=Network;InstantMessaging;Chat;
StartupWMClass=$APP_NAME
Keywords=chat;ai;encrypted;privacy;
DESKTOP
%files
/opt/%{name}/
/usr/bin/%{name}
/usr/share/applications/%{name}.desktop
/usr/share/icons/hicolor/512x512/apps/%{name}.png
%post
update-desktop-database /usr/share/applications 2>/dev/null || true
gtk-update-icon-cache -f -t /usr/share/icons/hicolor 2>/dev/null || true
%preun
rm -f /usr/share/applications/%{name}.desktop
update-desktop-database /usr/share/applications 2>/dev/null || true
%changelog
* $(date '+%a %b %d %Y') Chuk Development <support@chuk.dev> - $VERSION-1
- Release $VERSION
EOF
rpmbuild --define "_topdir $(pwd)/rpm" -bb "rpm/SPECS/$PACKAGE_NAME.spec"
find rpm/RPMS -name "*.rpm" -exec cp {} "releases/linux/${PACKAGE_NAME}_${VERSION}_${rpm_arch}.rpm" \;
print_success "Created ${PACKAGE_NAME}_${VERSION}_${rpm_arch}.rpm"
}
# Download appimagetool if not present
download_appimagetool() {
local SCRIPT_DIR
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
local TOOLS_DIR="$SCRIPT_DIR/tools"
local APPIMAGETOOL_PATH="$TOOLS_DIR/appimagetool"
if [ -x "$APPIMAGETOOL_PATH" ]; then
return 0
fi
print_info "appimagetool not found, downloading..."
mkdir -p "$TOOLS_DIR"
local DOWNLOAD_URL="https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
if command -v curl &> /dev/null; then
curl -L -o "$APPIMAGETOOL_PATH" "$DOWNLOAD_URL"
elif command -v wget &> /dev/null; then
wget -O "$APPIMAGETOOL_PATH" "$DOWNLOAD_URL"
else
print_error "Neither curl nor wget found. Cannot download appimagetool."
return 1
fi
if [ -f "$APPIMAGETOOL_PATH" ]; then
chmod +x "$APPIMAGETOOL_PATH"
print_success "Downloaded appimagetool"
return 0
else
print_error "Failed to download appimagetool"
return 1
fi
}
# Create AppImage
create_appimage() {
local arch=$1
local bundle
bundle=$(bundle_dir "$arch")
print_info "Creating AppImage for $arch..."
# Map to AppImage arch naming
local appimage_arch="x86_64"
[ "$arch" = "arm64" ] && appimage_arch="aarch64"
# Find appimagetool
local APPIMAGETOOL=""
local SCRIPT_DIR
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ ! -x "$SCRIPT_DIR/tools/appimagetool" ]; then
download_appimagetool
fi
if [ -x "$SCRIPT_DIR/tools/appimagetool" ]; then
APPIMAGETOOL="$SCRIPT_DIR/tools/appimagetool"
elif command -v appimagetool &> /dev/null; then
APPIMAGETOOL="appimagetool"
else
print_warning "appimagetool not found. Skipping AppImage creation."
return 0
fi
# Create AppDir structure
mkdir -p "AppDir/usr/bin"
mkdir -p "AppDir/usr/share/applications"
mkdir -p "AppDir/usr/share/icons/hicolor/512x512/apps"
# Copy Flutter bundle
cp -r "$bundle"/* "AppDir/usr/bin/"
chmod +x "AppDir/usr/bin/$APP_NAME"
# Copy icon
if [ -n "$ICON_PATH" ] && [ -f "$ICON_PATH" ]; then
cp "$ICON_PATH" "AppDir/usr/share/icons/hicolor/512x512/apps/$PACKAGE_NAME.png"
# AppImage needs icon in root
cp "$ICON_PATH" "AppDir/$PACKAGE_NAME.png"
fi
# Desktop entry
cat > "AppDir/$PACKAGE_NAME.desktop" <<EOF
[Desktop Entry]
Version=1.0
Type=Application
Name=$DISPLAY_NAME
GenericName=Chat Application
Comment=Privacy-focused AI chat with end-to-end encryption
Exec=$APP_NAME
Icon=$PACKAGE_NAME
Terminal=false
Categories=Network;InstantMessaging;Chat;
StartupWMClass=$APP_NAME
Keywords=chat;ai;encrypted;privacy;
EOF
# Copy desktop file into standard location too
cp "AppDir/$PACKAGE_NAME.desktop" "AppDir/usr/share/applications/"
# AppRun
cat > "AppDir/AppRun" <<'APPRUN'
#!/bin/bash
HERE="$(dirname "$(readlink -f "$0")")"
export LD_LIBRARY_PATH="${HERE}/usr/bin/lib:${LD_LIBRARY_PATH}"
exec "${HERE}/usr/bin/chuk_chat" "$@"
APPRUN
chmod +x "AppDir/AppRun"
# Build AppImage with correct architecture
ARCH=$appimage_arch $APPIMAGETOOL AppDir "releases/linux/${PACKAGE_NAME}_${VERSION}_${appimage_arch}.AppImage"
print_success "Created ${PACKAGE_NAME}_${VERSION}_${appimage_arch}.AppImage"
}
# Build Android APKs (mobile UI)
build_android() {
print_info "Building Android APKs..."
local defines
defines=$(dart_defines_mobile)
if eval flutter build apk --release --split-per-abi \
$defines \
--build-number=$BUILD_NUMBER \
--tree-shake-icons \
--split-debug-info=build/android-debug-info \
--obfuscate; then
mkdir -p releases/android
for apk in build/app/outputs/flutter-apk/app-*-release.apk; do
if [ -f "$apk" ]; then
filename=$(basename "$apk")
arch=$(echo "$filename" | sed 's/app-\(.*\)-release.apk/\1/')
cp "$apk" "releases/android/${PACKAGE_NAME}_${VERSION}_${arch}.apk"
print_success "Created ${PACKAGE_NAME}_${VERSION}_${arch}.apk"
fi
done
else
print_error "Android build failed"
return 1
fi
}
# Build Android APKs with desktop UI (for tablets)
build_android_desktop() {
print_info "Building Android APKs with desktop UI for tablets..."
local defines
defines=$(dart_defines_desktop)
if eval flutter build apk --release --split-per-abi \
$defines \
--build-number=$BUILD_NUMBER \
--tree-shake-icons \
--split-debug-info=build/android-debug-info \
--obfuscate; then
mkdir -p releases/android
for apk in build/app/outputs/flutter-apk/app-*-release.apk; do
if [ -f "$apk" ]; then
filename=$(basename "$apk")
arch=$(echo "$filename" | sed 's/app-\(.*\)-release.apk/\1/')
cp "$apk" "releases/android/${PACKAGE_NAME}_${VERSION}_${arch}_desktop.apk"
print_success "Created ${PACKAGE_NAME}_${VERSION}_${arch}_desktop.apk"
fi
done
else
print_error "Android tablet build failed"
return 1
fi
}
# Main build functions
build_linux_packages() {
print_header "Building Linux packages..."
for arch in amd64 arm64; do
print_header "Building for $arch..."
if build_linux $arch; then
create_deb $arch
create_rpm $arch
create_appimage $arch
rm -rf debian rpm AppDir
else
print_warning "Skipping $arch packages (build failed)"
fi
done
}
build_deb_packages() {
print_header "Building DEB packages..."
for arch in amd64 arm64; do
if build_linux $arch; then
create_deb $arch
rm -rf debian
else
print_warning "Skipping DEB for $arch"
fi
done
}
build_rpm_packages() {
print_header "Building RPM packages..."
for arch in amd64 arm64; do
if build_linux $arch; then
create_rpm $arch
rm -rf rpm
else
print_warning "Skipping RPM for $arch"
fi
done
}
build_appimage_packages() {
print_header "Building AppImage packages..."
for arch in amd64 arm64; do
if build_linux $arch; then
create_appimage $arch
rm -rf AppDir
else
print_warning "Skipping AppImage for $arch"
fi
done
}
# Show usage
show_usage() {
echo ""
print_header "Chuk Chat Build System"
echo ""
echo "Usage: $0 [target]"
echo ""
echo "Targets:"
echo " linux All Linux packages (DEB, RPM, AppImage)"
echo " deb DEB packages only (Debian/Ubuntu)"
echo " rpm RPM packages only (Fedora/RHEL)"
echo " appimage AppImage packages only"
echo " apk Android APKs (mobile UI)"
echo " apk-desktop Android APKs (desktop UI for tablets)"
echo " all Linux + Android"
echo ""
echo "Output: releases/linux/ and releases/android/"
echo ""
}
# Main execution
main() {
if [ $# -eq 0 ] || [ "$1" = "--help" ] || [ "$1" = "-h" ] || [ "$1" = "help" ]; then
show_usage
exit 0
fi
local target=$1
extract_app_info
load_env
find_app_icon
cleanup
print_header "Building $DISPLAY_NAME v$VERSION..."
case $target in
"linux") build_linux_packages ;;
"deb") build_deb_packages ;;
"rpm") build_rpm_packages ;;
"appimage") build_appimage_packages ;;
"apk") build_android ;;
"apk-desktop") build_android_desktop ;;
"all")
build_linux_packages
build_android
;;
*)
print_error "Unknown target: $target"
show_usage
exit 1
;;
esac
echo ""
print_success "Build completed!"
echo ""
print_info "Linux packages:"
ls -lh releases/linux/ 2>/dev/null || echo " (none)"
echo ""
print_info "Android packages:"
ls -lh releases/android/ 2>/dev/null || echo " (none)"
}
# Check dependencies
check_dependencies() {
local missing_deps=()
command -v flutter &> /dev/null || missing_deps+=("flutter")
command -v dpkg-deb &> /dev/null || missing_deps+=("dpkg-deb")
if [ ${#missing_deps[@]} -ne 0 ]; then
print_error "Missing dependencies: ${missing_deps[*]}"
exit 1
fi
}
check_dependencies
main "$@"