Skip to content

Commit 457de8c

Browse files
committed
show linker warnings even if it returns 0
1 parent 54dcff1 commit 457de8c

File tree

10 files changed

+82
-27
lines changed

10 files changed

+82
-27
lines changed

compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
183183
codegen_ssa_linker_not_found = linker `{$linker_path}` not found
184184
.note = {$error}
185185
186+
codegen_ssa_linker_output = {$inner}
187+
186188
codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
187189
188190
codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
1818
use rustc_errors::DiagCtxtHandle;
1919
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
2020
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
21+
use rustc_macros::Diagnostic;
2122
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
2223
use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs};
2324
use rustc_middle::bug;
@@ -749,6 +750,14 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out
749750
}
750751
}
751752

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+
752761
/// Create a dynamic library or executable.
753762
///
754763
/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
@@ -1032,8 +1041,22 @@ fn link_natively(
10321041

10331042
sess.dcx().abort_if_errors();
10341043
}
1035-
info!("linker stderr:\n{}", escape_string(&prog.stderr));
1036-
info!("linker stdout:\n{}", escape_string(&prog.stdout));
1044+
1045+
if !prog.stderr.is_empty() {
1046+
// We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
1047+
let stderr = escape_string(&prog.stderr);
1048+
debug!("original stderr: {stderr}");
1049+
let stderr = stderr
1050+
.strip_prefix("warning: ")
1051+
.unwrap_or(&stderr)
1052+
.replace(": warning: ", ": ");
1053+
sess.dcx().emit_warn(LinkerOutput { inner: format!("linker stderr: {stderr}") });
1054+
}
1055+
if !prog.stdout.is_empty() && sess.opts.verbose {
1056+
sess.dcx().emit_warn(LinkerOutput {
1057+
inner: format!("linker stdout: {}", escape_string(&prog.stdout)),
1058+
});
1059+
}
10371060
}
10381061
Err(e) => {
10391062
let linker_not_found = e.kind() == io::ErrorKind::NotFound;

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ use crate::mir::operand::OperandValue;
4444
use crate::mir::place::PlaceRef;
4545
use crate::traits::*;
4646
use crate::{
47-
CachedModuleCodegen, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, errors, meth, mir,
47+
CachedModuleCodegen, CodegenLintLevels, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
48+
errors, meth, mir,
4849
};
4950

5051
pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
@@ -926,6 +927,7 @@ impl CrateInfo {
926927
dependency_formats: Lrc::clone(tcx.dependency_formats(())),
927928
windows_subsystem,
928929
natvis_debugger_visualizers: Default::default(),
930+
lint_levels: CodegenLintLevels::from_tcx(tcx),
929931
};
930932

931933
info.native_libraries.reserve(n_crates);

compiler/rustc_codegen_ssa/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ pub struct CrateInfo {
200200
pub dependency_formats: Lrc<Dependencies>,
201201
pub windows_subsystem: Option<String>,
202202
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
203+
pub lint_levels: CodegenLintLevels,
203204
}
204205

205206
#[derive(Encodable, Decodable)]
Lines changed: 17 additions & 0 deletions
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/rmake.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,25 @@ fn main() {
1010
// first, compile our linker
1111
rustc().arg("fake-linker.rs").output("fake-linker").run();
1212

13+
// Run rustc with our fake linker, and make sure it shows warnings
14+
let warnings = run_rustc().link_arg("run_make_warn").run();
15+
warnings.assert_stderr_contains("warning: linker stderr: bar");
16+
17+
// Make sure it shows stdout, but only when --verbose is passed
18+
run_rustc()
19+
.link_arg("run_make_info")
20+
.verbose()
21+
.run()
22+
.assert_stderr_contains("warning: linker stdout: foo");
23+
run_rustc()
24+
.link_arg("run_make_info")
25+
.run()
26+
.assert_stderr_not_contains("warning: linker stdout: foo");
27+
28+
// Make sure we short-circuit this new path if the linker exits with an error
29+
// (so the diagnostic is less verbose)
30+
run_rustc().link_arg("run_make_error").run_fail().assert_stderr_contains("note: error: baz");
31+
1332
// Make sure we don't show the linker args unless `--verbose` is passed
1433
run_rustc()
1534
.link_arg("run_make_error")

tests/run-make/rust-lld-by-default-beta-stable/rmake.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ use run_make_support::rustc;
1212
fn main() {
1313
// A regular compilation should not use rust-lld by default. We'll check that by asking the
1414
// linker to display its version number with a link-arg.
15-
let output = rustc()
16-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
17-
.link_arg("-Wl,-v")
18-
.input("main.rs")
19-
.run();
15+
let output = rustc().verbose().link_arg("-Wl,-v").input("main.rs").run();
2016
assert!(
2117
!find_lld_version_in_logs(output.stderr_utf8()),
2218
"the LLD version string should not be present in the output logs:\n{}",

tests/run-make/rust-lld-by-default-nightly/rmake.rs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,16 @@ use run_make_support::rustc;
1212
fn main() {
1313
// A regular compilation should use rust-lld by default. We'll check that by asking the linker
1414
// to display its version number with a link-arg.
15-
let output = rustc()
16-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
17-
.link_arg("-Wl,-v")
18-
.input("main.rs")
19-
.run();
15+
let output = rustc().verbose().link_arg("-Wl,-v").input("main.rs").run();
2016
assert!(
2117
find_lld_version_in_logs(output.stderr_utf8()),
2218
"the LLD version string should be present in the output logs:\n{}",
2319
output.stderr_utf8()
2420
);
2521

2622
// But it can still be disabled by turning the linker feature off.
27-
let output = rustc()
28-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
29-
.link_arg("-Wl,-v")
30-
.arg("-Zlinker-features=-lld")
31-
.input("main.rs")
32-
.run();
23+
let output =
24+
rustc().verbose().link_arg("-Wl,-v").arg("-Zlinker-features=-lld").input("main.rs").run();
3325
assert!(
3426
!find_lld_version_in_logs(output.stderr_utf8()),
3527
"the LLD version string should not be present in the output logs:\n{}",
@@ -38,6 +30,7 @@ fn main() {
3830
}
3931

4032
fn find_lld_version_in_logs(stderr: String) -> bool {
41-
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
33+
let lld_version_re =
34+
Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
4235
stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
4336
}

tests/run-make/rust-lld-custom-target/rmake.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn main() {
1515
// Compile to a custom target spec with rust-lld enabled by default. We'll check that by asking
1616
// the linker to display its version number with a link-arg.
1717
let output = rustc()
18-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
18+
.verbose()
1919
.crate_type("cdylib")
2020
.target("custom-target.json")
2121
.link_arg("-Wl,-v")
@@ -29,7 +29,7 @@ fn main() {
2929

3030
// But it can also be disabled via linker features.
3131
let output = rustc()
32-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
32+
.verbose()
3333
.crate_type("cdylib")
3434
.target("custom-target.json")
3535
.arg("-Zlinker-features=-lld")
@@ -44,6 +44,7 @@ fn main() {
4444
}
4545

4646
fn find_lld_version_in_logs(stderr: String) -> bool {
47-
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
47+
let lld_version_re =
48+
Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
4849
stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
4950
}

tests/run-make/rust-lld/rmake.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ fn main() {
1414
// Opt-in to lld and the self-contained linker, to link with rust-lld. We'll check that by
1515
// asking the linker to display its version number with a link-arg.
1616
let output = rustc()
17-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
1817
.arg("-Zlinker-features=+lld")
1918
.arg("-Clink-self-contained=+linker")
2019
.arg("-Zunstable-options")
20+
.verbose()
2121
.link_arg(linker_version_flag)
2222
.input("main.rs")
2323
.run();
@@ -29,8 +29,8 @@ fn main() {
2929

3030
// It should not be used when we explicitly opt-out of lld.
3131
let output = rustc()
32-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
3332
.link_arg(linker_version_flag)
33+
.verbose()
3434
.arg("-Zlinker-features=-lld")
3535
.input("main.rs")
3636
.run();
@@ -43,8 +43,8 @@ fn main() {
4343
// While we're here, also check that the last linker feature flag "wins" when passed multiple
4444
// times to rustc.
4545
let output = rustc()
46-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
4746
.link_arg(linker_version_flag)
47+
.verbose()
4848
.arg("-Clink-self-contained=+linker")
4949
.arg("-Zunstable-options")
5050
.arg("-Zlinker-features=-lld")
@@ -60,6 +60,7 @@ fn main() {
6060
}
6161

6262
fn find_lld_version_in_logs(stderr: String) -> bool {
63-
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
63+
let lld_version_re =
64+
Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
6465
stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
6566
}

0 commit comments

Comments
 (0)