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
|
@ -4,6 +4,9 @@ metadata_as_needed_compatibility =
|
|||
metadata_bad_panic_strategy =
|
||||
the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
|
||||
|
||||
metadata_binary_output_to_tty =
|
||||
option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty
|
||||
|
||||
metadata_bundle_needs_static =
|
||||
linking modifier `bundle` is only compatible with `static` linking kind
|
||||
|
||||
|
@ -63,6 +66,9 @@ metadata_fail_seek_file =
|
|||
metadata_fail_write_file =
|
||||
failed to write to the file: {$err}
|
||||
|
||||
metadata_failed_copy_to_stdout =
|
||||
failed to copy {$filename} to stdout: {$err}
|
||||
|
||||
metadata_failed_create_encoded_metadata =
|
||||
failed to create encoded metadata from file: {$err}
|
||||
|
||||
|
|
|
@ -395,6 +395,17 @@ pub struct FailedWriteError {
|
|||
pub err: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_failed_copy_to_stdout)]
|
||||
pub struct FailedCopyToStdout {
|
||||
pub filename: PathBuf,
|
||||
pub err: Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_binary_output_to_tty)]
|
||||
pub struct BinaryOutputToTty;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_missing_native_library)]
|
||||
pub struct MissingNativeLibrary<'a> {
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
use crate::errors::{
|
||||
FailedCreateEncodedMetadata, FailedCreateFile, FailedCreateTempdir, FailedWriteError,
|
||||
BinaryOutputToTty, FailedCopyToStdout, FailedCreateEncodedMetadata, FailedCreateFile,
|
||||
FailedCreateTempdir, FailedWriteError,
|
||||
};
|
||||
use crate::{encode_metadata, EncodedMetadata};
|
||||
|
||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::OutputType;
|
||||
use rustc_session::config::{OutFileName, OutputType};
|
||||
use rustc_session::output::filename_for_metadata;
|
||||
use rustc_session::{MetadataKind, Session};
|
||||
use tempfile::Builder as TempFileBuilder;
|
||||
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{fs, io};
|
||||
|
||||
// FIXME(eddyb) maybe include the crate name in this?
|
||||
pub const METADATA_FILENAME: &str = "lib.rmeta";
|
||||
|
@ -74,23 +75,37 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
|
|||
// this file always exists.
|
||||
let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata);
|
||||
let (metadata_filename, metadata_tmpdir) = if need_metadata_file {
|
||||
if let Err(err) = non_durable_rename(&metadata_filename, &out_filename) {
|
||||
tcx.sess.emit_fatal(FailedWriteError { filename: out_filename, err });
|
||||
}
|
||||
let filename = match out_filename {
|
||||
OutFileName::Real(ref path) => {
|
||||
if let Err(err) = non_durable_rename(&metadata_filename, path) {
|
||||
tcx.sess.emit_fatal(FailedWriteError { filename: path.to_path_buf(), err });
|
||||
}
|
||||
path.clone()
|
||||
}
|
||||
OutFileName::Stdout => {
|
||||
if out_filename.is_tty() {
|
||||
tcx.sess.emit_err(BinaryOutputToTty);
|
||||
} else if let Err(err) = copy_to_stdout(&metadata_filename) {
|
||||
tcx.sess
|
||||
.emit_err(FailedCopyToStdout { filename: metadata_filename.clone(), err });
|
||||
}
|
||||
metadata_filename
|
||||
}
|
||||
};
|
||||
if tcx.sess.opts.json_artifact_notifications {
|
||||
tcx.sess
|
||||
.parse_sess
|
||||
.span_diagnostic
|
||||
.emit_artifact_notification(&out_filename, "metadata");
|
||||
.emit_artifact_notification(&out_filename.as_path(), "metadata");
|
||||
}
|
||||
(out_filename, None)
|
||||
(filename, None)
|
||||
} else {
|
||||
(metadata_filename, Some(metadata_tmpdir))
|
||||
};
|
||||
|
||||
// Load metadata back to memory: codegen may need to include it in object files.
|
||||
let metadata =
|
||||
EncodedMetadata::from_path(metadata_filename, metadata_tmpdir).unwrap_or_else(|err| {
|
||||
let metadata = EncodedMetadata::from_path(metadata_filename.clone(), metadata_tmpdir)
|
||||
.unwrap_or_else(|err| {
|
||||
tcx.sess.emit_fatal(FailedCreateEncodedMetadata { err });
|
||||
});
|
||||
|
||||
|
@ -116,3 +131,11 @@ pub fn non_durable_rename(src: &Path, dst: &Path) -> std::io::Result<()> {
|
|||
let _ = std::fs::remove_file(dst);
|
||||
std::fs::rename(src, dst)
|
||||
}
|
||||
|
||||
pub fn copy_to_stdout(from: &Path) -> io::Result<()> {
|
||||
let file = fs::File::open(from)?;
|
||||
let mut reader = io::BufReader::new(file);
|
||||
let mut stdout = io::stdout();
|
||||
io::copy(&mut reader, &mut stdout)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue