@@ -22,6 +22,7 @@ use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
2222use rustc_fs_util:: { TempDirBuilder , fix_windows_verbatim_for_gcc, try_canonicalize} ;
2323use rustc_hir:: attrs:: NativeLibKind ;
2424use rustc_hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
25+ use rustc_lint_defs:: builtin:: LINKER_INFO ;
2526use rustc_macros:: LintDiagnostic ;
2627use rustc_metadata:: fs:: { METADATA_FILENAME , copy_to_stdout, emit_wrapper_file} ;
2728use rustc_metadata:: {
@@ -60,7 +61,8 @@ use super::rpath::{self, RPathConfig};
6061use super :: { apple, versioned_llvm_target} ;
6162use crate :: base:: needs_allocator_shim_for_linking;
6263use crate :: {
63- CodegenLintLevels , CodegenResults , CompiledModule , CrateInfo , NativeLib , errors, looks_like_rust_object_file
64+ CodegenLintLevels , CodegenResults , CompiledModule , CrateInfo , NativeLib , errors,
65+ looks_like_rust_object_file,
6466} ;
6567
6668pub fn ensure_removed ( dcx : DiagCtxtHandle < ' _ > , path : & Path ) {
@@ -678,37 +680,106 @@ fn is_msvc_link_exe(sess: &Session) -> bool {
678680 && linker_path. to_str ( ) == Some ( "link.exe" )
679681}
680682
683+ fn is_macos_ld ( sess : & Session ) -> bool {
684+ let ( _, flavor) = linker_and_flavor ( sess) ;
685+ sess. target . is_like_darwin && matches ! ( flavor, LinkerFlavor :: Darwin ( _, Lld :: No ) )
686+ }
687+
688+ fn is_windows_gnu_ld ( sess : & Session ) -> bool {
689+ let ( _, flavor) = linker_and_flavor ( sess) ;
690+ sess. target . is_like_windows
691+ && !sess. target . is_like_msvc
692+ && matches ! ( flavor, LinkerFlavor :: Gnu ( _, Lld :: No ) )
693+ }
694+
681695fn report_linker_output ( sess : & Session , levels : CodegenLintLevels , stdout : & [ u8 ] , stderr : & [ u8 ] ) {
682- let escaped_stderr = escape_string ( & stderr) ;
696+ let mut escaped_stderr = escape_string ( & stderr) ;
683697 let mut escaped_stdout = escape_string ( & stdout) ;
698+ let mut linker_info = String :: new ( ) ;
699+
684700 info ! ( "linker stderr:\n {}" , & escaped_stderr) ;
685701 info ! ( "linker stdout:\n {}" , & escaped_stdout) ;
686702
703+ fn for_each ( bytes : & [ u8 ] , mut f : impl FnMut ( & str , & mut String ) ) -> String {
704+ let mut output = String :: new ( ) ;
705+ if let Ok ( str) = str:: from_utf8 ( bytes) {
706+ info ! ( "line: {str}" ) ;
707+ output = String :: with_capacity ( str. len ( ) ) ;
708+ for line in str. lines ( ) {
709+ f ( line. trim ( ) , & mut output) ;
710+ }
711+ }
712+ escape_string ( output. trim ( ) . as_bytes ( ) )
713+ }
714+
687715 // Hide some progress messages from link.exe that we don't care about.
688716 // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146
689717 if is_msvc_link_exe ( sess) {
690- if let Ok ( str) = str:: from_utf8 ( & stdout) {
691- let mut output = String :: with_capacity ( str. len ( ) ) ;
692- for line in str. lines ( ) {
693- if line. starts_with ( " Creating library" )
694- || line. starts_with ( "Generating code" )
695- || line. starts_with ( "Finished generating code" )
696- {
697- continue ;
698- } else {
699- output += line;
700- output += "\r \n "
701- }
718+ escaped_stdout = for_each ( & stdout, |line, output| {
719+ if line. starts_with ( " Creating library" )
720+ || line. starts_with ( "Generating code" )
721+ || line. starts_with ( "Finished generating code" )
722+ {
723+ linker_info += line;
724+ linker_info += "\r \n " ;
725+ } else {
726+ * output += line;
727+ * output += "\r \n "
702728 }
703- escaped_stdout = escape_string ( output. trim ( ) . as_bytes ( ) )
704- }
729+ } ) ;
730+ } else if is_macos_ld ( sess) {
731+ let deployment_mismatch = |line : & str | {
732+ line. starts_with ( "ld: warning: object file (" )
733+ && line. contains ( "was built for newer 'macOS' version" )
734+ && line. contains ( "than being linked" )
735+ } ;
736+ let search_path = |line : & str | {
737+ line. starts_with ( "ld: warning: search path '" ) && line. ends_with ( "' not found" )
738+ } ;
739+ escaped_stderr = for_each ( & stderr, |line, output| {
740+ if line. starts_with ( "ld: warning: ignoring duplicate libraries: " )
741+ || deployment_mismatch ( line)
742+ || search_path ( line)
743+ {
744+ linker_info += line;
745+ linker_info += "\n " ;
746+ } else {
747+ * output += line;
748+ * output += "\n "
749+ }
750+ } ) ;
751+ } else if is_windows_gnu_ld ( sess) {
752+ let mut saw_exclude_symbol = false ;
753+ let exclude_symbols = |line : & str | {
754+ line. starts_with ( "Warning: .drectve `-exclude-symbols:" )
755+ && line. ends_with ( "' unrecognized" )
756+ } ;
757+ // FIXME: are we sure this is stderr and not stdout?
758+ escaped_stderr = for_each ( & stderr, |line, output| {
759+ if exclude_symbols ( line) {
760+ saw_exclude_symbol = true ;
761+ linker_info += line;
762+ linker_info += "\n " ;
763+ } else if saw_exclude_symbol && line == "Warning: corrupt .drectve at end of def file" {
764+ linker_info += line;
765+ linker_info += "\n " ;
766+ } else {
767+ * output += line;
768+ * output += "\n "
769+ }
770+ } ) ;
705771 }
706772
707773 let lint_msg = |msg| {
708774 lint_level ( sess, LINKER_MESSAGES , levels. linker_messages , None , |diag| {
709775 LinkerOutput { inner : msg } . decorate_lint ( diag)
710776 } )
711777 } ;
778+ let lint_info = |msg| {
779+ lint_level ( sess, LINKER_INFO , levels. linker_info , None , |diag| {
780+ LinkerOutput { inner : msg } . decorate_lint ( diag)
781+ } )
782+ } ;
712783
713784 if !escaped_stderr. is_empty ( ) {
714785 // We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
@@ -721,6 +792,9 @@ fn report_linker_output(sess: &Session, levels: CodegenLintLevels, stdout: &[u8]
721792 if !escaped_stdout. is_empty ( ) {
722793 lint_msg ( format ! ( "linker stdout: {}" , escaped_stdout) )
723794 }
795+ if !linker_info. is_empty ( ) {
796+ lint_info ( linker_info) ;
797+ }
724798}
725799
726800/// Create a dynamic library or executable.
@@ -960,7 +1034,12 @@ fn link_natively(
9601034 sess. dcx ( ) . abort_if_errors ( ) ;
9611035 }
9621036
963- report_linker_output ( sess, codegen_results. crate_info . lint_levels , & prog. stdout , & prog. stderr ) ;
1037+ report_linker_output (
1038+ sess,
1039+ codegen_results. crate_info . lint_levels ,
1040+ & prog. stdout ,
1041+ & prog. stderr ,
1042+ ) ;
9641043 }
9651044 Err ( e) => {
9661045 let linker_not_found = e. kind ( ) == io:: ErrorKind :: NotFound ;
0 commit comments