Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 7b0e01d

Browse files
committedNov 30, 2024·
Auto merge of rust-lang#119286 - jyn514:linker-output, r=<try>
show linker output even if the linker succeeds - show stderr by default - show stdout if `--verbose` is passed - remove both from RUSTC_LOG - hide the linker cli args unless `--verbose` is passed fixes rust-lang#83436. fixes rust-lang#38206. fixes rust-lang#109979. helps with rust-lang#46998. cc https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/uplift.20some.20-Zverbose.20calls.20and.20rename.20to.E2.80.A6.20compiler-team.23706/near/408986134 this is based on rust-lang#119129 for convenience so i didn't have to duplicate the changes around saving `--verbose` in rust-lang@cb6d033#diff-7a49efa20548d6806dbe1c66dd4dc445fda18fcbbf1709520cadecc4841aae12 try-job: aarch64-apple r? `@bjorn3`
2 parents e48ddd8 + fe9f272 commit 7b0e01d

File tree

24 files changed

+285
-59
lines changed

24 files changed

+285
-59
lines changed
 

‎compiler/rustc_codegen_ssa/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
183183
codegen_ssa_linker_not_found = linker `{$linker_path}` not found
184184
.note = {$error}
185185
186+
codegen_ssa_linker_output = {$inner}
187+
186188
codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
187189
188190
codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}

‎compiler/rustc_codegen_ssa/src/back/link.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ use rustc_ast::CRATE_NODE_ID;
1515
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
1616
use rustc_data_structures::memmap::Mmap;
1717
use rustc_data_structures::temp_dir::MaybeTempDir;
18-
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError};
18+
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError, LintDiagnostic};
1919
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
2020
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
21+
use rustc_macros::LintDiagnostic;
2122
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
2223
use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs};
2324
use rustc_middle::bug;
25+
use rustc_middle::lint::lint_level;
2426
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
2527
use rustc_middle::middle::dependency_format::Linkage;
2628
use rustc_middle::middle::exported_symbols::SymbolExportKind;
@@ -29,6 +31,7 @@ use rustc_session::config::{
2931
OutputType, PrintKind, SplitDwarfKind, Strip,
3032
};
3133
use rustc_session::cstore::DllImport;
34+
use rustc_session::lint::builtin::LINKER_MESSAGES;
3235
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
3336
use rustc_session::search_paths::PathKind;
3437
use rustc_session::utils::NativeLibKind;
@@ -762,6 +765,14 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out
762765
}
763766
}
764767

768+
#[derive(LintDiagnostic)]
769+
#[diag(codegen_ssa_linker_output)]
770+
/// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just
771+
/// end up with inconsistent languages within the same diagnostic.
772+
struct LinkerOutput {
773+
inner: String,
774+
}
775+
765776
/// Create a dynamic library or executable.
766777
///
767778
/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
@@ -998,12 +1009,12 @@ fn link_natively(
9981009
let mut output = prog.stderr.clone();
9991010
output.extend_from_slice(&prog.stdout);
10001011
let escaped_output = escape_linker_output(&output, flavor);
1001-
// FIXME: Add UI tests for this error.
10021012
let err = errors::LinkingFailed {
10031013
linker_path: &linker_path,
10041014
exit_status: prog.status,
10051015
command: &cmd,
10061016
escaped_output,
1017+
verbose: sess.opts.verbose,
10071018
};
10081019
sess.dcx().emit_err(err);
10091020
// If MSVC's `link.exe` was expected but the return code
@@ -1045,8 +1056,27 @@ fn link_natively(
10451056

10461057
sess.dcx().abort_if_errors();
10471058
}
1048-
info!("linker stderr:\n{}", escape_string(&prog.stderr));
1049-
info!("linker stdout:\n{}", escape_string(&prog.stdout));
1059+
1060+
let (level, src) = codegen_results.crate_info.lint_levels.linker_messages;
1061+
let lint = |msg| {
1062+
lint_level(sess, LINKER_MESSAGES, level, src, None, |diag| {
1063+
LinkerOutput { inner: msg }.decorate_lint(diag)
1064+
})
1065+
};
1066+
1067+
if !prog.stderr.is_empty() {
1068+
// We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present.
1069+
let stderr = escape_string(&prog.stderr);
1070+
debug!("original stderr: {stderr}");
1071+
let stderr = stderr
1072+
.strip_prefix("warning: ")
1073+
.unwrap_or(&stderr)
1074+
.replace(": warning: ", ": ");
1075+
lint(format!("linker stderr: {stderr}"));
1076+
}
1077+
if !prog.stdout.is_empty() && sess.opts.verbose {
1078+
lint(format!("linker stdout: {}", escape_string(&prog.stdout)))
1079+
}
10501080
}
10511081
Err(e) => {
10521082
let linker_not_found = e.kind() == io::ErrorKind::NotFound;

‎compiler/rustc_codegen_ssa/src/base.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ use crate::mir::operand::OperandValue;
4545
use crate::mir::place::PlaceRef;
4646
use crate::traits::*;
4747
use crate::{
48-
CachedModuleCodegen, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, errors, meth, mir,
48+
CachedModuleCodegen, CodegenLintLevels, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
49+
errors, meth, mir,
4950
};
5051

5152
pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
@@ -926,6 +927,7 @@ impl CrateInfo {
926927
dependency_formats: Lrc::clone(tcx.dependency_formats(())),
927928
windows_subsystem,
928929
natvis_debugger_visualizers: Default::default(),
930+
lint_levels: CodegenLintLevels::from_tcx(tcx),
929931
};
930932

931933
info.native_libraries.reserve(n_crates);

‎compiler/rustc_codegen_ssa/src/errors.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ pub(crate) struct LinkingFailed<'a> {
349349
pub exit_status: ExitStatus,
350350
pub command: &'a Command,
351351
pub escaped_output: String,
352+
pub verbose: bool,
352353
}
353354

354355
impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
@@ -359,7 +360,13 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
359360

360361
let contains_undefined_ref = self.escaped_output.contains("undefined reference to");
361362

362-
diag.note(format!("{:?}", self.command)).note(self.escaped_output);
363+
if self.verbose {
364+
diag.note(format!("{:?}", self.command));
365+
} else {
366+
diag.note("use `--verbose` to show all linker arguments");
367+
}
368+
369+
diag.note(self.escaped_output);
363370

364371
// Trying to match an error from OS linkers
365372
// which by now we have no way to translate.

‎compiler/rustc_codegen_ssa/src/lib.rs

+22
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,23 @@ use rustc_ast as ast;
2929
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
3030
use rustc_data_structures::sync::Lrc;
3131
use rustc_data_structures::unord::UnordMap;
32+
use rustc_hir::CRATE_HIR_ID;
3233
use rustc_hir::def_id::CrateNum;
3334
use rustc_macros::{Decodable, Encodable, HashStable};
3435
use rustc_middle::dep_graph::WorkProduct;
36+
use rustc_middle::lint::LintLevelSource;
3537
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
3638
use rustc_middle::middle::dependency_format::Dependencies;
3739
use rustc_middle::middle::exported_symbols::SymbolExportKind;
40+
use rustc_middle::ty::TyCtxt;
3841
use rustc_middle::util::Providers;
3942
use rustc_serialize::opaque::{FileEncoder, MemDecoder};
4043
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
4144
use rustc_session::Session;
4245
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
4346
use rustc_session::cstore::{self, CrateSource};
47+
use rustc_session::lint::Level;
48+
use rustc_session::lint::builtin::LINKER_MESSAGES;
4449
use rustc_session::utils::NativeLibKind;
4550
use rustc_span::symbol::Symbol;
4651

@@ -200,6 +205,7 @@ pub struct CrateInfo {
200205
pub dependency_formats: Lrc<Dependencies>,
201206
pub windows_subsystem: Option<String>,
202207
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
208+
pub lint_levels: CodegenLintLevels,
203209
}
204210

205211
#[derive(Encodable, Decodable)]
@@ -302,3 +308,19 @@ impl CodegenResults {
302308
Ok((codegen_results, outputs))
303309
}
304310
}
311+
312+
/// A list of lint levels used in codegen.
313+
///
314+
/// When using `-Z link-only`, we don't have access to the tcx and must work
315+
/// solely from the `.rlink` file. `Lint`s are defined too early to be encodeable.
316+
/// Instead, encode exactly the information we need.
317+
#[derive(Copy, Clone, Debug, Encodable, Decodable)]
318+
pub struct CodegenLintLevels {
319+
linker_messages: (Level, LintLevelSource),
320+
}
321+
322+
impl CodegenLintLevels {
323+
pub fn from_tcx(tcx: TyCtxt<'_>) -> Self {
324+
Self { linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID) }
325+
}
326+
}

‎compiler/rustc_lint/src/levels.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,17 @@ fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> {
130130
!has_future_breakage && !lint.eval_always
131131
})
132132
.filter_map(|lint| {
133-
let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID);
134-
if matches!(lint_level, (Level::Allow, ..))
135-
|| (matches!(lint_level, (.., LintLevelSource::Default)))
136-
&& lint.default_level(tcx.sess.edition()) == Level::Allow
137-
{
138-
Some(LintId::of(lint))
133+
if !lint.eval_always {
134+
let lint_level =
135+
map.lint_level_id_at_node(Some(tcx), tcx.sess, LintId::of(lint), CRATE_HIR_ID);
136+
if matches!(lint_level, (Level::Allow, ..))
137+
|| (matches!(lint_level, (.., LintLevelSource::Default)))
138+
&& lint.default_level(tcx.sess.edition()) == Level::Allow
139+
{
140+
Some(LintId::of(lint))
141+
} else {
142+
None
143+
}
139144
} else {
140145
None
141146
}
@@ -248,8 +253,8 @@ impl LintLevelsProvider for LintLevelQueryMap<'_> {
248253
fn insert(&mut self, id: LintId, lvl: LevelAndSource) {
249254
self.specs.specs.get_mut_or_insert_default(self.cur.local_id).insert(id, lvl);
250255
}
251-
fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource {
252-
self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
256+
fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource {
257+
self.specs.lint_level_id_at_node(Some(self.tcx), sess, LintId::of(lint), self.cur)
253258
}
254259
fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) {
255260
self.specs.expectations.push((id, expectation))

‎compiler/rustc_lint_defs/src/builtin.rs

+34
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ declare_lint_pass! {
6060
LARGE_ASSIGNMENTS,
6161
LATE_BOUND_LIFETIME_ARGUMENTS,
6262
LEGACY_DERIVE_HELPERS,
63+
LINKER_MESSAGES,
6364
LONG_RUNNING_CONST_EVAL,
6465
LOSSY_PROVENANCE_CASTS,
6566
MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
@@ -4080,6 +4081,39 @@ declare_lint! {
40804081
"call to foreign functions or function pointers with FFI-unwind ABI"
40814082
}
40824083

4084+
declare_lint! {
4085+
/// The `linker_messages` lint forwards warnings from the linker.
4086+
///
4087+
/// ### Example
4088+
///
4089+
/// ```rust,ignore (needs CLI args, platform-specific)
4090+
/// extern "C" {
4091+
/// fn foo();
4092+
/// }
4093+
/// fn main () { unsafe { foo(); } }
4094+
/// ```
4095+
///
4096+
/// On Linux, using `gcc -Wl,--warn-unresolved-symbols` as a linker, this will produce
4097+
///
4098+
/// ```text
4099+
/// warning: linker stderr: rust-lld: undefined symbol: foo
4100+
/// >>> referenced by rust_out.69edbd30df4ae57d-cgu.0
4101+
/// >>> rust_out.rust_out.69edbd30df4ae57d-cgu.0.rcgu.o:(rust_out::main::h3a90094b06757803)
4102+
/// |
4103+
/// = note: `#[warn(linker_messages)]` on by default
4104+
///
4105+
/// warning: 1 warning emitted
4106+
/// ```
4107+
///
4108+
/// ### Explanation
4109+
///
4110+
/// Linkers emit platform-specific and program-specific warnings that cannot be predicted in advance by the rust compiler.
4111+
/// They are forwarded by default, but can be disabled by adding `#![allow(linker_messages)]` at the crate root.
4112+
pub LINKER_MESSAGES,
4113+
Warn,
4114+
"warnings emitted at runtime by the target-specific linker program"
4115+
}
4116+
40834117
declare_lint! {
40844118
/// The `named_arguments_used_positionally` lint detects cases where named arguments are only
40854119
/// used positionally in format strings. This usage is valid but potentially very confusing.

‎compiler/rustc_lint_defs/src/lib.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,19 @@ impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectation
161161
/// Setting for how to handle a lint.
162162
///
163163
/// See: <https://doc.rust-lang.org/rustc/lints/levels.html>
164-
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, HashStable_Generic)]
164+
#[derive(
165+
Clone,
166+
Copy,
167+
PartialEq,
168+
PartialOrd,
169+
Eq,
170+
Ord,
171+
Debug,
172+
Hash,
173+
Encodable,
174+
Decodable,
175+
HashStable_Generic
176+
)]
165177
pub enum Level {
166178
/// The `allow` level will not issue any message.
167179
Allow,

‎compiler/rustc_middle/src/lint.rs

+30-18
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use std::cmp;
33
use rustc_data_structures::fx::FxIndexMap;
44
use rustc_data_structures::sorted_map::SortedMap;
55
use rustc_errors::{Diag, MultiSpan};
6-
use rustc_hir::{HirId, ItemLocalId};
7-
use rustc_macros::HashStable;
6+
use rustc_hir::{CRATE_HIR_ID, HirId, ItemLocalId};
7+
use rustc_macros::{Decodable, Encodable, HashStable};
88
use rustc_session::Session;
99
use rustc_session::lint::builtin::{self, FORBIDDEN_LINT_GROUPS};
1010
use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId};
@@ -15,7 +15,7 @@ use tracing::instrument;
1515
use crate::ty::TyCtxt;
1616

1717
/// How a lint level was set.
18-
#[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)]
18+
#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, HashStable, Debug)]
1919
pub enum LintLevelSource {
2020
/// Lint is at the default level as declared in rustc.
2121
Default,
@@ -119,7 +119,7 @@ impl ShallowLintLevelMap {
119119
#[instrument(level = "trace", skip(self, tcx), ret)]
120120
fn probe_for_lint_level(
121121
&self,
122-
tcx: TyCtxt<'_>,
122+
tcx: Option<TyCtxt<'_>>,
123123
id: LintId,
124124
start: HirId,
125125
) -> (Option<Level>, LintLevelSource) {
@@ -132,31 +132,38 @@ impl ShallowLintLevelMap {
132132
let mut owner = start.owner;
133133
let mut specs = &self.specs;
134134

135-
for parent in tcx.hir().parent_id_iter(start) {
136-
if parent.owner != owner {
137-
owner = parent.owner;
138-
specs = &tcx.shallow_lint_levels_on(owner).specs;
139-
}
140-
if let Some(map) = specs.get(&parent.local_id)
141-
&& let Some(&(level, src)) = map.get(&id)
142-
{
143-
return (Some(level), src);
135+
if let Some(tcx) = tcx {
136+
for parent in tcx.hir().parent_id_iter(start) {
137+
if parent.owner != owner {
138+
owner = parent.owner;
139+
specs = &tcx.shallow_lint_levels_on(owner).specs;
140+
}
141+
if let Some(map) = specs.get(&parent.local_id)
142+
&& let Some(&(level, src)) = map.get(&id)
143+
{
144+
return (Some(level), src);
145+
}
144146
}
145147
}
146148

147149
(None, LintLevelSource::Default)
148150
}
149151

150152
/// Fetch and return the user-visible lint level for the given lint at the given HirId.
151-
#[instrument(level = "trace", skip(self, tcx), ret)]
153+
#[instrument(level = "trace", skip(self, tcx, sess), ret)]
152154
pub fn lint_level_id_at_node(
153155
&self,
154-
tcx: TyCtxt<'_>,
156+
tcx: Option<TyCtxt<'_>>,
157+
sess: &Session,
155158
lint: LintId,
156159
cur: HirId,
157160
) -> (Level, LintLevelSource) {
161+
assert!(
162+
tcx.is_some() || cur == CRATE_HIR_ID,
163+
"must pass in a tcx to access any level other than the root"
164+
);
158165
let (level, mut src) = self.probe_for_lint_level(tcx, lint, cur);
159-
let level = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| {
166+
let level = reveal_actual_level(level, &mut src, sess, lint, |lint| {
160167
self.probe_for_lint_level(tcx, lint, cur)
161168
});
162169
(level, src)
@@ -166,14 +173,19 @@ impl ShallowLintLevelMap {
166173
impl TyCtxt<'_> {
167174
/// Fetch and return the user-visible lint level for the given lint at the given HirId.
168175
pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) {
169-
self.shallow_lint_levels_on(id.owner).lint_level_id_at_node(self, LintId::of(lint), id)
176+
self.shallow_lint_levels_on(id.owner).lint_level_id_at_node(
177+
Some(self),
178+
self.sess,
179+
LintId::of(lint),
180+
id,
181+
)
170182
}
171183
}
172184

173185
/// This struct represents a lint expectation and holds all required information
174186
/// to emit the `unfulfilled_lint_expectations` lint if it is unfulfilled after
175187
/// the `LateLintPass` has completed.
176-
#[derive(Clone, Debug, HashStable)]
188+
#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
177189
pub struct LintExpectation {
178190
/// The reason for this expectation that can optionally be added as part of
179191
/// the attribute. It will be displayed as part of the lint message.

‎compiler/rustc_passes/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,9 @@ passes_unused_duplicate =
798798
passes_unused_empty_lints_note =
799799
attribute `{$name}` with an empty list has no effect
800800
801+
passes_unused_linker_warnings_note =
802+
the `linker_warnings` lint can only be controlled at the root of a crate with `--crate-type bin`
803+
801804
passes_unused_multiple =
802805
multiple `{$name}` attributes
803806
.suggestion = remove this attribute

‎compiler/rustc_passes/src/check_attr.rs

+10
Original file line numberDiff line numberDiff line change
@@ -2271,6 +2271,16 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
22712271
&& item.path == sym::reason
22722272
{
22732273
errors::UnusedNote::NoLints { name: attr.name_or_empty() }
2274+
} else if matches!(
2275+
attr.name_or_empty(),
2276+
sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
2277+
) && let Some(meta) = attr.meta_item_list()
2278+
&& meta.iter().any(|meta| {
2279+
meta.meta_item().map_or(false, |item| item.path == sym::linker_messages)
2280+
})
2281+
&& hir_id != CRATE_HIR_ID
2282+
{
2283+
errors::UnusedNote::LinkerWarningsBinaryCrateOnly
22742284
} else if attr.name_or_empty() == sym::default_method_body_is_const {
22752285
errors::UnusedNote::DefaultMethodBodyConst
22762286
} else {

‎compiler/rustc_passes/src/errors.rs

+2
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,8 @@ pub(crate) enum UnusedNote {
762762
NoLints { name: Symbol },
763763
#[note(passes_unused_default_method_body_const_note)]
764764
DefaultMethodBodyConst,
765+
#[note(passes_unused_linker_warnings_note)]
766+
LinkerWarningsBinaryCrateOnly,
765767
}
766768

767769
#[derive(LintDiagnostic)]

‎compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,7 @@ symbols! {
11531153
link_section,
11541154
linkage,
11551155
linker,
1156+
linker_messages,
11561157
lint_reasons,
11571158
literal,
11581159
load,

‎src/bootstrap/src/core/build_steps/compile.rs

+5
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,11 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
592592
// separate setting for the compiler.
593593
cargo.rustflag("-Cforce-frame-pointers=yes");
594594

595+
// Ignore linker warnings on macOS for now. These are complicated to fix and don't affect the build.
596+
if target.contains("apple-darwin") {
597+
cargo.rustflag("-Alinker-messages");
598+
}
599+
595600
let html_root =
596601
format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
597602
cargo.rustflag(&html_root);

‎src/tools/run-make-support/src/external_deps/rustc.rs

+6
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,12 @@ impl Rustc {
319319
self
320320
}
321321

322+
/// Pass the `--verbose` flag.
323+
pub fn verbose(&mut self) -> &mut Self {
324+
self.cmd.arg("--verbose");
325+
self
326+
}
327+
322328
/// `EXTRARSCXXFLAGS`
323329
pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
324330
// Adapted from tools.mk (trimmed):

‎tests/run-make/link-args-order/rmake.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@ fn main() {
1515
.link_args("b c")
1616
.link_args("d e")
1717
.link_arg("f")
18+
.arg("--print=link-args")
1819
.run_fail()
19-
.assert_stderr_contains(r#""a" "b" "c" "d" "e" "f""#);
20+
.assert_stdout_contains(r#""a" "b" "c" "d" "e" "f""#);
2021
rustc()
2122
.input("empty.rs")
2223
.linker_flavor(linker)
2324
.arg("-Zpre-link-arg=a")
2425
.arg("-Zpre-link-args=b c")
2526
.arg("-Zpre-link-args=d e")
2627
.arg("-Zpre-link-arg=f")
28+
.arg("--print=link-args")
2729
.run_fail()
28-
.assert_stderr_contains(r#""a" "b" "c" "d" "e" "f""#);
30+
.assert_stdout_contains(r#""a" "b" "c" "d" "e" "f""#);
2931
}

‎tests/run-make/link-dedup/rmake.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ fn main() {
1414
rustc().input("depb.rs").run();
1515
rustc().input("depc.rs").run();
1616

17-
let output = rustc().input("empty.rs").cfg("bar").run_fail();
18-
output.assert_stderr_contains(needle_from_libs(&["testa", "testb", "testa"]));
17+
let output = rustc().input("empty.rs").cfg("bar").arg("--print=link-args").run_fail();
18+
output.assert_stdout_contains(needle_from_libs(&["testa", "testb", "testa"]));
1919

20-
let output = rustc().input("empty.rs").run_fail();
21-
output.assert_stderr_contains(needle_from_libs(&["testa"]));
22-
output.assert_stderr_not_contains(needle_from_libs(&["testb"]));
23-
output.assert_stderr_not_contains(needle_from_libs(&["testa", "testa", "testa"]));
20+
let output = rustc().input("empty.rs").arg("--print=link-args").run_fail();
21+
output.assert_stdout_contains(needle_from_libs(&["testa"]));
22+
output.assert_stdout_not_contains(needle_from_libs(&["testb"]));
23+
output.assert_stdout_not_contains(needle_from_libs(&["testa", "testa", "testa"]));
2424
// Adjacent identical native libraries are no longer deduplicated if
2525
// they come from different crates (https://github.com/rust-lang/rust/pull/103311)
2626
// so the following will fail:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fn main() {
2+
for arg in std::env::args() {
3+
match &*arg {
4+
"run_make_info" => println!("foo"),
5+
"run_make_warn" => eprintln!("warning: bar"),
6+
"run_make_error" => {
7+
eprintln!("error: baz");
8+
std::process::exit(1);
9+
}
10+
_ => (),
11+
}
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/sh
2+
3+
code=0
4+
while ! [ $# = 0 ]; do
5+
case "$1" in
6+
run_make_info) echo "foo"
7+
;;
8+
run_make_warn) echo "warning: bar" >&2
9+
;;
10+
run_make_error) echo "error: baz" >&2; code=1
11+
;;
12+
*) ;; # rustc passes lots of args we don't care about
13+
esac
14+
shift
15+
done
16+
17+
exit $code

‎tests/run-make/linker-warning/main.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use std::path::Path;
2+
3+
use run_make_support::rfs::remove_file;
4+
use run_make_support::{Rustc, rustc};
5+
6+
fn run_rustc() -> Rustc {
7+
let mut rustc = rustc();
8+
rustc.arg("main.rs").output("main").linker("./fake-linker");
9+
rustc
10+
}
11+
12+
fn main() {
13+
// first, compile our linker
14+
rustc().arg("fake-linker.rs").output("fake-linker").run();
15+
16+
// Run rustc with our fake linker, and make sure it shows warnings
17+
let warnings = run_rustc().link_arg("run_make_warn").run();
18+
warnings.assert_stderr_contains("warning: linker stderr: bar");
19+
20+
// Make sure it shows stdout, but only when --verbose is passed
21+
run_rustc()
22+
.link_arg("run_make_info")
23+
.verbose()
24+
.run()
25+
.assert_stderr_contains("warning: linker stdout: foo");
26+
run_rustc()
27+
.link_arg("run_make_info")
28+
.run()
29+
.assert_stderr_not_contains("warning: linker stdout: foo");
30+
31+
// Make sure we short-circuit this new path if the linker exits with an error
32+
// (so the diagnostic is less verbose)
33+
run_rustc().link_arg("run_make_error").run_fail().assert_stderr_contains("note: error: baz");
34+
35+
// Make sure we don't show the linker args unless `--verbose` is passed
36+
run_rustc()
37+
.link_arg("run_make_error")
38+
.verbose()
39+
.run_fail()
40+
.assert_stderr_contains_regex("fake-linker.*run_make_error");
41+
run_rustc()
42+
.link_arg("run_make_error")
43+
.run_fail()
44+
.assert_stderr_not_contains_regex("fake-linker.*run_make_error");
45+
}

‎tests/run-make/rust-lld-by-default-nightly/rmake.rs

+5-12
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,16 @@ use run_make_support::rustc;
1212
fn main() {
1313
// A regular compilation should use rust-lld by default. We'll check that by asking the linker
1414
// to display its version number with a link-arg.
15-
let output = rustc()
16-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
17-
.link_arg("-Wl,-v")
18-
.input("main.rs")
19-
.run();
15+
let output = rustc().verbose().link_arg("-Wl,-v").input("main.rs").run();
2016
assert!(
2117
find_lld_version_in_logs(output.stderr_utf8()),
2218
"the LLD version string should be present in the output logs:\n{}",
2319
output.stderr_utf8()
2420
);
2521

2622
// But it can still be disabled by turning the linker feature off.
27-
let output = rustc()
28-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
29-
.link_arg("-Wl,-v")
30-
.arg("-Zlinker-features=-lld")
31-
.input("main.rs")
32-
.run();
23+
let output =
24+
rustc().verbose().link_arg("-Wl,-v").arg("-Zlinker-features=-lld").input("main.rs").run();
3325
assert!(
3426
!find_lld_version_in_logs(output.stderr_utf8()),
3527
"the LLD version string should not be present in the output logs:\n{}",
@@ -38,6 +30,7 @@ fn main() {
3830
}
3931

4032
fn find_lld_version_in_logs(stderr: String) -> bool {
41-
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
33+
let lld_version_re =
34+
Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
4235
stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
4336
}

‎tests/run-make/rust-lld-custom-target/rmake.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn main() {
1515
// Compile to a custom target spec with rust-lld enabled by default. We'll check that by asking
1616
// the linker to display its version number with a link-arg.
1717
let output = rustc()
18-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
18+
.verbose()
1919
.crate_type("cdylib")
2020
.target("custom-target.json")
2121
.link_arg("-Wl,-v")
@@ -44,6 +44,7 @@ fn main() {
4444
}
4545

4646
fn find_lld_version_in_logs(stderr: String) -> bool {
47-
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
47+
let lld_version_re =
48+
Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
4849
stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
4950
}

‎tests/run-make/rust-lld/rmake.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ fn main() {
1414
// Opt-in to lld and the self-contained linker, to link with rust-lld. We'll check that by
1515
// asking the linker to display its version number with a link-arg.
1616
let output = rustc()
17-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
1817
.arg("-Zlinker-features=+lld")
1918
.arg("-Clink-self-contained=+linker")
2019
.arg("-Zunstable-options")
20+
.verbose()
2121
.link_arg(linker_version_flag)
2222
.input("main.rs")
2323
.run();
@@ -29,8 +29,8 @@ fn main() {
2929

3030
// It should not be used when we explicitly opt-out of lld.
3131
let output = rustc()
32-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
3332
.link_arg(linker_version_flag)
33+
.verbose()
3434
.arg("-Zlinker-features=-lld")
3535
.input("main.rs")
3636
.run();
@@ -43,8 +43,8 @@ fn main() {
4343
// While we're here, also check that the last linker feature flag "wins" when passed multiple
4444
// times to rustc.
4545
let output = rustc()
46-
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
4746
.link_arg(linker_version_flag)
47+
.verbose()
4848
.arg("-Clink-self-contained=+linker")
4949
.arg("-Zunstable-options")
5050
.arg("-Zlinker-features=-lld")
@@ -60,6 +60,7 @@ fn main() {
6060
}
6161

6262
fn find_lld_version_in_logs(stderr: String) -> bool {
63-
let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
63+
let lld_version_re =
64+
Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
6465
stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
6566
}

0 commit comments

Comments
 (0)
Please sign in to comment.