Skip to content

picolibc 与 compiler-rt-builtins —— C 库以源码包形态进入索引 - #336

Merged
Sunrisepeak merged 1 commit into
mainfrom
feat/picolibc-source-packages
Sep 4, 2026
Merged

picolibc 与 compiler-rt-builtins —— C 库以源码包形态进入索引#336
Sunrisepeak merged 1 commit into
mainfrom
feat/picolibc-source-packages

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

picolibc 1.8.12 and compiler-rt-builtins 22.1.8 — the C library, as source

⭐⭐ SOURCE PACKAGES, NOT A PREBUILT SYSROOT, AND THE MEASUREMENTS SAY WHY.

A prebuilt C library ships one build per ABI a target table can name — seven for
Cortex-M alone — and every consumer then finds the right one through a libdir
convention that must match the payload byte for byte. That convention is what
#481 was filed about, and on ARM it cannot work at all: the key
<march>/<mabi> does not separate the float ABI, because mabi there names the
procedure call standard and is aapcs either way.

Measured while building the prebuilt first: the seven profiles collapsed into
FIVE directories and the soft-float row received a library carrying
Tag_ABI_HardFP_use. Nothing failed at build time.

⚠️ And the headers were never per-profile. Across those seven builds the whole
include tree — picolibc.h and newlib.h, which meson GENERATES, included — is
byte-identical. The prebuilt shipped seven copies of one directory.

Compiled with the same compile_flags as the program consuming it, ABI
agreement holds by construction, and the version lands in mcpp.lock rather
than being pinned inside a target table.

What the source route cost instead

Four upstream partitions a flat library has to be told about, each found by a
link error rather than by reading:

  • libos/semihost and libos/dummyhost define the same syscalls and upstream
    keeps them in separate ARCHIVES, where link order decides. A feature here.
  • semihost/fake is the COMPLEMENT of semihost/common — 13 of 26 files — and
    the complement cannot be computed from filenames: fake_io.c collides with
    common/iob.c on stdin/stdout/stderr.
  • the machine directory carries variants for every ARM profile upstream serves;
    memcpy-armv7a.S needs ARM mode and Thumb-2, which no M-profile core has.
  • a negative glob in a base source set applies to the MERGED set, so
    !…/machine/** cancels the per-target block that adds the right one back.

And for the builtins, one more: upstream picks per CPU and the sets are nested —
25 files on armv6-m, 90 on armv8-m.main — so the list is the INTERSECTION, and
the routines it omits come from the generic C. An exclusion pattern was not
enough either: !builtins/arm/*vfp.S misses save_vfp_d8_d15_regs.S.

Measured

Both build for all seven M-profile rows. A printf("%.2f") program built
against them plus cortex-m-rt boots on QEMU's mps2-an385, prints 13.00 and
exits 0 — and the same source without the feature fails at 'stdio.h' file not found, which is the zero-libc tier behaving as documented.

Both tarballs verified against their bytes and re-fetched from the CN mirror,
byte-identical. Index lints pass.

…ource

⭐⭐ SOURCE PACKAGES, NOT A PREBUILT SYSROOT, AND THE MEASUREMENTS SAY WHY.

A prebuilt C library ships one build per ABI a target table can name — seven for
Cortex-M alone — and every consumer then finds the right one through a `libdir`
convention that must match the payload byte for byte. That convention is what
#481 was filed about, and on ARM it cannot work at all: the key
`<march>/<mabi>` does not separate the float ABI, because `mabi` there names the
procedure call standard and is `aapcs` either way.

Measured while building the prebuilt first: the seven profiles collapsed into
FIVE directories and the soft-float row received a library carrying
`Tag_ABI_HardFP_use`. Nothing failed at build time.

⚠️ And the headers were never per-profile. Across those seven builds the whole
include tree — `picolibc.h` and `newlib.h`, which meson GENERATES, included — is
byte-identical. The prebuilt shipped seven copies of one directory.

Compiled with the same `compile_flags` as the program consuming it, ABI
agreement holds by construction, and the version lands in `mcpp.lock` rather
than being pinned inside a target table.

## What the source route cost instead

Four upstream partitions a flat library has to be told about, each found by a
link error rather than by reading:

* `libos/semihost` and `libos/dummyhost` define the same syscalls and upstream
  keeps them in separate ARCHIVES, where link order decides. A feature here.
* `semihost/fake` is the COMPLEMENT of `semihost/common` — 13 of 26 files — and
  the complement cannot be computed from filenames: `fake_io.c` collides with
  `common/iob.c` on `stdin`/`stdout`/`stderr`.
* the machine directory carries variants for every ARM profile upstream serves;
  `memcpy-armv7a.S` needs ARM mode and Thumb-2, which no M-profile core has.
* a negative glob in a base source set applies to the MERGED set, so
  `!…/machine/**` cancels the per-target block that adds the right one back.

And for the builtins, one more: upstream picks per CPU and the sets are nested —
25 files on armv6-m, 90 on armv8-m.main — so the list is the INTERSECTION, and
the routines it omits come from the generic C. An exclusion pattern was not
enough either: `!builtins/arm/*vfp.S` misses `save_vfp_d8_d15_regs.S`.

## Measured

Both build for all seven M-profile rows. A `printf("%.2f")` program built
against them plus `cortex-m-rt` boots on QEMU's `mps2-an385`, prints `13.00` and
exits 0 — and the same source without the feature fails at `'stdio.h' file not
found`, which is the zero-libc tier behaving as documented.

Both tarballs verified against their bytes and re-fetched from the CN mirror,
byte-identical. Index lints pass.
@Sunrisepeak
Sunrisepeak merged commit f3df5f5 into main Sep 4, 2026
8 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.

1 participant