Skip to content

Commit b58c2fb

Browse files
committed
show linker warnings even if it returns 0
1 parent 6ce3c6c commit b58c2fb

File tree

5 files changed

+61
-2
lines changed

5 files changed

+61
-2
lines changed

compiler/rustc_codegen_ssa/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
172172
codegen_ssa_linker_not_found = linker `{$linker_path}` not found
173173
.note = {$error}
174174
175+
codegen_ssa_linker_output = {$inner}
176+
175177
codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
176178
177179
codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}

compiler/rustc_codegen_ssa/src/back/link.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,14 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out
750750
}
751751
}
752752

753+
#[derive(Diagnostic)]
754+
#[diag(codegen_ssa_linker_output)]
755+
/// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just
756+
/// end up with inconsistent languages within the same diagnostic.
757+
struct LinkerOutput {
758+
inner: String,
759+
}
760+
753761
/// Create a dynamic library or executable.
754762
///
755763
/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
@@ -1022,8 +1030,22 @@ fn link_natively(
10221030

10231031
sess.dcx().abort_if_errors();
10241032
}
1025-
info!("linker stderr:\n{}", escape_string(&prog.stderr));
1026-
info!("linker stdout:\n{}", escape_string(&prog.stdout));
1033+
1034+
if !prog.stderr.is_empty() {
1035+
// We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
1036+
let stderr = escape_string(&prog.stderr);
1037+
debug!("original stderr: {stderr}");
1038+
let stderr = stderr
1039+
.strip_prefix("warning: ")
1040+
.unwrap_or(&stderr)
1041+
.replace(": warning: ", ": ");
1042+
sess.dcx().emit_warn(LinkerOutput { inner: format!("linker stderr: {stderr}") });
1043+
}
1044+
if !prog.stdout.is_empty() && sess.opts.verbose {
1045+
sess.dcx().emit_warn(LinkerOutput {
1046+
inner: format!("linker stdout: {}", escape_string(&prog.stdout)),
1047+
});
1048+
}
10271049
}
10281050
Err(e) => {
10291051
let linker_not_found = e.kind() == io::ErrorKind::NotFound;
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
include ../tools.mk
2+
3+
RUN_RUSTC := $(RUSTC_ORIGINAL) main.rs -o $(TMPDIR)/main -C linker=./fake-linker.sh
4+
5+
all:
6+
# Run rustc with our fake linker, and make sure it shows warnings
7+
$(RUN_RUSTC) -C link-arg=run_make_warn 2>&1 | $(CGREP) "warning: linker stderr: bar"
8+
9+
# Make sure it shows stdout, but only when --verbose is passed
10+
$(RUN_RUSTC) -C link-arg=run_make_info --verbose 2>&1 | $(CGREP) "warning: linker stdout: foo"
11+
$(RUN_RUSTC) -C link-arg=run_make_info 2>&1 | $(CGREP) -v "warning: linker stdout: foo"
12+
13+
# Make sure we short-circuit this new path if the linker exits with an error (so the diagnostic is less verbose)
14+
rm -f $(TMPDIR)/main
15+
$(RUN_RUSTC) -C link-arg=run_make_error 2>&1 | $(CGREP) "note: error: baz"
16+
! [ -e $(TMPDIR)/main ]
17+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/sh
2+
3+
code=0
4+
while ! [ $# = 0 ]; do
5+
case "$1" in
6+
run_make_info) echo "foo"
7+
;;
8+
run_make_warn) echo "warning: bar" >&2
9+
;;
10+
run_make_error) echo "error: baz" >&2; code=1
11+
;;
12+
*) ;; # rustc passes lots of args we don't care about
13+
esac
14+
shift
15+
done
16+
17+
exit $code

tests/run-make/linker-warning/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}

0 commit comments

Comments
 (0)