Files
hammer/recipes/helix.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

83 lines
4.7 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 = "helix"
version = "25.07.1"
[source]
tarball = "https://github.com/helix-editor/helix/archive/25.07.1/helix-25.07.1.tar.gz"
# FIXME sha256: el wrapper lo calcula (Alpine publica sha512). sha512 de Alpine:
# sha512 = "a8f64782273d88cd43b1aeadf45d1fa6a913c9c0b77c1da716ffdc64ec02e89db1bfb2dde4333509c3ddb5733b8f5a450b44ca54d35f113c3c0f411c01f4ce8c"
sha256 = "27c8bc3eba46bc7bab1e3629c6b28ff94882eeff17366b3ea69cd8ceffba7541"
patches = ["fix-gotmpl-grammar-source.patch"]
# GUETO gcc: helix trae tree-house-bindings (tree-sitter en C); cc-rs hace detección de familia
# de compilador con `zig -E` y zig la rechaza. compiler="gcc" usa el musl gcc de Alpine.
[build]
compiler = "gcc"
target = "x86_64-linux-musl"
link = "static"
flags = []
[build.phases]
# Fase compile custom OBLIGATORIA (a diferencia de tuc, que la borró): helix necesita exportar dos
# env vars antes de cargo, y el path default del lab no da dónde ponerlas. Pero entonces hay que
# REPLICAR A MANO el setup estático del lab — mismo patrón que cargo-edit.
#
# POR QUÉ (2026-07-17, frente static-audit): el `cargo build --frozen --release` que traía la receta
# importada de Alpine PISABA el comando del lab entero (`resolve_phases` sólo autogenera la fase si la
# receta no la trae: `if out.compile.is_none()`). Al pisarlo se perdían las tres cosas que hacen
# honesto al `link = "static"`: `+crt-static` (musl adentro), `relocation-model=static` (ET_EXEC en vez
# de PIE) y `-C linker=.hammer-zig-cc` (el wrapper que sanea el triple `x86_64-alpine-linux-musl`, que
# zig rechaza). hx salía PIE dinámico con `NEEDED: libgcc_s.so.1, libc.so`.
#
# Ese `libgcc_s` NO lo metían las tree-house-bindings ni ningún otro C: es el UNWINDER de la std de
# rustc, que sin `+crt-static` se enlaza dinámico contra el libgcc_s de Alpine. El fix de C/C++
# (`-static-libgcc`) acá no aplica. Prueba: tuc es Rust puro, sin una línea de C, y arrastraba el
# MISMO libgcc_s por la misma causa.
#
# `crt-static` va TRAS `cargo rustc --` y NUNCA en RUSTFLAGS: en build nativo RUSTFLAGS alcanza también
# a los proc-macros (un proc-macro es un dylib PIC) y rustc aborta con "cannot produce proc-macro".
# Como `cargo rustc --` exige UN único target, se fija `--bin hx`. Y `-p helix-term` porque la raíz de
# helix es un manifiesto VIRTUAL (workspace sin paquete propio): sin `-p`, cargo rustc corta con
# "is a virtual manifest, but this command requires running against an actual package". helix-term es
# quien declara `[[bin]] name = "hx"`.
#
# CC=gcc: el GUETO declarado arriba (cc-rs compila el tree-sitter en C y rechaza zig). El linker sigue
# siendo zig-cc: los .o de gcc-musl y el Rust zig-musl son ABI-compatibles (ambos musl, mismo ELF).
compile = '''
# This path is embedded in the resulting binary so that helix can find system grammars
# https://github.com/helix-editor/helix/blob/25.01.1/helix-loader/src/lib.rs#L64
export HELIX_DEFAULT_RUNTIME=/usr/share/helix/runtime
# Sandbox hermético: helix-term/build.rs intenta `git clone` de 245 gramáticas tree-sitter
# (sin red ⇒ panic). Lo desactivamos; las gramáticas van por runtime/ (build post-install).
export HELIX_DISABLE_AUTO_GRAMMAR_BUILD=1
# de-Alpinizado: cargo-auditable no está en el lab de hammer; build plano (Etapa G)
printf '%s\n' '#!/bin/sh' 'for a do' 'case "$a" in --target=*) a=--target=x86_64-linux-musl ;; esac' 'set -- "$@" "$a"' 'shift' 'done' 'exec zig cc -mcpu=baseline "$@"' > "$PWD/.hammer-zig-cc"
chmod +x "$PWD/.hammer-zig-cc"
RF="-C linker=$PWD/.hammer-zig-cc"
rustc -vV | grep -q 'host: .*-alpine-' || RF="$RF -C link-self-contained=no"
CC=gcc CXX=g++ AR=ar RUSTFLAGS="$RF" cargo rustc --release --locked --offline -p helix-term --bin hx -- -C target-feature=+crt-static -C relocation-model=static
'''
# de package() de Alpine (traducido $pkgdir→/out):
install = '''
_abuild_phase() {
install -D -m755 target/release/hx -t "/out"/usr/bin/
install -D -m644 contrib/completion/hx.bash "/out"/usr/share/bash-completion/completions/hx
install -D -m644 contrib/completion/hx.fish "/out"/usr/share/fish/vendor_completions.d/hx.fish
install -D -m644 contrib/completion/hx.zsh "/out"/usr/share/zsh/site-functions/_hx
install -D -m644 contrib/Helix.desktop -t "/out"/usr/share/applications/
install -D -m644 logo.svg "/out"/usr/share/icons/hicolor/scalable/apps/Helix.svg
install -d -m755 "/out"/usr/share/"helix"
rm runtime/grammars/.gitkeep
rm runtime/themes/README.md
rm -rf runtime/grammars/sources
cp -r runtime "/out"/usr/share/"helix"
}
_abuild_phase
'''