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