From 69ed6e53c035f4e4e32eb855e0012b25605f5db9 Mon Sep 17 00:00:00 2001 From: Sergio Date: Fri, 18 Sep 2026 13:11:57 +0000 Subject: [PATCH] =?UTF-8?q?la=20caja=20no=20ten=C3=ADa=20NING=C3=9AN=20dri?= =?UTF-8?q?ver=20de=20C:=20se=20lo=20damos=20con=20el=20zig=20que=20ya=20e?= =?UTF-8?q?st=C3=A1=20en=20su=20store?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `command -v cc gcc clang zig` en la caja no devolvía nada. Eso no es sólo incómodo: es lo que hacía que rustc, con el compilador propio ya sellado, no pudiera enlazar una sola dylib —y ahí entran todas las proc-macros—. El `-L /usr/lib` obvio empeora las cosas: rompe los estáticos, porque rustc enlaza musl static-PIE con su copia self-contained y ese camino le hace preferir la libc.a del sistema, que no es PIC. El camino de librerías no puede ser global; quien sabe cuál es cuál es un driver de C. NO introduce nada nuevo en el corpus: envuelve el `seed-zig` que ya está en el store —producto del bootstrap, como stage1-rootfs—. Volver a zig el compilador de C OFICIAL de la distro sería otra cosa, y es decisión de ADR. La caché de zig va a /work y no a la raíz de 5,9 G, que ya nos costó una caída. Controles que corre el propio guion, sobre el HECHO y no sobre la intención: compila y ejecuta un hola mundo en C; enlaza una proc-macro, compila el programa que la usa y lo ejecuta; y —el que evita el remedio peor que la enfermedad— comprueba que el estático SIN banderas siga enlazando. Co-Authored-By: Claude Opus 5 (1M context) --- scripts/servidor/cc-por-zig.sh | 84 ++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100755 scripts/servidor/cc-por-zig.sh diff --git a/scripts/servidor/cc-por-zig.sh b/scripts/servidor/cc-por-zig.sh new file mode 100755 index 00000000..3b87d793 --- /dev/null +++ b/scripts/servidor/cc-por-zig.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# Le da a la caja un DRIVER DE C — hoy no tiene ninguno — usando el zig que ya está en su store. +# +# ── POR QUÉ (2026-09-18) ──────────────────────────────────────────────────────────────────────── +# `command -v cc gcc clang zig` en la caja no devuelve NADA. Eso no es sólo incómodo: es lo que hace +# que `rustc`, con el compilador propio ya sellado, **no pueda enlazar una sola dylib** —y ahí entran +# TODAS las proc-macros: serde_derive, clap_derive…—: +# +# ld.lld: error: unable to find library -lgcc_s +# ld.lld: error: unable to find library -lc +# +# Y el `-L /usr/lib` obvio EMPEORA las cosas: rompe los estáticos, que hoy funcionan, porque rustc +# enlaza musl static-PIE con su copia self-contained y ese camino le hace preferir la `libc.a` del +# sistema, que no es PIC. El camino de librerías no puede ser global: el estático lo quiere fuera y +# el dinámico lo quiere dentro. Quien sabe cuál es cuál es un driver de C. (SDD 28 §6.52.) +# +# ⚠ NO introduce nada nuevo en el corpus: usa el `seed-zig` que YA está en el store —producto del +# bootstrap (SDD 11), como `stage1-rootfs`— y sólo lo envuelve. Volver a zig el compilador de C +# OFICIAL de la distro sería otra cosa, y es decisión de ADR, no de un guion de puesta a punto. +# +# Idempotente. Se corre EN LA CAJA, como root. +set -eu + +STORE=${STORE:-/store} +ZIG=$(find "$STORE" -maxdepth 3 -type f -perm -100 -name zig -path "*seed-zig*" 2>/dev/null | head -1) +[ -n "$ZIG" ] || { echo "no encuentro el zig de seed-zig en $STORE — sin él no hay driver" >&2; exit 1; } +"$ZIG" version >/dev/null 2>&1 || { echo "el zig de $ZIG no ejecuta en esta caja" >&2; exit 1; } +echo "==> zig $("$ZIG" version) en $ZIG" + +# La caché de zig NO va en la raíz: son 5,9 G y ya nos costó una caída entera (SDD 28 §6.50 quinquies). +CACHE=${CACHE:-/work/zig-cache} +mkdir -p "$CACHE" + +for par in "cc:cc" "c++:c++"; do + nombre=${par%%:*}; sub=${par##*:} + cat > "/usr/bin/$nombre" < /etc/profile.d/rust-enlazador.sh <<'EOF' +# El enlace de rust pasa por el driver de C (ver /usr/bin/cc). Sin esto no enlaza ninguna dylib, +# o sea ninguna proc-macro. SDD 28 §6.52. +export RUSTFLAGS="${RUSTFLAGS:-} -C linker=cc -C linker-flavor=gcc -C link-self-contained=no" +EOF +chmod 644 /etc/profile.d/rust-enlazador.sh + +# ── CONTROLES: lo que importa es que COMPILE, no que el fichero exista ─────────────────────────── +T=$(mktemp -d); trap 'rm -rf "$T"' EXIT +printf '#include \nint main(void){ puts("C en takana"); return 0; }\n' > "$T/h.c" +cc -o "$T/h" "$T/h.c" 2>"$T/err" || { echo "✗ el cc nuevo no compila un hola mundo:" >&2; head -5 "$T/err" >&2; exit 1; } +out=$("$T/h") || { echo "✗ compiló y no corre" >&2; exit 1; } +echo " ✓ C: $out" + +R=$(ls -d "$STORE"/*-rust 2>/dev/null | tail -1) +if [ -n "$R" ] && [ -x "$R/usr/bin/rustc" ]; then + printf 'extern crate proc_macro;\nuse proc_macro::TokenStream;\n#[proc_macro]\npub fn m(_i: TokenStream) -> TokenStream { "fn v() -> u32 { 42 }".parse().unwrap() }\n' > "$T/pm.rs" + # shellcheck disable=SC2086 + LD_LIBRARY_PATH=$R/usr/lib "$R/usr/bin/rustc" -C linker=cc -C linker-flavor=gcc -C link-self-contained=no \ + --edition 2021 --crate-type proc-macro --out-dir "$T" "$T/pm.rs" 2>"$T/err2" || { + echo "✗ la proc-macro sigue sin enlazar:" >&2; grep -m3 error "$T/err2" >&2; exit 1; } + so=$(ls "$T"/*.so 2>/dev/null | head -1) + [ -n "$so" ] || { echo "✗ no salió la dylib de la proc-macro" >&2; exit 1; } + printf 'extern crate pm;\npm::m!();\nfn main(){ println!("proc-macro: {}", v()); }\n' > "$T/u.rs" + LD_LIBRARY_PATH=$R/usr/lib "$R/usr/bin/rustc" -C linker=cc -C linker-flavor=gcc -C link-self-contained=no \ + --edition 2021 --extern pm="$so" -o "$T/u" "$T/u.rs" 2>"$T/err3" || { + echo "✗ no compila el programa que USA la macro:" >&2; grep -m3 error "$T/err3" >&2; exit 1; } + echo " ✓ rust: $("$T/u")" + # Y el control que evita el remedio peor que la enfermedad: el estático tiene que seguir andando. + printf 'fn main(){ println!("estático ok"); }\n' > "$T/s.rs" + LD_LIBRARY_PATH=$R/usr/lib "$R/usr/bin/rustc" --edition 2021 -o "$T/s" "$T/s.rs" 2>/dev/null \ + && echo " ✓ rust estático (sin banderas): $("$T/s")" \ + || { echo "✗ el estático SIN banderas dejó de enlazar — eso es peor que el problema" >&2; exit 1; } +else + echo " (no hay rust en el store: me salto sus controles)" +fi +echo "la caja tiene driver de C"