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