@@ -18,6 +18,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
1818use rustc_errors:: { DiagCtxtHandle , ErrorGuaranteed , FatalError } ;
1919use rustc_fs_util:: { fix_windows_verbatim_for_gcc, try_canonicalize} ;
2020use rustc_hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
21+ use rustc_macros:: Diagnostic ;
2122use rustc_metadata:: fs:: { copy_to_stdout, emit_wrapper_file, METADATA_FILENAME } ;
2223use rustc_metadata:: { find_native_static_library, walk_native_lib_search_dirs} ;
2324use rustc_middle:: bug;
@@ -750,6 +751,14 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out
750751 }
751752}
752753
754+ #[ derive( Diagnostic ) ]
755+ #[ diag( codegen_ssa_linker_output) ]
756+ /// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just
757+ /// end up with inconsistent languages within the same diagnostic.
758+ struct LinkerOutput {
759+ inner : String ,
760+ }
761+
753762/// Create a dynamic library or executable.
754763///
755764/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
@@ -976,12 +985,12 @@ fn link_natively(
976985 let mut output = prog. stderr . clone ( ) ;
977986 output. extend_from_slice ( & prog. stdout ) ;
978987 let escaped_output = escape_linker_output ( & output, flavor) ;
979- // FIXME: Add UI tests for this error.
980988 let err = errors:: LinkingFailed {
981989 linker_path : & linker_path,
982990 exit_status : prog. status ,
983991 command : & cmd,
984992 escaped_output,
993+ verbose : sess. opts . verbose ,
985994 } ;
986995 sess. dcx ( ) . emit_err ( err) ;
987996 // If MSVC's `link.exe` was expected but the return code
@@ -1022,8 +1031,22 @@ fn link_natively(
10221031
10231032 sess. dcx ( ) . abort_if_errors ( ) ;
10241033 }
1025- info ! ( "linker stderr:\n {}" , escape_string( & prog. stderr) ) ;
1026- info ! ( "linker stdout:\n {}" , escape_string( & prog. stdout) ) ;
1034+
1035+ if !prog. stderr . is_empty ( ) {
1036+ // We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
1037+ let stderr = escape_string ( & prog. stderr ) ;
1038+ debug ! ( "original stderr: {stderr}" ) ;
1039+ let stderr = stderr
1040+ . strip_prefix ( "warning: " )
1041+ . unwrap_or ( & stderr)
1042+ . replace ( ": warning: " , ": " ) ;
1043+ sess. dcx ( ) . emit_warn ( LinkerOutput { inner : format ! ( "linker stderr: {stderr}" ) } ) ;
1044+ }
1045+ if !prog. stdout . is_empty ( ) && sess. opts . verbose {
1046+ sess. dcx ( ) . emit_warn ( LinkerOutput {
1047+ inner : format ! ( "linker stdout: {}" , escape_string( & prog. stdout) ) ,
1048+ } ) ;
1049+ }
10271050 }
10281051 Err ( e) => {
10291052 let linker_not_found = e. kind ( ) == io:: ErrorKind :: NotFound ;
0 commit comments