Shorten linker output even more when --verbose
is not present
- Don't show environment variables. Seeing PATH is almost never useful, and it can be extremely long. - For .rlibs in the sysroot, replace crate hashes with a `"-*"` string. This will expand to the full crate name when pasted into the shell. - Move `.rlib` to outside the glob. - Abbreviate the sysroot path to `<sysroot>` wherever it appears in the arguments. This also adds an example of the linker output as a run-make test. Currently it only runs on x86_64-unknown-linux-gnu, because each platform has its own linker arguments. So that it's stable across machines, pass BUILD_ROOT as an argument through compiletest through to run-make tests. - Only use linker-flavor=gnu-cc if we're actually going to compare the output. It doesn't exist on MacOS.
This commit is contained in:
parent
f7cc13af82
commit
c1b4ab0e73
11 changed files with 118 additions and 28 deletions
|
@ -8,6 +8,7 @@ edition = "2021"
|
|||
ar_archive_writer = "0.4.2"
|
||||
arrayvec = { version = "0.7", default-features = false }
|
||||
bitflags = "2.4.1"
|
||||
bstr = "1.11.3"
|
||||
# Pinned so `cargo update` bumps don't cause breakage. Please also update the
|
||||
# `cc` in `rustc_llvm` if you update the `cc` here.
|
||||
cc = "=1.2.7"
|
||||
|
|
|
@ -13,6 +13,7 @@ pub(crate) struct Command {
|
|||
args: Vec<OsString>,
|
||||
env: Vec<(OsString, OsString)>,
|
||||
env_remove: Vec<OsString>,
|
||||
env_clear: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -36,7 +37,13 @@ impl Command {
|
|||
}
|
||||
|
||||
fn _new(program: Program) -> Command {
|
||||
Command { program, args: Vec::new(), env: Vec::new(), env_remove: Vec::new() }
|
||||
Command {
|
||||
program,
|
||||
args: Vec::new(),
|
||||
env: Vec::new(),
|
||||
env_remove: Vec::new(),
|
||||
env_clear: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn arg<P: AsRef<OsStr>>(&mut self, arg: P) -> &mut Command {
|
||||
|
@ -79,6 +86,11 @@ impl Command {
|
|||
self
|
||||
}
|
||||
|
||||
pub(crate) fn env_clear(&mut self) -> &mut Command {
|
||||
self.env_clear = true;
|
||||
self
|
||||
}
|
||||
|
||||
fn _env_remove(&mut self, key: &OsStr) {
|
||||
self.env_remove.push(key.to_owned());
|
||||
}
|
||||
|
@ -106,6 +118,9 @@ impl Command {
|
|||
for k in &self.env_remove {
|
||||
ret.env_remove(k);
|
||||
}
|
||||
if self.env_clear {
|
||||
ret.env_clear();
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
|
|
|
@ -1007,6 +1007,7 @@ fn link_natively(
|
|||
command: cmd,
|
||||
escaped_output,
|
||||
verbose: sess.opts.verbose,
|
||||
sysroot_dir: sess.sysroot.clone(),
|
||||
};
|
||||
sess.dcx().emit_err(err);
|
||||
// If MSVC's `link.exe` was expected but the return code
|
||||
|
|
|
@ -351,6 +351,7 @@ pub(crate) struct LinkingFailed<'a> {
|
|||
pub command: Command,
|
||||
pub escaped_output: String,
|
||||
pub verbose: bool,
|
||||
pub sysroot_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
|
||||
|
@ -364,6 +365,8 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
|
|||
if self.verbose {
|
||||
diag.note(format!("{:?}", self.command));
|
||||
} else {
|
||||
self.command.env_clear();
|
||||
|
||||
enum ArgGroup {
|
||||
Regular(OsString),
|
||||
Objects(usize),
|
||||
|
@ -398,26 +401,55 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
|
|||
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(",");
|
||||
let crate_hash = regex::bytes::Regex::new(r"-[0-9a-f]+\.rlib$").unwrap();
|
||||
self.command.args(args.into_iter().map(|arg_group| {
|
||||
match arg_group {
|
||||
// SAFETY: we are only matching on ASCII, not any surrogate pairs, so any replacements we do will still be valid.
|
||||
ArgGroup::Regular(arg) => unsafe {
|
||||
use bstr::ByteSlice;
|
||||
OsString::from_encoded_bytes_unchecked(
|
||||
arg.as_encoded_bytes().replace(
|
||||
self.sysroot_dir.as_os_str().as_encoded_bytes(),
|
||||
b"<sysroot>",
|
||||
),
|
||||
)
|
||||
},
|
||||
ArgGroup::Objects(n) => OsString::from(format!("<{n} object files omitted>")),
|
||||
ArgGroup::Rlibs(mut dir, rlibs) => {
|
||||
let is_sysroot_dir = match dir.strip_prefix(&self.sysroot_dir) {
|
||||
Ok(short) => {
|
||||
dir = Path::new("<sysroot>").join(short);
|
||||
true
|
||||
}
|
||||
Err(_) => false,
|
||||
};
|
||||
let mut arg = dir.into_os_string();
|
||||
arg.push("/{");
|
||||
let mut first = true;
|
||||
for mut rlib in rlibs {
|
||||
if !first {
|
||||
arg.push(",");
|
||||
}
|
||||
first = false;
|
||||
if is_sysroot_dir {
|
||||
// SAFETY: Regex works one byte at a type, and our regex will not match surrogate pairs (because it only matches ascii).
|
||||
rlib = unsafe {
|
||||
OsString::from_encoded_bytes_unchecked(
|
||||
crate_hash
|
||||
.replace(rlib.as_encoded_bytes(), b"-*")
|
||||
.into_owned(),
|
||||
)
|
||||
};
|
||||
}
|
||||
arg.push(rlib);
|
||||
}
|
||||
first = false;
|
||||
arg.push(rlib);
|
||||
arg.push("}.rlib");
|
||||
arg
|
||||
}
|
||||
arg.push("}");
|
||||
arg
|
||||
}
|
||||
}));
|
||||
|
||||
diag.note(format!("{:?}", self.command));
|
||||
diag.note(format!("{:?}", self.command).trim_start_matches("env -i").to_owned());
|
||||
diag.note("some arguments are omitted. use `--verbose` to show all linker arguments");
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue