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 1436Shell 145Markdown 88Rust 852991 Definitions

⎇ c7c233755906f41d36c319886430edc8459185ee scripts/servidor/cc-por-zig.sh Shell · 111 lines · 6.6 KB History raw

en la caja `/etc/profile.d` no lo leía nadie: `/etc/profile` no existía 41b21755b · Sergio ·

1#!/bin/sh
2# Le da a la caja un DRIVER DE C — hoy no tiene ninguno — usando el zig que ya está en su store.
3#
4# ── POR QUÉ (2026-09-18) ────────────────────────────────────────────────────────────────────────
5# `command -v cc gcc clang zig` en la caja no devuelve NADA. Eso no es sólo incómodo: es lo que hace
6# que `rustc`, con el compilador propio ya sellado, **no pueda enlazar una sola dylib** —y ahí entran
7# TODAS las proc-macros: serde_derive, clap_derive…—:
8#
9#     ld.lld: error: unable to find library -lgcc_s
10#     ld.lld: error: unable to find library -lc
11#
12# Y el `-L /usr/lib` obvio EMPEORA las cosas: rompe los estáticos, que hoy funcionan, porque rustc
13# enlaza musl static-PIE con su copia self-contained y ese camino le hace preferir la `libc.a` del
14# sistema, que no es PIC. El camino de librerías no puede ser global: el estático lo quiere fuera y
15# el dinámico lo quiere dentro. Quien sabe cuál es cuál es un driver de C. (SDD 28 §6.52.)
16#
17# ⚠ NO introduce nada nuevo en el corpus: usa el `seed-zig` que YA está en el store —producto del
18# bootstrap (SDD 11), como `stage1-rootfs`— y sólo lo envuelve. Volver a zig el compilador de C
19# OFICIAL de la distro sería otra cosa, y es decisión de ADR, no de un guion de puesta a punto.
20#
21# Idempotente. Se corre EN LA CAJA, como root.
22set -eu
23
24STORE=${STORE:-/store}
25ZIG=$(find "$STORE" -maxdepth 3 -type f -perm -100 -name zig -path "*seed-zig*" 2>/dev/null | head -1)
26[ -n "$ZIG" ] || { echo "no encuentro el zig de seed-zig en $STORE — sin él no hay driver" >&2; exit 1; }
27"$ZIG" version >/dev/null 2>&1 || { echo "el zig de $ZIG no ejecuta en esta caja" >&2; exit 1; }
28echo "==> zig $("$ZIG" version) en $ZIG"
29
30# 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).
31CACHE=${CACHE:-/work/zig-cache}
32mkdir -p "$CACHE"
33
34for par in "cc:cc" "c++:c++"; do
35  nombre=${par%%:*}; sub=${par##*:}
36  cat > "/usr/bin/$nombre" <<EOF
37#!/bin/sh
38# Generado por scripts/servidor/cc-por-zig.sh — envoltorio de \`zig $sub\`.
39ZIG_GLOBAL_CACHE_DIR=\${ZIG_GLOBAL_CACHE_DIR:-$CACHE} exec "$ZIG" $sub "\$@"
40EOF
41  chmod 755 "/usr/bin/$nombre"
42done
43
44# rustc NO usa el driver por su cuenta: su enlazador por defecto en este triple es `ld.lld` invocado
45# directo. Las tres banderas son necesarias —y `link-self-contained=no` lo es porque este toolchain
46# no trae `rust-lld` (incompatible con el llvm-config externo); la variante fina `=-linker` es
47# INESTABLE en este triple y exige `-Z`.
48mkdir -p /etc/profile.d
49cat > /etc/profile.d/rust-enlazador.sh <<'EOF'
50# El enlace de rust pasa por el driver de C (ver /usr/bin/cc). Sin esto no enlaza ninguna dylib,
51# o sea ninguna proc-macro. SDD 28 §6.52.
52export RUSTFLAGS="${RUSTFLAGS:-} -C linker=cc -C linker-flavor=gcc -C link-self-contained=no"
53EOF
54chmod 644 /etc/profile.d/rust-enlazador.sh
55
56# ⚠ …Y RESULTA QUE EN ESTA CAJA `/etc/profile.d` NO LO LEÍA NADIE: `/etc/profile` **no existía**.
57# O sea que dejar ahí el fichero habría sido exactamente la avería que este repo persigue —presente,
58# con contenido, y sin efecto—. Se descubrió con el control de abajo, que pregunta por la VARIABLE en
59# una shell de login y no por el fichero. De paso revive el `bash_completion.sh` que ya estaba ahí,
60# igual de mudo. No se toca el PATH: el de la caja lo fija el init y pisarlo desde acá sería cambiar
61# algo que nadie pidió.
62if [ ! -f /etc/profile ]; then
63  cat > /etc/profile <<'EOF'
64# /etc/profile — lo lee toda shell de LOGIN. Existe para que `/etc/profile.d/*.sh` sirva de algo:
65# el directorio estaba y nadie lo leía (2026-09-18).
66for _f in /etc/profile.d/*.sh; do
67  [ -r "$_f" ] && . "$_f"
68done
69unset _f
70EOF
71  chmod 644 /etc/profile
72  echo "  (creado /etc/profile: el directorio profile.d existía y no lo leía nadie)"
73fi
74
75# ── CONTROLES: lo que importa es que COMPILE, no que el fichero exista ───────────────────────────
76T=$(mktemp -d); trap 'rm -rf "$T"' EXIT
77printf '#include <stdio.h>\nint main(void){ puts("C en takana"); return 0; }\n' > "$T/h.c"
78cc -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; }
79out=$("$T/h") || { echo "✗ compiló y no corre" >&2; exit 1; }
80echo "  ✓ C: $out"
81
82R=$(ls -d "$STORE"/*-rust 2>/dev/null | tail -1)
83if [ -n "$R" ] && [ -x "$R/usr/bin/rustc" ]; then
84  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"
85  # shellcheck disable=SC2086
86  LD_LIBRARY_PATH=$R/usr/lib "$R/usr/bin/rustc" -C linker=cc -C linker-flavor=gcc -C link-self-contained=no \
87      --edition 2021 --crate-type proc-macro --out-dir "$T" "$T/pm.rs" 2>"$T/err2" || {
88    echo "✗ la proc-macro sigue sin enlazar:" >&2; grep -m3 error "$T/err2" >&2; exit 1; }
89  so=$(ls "$T"/*.so 2>/dev/null | head -1)
90  [ -n "$so" ] || { echo "✗ no salió la dylib de la proc-macro" >&2; exit 1; }
91  printf 'extern crate pm;\npm::m!();\nfn main(){ println!("proc-macro: {}", v()); }\n' > "$T/u.rs"
92  LD_LIBRARY_PATH=$R/usr/lib "$R/usr/bin/rustc" -C linker=cc -C linker-flavor=gcc -C link-self-contained=no \
93      --edition 2021 --extern pm="$so" -o "$T/u" "$T/u.rs" 2>"$T/err3" || {
94    echo "✗ no compila el programa que USA la macro:" >&2; grep -m3 error "$T/err3" >&2; exit 1; }
95  echo "  ✓ rust: $("$T/u")"
96  # Y el control que evita el remedio peor que la enfermedad: el estático tiene que seguir andando.
97  printf 'fn main(){ println!("estático ok"); }\n' > "$T/s.rs"
98  LD_LIBRARY_PATH=$R/usr/lib "$R/usr/bin/rustc" --edition 2021 -o "$T/s" "$T/s.rs" 2>/dev/null \
99    && echo "  ✓ rust estático (sin banderas): $("$T/s")" \
100    || { echo "✗ el estático SIN banderas dejó de enlazar — eso es peor que el problema" >&2; exit 1; }
101else
102  echo "  (no hay rust en el store: me salto sus controles)"
103fi
104# ── CONTROL DEL ENTORNO: la variable, no el fichero ─────────────────────────────────────────────
105# Que el `.sh` exista no dice nada; lo que importa es que una shell de LOGIN lo traiga puesto.
106rf=$(sh -lc 'printf "%s" "$RUSTFLAGS"' 2>/dev/null || true)
107case "$rf" in
108  *"linker-flavor=gcc"*) echo "  ✓ entorno: una shell de login trae RUSTFLAGS puesto" ;;
109  *) echo "✗ /etc/profile.d/rust-enlazador.sh existe pero una shell de login NO lo recoge (RUSTFLAGS='$rf')" >&2; exit 1 ;;
110esac
111echo "la caja tiene driver de C"