From c0822ed9b8807ff350e24377e9d1999cc28edf0f Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 24 Dec 2023 18:38:00 -0500 Subject: show linker warnings even if it returns 0 --- compiler/rustc_codegen_ssa/src/back/link.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src/back') diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index df35b5e8426..378b6a50f7f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -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; -- cgit 1.4.1-3-g733a5 From 537218afb2b7f6c8ef9793a52b45c73d1dcb4d4c Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 16 Oct 2024 01:14:10 -0400 Subject: make it possible to silence linker warnings with a crate-level attribute this was slightly complicated because codegen_ssa doesn't have access to a tcx. --- compiler/rustc_codegen_ssa/src/back/link.rs | 21 ++++++++++++------ compiler/rustc_codegen_ssa/src/lib.rs | 21 ++++++++++++++++++ compiler/rustc_lint_defs/src/builtin.rs | 34 +++++++++++++++++++++++++++++ compiler/rustc_lint_defs/src/lib.rs | 14 +++++++++++- compiler/rustc_middle/src/lint.rs | 6 ++--- 5 files changed, 85 insertions(+), 11 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src/back') diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 378b6a50f7f..80758aac134 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -15,13 +15,14 @@ use rustc_ast::CRATE_NODE_ID; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{DiagCtxtHandle, LintDiagnostic}; 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_macros::LintDiagnostic; 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; +use rustc_middle::lint::lint_level; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::SymbolExportKind; @@ -30,6 +31,7 @@ use rustc_session::config::{ OutputType, PrintKind, SplitDwarfKind, Strip, }; use rustc_session::cstore::DllImport; +use rustc_session::lint::builtin::LINKER_MESSAGES; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; @@ -750,7 +752,7 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out } } -#[derive(Diagnostic)] +#[derive(LintDiagnostic)] #[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. @@ -1038,6 +1040,13 @@ fn link_natively( sess.dcx().abort_if_errors(); } + let (level, src) = codegen_results.crate_info.lint_levels.linker_messages; + let lint = |msg| { + lint_level(sess, LINKER_MESSAGES, level, src, None, |diag| { + LinkerOutput { inner: msg }.decorate_lint(diag) + }) + }; + 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); @@ -1046,12 +1055,10 @@ fn link_natively( .strip_prefix("warning: ") .unwrap_or(&stderr) .replace(": warning: ", ": "); - sess.dcx().emit_warn(LinkerOutput { inner: format!("linker stderr: {stderr}") }); + lint(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)), - }); + lint(format!("linker stdout: {}", escape_string(&prog.stdout))) } } Err(e) => { diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 332f2ffbc88..40299ae2630 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -29,18 +29,23 @@ use rustc_ast as ast; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::unord::UnordMap; +use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::CrateNum; use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_middle::dep_graph::WorkProduct; +use rustc_middle::lint::LintLevelSource; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; +use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_serialize::opaque::{FileEncoder, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; +use rustc_session::lint::Level; +use rustc_session::lint::builtin::LINKER_MESSAGES; use rustc_session::utils::NativeLibKind; use rustc_span::Symbol; @@ -303,3 +308,19 @@ impl CodegenResults { Ok((codegen_results, outputs)) } } + +/// A list of lint levels used in codegen. +/// +/// When using `-Z link-only`, we don't have access to the tcx and must work +/// solely from the `.rlink` file. `Lint`s are defined too early to be encodeable. +/// Instead, encode exactly the information we need. +#[derive(Copy, Clone, Debug, Encodable, Decodable)] +pub struct CodegenLintLevels { + linker_messages: (Level, LintLevelSource), +} + +impl CodegenLintLevels { + pub fn from_tcx(tcx: TyCtxt<'_>) -> Self { + Self { linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID) } + } +} diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 9fc527a6a3a..5cdd18f5ea9 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -60,6 +60,7 @@ declare_lint_pass! { LARGE_ASSIGNMENTS, LATE_BOUND_LIFETIME_ARGUMENTS, LEGACY_DERIVE_HELPERS, + LINKER_MESSAGES, LONG_RUNNING_CONST_EVAL, LOSSY_PROVENANCE_CASTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, @@ -4085,6 +4086,39 @@ declare_lint! { "call to foreign functions or function pointers with FFI-unwind ABI" } +declare_lint! { + /// The `linker_messages` lint forwards warnings from the linker. + /// + /// ### Example + /// + /// ```rust,ignore (needs CLI args, platform-specific) + /// extern "C" { + /// fn foo(); + /// } + /// fn main () { unsafe { foo(); } } + /// ``` + /// + /// On Linux, using `gcc -Wl,--warn-unresolved-symbols` as a linker, this will produce + /// + /// ```text + /// warning: linker stderr: rust-lld: undefined symbol: foo + /// >>> referenced by rust_out.69edbd30df4ae57d-cgu.0 + /// >>> rust_out.rust_out.69edbd30df4ae57d-cgu.0.rcgu.o:(rust_out::main::h3a90094b06757803) + /// | + /// = note: `#[warn(linker_messages)]` on by default + /// + /// warning: 1 warning emitted + /// ``` + /// + /// ### Explanation + /// + /// Linkers emit platform-specific and program-specific warnings that cannot be predicted in advance by the rust compiler. + /// They are forwarded by default, but can be disabled by adding `#![allow(linker_messages)]` at the crate root. + pub LINKER_MESSAGES, + Warn, + "warnings emitted at runtime by the target-specific linker program" +} + declare_lint! { /// The `named_arguments_used_positionally` lint detects cases where named arguments are only /// used positionally in format strings. This usage is valid but potentially very confusing. diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7786d3eb59a..9f4c5d89d0e 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -161,7 +161,19 @@ impl ToStableHashKey for LintExpectation /// Setting for how to handle a lint. /// /// See: -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, HashStable_Generic)] +#[derive( + Clone, + Copy, + PartialEq, + PartialOrd, + Eq, + Ord, + Debug, + Hash, + Encodable, + Decodable, + HashStable_Generic +)] pub enum Level { /// The `allow` level will not issue any message. Allow, diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 620d9f1c357..cae980cde61 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::{Diag, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; -use rustc_macros::HashStable; +use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_session::Session; use rustc_session::lint::builtin::{self, FORBIDDEN_LINT_GROUPS}; use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId}; @@ -15,7 +15,7 @@ use tracing::instrument; use crate::ty::TyCtxt; /// How a lint level was set. -#[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, HashStable, Debug)] pub enum LintLevelSource { /// Lint is at the default level as declared in rustc. Default, @@ -173,7 +173,7 @@ impl TyCtxt<'_> { /// This struct represents a lint expectation and holds all required information /// to emit the `unfulfilled_lint_expectations` lint if it is unfulfilled after /// the `LateLintPass` has completed. -#[derive(Clone, Debug, HashStable)] +#[derive(Clone, Debug, Encodable, Decodable, HashStable)] pub struct LintExpectation { /// The reason for this expectation that can optionally be added as part of /// the attribute. It will be displayed as part of the lint message. -- cgit 1.4.1-3-g733a5 From 26708aa941d64242e2cd8a8e29e0d16c875bcc2a Mon Sep 17 00:00:00 2001 From: jyn Date: Fri, 17 Jan 2025 08:00:28 -0500 Subject: Don't require `--verbose` to show linker stdout --- compiler/rustc_codegen_ssa/src/back/link.rs | 11 +++++++---- compiler/rustc_passes/src/check_attr.rs | 17 +++++++++++++---- tests/run-make/linker-warning/rmake.rs | 7 +------ tests/run-make/rust-lld-by-default-beta-stable/rmake.rs | 5 +++-- tests/run-make/rust-lld-by-default-nightly/rmake.rs | 5 ++--- tests/run-make/rust-lld-custom-target/rmake.rs | 2 -- tests/run-make/rust-lld/rmake.rs | 10 ++-------- 7 files changed, 28 insertions(+), 29 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src/back') diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 80758aac134..fae59a3b9dc 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1040,6 +1040,11 @@ fn link_natively( sess.dcx().abort_if_errors(); } + let stderr = escape_string(&prog.stderr); + let stdout = escape_string(&prog.stdout); + info!("linker stderr:\n{}", &stderr); + info!("linker stdout:\n{}", &stdout); + let (level, src) = codegen_results.crate_info.lint_levels.linker_messages; let lint = |msg| { lint_level(sess, LINKER_MESSAGES, level, src, None, |diag| { @@ -1049,16 +1054,14 @@ fn link_natively( 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: ", ": "); lint(format!("linker stderr: {stderr}")); } - if !prog.stdout.is_empty() && sess.opts.verbose { - lint(format!("linker stdout: {}", escape_string(&prog.stdout))) + if !prog.stdout.is_empty() { + lint(format!("linker stdout: {}", stdout)) } } Err(e) => { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 7df792c0f79..3d88fe1a4d3 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2338,11 +2338,20 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }) { if hir_id != CRATE_HIR_ID { - let err = match attr.style { - ast::AttrStyle::Outer => errors::OuterCrateLevelAttr, - ast::AttrStyle::Inner => errors::OuterCrateLevelAttr, + match attr.style { + ast::AttrStyle::Outer => self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::OuterCrateLevelAttr, + ), + ast::AttrStyle::Inner => self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::InnerCrateLevelAttr, + ), }; - self.tcx.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, err); return; } else { let never_needs_link = self diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 5967f5b32e9..0a4c13c5f01 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -14,16 +14,11 @@ fn main() { 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 + // Make sure it shows stdout 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) diff --git a/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs b/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs index 85860fc95b8..d2f1e8b253a 100644 --- a/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs +++ b/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs @@ -12,7 +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().verbose().link_arg("-Wl,-v").input("main.rs").run(); + let output = rustc().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{}", @@ -21,6 +21,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())) } diff --git a/tests/run-make/rust-lld-by-default-nightly/rmake.rs b/tests/run-make/rust-lld-by-default-nightly/rmake.rs index 4026af83064..a25a69b859b 100644 --- a/tests/run-make/rust-lld-by-default-nightly/rmake.rs +++ b/tests/run-make/rust-lld-by-default-nightly/rmake.rs @@ -12,7 +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().verbose().link_arg("-Wl,-v").input("main.rs").run(); + let output = rustc().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{}", @@ -20,8 +20,7 @@ fn main() { ); // But it can still be disabled by turning the linker feature off. - let output = - rustc().verbose().link_arg("-Wl,-v").arg("-Zlinker-features=-lld").input("main.rs").run(); + let output = rustc().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{}", diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs index 17468223306..a6f936ba6e5 100644 --- a/tests/run-make/rust-lld-custom-target/rmake.rs +++ b/tests/run-make/rust-lld-custom-target/rmake.rs @@ -15,7 +15,6 @@ 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() - .verbose() .crate_type("cdylib") .target("custom-target.json") .link_arg("-Wl,-v") @@ -29,7 +28,6 @@ fn main() { // But it can also be disabled via linker features. let output = rustc() - .verbose() .crate_type("cdylib") .target("custom-target.json") .arg("-Zlinker-features=-lld") diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs index 732bc6f6ba2..1f098fdb1d9 100644 --- a/tests/run-make/rust-lld/rmake.rs +++ b/tests/run-make/rust-lld/rmake.rs @@ -17,7 +17,6 @@ fn main() { .arg("-Zlinker-features=+lld") .arg("-Clink-self-contained=+linker") .arg("-Zunstable-options") - .verbose() .link_arg(linker_version_flag) .input("main.rs") .run(); @@ -28,12 +27,8 @@ fn main() { ); // It should not be used when we explicitly opt-out of lld. - let output = rustc() - .link_arg(linker_version_flag) - .verbose() - .arg("-Zlinker-features=-lld") - .input("main.rs") - .run(); + let output = + rustc().link_arg(linker_version_flag).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{}", @@ -44,7 +39,6 @@ fn main() { // times to rustc. let output = rustc() .link_arg(linker_version_flag) - .verbose() .arg("-Clink-self-contained=+linker") .arg("-Zunstable-options") .arg("-Zlinker-features=-lld") -- cgit 1.4.1-3-g733a5 From 0ff369c5a6359a586638254594cad328f8ce25d5 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 19 Jan 2025 09:26:08 -0500 Subject: Silence progress messages from MSVC link.exe These cannot be silenced with a CLI flag, and are not useful to warn about. They can still be viewed for debugging purposes using `RUSTC_LOG=rustc_codegen_ssa::link::back`. --- compiler/rustc_codegen_ssa/src/back/link.rs | 41 ++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src/back') diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index fae59a3b9dc..9688a5d47f2 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -992,6 +992,11 @@ fn link_natively( match prog { Ok(prog) => { + let is_msvc_link_exe = sess.target.is_like_msvc + && flavor == LinkerFlavor::Msvc(Lld::No) + // Match exactly "link.exe" + && linker_path.to_str() == Some("link.exe"); + if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); @@ -1008,16 +1013,9 @@ fn link_natively( // is not a Microsoft LNK error then suggest a way to fix or // install the Visual Studio build tools. if let Some(code) = prog.status.code() { - if sess.target.is_like_msvc - && flavor == LinkerFlavor::Msvc(Lld::No) - // Respect the command line override - && sess.opts.cg.linker.is_none() - // Match exactly "link.exe" - && linker_path.to_str() == Some("link.exe") - // All Microsoft `link.exe` linking error codes are - // four digit numbers in the range 1000 to 9999 inclusive - && (code < 1000 || code > 9999) - { + // All Microsoft `link.exe` linking ror codes are + // four digit numbers in the range 1000 to 9999 inclusive + if is_msvc_link_exe && (code < 1000 || code > 9999) { let is_vs_installed = windows_registry::find_vs_version().is_ok(); let has_linker = windows_registry::find_tool(&sess.target.arch, "link.exe").is_some(); @@ -1041,10 +1039,29 @@ fn link_natively( } let stderr = escape_string(&prog.stderr); - let stdout = escape_string(&prog.stdout); + let mut stdout = escape_string(&prog.stdout); info!("linker stderr:\n{}", &stderr); info!("linker stdout:\n{}", &stdout); + // Hide some progress messages from link.exe that we don't care about. + // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146 + if is_msvc_link_exe { + if let Ok(str) = str::from_utf8(&prog.stdout) { + let mut output = String::with_capacity(str.len()); + for line in stdout.lines() { + if line.starts_with(" Creating library") + || line.starts_with("Generating code") + || line.starts_with("Finished generating code") + { + continue; + } + output += line; + output += "\r\n" + } + stdout = escape_string(output.trim().as_bytes()) + } + } + let (level, src) = codegen_results.crate_info.lint_levels.linker_messages; let lint = |msg| { lint_level(sess, LINKER_MESSAGES, level, src, None, |diag| { @@ -1060,7 +1077,7 @@ fn link_natively( .replace(": warning: ", ": "); lint(format!("linker stderr: {stderr}")); } - if !prog.stdout.is_empty() { + if !stdout.is_empty() { lint(format!("linker stdout: {}", stdout)) } } -- cgit 1.4.1-3-g733a5