gioser

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 604Rust 56Shell 36Markdown 281227 Definitions

`perfil.servidor`: fuera el prebuilt ajeno, entra el toolchain propio

Sale `rust-toolchain-bin` —799 M de bytes AJENOS sellados tal cual (`foreign`)—, que era el escalón 1
del SDD 31 y cumplió su función: con él se construyó el escalón 2, y el escalón 2 ya compila,
enlaza y corre.

Entran TRES, que son el mismo hecho («esta caja compila Rust») partido en piezas:
· `rust` (353 M) — el compilador y cargo, de la granja, desde fuente.
· `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` — receta nueva que publica `/etc/cargo/config.toml` con las tres flags que unen a
  los dos. Sin ellas `cargo build` muere con «linker `cc` not found»: el toolchain estaría completo
  y MUDO, que es [[subcomando-sin-driver]] otra vez. Es config de SISTEMA y no de usuario a
  propósito — un `~/.cargo/config.toml` funcionaría para quien lo escribió y no para el siguiente.

⚠ Y `rust` se re-hashea otra vez (702094a8 → fe277b32) por una línea que descubrió el control de
PATH: **x.py instala en `/usr/local` por defecto, y el PATH de una caja takana es
`/bin:/usr/bin:/sbin:/usr/sbin`** — medido en la caja. O sea que el perfil habría proyectado un
`rustc` perfecto que nadie puede invocar: «existe ≠ se encuentra». Ahora `[install] prefix = "/usr"`,
como el resto del corpus.

Control previo que sí pasó: `rustc` y `cargo` corren SIN `LD_LIBRARY_PATH` — su `RUNPATH` es
`$ORIGIN/../lib`, así que la proyección del artefacto basta.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

0a894cfac15155938a41771e9e44d64692dbe7e9 · by Sergio · (1 month ago) · parent 240069801 · browse the tree at this commit

Semantic delta

No definition changed: this change is text, documentation or data.

5 files · +76 −7

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