Rollup merge of #75315 - Mark-Simulacrum:save-temps, r=ecstatic-morse
Avoid deleting temporary files on error Previously if the compiler error'd, fatally, then temporary directories which should be preserved by -Csave-temps would be deleted due to fatal compiler errors being implemented as panics. cc @infinity0 (Hopefully) fixes #75275, but I haven't tested
This commit is contained in:
commit
992988bbc5
@ -3367,6 +3367,7 @@ dependencies = [
|
||||
"smallvec 1.4.0",
|
||||
"stable_deref_trait",
|
||||
"stacker",
|
||||
"tempfile",
|
||||
"tracing",
|
||||
"winapi 0.3.8",
|
||||
]
|
||||
|
@ -1,4 +1,5 @@
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||
use rustc_fs_util::fix_windows_verbatim_for_gcc;
|
||||
use rustc_hir::def_id::CrateNum;
|
||||
use rustc_middle::middle::cstore::{EncodedMetadata, LibSource, NativeLib};
|
||||
@ -23,7 +24,7 @@ use super::rpath::{self, RPathConfig};
|
||||
use crate::{looks_like_rust_object_file, CodegenResults, CrateInfo, METADATA_FILENAME};
|
||||
|
||||
use cc::windows_registry;
|
||||
use tempfile::{Builder as TempFileBuilder, TempDir};
|
||||
use tempfile::Builder as TempFileBuilder;
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -70,27 +71,21 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
||||
}
|
||||
});
|
||||
|
||||
let tmpdir = TempFileBuilder::new()
|
||||
.prefix("rustc")
|
||||
.tempdir()
|
||||
.unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
|
||||
|
||||
if outputs.outputs.should_codegen() {
|
||||
let tmpdir = TempFileBuilder::new()
|
||||
.prefix("rustc")
|
||||
.tempdir()
|
||||
.unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
|
||||
let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps);
|
||||
let out_filename = out_filename(sess, crate_type, outputs, crate_name);
|
||||
match crate_type {
|
||||
CrateType::Rlib => {
|
||||
let _timer = sess.timer("link_rlib");
|
||||
link_rlib::<B>(
|
||||
sess,
|
||||
codegen_results,
|
||||
RlibFlavor::Normal,
|
||||
&out_filename,
|
||||
&tmpdir,
|
||||
)
|
||||
.build();
|
||||
link_rlib::<B>(sess, codegen_results, RlibFlavor::Normal, &out_filename, &path)
|
||||
.build();
|
||||
}
|
||||
CrateType::Staticlib => {
|
||||
link_staticlib::<B>(sess, codegen_results, &out_filename, &tmpdir);
|
||||
link_staticlib::<B>(sess, codegen_results, &out_filename, &path);
|
||||
}
|
||||
_ => {
|
||||
link_natively::<B>(
|
||||
@ -98,7 +93,7 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
||||
crate_type,
|
||||
&out_filename,
|
||||
codegen_results,
|
||||
tmpdir.path(),
|
||||
path.as_ref(),
|
||||
target_cpu,
|
||||
);
|
||||
}
|
||||
@ -107,10 +102,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
||||
sess.parse_sess.span_diagnostic.emit_artifact_notification(&out_filename, "link");
|
||||
}
|
||||
}
|
||||
|
||||
if sess.opts.cg.save_temps {
|
||||
let _ = tmpdir.into_path();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the temporary object file and metadata if we aren't saving temps
|
||||
@ -279,8 +270,8 @@ pub fn each_linked_rlib(
|
||||
/// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
|
||||
/// directory being searched for `extern crate` (observing an incomplete file).
|
||||
/// The returned path is the temporary file containing the complete metadata.
|
||||
pub fn emit_metadata(sess: &Session, metadata: &EncodedMetadata, tmpdir: &TempDir) -> PathBuf {
|
||||
let out_filename = tmpdir.path().join(METADATA_FILENAME);
|
||||
pub fn emit_metadata(sess: &Session, metadata: &EncodedMetadata, tmpdir: &MaybeTempDir) -> PathBuf {
|
||||
let out_filename = tmpdir.as_ref().join(METADATA_FILENAME);
|
||||
let result = fs::write(&out_filename, &metadata.raw_data);
|
||||
|
||||
if let Err(e) = result {
|
||||
@ -301,7 +292,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
|
||||
codegen_results: &CodegenResults,
|
||||
flavor: RlibFlavor,
|
||||
out_filename: &Path,
|
||||
tmpdir: &TempDir,
|
||||
tmpdir: &MaybeTempDir,
|
||||
) -> B {
|
||||
info!("preparing rlib to {:?}", out_filename);
|
||||
let mut ab = <B as ArchiveBuilder>::new(sess, out_filename, None);
|
||||
@ -406,7 +397,7 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
|
||||
sess: &'a Session,
|
||||
codegen_results: &CodegenResults,
|
||||
out_filename: &Path,
|
||||
tempdir: &TempDir,
|
||||
tempdir: &MaybeTempDir,
|
||||
) {
|
||||
let mut ab =
|
||||
link_rlib::<B>(sess, codegen_results, RlibFlavor::StaticlibBase, out_filename, tempdir);
|
||||
|
@ -30,6 +30,7 @@ bitflags = "1.2.1"
|
||||
measureme = "0.7.1"
|
||||
libc = "0.2"
|
||||
stacker = "0.1.9"
|
||||
tempfile = "3.0.5"
|
||||
|
||||
[dependencies.parking_lot]
|
||||
version = "0.10"
|
||||
|
@ -95,6 +95,7 @@ pub mod vec_linked_list;
|
||||
pub mod work_queue;
|
||||
pub use atomic_ref::AtomicRef;
|
||||
pub mod frozen;
|
||||
pub mod temp_dir;
|
||||
|
||||
pub struct OnDrop<F: Fn()>(pub F);
|
||||
|
||||
|
34
src/librustc_data_structures/temp_dir.rs
Normal file
34
src/librustc_data_structures/temp_dir.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use std::mem::ManuallyDrop;
|
||||
use std::path::Path;
|
||||
use tempfile::TempDir;
|
||||
|
||||
/// This is used to avoid TempDir being dropped on error paths unintentionally.
|
||||
#[derive(Debug)]
|
||||
pub struct MaybeTempDir {
|
||||
dir: ManuallyDrop<TempDir>,
|
||||
// Whether the TempDir should be deleted on drop.
|
||||
keep: bool,
|
||||
}
|
||||
|
||||
impl Drop for MaybeTempDir {
|
||||
fn drop(&mut self) {
|
||||
// Safety: We are in the destructor, and no further access will
|
||||
// occur.
|
||||
let dir = unsafe { ManuallyDrop::take(&mut self.dir) };
|
||||
if self.keep {
|
||||
dir.into_path();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for MaybeTempDir {
|
||||
fn as_ref(&self) -> &Path {
|
||||
self.dir.path()
|
||||
}
|
||||
}
|
||||
|
||||
impl MaybeTempDir {
|
||||
pub fn new(dir: TempDir, keep_on_drop: bool) -> MaybeTempDir {
|
||||
MaybeTempDir { dir: ManuallyDrop::new(dir), keep: keep_on_drop }
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ use rustc_ast::{self, ast, visit};
|
||||
use rustc_codegen_ssa::back::link::emit_metadata;
|
||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||
use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
|
||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||
use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
|
||||
use rustc_errors::{ErrorReported, PResult};
|
||||
use rustc_expand::base::ExtCtxt;
|
||||
@ -974,6 +975,7 @@ fn encode_and_write_metadata(
|
||||
.prefix("rmeta")
|
||||
.tempdir_in(out_filename.parent().unwrap())
|
||||
.unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)));
|
||||
let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
|
||||
let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir);
|
||||
if let Err(e) = fs::rename(&metadata_filename, &out_filename) {
|
||||
tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
|
||||
|
Loading…
Reference in New Issue
Block a user