Auto merge of #83846 - torhovland:issue-10971, r=davidtwco
Added the --temps-dir option Fixes #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.
This commit is contained in:
commit
9dbbbb12c0
@ -267,6 +267,7 @@ fn run_compiler(
|
|||||||
None,
|
None,
|
||||||
compiler.output_dir(),
|
compiler.output_dir(),
|
||||||
compiler.output_file(),
|
compiler.output_file(),
|
||||||
|
compiler.temps_dir(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if should_stop == Compilation::Stop {
|
if should_stop == Compilation::Stop {
|
||||||
@ -295,6 +296,7 @@ fn run_compiler(
|
|||||||
Some(compiler.input()),
|
Some(compiler.input()),
|
||||||
compiler.output_dir(),
|
compiler.output_dir(),
|
||||||
compiler.output_file(),
|
compiler.output_file(),
|
||||||
|
compiler.temps_dir(),
|
||||||
)
|
)
|
||||||
.and_then(|| {
|
.and_then(|| {
|
||||||
RustcDefaultCalls::list_metadata(
|
RustcDefaultCalls::list_metadata(
|
||||||
@ -647,6 +649,7 @@ fn print_crate_info(
|
|||||||
input: Option<&Input>,
|
input: Option<&Input>,
|
||||||
odir: &Option<PathBuf>,
|
odir: &Option<PathBuf>,
|
||||||
ofile: &Option<PathBuf>,
|
ofile: &Option<PathBuf>,
|
||||||
|
temps_dir: &Option<PathBuf>,
|
||||||
) -> Compilation {
|
) -> Compilation {
|
||||||
use rustc_session::config::PrintRequest::*;
|
use rustc_session::config::PrintRequest::*;
|
||||||
// PrintRequest::NativeStaticLibs is special - printed during linking
|
// PrintRequest::NativeStaticLibs is special - printed during linking
|
||||||
@ -685,7 +688,7 @@ fn print_crate_info(
|
|||||||
});
|
});
|
||||||
let attrs = attrs.as_ref().unwrap();
|
let attrs = attrs.as_ref().unwrap();
|
||||||
let t_outputs = rustc_interface::util::build_output_filenames(
|
let t_outputs = rustc_interface::util::build_output_filenames(
|
||||||
input, odir, ofile, attrs, sess,
|
input, odir, ofile, temps_dir, attrs, sess,
|
||||||
);
|
);
|
||||||
let id = rustc_session::output::find_crate_name(sess, attrs, input);
|
let id = rustc_session::output::find_crate_name(sess, attrs, input);
|
||||||
if *req == PrintRequest::CrateName {
|
if *req == PrintRequest::CrateName {
|
||||||
|
@ -36,6 +36,7 @@ pub struct Compiler {
|
|||||||
pub(crate) input_path: Option<PathBuf>,
|
pub(crate) input_path: Option<PathBuf>,
|
||||||
pub(crate) output_dir: Option<PathBuf>,
|
pub(crate) output_dir: Option<PathBuf>,
|
||||||
pub(crate) output_file: Option<PathBuf>,
|
pub(crate) output_file: Option<PathBuf>,
|
||||||
|
pub(crate) temps_dir: Option<PathBuf>,
|
||||||
pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
|
pub(crate) register_lints: Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>>,
|
||||||
pub(crate) override_queries:
|
pub(crate) override_queries:
|
||||||
Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
|
Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::ExternProviders)>,
|
||||||
@ -57,6 +58,9 @@ pub fn output_dir(&self) -> &Option<PathBuf> {
|
|||||||
pub fn output_file(&self) -> &Option<PathBuf> {
|
pub fn output_file(&self) -> &Option<PathBuf> {
|
||||||
&self.output_file
|
&self.output_file
|
||||||
}
|
}
|
||||||
|
pub fn temps_dir(&self) -> &Option<PathBuf> {
|
||||||
|
&self.temps_dir
|
||||||
|
}
|
||||||
pub fn register_lints(&self) -> &Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> {
|
pub fn register_lints(&self) -> &Option<Box<dyn Fn(&Session, &mut LintStore) + Send + Sync>> {
|
||||||
&self.register_lints
|
&self.register_lints
|
||||||
}
|
}
|
||||||
@ -65,7 +69,14 @@ pub fn build_output_filenames(
|
|||||||
sess: &Session,
|
sess: &Session,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[ast::Attribute],
|
||||||
) -> OutputFilenames {
|
) -> OutputFilenames {
|
||||||
util::build_output_filenames(&self.input, &self.output_dir, &self.output_file, attrs, sess)
|
util::build_output_filenames(
|
||||||
|
&self.input,
|
||||||
|
&self.output_dir,
|
||||||
|
&self.output_file,
|
||||||
|
&self.temps_dir,
|
||||||
|
attrs,
|
||||||
|
sess,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,6 +197,8 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let temps_dir = sess.opts.debugging_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));
|
||||||
|
|
||||||
let compiler = Compiler {
|
let compiler = Compiler {
|
||||||
sess,
|
sess,
|
||||||
codegen_backend,
|
codegen_backend,
|
||||||
@ -193,6 +206,7 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R
|
|||||||
input_path: config.input_path,
|
input_path: config.input_path,
|
||||||
output_dir: config.output_dir,
|
output_dir: config.output_dir,
|
||||||
output_file: config.output_file,
|
output_file: config.output_file,
|
||||||
|
temps_dir,
|
||||||
register_lints: config.register_lints,
|
register_lints: config.register_lints,
|
||||||
override_queries: config.override_queries,
|
override_queries: config.override_queries,
|
||||||
};
|
};
|
||||||
|
@ -692,6 +692,7 @@ pub fn prepare_outputs(
|
|||||||
&compiler.input,
|
&compiler.input,
|
||||||
&compiler.output_dir,
|
&compiler.output_dir,
|
||||||
&compiler.output_file,
|
&compiler.output_file,
|
||||||
|
&compiler.temps_dir,
|
||||||
&krate.attrs,
|
&krate.attrs,
|
||||||
sess,
|
sess,
|
||||||
);
|
);
|
||||||
@ -722,6 +723,13 @@ pub fn prepare_outputs(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ref dir) = compiler.temps_dir {
|
||||||
|
if fs::create_dir_all(dir).is_err() {
|
||||||
|
sess.err("failed to find or create the directory specified by `--temps-dir`");
|
||||||
|
return Err(ErrorReported);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
write_out_deps(sess, boxed_resolver, &outputs, &output_paths);
|
write_out_deps(sess, boxed_resolver, &outputs, &output_paths);
|
||||||
|
|
||||||
let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
|
let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
|
||||||
|
@ -685,6 +685,7 @@ macro_rules! untracked {
|
|||||||
untracked!(span_debug, true);
|
untracked!(span_debug, true);
|
||||||
untracked!(span_free_formats, true);
|
untracked!(span_free_formats, true);
|
||||||
untracked!(strip, Strip::Debuginfo);
|
untracked!(strip, Strip::Debuginfo);
|
||||||
|
untracked!(temps_dir, Some(String::from("abc")));
|
||||||
untracked!(terminal_width, Some(80));
|
untracked!(terminal_width, Some(80));
|
||||||
untracked!(threads, 99);
|
untracked!(threads, 99);
|
||||||
untracked!(time, true);
|
untracked!(time, true);
|
||||||
|
@ -604,6 +604,7 @@ pub fn build_output_filenames(
|
|||||||
input: &Input,
|
input: &Input,
|
||||||
odir: &Option<PathBuf>,
|
odir: &Option<PathBuf>,
|
||||||
ofile: &Option<PathBuf>,
|
ofile: &Option<PathBuf>,
|
||||||
|
temps_dir: &Option<PathBuf>,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[ast::Attribute],
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
) -> OutputFilenames {
|
) -> OutputFilenames {
|
||||||
@ -626,6 +627,7 @@ pub fn build_output_filenames(
|
|||||||
dirpath,
|
dirpath,
|
||||||
stem,
|
stem,
|
||||||
None,
|
None,
|
||||||
|
temps_dir.clone(),
|
||||||
sess.opts.cg.extra_filename.clone(),
|
sess.opts.cg.extra_filename.clone(),
|
||||||
sess.opts.output_types.clone(),
|
sess.opts.output_types.clone(),
|
||||||
)
|
)
|
||||||
@ -654,6 +656,7 @@ pub fn build_output_filenames(
|
|||||||
out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
|
out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
|
||||||
out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(),
|
out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(),
|
||||||
ofile,
|
ofile,
|
||||||
|
temps_dir.clone(),
|
||||||
sess.opts.cg.extra_filename.clone(),
|
sess.opts.cg.extra_filename.clone(),
|
||||||
sess.opts.output_types.clone(),
|
sess.opts.output_types.clone(),
|
||||||
)
|
)
|
||||||
|
@ -578,6 +578,7 @@ pub struct OutputFilenames {
|
|||||||
pub out_directory: PathBuf,
|
pub out_directory: PathBuf,
|
||||||
filestem: String,
|
filestem: String,
|
||||||
pub single_output_file: Option<PathBuf>,
|
pub single_output_file: Option<PathBuf>,
|
||||||
|
pub temps_directory: Option<PathBuf>,
|
||||||
pub outputs: OutputTypes,
|
pub outputs: OutputTypes,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,12 +593,14 @@ pub fn new(
|
|||||||
out_directory: PathBuf,
|
out_directory: PathBuf,
|
||||||
out_filestem: String,
|
out_filestem: String,
|
||||||
single_output_file: Option<PathBuf>,
|
single_output_file: Option<PathBuf>,
|
||||||
|
temps_directory: Option<PathBuf>,
|
||||||
extra: String,
|
extra: String,
|
||||||
outputs: OutputTypes,
|
outputs: OutputTypes,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
OutputFilenames {
|
OutputFilenames {
|
||||||
out_directory,
|
out_directory,
|
||||||
single_output_file,
|
single_output_file,
|
||||||
|
temps_directory,
|
||||||
outputs,
|
outputs,
|
||||||
filestem: format!("{}{}", out_filestem, extra),
|
filestem: format!("{}{}", out_filestem, extra),
|
||||||
}
|
}
|
||||||
@ -608,7 +611,14 @@ pub fn path(&self, flavor: OutputType) -> PathBuf {
|
|||||||
.get(&flavor)
|
.get(&flavor)
|
||||||
.and_then(|p| p.to_owned())
|
.and_then(|p| p.to_owned())
|
||||||
.or_else(|| self.single_output_file.clone())
|
.or_else(|| self.single_output_file.clone())
|
||||||
.unwrap_or_else(|| self.temp_path(flavor, None))
|
.unwrap_or_else(|| self.output_path(flavor))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the output path where a compilation artifact of the given type
|
||||||
|
/// should be placed on disk.
|
||||||
|
pub fn output_path(&self, flavor: OutputType) -> PathBuf {
|
||||||
|
let extension = flavor.extension();
|
||||||
|
self.with_directory_and_extension(&self.out_directory, &extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the path where a compilation artifact of the given type for the
|
/// Gets the path where a compilation artifact of the given type for the
|
||||||
@ -643,11 +653,17 @@ pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathB
|
|||||||
extension.push_str(ext);
|
extension.push_str(ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.with_extension(&extension)
|
let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
|
||||||
|
|
||||||
|
self.with_directory_and_extension(&temps_directory, &extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_extension(&self, extension: &str) -> PathBuf {
|
pub fn with_extension(&self, extension: &str) -> PathBuf {
|
||||||
let mut path = self.out_directory.join(&self.filestem);
|
self.with_directory_and_extension(&self.out_directory, extension)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf {
|
||||||
|
let mut path = directory.join(&self.filestem);
|
||||||
path.set_extension(extension);
|
path.set_extension(extension);
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
@ -1331,6 +1331,8 @@ mod parse {
|
|||||||
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
|
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
|
||||||
teach: bool = (false, parse_bool, [TRACKED],
|
teach: bool = (false, parse_bool, [TRACKED],
|
||||||
"show extended diagnostic help (default: no)"),
|
"show extended diagnostic help (default: no)"),
|
||||||
|
temps_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
|
||||||
|
"the directory the intermediate files are written to"),
|
||||||
terminal_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
|
terminal_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
|
||||||
"set the current terminal width"),
|
"set the current terminal width"),
|
||||||
tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
|
tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
|
||||||
|
10
src/doc/unstable-book/src/compiler-flags/temps-dir.md
Normal file
10
src/doc/unstable-book/src/compiler-flags/temps-dir.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# `temps-dir`
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The `-Ztemps-dir` compiler flag specifies the directory to write the
|
||||||
|
intermediate files in. If not set, the output directory is used. This option is
|
||||||
|
useful if you are running more than one instance of `rustc` (e.g. with different
|
||||||
|
`--crate-type` settings), and you need to make sure they are not overwriting
|
||||||
|
each other's intermediate files. No files are kept unless `-C save-temps=yes` is
|
||||||
|
also set.
|
10
src/test/run-make/issue-10971-temps-dir/Makefile
Normal file
10
src/test/run-make/issue-10971-temps-dir/Makefile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
-include ../../run-make-fulldeps/tools.mk
|
||||||
|
|
||||||
|
# Regression test for issue #10971
|
||||||
|
# Running two invocations in parallel would overwrite each other's temp files.
|
||||||
|
|
||||||
|
all:
|
||||||
|
touch $(TMPDIR)/lib.rs
|
||||||
|
|
||||||
|
$(RUSTC) --crate-type=lib -Z temps-dir=$(TMPDIR)/temp1 $(TMPDIR)/lib.rs & \
|
||||||
|
$(RUSTC) --crate-type=staticlib -Z temps-dir=$(TMPDIR)/temp2 $(TMPDIR)/lib.rs
|
Loading…
Reference in New Issue
Block a user