From b3da4e812591039ea1517e1f862fe7472516b0de Mon Sep 17 00:00:00 2001 From: Jeremy Collins Date: Mon, 6 Jul 2026 10:58:57 -0400 Subject: [PATCH] fix(tools): compile the tile57 CLI for Windows (gate the POSIX-only --tui) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The interactive `ascii --tui` / `explore --tui` loops enter raw mode via std.posix termios, whose type is `void` on Windows — so `raw.lflag.ICANON` failed to compile and broke `zig build` for x86_64/aarch64-windows-gnu. That in turn broke chartplotter's release cross-build: libtile57.a compiles fine, but the bundled `tile57` CLI exe (built by the same default `zig build`) did not. Gate each TUI body behind a comptime `builtin.os.tag == .windows` early return — the same idiom common.zig's terminalSize already uses — so the POSIX-only code is analysed out on Windows and the CLI compiles for every release target. `--tui` prints "not supported on Windows" there; batch render paths are unaffected. Also add engine CI (was docs-only): native build + `zig build test`, plus a cross-compile matrix over linux/windows amd64/arm64, so a target that fails to build is caught in the engine repo rather than only downstream at chartplotter release time. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 59 ++++++++++++++++++++++++++++++++++++++++ tools/ascii.zig | 4 +++ tools/explore.zig | 4 +++ 3 files changed, 67 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0007b10 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,59 @@ +name: CI + +on: + # push only on main; PR branches are covered by pull_request. Scoping push this + # way avoids the double run (a push to a branch with an open PR otherwise fires + # both events). + push: + branches: [main] + pull_request: + +# libtile57 (the static lib linked into chartplotter's CGO binary) and the tile57 +# CLI are built with Zig 0.16. The nested submodules carry the IHO S-101 catalogues +# that are embedded at build time, so checkout must be recursive. +# +# chartplotter cross-compiles its CGO binary against this engine with `zig cc` for +# linux + windows, amd64/arm64 (see chartplotter's release/xbuild). A default +# `zig build` builds BOTH libtile57.a and the `tile57` CLI exe, so the whole engine +# — not just the lib — has to compile for every one of those targets. The +# cross-compile matrix guards that here, in the engine repo, instead of only +# surfacing downstream when chartplotter tags a release. +jobs: + build-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + with: + submodules: recursive + - name: Install Zig + uses: mlugg/setup-zig@v2 + with: + version: 0.16.0 + - name: Build (native) + run: zig build -Doptimize=ReleaseFast + - name: Test + run: zig build test + + cross-compile: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + target: + - x86_64-linux-gnu + - aarch64-linux-gnu + - x86_64-windows-gnu + - aarch64-windows-gnu + steps: + - uses: actions/checkout@v7 + with: + submodules: recursive + - name: Install Zig + uses: mlugg/setup-zig@v2 + with: + version: 0.16.0 + # Builds libtile57.a + the tile57 CLI exe for the target. This is exactly + # what chartplotter's `xbuild` invokes per target before linking the Go + # binary, so a green matrix means the downstream cross-build will link. + - name: Cross-compile ${{ matrix.target }} + run: zig build -Dtarget=${{ matrix.target }} -Doptimize=ReleaseFast diff --git a/tools/ascii.zig b/tools/ascii.zig index 90c3d8a..f7a62ea 100644 --- a/tools/ascii.zig +++ b/tools/ascii.zig @@ -122,6 +122,10 @@ pub fn run(io: std.Io, a: std.mem.Allocator, args: []const [:0]const u8) !void { // carriage-returns), alternate screen + hidden cursor, terminal re-measured // every frame so a resize just repaints. fn runAsciiTui(io: std.Io, a: std.mem.Allocator, c: *chart.Chart, lon0: f64, lat0: f64, zoom0: f64, palette: render.resolve.PaletteId, m: *render.resolve.MarinerSettings, ansi: bool, kitty: bool) !void { + // The interactive TUI is POSIX-only: std.posix.termios is `void` on Windows, + // so gate the whole raw-mode body out at comptime (same idiom as common.zig's + // terminalSize). The non-interactive `ascii` render paths stay cross-platform. + if (@import("builtin").os.tag == .windows) return usageErr("--tui is not supported on Windows"); const stdout = std.Io.File.stdout(); const stdin_fd = std.Io.File.stdin().handle; const old = std.posix.tcgetattr(stdin_fd) catch return usageErr("--tui needs a terminal"); diff --git a/tools/explore.zig b/tools/explore.zig index f3d7da7..efbd621 100644 --- a/tools/explore.zig +++ b/tools/explore.zig @@ -1394,6 +1394,10 @@ fn exLoadCell( // transmit-once-per-view + place, deleted each frame — the same cached-region // pattern as the ascii kitty TUI, so it never scrolls the layout. fn exploreTui(io: std.Io, a: std.mem.Allocator, rows: []const ExIndexRow, cells: []const ExCellSrc, dir: std.Io.Dir, rules: []const u8, F: ExFilters, kitty: bool, palette: render.resolve.PaletteId, m: *const render.resolve.MarinerSettings, source: []const u8) !void { + // The interactive TUI is POSIX-only: std.posix.termios is `void` on Windows, + // so gate the whole raw-mode body out at comptime (same idiom as common.zig's + // terminalSize). The non-interactive `explore` paths stay cross-platform. + if (@import("builtin").os.tag == .windows) return usageErr("--tui is not supported on Windows"); const stdout = std.Io.File.stdout(); const stdin_fd = std.Io.File.stdin().handle; const old = std.posix.tcgetattr(stdin_fd) catch return usageErr("--tui needs a terminal");