Skip to content

chore(ci): purge cargo-zigbuild, zig and cargo-xwin for soldr's blessed cross path - #1416

Merged
zackees merged 2 commits into
mainfrom
chore/purge-legacy-cross
Sep 4, 2026
Merged

chore(ci): purge cargo-zigbuild, zig and cargo-xwin for soldr's blessed cross path#1416
zackees merged 2 commits into
mainfrom
chore/purge-legacy-cross

Conversation

@zackees

@zackees zackees commented Sep 4, 2026

Copy link
Copy Markdown
Member

Retires every zig- and xwin-based cross-compilation wrapper in favour of soldr's blessed path (soldr prepare --target X + soldr build --target X), adds a lint and a hook so they cannot come back, and documents the traps that cost real time getting here.

Why

soldr's prepare --help states the contract: it "installs the Rust standard library, selects and materializes the blessed compiler/linker plus SDK or sysroot, and exports the target-scoped environment. Legacy backend wrappers are diagnostic-only overrides and are never selected by this command."

Carrying the wrappers anyway was pure liability, proven twice in one day:

  • cargo-zigbuild was pip-installed unpinned and floated 0.23.1 → 0.23.4 mid-release, breaking both apple-darwin lanes of 2.5.22 with unable to read exported symbols list '-dead_strip': FileNotFound.
  • cargo-xwin required ~40 lines of CRT-casing symlink repair in the workflow to satisfy MSVC import libraries on a case-sensitive filesystem.

Verified before changing anything

target result
aarch64-apple-darwin soldr build → real Mach-O arm64 binary
x86_64-pc-windows-msvc soldr build → 41 MB fbuild.exe, no xwin shims
x86_64-unknown-linux-gnu (PyO3 cdylib) max symbol GLIBC_2.16

Both mac and windows lanes are green in CI on this branch (run 33815922498).

That last row is the one that matters for wheels: soldr's catalogue sysroot holds the manylinux_2_17 floor by itself, and holds it lower than the cargo zigbuild --target ...-gnu.2.17 lane it replaces (2.17).

The trap, now documented

Do not port zigbuild's .2.17 suffix onto a soldr target. soldr has no such target, logs the miss as a warning, falls back to the bare host toolchain and still exits 0 — yielding a GLIBC_2.39 .so tagged manylinux_2_17, which installs fine and fails at import on anything older than the build host. Filed upstream as zackees/soldr#3082.

Upstream work this depended on

The musl lanes needed three soldr fixes, all filed, fixed and merged:

setup-soldr is pinned to 0.9.12, the first release carrying them.

Changes

  • template_native_build.yml: four per-target build branches collapse to one soldr prepare + soldr build. Deleted the cargo-xwin install, the xwin system-deps step (clang/lld/llvm + the clang-cl symlink), the CRT-casing repair block, and the pip install.
  • ci/check_no_legacy_cross.py + ci/test_no_legacy_cross.py: the gate, wired into ci-workflow-drift.yml. Scans runnable lines only so comments keep the history; one-line lint-allow: legacy-cross pragma for a genuine exception.
  • ci/hooks/tool_guard.py: real-time half — blocks the retired commands in Bash, including soldr cargo zigbuild.
  • agents/docs/cross-compilation.md: the blessed path, the measured glibc floors, the suffix trap. Wired into the root routing table.
  • Cargo.toml: [workspace.metadata.soldr] targets so --target all resolves.
  • ci/docker-mac-cross/: migrated to soldr build; the image installs no cross toolchain of its own.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CfdhKY6DmrRJ6mzSTzLU58

zackees and others added 2 commits September 3, 2026 16:03
…ed path

soldr's `soldr prepare --target X` + `soldr build --target X` selects and
materializes the compiler, linker and SDK/sysroot for every triple we
ship. Its own `prepare --help` says the wrappers "are diagnostic-only
overrides and are never selected by this command", so carrying them was
pure liability — proven twice today:

  * cargo-zigbuild was pip-installed UNPINNED and floated 0.23.1 -> 0.23.4
    mid-release, breaking both apple-darwin lanes of 2.5.22 with
    `unable to read exported symbols list '-dead_strip': FileNotFound`.
  * cargo-xwin needed ~40 lines of CRT-casing symlink repair in the
    workflow to satisfy MSVC import libraries on a case-sensitive
    filesystem.

Verified locally on Linux before changing the template:

  aarch64-apple-darwin      soldr build -> Mach-O arm64 binary, 3m22s
  x86_64-pc-windows-msvc    soldr build -> 41MB fbuild.exe, no xwin shims
  x86_64-unknown-linux-gnu  PyO3 cdylib -> max symbol GLIBC_2.16

That last line is the one that matters for wheels: soldr's catalogue
sysroot holds the manylinux_2_17 floor by itself, and holds it lower than
the `cargo zigbuild --target ...-gnu.2.17` lane it replaces (2.17).

Do NOT port zigbuild's `.2.17` suffix onto a soldr target. soldr has no
such target, logs the miss as a warning, falls back to the bare host
toolchain and still exits 0 — yielding a GLIBC_2.39 .so tagged
manylinux_2_17, which installs fine and fails at import on anything older
than the build host. Filed as zackees/soldr#3082.

Changes:
  * template_native_build.yml: four per-target build branches collapse to
    one `soldr prepare` + `soldr build`; the cargo-xwin install, the xwin
    system-deps step (clang/lld/llvm + clang-cl symlink), the CRT-casing
    repair and the pip install all deleted.
  * ci/check_no_legacy_cross.py + tests: the gate, wired into
    ci-workflow-drift.yml. Scans runnable lines only, so comments can keep
    the history; one-line `lint-allow: legacy-cross` pragma for the rare
    genuine case.
  * ci/hooks/tool_guard.py: real-time half — blocks the retired commands
    in Bash, including `soldr cargo zigbuild`.
  * agents/docs/cross-compilation.md: the blessed path, the measured
    glibc floors, and the suffix trap. Wired into the routing table.
  * Cargo.toml: `[workspace.metadata.soldr] targets` so `--target all`
    resolves.
  * ci/docker-mac-cross: migrated to `soldr build`; the image installs no
    cross toolchain of its own.

musl is not yet green through soldr — `-lbz2` fails on a malformed `-L`
(zackees/soldr#3081, fix in flight). This branch does not release until
that lands and all six lanes are proven in CI.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CfdhKY6DmrRJ6mzSTzLU58
0.9.12 is the first soldr release carrying zackees/soldr#3083. Before it,
soldr exported PKG_CONFIG_SYSROOT_DIR for its managed musl/GNU Linux
bundles, and pkg-config prefixed that onto every absolute -L it emitted,
so a managed syslib resolved to sysroot+absolute -- a directory that does
not exist. Our musl lanes died with `ld: cannot find -lbz2`, which is the
last thing blocking the zigbuild purge on Linux.

The GNU lane was masked by ubuntu-24.04 happening to carry
/usr/lib/libbz2.so; the fix removes that accident, and the measured glibc
floor stays at 2.16 (CI guard ceiling 2.17).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CfdhKY6DmrRJ6mzSTzLU58
@zackees
zackees merged commit e4a871a into main Sep 4, 2026
16 of 18 checks passed
@zackees
zackees deleted the chore/purge-legacy-cross branch September 4, 2026 02:21
@fastled-project-sync fastled-project-sync Bot moved this to Triage in FastLED Tracker Sep 4, 2026
zackees added a commit that referenced this pull request Sep 6, 2026
`native_release_workflow_uses_current_cross_toolchains` asserts the exact
soldr version `template_native_build.yml` pins. #1416 (e4a871a) moved that
pin 0.9.6 -> 0.9.12 for the pkg-config sysroot fix, but left the test's
expected value at 0.9.6, so `Check` has been red on main ever since:

    assertion `left == right` failed: the setup-soldr step needs soldr
    >= 0.9.5 for catalogue-v2 Apple SDK assets
      left: Some("0.9.12")
     right: Some("0.9.6")

That blocks every open PR, not just the branch that noticed it.

Follow the pin, and extend the message to name the second floor as well --
it previously cited only the 0.9.5 catalogue-v2 requirement, which no longer
explains why the pin sits where it does.


Claude-Session: https://claude.ai/code/session_01MLhWkMfzLjrnLTDMBE6Fj9

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
zackees added a commit that referenced this pull request Sep 6, 2026
Ships the SAMD core fix from #1418 (closes #1400).

`samd-core` was fetched from GitHub's auto-generated source archive, which
omits submodules by design. Tag 1.7.16 declares two under `libraries/`:
`Adafruit_TinyUSB_Arduino` and `Adafruit_ZeroDMA`. That was latent until
#1401 added the unpack-time submodule check, which fires on the package
rather than on use -- so every SAMD build began failing before a compiler
ran, taking out metro_m4, samd21, samd21_zero, samd51j and samd51p
downstream in FastLED as soon as it pinned 2.5.22.

The core now comes from Adafruit's board-index bundle, which does carry the
submodule contents (368 files under Adafruit_TinyUSB_Arduino/ including
tusb.h, 25 under Adafruit_ZeroDMA/), with its SHA-256 pinned and verified --
the old URL passed no checksum at all.

Verified end to end: `fbuild build tests/platform/samd21 -e samd21` succeeds
(flash 11420 bytes, ram 3828 bytes).

Also carries #1419, which follows the soldr pin #1416 moved to 0.9.12 and
had left `Check` red on main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MLhWkMfzLjrnLTDMBE6Fj9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

1 participant