From 8913eae26bb010a2de486dfd9f317c4921c6edc4 Mon Sep 17 00:00:00 2001 From: sergio Date: Sun, 21 Jun 2026 09:09:19 -0400 Subject: [PATCH] Etapa G: el importador nix NO emite buildInputs como `[deps]` en recetas Rust MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hallazgo al escalar la primera tanda (12 CLI Rust): `hammer build` resuelve las deps relativas al dir de la receta y aborta si falta `recipes/.toml`. Las recetas Rust importadas arrastraban los buildInputs de nix como `[deps]` activas — pero nix lista el closure MAXIMAL (todos los backends C opcionales: zlib/pcre2/openssl/jemalloc), mientras el build Rust del lab usa las features DEFAULT de cargo (backend Rust puro: miniz_oxide vs zlib, rustls vs openssl) o las deja opt-in (pcre2). bat→zlib, fd→jemalloc, ripgrep→pcre2, xh→openssl fallaban al instante por deps espurias. Las recetas Rust validadas del corpus (ripgrep/uutils) NO declaran `[deps]`: cargo resuelve el grafo por vendoring; un sys-lib C que SÍ haga falta es adaptación per-paquete (patch/feature, p.ej. ripgrep-no-jemalloc), no una dep de corpus. - is_rust ⇒ los buildInputs quedan como COMENTARIO de provenance (no se pierden: señalan qué C podría necesitarse), no como `[deps]`. Imports C (no-Rust) intactos. - test rust_buildinputs_are_not_active_deps; filters_nix_stdenv_noise (C) sigue válido. Co-Authored-By: Claude Opus 4.8 --- crates/hammer-cli/src/nix_import.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/crates/hammer-cli/src/nix_import.rs b/crates/hammer-cli/src/nix_import.rs index f86cf41e..4a3cb163 100644 --- a/crates/hammer-cli/src/nix_import.rs +++ b/crates/hammer-cli/src/nix_import.rs @@ -160,8 +160,19 @@ pub fn to_recipe_toml(pkg: &NixPkg) -> Result { deps.push(n); } } + // Rust (buildRustPackage): NO emitir los buildInputs como `[deps]` activas. nix lista el closure + // MAXIMAL (todos los backends C opcionales: zlib, pcre2, openssl, jemalloc…), pero el build Rust + // del lab usa las features DEFAULT de cargo, que suelen traer backend Rust puro (miniz_oxide vs + // zlib, rustls vs openssl) o lo dejan opt-in (pcre2). Cargo resuelve el grafo Rust por vendoring; + // un sys-lib C que SÍ haga falta es adaptación per-paquete (patch/feature, p.ej. + // ripgrep-no-jemalloc), no una dep de corpus. Las recetas Rust validadas (ripgrep/uutils) NO + // declaran `[deps]`; emitirlas rompe `hammer build` (busca recipes/.toml). Quedan como + // COMENTARIO de provenance (no se pierden: señalan qué C podría necesitarse). let deps_block = if deps.is_empty() { String::new() + } else if pkg.is_rust { + let list = deps.join(", "); + format!("\n# buildInputs de nix (NO deps de hammer — cargo vendorea; backend Rust por\n# defecto). Si algún sys-crate C falla, adaptá per-paquete (patch/feature): {list}\n") } else { let list = deps.iter().map(|d| format!("\"{d}\"")).collect::>().join(", "); format!("\n[deps]\nbuild = [{list}]\n") @@ -417,6 +428,24 @@ mod tests { assert!(inst.contains("cp target/release/rg /out/usr/bin/rg"), "{inst}"); } + #[test] + fn rust_buildinputs_are_not_active_deps() { + // nix lista el closure maximal (pcre2/openssl…); para Rust NO deben volverse `[deps]` (cargo + // vendorea, backend Rust por defecto) — romperían `hammer build`. Quedan como comentario. + let json = r#"{ + "pname": "rg", "version": "14", + "source": { "url": "https://github.com/o/r/archive/abc.tar.gz", "output_hash_mode": "recursive" }, + "is_rust": true, "main_program": "rg", + "build_inputs": ["pcre2", "openssl"] + }"#; + let pkg: NixPkg = serde_json::from_str(json).unwrap(); + let toml = to_recipe_toml(&pkg).unwrap(); + let recipe = hammer_core::Recipe::from_toml(&toml).unwrap(); + assert!(recipe.deps.build.is_empty(), "Rust no emite deps activas: {:?}", recipe.deps.build); + assert!(toml.contains("# buildInputs de nix"), "deja provenance comentada: {toml}"); + assert!(toml.contains("pcre2"), "lista los nombres en el comentario: {toml}"); + } + #[test] fn filters_nix_stdenv_noise() { let json = r#"{