Skip to content

Commit

Permalink
Rollup merge of rust-lang#83846 - torhovland:issue-10971, r=davidtwco
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
GuillaumeGomez authored Jun 16, 2021
2 parents 8daad74 + 857b19d commit 2d097c1
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 4 deletions.
12 changes: 11 additions & 1 deletion compiler/rustc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,13 +216,15 @@ fn run_compiler(

let cfg = interface::parse_cfgspecs(matches.opt_strs("cfg"));
let (odir, ofile) = make_output(&matches);
let temps_dir = make_temps_dir(&matches);
let mut config = interface::Config {
opts: sopts,
crate_cfg: cfg,
input: Input::File(PathBuf::new()),
input_path: None,
output_file: ofile,
output_dir: odir,
temps_dir,
file_loader,
diagnostic_output,
stderr: None,
Expand Down Expand Up @@ -268,6 +270,7 @@ fn run_compiler(
None,
&compiler.output_dir(),
&compiler.output_file(),
&compiler.temps_dir(),
);

if should_stop == Compilation::Stop {
Expand Down Expand Up @@ -296,6 +299,7 @@ fn run_compiler(
Some(compiler.input()),
compiler.output_dir(),
compiler.output_file(),
compiler.temps_dir(),
)
.and_then(|| {
RustcDefaultCalls::list_metadata(
Expand Down Expand Up @@ -461,6 +465,11 @@ fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>)
(odir, ofile)
}

// Extract temporary directory from matches.
fn make_temps_dir(matches: &getopts::Matches) -> Option<PathBuf> {
matches.opt_str("temps-dir").map(|o| PathBuf::from(&o))
}

// Extract input (string or file and optional path) from matches.
fn make_input(
error_format: ErrorOutputType,
Expand Down Expand Up @@ -650,6 +659,7 @@ impl RustcDefaultCalls {
input: Option<&Input>,
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>,
temps_dir: &Option<PathBuf>,
) -> Compilation {
use rustc_session::config::PrintRequest::*;
// PrintRequest::NativeStaticLibs is special - printed during linking
Expand Down Expand Up @@ -691,7 +701,7 @@ impl RustcDefaultCalls {
});
let attrs = attrs.as_ref().unwrap();
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);
if *req == PrintRequest::CrateName {
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub struct Compiler {
pub(crate) input_path: Option<PathBuf>,
pub(crate) output_dir: 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) override_queries:
Option<fn(&Session, &mut ty::query::Providers, &mut ty::query::Providers)>,
Expand All @@ -56,6 +57,9 @@ impl Compiler {
pub fn output_file(&self) -> &Option<PathBuf> {
&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>> {
&self.register_lints
}
Expand All @@ -68,6 +72,7 @@ impl Compiler {
&self.input,
&self.output_dir,
&self.output_file,
&self.temps_dir,
&attrs,
&sess,
)
Expand Down Expand Up @@ -134,6 +139,7 @@ pub struct Config {
pub input_path: Option<PathBuf>,
pub output_dir: Option<PathBuf>,
pub output_file: Option<PathBuf>,
pub temps_dir: Option<PathBuf>,
pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
pub diagnostic_output: DiagnosticOutput,

Expand Down Expand Up @@ -195,6 +201,7 @@ pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R
input_path: config.input_path,
output_dir: config.output_dir,
output_file: config.output_file,
temps_dir: config.temps_dir,
register_lints: config.register_lints,
override_queries: config.override_queries,
};
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ pub fn prepare_outputs(
&compiler.input,
&compiler.output_dir,
&compiler.output_file,
&compiler.temps_dir,
&krate.attrs,
sess,
);
Expand Down Expand Up @@ -739,6 +740,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);

let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_interface/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ pub fn build_output_filenames(
input: &Input,
odir: &Option<PathBuf>,
ofile: &Option<PathBuf>,
temps_dir: &Option<PathBuf>,
attrs: &[ast::Attribute],
sess: &Session,
) -> OutputFilenames {
Expand All @@ -658,6 +659,7 @@ pub fn build_output_filenames(
dirpath,
stem,
None,
temps_dir.clone(),
sess.opts.cg.extra_filename.clone(),
sess.opts.output_types.clone(),
)
Expand Down Expand Up @@ -686,6 +688,7 @@ pub fn build_output_filenames(
out_file.parent().unwrap_or_else(|| Path::new("")).to_path_buf(),
out_file.file_stem().unwrap_or_default().to_str().unwrap().to_string(),
ofile,
temps_dir.clone(),
sess.opts.cg.extra_filename.clone(),
sess.opts.output_types.clone(),
)
Expand Down
23 changes: 20 additions & 3 deletions compiler/rustc_session/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ pub struct OutputFilenames {
pub out_directory: PathBuf,
filestem: String,
pub single_output_file: Option<PathBuf>,
pub temps_directory: Option<PathBuf>,
pub outputs: OutputTypes,
}

Expand All @@ -577,12 +578,14 @@ impl OutputFilenames {
out_directory: PathBuf,
out_filestem: String,
single_output_file: Option<PathBuf>,
temps_directory: Option<PathBuf>,
extra: String,
outputs: OutputTypes,
) -> Self {
OutputFilenames {
out_directory,
single_output_file,
temps_directory,
outputs,
filestem: format!("{}{}", out_filestem, extra),
}
Expand All @@ -593,7 +596,14 @@ impl OutputFilenames {
.get(&flavor)
.and_then(|p| p.to_owned())
.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
Expand Down Expand Up @@ -628,11 +638,17 @@ impl OutputFilenames {
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 {
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
}
Expand Down Expand Up @@ -1072,6 +1088,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
in <dir>",
"DIR",
),
opt::opt_s("", "temps-dir", "Write temporary output files to <dir>", "DIR"),
opt::opt_s(
"",
"explain",
Expand Down
9 changes: 9 additions & 0 deletions src/doc/rustc/src/command-line-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,15 @@ This flag controls the output filename.
The outputted crate will be written to this directory. This flag is ignored if
the [`-o` flag](#option-o-output) is used.

<a id="option-temps-dir"></a>
## `--temps-dir`: directory to write the intermediate files in

Intermediate files will be written to this directory. 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.

<a id="option-explain"></a>
## `--explain`: provide a detailed explanation of an error message

Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ crate fn create_config(
input_path: cpath,
output_file: None,
output_dir: None,
temps_dir: None,
file_loader: None,
diagnostic_output: DiagnosticOutput::Default,
stderr: None,
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/doctest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
input_path: None,
output_file: None,
output_dir: None,
temps_dir: None,
file_loader: None,
diagnostic_output: DiagnosticOutput::Default,
stderr: None,
Expand Down
1 change: 1 addition & 0 deletions src/test/run-make-fulldeps/issue-19371/foo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
input_path: None,
output_file: Some(output),
output_dir: None,
temps_dir: None,
file_loader: None,
diagnostic_output: DiagnosticOutput::Default,
stderr: None,
Expand Down
8 changes: 8 additions & 0 deletions src/test/run-make/issue-10971-temps-dir/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# 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 --temps-dir=$(TMPDIR)/temp1 --out-dir=$(TMPDIR) $(TMPDIR)/lib.rs \
& $(RUSTC) --crate-type=cdylib --temps-dir=$(TMPDIR)/temp2 --out-dir=$(TMPDIR) $(TMPDIR)/lib.rs

0 comments on commit 2d097c1

Please sign in to comment.