Files
SergioandClaude Opus 5 e903f486d9 el enlazador va DENTRO del compilador — /etc/cargo/config.toml es una ruta que cargo no lee
La prueba de la caja recién instalada —`cargo build` en un proyecto nuevo, sin flags ni rutas a
mano— falló con `linker `cc` not found`, y destapó que la pieza que había empaquetado era falsa:
**cargo NO LEE `/etc/cargo/config.toml`**. Sólo lee `$CARGO_HOME/config.toml`, los
`.cargo/config.toml` del proyecto y sus padres, y lo que se le pase con `--config` — que es lo que yo
venía pasando a mano en cada prueba, y por eso «funcionaba».

Y el arreglo no era mover el fichero: **el que enlaza es `rustc`, y rustc no lee la config de
cargo**. Las flags van DENTRO del compilador, en el spec del triple:

· `linker = "ld.lld"` + `linker_flavor = Gnu(Cc::No, Lld::Yes)` — sin esto rustc busca `cc`, que una
  caja takana no tiene.
· `crt_static_default = true` — sin esto enlaza dinámico y pide `-lgcc`, que no existe (la distro se
  construye con zig, que trae compiler-rt).
· `crt_static_allows_dylibs = true` — su pareja obligatoria: sin ella `crt-static` apaga los dylibs
  y con ellos los PROC-MACROS (serde_derive, clap_derive, las 44 recetas `cargo-*` con `derive`).
  El compilador en sí sigue dinámico: el `bootstrap.toml` fija `crt-static = false` para el build, y
  eso gana sobre el default del spec.

⇒ `cargo-config` (receta, árbol y copia en scripts/) se van enteros: un paquete que instala un
fichero que nadie abre es peor que no tenerlo.

Y de paso, `lld21` instala los cuatro alias como SYMLINKS y no como copias: cmake los duplicaba, 5 ×
96 M = 478 M de artefacto para 97 M de enlazador. Ahora 108 M, y `ld.lld` sigue despachando por
`argv[0]`, que es como upstream lo diseñó.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 13:07:56 +00:00

83 lines
4.9 KiB
TOML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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"