The bundling loop ran under set -euo pipefail; once no new /mingw64 deps
remained, grep exited 1 and aborted the script before makensis ran, so no
Setup.exe was produced. Disable strict mode in that subshell and collect
deps before copying. Anchor all installer source paths to the script dir
via ${__FILEDIR__} and switch the File glob to "\*" so extensionless files
and plugin subfolders are included.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
102 lines
3.2 KiB
Bash
Executable file
102 lines
3.2 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)
|
|
#
|
|
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/"
|