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 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 #[serde(rename = "openvmm_hcl")]
60 pub bin: PathBuf,
61 #[serde(rename = "openvmm_hcl.dbg")]
62 pub dbg: Option<PathBuf>,
63}
64
65impl Artifact for OpenvmmHclOutput {}
66
67#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
68pub struct OpenvmmHclBuildParams {
69 pub target: CommonTriple,
70 pub profile: OpenvmmHclBuildProfile,
71 pub features: BTreeSet<OpenvmmHclFeature>,
72 pub no_split_dbg_info: bool,
73 pub max_trace_level: MaxTraceLevel,
74}
75
76flowey_request! {
77 pub struct Request {
78 pub build_params: OpenvmmHclBuildParams,
79 pub openvmm_hcl_output: WriteVar<OpenvmmHclOutput>,
80 }
81}
82
83new_flow_node!(struct Node);
84
85impl FlowNode for Node {
86 type Request = Request;
87
88 fn imports(ctx: &mut ImportCtx<'_>) {
89 ctx.import::<crate::run_cargo_build::Node>();
90 ctx.import::<crate::init_openvmm_magicpath_openhcl_sysroot::Node>();
91 }
92
93 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
94 let requests = group_by(
95 requests
96 .into_iter()
97 .map(|r| (r.build_params, r.openvmm_hcl_output)),
98 );
99
100 for (
103 OpenvmmHclBuildParams {
104 target,
105 profile,
106 features,
107 no_split_dbg_info,
108 max_trace_level,
109 },
110 outvars,
111 ) in requests
112 {
113 let mut pre_build_deps = Vec::new();
114
115 let target = target.as_triple();
116
117 let arch = CommonArch::from_triple(&target)
118 .with_context(|| format!("cannot build openvmm_hcl on {}", target.architecture))?;
119
120 let openhcl_deps_path = ctx
121 .reqv(|v| crate::init_openvmm_magicpath_openhcl_sysroot::Request { arch, path: v });
122
123 pre_build_deps.push(openhcl_deps_path.into_side_effect());
125
126 let mut features = features
127 .into_iter()
128 .map(|f| match f {
129 OpenvmmHclFeature::Gdb => "gdb".into(),
130 OpenvmmHclFeature::MiSecure => "mi-secure".into(),
131 OpenvmmHclFeature::Tpm => "tpm".into(),
132 OpenvmmHclFeature::LocalOnlyCustom(s) => s,
133 })
134 .collect::<Vec<String>>();
135
136 features.extend(max_trace_level.features());
137
138 let extra_env = Some(ReadVar::from_static(crate::common::openhcl_build_env()));
142
143 let output = ctx.reqv(|v| crate::run_cargo_build::Request {
144 crate_name: "openvmm_hcl".into(),
145 out_name: "openvmm_hcl".into(),
146 crate_type: flowey_lib_common::run_cargo_build::CargoCrateType::Bin,
147 profile: match profile {
148 OpenvmmHclBuildProfile::Debug => crate::run_cargo_build::BuildProfile::Debug,
149 OpenvmmHclBuildProfile::Release => {
150 crate::run_cargo_build::BuildProfile::Release
151 }
152 OpenvmmHclBuildProfile::OpenvmmHclShip => {
153 crate::run_cargo_build::BuildProfile::UnderhillShip
154 }
155 },
156 features: CargoFeatureSet::Specific(features),
157 target,
158 no_split_dbg_info,
159 extra_env,
160 pre_build_deps,
161 output: v,
162 });
163
164 ctx.emit_minor_rust_step("report built openvmm_hcl", |ctx| {
165 let outvars = outvars.claim(ctx);
166 let output = output.claim(ctx);
167 move |rt| {
168 let output = match rt.read(output) {
169 crate::run_cargo_build::CargoBuildOutput::ElfBin { bin, dbg } => {
170 OpenvmmHclOutput { bin, dbg }
171 }
172 _ => unreachable!(),
173 };
174
175 rt.write_all(outvars, &output);
176 }
177 });
178 }
179
180 Ok(())
181 }
182}