Files
hammer/recipes/tuc.toml
T
sergioandClaude Opus 4.8 a8a9a396c3 static: helix y tuc — el libgcc_s NO venía de ningún C (MIENTEN: 0 en todo el store)
Mi hipótesis de partida era falsa y conviene dejarlo escrito: el libgcc_s.so.1 NO lo metía un
sys-crate en C, y -static-libgcc (el patrón de cmake) no aplicaba — ese patrón es para C/C++.

CAUSA REAL, una sola y compartida: ambas recetas PISABAN la fase compile del lab. El lab sólo
autogenera la fase si la receta no la trae (lib.rs:779, `if out.compile.is_none()`). Las dos venían
del import de Alpine con un `cargo build --frozen --release` propio que REEMPLAZA el comando del
lab entero, y con él las tres cosas que hacen honesto al link=static:
    -C target-feature=+crt-static   -C relocation-model=static   -C linker=.hammer-zig-cc
Sin crt-static, el rust enlaza dinámico contra musl Y contra libgcc_s — que es el UNWINDER DE LA
STD DE RUSTC, no un sys-crate.

LA EVIDENCIA QUE LO CIERRA (contraste, sin bisectar): estaba ya escrita en recipes/cargo-hack.toml
—'receta MÍNIMA sin fase compile custom (una fase cargo build produce binario DINÁMICO; el PATH
DEFAULT del lab aplica crt-static + linker zig → estático)'. cargo-hack es Rust puro y sale
estático; tuc TAMBIÉN es Rust puro, sin una línea de C, y arrastraba el mismo libgcc_s. Misma
toolchain, único delta = quién arma el cargo.

tuc: borrada la fase compile (no aportaba nada sobre el default) + flags=["--bin","tuc"] (cargo
  rustc exige un único target y tuc expone lib+bin homónimos). NEEDED=0, tuc 1.3.0 corre y
  'hola,mundo | tuc -d, -f2' → mundo.
helix: la fase custom es OBLIGATORIA (exporta HELIX_DEFAULT_RUNTIME y HELIX_DISABLE_AUTO_GRAMMAR_
  BUILD) ⇒ replicado a mano el setup del lab siguiendo cargo-edit. Su raíz es un manifiesto
  VIRTUAL ⇒ 'cargo rustc' cortaba con 'is a virtual manifest'; resuelto con -p helix-term, que
  declara [[bin]] name="hx". Sigue con compiler=gcc (el gueto cc-rs/tree-sitter es real).
  NEEDED=0, helix 25.07.1 corre.

MARCADOR: static-audit global = estáticos de verdad: 680 | MIENTEN: 0. Con dos honestidades: el
audit corrió DESPUÉS de los rebuilds (si no, sobre-reporta), y quedan 58 'sin artefacto o sin ELF'
que NO son un pase sino recetas no medidas. El cero es real para lo que el store cubre hoy, no una
prueba de clausura.

TRAMPA ARMADA (no tocada): el riesgo generaliza a toda receta Cargo importada de Alpine que traiga
compile propio — alpine_import.rs traduce el build() del APKBUILD literal. Hoy las 5 con compile
propio llevan crt-static, pero cada receta Rust nueva puede nacer mintiendo. Un gate barato: que el
lab avise/falle si una receta Cargo con link=static define compile sin crt-static. Cambia el lab ⇒
re-hashea sellados ⇒ decisión aparte.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 10:08:46 -04:00

46 lines
2.3 KiB
TOML

# Importada de Alpine aports por `hammer import-alpine` (Etapa G). PUNTO DE PARTIDA — pero
# YA trae los parches de musl de Alpine (lo que un import de nix pierde). Pendiente: el
# sha256 del tarball (el wrapper lo calcula), y adaptar build/install del shell de abuild.
name = "tuc"
version = "1.3.0"
[source]
tarball = "https://github.com/riquito/tuc/archive/v1.3.0/tuc-1.3.0.tar.gz"
# FIXME sha256: el wrapper lo calcula (Alpine publica sha512). sha512 de Alpine:
# sha512 = "da64cffa388d032576b1f96f13d20c1ee657cd99eba0d1b0252dcc133bcd5b2de49007a30c426760d845dbd5ddf23ab7b81ebb83bce4eba7f40d25712f539ddf"
sha256 = "81dc5f4a0355ecdf9515c88c34c365d20f339d316df7dbe72667cd2b18445c61"
[build]
compiler = "zig-cc"
target = "x86_64-linux-musl"
link = "static"
flags = ["--bin", "tuc"]
[build.phases]
# SIN fase `compile` custom — A PROPÓSITO (2026-07-17, frente static-audit).
#
# La receta importada de Alpine traía `cargo build --frozen --release`. Eso NO era inocente: en
# `resolve_phases` el lab sólo autogenera la fase si la receta NO la trae (`if out.compile.is_none()`),
# así que un `compile` propio REEMPLAZA el comando del lab ENTERO y con él se pierden las tres cosas
# que hacen honesto al `link = "static"`:
# 1. `-C target-feature=+crt-static` (mete musl DENTRO; sin esto el rust de Alpine enlaza dinámico)
# 2. `-C relocation-model=static` (ET_EXEC sin interpreter, en vez de PIE)
# 3. `-C linker=.hammer-zig-cc` (el wrapper que sanea el triple `x86_64-alpine-linux-musl`)
# El binario salía PIE dinámico con `NEEDED: libgcc_s.so.1, libc.musl-x86_64.so.1`.
#
# Ojo con el diagnóstico fácil: ese `libgcc_s` NO lo metía ningún sys-crate en C. tuc es Rust puro.
# Es el UNWINDER de la std de rustc, que sin `+crt-static` se enlaza dinámico contra el libgcc_s de
# Alpine. Por eso el fix no es `-static-libgcc` (eso es para C/C++): es dejar de pisar la fase del lab.
# Contraste que lo prueba: cargo-hack también es Rust puro, no tiene fase compile custom, y sale
# ET_EXEC estático. Misma toolchain, único delta = quién arma el `cargo`.
#
# `flags = ["--bin", "tuc"]`: el path default usa `cargo rustc -- <flags>`, que exige UN único target,
# y tuc expone lib + bin homónimos.
# de package() de Alpine (traducido $pkgdir→/out):
install = '''
_abuild_phase() {
install -Dm755 target/release/tuc -t "/out"/usr/bin/
}
_abuild_phase
'''