Skip to main content

flowey_lib_hvlite/_jobs/
check_clippy.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Ensure the OpenVMM repo is `clippy` clean.
5
6use crate::common::CommonArch;
7use crate::common::CommonProfile;
8use crate::common::CommonTriple;
9use flowey::node::prelude::*;
10use flowey_lib_common::run_cargo_build::CargoBuildProfile;
11use flowey_lib_common::run_cargo_build::CargoFeatureSet;
12use flowey_lib_common::run_cargo_clippy::CargoPackage;
13
14flowey_request! {
15    pub struct Request {
16        pub target: target_lexicon::Triple,
17        pub profile: CommonProfile,
18        pub done: WriteVar<SideEffect>,
19        pub also_check_misc_nostd_crates: bool,
20    }
21}
22
23new_simple_flow_node!(struct Node);
24
25impl SimpleFlowNode for Node {
26    type Request = Request;
27
28    fn imports(ctx: &mut ImportCtx<'_>) {
29        ctx.import::<crate::build_xtask::Node>();
30        ctx.import::<crate::git_checkout_openvmm_repo::Node>();
31        ctx.import::<crate::init_openvmm_magicpath_openhcl_sysroot::Node>();
32        ctx.import::<crate::install_openvmm_rust_build_essential::Node>();
33        ctx.import::<crate::init_cross_build::Node>();
34        ctx.import::<flowey_lib_common::install_rust::Node>();
35        ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
36        ctx.import::<flowey_lib_common::run_cargo_clippy::Node>();
37    }
38
39    fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
40        let Request {
41            target,
42            profile,
43            done,
44            also_check_misc_nostd_crates,
45        } = request;
46
47        let flowey_platform = ctx.platform();
48        let flowey_arch = ctx.arch();
49
50        let sysroot_arch = CommonArch::from_architecture(target.architecture)?;
51        let (boot_target, uefi_target) = match sysroot_arch {
52            CommonArch::X86_64 => ("x86_64-unknown-none", "x86_64-unknown-uefi"),
53            CommonArch::Aarch64 => ("aarch64-unknown-linux-musl", "aarch64-unknown-uefi"),
54        };
55
56        let mut pre_build_deps = Vec::new();
57
58        // FIXME: this will go away once we have a dedicated cargo .config.toml
59        // for the openhcl _bin_. until we have that, we are building _every_
60        // musl target using the openhcl toolchain...
61
62        if matches!(target.environment, target_lexicon::Environment::Musl) {
63            pre_build_deps.push(
64                ctx.reqv(|v| crate::init_openvmm_magicpath_openhcl_sysroot::Request {
65                    arch: sysroot_arch,
66                    path: v,
67                })
68                .into_side_effect(),
69            );
70        }
71
72        ctx.req(flowey_lib_common::install_rust::Request::InstallTargetTriple(target.clone()));
73        if also_check_misc_nostd_crates {
74            ctx.req(
75                flowey_lib_common::install_rust::Request::InstallTargetTriple(
76                    target_lexicon::triple!(uefi_target),
77                ),
78            );
79            ctx.req(
80                flowey_lib_common::install_rust::Request::InstallTargetTriple(
81                    target_lexicon::triple!(boot_target),
82                ),
83            );
84        }
85
86        // TODO: install build tools for other platforms
87        if matches!(
88            ctx.platform(),
89            FlowPlatform::Linux(FlowPlatformLinuxDistro::Ubuntu)
90        ) {
91            pre_build_deps.push(ctx.reqv(|v| {
92                flowey_lib_common::install_dist_pkg::Request::Install {
93                    package_names: vec!["libssl-dev".into(), "build-essential".into()],
94                    done: v,
95                }
96            }));
97        }
98
99        pre_build_deps.push(ctx.reqv(crate::install_openvmm_rust_build_essential::Request));
100
101        // Cross compiling for MacOS isn't supported, but clippy still works
102        // with no additional dependencies
103        if !matches!(
104            target.operating_system,
105            target_lexicon::OperatingSystem::Darwin(_)
106        ) {
107            pre_build_deps.push(
108                ctx.reqv(|v| crate::init_cross_build::Request {
109                    target: target.clone(),
110                    injected_env: v,
111                })
112                .into_side_effect(),
113            );
114        }
115
116        let xtask_target = CommonTriple::Common {
117            arch: flowey_arch.try_into()?,
118            platform: flowey_platform.try_into()?,
119        };
120
121        let xtask = ctx.reqv(|v| crate::build_xtask::Request {
122            target: xtask_target,
123            xtask: v,
124        });
125
126        let profile = match profile {
127            CommonProfile::Release => CargoBuildProfile::Release,
128            CommonProfile::Debug => CargoBuildProfile::Debug,
129        };
130
131        let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
132
133        let exclude = ctx.emit_rust_stepv("determine clippy exclusions", |ctx| {
134            let xtask = xtask.claim(ctx);
135            let repo_path = openvmm_repo_path.clone().claim(ctx);
136            move |rt| {
137                let xtask = rt.read(xtask);
138                let repo_path = rt.read(repo_path);
139
140                let mut exclude = vec!["guest_test_uefi".into()];
141
142                // packages depending on libfuzzer-sys are currently x86 only
143                if !(matches!(target.architecture, target_lexicon::Architecture::X86_64)
144                    && matches!(flowey_arch, FlowArch::X86_64))
145                {
146                    let xtask_bin = match xtask {
147                        crate::build_xtask::XtaskOutput::LinuxBin { bin, dbg: _ } => bin,
148                        crate::build_xtask::XtaskOutput::WindowsBin { exe, pdb: _ } => exe,
149                    };
150
151                    rt.sh.change_dir(repo_path);
152                    let output =
153                        flowey::shell_cmd!(rt, "{xtask_bin} fuzz list --crates").output()?;
154                    let output = String::from_utf8(output.stdout)?;
155
156                    let fuzz_crates = output.trim().split('\n').map(|s| s.to_owned());
157                    exclude.extend(fuzz_crates);
158
159                    exclude.push("chipset_device_fuzz".into());
160                    exclude.push("xtask_fuzz".into());
161                }
162
163                // packages requiring crypto support won't cross compile for macos
164                if matches!(
165                    target.operating_system,
166                    target_lexicon::OperatingSystem::Darwin(_)
167                ) {
168                    exclude.extend(["openssl_kdf", "vmgs_lib", "disk_crypt"].map(|x| x.into()));
169                }
170
171                Ok(Some(exclude))
172            }
173        });
174
175        // HACK: the following behavior has been cargo-culted from our old
176        // CI, and at some point, we should actually improve the testing
177        // story on windows, so that we can run with FeatureSet::All in CI.
178        //
179        // On windows & mac, we can't build with all features, as many crates
180        // require openSSL for crypto, which isn't supported in CI yet.
181        let features = if matches!(
182            target.operating_system,
183            target_lexicon::OperatingSystem::Windows | target_lexicon::OperatingSystem::Darwin(_)
184        ) {
185            CargoFeatureSet::None
186        } else {
187            CargoFeatureSet::All
188        };
189
190        let mut reqs = vec![ctx.reqv(|v| flowey_lib_common::run_cargo_clippy::Request {
191            in_folder: openvmm_repo_path.clone(),
192            package: CargoPackage::Workspace,
193            profile: profile.clone(),
194            features: features.clone(),
195            target,
196            extra_env: None,
197            exclude,
198            keep_going: true,
199            all_targets: true,
200            pre_build_deps: pre_build_deps.clone(),
201            done: v,
202        })];
203
204        if also_check_misc_nostd_crates {
205            reqs.push(ctx.reqv(|v| flowey_lib_common::run_cargo_clippy::Request {
206                in_folder: openvmm_repo_path.clone(),
207                package: CargoPackage::Crate("openhcl_boot".into()),
208                profile: profile.clone(),
209                features: features.clone(),
210                target: target_lexicon::triple!(boot_target),
211                extra_env: Some(vec![("MINIMAL_RT_BUILD".into(), "1".into())]),
212                exclude: ReadVar::from_static(None),
213                keep_going: true,
214                all_targets: false,
215                pre_build_deps: pre_build_deps.clone(),
216                done: v,
217            }));
218
219            // don't pass --all-targets, since that pulls in a std dependency
220            reqs.push(ctx.reqv(|v| flowey_lib_common::run_cargo_clippy::Request {
221                in_folder: openvmm_repo_path.clone(),
222                package: CargoPackage::Crate("guest_test_uefi".into()),
223                profile: profile.clone(),
224                features,
225                target: target_lexicon::triple!(uefi_target),
226                extra_env: None,
227                exclude: ReadVar::from_static(None),
228                keep_going: true,
229                all_targets: false,
230                pre_build_deps: pre_build_deps.clone(),
231                done: v,
232            }));
233        }
234
235        ctx.emit_side_effect_step(reqs, [done]);
236
237        Ok(())
238    }
239}