diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e4d4c6666..7a70448e5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -530,6 +530,26 @@ jobs: # → the native cargo build. Same flags/profile either way. if [[ "${{ matrix.target }}" == *musl* ]]; then cargo zigbuild --locked --release --target ${{ matrix.target }} --workspace --bins + elif [[ "${{ matrix.target }}" == *windows* ]]; then + # Windows-ONLY size strip: rebuild std with panic=immediate-abort + + # size-optimized std, so a field panic is a bare, process-local + # abort() with no backtrace. The gimli/addr2line DWARF machinery is + # ~10% of the CLI and useless on a stripped binary; a panic is a + # should-never-happen bug (the workspace lints forbid unwrap/panic + # in prod), so dropping the diagnostic is the right trade for ship. + # Needs nightly + rust-src (both from rust-toolchain.toml). Linux and + # macOS deliberately stay on the plain release profile. Measured: + # uffs.exe 1,292,800 -> 1,167,872 (-9.7%). See [profile.ship] in + # Cargo.toml. + cargo build --locked --profile ship \ + -Z build-std=std,panic_abort \ + -Z build-std-features=optimize_for_size \ + --target ${{ matrix.target }} --workspace --bins + # The `ship` profile outputs to target//ship/, but every + # packaging step below reads target//release/ — mirror the + # built .exe files across so none of those paths need to change. + mkdir -p "target/${{ matrix.target }}/release" + cp "target/${{ matrix.target }}/ship/"*.exe "target/${{ matrix.target }}/release/" else cargo build --locked --release --target ${{ matrix.target }} --workspace --bins fi diff --git a/Cargo.toml b/Cargo.toml index 6a025942b..f493b9d5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,7 @@ +cargo-features = [ + "panic-immediate-abort", +] # ship profile only (needs -Z build-std) + # ============================================================================= # Cargo.toml - UFFS (Ultra Fast File Search) Workspace # ============================================================================= @@ -763,6 +767,34 @@ opt-level = 0 [profile.release.package.uffs-cli] opt-level = "z" +# ───────────────────────────────────────────────────────────────────────────── +# Ship profile — minimal panic (removes the field-useless backtrace machinery) +# ───────────────────────────────────────────────────────────────────────────── +# Field binaries are stripped, so a *symbolized* backtrace is dead weight — the +# `gimli`/`addr2line` DWARF machinery inside std is ~10% of the CLI. This profile +# rebuilds std with `panic = "immediate-abort"`, so a field panic is a bare, +# process-local `abort()` (no message, no backtrace) — which matches the +# workspace no-panic lint policy (panics are forbidden in prod anyway). Dev + CI +# keep normal panics + full backtraces. +# +# Built ONLY with build-std (needs nightly + the `rust-src` component): +# cargo [xwin] build --profile ship -Z build-std=std,panic_abort --target +# +# Measured (x86_64-pc-windows-msvc, uffs.exe): 1,292,800 → 1,167,872 (−9.7%). +# +# CAVEAT: `panic_immediate_abort` became a first-class panic strategy in recent +# nightlies (it was a `-Z build-std-features` flag before), so this is unstable +# and may need re-touching on a toolchain bump. Deliberately NOT wired into the +# default release — opt in from the ship build when ready to own that. +[profile.ship] +inherits = "release" +panic = "immediate-abort" + +# Per-package overrides do not inherit into a derived profile, so keep the CLI +# size-first here too. +[profile.ship.package.uffs-cli] +opt-level = "z" + # ───────────────────────────────────────────────────────────────────────────── # Cross-compile profile for cargo-xwin (macOS → Windows MSVC) # ─────────────────────────────────────────────────────────────────────────────