From 850378840bd0a358c9ed7b2f375a623b04acf61f Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Wed, 14 Oct 2026 08:23:15 -0700 Subject: [PATCH] add windows and mac/intel to the build --- .forgejo/workflows/build.yaml | 37 +++++++++++++++++++++++++-------- .kiro/specs/calculator/tasks.md | 15 ++++++++----- README.md | 20 +++++++++++------- 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 3c060d4..c54f8a7 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -77,14 +77,23 @@ jobs: zig build jvm-test --summary all zig build jvm-test -Doptimize=ReleaseSmall --summary all - name: Package the CLI and TUI - # One binary holds both. Static musl on Linux, so it runs on any distribution. + # One binary holds both, cross-compiled from here for every desktop target NFR-2 + # names. Static musl on Linux, so it runs on any distribution. The Windows build + # imports only ntdll.dll and kernel32.dll, so tally.exe is the whole download; + # the tally.dll beside it is the C ABI library and the .pdb is debug info. run: | mkdir -p dist - for target in x86_64-linux-musl aarch64-linux-musl aarch64-macos; do + while read -r target built published; do zig build -Dtarget="$target" -Doptimize="$RELEASE_OPTIMIZATION" --prefix "out/$target" - name="tally-${target%-musl}" - cp "out/$target/bin/tally" "dist/$name" - done + cp "out/$target/bin/$built" "dist/$published" + done <<'EOF' + x86_64-linux-musl tally tally-x86_64-linux + aarch64-linux-musl tally tally-aarch64-linux + aarch64-macos tally tally-aarch64-macos + x86_64-macos tally tally-x86_64-macos + x86_64-windows-gnu tally.exe tally-x86_64-windows.exe + aarch64-windows-gnu tally.exe tally-aarch64-windows.exe + EOF ls -la dist - name: Upload uses: actions/upload-artifact@v3 @@ -206,11 +215,21 @@ jobs: public_key: 'https://emil.lerch.org/serverpublic.pem' uhub_control: 'true' - name: Transparency log entries + # One SOURCE_n / URL_n pair per signed file, however many there are: this listed + # four by hand, and adding a file would have dropped its log entry silently. + # Plain sed over the outputs as JSON, so nothing beyond bash is assumed. + env: + OUTPUTS: ${{ toJSON(steps.sign.outputs) }} run: | - echo "${{ steps.sign.outputs.SOURCE_0 }}: ${{ steps.sign.outputs.URL_0 }}" - echo "${{ steps.sign.outputs.SOURCE_1 }}: ${{ steps.sign.outputs.URL_1 }}" - echo "${{ steps.sign.outputs.SOURCE_2 }}: ${{ steps.sign.outputs.URL_2 }}" - echo "${{ steps.sign.outputs.SOURCE_3 }}: ${{ steps.sign.outputs.URL_3 }}" + i=0 + while :; do + source="$(printf '%s\n' "$OUTPUTS" | sed -n "s/.*\"SOURCE_${i}\": *\"\([^\"]*\)\".*/\1/p")" + [ -n "$source" ] || break + url="$(printf '%s\n' "$OUTPUTS" | sed -n "s/.*\"URL_${i}\": *\"\([^\"]*\)\".*/\1/p")" + echo "${source}: ${url}" + i=$((i + 1)) + done + [ "$i" -gt 0 ] || { echo "no signatures reported" >&2; exit 1; } - name: Upload uses: actions/upload-artifact@v3 with: diff --git a/.kiro/specs/calculator/tasks.md b/.kiro/specs/calculator/tasks.md index 8470b9c..b0b6f71 100644 --- a/.kiro/specs/calculator/tasks.md +++ b/.kiro/specs/calculator/tasks.md @@ -241,12 +241,17 @@ run uninstalls the app first). ## Build, CI and release -### Windows and Intel macOS are built by nobody and run by nobody +### The Intel macOS and Windows on ARM builds, and the TUI on Windows, have never run -NFR-2 names Windows x86-64 and macOS x86-64 alongside the targets CI builds (x86_64 and -aarch64 Linux, aarch64 macOS). `zig build -Dtarget=x86_64-windows-gnu` and -`-Dtarget=x86_64-macos` both compile today; neither is in CI's release builds, and -neither binary, nor the TUI on a Windows console, has ever been run. +CI builds and publishes `tally-x86_64-macos`, `tally-x86_64-windows.exe` and +`tally-aarch64-windows.exe` with the other desktop targets. The Windows CLI has been run +under Wine: arithmetic, programmer mode, conversion, `tally struct` from an argument and +from stdin, errors with exit status 1, and output redirected to a file and appended to. +Still never run: the Intel macOS binary at all (it is a well-formed x86_64 Mach-O, which +is all that has been checked), the ARM64 Windows binary at all (an ARM64 PE that, like +the x64 one, imports only `ntdll.dll` and `kernel32.dll`; Wine here does not run ARM64), +and the TUI on a real Windows console. Under Wine with no console it fails cleanly with +"failed to start the TUI: InvalidHandle", which says nothing about a console that exists. ### Tests that run the binary diff --git a/README.md b/README.md index a416a96..9c12a13 100644 --- a/README.md +++ b/README.md @@ -73,12 +73,15 @@ Builds of `master` are published to the [package registry](https://git.lerch.org/lobo/-/packages/generic/tally/latest), each file with a detached signature: -| File | What | -|-----------------------|----------------------------------------------| -| `tally-x86_64-linux` | CLI and TUI, static (musl), any distribution | -| `tally-aarch64-linux` | the same for 64-bit ARM | -| `tally-aarch64-macos` | Apple silicon | -| `tally.apk` | the Android app, Android 8.0 and later | +| File | What | +|-----------------------------|----------------------------------------------| +| `tally-x86_64-linux` | CLI and TUI, static (musl), any distribution | +| `tally-aarch64-linux` | the same for 64-bit ARM | +| `tally-aarch64-macos` | Apple silicon | +| `tally-x86_64-macos` | Intel Macs | +| `tally-x86_64-windows.exe` | 64-bit Windows, no runtime to install | +| `tally-aarch64-windows.exe` | the same for Windows on ARM | +| `tally.apk` | the Android app, Android 8.0 and later | ``` curl -fLO https://git.lerch.org/api/packages/lobo/generic/tally/latest/tally-x86_64-linux @@ -88,6 +91,9 @@ chmod +x tally-x86_64-linux `latest` moves with every push to master. Each build is also published under its short commit SHA, which never changes. +The Windows executables carry the same detached signature as everything else, but no +Authenticode signature, so SmartScreen may warn the first time one runs. + ### Verifying a download Every file is signed by a key held in a hardware security module, and every signature is @@ -287,7 +293,7 @@ punctuation: the source is ASCII. | Job | Runner | What | |---------------------|--------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Engine, CLI and TUI | `ubuntu-latest` | `zig fmt --check`, zlint, build, `zig build test` in Debug and each release mode, `zig build jvm-test` in Debug and ReleaseSmall, then release builds for x86_64 and aarch64 Linux and aarch64 macOS | +| Engine, CLI and TUI | `ubuntu-latest` | `zig fmt --check`, zlint, build, `zig build test` in Debug and each release mode, `zig build jvm-test` in Debug and ReleaseSmall, then release builds for Linux, macOS and Windows | | Android | `ubuntu-latest` | `zig build android` (which audits the libraries), the JVM unit tests, debug and unsigned release APKs (with lint's release checks) | | Sign | `ubuntu-latest-with-hsm` | master only: signs the APK with the HSM, then every release file with a detached signature logged to sigstore | | Publish | `ubuntu-latest` | master only: uploads the signed files to the generic package registry under the short SHA and `latest` |