flowey_lib_hvlite/
build_guest_test_uefi.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Build `guest_test_uefi` images and binaries
5
6use crate::run_cargo_build::common::CommonArch;
7use crate::run_cargo_build::common::CommonProfile;
8use flowey::node::prelude::*;
9use flowey_lib_common::run_cargo_build::CargoCrateType;
10use std::collections::BTreeMap;
11
12#[derive(Serialize, Deserialize)]
13pub struct GuestTestUefiOutput {
14    #[serde(rename = "guest_test_uefi.efi")]
15    pub efi: PathBuf,
16    #[serde(rename = "guest_test_uefi.pdb")]
17    pub pdb: PathBuf,
18    #[serde(rename = "guest_test_uefi.img")]
19    pub img: PathBuf,
20}
21
22impl Artifact for GuestTestUefiOutput {}
23
24flowey_request! {
25    pub struct Request {
26        pub arch: CommonArch,
27        pub profile: CommonProfile,
28        pub guest_test_uefi: WriteVar<GuestTestUefiOutput>,
29    }
30}
31
32new_flow_node!(struct Node);
33
34impl FlowNode for Node {
35    type Request = Request;
36
37    fn imports(ctx: &mut ImportCtx<'_>) {
38        ctx.import::<crate::run_cargo_build::Node>();
39        ctx.import::<crate::git_checkout_openvmm_repo::Node>();
40    }
41
42    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
43        let mut tasks: BTreeMap<_, Vec<_>> = BTreeMap::new();
44
45        for Request {
46            arch,
47            profile,
48            guest_test_uefi,
49        } in requests
50        {
51            tasks
52                .entry((arch, profile))
53                .or_default()
54                .push(guest_test_uefi);
55        }
56
57        for ((arch, profile), outvars) in tasks {
58            let output = ctx.reqv(|v| {
59                crate::run_cargo_build::Request {
60                    crate_name: "guest_test_uefi".into(),
61                    out_name: "guest_test_uefi".into(),
62                    crate_type: CargoCrateType::Bin,
63                    profile: profile.into(),
64                    features: [].into(),
65                    target: target_lexicon::Triple {
66                        architecture: arch.as_arch(),
67                        operating_system: target_lexicon::OperatingSystem::Uefi,
68                        environment: target_lexicon::Environment::Unknown,
69                        vendor: target_lexicon::Vendor::Unknown,
70                        // work around bug in target_lexicon (this shouldn't be Elf)
71                        binary_format: target_lexicon::BinaryFormat::Elf,
72                    },
73                    no_split_dbg_info: false,
74                    extra_env: None,
75                    pre_build_deps: Vec::new(),
76                    output: v,
77                }
78            });
79
80            let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
81
82            ctx.emit_rust_step("build guest_test_uefi.img", |ctx| {
83                let openvmm_repo_path = openvmm_repo_path.claim(ctx);
84                let output = output.claim(ctx);
85                let outvars = outvars.claim(ctx);
86                move |rt| {
87                    let (efi, pdb) = match rt.read(output) {
88                        crate::run_cargo_build::CargoBuildOutput::UefiBin { efi, pdb } => {
89                            (efi, pdb)
90                        }
91                        _ => unreachable!(),
92                    };
93
94                    // package it up into an img using the xtask
95                    let sh = xshell::Shell::new()?;
96                    let img_path = sh.current_dir().join("guest_test_uefi.img");
97                    let arch_arg = match arch {
98                        CommonArch::X86_64 => "bootx64",
99                        CommonArch::Aarch64 => "bootaa64",
100                    };
101                    sh.change_dir(rt.read(openvmm_repo_path));
102                    xshell::cmd!(
103                        sh,
104                        "cargo xtask guest-test uefi --output {img_path} --{arch_arg} {efi}"
105                    )
106                    .run()?;
107
108                    let output = GuestTestUefiOutput {
109                        efi,
110                        pdb,
111                        img: img_path.absolute()?,
112                    };
113
114                    for var in outvars {
115                        rt.write(var, &output);
116                    }
117
118                    Ok(())
119                }
120            });
121        }
122
123        Ok(())
124    }
125}