Introduce the Kotlin/Compose Android companion app and extend the TMDB proxy into a combo server that synchronizes the whole library as an encrypted snapshot, with all three components (Go server, Android, desktop) sharing one zero-knowledge crypto envelope and JSON schema. - server: add PostgreSQL-backed /sync/library (GET/PUT) with optimistic concurrency (revision + 409 on conflict); sync stays disabled unless DATABASE_URL is set. Add docker-compose with Postgres. - desktop: add libsodium CryptoEnvelope, LibrarySerializer and SyncClient; storage-mode and passphrase settings; a "Sync now" toolbar action with conflict resolution. - android: Room-backed library with local/cloud storage modes, encrypted sync client, and settings UI. The proxy server (URL + token) can be configured as a TMDB proxy even in local-only mode. Crypto is identical across platforms: Argon2id (libsodium crypto_pwhash, INTERACTIVE) + XChaCha20-Poly1305 in a versioned "UMTS" envelope, so a snapshot encrypted on one client decrypts on the other. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
109 lines
3.5 KiB
Bash
Executable file
109 lines
3.5 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# Build + package Ultimate Media Tracker for Windows.
|
|
# Run from the project root inside the MSYS2 *MINGW64* shell.
|
|
#
|
|
# Usage:
|
|
# ./build-windows.sh configure + build + bundle (+ installer)
|
|
# ./build-windows.sh clean wipe build/dist first
|
|
#
|
|
# Produces:
|
|
# dist/ portable build (zip & ship this folder)
|
|
# UltimateMediaTracker-Setup.exe NSIS installer (if makensis is installed)
|
|
#
|
|
# Prerequisites (MSYS2 MINGW64):
|
|
# pacman -S mingw-w64-x86_64-qt6 mingw-w64-x86_64-qt6-tools \
|
|
# mingw-w64-x86_64-libsodium mingw-w64-x86_64-cmake \
|
|
# mingw-w64-x86_64-ninja mingw-w64-x86_64-pkgconf
|
|
# libsodium provides the crypto for the encrypted library sync; its DLL is
|
|
# picked up automatically by the ldd bundling loop below.
|
|
#
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")"
|
|
|
|
BUILD_DIR="build-win"
|
|
DIST_DIR="dist"
|
|
EXE="umt.exe"
|
|
BUILD_TYPE="${BUILD_TYPE:-Release}"
|
|
|
|
# Must run in the MINGW64 environment so CMake finds Qt under /mingw64.
|
|
if [[ "${MSYSTEM:-}" != "MINGW64" ]]; then
|
|
echo "ERROR: run this from the MSYS2 MINGW64 shell (MSYSTEM=MINGW64)." >&2
|
|
exit 1
|
|
fi
|
|
|
|
WINDEPLOY="$(command -v windeployqt6 || command -v windeployqt || true)"
|
|
if [[ -z "$WINDEPLOY" ]]; then
|
|
echo "ERROR: windeployqt not found. Install with:" >&2
|
|
echo " pacman -S mingw-w64-x86_64-qt6-tools" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "${1:-}" == "clean" ]]; then
|
|
echo "==> Removing $BUILD_DIR and $DIST_DIR"
|
|
rm -rf "$BUILD_DIR" "$DIST_DIR"
|
|
fi
|
|
|
|
echo "==> Configuring ($BUILD_TYPE)"
|
|
# Set the generator only on a fresh dir; reusing one with -G errors out.
|
|
GEN=()
|
|
if [[ ! -f "$BUILD_DIR/CMakeCache.txt" ]]; then
|
|
GEN=(-G Ninja)
|
|
fi
|
|
cmake -S . -B "$BUILD_DIR" "${GEN[@]}" -DCMAKE_BUILD_TYPE="$BUILD_TYPE"
|
|
|
|
echo "==> Building"
|
|
cmake --build "$BUILD_DIR" -j
|
|
|
|
echo "==> Assembling $DIST_DIR"
|
|
rm -rf "$DIST_DIR"
|
|
mkdir -p "$DIST_DIR"
|
|
cp "$BUILD_DIR/$EXE" "$DIST_DIR/"
|
|
|
|
echo "==> Running windeployqt"
|
|
"$WINDEPLOY" --release --no-translations "$DIST_DIR/$EXE"
|
|
|
|
echo "==> Bundling MinGW runtime + transitive dependencies"
|
|
# windeployqt does not copy third-party MinGW DLLs (harfbuzz, freetype, png,
|
|
# pcre2, zlib, glib, libgcc/libstdc++/winpthread ...). Resolve them via ldd and
|
|
# repeat a few passes so transitive deps (incl. those of the deployed plugins)
|
|
# are all picked up.
|
|
( cd "$DIST_DIR"
|
|
# Disable strict mode here: once everything is copied, grep finds no new
|
|
# /mingw64 deps and returns 1, which would otherwise abort the whole script.
|
|
set +e +o pipefail
|
|
for _ in $(seq 1 6); do
|
|
deps="$(find . \( -name '*.exe' -o -name '*.dll' \) -print0 \
|
|
| xargs -0 -I{} ldd "{}" 2>/dev/null \
|
|
| grep -io '/mingw64/bin/[^ ]*\.dll' \
|
|
| sort -u)"
|
|
for f in $deps; do
|
|
[ -e "./$(basename "$f")" ] || cp "$f" .
|
|
done
|
|
done
|
|
)
|
|
|
|
echo "==> Verifying dependencies"
|
|
if command -v ntldd >/dev/null 2>&1; then
|
|
missing="$(cd "$DIST_DIR" && ntldd -R "$EXE" 2>/dev/null | grep -i 'not found' || true)"
|
|
if [[ -n "$missing" ]]; then
|
|
echo "WARNING: unresolved dependencies remain:" >&2
|
|
echo "$missing" >&2
|
|
else
|
|
echo " all dependencies resolved."
|
|
fi
|
|
else
|
|
echo " (install mingw-w64-x86_64-ntldd to auto-verify)"
|
|
fi
|
|
|
|
if command -v makensis >/dev/null 2>&1; then
|
|
echo "==> Building NSIS installer"
|
|
makensis installer.nsi
|
|
echo "==> Installer: UltimateMediaTracker-Setup.exe"
|
|
else
|
|
echo "NOTE: makensis not found; skipping installer."
|
|
echo " Install it with: pacman -S mingw-w64-x86_64-nsis"
|
|
fi
|
|
|
|
echo
|
|
echo "==> Done. Portable build in: $DIST_DIR/"
|