Skip to content

Prepend temp files with per-invocation random string to avoid temp filename conflicts #139453

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 11, 2025
Merged
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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4407,6 +4407,7 @@ dependencies = [
"bitflags",
"getopts",
"libc",
"rand 0.9.0",
"rustc_abi",
"rustc_ast",
"rustc_data_structures",
Expand Down
49 changes: 31 additions & 18 deletions compiler/rustc_codegen_cranelift/src/driver/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 module_name = Some(&codegen_results.modules[0].name[..]);
let path = crate_output.temp_path(output_type, module_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()
Expand All @@ -183,22 +186,16 @@ fn produce_final_output_artifacts(
ensure_removed(sess.dcx(), &path);
}
} else {
let extension = crate_output
.temp_path(output_type, None)
.extension()
.unwrap()
.to_str()
.unwrap()
.to_owned();

if crate_output.outputs.contains_explicit_name(&output_type) {
// 2) Multiple codegen units, with `--emit foo=some_name`. We have
// no good solution for this case, so warn the user.
sess.dcx().emit_warn(ssa_errors::IgnoringEmitPath { extension });
sess.dcx()
.emit_warn(ssa_errors::IgnoringEmitPath { extension: output_type.extension() });
} else if crate_output.single_output_file.is_some() {
// 3) Multiple codegen units, with `-o some_name`. We have
// no good solution for this case, so warn the user.
sess.dcx().emit_warn(ssa_errors::IgnoringOutput { extension });
sess.dcx()
.emit_warn(ssa_errors::IgnoringOutput { extension: output_type.extension() });
} else {
// 4) Multiple codegen units, but no explicit name. We
// just leave the `foo.0.x` files in place.
Expand Down Expand Up @@ -351,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>,
Expand All @@ -366,6 +364,7 @@ fn emit_cgu(

let module_regular = emit_module(
output_filenames,
invocation_temp,
prof,
product.object,
ModuleKind::Regular,
Expand All @@ -391,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,
Expand All @@ -409,7 +409,7 @@ fn emit_module(
object.set_section_data(comment_section, producer, 1);
}

let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&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)),
Expand Down Expand Up @@ -449,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(OutputType::Object, Some(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"),
Expand Down Expand Up @@ -595,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,
Expand All @@ -626,8 +635,11 @@ fn emit_metadata_module(tcx: TyCtxt<'_>, metadata: &EncodedMetadata) -> Compiled
.as_str()
.to_string();

let tmp_file =
tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&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);
Expand Down Expand Up @@ -657,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,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_cranelift/src/global_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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(OutputType::Object, Some(cgu_name)),
config.output_filenames.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp),
".asm",
);

Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
29 changes: 21 additions & 8 deletions compiler/rustc_codegen_gcc/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,23 @@ pub(crate) unsafe fn codegen(
{
let context = &module.module_llvm.context;

let module_name = module.name.clone();

let should_combine_object_files = module.module_llvm.should_combine_object_files;

let module_name = Some(&module_name[..]);

// NOTE: Only generate object files with GIMPLE when this environment variable is set for
// now because this requires a particular setup (same gcc/lto1/lto-wrapper commit as libgccjit).
// 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(OutputType::Bitcode, module_name);
let obj_out = cgcx.output_filenames.temp_path(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 {
Expand Down Expand Up @@ -117,14 +121,22 @@ pub(crate) unsafe fn codegen(
}

if config.emit_ir {
let out = cgcx.output_filenames.temp_path(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(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"));
}

Expand Down Expand Up @@ -238,6 +250,7 @@ pub(crate) unsafe fn codegen(
config.emit_asm,
config.emit_ir,
&cgcx.output_filenames,
cgcx.invocation_temp.as_deref(),
))
}

Expand Down
64 changes: 46 additions & 18 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,18 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar
tcx.output_filenames(()).split_dwarf_path(
tcx.sess.split_debuginfo(),
tcx.sess.opts.unstable_opts.split_dwarf_kind,
Some(mod_name),
mod_name,
tcx.sess.invocation_temp.as_deref(),
)
} else {
None
};

let output_obj_file =
Some(tcx.output_filenames(()).temp_path(OutputType::Object, Some(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(
Expand Down Expand Up @@ -330,8 +334,11 @@ pub(crate) fn save_temp_bitcode(
return;
}
let ext = format!("{name}.bc");
let cgu = Some(&module.name[..]);
let path = cgcx.output_filenames.temp_path_ext(&ext, cgu);
let path = cgcx.output_filenames.temp_path_ext_for_cgu(
&ext,
&module.name,
cgcx.invocation_temp.as_deref(),
);
write_bitcode_to_file(module, &path)
}

Expand Down Expand Up @@ -694,11 +701,12 @@ pub(crate) unsafe fn optimize(
let llcx = &*module.module_llvm.llcx;
let _handlers = DiagnosticHandlers::new(cgcx, dcx, llcx, module, CodegenDiagnosticsStage::Opt);

let module_name = module.name.clone();
let module_name = Some(&module_name[..]);

if config.emit_no_opt_bc {
let out = cgcx.output_filenames.temp_path_ext("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)
}

Expand Down Expand Up @@ -743,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(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()
{
Expand Down Expand Up @@ -801,8 +812,6 @@ pub(crate) unsafe fn codegen(
let llmod = module.module_llvm.llmod();
let llcx = &*module.module_llvm.llcx;
let tm = &*module.module_llvm.tm;
let module_name = module.name.clone();
let module_name = Some(&module_name[..]);
let _handlers =
DiagnosticHandlers::new(cgcx, dcx, llcx, &module, CodegenDiagnosticsStage::Codegen);

Expand All @@ -814,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(OutputType::Bitcode, module_name);
let obj_out = cgcx.output_filenames.temp_path(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 {
Expand Down Expand Up @@ -857,7 +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(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(
Expand Down Expand Up @@ -899,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(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
Expand Down Expand Up @@ -929,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(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,
Expand Down Expand Up @@ -994,6 +1021,7 @@ pub(crate) unsafe fn codegen(
config.emit_asm,
config.emit_ir,
&cgcx.output_filenames,
cgcx.invocation_temp.as_deref(),
))
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,8 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
&& let Some(f) = output_filenames.split_dwarf_path(
tcx.sess.split_debuginfo(),
tcx.sess.opts.unstable_opts.split_dwarf_kind,
Some(codegen_unit_name),
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))
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +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, Some(crate_name.as_str()));
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");
Expand Down
Loading
Loading