Fix id-namespace regression, add StrikeRequest type, kill full-panel
rerender on assign/alive/shell, add Windows build tooling - Board.add_target/add_ally's id auto-assignment used a bare next(c for c in string.ascii_uppercase if c not in used), which raises StopIteration once 26 entities of a group exist -- a real crash confirmed via a live traceback, and a direct regression from moving that sequence from per-type to per-group. This was the actual cause of "Accept as"/"Accept all" silently doing nothing. Fixed with _next_free_id(), which rolls over to two-letter ids instead of raising. - New TargetType.STRIKE_REQUEST: the bearing/distance-offset "taking fire" fire-support request (see the earlier two-entity split) now creates this instead of reusing STRIKE, so a radioed-in request is never confused with a strike the player placed themselves. Same crosshair icon, excluded from type pickers/dedupe like STRIKE. - The "Accept as..." popover on a detected map marker now uses the same icon grid the entity-edit "Change type" popover does (was a plain unfiltered text list of every TargetType, which also wrongly offered STRIKE/STRIKE_REQUEST as pickable). - Firing panel: _cycle_assignment/_toggle_alive/_pick_shell no longer route through app.py's full solver+dedupe+canvas+panel refresh -- none of the three can affect the solver or dedupe, and none change which cards exist or their order (except _toggle_alive in hide/sort_later mode). New FiringPanel._rebuild_one() rebuilds just the one changed card; on_visual_change is a new, lighter callback (just a map redraw) for the two of these three that actually affect it. This was a real, confirmed lag source with many units on the board: every click on any of these was previously rebuilding every card of every target. - Map right-click entity menu: added "Mark destroyed"/"Mark alive", reusing the same cheap-refresh path (new FiringPanel.refresh_after_alive_change). - packaging/windows/: a from-scratch (untested against a real boot) MSYS2 + WiX .msi build pipeline for Windows, driven from Linux via dockur/windows (KVM-in-container), no Windows machine or GitHub required. See its own README for status/caveats. - New/updated tests: id-namespace sharing + the 26-entity overflow regression (tests/test_models.py), StrikeRequest split (tests/test_ocr.py), warp_to_map's img_scale param (tests/test_map_vision_warp.py). 44/44 passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
# Windows .msi build (via dockur/windows)
|
||||
|
||||
Builds a Windows installer for FEnigma on a Linux host with no Windows
|
||||
machine and no GitHub, by booting a real Windows VM inside a container
|
||||
([dockur/windows](https://github.com/dockur/windows), QEMU+KVM under the
|
||||
hood, no license key needed for the eval install it fetches automatically)
|
||||
and driving the whole build over a shared folder.
|
||||
|
||||
**Status: written, not yet run against a real boot.** Everything here
|
||||
follows dockur/windows's and WiX's documented mechanics, but there's no
|
||||
KVM/Windows available in the environment this was authored in to actually
|
||||
exercise it end to end. Treat the first run as a debugging session, not a
|
||||
push-button success — watch it happen at http://localhost:8006 (dockur's
|
||||
noVNC viewer) so you can see where it's stuck if it stalls.
|
||||
|
||||
## How it fits together
|
||||
|
||||
- `docker-compose.yml` — boots the VM. Needs `/dev/kvm` on the host.
|
||||
- `oem/install.bat` — **one-time** provisioning, auto-run by Windows's own
|
||||
unattended setup on first boot (dockur/windows's `/oem` mechanism):
|
||||
installs MSYS2, then GTK4/libadwaita/PyGObject/numpy/Pillow/OpenCV/
|
||||
Tesseract through it, plus the WiX v3 toolset, and registers a
|
||||
boot-time watcher task. This is the slow part (Windows install itself,
|
||||
then package downloads) and only ever happens once — it lives on the
|
||||
VM's persistent disk (`./storage`, gitignored) from then on.
|
||||
- `oem/watch_build.bat` — runs at every boot from here on, polls the
|
||||
shared `Z:\` drive for a build request.
|
||||
- `oem/build.bat` — the actual per-build packaging: assembles a dist tree
|
||||
(bundled MSYS2 `mingw64` runtime + the `fenigma` package), harvests it
|
||||
into WiX components with `heat.exe`, and links it into an `.msi` with
|
||||
`candle.exe`/`light.exe`.
|
||||
- `oem/product.wxs` — the hand-authored shell around that harvested file
|
||||
list: install directory, Start Menu shortcut, and the `PYTHONPATH`
|
||||
environment variable the shortcut needs (mirrors `run.sh`'s
|
||||
`PYTHONPATH=src python -m fenigma.app`).
|
||||
- `build_windows.sh` — run this. Starts the VM, copies `../../src` onto
|
||||
the shared folder, drops a request file, waits for the `.msi` to come
|
||||
back, copies it to `../../dist-windows/`.
|
||||
|
||||
## Running it
|
||||
|
||||
```bash
|
||||
cd packaging/windows
|
||||
./build_windows.sh [version]
|
||||
```
|
||||
|
||||
First run: full unattended Windows install + provisioning, likely
|
||||
30-90 minutes, unattended (no interaction needed, but it needs to
|
||||
actually finish — don't kill it early). Every run after that: just boot
|
||||
the already-provisioned VM and build, a few minutes.
|
||||
|
||||
Requires `/dev/kvm` (virtualization enabled, your user in the `kvm`
|
||||
group) and Docker with Compose.
|
||||
|
||||
## Known rough edges / likely follow-up work
|
||||
|
||||
- **The dist tree is fat, not lean.** `build.bat` bulk-copies the entire
|
||||
`mingw64/` runtime rather than tracing the actual DLL/typelib/icon-
|
||||
theme/schema dependency closure of the app — reliable, but probably
|
||||
1GB+. Trimming it (e.g. by walking `pythonw.exe`'s and the compiled
|
||||
extension modules' actual dependencies) is a real but separate project.
|
||||
- **`heat.exe`'s default harvest options are a starting guess** for a
|
||||
tree this large and this GTK-specific (icon caches, gschemas, typelibs);
|
||||
it may need `-t` transforms or manual exclusions to produce a working
|
||||
component set.
|
||||
- **Not tested against a real GTK4/libadwaita Windows install at all** —
|
||||
MSYS2 ships these, but this is the first time this specific app has
|
||||
been pointed at them; expect a missing-DLL or schema error on first
|
||||
actual launch, not just a packaging error.
|
||||
- No code signing — Windows will show an "unknown publisher" warning.
|
||||
Executable
+80
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build a Windows .msi for FEnigma, entirely on this Linux host, no
|
||||
# Windows machine or GitHub required: boots a real Windows VM inside a
|
||||
# container (dockur/windows, QEMU+KVM), provisions it once (MSYS2 +
|
||||
# GTK4/libadwaita/PyGObject + WiX, see oem/install.bat), then drives every
|
||||
# build over a shared folder -- drop a request, wait for the .msi to show
|
||||
# up.
|
||||
#
|
||||
# UNTESTED end to end (no KVM/Windows available in the environment this
|
||||
# was written in) -- expect to debug oem/*.bat and product.wxs against a
|
||||
# real run. Watch the first boot/install at http://localhost:8006 (noVNC)
|
||||
# to see what's actually happening; it also has RDP on :3389 if you'd
|
||||
# rather use a real RDP client.
|
||||
#
|
||||
# First run: full unattended Windows install + provisioning, likely
|
||||
# 30-90 minutes. Every run after that: just boot + build, a few minutes.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")"
|
||||
|
||||
REPO_ROOT="$(cd .. && cd .. && pwd)"
|
||||
VERSION="${1:-0.1.0}"
|
||||
TIMEOUT_S="${BUILD_TIMEOUT_S:-7200}" # generous: covers a from-scratch first run
|
||||
OUT_DIR="${REPO_ROOT}/dist-windows"
|
||||
|
||||
if [ ! -e /dev/kvm ]; then
|
||||
echo "No /dev/kvm -- dockur/windows needs KVM (check virtualization is" >&2
|
||||
echo "enabled and your user is in the 'kvm' group: groups | grep kvm)." >&2
|
||||
exit 1
|
||||
fi
|
||||
command -v docker >/dev/null 2>&1 || { echo "docker not found." >&2; exit 1; }
|
||||
|
||||
mkdir -p storage oem shared/src shared/dist "$OUT_DIR"
|
||||
|
||||
echo "==> starting the Windows build VM (docker compose up -d)"
|
||||
docker compose up -d
|
||||
|
||||
echo "==> syncing FEnigma source into the VM's shared folder"
|
||||
rm -rf shared/src
|
||||
mkdir -p shared/src
|
||||
cp -r "${REPO_ROOT}/src" shared/src/
|
||||
echo "$VERSION" > shared/BUILD_VERSION
|
||||
rm -f shared/BUILD_DONE shared/BUILD_FAILED
|
||||
rm -rf shared/dist
|
||||
mkdir -p shared/dist
|
||||
|
||||
echo "==> requesting a build (version $VERSION)"
|
||||
touch shared/BUILD_REQUEST
|
||||
|
||||
echo "==> waiting for it (up to ${TIMEOUT_S}s -- first run is slow, see"
|
||||
echo " this script's own header comment; watch http://localhost:8006"
|
||||
echo " if you want to see what's actually happening)"
|
||||
elapsed=0
|
||||
while [ ! -e shared/BUILD_DONE ] && [ ! -e shared/BUILD_FAILED ]; do
|
||||
if [ "$elapsed" -ge "$TIMEOUT_S" ]; then
|
||||
echo "Timed out after ${TIMEOUT_S}s waiting for the build." >&2
|
||||
echo "Check the VM directly (http://localhost:8006) -- it may still" >&2
|
||||
echo "be mid Windows-install, or oem/install.bat may have wedged." >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 10
|
||||
elapsed=$((elapsed + 10))
|
||||
printf '.'
|
||||
done
|
||||
echo
|
||||
|
||||
if [ -e shared/BUILD_FAILED ]; then
|
||||
echo "==> build FAILED. Log:" >&2
|
||||
cat shared/dist/build.log 2>/dev/null || cat shared/build.log.failed 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
msi="$(find shared/dist -maxdepth 1 -name '*.msi' | head -n1)"
|
||||
if [ -z "$msi" ]; then
|
||||
echo "BUILD_DONE appeared but no .msi found in shared/dist -- see" >&2
|
||||
echo "shared/dist/build.log" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cp "$msi" "$OUT_DIR/"
|
||||
echo "==> done: $OUT_DIR/$(basename "$msi")"
|
||||
@@ -0,0 +1,37 @@
|
||||
# Boots a real Windows VM inside a container via dockur/windows (QEMU+KVM
|
||||
# under the hood, no Windows license/key needed for the eval install it
|
||||
# fetches automatically). Persistent disk lives in ./storage, so the
|
||||
# one-time provisioning in oem/install.bat only ever runs once -- every
|
||||
# later `docker compose up` just boots the already-provisioned VM.
|
||||
#
|
||||
# Requires /dev/kvm on the host (check with: ls -la /dev/kvm, and that
|
||||
# your user is in the `kvm` group).
|
||||
#
|
||||
# Volumes use the :Z suffix (SELinux relabeling for a container-private
|
||||
# label) -- confirmed needed on this host (Fedora, SELinux enforcing):
|
||||
# without it dockur/windows refuses to start with "Storage folder
|
||||
# (/storage) is not writeable!" even though normal Unix permissions are
|
||||
# fine. Harmless no-op on a host without SELinux.
|
||||
services:
|
||||
windows:
|
||||
image: dockurr/windows
|
||||
container_name: fenigma-windows-builder
|
||||
environment:
|
||||
VERSION: "11" # Windows 11 Pro, fetched+installed unattended on first boot
|
||||
RAM_SIZE: "8G"
|
||||
CPU_CORES: "4"
|
||||
DISK_SIZE: "80G" # MSYS2 + GTK4/libadwaita + WiX + build tree eats more than the 64G default
|
||||
devices:
|
||||
- /dev/kvm
|
||||
- /dev/net/tun
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
ports:
|
||||
- "8006:8006" # noVNC web viewer, http://localhost:8006 -- watch the first install here
|
||||
- "3389:3389/tcp" # RDP, if you'd rather use an RDP client
|
||||
volumes:
|
||||
- ./storage:/storage:Z # persistent VM disk
|
||||
- ./oem:/oem:Z # one-time provisioning payload, copied to C:\OEM on first install
|
||||
- ./shared:/shared:Z # live exchange folder, appears as Z:\ in Windows
|
||||
stop_grace_period: 2m
|
||||
restart: unless-stopped
|
||||
@@ -0,0 +1,86 @@
|
||||
@echo off
|
||||
REM Actual per-build packaging. Triggered by watch_build.bat once
|
||||
REM install.bat's one-time provisioning has already put MSYS2/GTK4/
|
||||
REM libadwaita/WiX in place. Reads source from Z:\src, writes
|
||||
REM FEnigma-<version>.msi to Z:\dist, and Z:\BUILD_DONE (or
|
||||
REM Z:\BUILD_FAILED, with the log copied alongside it) when finished.
|
||||
REM
|
||||
REM UNTESTED (see install.bat's note) -- the WiX harvest/link step in
|
||||
REM particular is likely to need iteration: bulk-copying all of
|
||||
REM mingw64\ is the "make it work first" approach, not a lean one, and
|
||||
REM heat.exe's default harvest options may need tuning to actually
|
||||
REM produce a working component set for a tree this size.
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
set LOG=Z:\build.log
|
||||
echo [build.bat] starting > %LOG%
|
||||
|
||||
if exist Z:\BUILD_VERSION (
|
||||
set /p APPVER=<Z:\BUILD_VERSION
|
||||
) else (
|
||||
set APPVER=0.1.0
|
||||
)
|
||||
echo [build.bat] version %APPVER% >> %LOG%
|
||||
|
||||
rd /s /q C:\build 2>nul
|
||||
mkdir C:\build\src
|
||||
mkdir C:\build\dist\src
|
||||
mkdir C:\build\dist\mingw64
|
||||
|
||||
echo [build.bat] copying source from Z:\src ... >> %LOG%
|
||||
xcopy /e /i /q Z:\src C:\build\src >> %LOG% 2>&1
|
||||
|
||||
echo [build.bat] sanity import check ... >> %LOG%
|
||||
set PYTHONPATH=C:\build\src\src
|
||||
C:\msys64\mingw64\bin\python3.exe -c "import fenigma.app" >> %LOG% 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [build.bat] FAILED: fenigma.app failed to import, see log >> %LOG%
|
||||
copy %LOG% Z:\build.log.failed >nul
|
||||
echo FAILED > Z:\BUILD_FAILED
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo [build.bat] assembling dist tree ... >> %LOG%
|
||||
xcopy /e /i /q C:\build\src\src C:\build\dist\src >> %LOG% 2>&1
|
||||
REM Bulk-copy the whole mingw64 runtime rather than hand-tracing the DLL/
|
||||
REM typelib/icon-theme/schema dependency closure -- bloated (likely 1GB+)
|
||||
REM but reliable; trimming this down is a known follow-up, not attempted
|
||||
REM here (see this file's top-of-file note).
|
||||
robocopy C:\msys64\mingw64 C:\build\dist\mingw64 /e /xd include share\doc share\man share\gtk-doc /nfl /ndl /njh /njs >> %LOG% 2>&1
|
||||
|
||||
echo [build.bat] harvesting WiX components ... >> %LOG%
|
||||
C:\wix\heat.exe dir C:\build\dist -cg AppFiles -gg -scom -sreg -sfrag -srd -sw5150 -dr INSTALLFOLDER -var var.DistDir -out C:\build\files.wxs >> %LOG% 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [build.bat] FAILED: heat.exe harvest failed >> %LOG%
|
||||
copy %LOG% Z:\build.log.failed >nul
|
||||
echo FAILED > Z:\BUILD_FAILED
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
copy /y C:\OEM\product.wxs C:\build\product.wxs >nul
|
||||
|
||||
echo [build.bat] compiling (candle) ... >> %LOG%
|
||||
C:\wix\candle.exe -dDistDir=C:\build\dist -dAppVersion=%APPVER% -out C:\build\ C:\build\product.wxs C:\build\files.wxs >> %LOG% 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [build.bat] FAILED: candle.exe failed >> %LOG%
|
||||
copy %LOG% Z:\build.log.failed >nul
|
||||
echo FAILED > Z:\BUILD_FAILED
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo [build.bat] linking (light) ... >> %LOG%
|
||||
C:\wix\light.exe -ext WixUIExtension -sice:ICE60 -sice:ICE61 -out C:\build\FEnigma-%APPVER%.msi C:\build\product.wixobj C:\build\files.wixobj >> %LOG% 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [build.bat] FAILED: light.exe failed >> %LOG%
|
||||
copy %LOG% Z:\build.log.failed >nul
|
||||
echo FAILED > Z:\BUILD_FAILED
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist Z:\dist mkdir Z:\dist
|
||||
copy /y C:\build\FEnigma-%APPVER%.msi Z:\dist\ >> %LOG% 2>&1
|
||||
copy /y %LOG% Z:\dist\build.log >nul
|
||||
|
||||
echo [build.bat] done >> %LOG%
|
||||
echo DONE > Z:\BUILD_DONE
|
||||
endlocal
|
||||
@@ -0,0 +1,81 @@
|
||||
@echo off
|
||||
REM One-time provisioning, auto-run by dockur/windows during the final step
|
||||
REM of Windows's own unattended setup (see its README's /oem mechanism).
|
||||
REM Everything here happens exactly once and lands on the VM's persistent
|
||||
REM disk -- later builds just boot this already-provisioned VM and run
|
||||
REM build.bat, no re-provisioning.
|
||||
REM
|
||||
REM UNTESTED end to end: written from MSYS2's documented CI bootstrap
|
||||
REM sequence (the same one msys2/setup-msys2 uses) and WiX's own docs, not
|
||||
REM verified against a live dockur/windows boot. Expect to debug this on
|
||||
REM the actual first run -- watch it happen at http://localhost:8006.
|
||||
REM
|
||||
REM Every step also echoes to Z:\install_progress.log (best-effort, only
|
||||
REM if the Z:\ shared drive happens to be up already at this point in
|
||||
REM setup) purely so build_windows.sh on the host has SOMETHING to show
|
||||
REM besides silence during the one-time provisioning run.
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
call :log "starting FEnigma build-VM provisioning"
|
||||
|
||||
REM -- MSYS2: the "base" self-extracting archive, not the GUI installer --
|
||||
REM (the GUI installer has no reliable non-interactive/silent flag across
|
||||
REM versions; the base sfx archive is what CI pipelines actually use).
|
||||
REM Discover the current filename by scraping the repo listing, since it's
|
||||
REM datestamped and there's no stable "latest" URL.
|
||||
call :log "finding current MSYS2 base archive..."
|
||||
powershell -NoProfile -Command ^
|
||||
"$ProgressPreference='SilentlyContinue';" ^
|
||||
"$html = Invoke-WebRequest -Uri 'https://repo.msys2.org/distrib/x86_64/' -UseBasicParsing;" ^
|
||||
"$name = ($html.Links | Where-Object { $_.href -match '^msys2-base-x86_64-.*\.sfx\.exe$' } | Select-Object -Last 1).href;" ^
|
||||
"Invoke-WebRequest -Uri ('https://repo.msys2.org/distrib/x86_64/' + $name) -OutFile 'C:\msys2-base.sfx.exe' -UseBasicParsing"
|
||||
if not exist C:\msys2-base.sfx.exe (
|
||||
call :log "FAILED: could not download MSYS2 base archive"
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
call :log "extracting MSYS2 to C:\msys64 ..."
|
||||
C:\msys2-base.sfx.exe -y -oC:\ >> C:\OEM\install.log 2>&1
|
||||
del C:\msys2-base.sfx.exe
|
||||
|
||||
REM First bash launch finalizes the base install and kills itself off
|
||||
REM mid-update (documented MSYS2 behavior) -- run it, ignore its exit
|
||||
REM code, then run the real update.
|
||||
call :log "bootstrapping MSYS2 (pacman -Syuu, twice) ..."
|
||||
C:\msys64\usr\bin\bash.exe -lc "exit 0" >> C:\OEM\install.log 2>&1
|
||||
C:\msys64\usr\bin\bash.exe -lc "pacman -Syuu --noconfirm" >> C:\OEM\install.log 2>&1
|
||||
C:\msys64\usr\bin\bash.exe -lc "pacman -Syuu --noconfirm" >> C:\OEM\install.log 2>&1
|
||||
|
||||
call :log "installing GTK4/libadwaita/PyGObject/build deps ..."
|
||||
C:\msys64\usr\bin\bash.exe -lc "pacman -S --noconfirm --needed mingw-w64-x86_64-python mingw-w64-x86_64-python-pip mingw-w64-x86_64-python-gobject mingw-w64-x86_64-gtk4 mingw-w64-x86_64-libadwaita mingw-w64-x86_64-python-numpy mingw-w64-x86_64-python-pillow mingw-w64-x86_64-opencv mingw-w64-x86_64-tesseract-ocr" >> C:\OEM\install.log 2>&1
|
||||
|
||||
call :log "pip install pytesseract (pure python, no wheel needed) ..."
|
||||
C:\msys64\mingw64\bin\python3.exe -m pip install pytesseract >> C:\OEM\install.log 2>&1
|
||||
|
||||
REM -- WiX v3 toolset (candle/light/heat), a plain zip of standalone exes,
|
||||
REM no installer needed. Fixed versioned URL, no scraping required.
|
||||
call :log "fetching WiX v3.11 ..."
|
||||
powershell -NoProfile -Command ^
|
||||
"$ProgressPreference='SilentlyContinue';" ^
|
||||
"Invoke-WebRequest -Uri 'https://github.com/wixtoolset/wix3/releases/download/wix3111rtm/wix311-binaries.zip' -OutFile 'C:\wix311-binaries.zip' -UseBasicParsing;" ^
|
||||
"Expand-Archive -Path 'C:\wix311-binaries.zip' -DestinationPath 'C:\wix' -Force"
|
||||
del C:\wix311-binaries.zip
|
||||
|
||||
REM -- Register the build watcher to run at every boot from here on, plus
|
||||
REM kick it off right now too (ONSTART won't retroactively fire for this
|
||||
REM already-in-progress boot). Runs as SYSTEM so it works with no user
|
||||
REM logged in.
|
||||
call :log "registering build watcher ..."
|
||||
schtasks /create /tn "FenigmaBuildWatcher" /sc onstart /ru SYSTEM /rl HIGHEST /tr "C:\OEM\watch_build.bat" /f >> C:\OEM\install.log 2>&1
|
||||
start "" cmd /c C:\OEM\watch_build.bat
|
||||
|
||||
call :log "provisioning done"
|
||||
echo DONE > C:\OEM\provisioned.marker
|
||||
if exist Z:\ echo DONE > Z:\PROVISIONED
|
||||
endlocal
|
||||
exit /b 0
|
||||
|
||||
:log
|
||||
echo [install.bat] %~1 >> C:\OEM\install.log
|
||||
if exist Z:\ echo [install.bat] %~1 >> Z:\install_progress.log
|
||||
exit /b 0
|
||||
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Hand-authored shell: directory layout, the Start Menu shortcut, and the
|
||||
PYTHONPATH environment variable the shortcut relies on (see run.sh's
|
||||
equivalent `PYTHONPATH=src python -m fenigma.app`). The actual app/
|
||||
runtime files are a separate auto-harvested fragment (files.wxs, built
|
||||
by heat.exe in build.bat) referenced here only by its ComponentGroup id.
|
||||
|
||||
UpgradeCode below is a fixed, generated-once GUID: DO NOT regenerate
|
||||
it, that's what lets a newer .msi upgrade an older install in place
|
||||
instead of installing side by side. ProductCode is left as "*" (auto-
|
||||
generated per build), which is the normal WiX pattern.
|
||||
|
||||
UNTESTED (see build.bat's top-of-file note).
|
||||
-->
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Product Id="*"
|
||||
Name="FEnigma"
|
||||
Language="1033"
|
||||
Version="$(var.AppVersion)"
|
||||
Manufacturer="FEnigma"
|
||||
UpgradeCode="DAB672A3-9E27-4F3F-8251-0AACD6E57B94">
|
||||
|
||||
<Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine" />
|
||||
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of FEnigma is already installed." />
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="ProgramFiles64Folder">
|
||||
<Directory Id="INSTALLFOLDER" Name="FEnigma" />
|
||||
</Directory>
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" Name="FEnigma" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<!-- AppFiles (all of dist\mingw64 + dist\src, harvested by heat.exe
|
||||
into files.wxs) is referenced by id only: its actual file list
|
||||
lives in that generated fragment, not here. -->
|
||||
<Feature Id="MainFeature" Title="FEnigma" Level="1">
|
||||
<ComponentGroupRef Id="AppFiles" />
|
||||
<ComponentRef Id="ApplicationShortcutComponent" />
|
||||
</Feature>
|
||||
|
||||
<DirectoryRef Id="ApplicationProgramsFolder">
|
||||
<Component Id="ApplicationShortcutComponent" Guid="*">
|
||||
<Shortcut Id="ApplicationStartMenuShortcut"
|
||||
Name="FEnigma"
|
||||
Description="Screen-reading helper for IRON NEST: Heavy Turret Simulator"
|
||||
Target="[INSTALLFOLDER]mingw64\bin\pythonw.exe"
|
||||
Arguments="-m fenigma.app"
|
||||
WorkingDirectory="INSTALLFOLDER" />
|
||||
<RemoveFolder Id="CleanUpShortcut" On="uninstall" />
|
||||
<!-- Machine-wide PYTHONPATH so the bundled mingw64\bin\pythonw.exe
|
||||
(which knows nothing about this app on its own) can find the
|
||||
fenigma package: same role run.sh's env var plays on Linux.
|
||||
Permanent="no": removed again on uninstall. -->
|
||||
<Environment Id="PythonPathEnv" Name="PYTHONPATH" Value="[INSTALLFOLDER]src"
|
||||
Permanent="no" Action="set" System="yes" Part="last" />
|
||||
<RegistryValue Root="HKCU" Key="Software\FEnigma" Name="installed" Type="integer" Value="1" KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- WixUI_Minimal: no EULA screen, so no WixUILicenseRtf override needed. -->
|
||||
<UIRef Id="WixUI_Minimal" />
|
||||
</Product>
|
||||
</Wix>
|
||||
@@ -0,0 +1,31 @@
|
||||
@echo off
|
||||
REM Runs persistently from system boot (see install.bat's scheduled task).
|
||||
REM Polls the host-shared Z:\ drive for a build request and, when one
|
||||
REM shows up, runs build.bat against it. This is what lets build_windows.sh
|
||||
REM on the Linux host trigger a build without any RDP/remote-exec: it's
|
||||
REM all just files dropped on the shared folder in both directions.
|
||||
REM
|
||||
REM UNTESTED (see install.bat's note).
|
||||
|
||||
:wait_for_share
|
||||
if not exist Z:\ (
|
||||
timeout /t 5 /nobreak >nul
|
||||
goto wait_for_share
|
||||
)
|
||||
|
||||
:loop
|
||||
if exist Z:\BUILD_REQUEST (
|
||||
REM Claim the request before acting on it -- if watch_build.bat somehow
|
||||
REM ended up running twice this boot (install.bat starts it once
|
||||
REM immediately, the ONSTART task could also fire the same boot), only
|
||||
REM one of them wins this move and actually builds.
|
||||
move /y Z:\BUILD_REQUEST Z:\BUILD_REQUEST.claimed >nul 2>&1
|
||||
if exist Z:\BUILD_REQUEST.claimed (
|
||||
del Z:\BUILD_REQUEST.claimed
|
||||
del /q Z:\BUILD_DONE 2>nul
|
||||
del /q Z:\BUILD_FAILED 2>nul
|
||||
call C:\OEM\build.bat
|
||||
)
|
||||
)
|
||||
timeout /t 5 /nobreak >nul
|
||||
goto loop
|
||||
Reference in New Issue
Block a user