Skip to content

Commit 3019fa4

Browse files
authored
Rollup merge of rust-lang#83846 - torhovland:issue-10971, r=davidtwco
Added the --temps-dir option Fixes rust-lang#10971. The new `--temps-dir` option puts intermediate files in a user-specified directory. This provides a fix for the issue where parallel invocations of rustc would overwrite each other's intermediate files. No files are kept in the intermediate directory unless `-C save-temps=yes`. If additional files are specifically requested using `--emit asm,llvm-bc,llvm-ir,obj,metadata,link,dep-info,mir`, these will be put in the output directory rather than the intermediate directory. This is a backward-compatible change, i.e. if `--temps-dir` is not specified, the behavior is the same as before.
2 parents d608229 + 13dbdc6 commit 3019fa4

File tree

9 files changed

+75
-5
lines changed

9 files changed

+75
-5
lines changed

compiler/rustc_driver/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ fn run_compiler(
267267
None,
268268
compiler.output_dir(),
269269
compiler.output_file(),
270+
compiler.temps_dir(),
270271
);
271272

272273
if should_stop == Compilation::Stop {
@@ -295,6 +296,7 @@ fn run_compiler(
295296
Some(compiler.input()),
296297
compiler.output_dir(),
297298
compiler.output_file(),
299+
compiler.temps_dir(),
298300
)
299301
.and_then(|| {
300302
RustcDefaultCalls::list_metadata(
@@ -647,6 +649,7 @@ impl RustcDefaultCalls {
647649
input: Option<&Input>,
648650
odir: &Option<PathBuf>,
649651
ofile: &Option<PathBuf>,
652+
temps_dir: &Option<PathBuf>,
650653
) -> Compilation {
651654
use rustc_session::config::PrintRequest::*;
652655
// PrintRequest::NativeStaticLibs is special - printed during linking
@@ -685,7 +688,7 @@ impl RustcDefaultCalls {
685688
});
686689
let attrs = attrs.as_ref().unwrap();
687690
let t_outputs = rustc_interface::util::build_output_filenames(
688-
input, odir, ofile, attrs, sess,
691+
input, odir, ofile, temps_dir, attrs, sess,
689692
);
690693
let id = rustc_session::output::find_crate_name(sess, attrs, input);
691694
if *req == PrintRequest::CrateName {

compiler/rustc_interface/src/interface.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub struct Compiler {
3636
pub(crate) input_path: Option<PathBuf>,
3737
pub(crate) output_dir: Option<PathBuf>,
3838
pub(crate) output_file: Option<PathBuf>,
39+
pub(crate) temps_dir: Option<PathBuf>,
3940
pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
4041
pub(crate) override_queries:
4142
Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
@@ -57,6 +58,9 @@ impl Compiler {
5758
pub fn output_file(&self) -> &Option<PathBuf> {
5859
&self.output_file
5960
}
61+
pub fn temps_dir(&self) -> &Option<PathBuf> {
62+
&self.temps_dir
63+
}
6064
pub fn register_lints(&self) -> &Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> {
6165
&self.register_lints
6266
}
@@ -65,7 +69,14 @@ impl Compiler {
6569
sess: &Session,
6670
attrs: &[ast::Attribute],
6771
) -> OutputFilenames {
68-
util::build_output_filenames(&self.input, &self.output_dir, &self.output_file, attrs, sess)
72+
util::build_output_filenames(
73+
&self.input,
74+
&self.output_dir,
75+
&self.output_file,
76+
&self.temps_dir,
77+
attrs,
78+
sess,
79+
)
6980
}
7081
}
7182

@@ -186,13 +197,16 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R
186197
);
187198
}
188199

200+
let temps_dir = sess.opts.debugging_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));
201+
189202
let compiler = Compiler {
190203
sess,
191204
codegen_backend,
192205
input: config.input,
193206
input_path: config.input_path,
194207
output_dir: config.output_dir,
195208
output_file: config.output_file,
209+
temps_dir,
196210
register_lints: config.register_lints,
197211
override_queries: config.override_queries,
198212
};

compiler/rustc_interface/src/passes.rs

+8
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ pub fn prepare_outputs(
692692
&compiler.input,
693693
&compiler.output_dir,
694694
&compiler.output_file,
695+
&compiler.temps_dir,
695696
&krate.attrs,
696697
sess,
697698
);
@@ -722,6 +723,13 @@ pub fn prepare_outputs(
722723
}
723724
}
724725

726+
if let Some(ref dir) = compiler.temps_dir {
727+
if fs::create_dir_all(dir).is_err() {
728+
sess.err("failed to find or create the directory specified by `--temps-dir`");
729+
return Err(ErrorReported);
730+
}
731+
}
732+
725733
write_out_deps(sess, boxed_resolver, &outputs, &output_paths);
726734

727735
let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)

compiler/rustc_interface/src/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,7 @@ fn test_debugging_options_tracking_hash() {
685685
untracked!(span_debug, true);
686686
untracked!(span_free_formats, true);
687687
untracked!(strip, Strip::Debuginfo);
688+
untracked!(temps_dir, Some(String::from("abc")));
688689
untracked!(terminal_width, Some(80));
689690
untracked!(threads, 99);
690691
untracked!(time, true);

compiler/rustc_interface/src/util.rs

+3
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ pub fn build_output_filenames(
604604
input: &Input,
605605
odir: &Option<PathBuf>,
606606
ofile: &Option<PathBuf>,
607+
temps_dir: &Option<PathBuf>,
607608
attrs: &[ast::Attribute],
608609
sess: &Session,
609610
) -> OutputFilenames {
@@ -626,6 +627,7 @@ pub fn build_output_filenames(
626627
dirpath,
627628
stem,
628629
None,
630+
temps_dir.clone(),
629631
sess.opts.cg.extra_filename.clone(),
630632
sess.opts.output_types.clone(),
631633
)
@@ -654,6 +656,7 @@ pub fn build_output_filenames(
654656
out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
655657
out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(),
656658
ofile,
659+
temps_dir.clone(),
657660
sess.opts.cg.extra_filename.clone(),
658661
sess.opts.output_types.clone(),
659662
)

compiler/rustc_session/src/config.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ pub struct OutputFilenames {
578578
pub out_directory: PathBuf,
579579
filestem: String,
580580
pub single_output_file: Option<PathBuf>,
581+
pub temps_directory: Option<PathBuf>,
581582
pub outputs: OutputTypes,
582583
}
583584

@@ -592,12 +593,14 @@ impl OutputFilenames {
592593
out_directory: PathBuf,
593594
out_filestem: String,
594595
single_output_file: Option<PathBuf>,
596+
temps_directory: Option<PathBuf>,
595597
extra: String,
596598
outputs: OutputTypes,
597599
) -> Self {
598600
OutputFilenames {
599601
out_directory,
600602
single_output_file,
603+
temps_directory,
601604
outputs,
602605
filestem: format!("{}{}", out_filestem, extra),
603606
}
@@ -608,7 +611,14 @@ impl OutputFilenames {
608611
.get(&flavor)
609612
.and_then(|p| p.to_owned())
610613
.or_else(|| self.single_output_file.clone())
611-
.unwrap_or_else(|| self.temp_path(flavor, None))
614+
.unwrap_or_else(|| self.output_path(flavor))
615+
}
616+
617+
/// Gets the output path where a compilation artifact of the given type
618+
/// should be placed on disk.
619+
pub fn output_path(&self, flavor: OutputType) -> PathBuf {
620+
let extension = flavor.extension();
621+
self.with_directory_and_extension(&self.out_directory, &extension)
612622
}
613623

614624
/// Gets the path where a compilation artifact of the given type for the
@@ -643,11 +653,17 @@ impl OutputFilenames {
643653
extension.push_str(ext);
644654
}
645655

646-
self.with_extension(&extension)
656+
let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
657+
658+
self.with_directory_and_extension(&temps_directory, &extension)
647659
}
648660

649661
pub fn with_extension(&self, extension: &str) -> PathBuf {
650-
let mut path = self.out_directory.join(&self.filestem);
662+
self.with_directory_and_extension(&self.out_directory, extension)
663+
}
664+
665+
fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf {
666+
let mut path = directory.join(&self.filestem);
651667
path.set_extension(extension);
652668
path
653669
}

compiler/rustc_session/src/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1331,6 +1331,8 @@ options! {
13311331
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
13321332
teach: bool = (false, parse_bool, [TRACKED],
13331333
"show extended diagnostic help (default: no)"),
1334+
temps_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
1335+
"the directory the intermediate files are written to"),
13341336
terminal_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
13351337
"set the current terminal width"),
13361338
tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# `temps-dir`
2+
3+
--------------------
4+
5+
The `-Ztemps-dir` compiler flag specifies the directory to write the
6+
intermediate files in. If not set, the output directory is used. This option is
7+
useful if you are running more than one instance of `rustc` (e.g. with different
8+
`--crate-type` settings), and you need to make sure they are not overwriting
9+
each other's intermediate files. No files are kept unless `-C save-temps=yes` is
10+
also set.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
-include ../../run-make-fulldeps/tools.mk
2+
3+
# Regression test for issue #10971
4+
# Running two invocations in parallel would overwrite each other's temp files.
5+
6+
## clean up unused env variables which might cause harm.
7+
unexport RUSTC_LINKER
8+
9+
all:
10+
touch $(TMPDIR)/lib.rs
11+
12+
$(RUSTC) --crate-type=lib -Z temps-dir=$(TMPDIR)/temp1 $(TMPDIR)/lib.rs & \
13+
$(RUSTC) --crate-type=cdylib -Z temps-dir=$(TMPDIR)/temp2 $(TMPDIR)/lib.rs

0 commit comments

Comments
 (0)