Skip to content

Commit a32f1ae

Browse files
committed
Respect -o output file in --print
1 parent 34d3fcb commit a32f1ae

File tree

1 file changed

+50
-12
lines changed
  • compiler/rustc_driver_impl/src

1 file changed

+50
-12
lines changed

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ use std::cmp::max;
5151
use std::collections::BTreeMap;
5252
use std::env;
5353
use std::ffi::OsString;
54-
use std::fs;
54+
use std::fmt;
55+
use std::fs::{self, File};
5556
use std::io::{self, IsTerminal, Read, Write};
5657
use std::panic::{self, catch_unwind};
5758
use std::path::PathBuf;
@@ -67,6 +68,11 @@ macro do_not_use_print($($t:tt)*) {
6768
)
6869
}
6970

71+
#[allow(unused_macros)]
72+
macro do_not_use_safe_print($($t:tt)*) {
73+
std::compile_error!("Don't use `safe_print` or `safe_println` here, use `println_info` instead")
74+
}
75+
7076
// This import blocks the use of panicking `print` and `println` in all the code
7177
// below. Please use `safe_print` and `safe_println` to avoid ICE when
7278
// encountering an I/O error during print.
@@ -718,6 +724,13 @@ fn print_crate_info(
718724
parse_attrs: bool,
719725
) -> Compilation {
720726
use rustc_session::config::PrintRequest::*;
727+
728+
// This import prevents the following code from using the printing macros
729+
// used by the rest of the module. Within this function, we only write to
730+
// the output specified by `sess.io.output_file`.
731+
#[allow(unused_imports)]
732+
use {do_not_use_safe_print as safe_print, do_not_use_safe_print as safe_println};
733+
721734
// NativeStaticLibs and LinkArgs are special - printed during linking
722735
// (empty iterator returns true)
723736
if sess.opts.prints.iter().all(|&p| p == NativeStaticLibs || p == LinkArgs) {
@@ -736,17 +749,42 @@ fn print_crate_info(
736749
} else {
737750
None
738751
};
752+
753+
let mut output_io: Box<dyn Write> = match &sess.io.output_file {
754+
Some(OutFileName::Real(output_file_path)) => match File::create(output_file_path) {
755+
Ok(output_file) => Box::new(output_file),
756+
Err(err) => handler.early_error(format!(
757+
"failed to create {}: {}",
758+
output_file_path.display(),
759+
err,
760+
)),
761+
},
762+
None | Some(OutFileName::Stdout) => Box::new(io::stdout()),
763+
};
764+
765+
fn write_output(output_io: &mut dyn Write, args: fmt::Arguments<'_>) {
766+
if let Err(_) = output_io.write_fmt(args) {
767+
rustc_errors::FatalError.raise();
768+
}
769+
}
770+
771+
macro_rules! println_info {
772+
($($arg:tt)*) => {
773+
write_output(&mut *output_io, format_args!("{}\n", format_args!($($arg)*)))
774+
};
775+
}
776+
739777
for req in &sess.opts.prints {
740778
match *req {
741779
TargetList => {
742780
let mut targets = rustc_target::spec::TARGETS.to_vec();
743781
targets.sort_unstable();
744-
safe_println!("{}", targets.join("\n"));
782+
println_info!("{}", targets.join("\n"));
745783
}
746-
Sysroot => safe_println!("{}", sess.sysroot.display()),
747-
TargetLibdir => safe_println!("{}", sess.target_tlib_path.dir.display()),
784+
Sysroot => println_info!("{}", sess.sysroot.display()),
785+
TargetLibdir => println_info!("{}", sess.target_tlib_path.dir.display()),
748786
TargetSpec => {
749-
safe_println!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
787+
println_info!("{}", serde_json::to_string_pretty(&sess.target.to_json()).unwrap());
750788
}
751789
AllTargetSpecs => {
752790
let mut targets = BTreeMap::new();
@@ -755,7 +793,7 @@ fn print_crate_info(
755793
let target = Target::expect_builtin(&triple);
756794
targets.insert(name, target.to_json());
757795
}
758-
safe_println!("{}", serde_json::to_string_pretty(&targets).unwrap());
796+
println_info!("{}", serde_json::to_string_pretty(&targets).unwrap());
759797
}
760798
FileNames | CrateName => {
761799
let Some(attrs) = attrs.as_ref() else {
@@ -765,14 +803,14 @@ fn print_crate_info(
765803
let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
766804
let id = rustc_session::output::find_crate_name(sess, attrs);
767805
if *req == PrintRequest::CrateName {
768-
safe_println!("{id}");
806+
println_info!("{id}");
769807
continue;
770808
}
771809
let crate_types = collect_crate_types(sess, attrs);
772810
for &style in &crate_types {
773811
let fname =
774812
rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
775-
safe_println!("{}", fname.as_path().file_name().unwrap().to_string_lossy());
813+
println_info!("{}", fname.as_path().file_name().unwrap().to_string_lossy());
776814
}
777815
}
778816
Cfg => {
@@ -806,13 +844,13 @@ fn print_crate_info(
806844

807845
cfgs.sort();
808846
for cfg in cfgs {
809-
safe_println!("{cfg}");
847+
println_info!("{cfg}");
810848
}
811849
}
812850
CallingConventions => {
813851
let mut calling_conventions = rustc_target::spec::abi::all_names();
814852
calling_conventions.sort_unstable();
815-
safe_println!("{}", calling_conventions.join("\n"));
853+
println_info!("{}", calling_conventions.join("\n"));
816854
}
817855
RelocationModels
818856
| CodeModels
@@ -830,15 +868,15 @@ fn print_crate_info(
830868

831869
for split in &[Off, Packed, Unpacked] {
832870
if sess.target.options.supported_split_debuginfo.contains(split) {
833-
safe_println!("{split}");
871+
println_info!("{split}");
834872
}
835873
}
836874
}
837875
DeploymentTarget => {
838876
use rustc_target::spec::current_apple_deployment_target;
839877

840878
if sess.target.is_like_osx {
841-
safe_println!(
879+
println_info!(
842880
"deployment_target={}",
843881
current_apple_deployment_target(&sess.target)
844882
.expect("unknown Apple target OS")

0 commit comments

Comments
 (0)