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::run_cargo_build::CargoFeatureSet;
10use std::collections::BTreeMap;
11use std::collections::BTreeSet;
12
13#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
14pub enum OpenvmmFeature {
15    Gdb,
16    Tpm,
17    UnstableWhp,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
21pub struct OpenvmmBuildParams {
22    pub profile: CommonProfile,
23    pub target: CommonTriple,
24    pub features: BTreeSet<OpenvmmFeature>,
25}
26
27#[derive(Serialize, Deserialize)]
28#[serde(untagged)]
29pub enum OpenvmmOutput {
30    WindowsBin {
31        #[serde(rename = "openvmm.exe")]
32        exe: PathBuf,
33        #[serde(rename = "openvmm.pdb")]
34        pdb: PathBuf,
35    },
36    LinuxBin {
37        #[serde(rename = "openvmm")]
38        bin: PathBuf,
39        #[serde(rename = "openvmm.dbg")]
40        dbg: PathBuf,
41    },
42}
43
44impl Artifact for OpenvmmOutput {}
45
46flowey_request! {
47    pub struct Request {
48        pub params: OpenvmmBuildParams,
49        pub version: Option<ReadVar<(u16, u16, u16, u16)>>,
50        pub openvmm: WriteVar<OpenvmmOutput>,
51    }
52}
53
54new_flow_node!(struct Node);
55
56impl FlowNode for Node {
57    type Request = Request;
58
59    fn imports(ctx: &mut ImportCtx<'_>) {
60        ctx.import::<crate::run_cargo_build::Node>();
61        ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
62    }
63
64    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
65        let mut pre_build_deps = Vec::new();
66
67        // TODO: install build tools for other platforms
68        if matches!(
69            ctx.platform(),
70            FlowPlatform::Linux(FlowPlatformLinuxDistro::Ubuntu)
71        ) {
72            pre_build_deps.push(ctx.reqv(|v| {
73                flowey_lib_common::install_dist_pkg::Request::Install {
74                    package_names: vec!["libssl-dev".into(), "pkg-config".into()],
75                    done: v,
76                }
77            }));
78        }
79
80        for Request {
81            params:
82                OpenvmmBuildParams {
83                    profile,
84                    target,
85                    features,
86                },
87            version,
88            openvmm: openvmm_bin,
89        } in requests
90        {
91            // Set the OPENVMM_* env vars for version information (if provided).
92            let extra_env = version.map(|version| {
93                ctx.emit_minor_rust_stepv("set openvmm version env vars", |ctx| {
94                    let version = version.claim(ctx);
95                    |rt| {
96                        let mut env = BTreeMap::new();
97                        let (major, minor, patch, revision) = rt.read(version);
98                        env.insert("OPENVMM_MAJOR".into(), major.to_string());
99                        env.insert("OPENVMM_MINOR".into(), minor.to_string());
100                        env.insert("OPENVMM_PATCH".into(), patch.to_string());
101                        env.insert("OPENVMM_REVISION".into(), revision.to_string());
102                        env
103                    }
104                })
105            });
106
107            let output = ctx.reqv(|v| crate::run_cargo_build::Request {
108                crate_name: "openvmm".into(),
109                out_name: "openvmm".into(),
110                crate_type: flowey_lib_common::run_cargo_build::CargoCrateType::Bin,
111                profile: profile.into(),
112                features: CargoFeatureSet::Specific(
113                    features
114                        .into_iter()
115                        .map(|f| {
116                            match f {
117                                OpenvmmFeature::Gdb => "gdb",
118                                OpenvmmFeature::Tpm => "tpm",
119                                OpenvmmFeature::UnstableWhp => "unstable_whp",
120                            }
121                            .into()
122                        })
123                        .collect(),
124                ),
125                target: target.as_triple(),
126                no_split_dbg_info: false,
127                extra_env,
128                pre_build_deps: pre_build_deps.clone(),
129                output: v,
130            });
131
132            ctx.emit_minor_rust_step("report built openvmm", |ctx| {
133                let openvmm_bin = openvmm_bin.claim(ctx);
134                let output = output.claim(ctx);
135                move |rt| {
136                    let output = match rt.read(output) {
137                        crate::run_cargo_build::CargoBuildOutput::WindowsBin { exe, pdb } => {
138                            OpenvmmOutput::WindowsBin { exe, pdb }
139                        }
140                        crate::run_cargo_build::CargoBuildOutput::ElfBin { bin, dbg } => {
141                            OpenvmmOutput::LinuxBin {
142                                bin,
143                                dbg: dbg.unwrap(),
144                            }
145                        }
146                        _ => unreachable!(),
147                    };
148
149                    rt.write(openvmm_bin, &output);
150                }
151            });
152        }
153
154        Ok(())
155    }
156}