Files
SergioandClaude Opus 5 7e86459738 musl-shared: el corpus publica su propio CARGADOR — 23 binarios dejan de ser inertes
La imagen del perfil servidor traía 23 binarios de 726 que no podían ejecutarse:

    $ python3 -c "print(1)"
    sh: python3: not found        <- y `command -v python3` decía /usr/bin/python3

No faltaban: eran ELF dinámicos pidiendo `/lib/ld-musl-x86_64.so.1`, y **ningún artefacto del corpus
publicaba ese fichero**. Funcionaban en el hub sólo porque el rootfs Alpine del LAB lo presta — la
misma fuga que documentan `zlib-shared` y `expat-shared`, un piso más abajo, y peor: el lab no entra
en `hash_inputs`, así que la dependencia era invisible para el store.

Los 23 son la suite binutils entera + perl, python3, sqlite3, flex y nft. Entre ellos, TODO el
instrumental del proyecto, que es Python.

**Variante y no `--enable-shared` en la canónica**: `musl` es componente de Stage 1 y su `of_tree` es
el baseline de `selfhost-verify`. Re-hashearlo obliga a rehacer ese baseline a propósito, y eso es su
propia unidad de trabajo. Con el patrón `*-shared` (ya hay 23 en el corpus) la canónica no se mueve —
control: `takana hash recipes/musl.toml` sigue dando `b3:ce952f72…`, el mismo sellado de Stage 1. Y
además `musl` no es dep de NADIE (medido: sólo de sí misma; el enlace estático lo resuelve el musl de
zig), así que esto suma sin mover un solo ArtifactHash del corpus.

**⚠ `compiler = "gcc"` y no `zig-cc`, medido.** Con zig cc el `libc.so` sale con 1586 símbolos
dinámicos contra los 1654 de Alpine, y los 68 que faltan son EXACTAMENTE los que musl implementa en
ensamblador x86_64 (`memset memcpy memmove memcmp strlen` y toda la familia matemática) más los
`__stack_chk_*`. No es que no se compilen —en el `libc.a` canónico están—: zig los resuelve con su
propio musl y los deja `FUNC LOCAL HIDDEN` de tamaño 0, fuera de la tabla dinámica. El síntoma es un
cargador que arranca, reloca y muere con `memset: symbol not found`, que se lee como "el binario está
roto" y no como "a la libc le faltan símbolos". Con gcc: **1651 símbolos**, `memset` y `ceil`
presentes, y `python3 3.12.10` CORRE con el cargador del corpus.

De paso: el comentario de `musl.toml` decía que el artefacto aportaba «el loader, para uso dinámico
futuro». Era falso —`--disable-shared` no construye ninguno— y es justo la etiqueta que hizo que
nadie buscara el agujero. Corregido (los comentarios no entran en `hash_inputs`; verificado).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RomoxEGZUhaT4pob1QSX5x
2026-09-11 01:47:54 +00:00

36 lines
1.5 KiB
TOML

# musl libc 1.2.5 — libc del target para el userland mínimo del Stage 1 (SDD 11 §3).
#
# Se compila estática con `zig cc` cross al target. El artefacto aporta headers + libc.a + los
# `crt*.o`. Tarball release pinned por sha256: igual de fuerte que un commit git para
# reproducibilidad (ADR 0006).
#
# ⚠ ANTES ESTE COMENTARIO DECÍA «y el loader, para uso dinámico futuro». Era FALSO y costó caro: con
# `--disable-shared` musl NO construye `libc.so` ni `ld-musl-x86_64.so.1`, así que el corpus no
# publicaba ningún cargador dinámico y los 23 binarios dinámicos de una imagen quedaban INERTES
# (SDD 28 §6.4). El loader vive ahora en `recipes/musl-shared.toml`; esta receta sigue siendo
# estática pura, que es lo que Stage 1 necesita.
name = "musl"
version = "1.2.5"
license = "MIT"
[source]
tarball = "https://musl.libc.org/releases/musl-1.2.5.tar.gz"
sha256 = "a9a118bbe84d8764da0ea0d28b3ab3fae8477fc7e4085d90102b8596fc7c75e4"
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "static"
[deps]
build = ["make"]
[build.phases]
# El sandbox exporta CC="zig cc", DESTDIR=/out y PREFIX=/usr. musl trae su propio `configure`.
# Sólo estático: los componentes Rust se compilan crt-static + no-PIE (autocontenidos, ET_EXEC sin
# interpreter), así que el rootfs no necesita el loader/shared de musl. Ver runbooks §8.
configure = "./configure --prefix=/usr --disable-shared --enable-static"
compile = "make -j\"$(nproc)\""
install = "make install"