Skip to content

Make ci-job-clippy's board selection cover all archs, dynamically - #3

Draft
ppannuto-claude wants to merge 2 commits into
ppannuto:masterfrom
ppannuto-claude:prepush-arch-coverage
Draft

Make ci-job-clippy's board selection cover all archs, dynamically#3
ppannuto-claude wants to merge 2 commits into
ppannuto:masterfrom
ppannuto-claude:prepush-arch-coverage

Conversation

@ppannuto-claude

@ppannuto-claude ppannuto-claude commented Aug 27, 2026

Copy link
Copy Markdown

Pull Request Overview

ci-job-clippy's per-board list (nrf52840dk, raspberry_pi_pico, hifive1,
qemu_i486_q35) was a hand-picked, hand-maintained set meant to exercise
clippy against each arch/* crate's real target-specific code (workspace
clippy alone runs against the host target and never touches
cfg(target_arch = "...") code). It quietly missed several archs: nothing
covered cortexm7, cortexm33, or rv64i.

Replaces the static list with tools/build/list_arch_boards.sh, which
picks one deterministic (alphabetically-first) representative board per
arch/* crate actually in use. The set self-updates as boards/archs are
added, removed, or rewired, instead of silently drifting out of sync. New
board set: apollo3/lora_things_plus, arty_e21, cy8cproto_62_4343_w,
imxrt1050-evkb, lpc55s69-evk, qemu_i486_q35, qemu_rv64_virt.

An earlier version of this PR computed the board set via cargo metadata
(each board's full transitive dependency graph). Turned out to be
solving a problem the codebase doesn't have: every chip that depends on
an arch crate does so directly (verified against every chips/*/Cargo.toml),
so the script now does two plain, static lookups instead — a board's own
Cargo.toml and its chip's, both grepped for an .../arch/... path
dependency (a few boards, e.g. hail and the apollo3 boards, depend on
an arch crate directly and via their chip, so both are checked). Any
other arch crate one of those depends on in turn (e.g. cortexm4f on
cortexv7m on cortexm) is compiled — and so checked — as a side effect
of building it, without needing its own separate pick. The script now
lives in tools/build/ next to the sibling list_boards.sh/list_archs.sh/
list_chips.sh it mirrors, is plain bash (no cargo metadata, no
Python), and its name/comments say nothing about clippy — enumerating
boards per arch is all it does, and clippy is just one possible consumer.

Previously every board's clippy invocation unconditionally passed
-Zjson-target-spec, an unstable flag actually needed only by
qemu_i486_q35 (whose target is a bare JSON filename rather than a path).
Fixed at the source instead: qemu_i486_q35's own .cargo/config.toml
now sets [unstable] json-target-spec = true, the same persistent-config
mechanism ../cargo/riscv_flags.toml already uses for the RISC-V boards'
JSON specs (those are referenced by relative path instead, so didn't need
it spelled out explicitly). A plain cargo clippy/check/build now all
work with no -Z flag anywhere, so also dropped qemu_i486_q35's own
now-redundant CARGO = cargo -Zjson-target-spec Makefile override.

ci-job-clippy stays a single target that loops over the board list
(matching the existing style of ci-job-archs/ci-job-chips), rather than
being split into per-board sub-targets — that split is only useful for
make -j dispatch, which is #2's concern, not this PR's.

I looked for other Makefile lists with this same "static subset silently
standing in for full coverage" shape (per-arch/chip smoke-test lists,
QEMU/hardware test lists, etc.) and didn't find another instance worth
changing: everywhere else that needs "all boards/archs/chips" already
uses the existing tools/build/list_*.sh scripts, and the remaining
hand-picked single-board jobs (ci-job-msrv → hail,
ci-job-debug-support-targets → nrf52dk) are explicitly arbitrary
single-board smoke tests, not coverage claims.

Based directly on master; #2 (parallel prepush dispatch) is rebased on
top of this one, since it needs the dynamic board list here to generate
its per-board sub-targets from.

Testing Strategy

make prepush passes on a cold cache (make clean first), including a
full clippy run across the workspace + the 7 selected boards. make -C boards/qemu_i486_q35 still produces a working kernel .elf/.bin after
removing its CARGO override, confirming the persistent-config fix fully
replaces the per-invocation -Z flag for every build path (not just
clippy). Directly reproduced the old bare-filename-target error
(`.json` target specs require -Zjson-target-spec ) to confirm the
flag was genuinely needed before the config fix, and that a plain
../cargo/*.json relative-path target (what the RISC-V boards use)
doesn't need it, matching riscv_flags.toml's existing approach.

A cold-context review caught a real (if currently harmless) bug in
list_arch_boards.sh's regex: it required exact path = "..." spacing,
but chips/psoc62xa/Cargo.toml and chips/rp2040/Cargo.toml both write
path="..." with none, so their cortex-m0p dependency silently didn't
match. Only harmless today because every board using those chips also
redeclares the same arch crate directly in its own Cargo.toml — a
future cleanup removing that "redundant" direct dependency would
silently drop cortex-m0p from coverage with nothing to flag it.
Loosened the regex to tolerate any whitespace around =, verified
against both files. Also quoted $(CURDIR) in the Makefile's cd-back
(a checkout path with spaces would otherwise break it) and added a
missing tput sgr0 reset after each per-board banner's tput bold.

The same review suggested cross-checking the result against arch/'s
directory listing to catch this class of gap generally. Not done:
several arch crates (cortex-m3 among them) are legitimately unused by
any board today, so a blind diff would permanently false-flag those —
telling "unused" apart from "silently missed" again needs the full
dependency graph this script deliberately doesn't build.

TODO or Help Wanted

None.

Checklist

  • Ran make prepush.

PR Contents

Documentation

  • No documentation updates are required.

@ppannuto-claude
ppannuto-claude force-pushed the prepush-arch-coverage branch 3 times, most recently from 1507e44 to 89df5c2 Compare August 28, 2026 07:10
…et-spec

qemu_i486_q35's target is a bare JSON filename, not a path, which cargo
only resolves as a custom target spec (rather than requiring a builtin
triple name) via the unstable json-target-spec mechanism. Previously
this was passed as a `-Zjson-target-spec` CLI flag baked into the
board's own Makefile (`CARGO = cargo -Zjson-target-spec`), the only
board doing so.

Set it instead via `[unstable] json-target-spec = true` in the board's
own .cargo/config.toml -- the same persistent-config mechanism
../cargo/riscv_flags.toml already uses for the RISC-V boards' JSON
specs (those are referenced by relative path instead, so didn't need
it spelled out explicitly). That makes a plain `cargo
clippy`/`cargo check`/`cargo build` all work with no special-casing in
the board Makefile, so the now-redundant CARGO override is dropped.
Also removed a stale `[env] RUST_TARGET_PATH` + TODO comment that
predated the current include-based config layout.

Verified: a full `make -C boards/qemu_i486_q35` build still produces a
working kernel binary with the CARGO override removed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread tools/build/list_arch_boards.sh Outdated
Comment thread tools/build/list_arch_boards.sh Outdated
Comment thread tools/build/list_arch_boards.sh Outdated
Comment thread tools/build/list_arch_boards.sh
Comment on lines +45 to +53
for arch in $(./tools/build/list_archs.sh); do
# Not every arch/* crate has a board (e.g. cortex-m3, today) -- skip
# those rather than erroring, same as the old board-first version did.
for board in "${boards[@]}"; do
if board_depends_on_arch "$board" "$arch"; then
echo "$board"
break
fi
done

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is cortex-m3 the only unused arch in-tree right now? There are PRs pending that will use it, if so, we can drop this and we'll pend this PR until the PRs land that add a board that use cortex-m3

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed: cortex-m3 is the only arch crate with zero coverage, direct or transitive -- checked no board/chip depends on it and no other arch crate depends on it either (both a board and an arch crate must be absent for this to fire; cortex-v7m/cortex-m/cortex-m0/riscv all have zero direct board matches too, but each is a sibling dependency of some other arch crate a board does use, so they don't trip this). Didn't find an open PR or issue referencing it via gh pr/issue list --search, but that's not conclusive if it's not filed yet. Implemented the hard-fail: make ci-job-clippy now fails specifically and only on cortex-m3 (verified), so this'll go green again on its own once a board landing depends on it.

Comment thread Makefile Outdated
Comment thread Makefile Outdated
Comment thread Makefile Outdated
The hand-picked board list (nrf52840dk, raspberry_pi_pico, hifive1,
qemu_i486_q35) silently missed arch/* crates with no board maintaining
the list ever noticed: cortexm7, cortexm33, and rv64i had no clippy
coverage with a real target.

tools/build/list_arch_boards.sh picks one board per arch/* crate, so
the set self-updates as boards and archs are added or removed instead
of drifting stale. It iterates tools/build/list_archs.sh's small,
already-existing arch list on the outside and boards on the inside,
stopping at the first (alphabetically, since boards are sorted first)
match per arch -- rather than scanning every board regardless of
whether a match was already found. Every chip that depends on an arch
crate does so directly (one hop; verified against every
chips/*/Cargo.toml), and a few board crates also depend on an arch
crate directly alongside their chip (e.g. hail, the apollo3 boards) --
so for each candidate board, check both its own Cargo.toml and its
chip's for an arch/ path dependency.

An arch crate with no board using it directly is only an error if no
*other* arch crate depends on it either (checked with one more grep
over arch/*/Cargo.toml): e.g. cortex-v7m, cortex-m, cortex-m0, and
riscv all have zero boards depending on them directly today, but each
is a sibling dependency of some other arch crate that a board does use
directly (cortex-m4f -> cortex-v7m -> cortex-m, rv32i -> riscv, etc.),
so building that board compiles -- and so checks -- them too as a side
effect, with no separate pick needed. cortex-m3 is currently the only
arch crate genuinely unreachable either way; the script correctly
hard-fails on it (verified: `make ci-job-clippy` now fails specifically
and only on cortex-m3, everything else still resolves to the same 7
boards as before). This should self-resolve once a board using
cortex-m3 lands.

Results are collected into a variable and only printed after the full
loop succeeds, rather than printed as each arch resolves: a failure
partway through then leaves stdout completely empty instead of an
incomplete board list, which matters because a `$(shell ...)`-based
caller (as opposed to a direct invocation checked with `|| exit 1`)
can only observe empty-vs-nonempty output, not the exit status.

An earlier version used `cargo metadata` to compute each board's whole
transitive dependency graph, which turned out to be solving a problem
that doesn't exist here -- the codebase just doesn't have deep
chip->chip->arch chains that would need it.

A cold-context review caught a real bug in the regex: `path = "..."`
requires exact spacing around `=`, but two chips (psoc62xa, rp2040)
write `path="..."` with none, so their arch dependency silently didn't
match. Harmless today only by coincidence -- both boards using those
chips also happen to redeclare the same arch crate directly, so the
board-level lookup covered for it -- but a future cleanup removing
that "redundant" direct dependency would silently drop cortex-m0p from
clippy coverage with nothing to flag it. Loosened the regex to
tolerate any whitespace around `=`.

Verified: `make prepush` passes except for ci-job-clippy, which fails
specifically and only on the cortex-m3 gap described above; output for
every other arch is identical to the earlier board-first version's.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@ppannuto ppannuto left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that changes from the first commit in this series have been cherry-picked to master and should be dropped from this PR

Comment on lines +13 to +16
# Variants of another board (extra feature/policy configs, tutorial
# copies) are skipped, same as boards/README.md's own tooling, since
# they're not independent ports and would just be redundant picks.
# Sorted once so the loop below can stop at the first (alphabetical) match.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Variants of another board (extra feature/policy configs, tutorial
# copies) are skipped, same as boards/README.md's own tooling, since
# they're not independent ports and would just be redundant picks.
# Sorted once so the loop below can stop at the first (alphabetical) match.
# Just look at "real" boards. Alpha-sort for consistency in arbitrary choices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants