mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
Rollup merge of #133633 - jyn514:hide-linker-args, r=bjorn3,jyn514
don't show the full linker args unless `--verbose` is passed the linker arguments can be *very* long, especially for crates with many dependencies. often they are not useful. omit them unless the user specifically requests them. split out from https://github.com/rust-lang/rust/pull/119286. fixes https://github.com/rust-lang/rust/issues/109979. r? `@bjorn3` try-build: i686-mingw
This commit is contained in:
commit
5ce0d812fa
@ -986,12 +986,12 @@ fn link_natively(
|
|||||||
let mut output = prog.stderr.clone();
|
let mut output = prog.stderr.clone();
|
||||||
output.extend_from_slice(&prog.stdout);
|
output.extend_from_slice(&prog.stdout);
|
||||||
let escaped_output = escape_linker_output(&output, flavor);
|
let escaped_output = escape_linker_output(&output, flavor);
|
||||||
// FIXME: Add UI tests for this error.
|
|
||||||
let err = errors::LinkingFailed {
|
let err = errors::LinkingFailed {
|
||||||
linker_path: &linker_path,
|
linker_path: &linker_path,
|
||||||
exit_status: prog.status,
|
exit_status: prog.status,
|
||||||
command: &cmd,
|
command: cmd,
|
||||||
escaped_output,
|
escaped_output,
|
||||||
|
verbose: sess.opts.verbose,
|
||||||
};
|
};
|
||||||
sess.dcx().emit_err(err);
|
sess.dcx().emit_err(err);
|
||||||
// If MSVC's `link.exe` was expected but the return code
|
// If MSVC's `link.exe` was expected but the return code
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Errors emitted by codegen_ssa
|
//! Errors emitted by codegen_ssa
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::ffi::OsString;
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -345,21 +346,82 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for ThorinErrorWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct LinkingFailed<'a> {
|
pub(crate) struct LinkingFailed<'a> {
|
||||||
pub linker_path: &'a PathBuf,
|
pub linker_path: &'a Path,
|
||||||
pub exit_status: ExitStatus,
|
pub exit_status: ExitStatus,
|
||||||
pub command: &'a Command,
|
pub command: Command,
|
||||||
pub escaped_output: String,
|
pub escaped_output: String,
|
||||||
|
pub verbose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
|
impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
|
||||||
fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
|
fn into_diag(mut self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> {
|
||||||
let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_linking_failed);
|
let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_linking_failed);
|
||||||
diag.arg("linker_path", format!("{}", self.linker_path.display()));
|
diag.arg("linker_path", format!("{}", self.linker_path.display()));
|
||||||
diag.arg("exit_status", format!("{}", self.exit_status));
|
diag.arg("exit_status", format!("{}", self.exit_status));
|
||||||
|
|
||||||
let contains_undefined_ref = self.escaped_output.contains("undefined reference to");
|
let contains_undefined_ref = self.escaped_output.contains("undefined reference to");
|
||||||
|
|
||||||
diag.note(format!("{:?}", self.command)).note(self.escaped_output);
|
if self.verbose {
|
||||||
|
diag.note(format!("{:?}", self.command));
|
||||||
|
} else {
|
||||||
|
enum ArgGroup {
|
||||||
|
Regular(OsString),
|
||||||
|
Objects(usize),
|
||||||
|
Rlibs(PathBuf, Vec<OsString>),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Omit rust object files and fold rlibs in the error by default to make linker errors a
|
||||||
|
// bit less verbose.
|
||||||
|
let orig_args = self.command.take_args();
|
||||||
|
let mut args: Vec<ArgGroup> = vec![];
|
||||||
|
for arg in orig_args {
|
||||||
|
if arg.as_encoded_bytes().ends_with(b".rcgu.o") {
|
||||||
|
if let Some(ArgGroup::Objects(n)) = args.last_mut() {
|
||||||
|
*n += 1;
|
||||||
|
} else {
|
||||||
|
args.push(ArgGroup::Objects(1));
|
||||||
|
}
|
||||||
|
} else if arg.as_encoded_bytes().ends_with(b".rlib") {
|
||||||
|
let rlib_path = Path::new(&arg);
|
||||||
|
let dir = rlib_path.parent().unwrap();
|
||||||
|
let filename = rlib_path.file_name().unwrap().to_owned();
|
||||||
|
if let Some(ArgGroup::Rlibs(parent, rlibs)) = args.last_mut() {
|
||||||
|
if parent == dir {
|
||||||
|
rlibs.push(filename);
|
||||||
|
} else {
|
||||||
|
args.push(ArgGroup::Rlibs(dir.to_owned(), vec![filename]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args.push(ArgGroup::Rlibs(dir.to_owned(), vec![filename]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args.push(ArgGroup::Regular(arg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.command.args(args.into_iter().map(|arg_group| match arg_group {
|
||||||
|
ArgGroup::Regular(arg) => arg,
|
||||||
|
ArgGroup::Objects(n) => OsString::from(format!("<{n} object files omitted>")),
|
||||||
|
ArgGroup::Rlibs(dir, rlibs) => {
|
||||||
|
let mut arg = dir.into_os_string();
|
||||||
|
arg.push("/{");
|
||||||
|
let mut first = true;
|
||||||
|
for rlib in rlibs {
|
||||||
|
if !first {
|
||||||
|
arg.push(",");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
arg.push(rlib);
|
||||||
|
}
|
||||||
|
arg.push("}");
|
||||||
|
arg
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
diag.note(format!("{:?}", self.command));
|
||||||
|
diag.note("some arguments are omitted. use `--verbose` to show all linker arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
diag.note(self.escaped_output);
|
||||||
|
|
||||||
// Trying to match an error from OS linkers
|
// Trying to match an error from OS linkers
|
||||||
// which by now we have no way to translate.
|
// which by now we have no way to translate.
|
||||||
|
@ -325,6 +325,12 @@ impl Rustc {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pass the `--verbose` flag.
|
||||||
|
pub fn verbose(&mut self) -> &mut Self {
|
||||||
|
self.cmd.arg("--verbose");
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// `EXTRARSCXXFLAGS`
|
/// `EXTRARSCXXFLAGS`
|
||||||
pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
|
pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
|
||||||
// Adapted from tools.mk (trimmed):
|
// Adapted from tools.mk (trimmed):
|
||||||
|
@ -15,8 +15,9 @@ fn main() {
|
|||||||
.link_args("b c")
|
.link_args("b c")
|
||||||
.link_args("d e")
|
.link_args("d e")
|
||||||
.link_arg("f")
|
.link_arg("f")
|
||||||
|
.arg("--print=link-args")
|
||||||
.run_fail()
|
.run_fail()
|
||||||
.assert_stderr_contains(r#""a" "b" "c" "d" "e" "f""#);
|
.assert_stdout_contains(r#""a" "b" "c" "d" "e" "f""#);
|
||||||
rustc()
|
rustc()
|
||||||
.input("empty.rs")
|
.input("empty.rs")
|
||||||
.linker_flavor(linker)
|
.linker_flavor(linker)
|
||||||
@ -24,6 +25,7 @@ fn main() {
|
|||||||
.arg("-Zpre-link-args=b c")
|
.arg("-Zpre-link-args=b c")
|
||||||
.arg("-Zpre-link-args=d e")
|
.arg("-Zpre-link-args=d e")
|
||||||
.arg("-Zpre-link-arg=f")
|
.arg("-Zpre-link-arg=f")
|
||||||
|
.arg("--print=link-args")
|
||||||
.run_fail()
|
.run_fail()
|
||||||
.assert_stderr_contains(r#""a" "b" "c" "d" "e" "f""#);
|
.assert_stdout_contains(r#""a" "b" "c" "d" "e" "f""#);
|
||||||
}
|
}
|
||||||
|
@ -14,13 +14,13 @@ fn main() {
|
|||||||
rustc().input("depb.rs").run();
|
rustc().input("depb.rs").run();
|
||||||
rustc().input("depc.rs").run();
|
rustc().input("depc.rs").run();
|
||||||
|
|
||||||
let output = rustc().input("empty.rs").cfg("bar").run_fail();
|
let output = rustc().input("empty.rs").cfg("bar").arg("--print=link-args").run_fail();
|
||||||
output.assert_stderr_contains(needle_from_libs(&["testa", "testb", "testa"]));
|
output.assert_stdout_contains(needle_from_libs(&["testa", "testb", "testa"]));
|
||||||
|
|
||||||
let output = rustc().input("empty.rs").run_fail();
|
let output = rustc().input("empty.rs").arg("--print=link-args").run_fail();
|
||||||
output.assert_stderr_contains(needle_from_libs(&["testa"]));
|
output.assert_stdout_contains(needle_from_libs(&["testa"]));
|
||||||
output.assert_stderr_not_contains(needle_from_libs(&["testb"]));
|
output.assert_stdout_not_contains(needle_from_libs(&["testb"]));
|
||||||
output.assert_stderr_not_contains(needle_from_libs(&["testa", "testa", "testa"]));
|
output.assert_stdout_not_contains(needle_from_libs(&["testa", "testa", "testa"]));
|
||||||
// Adjacent identical native libraries are no longer deduplicated if
|
// Adjacent identical native libraries are no longer deduplicated if
|
||||||
// they come from different crates (https://github.com/rust-lang/rust/pull/103311)
|
// they come from different crates (https://github.com/rust-lang/rust/pull/103311)
|
||||||
// so the following will fail:
|
// so the following will fail:
|
||||||
|
13
tests/run-make/linker-warning/fake-linker.rs
Normal file
13
tests/run-make/linker-warning/fake-linker.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
fn main() {
|
||||||
|
for arg in std::env::args() {
|
||||||
|
match &*arg {
|
||||||
|
"run_make_info" => println!("foo"),
|
||||||
|
"run_make_warn" => eprintln!("warning: bar"),
|
||||||
|
"run_make_error" => {
|
||||||
|
eprintln!("error: baz");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
tests/run-make/linker-warning/main.rs
Normal file
1
tests/run-make/linker-warning/main.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
fn main() {}
|
28
tests/run-make/linker-warning/rmake.rs
Normal file
28
tests/run-make/linker-warning/rmake.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use run_make_support::{Rustc, rustc};
|
||||||
|
|
||||||
|
fn run_rustc() -> Rustc {
|
||||||
|
let mut rustc = rustc();
|
||||||
|
rustc.arg("main.rs").output("main").linker("./fake-linker");
|
||||||
|
rustc
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// first, compile our linker
|
||||||
|
rustc().arg("fake-linker.rs").output("fake-linker").run();
|
||||||
|
|
||||||
|
// Make sure we don't show the linker args unless `--verbose` is passed
|
||||||
|
run_rustc()
|
||||||
|
.link_arg("run_make_error")
|
||||||
|
.verbose()
|
||||||
|
.run_fail()
|
||||||
|
.assert_stderr_contains_regex("fake-linker.*run_make_error")
|
||||||
|
.assert_stderr_not_contains("object files omitted")
|
||||||
|
.assert_stderr_contains_regex(r"lib(/|\\\\)libstd");
|
||||||
|
run_rustc()
|
||||||
|
.link_arg("run_make_error")
|
||||||
|
.run_fail()
|
||||||
|
.assert_stderr_contains("fake-linker")
|
||||||
|
.assert_stderr_contains("object files omitted")
|
||||||
|
.assert_stderr_contains_regex(r"\{")
|
||||||
|
.assert_stderr_not_contains_regex(r"lib(/|\\\\)libstd");
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user