Skip to content

Commit c666de8

Browse files
committed
wip: split out linker-info from linker-messages
1 parent e0974e7 commit c666de8

File tree

10 files changed

+177
-21
lines changed

10 files changed

+177
-21
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

Lines changed: 96 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
2222
use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize};
2323
use rustc_hir::attrs::NativeLibKind;
2424
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
25+
use rustc_lint_defs::builtin::LINKER_INFO;
2526
use rustc_macros::LintDiagnostic;
2627
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
2728
use rustc_metadata::{
@@ -60,7 +61,8 @@ use super::rpath::{self, RPathConfig};
6061
use super::{apple, versioned_llvm_target};
6162
use crate::base::needs_allocator_shim_for_linking;
6263
use crate::{
63-
CodegenLintLevels, CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file
64+
CodegenLintLevels, CodegenResults, CompiledModule, CrateInfo, NativeLib, errors,
65+
looks_like_rust_object_file,
6466
};
6567

6668
pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
@@ -678,37 +680,106 @@ fn is_msvc_link_exe(sess: &Session) -> bool {
678680
&& linker_path.to_str() == Some("link.exe")
679681
}
680682

683+
fn is_macos_ld(sess: &Session) -> bool {
684+
let (_, flavor) = linker_and_flavor(sess);
685+
sess.target.is_like_darwin && matches!(flavor, LinkerFlavor::Darwin(_, Lld::No))
686+
}
687+
688+
fn is_windows_gnu_ld(sess: &Session) -> bool {
689+
let (_, flavor) = linker_and_flavor(sess);
690+
sess.target.is_like_windows
691+
&& !sess.target.is_like_msvc
692+
&& matches!(flavor, LinkerFlavor::Gnu(_, Lld::No))
693+
}
694+
681695
fn report_linker_output(sess: &Session, levels: CodegenLintLevels, stdout: &[u8], stderr: &[u8]) {
682-
let escaped_stderr = escape_string(&stderr);
696+
let mut escaped_stderr = escape_string(&stderr);
683697
let mut escaped_stdout = escape_string(&stdout);
698+
let mut linker_info = String::new();
699+
684700
info!("linker stderr:\n{}", &escaped_stderr);
685701
info!("linker stdout:\n{}", &escaped_stdout);
686702

703+
fn for_each(bytes: &[u8], mut f: impl FnMut(&str, &mut String)) -> String {
704+
let mut output = String::new();
705+
if let Ok(str) = str::from_utf8(bytes) {
706+
info!("line: {str}");
707+
output = String::with_capacity(str.len());
708+
for line in str.lines() {
709+
f(line.trim(), &mut output);
710+
}
711+
}
712+
escape_string(output.trim().as_bytes())
713+
}
714+
687715
// Hide some progress messages from link.exe that we don't care about.
688716
// See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146
689717
if is_msvc_link_exe(sess) {
690-
if let Ok(str) = str::from_utf8(&stdout) {
691-
let mut output = String::with_capacity(str.len());
692-
for line in str.lines() {
693-
if line.starts_with(" Creating library")
694-
|| line.starts_with("Generating code")
695-
|| line.starts_with("Finished generating code")
696-
{
697-
continue;
698-
} else {
699-
output += line;
700-
output += "\r\n"
701-
}
718+
escaped_stdout = for_each(&stdout, |line, output| {
719+
if line.starts_with(" Creating library")
720+
|| line.starts_with("Generating code")
721+
|| line.starts_with("Finished generating code")
722+
{
723+
linker_info += line;
724+
linker_info += "\r\n";
725+
} else {
726+
*output += line;
727+
*output += "\r\n"
702728
}
703-
escaped_stdout = escape_string(output.trim().as_bytes())
704-
}
729+
});
730+
} else if is_macos_ld(sess) {
731+
let deployment_mismatch = |line: &str| {
732+
line.starts_with("ld: warning: object file (")
733+
&& line.contains("was built for newer 'macOS' version")
734+
&& line.contains("than being linked")
735+
};
736+
let search_path = |line: &str| {
737+
line.starts_with("ld: warning: search path '") && line.ends_with("' not found")
738+
};
739+
escaped_stderr = for_each(&stderr, |line, output| {
740+
if line.starts_with("ld: warning: ignoring duplicate libraries: ")
741+
|| deployment_mismatch(line)
742+
|| search_path(line)
743+
{
744+
linker_info += line;
745+
linker_info += "\n";
746+
} else {
747+
*output += line;
748+
*output += "\n"
749+
}
750+
});
751+
} else if is_windows_gnu_ld(sess) {
752+
let mut saw_exclude_symbol = false;
753+
let exclude_symbols = |line: &str| {
754+
line.starts_with("Warning: .drectve `-exclude-symbols:")
755+
&& line.ends_with("' unrecognized")
756+
};
757+
// FIXME: are we sure this is stderr and not stdout?
758+
escaped_stderr = for_each(&stderr, |line, output| {
759+
if exclude_symbols(line) {
760+
saw_exclude_symbol = true;
761+
linker_info += line;
762+
linker_info += "\n";
763+
} else if saw_exclude_symbol && line == "Warning: corrupt .drectve at end of def file" {
764+
linker_info += line;
765+
linker_info += "\n";
766+
} else {
767+
*output += line;
768+
*output += "\n"
769+
}
770+
});
705771
}
706772

707773
let lint_msg = |msg| {
708774
lint_level(sess, LINKER_MESSAGES, levels.linker_messages, None, |diag| {
709775
LinkerOutput { inner: msg }.decorate_lint(diag)
710776
})
711777
};
778+
let lint_info = |msg| {
779+
lint_level(sess, LINKER_INFO, levels.linker_info, None, |diag| {
780+
LinkerOutput { inner: msg }.decorate_lint(diag)
781+
})
782+
};
712783

713784
if !escaped_stderr.is_empty() {
714785
// We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
@@ -721,6 +792,9 @@ fn report_linker_output(sess: &Session, levels: CodegenLintLevels, stdout: &[u8]
721792
if !escaped_stdout.is_empty() {
722793
lint_msg(format!("linker stdout: {}", escaped_stdout))
723794
}
795+
if !linker_info.is_empty() {
796+
lint_info(linker_info);
797+
}
724798
}
725799

726800
/// Create a dynamic library or executable.
@@ -960,7 +1034,12 @@ fn link_natively(
9601034
sess.dcx().abort_if_errors();
9611035
}
9621036

963-
report_linker_output(sess, codegen_results.crate_info.lint_levels, &prog.stdout, &prog.stderr);
1037+
report_linker_output(
1038+
sess,
1039+
codegen_results.crate_info.lint_levels,
1040+
&prog.stdout,
1041+
&prog.stderr,
1042+
);
9641043
}
9651044
Err(e) => {
9661045
let linker_not_found = e.kind() == io::ErrorKind::NotFound;

compiler/rustc_codegen_ssa/src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use rustc_data_structures::unord::UnordMap;
2626
use rustc_hir::CRATE_HIR_ID;
2727
use rustc_hir::attrs::{CfgEntry, NativeLibKind};
2828
use rustc_hir::def_id::CrateNum;
29+
use rustc_lint_defs::builtin::LINKER_INFO;
2930
use rustc_macros::{Decodable, Encodable, HashStable};
3031
use rustc_metadata::EncodedMetadata;
3132
use rustc_middle::dep_graph::WorkProduct;
@@ -360,10 +361,14 @@ impl CodegenResults {
360361
#[derive(Copy, Clone, Debug, Encodable, Decodable)]
361362
pub struct CodegenLintLevels {
362363
linker_messages: LevelAndSource,
364+
linker_info: LevelAndSource,
363365
}
364366

365367
impl CodegenLintLevels {
366368
pub fn from_tcx(tcx: TyCtxt<'_>) -> Self {
367-
Self { linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID) }
369+
Self {
370+
linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID),
371+
linker_info: tcx.lint_level_at_node(LINKER_INFO, CRATE_HIR_ID),
372+
}
368373
}
369374
}

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ declare_lint_pass! {
5858
LARGE_ASSIGNMENTS,
5959
LATE_BOUND_LIFETIME_ARGUMENTS,
6060
LEGACY_DERIVE_HELPERS,
61+
LINKER_INFO,
6162
LINKER_MESSAGES,
6263
LONG_RUNNING_CONST_EVAL,
6364
LOSSY_PROVENANCE_CASTS,
@@ -4010,10 +4011,44 @@ declare_lint! {
40104011
/// and actionable warning of similar quality to our other diagnostics. See this tracking
40114012
/// issue for more details: <https://github.com/rust-lang/rust/issues/136096>.
40124013
pub LINKER_MESSAGES,
4013-
Allow,
4014+
Warn,
40144015
"warnings emitted at runtime by the target-specific linker program"
40154016
}
40164017

4018+
declare_lint! {
4019+
/// The `linker_info` lint forwards warnings from the linker that are known to be informational-only.
4020+
///
4021+
/// ### Example
4022+
///
4023+
/// ```rust,ignore (needs CLI args, platform-specific)
4024+
/// #[warn(linker_info)]
4025+
/// fn main () {}
4026+
/// ```
4027+
///
4028+
/// On MacOS, using `-C link-arg=-lc` and the default linker, this will produce
4029+
///
4030+
/// ```text
4031+
/// warning: linker stderr: ld: ignoring duplicate libraries: '-lc'
4032+
/// |
4033+
/// note: the lint level is defined here
4034+
/// --> ex.rs:1:9
4035+
/// |
4036+
/// 1 | #![warn(linker_info)]
4037+
/// | ^^^^^^^^^^^^^^^
4038+
/// ```
4039+
///
4040+
/// ### Explanation
4041+
///
4042+
/// Many linkers are very "chatty" and print lots of information that is not necessarily
4043+
/// indicative of an issue. This output has been ignored for many years and is often not
4044+
/// actionable by developers. It is silenced unless the developer specifically requests for it
4045+
/// to be printed. See this tracking issue for more details:
4046+
/// <https://github.com/rust-lang/rust/issues/136096>.
4047+
pub LINKER_INFO,
4048+
Allow,
4049+
"linker warnings known to be informational-only and not indicative of a problem"
4050+
}
4051+
40174052
declare_lint! {
40184053
/// The `named_arguments_used_positionally` lint detects cases where named arguments are only
40194054
/// used positionally in format strings. This usage is valid but potentially very confusing.

compiler/rustc_passes/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ passes_unused_empty_lints_note =
642642
attribute `{$name}` with an empty list has no effect
643643
644644
passes_unused_linker_messages_note =
645-
the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked
645+
the `linker_messages` and `linker_info` lints can only be controlled at the root of a crate that needs to be linked
646646
647647
passes_unused_multiple =
648648
multiple `{$name}` attributes

compiler/rustc_passes/src/check_attr.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1947,7 +1947,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
19471947
} else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
19481948
&& let Some(meta) = attr.meta_item_list()
19491949
&& meta.iter().any(|meta| {
1950-
meta.meta_item().map_or(false, |item| item.path == sym::linker_messages)
1950+
meta.meta_item().map_or(false, |item| {
1951+
item.path == sym::linker_messages || item.path == sym::linker_info
1952+
})
19511953
})
19521954
{
19531955
if hir_id != CRATE_HIR_ID {

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,6 +1328,7 @@ symbols! {
13281328
link_section,
13291329
linkage,
13301330
linker,
1331+
linker_info,
13311332
linker_messages,
13321333
linkonce,
13331334
linkonce_odr,
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//@ only-apple
2+
//@ compile-flags: -C link-arg=-lc -C link-arg=-lc
3+
//@ build-fail
4+
#![deny(linker_info)]
5+
//~? ERROR ignoring duplicate libraries
6+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: ld: warning: ignoring duplicate libraries: '-lc'
2+
3+
|
4+
note: the lint level is defined here
5+
--> $DIR/macos-ignoring-duplicate.rs:4:9
6+
|
7+
LL | #![deny(linker_info)]
8+
| ^^^^^^^^^^^
9+
10+
error: aborting due to 1 previous error
11+
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//@ only-apple
2+
//@ compile-flags: -C link-arg=-Wl,-L/no/such/file/or/directory
3+
//@ build-fail
4+
#![deny(linker_info)]
5+
//~? ERROR search path
6+
fn main() {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: ld: warning: search path '/no/such/file/or/directory' not found
2+
3+
|
4+
note: the lint level is defined here
5+
--> $DIR/macos-search-path.rs:4:9
6+
|
7+
LL | #![deny(linker_info)]
8+
| ^^^^^^^^^^^
9+
10+
error: aborting due to 1 previous error
11+

0 commit comments

Comments
 (0)