Prepend temp files with a string per invocation of rustc

This commit is contained in:
Michael Goulet 2025-04-06 23:50:16 +00:00
parent effef88ac7
commit 9c372d8940
17 changed files with 260 additions and 50 deletions

View File

@ -4407,6 +4407,7 @@ dependencies = [
"bitflags",
"getopts",
"libc",
"rand 0.9.0",
"rustc_abi",
"rustc_ast",
"rustc_data_structures",

View File

@ -169,8 +169,11 @@ fn produce_final_output_artifacts(
if codegen_results.modules.len() == 1 {
// 1) Only one codegen unit. In this case it's no difficulty
// to copy `foo.0.x` to `foo.x`.
let path =
crate_output.temp_path_for_cgu(output_type, &codegen_results.modules[0].name);
let path = crate_output.temp_path_for_cgu(
output_type,
&codegen_results.modules[0].name,
sess.invocation_temp.as_deref(),
);
let output = crate_output.path(output_type);
if !output_type.is_text_output() && output.is_tty() {
sess.dcx()
@ -345,6 +348,7 @@ fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> {
fn emit_cgu(
output_filenames: &OutputFilenames,
invocation_temp: Option<&str>,
prof: &SelfProfilerRef,
name: String,
module: UnwindModule<ObjectModule>,
@ -360,6 +364,7 @@ fn emit_cgu(
let module_regular = emit_module(
output_filenames,
invocation_temp,
prof,
product.object,
ModuleKind::Regular,
@ -385,6 +390,7 @@ fn emit_cgu(
fn emit_module(
output_filenames: &OutputFilenames,
invocation_temp: Option<&str>,
prof: &SelfProfilerRef,
mut object: cranelift_object::object::write::Object<'_>,
kind: ModuleKind,
@ -403,7 +409,7 @@ fn emit_module(
object.set_section_data(comment_section, producer, 1);
}
let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name);
let tmp_file = output_filenames.temp_path_for_cgu(OutputType::Object, &name, invocation_temp);
let file = match File::create(&tmp_file) {
Ok(file) => file,
Err(err) => return Err(format!("error creating object file: {}", err)),
@ -443,8 +449,11 @@ fn reuse_workproduct_for_cgu(
cgu: &CodegenUnit<'_>,
) -> Result<ModuleCodegenResult, String> {
let work_product = cgu.previous_work_product(tcx);
let obj_out_regular =
tcx.output_filenames(()).temp_path_for_cgu(OutputType::Object, cgu.name().as_str());
let obj_out_regular = tcx.output_filenames(()).temp_path_for_cgu(
OutputType::Object,
cgu.name().as_str(),
tcx.sess.invocation_temp.as_deref(),
);
let source_file_regular = rustc_incremental::in_incr_comp_dir_sess(
&tcx.sess,
&work_product.saved_files.get("o").expect("no saved object file in work product"),
@ -589,13 +598,19 @@ fn module_codegen(
let global_asm_object_file =
profiler.generic_activity_with_arg("compile assembly", &*cgu_name).run(|| {
crate::global_asm::compile_global_asm(&global_asm_config, &cgu_name, &cx.global_asm)
crate::global_asm::compile_global_asm(
&global_asm_config,
&cgu_name,
&cx.global_asm,
cx.invocation_temp.as_deref(),
)
})?;
let codegen_result =
profiler.generic_activity_with_arg("write object file", &*cgu_name).run(|| {
emit_cgu(
&global_asm_config.output_filenames,
cx.invocation_temp.as_deref(),
&profiler,
cgu_name,
module,
@ -620,8 +635,11 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled
.as_str()
.to_string();
let tmp_file =
tcx.output_filenames(()).temp_path_for_cgu(OutputType::Metadata, &metadata_cgu_name);
let tmp_file = tcx.output_filenames(()).temp_path_for_cgu(
OutputType::Metadata,
&metadata_cgu_name,
tcx.sess.invocation_temp.as_deref(),
);
let symbol_name = rustc_middle::middle::exported_symbols::metadata_symbol_name(tcx);
let obj = create_compressed_metadata_file(tcx.sess, metadata, &symbol_name);
@ -651,6 +669,7 @@ fn emit_allocator_module(tcx: TyCtxt<'_>) -> Option<CompiledModule> {
match emit_module(
tcx.output_filenames(()),
tcx.sess.invocation_temp.as_deref(),
&tcx.sess.prof,
product.object,
ModuleKind::Allocator,

View File

@ -132,6 +132,7 @@ pub(crate) fn compile_global_asm(
config: &GlobalAsmConfig,
cgu_name: &str,
global_asm: &str,
invocation_temp: Option<&str>,
) -> Result<Option<PathBuf>, String> {
if global_asm.is_empty() {
return Ok(None);
@ -146,7 +147,7 @@ pub(crate) fn compile_global_asm(
global_asm.push('\n');
let global_asm_object_file = add_file_stem_postfix(
config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name),
config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp),
".asm",
);

View File

@ -124,6 +124,7 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
/// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
struct CodegenCx {
output_filenames: Arc<OutputFilenames>,
invocation_temp: Option<String>,
should_write_ir: bool,
global_asm: String,
inline_asm_index: usize,
@ -142,6 +143,7 @@ impl CodegenCx {
};
CodegenCx {
output_filenames: tcx.output_filenames(()).clone(),
invocation_temp: tcx.sess.invocation_temp.clone(),
should_write_ir: crate::pretty_clif::should_write_ir(tcx),
global_asm: String::new(),
inline_asm_index: 0,

View File

@ -31,8 +31,16 @@ pub(crate) unsafe fn codegen(
// TODO(antoyo): remove this environment variable.
let fat_lto = env::var("EMBED_LTO_BITCODE").as_deref() == Ok("1");
let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name);
let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name);
let bc_out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::Bitcode,
&module.name,
cgcx.invocation_temp.as_deref(),
);
let obj_out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::Object,
&module.name,
cgcx.invocation_temp.as_deref(),
);
if config.bitcode_needed() {
if fat_lto {
@ -113,15 +121,22 @@ pub(crate) unsafe fn codegen(
}
if config.emit_ir {
let out =
cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name);
let out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::LlvmAssembly,
&module.name,
cgcx.invocation_temp.as_deref(),
);
std::fs::write(out, "").expect("write file");
}
if config.emit_asm {
let _timer =
cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name);
let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name);
let path = cgcx.output_filenames.temp_path_for_cgu(
OutputType::Assembly,
&module.name,
cgcx.invocation_temp.as_deref(),
);
context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str"));
}
@ -235,6 +250,7 @@ pub(crate) unsafe fn codegen(
config.emit_asm,
config.emit_ir,
&cgcx.output_filenames,
cgcx.invocation_temp.as_deref(),
))
}

View File

@ -120,13 +120,17 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar
tcx.sess.split_debuginfo(),
tcx.sess.opts.unstable_opts.split_dwarf_kind,
mod_name,
tcx.sess.invocation_temp.as_deref(),
)
} else {
None
};
let output_obj_file =
Some(tcx.output_filenames(()).temp_path_for_cgu(OutputType::Object, mod_name));
let output_obj_file = Some(tcx.output_filenames(()).temp_path_for_cgu(
OutputType::Object,
mod_name,
tcx.sess.invocation_temp.as_deref(),
));
let config = TargetMachineFactoryConfig { split_dwarf_file, output_obj_file };
target_machine_factory(
@ -330,7 +334,11 @@ pub(crate) fn save_temp_bitcode(
return;
}
let ext = format!("{name}.bc");
let path = cgcx.output_filenames.temp_path_ext_for_cgu(&ext, &module.name);
let path = cgcx.output_filenames.temp_path_ext_for_cgu(
&ext,
&module.name,
cgcx.invocation_temp.as_deref(),
);
write_bitcode_to_file(module, &path)
}
@ -694,7 +702,11 @@ pub(crate) unsafe fn optimize(
let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt);
if config.emit_no_opt_bc {
let out = cgcx.output_filenames.temp_path_ext_for_cgu("no-opt.bc", &module.name);
let out = cgcx.output_filenames.temp_path_ext_for_cgu(
"no-opt.bc",
&module.name,
cgcx.invocation_temp.as_deref(),
);
write_bitcode_to_file(module, &out)
}
@ -739,8 +751,11 @@ pub(crate) unsafe fn optimize(
if let Some(thin_lto_buffer) = thin_lto_buffer {
let thin_lto_buffer = unsafe { ThinBuffer::from_raw_ptr(thin_lto_buffer) };
module.thin_lto_buffer = Some(thin_lto_buffer.data().to_vec());
let bc_summary_out =
cgcx.output_filenames.temp_path_for_cgu(OutputType::ThinLinkBitcode, &module.name);
let bc_summary_out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::ThinLinkBitcode,
&module.name,
cgcx.invocation_temp.as_deref(),
);
if config.emit_thin_lto_summary
&& let Some(thin_link_bitcode_filename) = bc_summary_out.file_name()
{
@ -808,8 +823,16 @@ pub(crate) unsafe fn codegen(
// copy it to the .o file, and delete the bitcode if it wasn't
// otherwise requested.
let bc_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Bitcode, &module.name);
let obj_out = cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, &module.name);
let bc_out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::Bitcode,
&module.name,
cgcx.invocation_temp.as_deref(),
);
let obj_out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::Object,
&module.name,
cgcx.invocation_temp.as_deref(),
);
if config.bitcode_needed() {
if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
@ -851,8 +874,11 @@ pub(crate) unsafe fn codegen(
if config.emit_ir {
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_ir", &*module.name);
let out =
cgcx.output_filenames.temp_path_for_cgu(OutputType::LlvmAssembly, &module.name);
let out = cgcx.output_filenames.temp_path_for_cgu(
OutputType::LlvmAssembly,
&module.name,
cgcx.invocation_temp.as_deref(),
);
let out_c = path_to_c_string(&out);
extern "C" fn demangle_callback(
@ -894,7 +920,11 @@ pub(crate) unsafe fn codegen(
if config.emit_asm {
let _timer =
cgcx.prof.generic_activity_with_arg("LLVM_module_codegen_emit_asm", &*module.name);
let path = cgcx.output_filenames.temp_path_for_cgu(OutputType::Assembly, &module.name);
let path = cgcx.output_filenames.temp_path_for_cgu(
OutputType::Assembly,
&module.name,
cgcx.invocation_temp.as_deref(),
);
// We can't use the same module for asm and object code output,
// because that triggers various errors like invalid IR or broken
@ -924,7 +954,9 @@ pub(crate) unsafe fn codegen(
.prof
.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name);
let dwo_out = cgcx.output_filenames.temp_path_dwo_for_cgu(&module.name);
let dwo_out = cgcx
.output_filenames
.temp_path_dwo_for_cgu(&module.name, cgcx.invocation_temp.as_deref());
let dwo_out = match (cgcx.split_debuginfo, cgcx.split_dwarf_kind) {
// Don't change how DWARF is emitted when disabled.
(SplitDebuginfo::Off, _) => None,
@ -989,6 +1021,7 @@ pub(crate) unsafe fn codegen(
config.emit_asm,
config.emit_ir,
&cgcx.output_filenames,
cgcx.invocation_temp.as_deref(),
))
}

View File

@ -911,6 +911,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
tcx.sess.split_debuginfo(),
tcx.sess.opts.unstable_opts.split_dwarf_kind,
codegen_unit_name,
tcx.sess.invocation_temp.as_deref(),
) {
// We get a path relative to the working directory from split_dwarf_path
Some(tcx.sess.source_map().path_mapping().to_real_filename(f))

View File

@ -112,7 +112,12 @@ pub fn link_binary(
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, &crate_name);
let out_filename = output.file_for_writing(
outputs,
OutputType::Exe,
&crate_name,
sess.invocation_temp.as_deref(),
);
match crate_type {
CrateType::Rlib => {
let _timer = sess.timer("link_rlib");

View File

@ -307,13 +307,17 @@ impl TargetMachineFactoryConfig {
cgcx.split_debuginfo,
cgcx.split_dwarf_kind,
module_name,
cgcx.invocation_temp.as_deref(),
)
} else {
None
};
let output_obj_file =
Some(cgcx.output_filenames.temp_path_for_cgu(OutputType::Object, module_name));
let output_obj_file = Some(cgcx.output_filenames.temp_path_for_cgu(
OutputType::Object,
module_name,
cgcx.invocation_temp.as_deref(),
));
TargetMachineFactoryConfig { split_dwarf_file, output_obj_file }
}
}
@ -344,6 +348,7 @@ pub struct CodegenContext<B: WriteBackendMethods> {
pub crate_types: Vec<CrateType>,
pub each_linked_rlib_for_lto: Vec<(CrateNum, PathBuf)>,
pub output_filenames: Arc<OutputFilenames>,
pub invocation_temp: Option<String>,
pub regular_module_config: Arc<ModuleConfig>,
pub metadata_module_config: Arc<ModuleConfig>,
pub allocator_module_config: Arc<ModuleConfig>,
@ -582,7 +587,11 @@ fn produce_final_output_artifacts(
if let [module] = &compiled_modules.modules[..] {
// 1) Only one codegen unit. In this case it's no difficulty
// to copy `foo.0.x` to `foo.x`.
let path = crate_output.temp_path_for_cgu(output_type, &module.name);
let path = crate_output.temp_path_for_cgu(
output_type,
&module.name,
sess.invocation_temp.as_deref(),
);
let output = crate_output.path(output_type);
if !output_type.is_text_output() && output.is_tty() {
sess.dcx()
@ -959,7 +968,12 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
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, &module.name)
.split_dwarf_path(
cgcx.split_debuginfo,
cgcx.split_dwarf_kind,
&module.name,
cgcx.invocation_temp.as_deref(),
)
.expect(
"saved dwarf object in work product but `split_dwarf_path` returned `None`",
);
@ -969,7 +983,11 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
let mut load_from_incr_cache = |perform, output_type: OutputType| {
if perform {
let saved_file = module.source.saved_files.get(output_type.extension())?;
let output_path = cgcx.output_filenames.temp_path_for_cgu(output_type, &module.name);
let output_path = cgcx.output_filenames.temp_path_for_cgu(
output_type,
&module.name,
cgcx.invocation_temp.as_deref(),
);
load_from_incr_comp_dir(output_path, &saved_file)
} else {
None
@ -1214,6 +1232,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
pointer_size: tcx.data_layout.pointer_size,
invocation_temp: sess.invocation_temp.clone(),
};
// This is the "main loop" of parallel work happening for parallel codegen.

View File

@ -640,9 +640,11 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
let metadata_cgu_name =
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata")).to_string();
tcx.sess.time("write_compressed_metadata", || {
let file_name = tcx
.output_filenames(())
.temp_path_for_cgu(OutputType::Metadata, &metadata_cgu_name);
let file_name = tcx.output_filenames(()).temp_path_for_cgu(
OutputType::Metadata,
&metadata_cgu_name,
tcx.sess.invocation_temp.as_deref(),
);
let data = create_compressed_metadata_file(
tcx.sess,
&metadata,

View File

@ -105,14 +105,19 @@ impl<M> ModuleCodegen<M> {
emit_asm: bool,
emit_ir: bool,
outputs: &OutputFilenames,
invocation_temp: Option<&str>,
) -> CompiledModule {
let object = emit_obj.then(|| outputs.temp_path_for_cgu(OutputType::Object, &self.name));
let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo_for_cgu(&self.name));
let bytecode = emit_bc.then(|| outputs.temp_path_for_cgu(OutputType::Bitcode, &self.name));
let assembly =
emit_asm.then(|| outputs.temp_path_for_cgu(OutputType::Assembly, &self.name));
let llvm_ir =
emit_ir.then(|| outputs.temp_path_for_cgu(OutputType::LlvmAssembly, &self.name));
let object = emit_obj
.then(|| outputs.temp_path_for_cgu(OutputType::Object, &self.name, invocation_temp));
let dwarf_object =
emit_dwarf_obj.then(|| outputs.temp_path_dwo_for_cgu(&self.name, invocation_temp));
let bytecode = emit_bc
.then(|| outputs.temp_path_for_cgu(OutputType::Bitcode, &self.name, invocation_temp));
let assembly = emit_asm
.then(|| outputs.temp_path_for_cgu(OutputType::Assembly, &self.name, invocation_temp));
let llvm_ir = emit_ir.then(|| {
outputs.temp_path_for_cgu(OutputType::LlvmAssembly, &self.name, invocation_temp)
});
CompiledModule {
name: self.name.clone(),

View File

@ -800,6 +800,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
sess.opts.cg.metadata.clone(),
sess.cfg_version,
);
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
let dep_type = DepsType { dep_names: rustc_query_impl::dep_kind_names() };

View File

@ -7,6 +7,7 @@ edition = "2024"
# tidy-alphabetical-start
bitflags = "2.4.1"
getopts = "0.2"
rand = "0.9.0"
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_data_structures = { path = "../rustc_data_structures" }

View File

@ -1016,10 +1016,13 @@ impl OutFileName {
outputs: &OutputFilenames,
flavor: OutputType,
codegen_unit_name: &str,
invocation_temp: Option<&str>,
) -> PathBuf {
match *self {
OutFileName::Real(ref path) => path.clone(),
OutFileName::Stdout => outputs.temp_path_for_cgu(flavor, codegen_unit_name),
OutFileName::Stdout => {
outputs.temp_path_for_cgu(flavor, codegen_unit_name, invocation_temp)
}
}
}
@ -1094,21 +1097,41 @@ impl OutputFilenames {
/// Gets the path where a compilation artifact of the given type for the
/// given codegen unit should be placed on disk. If codegen_unit_name is
/// None, a path distinct from those of any codegen unit will be generated.
pub fn temp_path_for_cgu(&self, flavor: OutputType, codegen_unit_name: &str) -> PathBuf {
pub fn temp_path_for_cgu(
&self,
flavor: OutputType,
codegen_unit_name: &str,
invocation_temp: Option<&str>,
) -> PathBuf {
let extension = flavor.extension();
self.temp_path_ext_for_cgu(extension, codegen_unit_name)
self.temp_path_ext_for_cgu(extension, codegen_unit_name, invocation_temp)
}
/// Like `temp_path`, but specifically for dwarf objects.
pub fn temp_path_dwo_for_cgu(&self, codegen_unit_name: &str) -> PathBuf {
self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name)
pub fn temp_path_dwo_for_cgu(
&self,
codegen_unit_name: &str,
invocation_temp: Option<&str>,
) -> PathBuf {
self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp)
}
/// Like `temp_path`, but also supports things where there is no corresponding
/// OutputType, like noopt-bitcode or lto-bitcode.
pub fn temp_path_ext_for_cgu(&self, ext: &str, codegen_unit_name: &str) -> PathBuf {
pub fn temp_path_ext_for_cgu(
&self,
ext: &str,
codegen_unit_name: &str,
invocation_temp: Option<&str>,
) -> PathBuf {
let mut extension = codegen_unit_name.to_string();
// Append `.{invocation_temp}` to ensure temporary files are unique.
if let Some(rng) = invocation_temp {
extension.push('.');
extension.push_str(rng);
}
// FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty.
// Append `.rcgu.{ext}`.
if !ext.is_empty() {
@ -1144,9 +1167,10 @@ impl OutputFilenames {
split_debuginfo_kind: SplitDebuginfo,
split_dwarf_kind: SplitDwarfKind,
cgu_name: &str,
invocation_temp: Option<&str>,
) -> Option<PathBuf> {
let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name);
let dwo_out = self.temp_path_dwo_for_cgu(cgu_name);
let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp);
let dwo_out = self.temp_path_dwo_for_cgu(cgu_name, invocation_temp);
match (split_debuginfo_kind, split_dwarf_kind) {
(SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None,
// Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes

View File

@ -6,6 +6,8 @@ use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::{env, fmt, io};
use rand::{RngCore, rng};
use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
use rustc_data_structures::flock;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
@ -203,6 +205,14 @@ pub struct Session {
target_filesearch: FileSearch,
host_filesearch: FileSearch,
/// A random string generated per invocation of rustc.
///
/// This is prepended to all temporary files so that they do not collide
/// during concurrent invocations of rustc, or past invocations that were
/// preserved with a flag like `-C save-temps`, since these files may be
/// hard linked.
pub invocation_temp: Option<String>,
}
#[derive(PartialEq, Eq, PartialOrd, Ord)]
@ -1117,6 +1127,12 @@ pub fn build_session(
let target_filesearch =
filesearch::FileSearch::new(&sopts.search_paths, &target_tlib_path, &target);
let host_filesearch = filesearch::FileSearch::new(&sopts.search_paths, &host_tlib_path, &host);
let invocation_temp = sopts
.incremental
.as_ref()
.map(|_| rng().next_u32().to_base_fixed_len(CASE_INSENSITIVE).to_string());
let sess = Session {
target,
host,
@ -1140,6 +1156,7 @@ pub fn build_session(
expanded_args,
target_filesearch,
host_filesearch,
invocation_temp,
};
validate_commandline_args_with_session_available(&sess);

View File

@ -0,0 +1,32 @@
//@ only-x86_64-unknown-linux-gnu
// Regression test for the incremental bug in <https://github.com/rust-lang/rust/issues/139407>.
//
// A detailed explanation is described in <https://github.com/rust-lang/rust/pull/139453>,
// however the gist of the issue is that hard-linking temporary files can interact strangely
// across incremental sessions that are not finalized due to errors originating from the
// codegen backend.
use run_make_support::{run, rustc};
fn main() {
let mk_rustc = || {
let mut rustc = rustc();
rustc.input("test.rs").incremental("incr").arg("-Csave-temps").output("test");
rustc
};
// Revision 1
mk_rustc().cfg("rpass1").run();
run("test");
// Revision 2
mk_rustc().cfg("cfail2").run_fail();
// Expected to fail.
// Revision 3
mk_rustc().cfg("rpass3").run();
run("test");
}

View File

@ -0,0 +1,31 @@
#[inline(never)]
#[cfg(any(rpass1, rpass3))]
fn a() -> i32 {
0
}
#[cfg(any(cfail2))]
fn a() -> i32 {
1
}
fn main() {
evil::evil();
assert_eq!(a(), 0);
}
mod evil {
#[cfg(any(rpass1, rpass3))]
pub fn evil() {
unsafe {
std::arch::asm!("/* */");
}
}
#[cfg(any(cfail2))]
pub fn evil() {
unsafe {
std::arch::asm!("missing");
}
}
}