Skip to main content

flowey_lib_hvlite/
build_vmfirmwareigvm_dll.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Build an instance of `vmfirmwareigvm.dll`
5
6use crate::common::CommonArch;
7use crate::common::CommonTriple;
8use flowey::node::prelude::*;
9use std::collections::BTreeMap;
10
11#[derive(Serialize, Deserialize)]
12pub struct VmfirmwareigvmDllOutput {
13    #[serde(rename = "vmfirmwareigvm.dll")]
14    pub dll: PathBuf,
15}
16
17impl Artifact for VmfirmwareigvmDllOutput {}
18
19flowey_request! {
20    pub struct Request {
21        pub arch: CommonArch,
22        pub igvm_bin: ReadVar<PathBuf>,
23        /// (major, minor, patch, revision)
24        pub dll_version: ReadVar<(u16, u16, u16, u16)>,
25        pub internal_dll_name: String,
26        pub vmfirmwareigvm_dll: WriteVar<VmfirmwareigvmDllOutput>,
27    }
28}
29
30new_simple_flow_node!(struct Node);
31
32impl SimpleFlowNode for Node {
33    type Request = Request;
34
35    fn imports(ctx: &mut ImportCtx<'_>) {
36        ctx.import::<crate::run_cargo_build::Node>();
37    }
38
39    fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
40        let Request {
41            arch,
42            igvm_bin,
43            internal_dll_name,
44            dll_version,
45            vmfirmwareigvm_dll,
46        } = request;
47
48        let extra_env = ctx.emit_rust_stepv("determine vmfirmwareigvm_dll env vars", |ctx| {
49            let igvm_bin = igvm_bin.claim(ctx);
50            let dll_version = dll_version.claim(ctx);
51            move |rt| {
52                let mut extra_env = BTreeMap::new();
53
54                // set the various build-time env vars `vmfirmwareigvm_dll` expects
55                {
56                    extra_env.insert("UH_DLL_NAME".into(), internal_dll_name);
57                    extra_env.insert(
58                        "UH_IGVM_PATH".into(),
59                        // rc.exe treats '\' in windows paths as escape sequences.
60                        // there is likely a more robust solution to fix this, but
61                        // a simple swap from '\' to '/' seems to work fine for now
62                        rt.read(igvm_bin)
63                            .absolute()
64                            .context("Failed to make igvm bin path absolute")?
65                            .display()
66                            .to_string()
67                            .replace('\\', "/"),
68                    );
69                    let (major, minor, patch, revision) = rt.read(dll_version);
70                    extra_env.insert("UH_MAJOR".into(), major.to_string());
71                    extra_env.insert("UH_MINOR".into(), minor.to_string());
72                    extra_env.insert("UH_PATCH".into(), patch.to_string());
73                    extra_env.insert("UH_REVISION".into(), revision.to_string());
74                }
75
76                // workaround for the fact that hvlite's root-level `.cargo/config.toml`
77                // currently sets a bunch of extraneous linker flags via
78                //
79                // [target.'cfg(all(windows, target_env = "msvc"))']
80                extra_env.insert("RUSTFLAGS".into(), "".into());
81
82                Ok(extra_env)
83            }
84        });
85
86        let output = ctx.reqv(|v| crate::run_cargo_build::Request {
87            crate_name: "vmfirmwareigvm_dll".into(),
88            out_name: "vmfirmwareigvm_dll".into(),
89            crate_type: flowey_lib_common::run_cargo_build::CargoCrateType::DynamicLib,
90            profile: crate::run_cargo_build::BuildProfile::Release,
91            features: Default::default(),
92            target: CommonTriple::Common {
93                arch,
94                platform: crate::common::CommonPlatform::WindowsMsvc,
95            }
96            .as_triple(),
97            no_split_dbg_info: false,
98            extra_env: Some(extra_env),
99            pre_build_deps: Vec::new(),
100            output: v,
101        });
102
103        ctx.emit_minor_rust_step("report built vmfirmwareigvm_dll", |ctx| {
104            let vmfirmwareigvm_dll = vmfirmwareigvm_dll.claim(ctx);
105            let output = output.claim(ctx);
106            move |rt| {
107                let output = match rt.read(output) {
108                    crate::run_cargo_build::CargoBuildOutput::WindowsDynamicLib {
109                        dll,
110                        // this is a resource dll, so these don't matter
111                        dll_lib: _,
112                        pdb: _,
113                    } => VmfirmwareigvmDllOutput { dll },
114                    _ => unreachable!(),
115                };
116
117                rt.write(vmfirmwareigvm_dll, &output);
118            }
119        });
120
121        Ok(())
122    }
123}