tawasuyu

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…

⎇ main recipes/lld21-zlibrs.toml TOML · 83 siq'ikuna · 5.1 KB Ñawpa willay ch'uya

paso 8 ter: lld21 sobre zlib-rs — el caso dinámico destapó que la .so no declaraba SONAME 6b10a805a · Sergio ·

1# LLD 21.1.2 sobre zlib-rs — la PRUEBA DE CONSUMIDOR DINÁMICO del paso 8 del plan.
2#
3# ══ POR QUÉ ESTA VARIANTE, Y POR QUÉ lld ES EL CASO QUE FALTABA ════════════════════════════════
4# `pigz-zlibrs` probó el enlace ESTÁTICO (`libz.a` + `-lunwind`). Este prueba el otro, que es el que
5# de verdad puede fallar callado: **lld enlaza `libz.so.1` DINÁMICAMENTE** —`link = "dynamic"` en su
6# receta, por una razón medida que está escrita allá— así que acá lo que se pone a prueba no es sólo
7# compilar, es que el `NEEDED` grabado sea el correcto y que el cargador lo resuelva en ejecución.
8#
9# ⚠ **Y ahí apareció el defecto que el caso estático no podía mostrar: la `.so` de zlib-rs no
10# declaraba SONAME.** `readelf -d` sobre la `libz_rs.so` que sale de cargo mostraba `NEEDED` y ningún
11# `SONAME`, mientras la `zlib-shared` del corpus declara `libz.so.1`. Un consumidor enlazado contra una
12# `.so` sin soname graba la RUTA con la que se enlazó, no el nombre de la librería ⇒ sella, reproduce
13# y no corre ([[needed-colgante-libstdcxx]]). Arreglado en `recipes/zlib-rs.toml` con
14# `-C link-arg=-Wl,-soname,libz.so.1`; esta receta existe para comprobarlo de punta a punta.
15#
16# ⚠ **lld USA zlib de verdad, no de adorno**: `LLVM_ENABLE_ZLIB` está encendido porque los objetos
17# `crt*` del sysroot de rust traen las secciones de depuración comprimidas
18# (`ELFCOMPRESS_ZLIB`) y un enlazador sin zlib no puede ni leerlos. O sea que si zlib-rs no
19# descomprimiera bien, el fallo aparecería enlazando, no en un `--version`.
20#
21# Lo único que cambia frente a `recipes/lld21.toml`: la dep (`zlib-rs` en vez de `zlib`). No hace
22# falta `-lunwind` —y eso es un hallazgo del caso dinámico—: la `.so` de zlib-rs trae
23# `NEEDED libgcc_s.so.1`, que es quien provee los `_Unwind_*` en ejecución, así que el consumidor no
24# tiene que sumar nada. La reserva del unwinder era del enlace ESTÁTICO.
25name    = "lld21-zlibrs"
26version = "21.1.2"
27license = "Apache-2.0 WITH LLVM-exception"
28
29[source]
30# El mismo tarball que `llvm21`, byte por byte: la URL es locator y el sha256 es la identidad
31# (ADR 0013), así que compartir fuente entre dos recetas no cuesta nada.
32tarball = "https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.2/llvm-project-21.1.2.src.tar.xz"
33sha256  = "1a417d1c8faf8d93e73fec1cbb76d393ed3218974c2283c7bac9672d3d47c54b"
34
35[build]
36compiler = "zig-cc"
37target   = "x86_64-linux-musl"
38# ⚠ `dynamic` NO es una preferencia: con `static` el binario SELLA, arranca y **se muere en cuanto
39# hace algo** (medido 2026-09-16). `ld.lld --version` y `--help` contestan bien; cualquier enlace
40# —incluso uno que sólo debería dar un error, como un fichero de entrada inexistente— termina en
41# SIGSEGV con el banner de LLVM y un «Stack dump:» vacío. La firma es la de los registros estáticos
42# de LLVM: `cl::opt`, `TargetRegistry` y compañía se inicializan desde constructores globales que
43# viven en objetos de las `.a`, y un enlace estático agresivo los DESCARTA por no estar
44# referenciados — lo que funciona es lo que no los necesita (`--version`), y lo que no, revienta.
45# Es la misma familia que `link-static-mentira-libtool`: el flag global de la receta decide cosas
46# que la receta no dice.
47link     = "dynamic"
48strip_debug = true
49
50[deps]
51# `llvm21` NO es un adorno: el build standalone de lld necesita su `lib/cmake/llvm/LLVMConfig.cmake`
52# y sus `.a`. Es la misma dep que el paso `Lld` del bootstrap de rustc habría usado.
53build = ["llvm21", "cmake", "samurai", "python3", "pkgconf", "zlib-rs"]
54
55[build.phases]
56# ⚠ `LLVM_ENABLE_ZLIB` va ENCENDIDO —al revés que en `llvm21`— y lo decidió un error, no el gusto:
57#
58#     lld: error: …/self-contained/crtn.o:(.debug_line) is compressed with ELFCOMPRESS_ZLIB,
59#          but lld is not built with zlib support
60#
61# Los objetos `crt*` que rust trae en su sysroot llevan las secciones de depuración COMPRIMIDAS, así
62# que un enlazador sin zlib no puede ni leerlos. Para `llvm21` apagarlo era gratis; para el
63# ENLAZADOR no lo es.
64#
65# `g++` con los runtimes estáticos, igual que `llvm21` y `cmake`: C++ a escala con zig sigue siendo
66# terreno minado, y además LLD tiene que casar ABI con el LLVM contra el que enlaza — que se
67# construyó exactamente así.
68configure = '''
69CC=gcc CXX='g++ -static-libstdc++ -static-libgcc' \
70cmake -S lld -B build -G Ninja \
71  -DCMAKE_BUILD_TYPE=Release \
72  -DCMAKE_INSTALL_PREFIX=/usr \
73  -DLLVM_DIR=/usr/lib/cmake/llvm \
74  -DLLVM_INCLUDE_TESTS=OFF \
75  -DLLVM_ENABLE_ZSTD=OFF \
76  -DLLVM_ENABLE_LIBXML2=OFF
77'''
78compile = "ninja -C build"
79# ⚠ LOS CINCO `lld` SON EL MISMO BINARIO, Y cmake LOS INSTALA COMO CINCO COPIAS: medido, 5 × 96 M =
80# **478 M de artefacto para 97 M de enlazador**. `lld` despacha por `argv[0]`, así que los cuatro
81# alias son symlinks por diseño de upstream — instalarlos como copias es sólo cómo quedó su cmake.
82# En una caja cuya raíz son 5,8 G, 380 M de duplicado no son un detalle.
83install = "DESTDIR=/out ninja -C build install && cd /out/usr/bin && for f in ld.lld ld64.lld lld-link wasm-ld; do ln -sf lld \"$f\"; done"