# LLD 21.1.2 — el ENLAZADOR de la distro. Mismo `llvm-project` que `llvm21`, construido aparte. # # ══ POR QUÉ EXISTE (SDD 31, muro 8) ════════════════════════════════════════════════════════════ # `rust` desde fuente selló, corre y **no puede enlazar**: en una caja sin `cc` —cualquier takana que # no sea un hub— `rustc hola.rs` muere con `linker \`lld\` not found`, y con el `ld` de binutils con # `cannot find -lgcc`. La causa está en una línea del log del propio build que parece informativa: # # skipping llvm-tools (x86_64-alpine-linux-musl): external LLVM # # Al usar un LLVM externo —que es lo que queremos, porque `llvm21` es del corpus— x.py se salta las # herramientas de LLVM, y `rust-lld` es una de ellas. # # ⚠ Y la vía obvia está CERRADA por el propio bootstrap, medido: `rust.lld = true` contesta # «Cannot enable LLD with `rust.lld = true` when using external llvm-config». La guarda tiene # sentido —LLD y LLVM comparten ABI de C++— pero deja una sola salida: construir LLD nosotros. # # ⚠ Y `llvm21` no servía de repuesto: sobre sus 1,6 G de artefacto **no publica ningún `lld`** # (`-DLLVM_ENABLE_PROJECTS=""`). Encenderlo ahí re-hashearía llvm21 y con él `rust`; separado, esto # suma sin mover nada. # # ══ QUÉ CAMBIA FRENTE A llvm21 ═════════════════════════════════════════════════════════════════ # Se compila SÓLO el subproyecto `lld` (`cmake -S lld`), contra el LLVM ya instalado por la dep: # minutos en vez de horas, y nada de volver a compilar los 1,6 G de librerías. name = "lld21" version = "21.1.2" license = "Apache-2.0 WITH LLVM-exception" [source] # El mismo tarball que `llvm21`, byte por byte: la URL es locator y el sha256 es la identidad # (ADR 0013), así que compartir fuente entre dos recetas no cuesta nada. tarball = "https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.2/llvm-project-21.1.2.src.tar.xz" sha256 = "1a417d1c8faf8d93e73fec1cbb76d393ed3218974c2283c7bac9672d3d47c54b" [build] compiler = "zig-cc" target = "x86_64-linux-musl" # ⚠ `dynamic` NO es una preferencia: con `static` el binario SELLA, arranca y **se muere en cuanto # hace algo** (medido 2026-09-16). `ld.lld --version` y `--help` contestan bien; cualquier enlace # —incluso uno que sólo debería dar un error, como un fichero de entrada inexistente— termina en # SIGSEGV con el banner de LLVM y un «Stack dump:» vacío. La firma es la de los registros estáticos # de LLVM: `cl::opt`, `TargetRegistry` y compañía se inicializan desde constructores globales que # viven en objetos de las `.a`, y un enlace estático agresivo los DESCARTA por no estar # referenciados — lo que funciona es lo que no los necesita (`--version`), y lo que no, revienta. # Es la misma familia que `link-static-mentira-libtool`: el flag global de la receta decide cosas # que la receta no dice. link = "dynamic" strip_debug = true [deps] # `llvm21` NO es un adorno: el build standalone de lld necesita su `lib/cmake/llvm/LLVMConfig.cmake` # y sus `.a`. Es la misma dep que el paso `Lld` del bootstrap de rustc habría usado. build = ["llvm21", "cmake", "samurai", "python3", "pkgconf", "zlib"] [build.phases] # ⚠ `LLVM_ENABLE_ZLIB` va ENCENDIDO —al revés que en `llvm21`— y lo decidió un error, no el gusto: # # lld: error: …/self-contained/crtn.o:(.debug_line) is compressed with ELFCOMPRESS_ZLIB, # but lld is not built with zlib support # # Los objetos `crt*` que rust trae en su sysroot llevan las secciones de depuración COMPRIMIDAS, así # que un enlazador sin zlib no puede ni leerlos. Para `llvm21` apagarlo era gratis; para el # ENLAZADOR no lo es. # # `g++` con los runtimes estáticos, igual que `llvm21` y `cmake`: C++ a escala con zig sigue siendo # terreno minado, y además LLD tiene que casar ABI con el LLVM contra el que enlaza — que se # construyó exactamente así. configure = ''' CC=gcc CXX='g++ -static-libstdc++ -static-libgcc' \ cmake -S lld -B build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr \ -DLLVM_DIR=/usr/lib/cmake/llvm \ -DLLVM_INCLUDE_TESTS=OFF \ -DLLVM_ENABLE_ZSTD=OFF \ -DLLVM_ENABLE_LIBXML2=OFF ''' compile = "ninja -C build" # ⚠ LOS CINCO `lld` SON EL MISMO BINARIO, Y cmake LOS INSTALA COMO CINCO COPIAS: medido, 5 × 96 M = # **478 M de artefacto para 97 M de enlazador**. `lld` despacha por `argv[0]`, así que los cuatro # alias son symlinks por diseño de upstream — instalarlos como copias es sólo cómo quedó su cmake. # En una caja cuya raíz son 5,8 G, 380 M de duplicado no son un detalle. install = "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"