@@ -15,12 +15,14 @@ use rustc_ast::CRATE_NODE_ID;
15
15
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
16
16
use rustc_data_structures:: memmap:: Mmap ;
17
17
use rustc_data_structures:: temp_dir:: MaybeTempDir ;
18
- use rustc_errors:: { DiagCtxtHandle , ErrorGuaranteed , FatalError } ;
18
+ use rustc_errors:: { DiagCtxtHandle , ErrorGuaranteed , FatalError , LintDiagnostic } ;
19
19
use rustc_fs_util:: { fix_windows_verbatim_for_gcc, try_canonicalize} ;
20
20
use rustc_hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
21
+ use rustc_macros:: LintDiagnostic ;
21
22
use rustc_metadata:: fs:: { METADATA_FILENAME , copy_to_stdout, emit_wrapper_file} ;
22
23
use rustc_metadata:: { find_native_static_library, walk_native_lib_search_dirs} ;
23
24
use rustc_middle:: bug;
25
+ use rustc_middle:: lint:: lint_level;
24
26
use rustc_middle:: middle:: debugger_visualizer:: DebuggerVisualizerFile ;
25
27
use rustc_middle:: middle:: dependency_format:: Linkage ;
26
28
use rustc_middle:: middle:: exported_symbols:: SymbolExportKind ;
@@ -29,6 +31,7 @@ use rustc_session::config::{
29
31
OutputType , PrintKind , SplitDwarfKind , Strip ,
30
32
} ;
31
33
use rustc_session:: cstore:: DllImport ;
34
+ use rustc_session:: lint:: builtin:: LINKER_MESSAGES ;
32
35
use rustc_session:: output:: { check_file_is_writeable, invalid_output_for_target, out_filename} ;
33
36
use rustc_session:: search_paths:: PathKind ;
34
37
use rustc_session:: utils:: NativeLibKind ;
@@ -52,7 +55,7 @@ use super::metadata::{MetadataPosition, create_wrapper_file};
52
55
use super :: rpath:: { self , RPathConfig } ;
53
56
use super :: { apple, versioned_llvm_target} ;
54
57
use crate :: {
55
- CodegenResults , CompiledModule , CrateInfo , NativeLib , common, errors,
58
+ CodegenLintLevels , CodegenResults , CompiledModule , CrateInfo , NativeLib , common, errors,
56
59
looks_like_rust_object_file,
57
60
} ;
58
61
@@ -70,6 +73,7 @@ pub fn link_binary(
70
73
sess : & Session ,
71
74
archive_builder_builder : & dyn ArchiveBuilderBuilder ,
72
75
codegen_results : CodegenResults ,
76
+ lint_levels : CodegenLintLevels ,
73
77
outputs : & OutputFilenames ,
74
78
) -> Result < ( ) , ErrorGuaranteed > {
75
79
let _timer = sess. timer ( "link_binary" ) ;
@@ -138,6 +142,7 @@ pub fn link_binary(
138
142
crate_type,
139
143
& out_filename,
140
144
& codegen_results,
145
+ lint_levels,
141
146
path. as_ref ( ) ,
142
147
) ?;
143
148
}
@@ -762,6 +767,14 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out
762
767
}
763
768
}
764
769
770
+ #[ derive( LintDiagnostic ) ]
771
+ #[ diag( codegen_ssa_linker_output) ]
772
+ /// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just
773
+ /// end up with inconsistent languages within the same diagnostic.
774
+ struct LinkerOutput {
775
+ inner : String ,
776
+ }
777
+
765
778
/// Create a dynamic library or executable.
766
779
///
767
780
/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
@@ -772,6 +785,7 @@ fn link_natively(
772
785
crate_type : CrateType ,
773
786
out_filename : & Path ,
774
787
codegen_results : & CodegenResults ,
788
+ lint_levels : CodegenLintLevels ,
775
789
tmpdir : & Path ,
776
790
) -> Result < ( ) , ErrorGuaranteed > {
777
791
info ! ( "preparing {:?} to {:?}" , crate_type, out_filename) ;
@@ -998,12 +1012,12 @@ fn link_natively(
998
1012
let mut output = prog. stderr . clone ( ) ;
999
1013
output. extend_from_slice ( & prog. stdout ) ;
1000
1014
let escaped_output = escape_linker_output ( & output, flavor) ;
1001
- // FIXME: Add UI tests for this error.
1002
1015
let err = errors:: LinkingFailed {
1003
1016
linker_path : & linker_path,
1004
1017
exit_status : prog. status ,
1005
1018
command : & cmd,
1006
1019
escaped_output,
1020
+ verbose : sess. opts . verbose ,
1007
1021
} ;
1008
1022
sess. dcx ( ) . emit_err ( err) ;
1009
1023
// If MSVC's `link.exe` was expected but the return code
@@ -1045,8 +1059,27 @@ fn link_natively(
1045
1059
1046
1060
sess. dcx ( ) . abort_if_errors ( ) ;
1047
1061
}
1048
- info ! ( "linker stderr:\n {}" , escape_string( & prog. stderr) ) ;
1049
- info ! ( "linker stdout:\n {}" , escape_string( & prog. stdout) ) ;
1062
+
1063
+ let ( level, src) = lint_levels. linker_messages ;
1064
+ let lint = |msg| {
1065
+ lint_level ( sess, LINKER_MESSAGES , level, src, None , |diag| {
1066
+ LinkerOutput { inner : msg } . decorate_lint ( diag)
1067
+ } )
1068
+ } ;
1069
+
1070
+ if !prog. stderr . is_empty ( ) {
1071
+ // We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
1072
+ let stderr = escape_string ( & prog. stderr ) ;
1073
+ debug ! ( "original stderr: {stderr}" ) ;
1074
+ let stderr = stderr
1075
+ . strip_prefix ( "warning: " )
1076
+ . unwrap_or ( & stderr)
1077
+ . replace ( ": warning: " , ": " ) ;
1078
+ lint ( format ! ( "linker stderr: {stderr}" ) ) ;
1079
+ }
1080
+ if !prog. stdout . is_empty ( ) && sess. opts . verbose {
1081
+ lint ( format ! ( "linker stdout: {}" , escape_string( & prog. stdout) ) )
1082
+ }
1050
1083
}
1051
1084
Err ( e) => {
1052
1085
let linker_not_found = e. kind ( ) == io:: ErrorKind :: NotFound ;
0 commit comments