sergio/takana
> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…
⎇ 8bf1623044075274682e4351a0f8e120047c2bed
crates/hammer-core/src/recipe.rs
Historia
Quién tocó qué
crudo
Scaffold inicial: workspace Rust + SDDs completos
1//! La `Recipe`: descripción pura de un build. Ver `docs/02-build-lab.md` §1.
2
3use serde::{Deserialize, Serialize};
4
5use crate::hash::ArtifactHash;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct Recipe {
9 pub name: String,
10 pub version: String,
11 pub source: Source,
12 pub build: Build,
13 #[serde(default)]
14 pub deps: Deps,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct Source {
19 pub repo: String,
20 /// Commit FIJADO. Nunca "HEAD". Ver ADR 0006.
21 pub commit: String,
22 #[serde(default)]
23 pub patches: Vec<String>,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct Build {
28 #[serde(default)]
29 pub compiler: Compiler,
30 #[serde(default = "default_target")]
31 pub target: String,
32 #[serde(default)]
33 pub link: LinkMode,
34 #[serde(default)]
35 pub flags: Vec<String>,
36}
37
38#[derive(Debug, Clone, Default, Serialize, Deserialize)]
39pub struct Deps {
40 #[serde(default)]
41 pub build: Vec<String>,
42 #[serde(default)]
43 pub runtime: Vec<String>,
44}
45
46/// Compilador del lab, POR RECETA (no global). `zig-cc` por defecto; escotilla a clang/gcc
47/// para paquetes con gcc-ismos. Ver ADR 0003.
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
49#[serde(rename_all = "kebab-case")]
50pub enum Compiler {
51 #[default]
52 ZigCc,
53 Clang,
54 Gcc,
55}
56
57impl Compiler {
58 pub fn as_str(&self) -> &'static str {
59 match self {
60 Compiler::ZigCc => "zig-cc",
61 Compiler::Clang => "clang",
62 Compiler::Gcc => "gcc",
63 }
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
68#[serde(rename_all = "lowercase")]
69pub enum LinkMode {
70 #[default]
71 Static,
72 Dynamic,
73}
74
75fn default_target() -> String {
76 "x86_64-linux-musl".to_string()
77}
78
79impl Recipe {
80 pub fn from_toml(_s: &str) -> crate::Result<Recipe> {
81 // TODO(fase-0): parsear TOML. Por ahora el parsing real lo añadiremos al implementar
82 // `hammer build`; el contrato (esta struct) ya está fijado.
83 Err(crate::Error::Recipe(
84 "parsing de receta TOML pendiente (Fase 0)".into(),
85 ))
86 }
87
88 /// Las entradas canónicas que alimentan el `ArtifactHash` de esta receta.
89 /// NOTA: el hash final también incorpora los hashes de las deps de build (recursivo),
90 /// que el lab resuelve antes de llamar aquí. Ver `docs/02-build-lab.md` §2 y §5.
91 pub fn hash_inputs(&self, dep_hashes: &[ArtifactHash]) -> Vec<Vec<u8>> {
92 let mut v: Vec<Vec<u8>> = vec![
93 self.source.commit.as_bytes().to_vec(),
94 self.build.compiler.as_str().as_bytes().to_vec(),
95 self.build.target.as_bytes().to_vec(),
96 format!("{:?}", self.build.link).into_bytes(),
97 ];
98 for p in &self.source.patches {
99 v.push(p.as_bytes().to_vec());
100 }
101 for f in &self.build.flags {
102 v.push(f.as_bytes().to_vec());
103 }
104 for d in dep_hashes {
105 v.push(d.as_str().as_bytes().to_vec());
106 }
107 v
108 }
109}