run_make_support/external_deps/
rustdoc.rs

1use std::ffi::OsStr;
2use std::path::Path;
3
4use crate::command::Command;
5use crate::env::env_var;
6use crate::target;
7use crate::util::set_host_compiler_dylib_path;
8
9/// Construct a new `rustdoc` invocation with target automatically set to cross-compile target and
10/// with host compiler runtime libs configured. Use [`bare_rustdoc`] to avoid automatically setting
11/// cross-compile target.
12#[track_caller]
13pub fn rustdoc() -> Rustdoc {
14    Rustdoc::new()
15}
16
17/// Bare `rustdoc` invocation, no args set.
18#[track_caller]
19pub fn bare_rustdoc() -> Rustdoc {
20    Rustdoc::bare()
21}
22
23#[derive(Debug)]
24#[must_use]
25pub struct Rustdoc {
26    cmd: Command,
27    target: Option<String>,
28}
29
30// Only fill in the target just before execution, so that it can be overridden.
31crate::macros::impl_common_helpers!(Rustdoc, |rustdoc: &mut Rustdoc| {
32    if let Some(target) = &rustdoc.target {
33        rustdoc.cmd.arg(&format!("--target={target}"));
34    }
35});
36
37#[track_caller]
38fn setup_common() -> Command {
39    let rustdoc = env_var("RUSTDOC");
40    let mut cmd = Command::new(rustdoc);
41    set_host_compiler_dylib_path(&mut cmd);
42    cmd
43}
44
45impl Rustdoc {
46    /// Construct a new `rustdoc` invocation with target automatically set to cross-compile target
47    /// and with host compiler runtime libs configured. Use [`bare_rustdoc`] to avoid automatically
48    /// setting cross-compile target.
49    #[track_caller]
50    pub fn new() -> Self {
51        let cmd = setup_common();
52        Self { cmd, target: Some(target()) }
53    }
54
55    /// Bare `rustdoc` invocation, no args set.
56    #[track_caller]
57    pub fn bare() -> Self {
58        let cmd = setup_common();
59        Self { cmd, target: None }
60    }
61
62    /// Specify where an external library is located.
63    pub fn extern_<P: AsRef<Path>>(&mut self, crate_name: &str, path: P) -> &mut Self {
64        assert!(
65            !crate_name.contains(|c: char| c.is_whitespace() || c == '\\' || c == '/'),
66            "crate name cannot contain whitespace or path separators"
67        );
68
69        let path = path.as_ref().to_string_lossy();
70
71        self.cmd.arg("--extern");
72        self.cmd.arg(format!("{crate_name}={path}"));
73
74        self
75    }
76
77    /// Specify path to the input file.
78    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
79        self.cmd.arg(path.as_ref());
80        self
81    }
82
83    /// Specify output directory.
84    #[doc(alias = "output")]
85    pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
86        self.cmd.arg("--out-dir").arg(path.as_ref());
87        self
88    }
89
90    /// Given a `path`, pass `@{path}` to `rustdoc` as an
91    /// [arg file](https://doc.rust-lang.org/rustdoc/command-line-arguments.html#path-load-command-line-flags-from-a-path).
92    pub fn arg_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
93        self.cmd.arg(format!("@{}", path.as_ref().display()));
94        self
95    }
96
97    /// Specify a stdin input buffer.
98    pub fn stdin_buf<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
99        self.cmd.stdin_buf(input);
100        self
101    }
102
103    /// Specify the edition year.
104    pub fn edition(&mut self, edition: &str) -> &mut Self {
105        self.cmd.arg("--edition");
106        self.cmd.arg(edition);
107        self
108    }
109
110    /// Specify the target triple, or a path to a custom target json spec file.
111    pub fn target<S: AsRef<str>>(&mut self, target: S) -> &mut Self {
112        // We store the target as a separate field, so that it can be specified multiple times.
113        // This is in particular useful to override the default target set in `Rustdoc::new()`.
114        self.target = Some(target.as_ref().to_string());
115        self
116    }
117
118    /// Specify the crate type.
119    pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
120        self.cmd.arg("--crate-type");
121        self.cmd.arg(crate_type);
122        self
123    }
124
125    /// Specify the crate name.
126    pub fn crate_name<S: AsRef<OsStr>>(&mut self, name: S) -> &mut Self {
127        self.cmd.arg("--crate-name");
128        self.cmd.arg(name.as_ref());
129        self
130    }
131
132    /// Add a directory to the library search path. It corresponds to the `-L`
133    /// rustdoc option.
134    pub fn library_search_path<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
135        self.cmd.arg("-L");
136        self.cmd.arg(path.as_ref());
137        self
138    }
139
140    /// Specify the output format.
141    pub fn output_format(&mut self, format: &str) -> &mut Self {
142        self.cmd.arg("--output-format");
143        self.cmd.arg(format);
144        self
145    }
146
147    /// Specify type(s) of output files to generate.
148    pub fn emit<S: AsRef<str>>(&mut self, kinds: S) -> &mut Self {
149        let kinds = kinds.as_ref();
150        self.cmd.arg(format!("--emit={kinds}"));
151        self
152    }
153}