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