Skip to content

Commit

Permalink
Auto merge of rust-lang#119286 - jyn514:linker-output, r=<try>
Browse files Browse the repository at this point in the history
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`
  • Loading branch information
bors committed Nov 29, 2024
2 parents 0c4f3a4 + fc8b598 commit 6fa9e3d
Show file tree
Hide file tree
Showing 27 changed files with 328 additions and 79 deletions.
5 changes: 3 additions & 2 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use rustc_codegen_ssa::back::write::{
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
};
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
use rustc_codegen_ssa::{CodegenLintLevels, CodegenResults, CompiledModule, ModuleCodegen};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError};
use rustc_metadata::EncodedMetadata;
Expand Down Expand Up @@ -374,6 +374,7 @@ impl CodegenBackend for LlvmCodegenBackend {
&self,
sess: &Session,
codegen_results: CodegenResults,
lint_levels: CodegenLintLevels,
outputs: &OutputFilenames,
) -> Result<(), ErrorGuaranteed> {
use rustc_codegen_ssa::back::link::link_binary;
Expand All @@ -382,7 +383,7 @@ impl CodegenBackend for LlvmCodegenBackend {

// Run the linker on any artifacts that resulted from the LLVM run.
// This should produce either a finished executable or library.
link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, outputs)
link_binary(sess, &LlvmArchiveBuilderBuilder, codegen_results, lint_levels, outputs)
}
}

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_ssa/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker
codegen_ssa_linker_not_found = linker `{$linker_path}` not found
.note = {$error}
codegen_ssa_linker_output = {$inner}
codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}
Expand Down
43 changes: 38 additions & 5 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +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, ErrorGuaranteed, FatalError};
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, FatalError, LintDiagnostic};
use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize};
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
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;
Expand All @@ -29,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;
Expand All @@ -52,7 +55,7 @@ use super::metadata::{MetadataPosition, create_wrapper_file};
use super::rpath::{self, RPathConfig};
use super::{apple, versioned_llvm_target};
use crate::{
CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors,
CodegenLintLevels, CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors,
looks_like_rust_object_file,
};

Expand All @@ -70,6 +73,7 @@ pub fn link_binary(
sess: &Session,
archive_builder_builder: &dyn ArchiveBuilderBuilder,
codegen_results: CodegenResults,
lint_levels: CodegenLintLevels,
outputs: &OutputFilenames,
) -> Result<(), ErrorGuaranteed> {
let _timer = sess.timer("link_binary");
Expand Down Expand Up @@ -138,6 +142,7 @@ pub fn link_binary(
crate_type,
&out_filename,
&codegen_results,
lint_levels,
path.as_ref(),
)?;
}
Expand Down Expand Up @@ -762,6 +767,14 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out
}
}

#[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.
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
Expand All @@ -772,6 +785,7 @@ fn link_natively(
crate_type: CrateType,
out_filename: &Path,
codegen_results: &CodegenResults,
lint_levels: CodegenLintLevels,
tmpdir: &Path,
) -> Result<(), ErrorGuaranteed> {
info!("preparing {:?} to {:?}", crate_type, out_filename);
Expand Down Expand Up @@ -998,12 +1012,12 @@ fn link_natively(
let mut output = prog.stderr.clone();
output.extend_from_slice(&prog.stdout);
let escaped_output = escape_linker_output(&output, flavor);
// FIXME: Add UI tests for this error.
let err = errors::LinkingFailed {
linker_path: &linker_path,
exit_status: prog.status,
command: &cmd,
escaped_output,
verbose: sess.opts.verbose,
};
sess.dcx().emit_err(err);
// If MSVC's `link.exe` was expected but the return code
Expand Down Expand Up @@ -1045,8 +1059,27 @@ fn link_natively(

sess.dcx().abort_if_errors();
}
info!("linker stderr:\n{}", escape_string(&prog.stderr));
info!("linker stdout:\n{}", escape_string(&prog.stdout));

let (level, src) = 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);
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)))
}
}
Err(e) => {
let linker_not_found = e.kind() == io::ErrorKind::NotFound;
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ pub(crate) struct LinkingFailed<'a> {
pub exit_status: ExitStatus,
pub command: &'a Command,
pub escaped_output: String,
pub verbose: bool,
}

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

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

diag.note(format!("{:?}", self.command)).note(self.escaped_output);
if self.verbose {
diag.note(format!("{:?}", self.command));
} else {
diag.note("use `--verbose` to show all linker arguments");
}

diag.note(self.escaped_output);

// Trying to match an error from OS linkers
// which by now we have no way to translate.
Expand Down
28 changes: 26 additions & 2 deletions compiler/rustc_codegen_ssa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::Symbol;

Expand Down Expand Up @@ -251,6 +256,7 @@ impl CodegenResults {
sess: &Session,
rlink_file: &Path,
codegen_results: &CodegenResults,
lint_levels: CodegenLintLevels,
outputs: &OutputFilenames,
) -> Result<usize, io::Error> {
let mut encoder = FileEncoder::new(rlink_file)?;
Expand All @@ -260,14 +266,15 @@ impl CodegenResults {
encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
encoder.emit_str(sess.cfg_version);
Encodable::encode(codegen_results, &mut encoder);
Encodable::encode(&lint_levels, &mut encoder);
Encodable::encode(outputs, &mut encoder);
encoder.finish().map_err(|(_path, err)| err)
}

pub fn deserialize_rlink(
sess: &Session,
data: Vec<u8>,
) -> Result<(Self, OutputFilenames), CodegenErrors> {
) -> Result<(Self, CodegenLintLevels, OutputFilenames), CodegenErrors> {
// The Decodable machinery is not used here because it panics if the input data is invalid
// and because its internal representation may change.
if !data.starts_with(RLINK_MAGIC) {
Expand Down Expand Up @@ -298,7 +305,24 @@ impl CodegenResults {
}

let codegen_results = CodegenResults::decode(&mut decoder);
let lint_levels = CodegenLintLevels::decode(&mut decoder);
let outputs = OutputFilenames::decode(&mut decoder);
Ok((codegen_results, outputs))
Ok((codegen_results, lint_levels, 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, 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) }
}
}
5 changes: 3 additions & 2 deletions compiler/rustc_codegen_ssa/src/traits/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use super::write::WriteBackendMethods;
use crate::back::archive::ArArchiveBuilderBuilder;
use crate::back::link::link_binary;
use crate::back::write::TargetMachineFactoryFn;
use crate::{CodegenResults, ModuleCodegen};
use crate::{CodegenLintLevels, CodegenResults, ModuleCodegen};

pub trait BackendTypes {
type Value: CodegenObject;
Expand Down Expand Up @@ -88,9 +88,10 @@ pub trait CodegenBackend {
&self,
sess: &Session,
codegen_results: CodegenResults,
lint_levels: CodegenLintLevels,
outputs: &OutputFilenames,
) -> Result<(), ErrorGuaranteed> {
link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, outputs)
link_binary(sess, &ArArchiveBuilderBuilder, codegen_results, lint_levels, outputs)
}

/// Returns `true` if this backend can be safely called from multiple threads.
Expand Down
49 changes: 28 additions & 21 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,27 +645,34 @@ fn process_rlink(sess: &Session, compiler: &interface::Compiler) {
let rlink_data = fs::read(file).unwrap_or_else(|err| {
dcx.emit_fatal(RlinkUnableToRead { err });
});
let (codegen_results, outputs) = match CodegenResults::deserialize_rlink(sess, rlink_data) {
Ok((codegen, outputs)) => (codegen, outputs),
Err(err) => {
match err {
CodegenErrors::WrongFileType => dcx.emit_fatal(RLinkWrongFileType),
CodegenErrors::EmptyVersionNumber => dcx.emit_fatal(RLinkEmptyVersionNumber),
CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => dcx
.emit_fatal(RLinkEncodingVersionMismatch { version_array, rlink_version }),
CodegenErrors::RustcVersionMismatch { rustc_version } => {
dcx.emit_fatal(RLinkRustcVersionMismatch {
rustc_version,
current_version: sess.cfg_version,
})
}
CodegenErrors::CorruptFile => {
dcx.emit_fatal(RlinkCorruptFile { file });
}
};
}
};
if compiler.codegen_backend.link(sess, codegen_results, &outputs).is_err() {
let (codegen_results, lint_levels, outputs) =
match CodegenResults::deserialize_rlink(sess, rlink_data) {
Ok((codegen, lints, outputs)) => (codegen, lints, outputs),
Err(err) => {
match err {
CodegenErrors::WrongFileType => dcx.emit_fatal(RLinkWrongFileType),
CodegenErrors::EmptyVersionNumber => {
dcx.emit_fatal(RLinkEmptyVersionNumber)
}
CodegenErrors::EncodingVersionMismatch { version_array, rlink_version } => {
dcx.emit_fatal(RLinkEncodingVersionMismatch {
version_array,
rlink_version,
})
}
CodegenErrors::RustcVersionMismatch { rustc_version } => {
dcx.emit_fatal(RLinkRustcVersionMismatch {
rustc_version,
current_version: sess.cfg_version,
})
}
CodegenErrors::CorruptFile => {
dcx.emit_fatal(RlinkCorruptFile { file });
}
};
}
};
if compiler.codegen_backend.link(sess, codegen_results, lint_levels, &outputs).is_err() {
FatalError.raise();
}
} else {
Expand Down
7 changes: 5 additions & 2 deletions compiler/rustc_interface/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use std::cell::{RefCell, RefMut};
use std::sync::Arc;

use rustc_ast as ast;
use rustc_codegen_ssa::CodegenResults;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::{CodegenLintLevels, CodegenResults};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::{OnceLock, WorkerLocal};
Expand Down Expand Up @@ -117,6 +117,7 @@ impl<'tcx> Queries<'tcx> {
pub struct Linker {
dep_graph: DepGraph,
output_filenames: Arc<OutputFilenames>,
lint_levels: CodegenLintLevels,
// Only present when incr. comp. is enabled.
crate_hash: Option<Svh>,
ongoing_codegen: Box<dyn Any>,
Expand Down Expand Up @@ -144,6 +145,7 @@ impl Linker {
Ok(Linker {
dep_graph: tcx.dep_graph.clone(),
output_filenames: Arc::clone(tcx.output_filenames(())),
lint_levels: CodegenLintLevels::from_tcx(tcx),
crate_hash: if tcx.needs_crate_hash() {
Some(tcx.crate_hash(LOCAL_CRATE))
} else {
Expand Down Expand Up @@ -187,6 +189,7 @@ impl Linker {
sess,
&rlink_file,
&codegen_results,
self.lint_levels,
&*self.output_filenames,
)
.map_err(|error| {
Expand All @@ -196,7 +199,7 @@ impl Linker {
}

let _timer = sess.prof.verbose_generic_activity("link_crate");
codegen_backend.link(sess, codegen_results, &self.output_filenames)
codegen_backend.link(sess, codegen_results, self.lint_levels, &self.output_filenames)
}
}

Expand Down
Loading

0 comments on commit 6fa9e3d

Please sign in to comment.