flowey_lib_hvlite/
build_openvmm.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Build `openvmm` binaries
5
6use crate::run_cargo_build::common::CommonProfile;
7use crate::run_cargo_build::common::CommonTriple;
8use flowey::node::prelude::*;
9use flowey_lib_common::run_cargo_build::CargoFeatureSet;
10use std::collections::BTreeSet;
11
12#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
13pub enum OpenvmmFeature {
14    Gdb,
15    Tpm,
16    UnstableWhp,
17}
18
19#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
20pub struct OpenvmmBuildParams {
21    pub profile: CommonProfile,
22    pub target: CommonTriple,
23    pub features: BTreeSet<OpenvmmFeature>,
24}
25
26#[derive(Serialize, Deserialize)]
27#[serde(untagged)]
28pub enum OpenvmmOutput {
29    WindowsBin {
30        #[serde(rename = "openvmm.exe")]
31        exe: PathBuf,
32        #[serde(rename = "openvmm.pdb")]
33        pdb: PathBuf,
34    },
35    LinuxBin {
36        #[serde(rename = "openvmm")]
37        bin: PathBuf,
38        #[serde(rename = "openvmm.dbg")]
39        dbg: PathBuf,
40    },
41}
42
43impl Artifact for OpenvmmOutput {}
44
45flowey_request! {
46    pub struct Request {
47        pub params: OpenvmmBuildParams,
48        pub openvmm: WriteVar<OpenvmmOutput>,
49    }
50}
51
52new_flow_node!(struct Node);
53
54impl FlowNode for Node {
55    type Request = Request;
56
57    fn imports(ctx: &mut ImportCtx<'_>) {
58        ctx.import::<crate::run_cargo_build::Node>();
59        ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
60    }
61
62    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
63        let installed_apt_deps =
64            ctx.reqv(|v| flowey_lib_common::install_dist_pkg::Request::Install {
65                package_names: vec!["libssl-dev".into(), "build-essential".into()],
66                done: v,
67            });
68
69        for Request {
70            params:
71                OpenvmmBuildParams {
72                    profile,
73                    target,
74                    features,
75                },
76            openvmm: openvmm_bin,
77        } in requests
78        {
79            let mut pre_build_deps = vec![installed_apt_deps.clone()];
80
81            // TODO: also need to take into account any default features in
82            // openvmm's Cargo.toml?
83            //
84            // maybe we can do something clever and parse the openvmm Cargo.toml
85            // file to discover these defaults?
86            for feat in &features {
87                match feat {
88                    OpenvmmFeature::Gdb => {}
89                    OpenvmmFeature::Tpm => pre_build_deps.push(ctx.reqv(|v| {
90                        flowey_lib_common::install_dist_pkg::Request::Install {
91                            package_names: vec!["build-essential".into()],
92                            done: v,
93                        }
94                    })),
95                    OpenvmmFeature::UnstableWhp => {}
96                }
97            }
98
99            let output = ctx.reqv(|v| crate::run_cargo_build::Request {
100                crate_name: "openvmm".into(),
101                out_name: "openvmm".into(),
102                crate_type: flowey_lib_common::run_cargo_build::CargoCrateType::Bin,
103                profile: profile.into(),
104                features: CargoFeatureSet::Specific(
105                    features
106                        .into_iter()
107                        .map(|f| {
108                            match f {
109                                OpenvmmFeature::Gdb => "gdb",
110                                OpenvmmFeature::Tpm => "tpm",
111                                OpenvmmFeature::UnstableWhp => "unstable_whp",
112                            }
113                            .into()
114                        })
115                        .collect(),
116                ),
117                target: target.as_triple(),
118                no_split_dbg_info: false,
119                extra_env: None,
120                pre_build_deps,
121                output: v,
122            });
123
124            ctx.emit_minor_rust_step("report built openvmm", |ctx| {
125                let openvmm_bin = openvmm_bin.claim(ctx);
126                let output = output.claim(ctx);
127                move |rt| {
128                    let output = match rt.read(output) {
129                        crate::run_cargo_build::CargoBuildOutput::WindowsBin { exe, pdb } => {
130                            OpenvmmOutput::WindowsBin { exe, pdb }
131                        }
132                        crate::run_cargo_build::CargoBuildOutput::ElfBin { bin, dbg } => {
133                            OpenvmmOutput::LinuxBin {
134                                bin,
135                                dbg: dbg.unwrap(),
136                            }
137                        }
138                        _ => unreachable!(),
139                    };
140
141                    rt.write(openvmm_bin, &output);
142                }
143            });
144        }
145
146        Ok(())
147    }
148}