Etapa G: tanda C tier-2 — import-batch PREFER=alpine + importador separa runtime depends
Arranca el tier-2 de la escalera (C clasico via Alpine, que trae los parches musl): - import-batch.sh: env PREFER=nix|alpine. Para tandas C, PREFER=alpine antepone Alpine — el import de nix de un C tiene exito (tarball) pero SIN parches musl => romperia al construir. Refactor a 'tiers' ordenados (misma escalera, dos sentidos). - tandas/cli-c.txt: primera tanda C (tree/which/sed/gawk/gzip/tar/jq/file). - importador Alpine: build-deps = SOLO makedepends. El depends de abuild es RUNTIME (gzip depends=less para zless) — no hace falta para compilar y rompia hammer build (buscaba recipes/less.toml). Ahora va como comentario de provenance. Mismo patron que el fix de buildInputs-de-nix en recetas Rust. VALIDADO: import C 8/8 desde Alpine/main con parches musl bajados; gzip pierde el less espurio. test extracts_source_patches_deps_phases actualizado (depends != build-dep). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -60,10 +60,13 @@ pub fn recipe_from_apkbuild(text: &str) -> Result<String, String> {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
// deps: makedepends + depends (nombres; filtramos self-subpaquetes y los negados `!x`).
|
// build-deps: SÓLO `makedepends`. El `depends` de abuild es RUNTIME (p.ej. gzip depends="less"
|
||||||
let mut deps: Vec<String> = Vec::new();
|
// para `zless`) — no hace falta para compilar y rompería `hammer build` (busca recipes/less.toml).
|
||||||
|
// Lo emitimos como comentario de provenance, no como `[deps] build`. (checkdepends ni se lee: no
|
||||||
|
// corremos la suite de tests del paquete.)
|
||||||
let self_prefix = format!("{pkgname}-");
|
let self_prefix = format!("{pkgname}-");
|
||||||
for src in [get("makedepends"), get("depends")] {
|
let normalize = |src: &str| -> Vec<String> {
|
||||||
|
let mut v: Vec<String> = Vec::new();
|
||||||
for d in src.split_whitespace() {
|
for d in src.split_whitespace() {
|
||||||
let d = d.trim();
|
let d = d.trim();
|
||||||
// Saltamos: negados (!x), variables sin expandir ($x), pins versionados a subpaquetes
|
// Saltamos: negados (!x), variables sin expandir ($x), pins versionados a subpaquetes
|
||||||
@@ -84,17 +87,22 @@ pub fn recipe_from_apkbuild(text: &str) -> Result<String, String> {
|
|||||||
.unwrap_or(d)
|
.unwrap_or(d)
|
||||||
.trim_end_matches("-dev")
|
.trim_end_matches("-dev")
|
||||||
.to_string();
|
.to_string();
|
||||||
if !name.is_empty() && !name.starts_with("so:") && !deps.contains(&name) {
|
if !name.is_empty() && !name.starts_with("so:") && !v.contains(&name) {
|
||||||
deps.push(name);
|
v.push(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
v
|
||||||
let deps_block = if deps.is_empty() {
|
|
||||||
String::new()
|
|
||||||
} else {
|
|
||||||
let list = deps.iter().map(|d| format!("\"{d}\"")).collect::<Vec<_>>().join(", ");
|
|
||||||
format!("\n[deps]\nbuild = [{list}]\n")
|
|
||||||
};
|
};
|
||||||
|
let deps = normalize(&get("makedepends"));
|
||||||
|
let runtime = normalize(&get("depends"));
|
||||||
|
let mut deps_block = String::new();
|
||||||
|
if !runtime.is_empty() {
|
||||||
|
deps_block.push_str(&format!("\n# depends de runtime de Alpine (NO build-deps): {}\n", runtime.join(", ")));
|
||||||
|
}
|
||||||
|
if !deps.is_empty() {
|
||||||
|
let list = deps.iter().map(|d| format!("\"{d}\"")).collect::<Vec<_>>().join(", ");
|
||||||
|
deps_block.push_str(&format!("\n[deps]\nbuild = [{list}]\n"));
|
||||||
|
}
|
||||||
|
|
||||||
// build()/package() → fases (best-effort, comentadas como abuild-shell a adaptar).
|
// build()/package() → fases (best-effort, comentadas como abuild-shell a adaptar).
|
||||||
let phases_block = {
|
let phases_block = {
|
||||||
@@ -316,11 +324,13 @@ package() {
|
|||||||
assert_eq!(recipe.source.tarball.as_deref(), Some("https://example.com/foo-2.5.tar.gz"));
|
assert_eq!(recipe.source.tarball.as_deref(), Some("https://example.com/foo-2.5.tar.gz"));
|
||||||
// LOS PARCHES DE MUSL cargados (el punto central):
|
// LOS PARCHES DE MUSL cargados (el punto central):
|
||||||
assert_eq!(recipe.source.patches, vec!["foo-musl-fix.patch", "foo-static.patch"]);
|
assert_eq!(recipe.source.patches, vec!["foo-musl-fix.patch", "foo-static.patch"]);
|
||||||
// deps: makedepends + depends, sin `-dev`:
|
// build-deps: SÓLO makedepends, sin `-dev`. El runtime `depends="bar"` NO entra como
|
||||||
|
// build-dep (rompería `hammer build`); queda como comentario de provenance.
|
||||||
assert!(recipe.deps.build.contains(&"zlib".to_string()));
|
assert!(recipe.deps.build.contains(&"zlib".to_string()));
|
||||||
assert!(recipe.deps.build.contains(&"openssl".to_string()));
|
assert!(recipe.deps.build.contains(&"openssl".to_string()));
|
||||||
assert!(recipe.deps.build.contains(&"linux-headers".to_string()));
|
assert!(recipe.deps.build.contains(&"linux-headers".to_string()));
|
||||||
assert!(recipe.deps.build.contains(&"bar".to_string()));
|
assert!(!recipe.deps.build.contains(&"bar".to_string()), "depends de runtime no es build-dep");
|
||||||
|
assert!(toml.contains("# depends de runtime de Alpine (NO build-deps): bar"), "provenance: {toml}");
|
||||||
// fases capturadas de build()/package() y TRADUCIDAS: $pkgdir → /out.
|
// fases capturadas de build()/package() y TRADUCIDAS: $pkgdir → /out.
|
||||||
assert!(recipe.build.phases.compile.as_deref().unwrap().contains("./configure"));
|
assert!(recipe.build.phases.compile.as_deref().unwrap().contains("./configure"));
|
||||||
let install = recipe.build.phases.install.as_deref().unwrap();
|
let install = recipe.build.phases.install.as_deref().unwrap();
|
||||||
|
|||||||
+30
-18
@@ -13,9 +13,10 @@
|
|||||||
# Ej: scripts/import-batch.sh ripgrep fd bat hyperfine
|
# Ej: scripts/import-batch.sh ripgrep fd bat hyperfine
|
||||||
# scripts/import-batch.sh -f tandas/cli-rust.txt
|
# scripts/import-batch.sh -f tandas/cli-rust.txt
|
||||||
# OUTDIR=recipes/incoming scripts/import-batch.sh sd dust
|
# OUTDIR=recipes/incoming scripts/import-batch.sh sd dust
|
||||||
# Env: OUTDIR (default recipes), NIX_STORE (p.ej. $HOME/.nixstore si /nix/store no es escribible),
|
# Env: OUTDIR (default recipes), PREFER (nix|alpine; default nix — alpine antepone Alpine para tandas
|
||||||
# ALPINE_BRANCH (default master), HAMMER (cmd del cli). Un nombre puede mapear nix→alpine
|
# C, que necesitan sus parches musl), NIX_STORE (p.ej. $HOME/.nixstore si /nix/store no es
|
||||||
# distintos con `nixattr=alpinepkg` (p.ej. `ripgrep=ripgrep`, `the_silver_searcher=the-silver-searcher`).
|
# escribible), ALPINE_BRANCH (default master), HAMMER (cmd del cli). Un nombre puede mapear
|
||||||
|
# nix→alpine distintos con `nixattr=alpinepkg` (p.ej. `the_silver_searcher=the-silver-searcher`).
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
here=$(dirname "$0")
|
here=$(dirname "$0")
|
||||||
@@ -31,6 +32,12 @@ else
|
|||||||
pkgs=$(printf '%s\n' "$@")
|
pkgs=$(printf '%s\n' "$@")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Orden de fuentes: PREFER=nix (default, tier-1 Rust/Go) o PREFER=alpine (tier-2 C, trae parches musl).
|
||||||
|
case "${PREFER:-nix}" in
|
||||||
|
alpine) TIERS="alpine-main alpine-community nix" ;;
|
||||||
|
nix|*) TIERS="nix alpine-main alpine-community" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
mkdir -p "$OUTDIR"
|
mkdir -p "$OUTDIR"
|
||||||
nix_n=0; alpine_n=0; failed=""; got=""
|
nix_n=0; alpine_n=0; failed=""; got=""
|
||||||
|
|
||||||
@@ -47,22 +54,27 @@ for entry in $pkgs; do
|
|||||||
out="$OUTDIR/${nixattr}.toml"
|
out="$OUTDIR/${nixattr}.toml"
|
||||||
|
|
||||||
printf '%-24s ' "$nixattr" >&2
|
printf '%-24s ' "$nixattr" >&2
|
||||||
if "$here/nix-import.sh" "$nixattr" > "$out.tmp" 2>/dev/null && [ -s "$out.tmp" ]; then
|
done_pkg=""
|
||||||
mv "$out.tmp" "$out"
|
# Orden de fuentes según PREFER (default nix, ~100% Rust/Go). PREFER=alpine antepone Alpine para
|
||||||
nix_n=$((nix_n + 1)); got="$got $nixattr"
|
# tandas C: el import de nix de un C tiene éxito (tarball) pero SIN los parches musl ⇒ rompería al
|
||||||
echo "✓ nix" >&2
|
# construir; Alpine los TRAE. Cada "tier" es una etiqueta y el comando que produce la receta.
|
||||||
elif "$here/alpine-import.sh" "$alpinepkg" main > "$out.tmp" 2>/dev/null && [ -s "$out.tmp" ]; then
|
for tier in $TIERS; do
|
||||||
mv "$out.tmp" "$out"
|
case $tier in
|
||||||
alpine_n=$((alpine_n + 1)); got="$got $nixattr"
|
nix) src="nix"; cmd_out=$("$here/nix-import.sh" "$nixattr" 2>/dev/null) || cmd_out="" ;;
|
||||||
echo "✓ alpine/main (parches musl)" >&2
|
alpine-main) src="alpine/main"; cmd_out=$("$here/alpine-import.sh" "$alpinepkg" main 2>/dev/null) || cmd_out="" ;;
|
||||||
elif "$here/alpine-import.sh" "$alpinepkg" community > "$out.tmp" 2>/dev/null && [ -s "$out.tmp" ]; then
|
alpine-comm*) src="alpine/community"; cmd_out=$("$here/alpine-import.sh" "$alpinepkg" community 2>/dev/null) || cmd_out="" ;;
|
||||||
mv "$out.tmp" "$out"
|
esac
|
||||||
alpine_n=$((alpine_n + 1)); got="$got $nixattr"
|
if [ -n "$cmd_out" ]; then
|
||||||
echo "✓ alpine/community (parches musl)" >&2
|
printf '%s\n' "$cmd_out" > "$out"
|
||||||
else
|
case $tier in nix) nix_n=$((nix_n + 1)) ;; *) alpine_n=$((alpine_n + 1)) ;; esac
|
||||||
rm -f "$out.tmp"
|
got="$got $nixattr"; done_pkg=1
|
||||||
|
echo "✓ $src" >&2
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -z "$done_pkg" ]; then
|
||||||
failed="$failed $nixattr"
|
failed="$failed $nixattr"
|
||||||
echo "✗ ni nix ni Alpine" >&2
|
echo "✗ ninguna fuente" >&2
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Tanda CLI C clásico — Etapa G. Tier 2 de la escalera (C/autotools → import-alpine, trae parches musl).
|
||||||
|
# Uso: PREFER=alpine OUTDIR=recipes/incoming scripts/import-batch.sh -f tandas/cli-c.txt
|
||||||
|
# Luego: scripts/pin-recipes.sh recipes/incoming/*.toml && build (medir build-yield C real).
|
||||||
|
# Sintaxis: un paquete por línea; '#' comenta; `nixattr=alpinepkg` si los nombres difieren.
|
||||||
|
# Evita por ahora los que piden ncurses (less/nano/htop) hasta portar esa lib al corpus.
|
||||||
|
tree
|
||||||
|
which
|
||||||
|
sed
|
||||||
|
gawk
|
||||||
|
gzip
|
||||||
|
tar
|
||||||
|
jq
|
||||||
|
file
|
||||||
Reference in New Issue
Block a user