diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..5f1ba45 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,17 @@ +# Windows cross-link fix for the D1 release matrix (cargo-zigbuild). +# +# Rust's std links `-lsynchronization` on Windows (WaitOnAddress-based thread +# parking). Rust normally satisfies this from the `self-contained` mingw libs +# of its `rust-mingw` component — which rust-overlay does NOT ship — and Zig's +# bundled mingw (used by `cargo zigbuild`) doesn't provide `libsynchronization.a` +# either. The actual symbols are *forwarded by kernel32* (already linked), so an +# empty stub import lib is enough to satisfy the linker. See `ci/winstub/`. +# +# These sections apply ONLY when building for the Windows targets, so host +# builds (the gate's `cargo test`/`clippy`) and the Linux release targets are +# unaffected. +[target.x86_64-pc-windows-gnu] +rustflags = ["-L", "native=ci/winstub"] + +[target.aarch64-pc-windows-gnullvm] +rustflags = ["-L", "native=ci/winstub"] diff --git a/ci/winstub/README.md b/ci/winstub/README.md new file mode 100644 index 0000000..ad05111 --- /dev/null +++ b/ci/winstub/README.md @@ -0,0 +1,30 @@ +# `ci/winstub/` — empty Windows import-lib stub + +`libsynchronization.a` here is an **empty `ar` archive** (8 bytes: `!\n`), +referenced by `.cargo/config.toml` via `-L native=ci/winstub` for the Windows +release targets. + +## Why + +The D1 release matrix cross-compiles Windows binaries from Linux with +`cargo zigbuild` (see `docs/ci/adr/`). Rust's `std` links `-lsynchronization` +for its `WaitOnAddress`-based thread parking. That import library is normally +provided by Rust's `rust-mingw` "self-contained" component — which `rust-overlay` +does not ship — and Zig's bundled mingw doesn't carry it either, so the link +fails with: + +``` +error: unable to find dynamic system library 'synchronization' +``` + +The functions it would import (`WaitOnAddress`, `WakeByAddressSingle`, +`WakeByAddressAll`) are **forwarded by `kernel32.dll`**, which is already linked, +so they resolve at link and run time without a real `synchronization` import +library. An **empty** stub is therefore sufficient: it satisfies the `-l` +lookup and contributes no symbols. + +## Regenerating + +``` +zig ar rcs ci/winstub/libsynchronization.a +``` diff --git a/ci/winstub/libsynchronization.a b/ci/winstub/libsynchronization.a new file mode 100644 index 0000000..8b277f0 --- /dev/null +++ b/ci/winstub/libsynchronization.a @@ -0,0 +1 @@ +! diff --git a/flake.nix b/flake.nix index 77e74d3..6407308 100644 --- a/flake.nix +++ b/flake.nix @@ -27,13 +27,6 @@ # from the crate metadata (no hand-maintained duplicate here). cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); - # musl-targeting C compiler for the static release build: rusqlite's - # `bundled` SQLite is compiled from C, so a `--target …-musl` cargo build - # needs a musl `cc` for that C, plus a musl linker. `targetPrefix` is - # "x86_64-unknown-linux-musl-", so the wrapped binary is - # `${muslCC}/bin/x86_64-unknown-linux-musl-cc`. - muslCC = pkgs.pkgsCross.musl64.stdenv.cc; - # System build inputs are deliberately tiny — this is a pure-Rust TUI: # * libsqlite3-sys is built with the `bundled` feature, so SQLite is # compiled from vendored C. That needs a C compiler, which the @@ -75,20 +68,21 @@ # CLAUDE.md "Build hygiene"). cargo-sweep prunes them; run it # periodically between milestones. pkgs.cargo-sweep - # musl cc/linker for the static release build (see muslCC above). - muslCC + # Cross-compilation for the D1 release matrix. `cargo zigbuild` uses + # Zig's bundled clang + libc as one universal cross cc/linker for + # every non-macOS target (Linux musl x64/arm64, Windows gnu/gnullvm + # x64/arm64) — including the `cc`-crate compile of rusqlite's bundled + # SQLite C — with no per-target toolchain or SDK. It auto-discovers + # `zig` on PATH, so no extra env is needed. + pkgs.cargo-zigbuild + pkgs.zig ]; - # Point cargo's musl target at the musl cc for both the bundled-C - # compile (CC_, consumed by the `cc` crate) and the final link - # (CARGO_TARGET__LINKER). Harmless for normal glibc builds — - # these only take effect when building `--target x86_64-…-musl`. shellHook = '' - export CC_x86_64_unknown_linux_musl="${muslCC}/bin/${muslCC.targetPrefix}cc" - export CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER="${muslCC}/bin/${muslCC.targetPrefix}cc" echo "RDBMS Playground dev shell ($(uname -s))" - echo " rust: $(rustc --version | cut -d' ' -f1-2)" - echo " cargo: $(cargo --version | cut -d' ' -f1-2)" + echo " rust: $(rustc --version | cut -d' ' -f1-2)" + echo " cargo: $(cargo --version | cut -d' ' -f1-2)" + echo " zig: $(zig version 2>/dev/null || echo '?') (cargo-zigbuild cross targets)" ''; }; }); diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 68cd111..64a9490 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -7,9 +7,15 @@ channel = "1.95.0" # rustfmt + clippy back the `fmt`/`clippy` CI stages; no coverage or WASM # tooling is needed here (pure-Rust TUI). components = ["rustfmt", "clippy"] -# x86_64 musl for the static release binary (D2: single static binary, no -# runtime deps). The glibc default links the host/nix-store glibc dynamically -# and isn't portable; the musl target with crt-static produces a fully static -# binary. Further D1 matrix targets (aarch64, windows-gnu, …) are added as the -# release matrix expands, step by step. -targets = ["x86_64-unknown-linux-musl"] +# The non-macOS D1 release matrix, all cross-built from Linux x86_64 via +# `cargo zigbuild` (D1: cross-platform binaries; D2: single static binary). +# Linux uses musl + crt-static for fully static, portable binaries; Windows +# uses the gnu/gnullvm ABIs (Zig statically links libc, so the .exe is +# standalone). macOS is deferred — its arboard/AppKit link needs Apple's SDK, +# which a Linux runner can't supply cleanly (see docs/ci/adr ADR-ci-001). +targets = [ + "x86_64-unknown-linux-musl", + "aarch64-unknown-linux-musl", + "x86_64-pc-windows-gnu", + "aarch64-pc-windows-gnullvm", +]