diff --git a/recipes/helix.toml b/recipes/helix.toml index 2de75cad..54550310 100644 --- a/recipes/helix.toml +++ b/recipes/helix.toml @@ -20,20 +20,44 @@ link = "static" flags = [] [build.phases] -# de build() de Alpine (traducido; el lab provee $CBUILD/$CHOST — Etapa G Fase 3; revisá --shared para estático): +# 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 = ''' -_abuild_phase() { -# 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) - cargo build --frozen --release -} -_abuild_phase +# 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 = ''' diff --git a/recipes/tuc.toml b/recipes/tuc.toml index 458a3d39..02555c9c 100644 --- a/recipes/tuc.toml +++ b/recipes/tuc.toml @@ -14,16 +14,28 @@ sha256 = "81dc5f4a0355ecdf9515c88c34c365d20f339d316df7dbe72667cd2b18445c61" compiler = "zig-cc" target = "x86_64-linux-musl" link = "static" -flags = [] +flags = ["--bin", "tuc"] [build.phases] -# de build() de Alpine (traducido; el lab provee $CBUILD/$CHOST — Etapa G Fase 3; revisá --shared para estático): -compile = ''' -_abuild_phase() { -cargo build --frozen --release -} -_abuild_phase -''' +# 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 -- `, que exige UN único target, +# y tuc expone lib + bin homónimos. # de package() de Alpine (traducido $pkgdir→/out): install = ''' _abuild_phase() {