Windows installer: cross-build on Linux and publish to a downloads folder
scripts/windows-publish.sh builds the NSIS setup.exe for x86_64-pc-windows-msvc through cargo-xwin, versioned like the RPM and APK, and copies it into a folder to serve: the newest three installers, a stable mtgc-latest-x64-setup.exe, and SHA256SUMS.
This commit is contained in:
39
README.md
39
README.md
@@ -138,6 +138,45 @@ From then on, `sudo dnf upgrade` picks up new releases.
|
||||
- The RPM is built against this machine's libraries, so it installs on this
|
||||
Fedora release and newer.
|
||||
|
||||
### Distributing to Windows
|
||||
|
||||
The Windows installer is cross-built here on Linux and published to a plain
|
||||
downloads folder you host. `scripts/windows-publish.sh` builds it through
|
||||
[cargo-xwin](https://github.com/rust-cross/cargo-xwin) and needs, once:
|
||||
|
||||
```bash
|
||||
sudo dnf install mingw-nsis-base llvm lld clang
|
||||
```
|
||||
|
||||
```bash
|
||||
cargo install --locked cargo-xwin
|
||||
```
|
||||
|
||||
```bash
|
||||
rustup target add x86_64-pc-windows-msvc
|
||||
```
|
||||
|
||||
Then, for each release:
|
||||
|
||||
```bash
|
||||
./scripts/windows-publish.sh ~/win-mtgc # or: npm run windows:publish -- ~/win-mtgc
|
||||
```
|
||||
|
||||
On Windows, download and run the setup.exe. A newer one upgrades the
|
||||
installed app in place.
|
||||
|
||||
- **Serve the whole directory.** It holds the versioned installers
|
||||
(`mtgc_0.1.<n>_x64-setup.exe`, the newest three), `mtgc-latest-x64-setup.exe`
|
||||
as a stable link to the newest, and `SHA256SUMS`.
|
||||
- Only the NSIS `setup.exe` can be built off Windows; an MSI needs WiX, which
|
||||
runs only on Windows. The first build downloads the MSVC CRT and Windows SDK
|
||||
into `~/.cache/cargo-xwin`.
|
||||
- The installer isn't code-signed, so SmartScreen warns about an unknown
|
||||
publisher the first time: **More info → Run anyway**. It fetches WebView2 if
|
||||
the machine lacks it (Windows 10 and 11 normally ship it).
|
||||
- Versions work as on Android: `0.1.<commits on HEAD>`, see
|
||||
[Distributing to phones](#distributing-to-phones-f-droid).
|
||||
|
||||
## Using it
|
||||
|
||||
- **Add Cards** — type a name (typos OK); ↑/↓ then Enter adds a copy.
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
"sync-server:build": "scripts/sync-server-image.sh build",
|
||||
"sync-server:push": "scripts/sync-server-image.sh push",
|
||||
"android:publish": "scripts/fdroid-publish.sh",
|
||||
"rpm:publish": "scripts/rpm-publish.sh"
|
||||
"rpm:publish": "scripts/rpm-publish.sh",
|
||||
"windows:publish": "scripts/windows-publish.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2",
|
||||
|
||||
149
scripts/windows-publish.sh
Executable file
149
scripts/windows-publish.sh
Executable file
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# windows-publish.sh — cross-build the Windows installer and add it to a downloads folder.
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/windows-publish.sh ~/win-mtgc
|
||||
#
|
||||
# Or through npm: `npm run windows:publish -- ~/win-mtgc`.
|
||||
#
|
||||
# Options:
|
||||
# --allow-dirty publish uncommitted changes; the file name gets a -dirty suffix
|
||||
#
|
||||
# Environment:
|
||||
# MTGC_WINDOWS_DIR downloads directory, if not given as an argument
|
||||
#
|
||||
# Builds on Linux for x86_64-pc-windows-msvc through cargo-xwin, which fetches
|
||||
# the MSVC CRT and Windows SDK into ~/.cache/cargo-xwin the first time. Only
|
||||
# the NSIS installer can be made off Windows (MSI needs WiX). The directory is
|
||||
# public — serve it as is. Needs `sudo dnf install mingw-nsis-base llvm lld
|
||||
# clang`, `cargo install --locked cargo-xwin`, `rustup target add
|
||||
# x86_64-pc-windows-msvc`, and the desktop setup from ./scripts/devel-setup.sh.
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
sed -n '3,22p' "$0" | sed 's/^# \{0,1\}//'
|
||||
exit "${1:-0}"
|
||||
}
|
||||
|
||||
info() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
|
||||
warn() { printf '\033[1;33m[warn]\033[0m %s\n' "$*"; }
|
||||
err() { printf '\033[1;31m[err]\033[0m %s\n' "$*" >&2; }
|
||||
|
||||
PACKAGE="mtgc"
|
||||
TARGET="x86_64-pc-windows-msvc"
|
||||
LATEST="$PACKAGE-latest-x64-setup.exe"
|
||||
KEEP=3 # versions kept in the folder, so a bad release can be rolled back
|
||||
|
||||
allow_dirty=false
|
||||
dir="${MTGC_WINDOWS_DIR:-}"
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--allow-dirty) allow_dirty=true ;;
|
||||
-h | --help) usage ;;
|
||||
-*) usage 1 ;;
|
||||
*) dir="$1" ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
[ -n "$dir" ] || usage 1
|
||||
mkdir -p "$dir"
|
||||
dir="$(cd "$dir" && pwd)"
|
||||
|
||||
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$repo_root"
|
||||
|
||||
# --- 1. Tools ---------------------------------------------------------------
|
||||
|
||||
for tool in makensis llvm-rc lld-link clang; do
|
||||
if ! command -v "$tool" >/dev/null 2>&1; then
|
||||
err "$tool not found. Install them: sudo dnf install mingw-nsis-base llvm lld clang"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
if ! command -v cargo-xwin >/dev/null 2>&1; then
|
||||
err "cargo-xwin not found. Install it: cargo install --locked cargo-xwin"
|
||||
exit 1
|
||||
fi
|
||||
if command -v rustup >/dev/null 2>&1 && ! rustup target list --installed | grep -qxF "$TARGET"; then
|
||||
err "the $TARGET Rust target is missing. Add it: rustup target add $TARGET"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- 2. Version -------------------------------------------------------------
|
||||
#
|
||||
# The installer's own version stays numeric (NSIS insists); a dirty build is
|
||||
# only marked in the file name.
|
||||
|
||||
source scripts/lib/release-version.sh
|
||||
file_version="$release_version"
|
||||
if $release_dirty; then
|
||||
if ! $allow_dirty; then
|
||||
err "the working tree has uncommitted changes; commit them or pass --allow-dirty"
|
||||
exit 1
|
||||
fi
|
||||
file_version="$release_version-dirty"
|
||||
fi
|
||||
|
||||
# --- 3. Only ever move forward ----------------------------------------------
|
||||
|
||||
newest=0
|
||||
for exe in "$dir/${PACKAGE}"_*_x64-setup.exe; do
|
||||
[ -e "$exe" ] || continue
|
||||
patch="${exe##*/${PACKAGE}_}"
|
||||
patch="${patch%_x64-setup.exe}"
|
||||
patch="${patch%-dirty}"
|
||||
patch="${patch##*.}"
|
||||
[ "$patch" -gt "$newest" ] && newest="$patch"
|
||||
done
|
||||
if [ "$release_count" -le "$newest" ]; then
|
||||
err "version $release_version is not newer than the folder's x.y.$newest; commit something first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- 4. Build ---------------------------------------------------------------
|
||||
|
||||
info "building $file_version for $TARGET"
|
||||
outputs="target/$TARGET/release/bundle/nsis"
|
||||
rm -rf "$outputs"
|
||||
cargo tauri build --runner cargo-xwin --target "$TARGET" --bundles nsis --ci \
|
||||
--config "{\"version\":\"$release_version\"}"
|
||||
|
||||
built="$(find "$outputs" -name '*-setup.exe' | head -1)"
|
||||
if [ -z "$built" ]; then
|
||||
err "the build produced no installer under $outputs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- 5. Publish -------------------------------------------------------------
|
||||
|
||||
name="${PACKAGE}_${file_version}_x64-setup.exe"
|
||||
cp "$built" "$dir/$name"
|
||||
# A copy, not a symlink, so the stable link survives rsync and any static host.
|
||||
cp "$built" "$dir/.$LATEST.tmp"
|
||||
mv -f "$dir/.$LATEST.tmp" "$dir/$LATEST"
|
||||
|
||||
# Drop all but the newest few versions.
|
||||
mapfile -t old < <(find "$dir" -maxdepth 1 -name "${PACKAGE}_*_x64-setup.exe" | sort -V | head -n -"$KEEP")
|
||||
if [ "${#old[@]}" -gt 0 ]; then
|
||||
rm -f "${old[@]}"
|
||||
fi
|
||||
|
||||
(cd "$dir" && sha256sum "$LATEST" "${PACKAGE}"_*_x64-setup.exe >SHA256SUMS)
|
||||
|
||||
# --- 6. How to use it -------------------------------------------------------
|
||||
|
||||
info "published $file_version"
|
||||
cat <<EOF
|
||||
|
||||
Serve $dir as is. It holds:
|
||||
|
||||
$name
|
||||
$LATEST (always the newest)
|
||||
SHA256SUMS
|
||||
|
||||
On Windows, download and run the setup.exe; running a newer one upgrades the
|
||||
installed app in place. The installer is unsigned, so SmartScreen warns about
|
||||
an unknown publisher the first time: More info → Run anyway.
|
||||
EOF
|
||||
Reference in New Issue
Block a user