Skip to content

feat(target): Cortex-M 的 C 库,以及那把多库的键为什么是三元组 - #553

Merged
Sunrisepeak merged 2 commits into
mainfrom
feat/picolibc-arm-libdir
Sep 4, 2026
Merged

feat(target): Cortex-M 的 C 库,以及那把多库的键为什么是三元组#553
Sunrisepeak merged 2 commits into
mainfrom
feat/picolibc-arm-libdir

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

feat(target): Cortex-M gets a C library, and its multilib key is the TRIPLE

xim:picolibc-arm@1.8.12 carries seven multilibs — picolibc plus the
compiler-rt builtins that link it, built together by one LLVM. A project opts in
with one line:

[target.thumbv7m-none-eabi]
sysroot = "xim:picolibc-arm@1.8.12"

and libdir is what makes that line find anything.

⚠️⚠️ The column is the TRIPLE here, not <march>/<mabi>

libdir names the sub-directory a multilib C library uses. On riscv,
<march>/<mabi> separates every profile because mabi there IS the float ABI —
lp64d and lp64 are different values. On ARM mabi names the PROCEDURE CALL
STANDARD and is aapcs for both variants, while the float ABI lives in the
triple's eabi/eabihf suffix. So armv7e-m/aapcs would name ONE directory
for two incompatible libraries.

Measured while building the payload: under the sibling convention the seven
M-profile profiles collapsed into FIVE directories, and armv7e-m/aapcs/libc.a
came out carrying Tag_ABI_HardFP_use and FP_arch: VFPv4-D16 — the hard-float
build, sitting exactly where a soft-float program would find it. Nothing failed
at build time.

The two ARMv7-A rows are filled for the same reason even though no package
carries an A-profile multilib yet: the column is a CONVENTION about where a
sysroot puts a profile, not a claim that one exists, and leaving it empty would
leave the next payload free to choose the arrangement that just failed.

⭐ Filling it does NOT give these rows a C library by default. The column is read
only once a sysroot has been resolved, and the target table still binds none:
the zero-libc tier stays the default and the manifest line is the opt-in.

The criteria are the ABI and the size, not the link

  • A unit test quantifies over every 32-bit ARM row and asserts that the soft and
    hard variants of ONE architecture name DIFFERENT directories — with a
    denominator, so the check cannot quietly range over nothing.
  • tests/e2e/338 builds the SOFT-float row and asserts the image declares no
    hard-float ABI tag, then runs it and reads $?.
  • ⚠️ And it asserts the artefact is not EMPTY. Measured while writing it: with
    the board's crt0 selection missing, the link SUCCEEDED and mcpp reported
    Size fw text 0 data 0 — a well-formed ELF containing nothing. Every check
    that looked only for "Finished" would have passed.

338 skips until the payload is published, and CI demands that it either passed
or said why — which is what distinguishes a skip from a silent zero exit.

97/97 unit; e2e 130-131, 332, 336, 338 green.

…TRIPLE

`xim:picolibc-arm@1.8.12` carries seven multilibs — picolibc plus the
compiler-rt builtins that link it, built together by one LLVM. A project opts in
with one line:

    [target.thumbv7m-none-eabi]
    sysroot = "xim:picolibc-arm@1.8.12"

and `libdir` is what makes that line find anything.

## ⚠️⚠️ The column is the TRIPLE here, not `<march>/<mabi>`

`libdir` names the sub-directory a multilib C library uses. On riscv,
`<march>/<mabi>` separates every profile because `mabi` there IS the float ABI —
`lp64d` and `lp64` are different values. On ARM `mabi` names the PROCEDURE CALL
STANDARD and is `aapcs` for both variants, while the float ABI lives in the
triple's `eabi`/`eabihf` suffix. So `armv7e-m/aapcs` would name ONE directory
for two incompatible libraries.

Measured while building the payload: under the sibling convention the seven
M-profile profiles collapsed into FIVE directories, and `armv7e-m/aapcs/libc.a`
came out carrying `Tag_ABI_HardFP_use` and `FP_arch: VFPv4-D16` — the hard-float
build, sitting exactly where a soft-float program would find it. Nothing failed
at build time.

The two ARMv7-A rows are filled for the same reason even though no package
carries an A-profile multilib yet: the column is a CONVENTION about where a
sysroot puts a profile, not a claim that one exists, and leaving it empty would
leave the next payload free to choose the arrangement that just failed.

⭐ Filling it does NOT give these rows a C library by default. The column is read
only once a sysroot has been resolved, and the target table still binds none:
the zero-libc tier stays the default and the manifest line is the opt-in.

## The criteria are the ABI and the size, not the link

* A unit test quantifies over every 32-bit ARM row and asserts that the soft and
  hard variants of ONE architecture name DIFFERENT directories — with a
  denominator, so the check cannot quietly range over nothing.
* `tests/e2e/338` builds the SOFT-float row and asserts the image declares no
  hard-float ABI tag, then runs it and reads `$?`.
* ⚠️ And it asserts the artefact is not EMPTY. Measured while writing it: with
  the board's crt0 selection missing, the link SUCCEEDED and mcpp reported
  `Size fw  text 0  data 0` — a well-formed ELF containing nothing. Every check
  that looked only for "Finished" would have passed.

338 skips until the payload is published, and CI demands that it either passed
or said why — which is what distinguishes a skip from a silent zero exit.

97/97 unit; e2e 130-131, 332, 336, 338 green.
…ind returns first

⚠️⚠️ IT PASSED LOCALLY AND FAILED ON CI, WHICH IS THE SIGNATURE OF AN ASSERTION
THAT DEPENDS ON SOMETHING NOBODY CHOSE.

The block ran `find target -name featrun | head -1`. By then two output
directories exist — one per feature set — and which one `find` walks first is
filesystem order.

What the fix actually changed is the cache ENTRY: it records the feature set its
artefacts were built with, and both fast paths compare it. Entries are written
most-recently-used first, so the first `features=` line belongs to the build
that just ran. Reading it is exact and order-free.

Measured on the same project: plain -> '', --features loud -> 'loud',
plain again -> '' — the third being the reading that was 'loud' before the fix.
@Sunrisepeak
Sunrisepeak merged commit feeb611 into main Sep 4, 2026
36 checks passed
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