diff --git a/crates/hammer-build/src/lib.rs b/crates/hammer-build/src/lib.rs index 4a39d7b8..e003d27f 100644 --- a/crates/hammer-build/src/lib.rs +++ b/crates/hammer-build/src/lib.rs @@ -539,6 +539,19 @@ fn resolve_phases(recipe: &Recipe, src: &Path) -> hammer_core::Result { // (i.e. un rust vanilla como el hammer-rust del frente self-host); para Alpine, // omitirlo. RUSTFLAGS alcanza a todas las unidades; los `bin_flags` (cargo rustc // --) sólo a la top. + // CC para los build-scripts (cc-rs compila el C de deps como libgit2-sys, + // openssl-sys, libc-stdhandle). Por defecto = el wrapper zig-cc. PERO zig-cc + // MISCOMPILA/RECHAZA muchos de esos C (mismo frente que file/jq en C puro: la + // granja lo reveló — delta/gitui/jless mueren ahí). Con `compiler="gcc"` la receta + // declara el GUETO: cc-rs usa gcc (el Alpine musl gcc del sandbox, probado en C), + // y el linker sigue siendo zig-cc — los .o/.a de gcc-musl y el Rust zig-musl son + // ABI-compatibles (ambos musl, mismo ELF x86-64). Aditivo: una receta Rust sin + // `compiler=` queda en ZigCc ⇒ baseline (ripgrep/fd/…) intacto. + let cc_for_scripts = match recipe.build.compiler { + Compiler::Gcc => "gcc", + Compiler::Clang => "clang", + Compiler::ZigCc => "$PWD/.hammer-zig-cc", + }; Some(format!( "printf '%s\\n' '#!/bin/sh' 'for a do' \ 'case \"$a\" in --target=*) a=--target=x86_64-linux-musl ;; esac' \ @@ -546,7 +559,7 @@ fn resolve_phases(recipe: &Recipe, src: &Path) -> hammer_core::Result { > \"$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=\"$PWD/.hammer-zig-cc\" RUSTFLAGS=\"$RF\" \ + CC=\"{cc_for_scripts}\" RUSTFLAGS=\"$RF\" \ cargo rustc --release --locked --offline{flags_suffix} -- {bin_flags}" )) } else { @@ -728,6 +741,32 @@ commit = "deadbeef" assert!(i.contains("find target/release"), "nativo instala de target/release ({i})"); } + #[test] + fn cargo_gcc_ghetto_uses_gcc_for_build_scripts() { + // Receta Rust con `compiler="gcc"`: el GUETO para crates con dep-C (libgit2-sys/openssl-sys/ + // libc-stdhandle) que zig-cc rechaza. cc-rs debe usar gcc (CC=gcc), pero el LINKER sigue + // siendo el wrapper zig-cc (objetos gcc-musl + Rust zig-musl son ABI-compatibles). + let d = tempfile::tempdir().unwrap(); + touch(d.path(), "Cargo.toml"); + let mut r = recipe(&[]); + r.build.compiler = Compiler::Gcc; + let c = resolve_phases(&r, d.path()).unwrap().compile.unwrap(); + assert!(c.contains("CC=\"gcc\""), "cc-rs usa gcc en el gueto ({c})"); + assert!(!c.contains("CC=\"$PWD/.hammer-zig-cc\""), "CC ya no es el wrapper ({c})"); + // El linker NO cambia: sigue el wrapper zig-cc. + assert!(c.contains("RF=\"-C linker=$PWD/.hammer-zig-cc"), "linker sigue zig-cc ({c})"); + assert!(c.contains("cargo rustc --release"), "sigue el camino cargo nativo ({c})"); + } + + #[test] + fn cargo_default_compiler_keeps_zig_cc_for_build_scripts() { + // Sin `compiler=` (default ZigCc): CC sigue siendo el wrapper — baseline ripgrep/fd intacto. + let d = tempfile::tempdir().unwrap(); + touch(d.path(), "Cargo.toml"); + let c = resolve_phases(&recipe(&[]), d.path()).unwrap().compile.unwrap(); + assert!(c.contains("CC=\"$PWD/.hammer-zig-cc\""), "default: cc-rs usa el wrapper zig ({c})"); + } + #[test] fn cargo_cross_target_keeps_triple() { // Un target NO nativo (cross real) sí pasa --target + el linker per-triple. diff --git a/recipes/delta.toml b/recipes/delta.toml new file mode 100644 index 00000000..09a9469f --- /dev/null +++ b/recipes/delta.toml @@ -0,0 +1,29 @@ +# Importada de nixpkgs por `hammer import-nix` (Etapa G). PUNTO DE PARTIDA, no final: +# - el build usa el lab de hammer (zig-cc / musl estático), NO el stdenv de nix ⇒ revisá +# compiler/link/phases y adaptá hasta que compile. +# - las deps van con su nombre NIX; remapealas a las recetas del corpus si difieren. +name = "delta" +version = "0.19.2" + +[source] +repo = "https://github.com/dandavison/delta" +commit = "1502986e81c8e3fa27bfb5b84bac6b281a6b1edd" + +# GUETO gcc para los build-scripts: delta trae `libgit2-sys`, que vendorea y COMPILA libgit2 desde +# C (decenas de .c). zig-cc los rechaza (la granja lo reveló: ToolExecError en apply.c/attr_file.c/…). +# `compiler="gcc"` ⇒ cc-rs compila ese C con el Alpine musl gcc (probado en C); el linker sigue zig-cc. +[build] +compiler = "gcc" +target = "x86_64-linux-musl" +link = "static" +flags = ["--bin", "delta"] + +[build.phases] +install = "mkdir -p /out/usr/bin && cp target/release/delta /out/usr/bin/delta" + +# libgit2-sys y libz-sys enlazan `-lz`; el lab materializa zlib (libz.a en /usr/lib) como capa overlay. +[deps] +build = ["zlib"] + +# buildInputs de nix (NO deps de hammer — cargo vendorea; backend Rust por +# defecto). Si algún sys-crate C falla, adaptá per-paquete (patch/feature): git, oniguruma diff --git a/recipes/incoming/gitui.toml b/recipes/incoming/gitui.toml index 8a50563a..4d8ebe0a 100644 --- a/recipes/incoming/gitui.toml +++ b/recipes/incoming/gitui.toml @@ -9,8 +9,10 @@ version = "0.28.1" repo = "https://github.com/gitui-org/gitui" commit = "e24fb45df1584ee8d8ebdc4258531b4a91ca975d" +# GUETO gcc para build-scripts: gitui trae openssl-src (vendorea+compila openssl 3.4 desde C) + +# libgit2-sys; zig-cc los rechaza. compiler="gcc" -> cc-rs usa el Alpine musl gcc; linker zig-cc. [build] -compiler = "zig-cc" +compiler = "gcc" target = "x86_64-linux-musl" link = "static" flags = ["--bin", "gitui"] diff --git a/recipes/incoming/jless.toml b/recipes/incoming/jless.toml index 728e33d5..d79198a7 100644 --- a/recipes/incoming/jless.toml +++ b/recipes/incoming/jless.toml @@ -9,8 +9,11 @@ version = "0.9.0" repo = "https://github.com/PaulJuliusMartinez/jless" commit = "21dd6100edb47145bb9570931bec29697bcd0d9b" +# GUETO gcc para los build-scripts: jless trae `libc-stdhandle` (un sys-crate con un imp.c que +# cc-rs compila); zig-cc lo rechaza (mismo frente que file/jq en C puro). `compiler="gcc"` ⇒ cc-rs +# usa el Alpine musl gcc para ese C; el linker sigue zig-cc (ABI musl compatible). [build] -compiler = "zig-cc" +compiler = "gcc" target = "x86_64-linux-musl" link = "static" flags = ["--bin", "jless"]