rustdoc: Support argument files

Factors out the `rustc_driver` logic that handles argument files
so that rustdoc supports them as well, e.g.:

    rustdoc @argfile

This is needed to be able to generate docs for projects that
already use argument files when compiling them, e.g. projects
that pass a huge number of `--cfg` arguments.

The feature was stabilized for `rustc` in #66172.

Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
Miguel Ojeda 2021-02-18 16:15:24 +01:00
parent c0b64d97be
commit 755b3fc722
11 changed files with 77 additions and 13 deletions

View File

@ -3,7 +3,7 @@ use std::fmt;
use std::fs;
use std::io;
pub fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
if let Some(path) = arg.strip_prefix('@') {
let file = match fs::read_to_string(path) {
Ok(file) => file,
@ -18,6 +18,20 @@ pub fn arg_expand(arg: String) -> Result<Vec<String>, Error> {
}
}
pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
let mut args = Vec::new();
for arg in at_args {
match arg_expand(arg.clone()) {
Ok(arg) => args.extend(arg),
Err(err) => rustc_session::early_error(
rustc_session::config::ErrorOutputType::default(),
&format!("Failed to load argument file: {}", err),
),
}
}
args
}
#[derive(Debug)]
pub enum Error {
Utf8Error(Option<String>),

View File

@ -55,7 +55,7 @@ use std::process::{self, Command, Stdio};
use std::str;
use std::time::Instant;
mod args;
pub mod args;
pub mod pretty;
/// Exit status code used for successful compilation and help output.
@ -188,16 +188,8 @@ fn run_compiler(
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
>,
) -> interface::Result<()> {
let mut args = Vec::new();
for arg in at_args {
match args::arg_expand(arg.clone()) {
Ok(arg) => args.extend(arg),
Err(err) => early_error(
ErrorOutputType::default(),
&format!("Failed to load argument file: {}", err),
),
}
}
let args = args::arg_expand_all(at_args);
let diagnostic_output = emitter.map_or(DiagnosticOutput::Default, DiagnosticOutput::Raw);
let matches = match handle_options(&args) {
Some(matches) => matches,

View File

@ -422,3 +422,10 @@ $ rustdoc src/lib.rs --crate-version 1.3.37
When `rustdoc` receives this flag, it will print an extra "Version (version)" into the sidebar of
the crate root's docs. You can use this flag to differentiate between different versions of your
library's documentation.
## `@path`: load command-line flags from a path
If you specify `@path` on the command-line, then it will open `path` and read
command line options from it. These options are one per line; a blank line indicates
an empty option. The file can use Unix or Windows style line endings, and must be
encoded as UTF-8.

View File

@ -432,13 +432,16 @@ fn usage(argv0: &str) {
(option.apply)(&mut options);
}
println!("{}", options.usage(&format!("{} [options] <input>", argv0)));
println!(" @path Read newline separated options from `path`\n");
println!("More information available at https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html")
}
/// A result type used by several functions under `main()`.
type MainResult = Result<(), ErrorReported>;
fn main_args(args: &[String]) -> MainResult {
fn main_args(at_args: &[String]) -> MainResult {
let args = rustc_driver::args::arg_expand_all(at_args);
let mut options = getopts::Options::new();
for option in opts() {
(option.apply)(&mut options);

View File

@ -0,0 +1,2 @@
--cfg
unbroken€

View File

@ -0,0 +1,12 @@
// Check to see if we can get parameters from an @argsfile file
//
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-badutf8.args
#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
#[cfg(not(unbroken))]
compile_error!("unbroken not set");
fn main() {
}

View File

@ -0,0 +1,2 @@
error: Failed to load argument file: Utf8 error in $DIR/commandline-argfile-badutf8.args

View File

@ -0,0 +1,15 @@
// Check to see if we can get parameters from an @argsfile file
//
// ignore-tidy-linelength
// normalize-stderr-test: "os error \d+" -> "os error $$ERR"
// normalize-stderr-test: "commandline-argfile-missing.args:[^(]*" -> "commandline-argfile-missing.args: $$FILE_MISSING "
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile-missing.args
#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
#[cfg(not(unbroken))]
compile_error!("unbroken not set");
fn main() {
}

View File

@ -0,0 +1,2 @@
error: Failed to load argument file: IO Error: $DIR/commandline-argfile-missing.args: $FILE_MISSING (os error $ERR)

View File

@ -0,0 +1,2 @@
--cfg
unbroken

View File

@ -0,0 +1,13 @@
// Check to see if we can get parameters from an @argsfile file
//
// check-pass
// compile-flags: --cfg cmdline_set @{{src-base}}/commandline-argfile.args
#[cfg(not(cmdline_set))]
compile_error!("cmdline_set not set");
#[cfg(not(unbroken))]
compile_error!("unbroken not set");
fn main() {
}