let work_product = if backend_config.disable_incr_cache {
None
} else {
- rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(tcx.sess, &name, &tmp_file)
+ rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
+ tcx.sess,
+ &name,
+ &[("o", &tmp_file)],
+ )
};
ModuleCodegenResult(
) -> CompiledModule {
let work_product = cgu.previous_work_product(tcx);
let obj_out = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu.name().as_str()));
- let source_file = rustc_incremental::in_incr_comp_dir_sess(&tcx.sess, &work_product.saved_file);
+ let source_file = rustc_incremental::in_incr_comp_dir_sess(
+ &tcx.sess,
+ &work_product.saved_files.get("o").expect("no saved object file in work product"),
+ );
if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) {
tcx.sess.err(&format!(
"unable to copy {} to {}: {}",
let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir");
for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) {
- if let Some(path) = &module.object {
- if let Some((id, product)) =
- copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, path)
- {
- work_products.insert(id, product);
- }
+ let mut files = Vec::new();
+ if let Some(object_file_path) = &module.object {
+ files.push(("o", object_file_path.as_path()));
+ }
+ if let Some(dwarf_object_file_path) = &module.dwarf_object {
+ files.push(("dwo", dwarf_object_file_path.as_path()));
+ }
+
+ if let Some((id, product)) =
+ copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, files.as_slice())
+ {
+ work_products.insert(id, product);
}
}
assert!(module_config.emit_obj != EmitObj::None);
let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap();
- let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name));
- let source_file = in_incr_comp_dir(&incr_comp_session_dir, &module.source.saved_file);
- debug!(
- "copying pre-existing module `{}` from {:?} to {}",
- module.name,
- source_file,
- obj_out.display()
+
+ let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| {
+ let source_file = in_incr_comp_dir(&incr_comp_session_dir, saved_path);
+ debug!(
+ "copying pre-existing module `{}` from {:?} to {}",
+ module.name,
+ source_file,
+ output_path.display()
+ );
+ match link_or_copy(&source_file, &output_path) {
+ Ok(_) => Some(output_path),
+ Err(err) => {
+ let diag_handler = cgcx.create_diag_handler();
+ diag_handler.err(&format!(
+ "unable to copy {} to {}: {}",
+ source_file.display(),
+ output_path.display(),
+ err
+ ));
+ None
+ }
+ }
+ };
+
+ let object = load_from_incr_comp_dir(
+ cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)),
+ &module.source.saved_files.get("o").expect("no saved object file in work product"),
);
- if let Err(err) = link_or_copy(&source_file, &obj_out) {
- let diag_handler = cgcx.create_diag_handler();
- diag_handler.err(&format!(
- "unable to copy {} to {}: {}",
- source_file.display(),
- obj_out.display(),
- err
- ));
- }
+ let dwarf_object =
+ module.source.saved_files.get("dwo").as_ref().and_then(|saved_dwarf_object_file| {
+ let dwarf_obj_out = cgcx
+ .output_filenames
+ .split_dwarf_path(cgcx.split_debuginfo, cgcx.split_dwarf_kind, Some(&module.name))
+ .expect(
+ "saved dwarf object in work product but `split_dwarf_path` returned `None`",
+ );
+ load_from_incr_comp_dir(dwarf_obj_out, &saved_dwarf_object_file)
+ });
WorkItemResult::Compiled(CompiledModule {
name: module.name,
kind: ModuleKind::Regular,
- object: Some(obj_out),
- dwarf_object: None,
+ object,
+ dwarf_object,
bytecode: None,
})
}
Decodable::decode(&mut work_product_decoder);
for swp in work_products {
- let mut all_files_exist = true;
- let path = in_incr_comp_dir_sess(sess, &swp.work_product.saved_file);
- if !path.exists() {
- all_files_exist = false;
-
- if sess.opts.debugging_opts.incremental_info {
- eprintln!(
- "incremental: could not find file for work \
- product: {}",
- path.display()
- );
+ let all_files_exist = swp.work_product.saved_files.iter().all(|(_, path)| {
+ let exists = in_incr_comp_dir_sess(sess, path).exists();
+ if !exists && sess.opts.debugging_opts.incremental_info {
+ eprintln!("incremental: could not find file for work product: {path}",);
}
- }
+ exists
+ });
if all_files_exist {
debug!("reconcile_work_products: all files for {:?} exist", swp);
for (id, wp) in previous_work_products.iter() {
if !new_work_products.contains_key(id) {
work_product::delete_workproduct_files(sess, wp);
- debug_assert!(!in_incr_comp_dir_sess(sess, &wp.saved_file).exists());
+ debug_assert!(
+ !wp.saved_files.iter().all(|(_, path)| in_incr_comp_dir_sess(sess, path).exists())
+ );
}
}
// Check that we did not delete one of the current work-products:
debug_assert!({
- new_work_products
- .iter()
- .map(|(_, wp)| in_incr_comp_dir_sess(sess, &wp.saved_file))
- .all(|path| path.exists())
+ new_work_products.iter().all(|(_, wp)| {
+ wp.saved_files.iter().all(|(_, path)| in_incr_comp_dir_sess(sess, path).exists())
+ })
});
}
//! [work products]: WorkProduct
use crate::persist::fs::*;
+use rustc_data_structures::stable_map::FxHashMap;
use rustc_fs_util::link_or_copy;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_session::Session;
pub fn copy_cgu_workproduct_to_incr_comp_cache_dir(
sess: &Session,
cgu_name: &str,
- path: &Path,
+ files: &[(&'static str, &Path)],
) -> Option<(WorkProductId, WorkProduct)> {
- debug!("copy_cgu_workproduct_to_incr_comp_cache_dir({:?},{:?})", cgu_name, path);
+ debug!(?cgu_name, ?files);
sess.opts.incremental.as_ref()?;
- let file_name = format!("{}.o", cgu_name);
- let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
- let saved_file = match link_or_copy(path, &path_in_incr_dir) {
- Ok(_) => file_name,
- Err(err) => {
- sess.warn(&format!(
- "error copying object file `{}` to incremental directory as `{}`: {}",
- path.display(),
- path_in_incr_dir.display(),
- err
- ));
- return None;
+ let mut saved_files = FxHashMap::default();
+ for (ext, path) in files {
+ let file_name = format!("{cgu_name}.{ext}");
+ let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name);
+ match link_or_copy(path, &path_in_incr_dir) {
+ Ok(_) => {
+ let _ = saved_files.insert(ext.to_string(), file_name);
+ }
+ Err(err) => {
+ sess.warn(&format!(
+ "error copying object file `{}` to incremental directory as `{}`: {}",
+ path.display(),
+ path_in_incr_dir.display(),
+ err
+ ));
+ }
}
- };
-
- let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_file };
+ }
+ let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_files };
+ debug!(?work_product);
let work_product_id = WorkProductId::from_cgu_name(cgu_name);
Some((work_product_id, work_product))
}
/// Removes files for a given work product.
pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
- let path = in_incr_comp_dir_sess(sess, &work_product.saved_file);
- match std_fs::remove_file(&path) {
- Ok(()) => {}
- Err(err) => {
+ for (_, path) in &work_product.saved_files {
+ let path = in_incr_comp_dir_sess(sess, path);
+ if let Err(err) = std_fs::remove_file(&path) {
sess.warn(&format!(
"file-system error deleting outdated file `{}`: {}",
path.display(),
#[derive(Clone, Debug, Encodable, Decodable)]
pub struct WorkProduct {
pub cgu_name: String,
- /// Saved file associated with this CGU.
- pub saved_file: String,
+ /// Saved files associated with this CGU. In each key/value pair, the value is the path to the
+ /// saved file and the key is some identifier for the type of file being saved.
+ ///
+ /// 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: FxHashMap<String, String>,
}
// Index type for `DepNodeData`'s edges.
--- /dev/null
+// Check that compiling with packed Split DWARF twice succeeds. This should confirm that DWARF
+// objects are cached as work products and available to the incremental compilation for `thorin` to
+// pack into a DWARF package.
+
+// ignore-tidy-linelength
+// only-x86_64-unknown-linux-gnu
+// revisions:rpass1 rpass2
+
+// [rpass1]compile-flags: -g -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
+// [rpass2]compile-flags: -g -Zquery-dep-graph -Zunstable-options -Csplit-debuginfo=packed -Zsplit-dwarf-kind=split
+
+#![feature(rustc_attrs)]
+// For `rpass2`, nothing has changed so everything should re-used.
+#![rustc_partition_reused(module = "split_debuginfo_cached", cfg = "rpass2")]
+#![rustc_partition_reused(module = "split_debuginfo_cached-another_module", cfg = "rpass2")]
+
+mod another_module {
+ pub fn foo() -> &'static str {
+ "hello world"
+ }
+}
+
+pub fn main() {
+ println!("{}", another_module::foo());
+}