1use crate::common::CommonArch;
7use crate::common::CommonTriple;
8use flowey::node::prelude::*;
9use flowey_lib_common::_util::group_by;
10use flowey_lib_common::run_cargo_build::CargoFeatureSet;
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 = group_by(
96 requests
97 .into_iter()
98 .map(|r| (r.build_params, r.openvmm_hcl_output)),
99 );
100
101 for (
104 OpenvmmHclBuildParams {
105 target,
106 profile,
107 features,
108 no_split_dbg_info,
109 max_trace_level,
110 },
111 outvars,
112 ) in requests
113 {
114 let mut pre_build_deps = Vec::new();
115
116 let target = target.as_triple();
117
118 let arch = CommonArch::from_triple(&target)
119 .with_context(|| format!("cannot build openvmm_hcl on {}", target.architecture))?;
120
121 let openhcl_deps_path = ctx
122 .reqv(|v| crate::init_openvmm_magicpath_openhcl_sysroot::Request { arch, path: v });
123
124 pre_build_deps.push(openhcl_deps_path.into_side_effect());
126
127 let mut features = features
128 .into_iter()
129 .map(|f| match f {
130 OpenvmmHclFeature::Gdb => "gdb".into(),
131 OpenvmmHclFeature::MiSecure => "mi-secure".into(),
132 OpenvmmHclFeature::Tpm => "tpm".into(),
133 OpenvmmHclFeature::ProductPolicy => "product_policy".into(),
134 OpenvmmHclFeature::LocalOnlyCustom(s) => s,
135 })
136 .collect::<Vec<String>>();
137
138 features.extend(max_trace_level.features());
139
140 let extra_env = Some(ReadVar::from_static(crate::common::openhcl_build_env()));
144
145 let output = ctx.reqv(|v| crate::run_cargo_build::Request {
146 crate_name: "openvmm_hcl".into(),
147 out_name: "openvmm_hcl".into(),
148 crate_type: flowey_lib_common::run_cargo_build::CargoCrateType::Bin,
149 profile: match profile {
150 OpenvmmHclBuildProfile::Debug => crate::run_cargo_build::BuildProfile::Debug,
151 OpenvmmHclBuildProfile::Release => {
152 crate::run_cargo_build::BuildProfile::Release
153 }
154 OpenvmmHclBuildProfile::OpenvmmHclShip => {
155 crate::run_cargo_build::BuildProfile::UnderhillShip
156 }
157 },
158 features: CargoFeatureSet::Specific(features),
159 target,
160 no_split_dbg_info,
161 extra_env,
162 pre_build_deps,
163 output: v,
164 });
165
166 ctx.emit_minor_rust_step("report built openvmm_hcl", |ctx| {
167 let outvars = outvars.claim(ctx);
168 let output = output.claim(ctx);
169 move |rt| {
170 let output = match rt.read(output) {
171 crate::run_cargo_build::CargoBuildOutput::ElfBin { bin, dbg } => {
172 OpenvmmHclOutput { bin, dbg }
173 }
174 _ => unreachable!(),
175 };
176
177 rt.write_all(outvars, &output);
178 }
179 });
180 }
181
182 Ok(())
183 }
184}