flowey_lib_hvlite/
build_rustdoc.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Document crates in the hvlite repo using rustdoc (via `cargo doc`).
5
6use crate::download_lxutil::LxutilArch;
7use flowey::node::prelude::*;
8use flowey_lib_common::run_cargo_doc::DocPackage;
9use flowey_lib_common::run_cargo_doc::DocPackageKind;
10
11new_flow_node!(struct Node);
12
13flowey_request! {
14    pub struct Request {
15        pub target_triple: target_lexicon::Triple,
16        pub docs: WriteVar<RustdocOutput>,
17    }
18}
19
20#[derive(Serialize, Deserialize)]
21pub struct RustdocOutput {
22    pub docs: PathBuf,
23}
24
25impl Artifact for RustdocOutput {
26    // The rustdoc output has too many files for Azure DevOps to handle,
27    // so we need to archive it before uploading.
28    const TAR_GZ_NAME: Option<&'static str> = Some("rustdoc.tar.gz");
29}
30
31impl FlowNode for Node {
32    type Request = Request;
33
34    fn imports(ctx: &mut ImportCtx<'_>) {
35        ctx.import::<crate::git_checkout_openvmm_repo::Node>();
36        ctx.import::<crate::init_openvmm_magicpath_lxutil::Node>();
37        ctx.import::<crate::install_openvmm_rust_build_essential::Node>();
38        ctx.import::<flowey_lib_common::run_cargo_doc::Node>();
39    }
40
41    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
42        let mut doc_requests = Vec::new();
43
44        for Request {
45            target_triple,
46            docs,
47        } in requests
48        {
49            doc_requests.push((target_triple, docs));
50        }
51
52        let doc_requests = doc_requests;
53
54        // -- end of req processing -- //
55
56        if doc_requests.is_empty() {
57            return Ok(());
58        }
59
60        let side_effects = vec![ctx.reqv(crate::install_openvmm_rust_build_essential::Request)];
61
62        let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
63
64        let no_deps = true;
65        let document_private_items = false; // TODO: would be nice to turn this on
66
67        for (target_triple, output) in doc_requests {
68            let mut target_side_effects = side_effects.clone();
69
70            // lxutil is required by certain build.rs scripts.
71            //
72            // FUTURE: should prob have a way to opt-out of this lxutil build
73            // script requirement in non-interactive scenarios?
74            let lxutil_arch = match target_triple.architecture {
75                target_lexicon::Architecture::X86_64 => LxutilArch::X86_64,
76                target_lexicon::Architecture::Aarch64(_) => LxutilArch::Aarch64,
77                arch => anyhow::bail!("unsupported arch {arch}"),
78            };
79            target_side_effects.push(ctx.reqv(|v| crate::init_openvmm_magicpath_lxutil::Request {
80                arch: lxutil_arch,
81                done: v,
82            }));
83
84            let cargo_cmd = ctx.reqv(|v| {
85                flowey_lib_common::run_cargo_doc::Request {
86                    in_folder: openvmm_repo_path.clone(),
87                    packages: vec![
88                        DocPackage {
89                            kind: DocPackageKind::Workspace {
90                                // this is a bin crate with no interesting docs;
91                                // easier to just exclude it.
92                                exclude: vec!["vmfirmwareigvm_dll".into()],
93                            },
94                            no_deps,
95                            document_private_items,
96                        },
97                        DocPackage {
98                            kind: DocPackageKind::NoStdCrate("guest_test_uefi".into()),
99                            no_deps,
100                            document_private_items,
101                        },
102                    ],
103                    target_triple: target_triple.clone(),
104                    cargo_cmd: v,
105                }
106            });
107
108            ctx.emit_rust_step(format!("document repo for target {target_triple}"), |ctx| {
109                target_side_effects.to_vec().claim(ctx);
110                let output = output.claim(ctx);
111                let cargo_cmd = cargo_cmd.claim(ctx);
112                move |rt| {
113                    let cargo_cmd = rt.read(cargo_cmd);
114                    let sh = xshell::Shell::new()?;
115                    let out_path = cargo_cmd.run(&sh)?;
116
117                    rt.write(output, &RustdocOutput { docs: out_path });
118                    Ok(())
119                }
120            });
121        }
122
123        Ok(())
124    }
125}