Auto merge of #111626 - pjhades:output, r=b-naber
Write to stdout if `-` is given as output file With this PR, if `-o -` or `--emit KIND=-` is provided, output will be written to stdout instead. Binary output (those of type `obj`, `llvm-bc`, `link` and `metadata`) being written this way will result in an error unless stdout is not a tty. Multiple output types going to stdout will trigger an error too, as they will all be mixded together. This implements https://github.com/rust-lang/compiler-team/issues/431 The idea behind the changes is to introduce an `OutFileName` enum that represents the output - be it a real path or stdout - and to use this enum along the code paths that handle different output types.
This commit is contained in:
commit
343ad6f059
32 changed files with 439 additions and 101 deletions
|
@ -8,7 +8,7 @@ use rustc_errors::{ErrorGuaranteed, Handler};
|
|||
use rustc_fs_util::fix_windows_verbatim_for_gcc;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc_metadata::find_native_static_library;
|
||||
use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
|
||||
use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME};
|
||||
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
|
||||
use rustc_middle::middle::dependency_format::Linkage;
|
||||
use rustc_middle::middle::exported_symbols::SymbolExportKind;
|
||||
|
@ -68,6 +68,7 @@ pub fn link_binary<'a>(
|
|||
) -> Result<(), ErrorGuaranteed> {
|
||||
let _timer = sess.timer("link_binary");
|
||||
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
|
||||
let mut tempfiles_for_stdout_output: Vec<PathBuf> = Vec::new();
|
||||
for &crate_type in sess.crate_types().iter() {
|
||||
// Ignore executable crates if we have -Z no-codegen, as they will error.
|
||||
if (sess.opts.unstable_opts.no_codegen || !sess.opts.output_types.should_codegen())
|
||||
|
@ -97,12 +98,15 @@ pub fn link_binary<'a>(
|
|||
.tempdir()
|
||||
.unwrap_or_else(|error| sess.emit_fatal(errors::CreateTempDir { error }));
|
||||
let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps);
|
||||
let out_filename = out_filename(
|
||||
let output = out_filename(
|
||||
sess,
|
||||
crate_type,
|
||||
outputs,
|
||||
codegen_results.crate_info.local_crate_name,
|
||||
);
|
||||
let crate_name = format!("{}", codegen_results.crate_info.local_crate_name);
|
||||
let out_filename =
|
||||
output.file_for_writing(outputs, OutputType::Exe, Some(crate_name.as_str()));
|
||||
match crate_type {
|
||||
CrateType::Rlib => {
|
||||
let _timer = sess.timer("link_rlib");
|
||||
|
@ -152,6 +156,17 @@ pub fn link_binary<'a>(
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
if output.is_stdout() {
|
||||
if output.is_tty() {
|
||||
sess.emit_err(errors::BinaryOutputToTty {
|
||||
shorthand: OutputType::Exe.shorthand(),
|
||||
});
|
||||
} else if let Err(e) = copy_to_stdout(&out_filename) {
|
||||
sess.emit_err(errors::CopyPath::new(&out_filename, output.as_path(), e));
|
||||
}
|
||||
tempfiles_for_stdout_output.push(out_filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,6 +204,11 @@ pub fn link_binary<'a>(
|
|||
remove_temps_from_module(allocator_module);
|
||||
}
|
||||
|
||||
// Remove the temporary files if output goes to stdout
|
||||
for temp in tempfiles_for_stdout_output {
|
||||
ensure_removed(sess.diagnostic(), &temp);
|
||||
}
|
||||
|
||||
// If no requested outputs require linking, then the object temporaries should
|
||||
// be kept.
|
||||
if !sess.opts.output_types.should_link() {
|
||||
|
|
|
@ -23,12 +23,13 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
|||
use rustc_incremental::{
|
||||
copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess,
|
||||
};
|
||||
use rustc_metadata::fs::copy_to_stdout;
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||
use rustc_middle::middle::exported_symbols::SymbolExportInfo;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::cgu_reuse_tracker::CguReuseTracker;
|
||||
use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType};
|
||||
use rustc_session::config::{self, CrateType, Lto, OutFileName, OutputFilenames, OutputType};
|
||||
use rustc_session::config::{Passes, SwitchWithOptPath};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
|
@ -535,9 +536,16 @@ fn produce_final_output_artifacts(
|
|||
let mut user_wants_objects = false;
|
||||
|
||||
// Produce final compile outputs.
|
||||
let copy_gracefully = |from: &Path, to: &Path| {
|
||||
if let Err(e) = fs::copy(from, to) {
|
||||
sess.emit_err(errors::CopyPath::new(from, to, e));
|
||||
let copy_gracefully = |from: &Path, to: &OutFileName| match to {
|
||||
OutFileName::Stdout => {
|
||||
if let Err(e) = copy_to_stdout(from) {
|
||||
sess.emit_err(errors::CopyPath::new(from, to.as_path(), e));
|
||||
}
|
||||
}
|
||||
OutFileName::Real(path) => {
|
||||
if let Err(e) = fs::copy(from, path) {
|
||||
sess.emit_err(errors::CopyPath::new(from, path, e));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -547,7 +555,12 @@ fn produce_final_output_artifacts(
|
|||
// to copy `foo.0.x` to `foo.x`.
|
||||
let module_name = Some(&compiled_modules.modules[0].name[..]);
|
||||
let path = crate_output.temp_path(output_type, module_name);
|
||||
copy_gracefully(&path, &crate_output.path(output_type));
|
||||
let output = crate_output.path(output_type);
|
||||
if !output_type.is_text_output() && output.is_tty() {
|
||||
sess.emit_err(errors::BinaryOutputToTty { shorthand: output_type.shorthand() });
|
||||
} else {
|
||||
copy_gracefully(&path, &output);
|
||||
}
|
||||
if !sess.opts.cg.save_temps && !keep_numbered {
|
||||
// The user just wants `foo.x`, not `foo.#module-name#.x`.
|
||||
ensure_removed(sess.diagnostic(), &path);
|
||||
|
|
|
@ -82,6 +82,12 @@ impl IntoDiagnosticArg for DebugArgPath<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_binary_output_to_tty)]
|
||||
pub struct BinaryOutputToTty {
|
||||
pub shorthand: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_ignoring_emit_path)]
|
||||
pub struct IgnoringEmitPath {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue