diff --git a/docs/state/targets.toml b/docs/state/targets.toml index 2253dfcc..da0d71a1 100644 --- a/docs/state/targets.toml +++ b/docs/state/targets.toml @@ -1352,13 +1352,23 @@ paquetes = [ # Su config (el `squid.conf`, el `passwd` y las dos ACL) es dato del SITIO y viaja con la mudanza, # no con el paquete: el servicio arranca sólo si está, y si no sale 78 diciéndolo. "squid", - # `rust-toolchain-bin` (2026-09-14): el compilador de Rust. Va en `servidor` y NO en `base` por - # tamaño —799 M— y porque una imagen de escritorio no compila nada; la caja que sirve el repo y - # construye sí. Es el paso 1 de tres: prebuilt ajeno (`foreign`) para desbloquear hoy; luego rustc - # desde fuente con el `llvm18` ya sellado; luego la cadena mrustc del selfhost. Sin compilador de - # Rust, la distro depende del LAB —un rootfs ajeno que ENTRA en el ArtifactHash— para poder - # reconstruir su propio instrumental, que son 12 crates y 42 555 líneas. - "rust-toolchain-bin", + # ── EL COMPILADOR DE RUST, QUE DESDE HOY ES NUESTRO (2026-09-16, SDD 31) ───────────────────── + # Acá vivía `rust-toolchain-bin`: el tarball oficial de rust-lang, 799 M de bytes AJENOS sellados + # tal cual (`foreign`). Era el escalón 1 —desbloquear hoy— y cumplió: con él se construyó el + # escalón 2, y el escalón 2 ya compila, enlaza y corre. Sale del perfil. + # + # Los tres que entran son el mismo hecho —«esta caja compila Rust»— partido en tres piezas: + # · `rust` el compilador y cargo, construidos por la granja desde fuente (353 M). + # · `lld21` el enlazador. NO es opcional: una caja takana **no tiene `cc`**, y sin + # enlazador `rustc` compila objetos y no produce un ejecutable. + # · `cargo-config` las tres flags que unen a los dos (`/etc/cargo/config.toml`). Sin ellas, + # `cargo build` muere con `linker \`cc\` not found` — el toolchain estaría + # completo y mudo. + # + # ⚠ Va en `servidor` y NO en `base` por tamaño y por sentido: una imagen de escritorio no compila + # nada; la caja que sirve el repo y construye, sí. Y sigue siendo el paso 2 de tres: el 3 es la + # cadena mrustc del selfhost, que es lo único que quita la dependencia del LAB para arrancar. + "rust", "lld21", "cargo-config", # `netup` (2026-09-10): el cliente DHCP propio que levanta la red al arrancar. Entra como RAÍZ # aunque su binario YA venga dentro del `product-rootfs`, y por una razón concreta: el del producto # está congelado en el artefacto sellado del bootstrap, así que un arreglo de netup no llega nunca diff --git a/recipes/cargo-config.toml b/recipes/cargo-config.toml new file mode 100644 index 00000000..3fbd1da3 --- /dev/null +++ b/recipes/cargo-config.toml @@ -0,0 +1,32 @@ +# cargo-config — la config que hace que `cargo build` FUNCIONE en una caja takana. +# +# ── POR QUÉ ES UNA RECETA Y NO UN FICHERO SUELTO (SDD 31) ─────────────────────────────────────── +# Una distro sin compilador de C puede compilar Rust —está probado— pero **no de fábrica**: sin esta +# config, `cargo build` muere con `linker \`cc\` not found`. Un toolchain que sella, se instala y no +# enlaza es [[subcomando-sin-driver]] otra vez, y la pieza que falta son tres flags. +# +# Va junto a `rust` y `lld21` en el perfil: los tres son el mismo hecho —«esta caja compila Rust»— +# partido en un compilador, un enlazador y la línea que los une. +# +# ⚠ Es config de SISTEMA, no de usuario: `/etc/cargo/config.toml` lo lee cualquier `cargo` de +# cualquier cuenta. Un `~/.cargo/config.toml` haría que el toolchain funcione para quien lo escribió +# y no para el siguiente. +name = "cargo-config" +version = "1" +license = "MIT" + +[source] +dir = "cargo-config/tree" + +[build] +compiler = "zig-cc" +target = "x86_64-linux-musl" +link = "static" +flags = [] + +[build.phases] +configure = "true" +compile = "true" +# `cp -r` y no `cp -a`: en el sandbox no hay privilegio para preservar el propietario (la lección de +# `os-release`). El dueño real lo pone la proyección del artefacto. +install = "mkdir -p /out/etc && cp -r /src/etc/. /out/etc/" diff --git a/recipes/cargo-config/tree/etc/cargo/config.toml b/recipes/cargo-config/tree/etc/cargo/config.toml new file mode 100644 index 00000000..bd0d18e9 --- /dev/null +++ b/recipes/cargo-config/tree/etc/cargo/config.toml @@ -0,0 +1,19 @@ +# Config del SITIO para cargo/rustc — SDD 31. +# +# ⚠ Sin esto, `cargo build` en una caja takana falla con `linker `cc` not found`: la distro NO TIENE +# compilador de C, y no hace falta que lo tenga. Lo que hace falta es decirle a rustc que el +# enlazador es el `ld` de binutils y que el modo es estático, que es el natural de musl. +# +# Por qué CADA flag, todos medidos el 2026-09-16 contra el rustc que construimos: +# · `linker-flavor=ld.lld` + `linker=/usr/bin/ld.lld` — el `lld` del corpus (`recipes/lld21.toml`). +# Hasta el 2026-09-16 acá decía el `ld` de binutils, porque el `lld` heredaba `LLVM_ENABLE_ZLIB=0` +# de `llvm21` y no podía leer las secciones de depuración COMPRIMIDAS de la libc del lab. Con +# `llvm21` reconstruido con zlib, lld enlaza y es más rápido. El `ld` de binutils sigue +# funcionando como alternativa: `-C linker-flavor=ld -C linker=/usr/bin/ld`. +# · `target-feature=+crt-static` — sin esto rustc pide `-lgcc`/`-lgcc_s` para el desenrollado y el +# enlace muere en `cannot find -lgcc`: la distro se construye con zig, que trae compiler-rt y no +# libgcc. Estático es además el modo natural de musl. +# · `link-self-contained=yes` — usa los `crt*.o` y la `libc.a` que el propio toolchain trae. +[target.x86_64-alpine-linux-musl] +linker = "/usr/bin/ld.lld" +rustflags = ["-C", "linker-flavor=ld.lld", "-C", "target-feature=+crt-static", "-C", "link-self-contained=yes"] diff --git a/recipes/incoming/cargo-config.toml b/recipes/incoming/cargo-config.toml new file mode 120000 index 00000000..65b32317 --- /dev/null +++ b/recipes/incoming/cargo-config.toml @@ -0,0 +1 @@ +../cargo-config.toml \ No newline at end of file diff --git a/recipes/rust.toml b/recipes/rust.toml index 1d693958..bfc63b04 100644 --- a/recipes/rust.toml +++ b/recipes/rust.toml @@ -118,6 +118,13 @@ codegen-tests = false deny-warnings = false musl-root = "/usr" +[install] +# ⚠ SIN ESTO EL TOOLCHAIN QUEDA FUERA DEL PATH, y es la trampa de «existe ≠ se encuentra»: el +# default de x.py es `/usr/local`, y el PATH de una caja takana es `/bin:/usr/bin:/sbin:/usr/sbin` +# — medido en la caja de producción. O sea que el perfil proyectaría un `rustc` perfecto que nadie +# puede invocar. El resto del corpus instala en `/usr`; esto se alinea. +prefix = "/usr" + [target.x86_64-alpine-linux-musl] llvm-config = "/usr/bin/llvm-config" # `false` a propósito: habilita dylibs, y sin dylibs no hay PROC-MACROS. Un rustc con