flowey_lib_hvlite/
build_openvmm_hcl.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Build `openvmm_hcl` binaries (NOT IGVM FILES!)
5
6use 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 std::collections::BTreeMap;
11use std::collections::BTreeSet;
12
13#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
14pub enum OpenvmmHclFeature {
15    Gdb,
16    Tpm,
17    LocalOnlyCustom(String),
18}
19
20#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
21pub enum OpenvmmHclBuildProfile {
22    Debug,
23    Release,
24    OpenvmmHclShip,
25}
26
27#[derive(Serialize, Deserialize)]
28pub struct OpenvmmHclOutput {
29    pub bin: PathBuf,
30    pub dbg: Option<PathBuf>,
31}
32
33#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
34pub struct OpenvmmHclBuildParams {
35    pub target: CommonTriple,
36    pub profile: OpenvmmHclBuildProfile,
37    pub features: BTreeSet<OpenvmmHclFeature>,
38    pub no_split_dbg_info: bool,
39}
40
41flowey_request! {
42    pub struct Request {
43        pub build_params: OpenvmmHclBuildParams,
44        pub openvmm_hcl_output: WriteVar<OpenvmmHclOutput>,
45    }
46}
47
48new_flow_node!(struct Node);
49
50impl FlowNode for Node {
51    type Request = Request;
52
53    fn imports(ctx: &mut ImportCtx<'_>) {
54        ctx.import::<crate::run_cargo_build::Node>();
55        ctx.import::<crate::init_openvmm_magicpath_openhcl_sysroot::Node>();
56    }
57
58    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
59        // de-dupe incoming requests
60        let requests = requests
61            .into_iter()
62            .fold(BTreeMap::<_, Vec<_>>::new(), |mut m, r| {
63                let Request {
64                    build_params,
65                    openvmm_hcl_output,
66                } = r;
67                m.entry(build_params).or_default().push(openvmm_hcl_output);
68                m
69            });
70
71        // -- end of req processing -- //
72
73        for (
74            OpenvmmHclBuildParams {
75                target,
76                profile,
77                features,
78                no_split_dbg_info,
79            },
80            outvars,
81        ) in requests
82        {
83            let mut pre_build_deps = Vec::new();
84
85            let target = target.as_triple();
86
87            let arch = CommonArch::from_triple(&target).ok_or_else(|| {
88                anyhow::anyhow!("cannot build openvmm_hcl on {}", target.architecture)
89            })?;
90
91            let openhcl_deps_path =
92                ctx.reqv(|v| crate::init_openvmm_magicpath_openhcl_sysroot::Request {
93                    arch: match arch {
94                        CommonArch::X86_64 => OpenvmmSysrootArch::X64,
95                        CommonArch::Aarch64 => OpenvmmSysrootArch::Aarch64,
96                    },
97                    path: v,
98                });
99
100            // required due to ambient dependencies in openvmm_hcl's source code
101            pre_build_deps.push(openhcl_deps_path.clone().into_side_effect());
102
103            let output = ctx.reqv(|v| crate::run_cargo_build::Request {
104                crate_name: "openvmm_hcl".into(),
105                out_name: "openvmm_hcl".into(),
106                crate_type: flowey_lib_common::run_cargo_build::CargoCrateType::Bin,
107                profile: match profile {
108                    OpenvmmHclBuildProfile::Debug => crate::run_cargo_build::BuildProfile::Debug,
109                    OpenvmmHclBuildProfile::Release => {
110                        crate::run_cargo_build::BuildProfile::Release
111                    }
112                    OpenvmmHclBuildProfile::OpenvmmHclShip => {
113                        crate::run_cargo_build::BuildProfile::UnderhillShip
114                    }
115                },
116                features: features
117                    .iter()
118                    .map(|f| {
119                        match f {
120                            OpenvmmHclFeature::Gdb => "gdb",
121                            OpenvmmHclFeature::Tpm => "tpm",
122                            OpenvmmHclFeature::LocalOnlyCustom(s) => s,
123                        }
124                        .into()
125                    })
126                    .collect(),
127                target,
128                no_split_dbg_info,
129                extra_env: None,
130                pre_build_deps,
131                output: v,
132            });
133
134            ctx.emit_minor_rust_step("report built openvmm_hcl", |ctx| {
135                let outvars = outvars.claim(ctx);
136                let output = output.claim(ctx);
137                move |rt| {
138                    let output = match rt.read(output) {
139                        crate::run_cargo_build::CargoBuildOutput::ElfBin { bin, dbg } => {
140                            OpenvmmHclOutput { bin, dbg }
141                        }
142                        _ => unreachable!(),
143                    };
144
145                    for var in outvars {
146                        rt.write(var, &output);
147                    }
148                }
149            });
150        }
151
152        Ok(())
153    }
154}