diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs index ca25c2b132206..c8aff10b6355b 100644 --- a/src/bootstrap/src/bin/rustc.rs +++ b/src/bootstrap/src/bin/rustc.rs @@ -22,8 +22,8 @@ use std::time::Instant; use arg_file_command::ArgFileCommand; use shared_helpers::{ - dylib_path, dylib_path_var, exe, maybe_dump, parse_rustc_stage, parse_rustc_verbose, - parse_value_from_args, + collect_args, dylib_path, dylib_path_var, exe, maybe_dump, parse_rustc_stage, + parse_rustc_verbose, parse_value_from_args, }; #[path = "../utils/shared_helpers.rs"] @@ -36,7 +36,7 @@ mod arg_file_command; mod proc_macro_deps; fn main() { - let orig_args = env::args_os().skip(1).collect::>(); + let orig_args = collect_args(); let mut args = orig_args.clone(); let stage = parse_rustc_stage(); diff --git a/src/bootstrap/src/bin/rustdoc.rs b/src/bootstrap/src/bin/rustdoc.rs index ef2462af952e1..fd048d138e090 100644 --- a/src/bootstrap/src/bin/rustdoc.rs +++ b/src/bootstrap/src/bin/rustdoc.rs @@ -7,7 +7,7 @@ use std::path::PathBuf; use arg_file_command::ArgFileCommand; use shared_helpers::{ - dylib_path, dylib_path_var, maybe_dump, parse_rustc_stage, parse_rustc_verbose, + collect_args, dylib_path, dylib_path_var, maybe_dump, parse_rustc_stage, parse_rustc_verbose, parse_value_from_args, }; @@ -18,7 +18,7 @@ mod shared_helpers; mod arg_file_command; fn main() { - let args = env::args_os().skip(1).collect::>(); + let args = collect_args(); let stage = parse_rustc_stage(); let verbose = parse_rustc_verbose(); diff --git a/src/bootstrap/src/utils/shared_helpers.rs b/src/bootstrap/src/utils/shared_helpers.rs index d620cc4bbb6b4..78af70ddb0f42 100644 --- a/src/bootstrap/src/utils/shared_helpers.rs +++ b/src/bootstrap/src/utils/shared_helpers.rs @@ -16,7 +16,8 @@ use std::env; use std::ffi::OsString; use std::fs::OpenOptions; -use std::io::Write; +use std::io::{BufRead, Write}; +use std::path::Path; use std::process::Command; use std::str::FromStr; @@ -126,3 +127,30 @@ pub fn parse_value_from_args<'a>(args: &'a [OsString], key: &str) -> Option<&'a None } + +/// Collect all the command line arguments, including the arguments from any `@argfile` +pub fn collect_args() -> Vec { + let mut args = Vec::with_capacity(env::args_os().len()); + for arg in env::args_os().skip(1) { + if let Some(s) = arg.to_str() + && let Some(path) = s.strip_prefix('@') + { + args.extend(args_from_argfile(Path::new(path))); + } else { + args.push(arg) + } + } + args +} + +/// Reads all the arguments from argfile given by `path`. +/// Each argument should be on a line by itself +fn args_from_argfile(path: &Path) -> Vec { + fn collect_lines(path: &Path) -> Result, std::io::Error> { + let file = std::fs::File::open(path)?; + let lines: Result, std::io::Error> = + std::io::BufReader::new(file).lines().map(|r| r.map(OsString::from)).collect(); + lines + } + collect_lines(path).expect("read args from argfile {path:?}") +}