Skip to main content

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::common::CommonProfile;
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, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
14pub enum OpenvmmFeature {
15    Gdb,
16    Tpm,
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        #[serde(default, skip_serializing_if = "Option::is_none")]
34        pdb: Option<PathBuf>,
35    },
36    LinuxBin {
37        #[serde(rename = "openvmm")]
38        bin: PathBuf,
39        #[serde(rename = "openvmm.dbg")]
40        dbg: Option<PathBuf>,
41    },
42}
43
44impl Artifact for OpenvmmOutput {}
45
46flowey_request! {
47    pub struct Request {
48        pub params: OpenvmmBuildParams,
49        pub openvmm: WriteVar<OpenvmmOutput>,
50    }
51}
52
53new_flow_node!(struct Node);
54
55impl FlowNode for Node {
56    type Request = Request;
57
58    fn imports(ctx: &mut ImportCtx<'_>) {
59        ctx.import::<crate::run_cargo_build::Node>();
60        ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
61    }
62
63    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
64        let requests = group_by(requests.into_iter().map(|r| (r.params, r.openvmm)));
65        if requests.is_empty() {
66            return Ok(());
67        }
68        let mut pre_build_deps = Vec::new();
69
70        // TODO: install build tools for other platforms
71        if matches!(
72            ctx.platform(),
73            FlowPlatform::Linux(FlowPlatformLinuxDistro::Ubuntu)
74        ) {
75            let mut package_names = crate::common::openssl_dev_packages(ctx.platform())?;
76            package_names.push("pkg-config".into());
77            pre_build_deps.push(ctx.reqv(|v| {
78                flowey_lib_common::install_dist_pkg::Request::Install {
79                    package_names,
80                    done: v,
81                }
82            }));
83        }
84
85        for (
86            OpenvmmBuildParams {
87                profile,
88                target,
89                features,
90            },
91            openvmm_bin,
92        ) in requests
93        {
94            let output = ctx.reqv(|v| crate::run_cargo_build::Request {
95                crate_name: "openvmm".into(),
96                out_name: "openvmm".into(),
97                crate_type: flowey_lib_common::run_cargo_build::CargoCrateType::Bin,
98                profile: profile.into(),
99                features: CargoFeatureSet::Specific(
100                    features
101                        .into_iter()
102                        .map(|f| {
103                            match f {
104                                OpenvmmFeature::Gdb => "gdb",
105                                OpenvmmFeature::Tpm => "tpm",
106                            }
107                            .into()
108                        })
109                        .collect(),
110                ),
111                target: target.as_triple(),
112                no_split_dbg_info: false,
113                extra_env: None,
114                pre_build_deps: pre_build_deps.clone(),
115                output: v,
116            });
117
118            ctx.emit_minor_rust_step("report built openvmm", |ctx| {
119                let openvmm_bin = openvmm_bin.claim(ctx);
120                let output = output.claim(ctx);
121                move |rt| {
122                    let output = match rt.read(output) {
123                        crate::run_cargo_build::CargoBuildOutput::WindowsBin { exe, pdb } => {
124                            OpenvmmOutput::WindowsBin { exe, pdb }
125                        }
126                        crate::run_cargo_build::CargoBuildOutput::ElfBin { bin, dbg } => {
127                            OpenvmmOutput::LinuxBin { bin, dbg }
128                        }
129                        _ => unreachable!(),
130                    };
131
132                    rt.write_all(openvmm_bin, &output);
133                }
134            });
135        }
136
137        Ok(())
138    }
139}