Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1940,7 +1940,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
/// Returns a pair of boolean indicating whether we should preserve the object and
/// dwarf object files on the filesystem for their debug information. This is often
/// useful with split-dwarf like schemes.
fn preserve_objects_for_their_debuginfo(sess: &Session) -> (bool, bool) {
pub(crate) fn preserve_objects_for_their_debuginfo(sess: &Session) -> (bool, bool) {
// If the objects don't have debuginfo there's nothing to preserve.
if sess.opts.debuginfo == config::DebugInfo::None {
return (false, false);
Expand Down
31 changes: 28 additions & 3 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ use rustc_middle::bug;
use rustc_middle::dep_graph::{WorkProduct, WorkProductMap};
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{
self, Lto, OptLevel, OutFileName, OutputFilenames, OutputType, Passes, SwitchWithOptPath,
self, DWARF_OBJECT_EXT, Lto, OptLevel, OutFileName, OutputFilenames, OutputType, Passes,
SwitchWithOptPath,
};
use rustc_session::{IncrCompSession, Session};
use rustc_span::source_map::SourceMap;
Expand All @@ -31,7 +32,7 @@ use rustc_structures::CrateType;
use rustc_target::spec::{MergeFunctions, SanitizerSet};
use tracing::debug;

use crate::back::link::ensure_removed;
use crate::back::link::{ensure_removed, preserve_objects_for_their_debuginfo};
use crate::back::lto::{self, SerializedModule, check_lto_allowed};
use crate::diagnostics::ErrorCreatingRemarkDir;
use crate::traits::*;
Expand Down Expand Up @@ -463,6 +464,7 @@ pub(crate) fn start_async_codegen<B: WriteBackendMethods>(
fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
sess: &Session,
incr_comp_session: Option<&IncrCompSession>,
output_filenames: &OutputFilenames,
compiled_modules: &CompiledModules,
) -> WorkProductMap {
let mut work_products = WorkProductMap::default();
Expand All @@ -474,16 +476,36 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(

let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir");

let (preserved_objects, preserved_dwarf_objects) =
if sess.opts.cg.save_temps || !sess.opts.output_types.should_link() {
// With `-Csave-temps` the user wants these files kept, so don't schedule their removal.
// Without a linked output the objects are the requested outputs themselves rather than
// files kept for the debuginfo of a linked artifact.
(false, false)
} else {
preserve_objects_for_their_debuginfo(sess)
};

for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
let mut files = Vec::new();
let mut preserved_debuginfo_exts = Vec::new();
if let Some(object_file_path) = &module.object {
files.push((OutputType::Object.extension(), object_file_path.as_path()));
if preserved_objects {
preserved_debuginfo_exts.push(OutputType::Object.extension());
}
}
if let Some(global_asm_object_file_path) = &module.global_asm_object {
files.push(("asm.o", global_asm_object_file_path.as_path()));
if preserved_objects {
preserved_debuginfo_exts.push("asm.o");
}
}
if let Some(dwarf_object_file_path) = &module.dwarf_object {
files.push(("dwo", dwarf_object_file_path.as_path()));
files.push((DWARF_OBJECT_EXT, dwarf_object_file_path.as_path()));
if preserved_dwarf_objects {
preserved_debuginfo_exts.push(DWARF_OBJECT_EXT);
}
}
if let Some(path) = &module.assembly {
files.push((OutputType::Assembly.extension(), path.as_path()));
Expand All @@ -500,6 +522,8 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
&module.name,
files.as_slice(),
&module.links_from_incr_cache,
output_filenames.invocation_temp.as_deref(),
&preserved_debuginfo_exts,
);
work_products.insert(id, product);
}
Expand Down Expand Up @@ -2221,6 +2245,7 @@ impl<B: WriteBackendMethods> OngoingCodegen<B> {
let work_products = copy_all_cgu_workproducts_to_incr_comp_cache_dir(
sess,
incr_comp_session,
&self.output_filenames,
&compiled_modules,
);
produce_final_output_artifacts(sess, &compiled_modules, &self.output_filenames);
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_incremental/src/persist/save.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rustc_middle::query::on_disk_cache;
use rustc_middle::ty::TyCtxt;
use rustc_serialize::Encodable as RustcEncodable;
use rustc_serialize::opaque::FileEncoder;
use rustc_session::config::OutputFilenames;
use rustc_session::{IncrCompSession, Session};
use tracing::debug;

Expand Down Expand Up @@ -94,6 +95,7 @@ pub fn save_work_product_index(
sess: &Session,
incr_comp_session: Option<&IncrCompSession>,
dep_graph: &DepGraph,
output_filenames: &OutputFilenames,
new_work_products: WorkProductMap,
) {
if sess.opts.incremental.is_none() {
Expand All @@ -115,6 +117,9 @@ pub fn save_work_product_index(
// We also need to clean out old work-products, as not all of them are
// deleted during invalidation. Some object files don't change their
// content, they are just not needed anymore.
//
// The same goes for files the previous session left in the output directory
// for debuginfo: this session replaces the artifact that referred to them.
let previous_work_products = dep_graph.previous_work_products();
for (id, wp) in previous_work_products.to_sorted_stable_ord() {
if !new_work_products.contains_key(id) {
Expand All @@ -127,6 +132,7 @@ pub fn save_work_product_index(
.exists())
);
}
work_product::delete_preserved_debuginfo_files(sess, output_filenames, wp);
}

// Check that we did not delete one of the current work-products:
Expand Down
44 changes: 42 additions & 2 deletions compiler/rustc_incremental/src/persist/work_product.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
//!
//! [work products]: WorkProduct

use std::fs as std_fs;
use std::path::{Path, PathBuf};
use std::{fs as std_fs, io};

use rustc_data_structures::unord::UnordMap;
use rustc_fs_util::link_or_copy;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_session::config::{DWARF_OBJECT_EXT, OutputFilenames};
use rustc_session::{IncrCompSession, Session};
use tracing::debug;

Expand All @@ -24,6 +25,8 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
cgu_name: &str,
files: &[(&'static str, &Path)],
known_links: &[PathBuf],
invocation_temp: Option<&str>,
preserved_debuginfo_extensions: &[&str],
) -> (WorkProductId, WorkProduct) {
debug!(?cgu_name, ?files);
assert!(sess.opts.incremental.is_some());
Expand All @@ -50,12 +53,49 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
}
}

let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_files };
let work_product = WorkProduct {
cgu_name: cgu_name.to_string(),
saved_files,
invocation_temp: invocation_temp.map(String::from),
preserved_debuginfo_extensions: preserved_debuginfo_extensions
.iter()
.map(|s| s.to_string())
.collect(),
};
debug!(?work_product);
let work_product_id = WorkProductId::from_cgu_name(cgu_name);
(work_product_id, work_product)
}

/// Removes the temporaries a previous session's work product left in the output directory for
/// debuginfo. Their paths are derived from this session's output settings, so only the
/// directories this session writes to are touched. Files that are already gone are not an error.
pub(crate) fn delete_preserved_debuginfo_files(
sess: &Session,
output_filenames: &OutputFilenames,
work_product: &WorkProduct,
) {
// Files with this session's own invocation string are its own temporaries.
if output_filenames.invocation_temp == work_product.invocation_temp {
return;
}

let mut previous_output_filenames = output_filenames.clone();
previous_output_filenames.invocation_temp = work_product.invocation_temp.clone();
for ext in &work_product.preserved_debuginfo_extensions {
let path = if ext == DWARF_OBJECT_EXT {
previous_output_filenames.temp_path_dwo_for_cgu(&work_product.cgu_name)
} else {
previous_output_filenames.temp_path_ext_for_cgu(ext, &work_product.cgu_name)
};
if let Err(err) = std_fs::remove_file(&path)
&& err.kind() != io::ErrorKind::NotFound
{
sess.dcx().emit_warn(diagnostics::DeleteWorkProduct { path: &path, err });
}
}
}

/// Removes files for a given work product.
pub(crate) fn delete_workproduct_files(
sess: &Session,
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_interface/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ impl Linker {
"metadata",
&[("rmeta", path)],
&[],
None,
&[],
);
work_products.insert(id, product);
}
Expand All @@ -117,6 +119,7 @@ impl Linker {
sess,
incr_comp_session.as_ref(),
&self.dep_graph,
&self.output_filenames,
work_products,
)
});
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,12 @@ pub struct WorkProduct {
/// By convention, file extensions are currently used as identifiers, i.e. the key "o" maps to
/// the object file's path, and "dwo" to the dwarf object file's path.
pub saved_files: UnordMap<String, String>,
/// The per-invocation string that is part of the temporaries' file names.
pub invocation_temp: Option<String>,
/// The extensions of temporaries this CGU left in the output directory
/// after linking because the linked artifact's debuginfo refers to them. A
/// later session deletes them once it has replaced that artifact.
pub preserved_debuginfo_extensions: Vec<String>,
}

pub type WorkProductMap = UnordMap<WorkProductId, WorkProduct>;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1201,7 +1201,7 @@ pub struct OutputFilenames {
/// hard linked.
// This does not affect incr comp outputs, only where temp files are stored.
#[stable_hash(ignore)]
invocation_temp: Option<String>,
pub invocation_temp: Option<String>,

explicit_dwo_out_directory: Option<PathBuf>,
pub outputs: OutputTypes,
Expand Down
Loading