1use crate::common::CommonArch;
7use crate::common::CommonTriple;
8use flowey::node::prelude::*;
9use flowey_lib_common::run_cargo_build::CargoFeatureSet;
10use std::collections::BTreeMap;
11use std::collections::BTreeSet;
12
13#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
14pub enum OpenvmmHclFeature {
15 Gdb,
16 MiSecure,
17 Tpm,
18 ProductPolicy,
19 LocalOnlyCustom(String),
20}
21
22#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
23pub enum OpenvmmHclBuildProfile {
24 Debug,
25 Release,
26 OpenvmmHclShip,
27}
28
29#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
30pub enum MaxTraceLevel {
31 Trace,
32 Debug,
33 Info,
34 Warn,
35 Error,
36 Off,
37}
38
39impl MaxTraceLevel {
40 pub fn features(&self) -> Vec<String> {
41 let name = match self {
42 MaxTraceLevel::Trace => return Vec::new(),
43 MaxTraceLevel::Debug => "debug",
44 MaxTraceLevel::Info => "info",
45 MaxTraceLevel::Warn => "warn",
46 MaxTraceLevel::Error => "error",
47 MaxTraceLevel::Off => "off",
48 };
49 vec![
52 format!("tracing/max_level_{}", name),
53 format!("tracing/release_max_level_{}", name),
54 ]
55 }
56}
57
58#[derive(Serialize, Deserialize)]
59pub struct OpenvmmHclOutput {
60 #[serde(rename = "openvmm_hcl")]
61 pub bin: PathBuf,
62 #[serde(rename = "openvmm_hcl.dbg")]
63 pub dbg: Option<PathBuf>,
64}
65
66impl Artifact for OpenvmmHclOutput {}
67
68#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
69pub struct OpenvmmHclBuildParams {
70 pub target: CommonTriple,
71 pub profile: OpenvmmHclBuildProfile,
72 pub features: BTreeSet<OpenvmmHclFeature>,
73 pub no_split_dbg_info: bool,
74 pub max_trace_level: MaxTraceLevel,
75}
76
77flowey_request! {
78 pub struct Request {
79 pub build_params: OpenvmmHclBuildParams,
80 pub openvmm_hcl_output: WriteVar<OpenvmmHclOutput>,
81 }
82}
83
84new_flow_node!(struct Node);
85
86impl FlowNode for Node {
87 type Request = Request;
88
89 fn imports(ctx: &mut ImportCtx<'_>) {
90 ctx.import::<crate::run_cargo_build::Node>();
91 ctx.import::<crate::init_openvmm_magicpath_openhcl_sysroot::Node>();
92 }
93
94 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
95 let requests = requests
97 .into_iter()
98 .fold(BTreeMap::<_, Vec<_>>::new(), |mut m, r| {
99 let Request {
100 build_params,
101 openvmm_hcl_output,
102 } = r;
103 m.entry(build_params).or_default().push(openvmm_hcl_output);
104 m
105 });
106
107 for (
110 OpenvmmHclBuildParams {
111 target,
112 profile,
113 features,
114 no_split_dbg_info,
115 max_trace_level,
116 },
117 outvars,
118 ) in requests
119 {
120 let mut pre_build_deps = Vec::new();
121
122 let target = target.as_triple();
123
124 let arch = CommonArch::from_triple(&target)
125 .with_context(|| format!("cannot build openvmm_hcl on {}", target.architecture))?;
126
127 let openhcl_deps_path = ctx
128 .reqv(|v| crate::init_openvmm_magicpath_openhcl_sysroot::Request { arch, path: v });
129
130 pre_build_deps.push(openhcl_deps_path.into_side_effect());
132
133 let mut features = features
134 .into_iter()
135 .map(|f| match f {
136 OpenvmmHclFeature::Gdb => "gdb".into(),
137 OpenvmmHclFeature::MiSecure => "mi-secure".into(),
138 OpenvmmHclFeature::Tpm => "tpm".into(),
139 OpenvmmHclFeature::ProductPolicy => "product_policy".into(),
140 OpenvmmHclFeature::LocalOnlyCustom(s) => s,
141 })
142 .collect::<Vec<String>>();
143
144 features.extend(max_trace_level.features());
145
146 let extra_env = Some(ReadVar::from_static(
150 [
151 ("CC_FORCE_DISABLE".to_string(), "1".to_string()),
152 (
153 "CMAKE".to_string(),
154 "cmake-is-forbidden-during-openvmm-hcl-build".to_string(),
155 ),
156 ]
157 .into_iter()
158 .collect(),
159 ));
160
161 let output = ctx.reqv(|v| crate::run_cargo_build::Request {
162 crate_name: "openvmm_hcl".into(),
163 out_name: "openvmm_hcl".into(),
164 crate_type: flowey_lib_common::run_cargo_build::CargoCrateType::Bin,
165 profile: match profile {
166 OpenvmmHclBuildProfile::Debug => crate::run_cargo_build::BuildProfile::Debug,
167 OpenvmmHclBuildProfile::Release => {
168 crate::run_cargo_build::BuildProfile::Release
169 }
170 OpenvmmHclBuildProfile::OpenvmmHclShip => {
171 crate::run_cargo_build::BuildProfile::UnderhillShip
172 }
173 },
174 features: CargoFeatureSet::Specific(features),
175 target,
176 no_split_dbg_info,
177 extra_env,
178 pre_build_deps,
179 output: v,
180 });
181
182 ctx.emit_minor_rust_step("report built openvmm_hcl", |ctx| {
183 let outvars = outvars.claim(ctx);
184 let output = output.claim(ctx);
185 move |rt| {
186 let output = match rt.read(output) {
187 crate::run_cargo_build::CargoBuildOutput::ElfBin { bin, dbg } => {
188 OpenvmmHclOutput { bin, dbg }
189 }
190 _ => unreachable!(),
191 };
192
193 for var in outvars {
194 rt.write(var, &output);
195 }
196 }
197 });
198 }
199
200 Ok(())
201 }
202}