Discovered building v1.1.0 that the MSI can be produced entirely on
Linux — no Windows VM, no manual WiX install, no GUI babysitting:
apt install wixl unzip gcc-mingw-w64-x86-64 binutils-mingw-w64-x86-64 \
mingw-w64-x86-64-dev curl
The new build-msi.sh script:
1. Runs sync.sh to refresh pkg/{lmcp,server,json}.lua from root.
2. Downloads Lua 5.4.2 Win64 binaries from LuaBinaries (Tools +
Library zips — interpreter + headers + import lib).
3. Cross-compiles LuaSocket 3.1.0 via x86_64-w64-mingw32-gcc
(produces socket-3.0.0.dll + mime-1.0.3.dll for Win64).
4. Stages pkg/lua/{lua.exe, lua54.dll, socket/, mime/, *.lua} per
the WiX manifest layout.
5. Invokes wixl on the lmcp.wxs manifest (with sed for the
Windows backslash path separators → forward slashes).
Output: lmcp-<version>.msi. Version is read from lmcp.wxs
Version="…", so bump that before each release.
Cold build: ~30s. Warm cache: ~5s. The artifact contains all 17
files the WiX manifest expects, ProductVersion matches lmcp.wxs.
README updated to point at build-msi.sh as the recommended path;
the Windows-side candle/light recipe kept as an alternative.
Reproducibility note (deferred): the MSI is not yet bit-reproducible
across builds — file mtimes in the Lua binaries' zip propagate to
the cab inside the MSI. The debian/lmcp/build-deb.sh in marfrit-
packages uses SOURCE_DATE_EPOCH to fix this; same pattern would
apply here. Out of scope for the first cut.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
windows/ was previously an untracked working tree with manually-
copied .lua files that drifted ~6 months out of date (missed every
feature added since April 2026). #18 introduces Option 1 from the
issue body: build-time sync.
New tracked files:
- windows/sync.sh — copies root {lmcp,server,json}.lua to pkg/.
Idempotent; run before WiX. Catches missing source files; logs
each sync.
- windows/README.md — workflow doc + tracked-vs-generated map.
- windows/lmcp.wxs — MSI manifest (Version bumped 0.1.0 → 1.1.0).
- windows/pkg/{install_service,start}.bat — Windows service
installer + launcher (now tracked; they were already in pkg/).
New .gitignore at repo root:
- windows/pkg/{lmcp,server,json}.lua — regenerated by sync.sh
- windows/pkg/lua/ — bundled Lua + LuaSocket runtime (downloaded
separately, not in git)
- editor noise (*.swp, *.swo, .DS_Store)
Verification (Phase 7):
$ ./windows/sync.sh
synced lmcp.lua
synced server.lua
synced json.lua
$ diff lmcp.lua windows/pkg/lmcp.lua → empty
$ git ls-files -o --exclude-standard windows/
windows/README.md
windows/lmcp.wxs
windows/pkg/install_service.bat
windows/pkg/start.bat
windows/sync.sh
$ git check-ignore windows/pkg/{lmcp,server,json}.lua → all 3 ignored
The "missed every feature since April" failure mode this fixes:
running sync.sh before each MSI build now guarantees pkg/ matches
master. Forgetting to run it is failure-loud (the MSI ships the
last sync's snapshot, easy to spot in QA), not silent (the manifest
points at fresh files that mismatch root).
Closes v1.1.0 milestone with #11, #20.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>