build: D1 cross-compile via cargo-zigbuild (4 non-macOS targets)
Replace the single-target musl cc with cargo-zigbuild + zig in the flake devShell — one universal cross cc/linker (incl. rusqlite's bundled SQLite C) for all four non-macOS D1 targets, added to rust-toolchain.toml: x86_64/aarch64-unknown-linux-musl (static, D2) x86_64-pc-windows-gnu, aarch64-pc-windows-gnullvm (standalone .exe) Windows links -lsynchronization (std WaitOnAddress), which rust-overlay's toolchain and zig's mingw don't ship; the symbols are forwarded by kernel32, so an empty stub libsynchronization.a (ci/winstub/, wired via .cargo/config.toml for the windows targets only) satisfies the linker. Verified: all four build; linux static; windows valid PE32+.
This commit is contained in:
@@ -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"]
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# `ci/winstub/` — empty Windows import-lib stub
|
||||||
|
|
||||||
|
`libsynchronization.a` here is an **empty `ar` archive** (8 bytes: `!<arch>\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
|
||||||
|
```
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!<arch>
|
||||||
@@ -27,13 +27,6 @@
|
|||||||
# from the crate metadata (no hand-maintained duplicate here).
|
# from the crate metadata (no hand-maintained duplicate here).
|
||||||
cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml);
|
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:
|
# System build inputs are deliberately tiny — this is a pure-Rust TUI:
|
||||||
# * libsqlite3-sys is built with the `bundled` feature, so SQLite is
|
# * libsqlite3-sys is built with the `bundled` feature, so SQLite is
|
||||||
# compiled from vendored C. That needs a C compiler, which the
|
# 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
|
# CLAUDE.md "Build hygiene"). cargo-sweep prunes them; run it
|
||||||
# periodically between milestones.
|
# periodically between milestones.
|
||||||
pkgs.cargo-sweep
|
pkgs.cargo-sweep
|
||||||
# musl cc/linker for the static release build (see muslCC above).
|
# Cross-compilation for the D1 release matrix. `cargo zigbuild` uses
|
||||||
muslCC
|
# 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_<target>, consumed by the `cc` crate) and the final link
|
|
||||||
# (CARGO_TARGET_<TARGET>_LINKER). Harmless for normal glibc builds —
|
|
||||||
# these only take effect when building `--target x86_64-…-musl`.
|
|
||||||
shellHook = ''
|
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 "RDBMS Playground dev shell ($(uname -s))"
|
||||||
echo " rust: $(rustc --version | cut -d' ' -f1-2)"
|
echo " rust: $(rustc --version | cut -d' ' -f1-2)"
|
||||||
echo " cargo: $(cargo --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)"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
+12
-6
@@ -7,9 +7,15 @@ channel = "1.95.0"
|
|||||||
# rustfmt + clippy back the `fmt`/`clippy` CI stages; no coverage or WASM
|
# rustfmt + clippy back the `fmt`/`clippy` CI stages; no coverage or WASM
|
||||||
# tooling is needed here (pure-Rust TUI).
|
# tooling is needed here (pure-Rust TUI).
|
||||||
components = ["rustfmt", "clippy"]
|
components = ["rustfmt", "clippy"]
|
||||||
# x86_64 musl for the static release binary (D2: single static binary, no
|
# The non-macOS D1 release matrix, all cross-built from Linux x86_64 via
|
||||||
# runtime deps). The glibc default links the host/nix-store glibc dynamically
|
# `cargo zigbuild` (D1: cross-platform binaries; D2: single static binary).
|
||||||
# and isn't portable; the musl target with crt-static produces a fully static
|
# Linux uses musl + crt-static for fully static, portable binaries; Windows
|
||||||
# binary. Further D1 matrix targets (aarch64, windows-gnu, …) are added as the
|
# uses the gnu/gnullvm ABIs (Zig statically links libc, so the .exe is
|
||||||
# release matrix expands, step by step.
|
# standalone). macOS is deferred — its arboard/AppKit link needs Apple's SDK,
|
||||||
targets = ["x86_64-unknown-linux-musl"]
|
# 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",
|
||||||
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user