Skip to main content

flowey_lib_hvlite/
build_sidecar.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Build `sidecar` binaries
5
6use crate::common::CommonArch;
7use crate::run_cargo_build::BuildProfile;
8use flowey::node::prelude::*;
9use std::collections::BTreeMap;
10
11#[derive(Serialize, Deserialize)]
12pub struct SidecarOutput {
13    #[serde(rename = "sidecar")]
14    pub bin: PathBuf,
15    #[serde(rename = "sidecar.dbg")]
16    pub dbg: PathBuf,
17}
18
19#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
20pub enum SidecarBuildProfile {
21    Debug,
22    Release,
23}
24
25#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
26pub struct SidecarBuildParams {
27    pub arch: CommonArch,
28    pub profile: SidecarBuildProfile,
29}
30
31flowey_request! {
32    pub struct Request {
33        pub build_params: SidecarBuildParams,
34        pub sidecar: WriteVar<SidecarOutput>,
35    }
36}
37
38new_flow_node!(struct Node);
39
40impl FlowNode for Node {
41    type Request = Request;
42
43    fn imports(ctx: &mut ImportCtx<'_>) {
44        ctx.import::<crate::run_cargo_build::Node>();
45    }
46
47    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
48        // de-dupe incoming requests
49        let requests = requests
50            .into_iter()
51            .fold(BTreeMap::<_, Vec<_>>::new(), |mut m, r| {
52                let Request {
53                    build_params,
54                    sidecar,
55                } = r;
56                m.entry(build_params).or_default().push(sidecar);
57                m
58            });
59
60        for (SidecarBuildParams { arch, profile }, sidecar) in requests {
61            let target = target_lexicon::Triple {
62                architecture: arch.as_arch(),
63                operating_system: target_lexicon::OperatingSystem::None_,
64                environment: target_lexicon::Environment::Unknown,
65                vendor: target_lexicon::Vendor::Custom(target_lexicon::CustomVendor::Static(
66                    "minimal_rt",
67                )),
68                binary_format: target_lexicon::BinaryFormat::Unknown,
69            };
70
71            // We use special profiles for boot, convert from the standard ones:
72            let profile = match profile {
73                SidecarBuildProfile::Debug => BuildProfile::BootDev,
74                SidecarBuildProfile::Release => BuildProfile::BootRelease,
75            };
76
77            let output = ctx.reqv(|v| crate::run_cargo_build::Request {
78                crate_name: "sidecar".into(),
79                out_name: "sidecar".into(),
80                crate_type: flowey_lib_common::run_cargo_build::CargoCrateType::Bin,
81                profile,
82                features: Default::default(),
83                target,
84                no_split_dbg_info: false,
85                extra_env: Some(ReadVar::from_static(
86                    [
87                        ("RUSTC_BOOTSTRAP".to_string(), "1".to_string()),
88                        // Forbid cc-rs and CMake from compiling anything
89                        ("CC_FORCE_DISABLE".to_string(), "1".to_string()),
90                        (
91                            "CMAKE".to_string(),
92                            "cmake-is-forbidden-during-openvmm-hcl-build".to_string(),
93                        ),
94                    ]
95                    .into_iter()
96                    .collect(),
97                )),
98                pre_build_deps: Vec::new(),
99                output: v,
100            });
101
102            ctx.emit_minor_rust_step("report built sidecar", |ctx| {
103                let sidecar = sidecar.claim(ctx);
104                let output = output.claim(ctx);
105                move |rt| {
106                    let output = match rt.read(output) {
107                        crate::run_cargo_build::CargoBuildOutput::ElfBin { bin, dbg } => {
108                            SidecarOutput {
109                                bin,
110                                dbg: dbg.unwrap(),
111                            }
112                        }
113                        _ => unreachable!(),
114                    };
115
116                    for var in sidecar {
117                        rt.write(var, &output);
118                    }
119                }
120            });
121        }
122
123        Ok(())
124    }
125}