Files
takana/recipes/rust.toml
T
SergioandClaude Opus 5 ac856501b2 rust: el séptimo muro es el openssl de cargo — y va la variante CON THREADS
El parche del triple FUNCIONÓ: el build pasó el stage 2 —donde moría— y llegó hasta las herramientas.
Ahí cortó otra cosa:

    error: failed to run custom build command for `openssl-sys v0.9.114`
    The system library `openssl` required by crate `openssl-sys` was not found.

`tools = ["cargo"]` arrastra `openssl-sys`, y eso pasa DESPUÉS de compilar las ~400 crates del
compilador, o sea a la hora y media de build.

La dep que entra es `openssl-threads` y NO la canónica, aunque las dos publiquen sólo `.a`: el
`Configure` de openssl APAGA LOS THREADS en cuanto ve `-static` en LDFLAGS, y la canónica se
construye así. Un cargo —masivamente multihilo— enlazado contra un openssl sin soporte de hilos es
la clase de fallo que no se ve al construir ni al arrancar. La variante ya existía por exactamente
lo mismo para `python3`, y el worker la tiene sellada con el mismo hash.

Van también `OPENSSL_STATIC=1` y `OPENSSL_DIR=/usr`: el lab publica `.a` y ningún `.so`, y sin
decírselo `openssl-sys` busca la dinámica y falla con un mensaje que habla de pkg-config.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 23:59:22 +00:00

135 lines
7.6 KiB
TOML

# rust 1.97.0 DESDE FUENTE — el paso 2 de los tres, y el que hace que el compilador sea nuestro.
#
# ══ LA CADENA, Y POR QUÉ ESTE ES EL SEGUNDO ESCALÓN ════════════════════════════════════════════
# 1. `rust-toolchain-bin` — el tarball oficial, `foreign`, sellado tal cual. Desbloqueó que una
# caja takana compile Rust (probado: `rustc 1.97.0` y un binario que corre). Es el escalón.
# 2. **esto** — rustc construido acá, con `llvm21` del corpus y con el (1) como **stage0**. Un
# prebuilt ajeno sirve exactamente para esto: ser el escalón que permite dejar de necesitarlo.
# 3. La cadena `mrustc → 1.90 → 1.91.0 → 1.91.1` del selfhost, que quita hasta ese escalón.
#
# ⚠ **`local-rebuild = true` NO es un detalle.** El bootstrap de rustc espera que el stage0 sea el
# compilador ANTERIOR (o el beta de esta versión); acá el stage0 es **1.97.0 construyendo 1.97.0**, y
# sin esa opción x.py aborta por «stage0 compiler version mismatch». Es el modo que usan las distros
# para reconstruir la misma versión con la misma versión.
#
# ⚠ **El LLVM es EXTERNO y tiene que ser ≥21**, medido en el propio bootstrap:
# `panic!("bad LLVM version: {version}, need >=21")`. Por eso existe `llvm21` y por eso `llvm18` —que
# ya estaba sellado— no servía: lo usa mesa, que no soporta 21. Ver `recipes/llvm21.toml`.
#
# ⚠ Sin red: el tarball `-src` trae `vendor/` con todas las deps de cargo. Es la única forma de que
# esto construya dentro del sandbox, que no tiene red después del fetch.
name = "rust"
version = "1.97.0"
license = "MIT OR Apache-2.0"
[source]
tarball = "https://static.rust-lang.org/dist/rustc-1.97.0-src.tar.xz"
sha256 = "de002ee301c1b7422b0a7b09d7c4cb4924cd3224e6cfb24f065dad786dd3ed12"
# El triple de Alpine, DENTRO del compilador: sin esto el stage 2 muere con «could not find
# specification for target x86_64-alpine-linux-musl» — el nombre que el stage0 necesita es uno que
# upstream no conoce. Es lo que hace Alpine en su APKBUILD. Ver SDD 31 §4.bis y la cabecera del
# propio parche.
patches = ["rust-alpine-target.patch"]
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "dynamic"
flags = []
[deps]
# `rust-toolchain-bin` es el STAGE0: el compilador con el que arranca el build. `llvm21` aporta el
# `llvm-config` y las librerías. `cmake`/`samurai`/`pkgconf` los pide el propio bootstrap aunque el
# LLVM venga hecho (compila algunas cosas nativas: `compiler-rt` para los sanitizers, jemalloc…).
# ⚠ EL STAGE0 **NO** ES `rust-toolchain-bin`, Y ESO SE APRENDIÓ CHOCANDO. El toolchain musl oficial
# de rust-lang está compilado con `crt-static = true`, y un rustc así **no puede producir
# proc-macros** — que son dylibs. El primer intento murió en el primer minuto:
#
# error: cannot produce proc-macro for `clap_derive v4.5.18` as the target
# `x86_64-unknown-linux-musl` does not support these crate types
#
# …compilando el PROPIO bootstrap de rustc, que usa `clap` con derive. O sea: el prebuilt oficial
# sirve para compilar programas (probado: un binario que corre) y **no** para arrancar el build de
# rustc. El stage0 es el `rustc` del LAB, que Alpine construye con soporte de dylib.
#
# Y por eso abajo va `crt-static = false` para el host: sin eso, el rustc que salga de acá heredaría
# el mismo defecto y no podría compilar ni una receta del corpus que use `derive`.
build = ["llvm21", "cmake", "samurai", "python3", "pkgconf", "curl", "openssl-threads"]
[build.phases]
# El fichero de configuración de x.py se llama `bootstrap.toml` desde 1.8x; se escribe también
# `config.toml` porque el nombre viejo sigue siendo el que busca media documentación, y un fichero
# de más no cuesta nada mientras el de verdad esté.
configure = '''
cat > bootstrap.toml <<'CFG'
profile = "dist"
change-id = "ignore"
[build]
# ⚠⚠ EL TRIPLE ES EL DE ALPINE, `x86_64-alpine-linux-musl`, Y NO EL CANÓNICO. Cuesta dos fallos
# seguidos entenderlo:
# · Sin decir `build`, x.py detecta el del `cc` del sandbox (el de Alpine) y entonces una sección
# `[target.x86_64-alpine-linux-musl]` **no aplica a nada**: ignora el `llvm-config` externo y se
# pone a construir LLVM él solo — se vio porque entró en `/src/build/x86_64-alpine-linux-musl/`.
# · Y al forzar el canónico, el stage0 del LAB **no tiene la std de ese triple**:
# `error[E0463]: can't find crate for std`. Alpine RENOMBRA el triple, y su rustc sólo trae la
# std del suyo.
# Así que se usa el de Alpine en todas partes, que además es el triple con el que ya se compila todo
# el corpus. Es el mismo camino que toma el APKBUILD de rust de Alpine.
build = "x86_64-alpine-linux-musl"
docs = false
extended = true
tools = ["cargo"]
local-rebuild = true
# Hay que NOMBRAR el stage0 aunque ya esté en el PATH: sin estas dos líneas, x.py se salta el
# compilador local y va a DESCARGAR el toolchain de `static.rust-lang.org` — que en un sandbox sin
# red muere con un `RuntimeError: failed verification` en `download_toolchain()`, un mensaje que no
# menciona ni la red ni el stage0. Estas rutas son las del LAB, no las del prebuilt (ver arriba).
rustc = "/usr/bin/rustc"
cargo = "/usr/bin/cargo"
target = ["x86_64-alpine-linux-musl"]
host = ["x86_64-alpine-linux-musl"]
vendor = true
[llvm]
download-ci-llvm = false
link-shared = false
[rust]
channel = "stable"
codegen-tests = false
deny-warnings = false
musl-root = "/usr"
[target.x86_64-alpine-linux-musl]
llvm-config = "/usr/bin/llvm-config"
# `false` a propósito: habilita dylibs, y sin dylibs no hay PROC-MACROS. Un rustc con
# `crt-static = true` no puede compilar `serde_derive`, `clap_derive` ni ninguna de las 44 recetas
# `cargo-*` del corpus que usan `derive`.
crt-static = false
CFG
cp bootstrap.toml config.toml
# La versión del stage0 se COMPRUEBA, no se asume: `local-rebuild` sólo es correcto si el compilador
# de arranque es exactamente esta versión, y si alguien mueve el pin de `rust-toolchain-bin` esto
# tiene que fallar acá y no tres horas después.
rustc --version | grep -q '1[.]97[.]0' || { echo "stage0 NO es 1.97.0: $(rustc --version)" >&2; exit 1; }
llvm-config --version
'''
# `CC`/`CXX` de GCC para los build scripts nativos (jemalloc, compiler-rt): con el wrapper de zig,
# cmake declara el compilador «broken» en su prueba de ABI. Mismo motivo por el que `llvm21` y
# `cmake` usan g++ en vez de zig.
# ── EL OPENSSL DE CARGO, Y POR QUÉ ES LA VARIANTE CON THREADS ──────────────────────────────────
# `tools = ["cargo"]` arrastra `openssl-sys`, que sin openssl en el lab corta con «The system library
# `openssl` required by crate `openssl-sys` was not found» — y eso pasa DESPUÉS de compilar las 400
# crates del compilador, o sea a la hora y media de build.
#
# La dep es `openssl-threads` y NO la canónica, aunque las dos publiquen sólo `.a`: el `Configure` de
# openssl **apaga los threads en cuanto ve `-static` en LDFLAGS**, y la canónica se construye así. Un
# cargo —que es masivamente multihilo— enlazado contra un openssl sin soporte de hilos es la clase de
# fallo que no se ve al construir ni al arrancar. La variante existe por lo mismo para `python3`.
#
# `OPENSSL_STATIC`/`OPENSSL_DIR`: el lab publica `.a` y ningún `.so`, y sin decírselo `openssl-sys`
# busca la dinámica y falla con un mensaje que habla de pkg-config y no de eso.
compile = "export CC=gcc CXX=g++ AR=ar RANLIB=ranlib OPENSSL_STATIC=1 OPENSSL_DIR=/usr && python3 x.py build --stage 2"
install = "export CC=gcc CXX=g++ AR=ar RANLIB=ranlib OPENSSL_STATIC=1 OPENSSL_DIR=/usr && DESTDIR=/out python3 x.py install --stage 2"