Skip to content

Commit 060a457

Browse files
committed
show linker warnings even if it returns 0
1 parent df9d457 commit 060a457

File tree

5 files changed

+60
-2
lines changed

5 files changed

+60
-2
lines changed

compiler/rustc_codegen_ssa/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
160160
codegen_ssa_linker_not_found = linker `{$linker_path}` not found
161161
.note = {$error}
162162
163+
codegen_ssa_linker_output = {$inner}
164+
163165
codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
164166
165167
codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}

compiler/rustc_codegen_ssa/src/back/link.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,15 @@ fn link_dwarf_object<'a>(
721721
}
722722
}
723723

724+
#[derive(Diagnostic)]
725+
#[diag(codegen_ssa_linker_output)]
726+
/// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just
727+
/// end up with inconsistent languages within the same diagnostic. Ideally we'd accept strings in
728+
/// `emit_warning`, but I didn't feel like doing that much of a refactor.
729+
struct LinkerOutput {
730+
inner: String,
731+
}
732+
724733
/// Create a dynamic library or executable.
725734
///
726735
/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
@@ -972,8 +981,20 @@ fn link_natively<'a>(
972981

973982
sess.abort_if_errors();
974983
}
975-
info!("linker stderr:\n{}", escape_string(&prog.stderr));
976-
info!("linker stdout:\n{}", escape_string(&prog.stdout));
984+
985+
if !prog.stderr.is_empty() {
986+
// We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
987+
let stderr = escape_string(&prog.stderr);
988+
debug!("original stderr: {stderr}");
989+
let stderr =
990+
stderr.strip_prefix("warning: ").unwrap_or(&stderr).replace(" warning: ", " ");
991+
sess.emit_warning(LinkerOutput { inner: format!("linker stderr: {stderr}") });
992+
}
993+
if !prog.stdout.is_empty() && sess.opts.verbose {
994+
sess.emit_warning(LinkerOutput {
995+
inner: format!("linker stdout: {}", escape_string(&prog.stdout)),
996+
});
997+
}
977998
}
978999
Err(e) => {
9791000
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)