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