@@ -51,7 +51,8 @@ use std::cmp::max;
51
51
use std:: collections:: BTreeMap ;
52
52
use std:: env;
53
53
use std:: ffi:: OsString ;
54
- use std:: fs;
54
+ use std:: fmt;
55
+ use std:: fs:: { self , File } ;
55
56
use std:: io:: { self , IsTerminal , Read , Write } ;
56
57
use std:: panic:: { self , catch_unwind} ;
57
58
use std:: path:: PathBuf ;
@@ -67,6 +68,11 @@ macro do_not_use_print($($t:tt)*) {
67
68
)
68
69
}
69
70
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
+
70
76
// This import blocks the use of panicking `print` and `println` in all the code
71
77
// below. Please use `safe_print` and `safe_println` to avoid ICE when
72
78
// encountering an I/O error during print.
@@ -718,6 +724,13 @@ fn print_crate_info(
718
724
parse_attrs: bool ,
719
725
) -> Compilation {
720
726
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
+
721
734
// NativeStaticLibs and LinkArgs are special - printed during linking
722
735
// (empty iterator returns true)
723
736
if sess. opts. prints. iter( ) . all( |& p| p == NativeStaticLibs || p == LinkArgs ) {
@@ -736,17 +749,42 @@ fn print_crate_info(
736
749
} else {
737
750
None
738
751
} ;
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
+
739
777
for req in & sess. opts. prints {
740
778
match * req {
741
779
TargetList => {
742
780
let mut targets = rustc_target:: spec:: TARGETS . to_vec( ) ;
743
781
targets. sort_unstable( ) ;
744
- safe_println ! ( "{}" , targets. join( "\n " ) ) ;
782
+ println_info !( "{}" , targets. join( "\n " ) ) ;
745
783
}
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( ) ) ,
748
786
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( ) ) ;
750
788
}
751
789
AllTargetSpecs => {
752
790
let mut targets = BTreeMap :: new( ) ;
@@ -755,7 +793,7 @@ fn print_crate_info(
755
793
let target = Target :: expect_builtin( & triple) ;
756
794
targets. insert( name, target. to_json( ) ) ;
757
795
}
758
- safe_println ! ( "{}" , serde_json:: to_string_pretty( & targets) . unwrap( ) ) ;
796
+ println_info !( "{}" , serde_json:: to_string_pretty( & targets) . unwrap( ) ) ;
759
797
}
760
798
FileNames | CrateName => {
761
799
let Some ( attrs) = attrs. as_ref( ) else {
@@ -765,14 +803,14 @@ fn print_crate_info(
765
803
let t_outputs = rustc_interface:: util:: build_output_filenames( attrs, sess) ;
766
804
let id = rustc_session:: output:: find_crate_name( sess, attrs) ;
767
805
if * req == PrintRequest :: CrateName {
768
- safe_println ! ( "{id}" ) ;
806
+ println_info !( "{id}" ) ;
769
807
continue ;
770
808
}
771
809
let crate_types = collect_crate_types( sess, attrs) ;
772
810
for & style in & crate_types {
773
811
let fname =
774
812
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( ) ) ;
776
814
}
777
815
}
778
816
Cfg => {
@@ -806,13 +844,13 @@ fn print_crate_info(
806
844
807
845
cfgs. sort( ) ;
808
846
for cfg in cfgs {
809
- safe_println ! ( "{cfg}" ) ;
847
+ println_info !( "{cfg}" ) ;
810
848
}
811
849
}
812
850
CallingConventions => {
813
851
let mut calling_conventions = rustc_target:: spec:: abi:: all_names( ) ;
814
852
calling_conventions. sort_unstable( ) ;
815
- safe_println ! ( "{}" , calling_conventions. join( "\n " ) ) ;
853
+ println_info !( "{}" , calling_conventions. join( "\n " ) ) ;
816
854
}
817
855
RelocationModels
818
856
| CodeModels
@@ -830,15 +868,15 @@ fn print_crate_info(
830
868
831
869
for split in & [ Off , Packed , Unpacked ] {
832
870
if sess. target. options. supported_split_debuginfo. contains( split) {
833
- safe_println ! ( "{split}" ) ;
871
+ println_info !( "{split}" ) ;
834
872
}
835
873
}
836
874
}
837
875
DeploymentTarget => {
838
876
use rustc_target:: spec:: current_apple_deployment_target;
839
877
840
878
if sess. target. is_like_osx {
841
- safe_println ! (
879
+ println_info !(
842
880
"deployment_target={}" ,
843
881
current_apple_deployment_target( & sess. target)
844
882
. expect( "unknown Apple target OS" )
0 commit comments