End-user perspective vs. infra cost · prepared 2026-05-18
gh run download against the latest CI run is usually faster than re-running locally.
Regardless of build method, the user runs bunx fbi-proxy which downloads the right
binary for their host. The interesting question is: does the binary just work?
| Concern | Native-on-CI (current) | cargo-zigbuild |
cross |
|---|---|---|---|
| All 6 targets shipped | Yes | Yes | No — macOS missing1 |
| Linux glibc compatibility floor | ubuntu-latest libc (~2.39, May 2026) | Pick any glibc version explicitly--target x86_64-unknown-linux-gnu.2.17 |
Image-dependent (~2.31 by default) |
| macOS minimum version | macos-latest SDK (macOS 14+) | Configurable via MACOSX_DEPLOYMENT_TARGET |
N/A |
| Windows MSVC subtleties | Native MSVC — zero surprises | MinGW-style, not MSVC | MinGW-style, not MSVC |
| Binary signing path | Can codesign in CI (Apple/Windows) | Local — manual signing | Local — manual signing |
| Trust signal (provenance) | Built on GitHub-hosted runners; SLSA-friendly | Built on your machine | Built on your machine |
1 Apple's macOS SDK isn't redistributable, so Docker-based cross can't legally ship
a macOS toolchain. cargo-zigbuild sidesteps this with Zig's Mach-O linker but you
still need the macOS SDK headers on disk.
| Cost | Native-on-CI (current) | cargo-zigbuild local |
cross local |
|---|---|---|---|
| Wall-clock per build (6 targets) | ~5 min (parallel matrix) | ~3-6 min (sequential, one host) | ~6-10 min (Docker pull then build) |
| First-run setup | $0 — already configured | cargo install cargo-zigbuild+ brew install zig or pip install ziglang (~50MB) |
cargo install cross+ Docker images (500MB-1GB total) |
| Per-build runner $ (private repo)2 | ~$1.04 (2× Linux + 2× Windows 2× + 2× macOS 10×) | $0 (local) | $0 (local) |
| Per-build runner $ (public repo — this repo) | $0 — unlimited minutes | $0 | $0 |
| Iteration loop (incremental edit → binary) | 5 min push → wait → download | ~30s incremental | ~1-2 min (Docker overhead) |
| Maintenance — toolchain drift | GitHub-managed runners auto-update | Zig releases ~monthly; pin via lockfile | Docker images updated upstream |
| Disk footprint | $0 local | ~150 MB | ~1.5 GB |
2 Rough estimate using GitHub's per-minute pricing (May 2026): Linux $0.008/min, Windows $0.016/min, macOS $0.08/min × ~5 min each.
Public repo · cuts no corners · provenance + signing path · zero local toolchain. The
only downside is iteration time, and gh run download <run-id> closes that
gap to one command.
cargo-zigbuild if…You want to test a specific non-host target quickly without pushing to main — e.g., debugging a macOS-only segfault from a Linux dev box, or producing a glibc-2.17-compatible Linux binary for legacy servers. Only setup that lets a Linux host produce macOS binaries.
cross if…You want a clean Docker-per-target sandbox, you don't need macOS locally, and you prefer
one tool that handles linux+windows. Roughly equivalent in capability to direct
cargo build --target=X with system toolchains installed, but no host-pollution.
You move this repo to a private org and macOS minutes start showing up on the invoice.
At that point, build linux + windows with cargo-zigbuild on a single Linux
runner (saves ~75%), and keep one macOS runner for the two Apple targets. Don't optimize
this prematurely.
gh run download — the no-install pathgh run list --workflow="Build and Release" --branch=main --limit=1 --json databaseId -q '.[0].databaseId' \
| xargs -I{} gh run download {} --dir ./release
Drops all 6 binaries into release/. ~2 seconds of your time, zero local toolchain.
cargo-zigbuild — one-time setup# Install
cargo install cargo-zigbuild
pip install ziglang # or: brew install zig
# Add targets
rustup target add aarch64-unknown-linux-gnu
rustup target add x86_64-apple-darwin aarch64-apple-darwin
rustup target add x86_64-pc-windows-gnu
# Build (any target, no extra config)
cargo zigbuild --release --target aarch64-apple-darwin
cargo zigbuild --release --target x86_64-unknown-linux-gnu.2.17 # pin glibc
cross — one-time setup# Install (Docker must be running)
cargo install cross --git https://github.com/cross-rs/cross
# Build
cross build --release --target aarch64-unknown-linux-gnu
cross build --release --target x86_64-pc-windows-gnu
ubuntu-latest require the runner's current glibc on user machines.
If users on older distros report "GLIBC_2.X not found", switch the Linux x64 job
to cargo-zigbuild with a pinned floor (e.g. .2.17 matches
CentOS 7 / RHEL 7).cross/zigbuild is less
battle-tested.Don't change anything. Add this two-liner to package.json scripts so
"download the latest CI build for my host" is one keystroke:
"scripts": {
"dl-artifacts": "gh run list --workflow='Build and Release' --branch=main --limit=1 --json databaseId -q '.[0].databaseId' | xargs -I{} gh run download {} --dir release"
}
Revisit if (a) the repo goes private, (b) users hit glibc-floor issues, or (c) you want sub-minute iteration on a target you don't run natively.