1
Fork 0

show linker warnings even if it returns 0

This commit is contained in:
jyn 2023-12-24 18:38:00 -05:00
parent 9f4d9dc102
commit c0822ed9b8
10 changed files with 82 additions and 27 deletions

View file

@ -183,6 +183,8 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
codegen_ssa_linker_not_found = linker `{$linker_path}` not found
.note = {$error}
codegen_ssa_linker_output = {$inner}
codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}

View file

@ -18,6 +18,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::DiagCtxtHandle;
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_macros::Diagnostic;
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs};
use rustc_middle::bug;
@ -749,6 +750,14 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out
}
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_linker_output)]
/// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just
/// end up with inconsistent languages within the same diagnostic.
struct LinkerOutput {
inner: String,
}
/// Create a dynamic library or executable.
///
/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
@ -1028,8 +1037,22 @@ fn link_natively(
sess.dcx().abort_if_errors();
}
info!("linker stderr:\n{}", escape_string(&prog.stderr));
info!("linker stdout:\n{}", escape_string(&prog.stdout));
if !prog.stderr.is_empty() {
// We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
let stderr = escape_string(&prog.stderr);
debug!("original stderr: {stderr}");
let stderr = stderr
.strip_prefix("warning: ")
.unwrap_or(&stderr)
.replace(": warning: ", ": ");
sess.dcx().emit_warn(LinkerOutput { inner: format!("linker stderr: {stderr}") });
}
if !prog.stdout.is_empty() && sess.opts.verbose {
sess.dcx().emit_warn(LinkerOutput {
inner: format!("linker stdout: {}", escape_string(&prog.stdout)),
});
}
}
Err(e) => {
let linker_not_found = e.kind() == io::ErrorKind::NotFound;

View file

@ -44,7 +44,8 @@ use crate::mir::operand::OperandValue;
use crate::mir::place::PlaceRef;
use crate::traits::*;
use crate::{
CachedModuleCodegen, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, errors, meth, mir,
CachedModuleCodegen, CodegenLintLevels, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
errors, meth, mir,
};
pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
@ -927,6 +928,7 @@ impl CrateInfo {
dependency_formats: Lrc::clone(tcx.dependency_formats(())),
windows_subsystem,
natvis_debugger_visualizers: Default::default(),
lint_levels: CodegenLintLevels::from_tcx(tcx),
};
info.native_libraries.reserve(n_crates);

View file

@ -200,6 +200,7 @@ pub struct CrateInfo {
pub dependency_formats: Lrc<Dependencies>,
pub windows_subsystem: Option<String>,
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
pub lint_levels: CodegenLintLevels,
}
#[derive(Encodable, Decodable)]

View file

@ -0,0 +1,17 @@
#!/bin/sh
code=0
while ! [ $# = 0 ]; do
case "$1" in
run_make_info) echo "foo"
;;
run_make_warn) echo "warning: bar" >&2
;;
run_make_error) echo "error: baz" >&2; code=1
;;
*) ;; # rustc passes lots of args we don't care about
esac
shift
done
exit $code

View file

@ -10,6 +10,25 @@ fn main() {
// first, compile our linker
rustc().arg("fake-linker.rs").output("fake-linker").run();
// Run rustc with our fake linker, and make sure it shows warnings
let warnings = run_rustc().link_arg("run_make_warn").run();
warnings.assert_stderr_contains("warning: linker stderr: bar");
// Make sure it shows stdout, but only when --verbose is passed
run_rustc()
.link_arg("run_make_info")
.verbose()
.run()
.assert_stderr_contains("warning: linker stdout: foo");
run_rustc()
.link_arg("run_make_info")
.run()
.assert_stderr_not_contains("warning: linker stdout: foo");
// Make sure we short-circuit this new path if the linker exits with an error
// (so the diagnostic is less verbose)
run_rustc().link_arg("run_make_error").run_fail().assert_stderr_contains("note: error: baz");
// Make sure we don't show the linker args unless `--verbose` is passed
run_rustc()
.link_arg("run_make_error")

View file

@ -12,11 +12,7 @@ use run_make_support::rustc;
fn main() {
// A regular compilation should not use rust-lld by default. We'll check that by asking the
// linker to display its version number with a link-arg.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
.link_arg("-Wl,-v")
.input("main.rs")
.run();
let output = rustc().verbose().link_arg("-Wl,-v").input("main.rs").run();
assert!(
!find_lld_version_in_logs(output.stderr_utf8()),
"the LLD version string should not be present in the output logs:\n{}",

View file

@ -12,11 +12,7 @@ use run_make_support::rustc;
fn main() {
// A regular compilation should use rust-lld by default. We'll check that by asking the linker
// to display its version number with a link-arg.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
.link_arg("-Wl,-v")
.input("main.rs")
.run();
let output = rustc().verbose().link_arg("-Wl,-v").input("main.rs").run();
assert!(
find_lld_version_in_logs(output.stderr_utf8()),
"the LLD version string should be present in the output logs:\n{}",
@ -24,12 +20,8 @@ fn main() {
);
// But it can still be disabled by turning the linker feature off.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
.link_arg("-Wl,-v")
.arg("-Zlinker-features=-lld")
.input("main.rs")
.run();
let output =
rustc().verbose().link_arg("-Wl,-v").arg("-Zlinker-features=-lld").input("main.rs").run();
assert!(
!find_lld_version_in_logs(output.stderr_utf8()),
"the LLD version string should not be present in the output logs:\n{}",
@ -38,6 +30,7 @@ fn main() {
}
fn find_lld_version_in_logs(stderr: String) -> bool {
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
let lld_version_re =
Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
}

View file

@ -15,7 +15,7 @@ fn main() {
// Compile to a custom target spec with rust-lld enabled by default. We'll check that by asking
// the linker to display its version number with a link-arg.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
.verbose()
.crate_type("cdylib")
.target("custom-target.json")
.link_arg("-Wl,-v")
@ -29,7 +29,7 @@ fn main() {
// But it can also be disabled via linker features.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
.verbose()
.crate_type("cdylib")
.target("custom-target.json")
.arg("-Zlinker-features=-lld")
@ -44,6 +44,7 @@ fn main() {
}
fn find_lld_version_in_logs(stderr: String) -> bool {
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
let lld_version_re =
Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
}

View file

@ -14,10 +14,10 @@ fn main() {
// Opt-in to lld and the self-contained linker, to link with rust-lld. We'll check that by
// asking the linker to display its version number with a link-arg.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
.arg("-Zlinker-features=+lld")
.arg("-Clink-self-contained=+linker")
.arg("-Zunstable-options")
.verbose()
.link_arg(linker_version_flag)
.input("main.rs")
.run();
@ -29,8 +29,8 @@ fn main() {
// It should not be used when we explicitly opt-out of lld.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
.link_arg(linker_version_flag)
.verbose()
.arg("-Zlinker-features=-lld")
.input("main.rs")
.run();
@ -43,8 +43,8 @@ fn main() {
// While we're here, also check that the last linker feature flag "wins" when passed multiple
// times to rustc.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
.link_arg(linker_version_flag)
.verbose()
.arg("-Clink-self-contained=+linker")
.arg("-Zunstable-options")
.arg("-Zlinker-features=-lld")
@ -60,6 +60,7 @@ fn main() {
}
fn find_lld_version_in_logs(stderr: String) -> bool {
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
let lld_version_re =
Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
}