Shorten linker output even more when --verbose is not present · rust-lang/rust@c1b4ab0 (original) (raw)

11 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -3537,6 +3537,7 @@ dependencies = [
3537 3537 "ar_archive_writer",
3538 3538 "arrayvec",
3539 3539 "bitflags",
3540 +"bstr",
3540 3541 "cc",
3541 3542 "either",
3542 3543 "itertools",
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ edition = "2021"
8 8 ar_archive_writer = "0.4.2"
9 9 arrayvec = { version = "0.7", default-features = false }
10 10 bitflags = "2.4.1"
11 +bstr = "1.11.3"
11 12 # Pinned so `cargo update` bumps don't cause breakage. Please also update the
12 13 # `cc` in `rustc_llvm` if you update the `cc` here.
13 14 cc = "=1.2.7"
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ pub(crate) struct Command {
13 13 args: Vec<OsString>,
14 14 env: Vec<(OsString, OsString)>,
15 15 env_remove: Vec<OsString>,
16 +env_clear: bool,
16 17 }
17 18
18 19 #[derive(Clone)]
@@ -36,7 +37,13 @@ impl Command {
36 37 }
37 38
38 39 fn _new(program: Program) -> Command {
39 -Command { program, args: Vec::new(), env: Vec::new(), env_remove: Vec::new() }
40 +Command {
41 + program,
42 +args: Vec::new(),
43 +env: Vec::new(),
44 +env_remove: Vec::new(),
45 +env_clear: false,
46 +}
40 47 }
41 48
42 49 pub(crate) fn arg<P: AsRef<OsStr>>(&mut self, arg: P) -> &mut Command {
@@ -79,6 +86,11 @@ impl Command {
79 86 self
80 87 }
81 88
89 +pub(crate) fn env_clear(&mut self) -> &mut Command {
90 +self.env_clear = true;
91 +self
92 +}
93 +
82 94 fn _env_remove(&mut self, key: &OsStr) {
83 95 self.env_remove.push(key.to_owned());
84 96 }
@@ -106,6 +118,9 @@ impl Command {
106 118 for k in &self.env_remove {
107 119 ret.env_remove(k);
108 120 }
121 +if self.env_clear {
122 + ret.env_clear();
123 +}
109 124 ret
110 125 }
111 126
Original file line number Diff line number Diff line change
@@ -1007,6 +1007,7 @@ fn link_natively(
1007 1007 command: cmd,
1008 1008 escaped_output,
1009 1009 verbose: sess.opts.verbose,
1010 +sysroot_dir: sess.sysroot.clone(),
1010 1011 };
1011 1012 sess.dcx().emit_err(err);
1012 1013 // If MSVC's `link.exe` was expected but the return code
Original file line number Diff line number Diff line change
@@ -351,6 +351,7 @@ pub(crate) struct LinkingFailed<'a> {
351 351 pub command: Command,
352 352 pub escaped_output: String,
353 353 pub verbose: bool,
354 +pub sysroot_dir: PathBuf,
354 355 }
355 356
356 357 impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
@@ -364,6 +365,8 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
364 365 if self.verbose {
365 366 diag.note(format!("{:?}", self.command));
366 367 } else {
368 +self.command.env_clear();
369 +
367 370 enum ArgGroup {
368 371 Regular(OsString),
369 372 Objects(usize),
@@ -398,26 +401,55 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
398 401 args.push(ArgGroup::Regular(arg));
399 402 }
400 403 }
401 -self.command.args(args.into_iter().map(|arg_group
402 -ArgGroup::Regular(arg) => arg,
403 -ArgGroup::Objects(n) => OsString::from(format!("<{n} object files omitted>")),
404 -ArgGroup::Rlibs(dir, rlibs) => {
405 -let mut arg = dir.into_os_string();
406 - arg.push("/{");
407 -let mut first = true;
408 -for rlib in rlibs {
409 -if !first {
410 - arg.push(",");
404 +let crate_hash = regex::bytes::Regex::new(r"-[0-9a-f]+\.rlib$").unwrap();
405 +self.command.args(args.into_iter().map(|arg_group
406 +match arg_group {
407 +// SAFETY: we are only matching on ASCII, not any surrogate pairs, so any replacements we do will still be valid.
408 +ArgGroup::Regular(arg) => unsafe {
409 +use bstr::ByteSlice;
410 +OsString::from_encoded_bytes_unchecked(
411 + arg.as_encoded_bytes().replace(
412 +self.sysroot_dir.as_os_str().as_encoded_bytes(),
413 +b"",
414 +),
415 +)
416 +},
417 +ArgGroup::Objects(n) => OsString::from(format!("<{n} object files omitted>")),
418 +ArgGroup::Rlibs(mut dir, rlibs) => {
419 +let is_sysroot_dir = match dir.strip_prefix(&self.sysroot_dir) {
420 +Ok(short) => {
421 + dir = Path::new("").join(short);
422 +true
423 +}
424 +Err(_) => false,
425 +};
426 +let mut arg = dir.into_os_string();
427 + arg.push("/{");
428 +let mut first = true;
429 +for mut rlib in rlibs {
430 +if !first {
431 + arg.push(",");
432 +}
433 + first = false;
434 +if is_sysroot_dir {
435 +// SAFETY: Regex works one byte at a type, and our regex will not match surrogate pairs (because it only matches ascii).
436 + rlib = unsafe {
437 +OsString::from_encoded_bytes_unchecked(
438 + crate_hash
439 +.replace(rlib.as_encoded_bytes(), b"-*")
440 +.into_owned(),
441 +)
442 +};
443 +}
444 + arg.push(rlib);
411 445 }
412 -first = false;
413 - arg.push(rlib);
446 +arg.push("}.rlib");
447 + arg
414 448 }
415 - arg.push("}");
416 - arg
417 449 }
418 450 }));
419 451
420 - diag.note(format!("{:?}", self.command));
452 + diag.note(format!("{:?}", self.command).trim_start_matches("env -i").to_owned());
421 453 diag.note("some arguments are omitted. use `--verbose` to show all linker arguments");
422 454 }
423 455
Original file line number Diff line number Diff line change
@@ -414,6 +414,8 @@ impl TestCx<'_> {
414 414 // Provide path to checkout root. This is the top-level directory containing
415 415 // rust-lang/rust checkout.
416 416 .env("SOURCE_ROOT", &source_root)
417 +// Path to the build directory. This is usually the same as `source_root.join("build").join("host")`.
418 +.env("BUILD_ROOT", &build_root)
417 419 // Provide path to stage-corresponding rustc.
418 420 .env("RUSTC", &self.config.rustc_path)
419 421 // Provide the directory to libraries that are needed to run the *compiler*. This is not
Original file line number Diff line number Diff line change
@@ -90,7 +90,7 @@ pub use artifact_names::{
90 90 /// Path-related helpers.
91 91 pub use path_helpers::{
92 92 cwd, filename_contains, filename_not_in_denylist, has_extension, has_prefix, has_suffix,
93 - not_contains, path, shallow_find_files, source_root,
93 + not_contains, path, shallow_find_files, build_root, source_root,
94 94 };
95 95
96 96 /// Helpers for scoped test execution where certain properties are attempted to be maintained.
Original file line number Diff line number Diff line change
@@ -34,6 +34,12 @@ pub fn source_root() -> PathBuf {
34 34 env_var("SOURCE_ROOT").into()
35 35 }
36 36
37 +/// Path to the build directory root.
38 +#[must_use]
39 +pub fn build_root() -> PathBuf {
40 +env_var("BUILD_ROOT").into()
41 +}
42 +
37 43 /// Browse the directory `path` non-recursively and return all files which respect the parameters
38 44 /// outlined by `closure`.
39 45 #[track_caller]
Original file line number Diff line number Diff line change
@@ -253,6 +253,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
253 253 "bitflags",
254 254 "blake3",
255 255 "block-buffer",
256 +"bstr",
256 257 "byteorder", // via ruzstd in object in thorin-dwp
257 258 "cc",
258 259 "cfg-if",
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
1 -use run_make_support::{Rustc, rustc};
1 +use run_make_support::{Rustc, diff, regex, rustc};
2 2
3 3 fn run_rustc() -> Rustc {
4 4 let mut rustc = rustc();
5 - rustc.arg("main.rs").output("main").linker("./fake-linker");
5 + rustc
6 +.arg("main.rs")
7 +// NOTE: `link-self-contained` can vary depending on config.toml.
8 +// Make sure we use a consistent value.
9 +.arg("-Clink-self-contained=-linker")
10 +.arg("-Zunstable-options")
11 +.output("main")
12 +.linker("./fake-linker");
13 +if run_make_support::target() == "x86_64-unknown-linux-gnu" {
14 +// The value of `rust.lld` is different between CI and locally. Override it explicitly.
15 + rustc.arg("-Clinker-flavor=gnu-cc");
16 +}
6 17 rustc
7 18 }
8 19
@@ -25,21 +36,32 @@ fn main() {
25 36 run_rustc().link_arg("run_make_error").run_fail().assert_stderr_contains("note: error: baz");
26 37
27 38 // Make sure we don't show the linker args unless `--verbose` is passed
28 -run_rustc()
29 -.link_arg("run_make_error")
30 -.verbose()
31 -.run_fail()
32 -.assert_stderr_contains_regex("fake-linker.*run_make_error")
39 +let out = run_rustc().link_arg("run_make_error").verbose().run_fail();
40 + out.assert_stderr_contains_regex("fake-linker.*run_make_error")
33 41 .assert_stderr_not_contains("object files omitted")
42 +.assert_stderr_contains(r".rcgu.o")
34 43 .assert_stderr_contains_regex(r"lib(/|\\\\)libstd");
35 -run_rustc()
36 -.link_arg("run_make_error")
37 -.run_fail()
38 -.assert_stderr_contains("fake-linker")
44 +
45 +let out = run_rustc().link_arg("run_make_error").run_fail();
46 + out.assert_stderr_contains("fake-linker")
39 47 .assert_stderr_contains("object files omitted")
40 48 .assert_stderr_contains_regex(r"\{")
49 +.assert_stderr_not_contains(r".rcgu.o")
41 50 .assert_stderr_not_contains_regex(r"lib(/|\\\\)libstd");
42 51
52 +// FIXME: we should have a version of this for mac and windows
53 +if run_make_support::target() == "x86_64-unknown-linux-gnu" {
54 +diff()
55 +.expected_file("short-error.txt")
56 +.actual_text("(linker error)", out.stderr())
57 +.normalize(r#"/rustc[^/]*/"#, "/rustc/")
58 +.normalize(
59 + regex::escape(run_make_support::build_root().to_str().unwrap()),
60 +"/build-root",
61 +)
62 +.run();
63 +}
64 +
43 65 // Make sure we show linker warnings even across `-Z no-link`
44 66 rustc()
45 67 .arg("-Zno-link")
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
1 +error: linking with `./fake-linker` failed: exit status: 1
2 + |
3 + = note: "./fake-linker" "-m64" "/tmp/rustc/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,liballoc-*,librustc_std_workspace_core-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/build-root/test/run-make/linker-warning/rmake_out" "-L" "/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error"
4 + = note: some arguments are omitted. use `--verbose` to show all linker arguments
5 + = note: error: baz
6 +
7 +
8 +error: aborting due to 1 previous error
9 +