diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index f3a00a00750..90e501a2342 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -1141,7 +1141,7 @@ impl RustDocFingerprint { let fingerprint_path = build_runner .files() - .host_root() + .host_build_root() .join(".rustdoc_fingerprint.json"); let write_fingerprint = || -> CargoResult<()> { paths::write( @@ -1181,7 +1181,7 @@ impl RustDocFingerprint { .bcx .all_kinds .iter() - .map(|kind| build_runner.files().layout(*kind).doc()) + .map(|kind| build_runner.files().layout(*kind).artifact_dir().doc()) .filter(|path| path.exists()) .try_for_each(|path| clean_doc(path))?; write_fingerprint()?; diff --git a/src/cargo/core/compiler/build_runner/compilation_files.rs b/src/cargo/core/compiler/build_runner/compilation_files.rs index 23ea9867fd4..34d4660c5be 100644 --- a/src/cargo/core/compiler/build_runner/compilation_files.rs +++ b/src/cargo/core/compiler/build_runner/compilation_files.rs @@ -211,13 +211,13 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { // Docscrape units need to have doc/ set as the out_dir so sources for reverse-dependencies // will be put into doc/ and not into deps/ where the *.examples files are stored. if unit.mode.is_doc() || unit.mode.is_doc_scrape() { - self.layout(unit.kind).doc().to_path_buf() + self.layout(unit.kind).artifact_dir().doc().to_path_buf() } else if unit.mode.is_doc_test() { panic!("doc tests do not have an out dir"); } else if unit.target.is_custom_build() { self.build_script_dir(unit) } else if unit.target.is_example() { - self.layout(unit.kind).build_examples().to_path_buf() + self.layout(unit.kind).build_dir().examples().to_path_buf() } else if unit.artifact.is_true() { self.artifact_dir(unit) } else { @@ -250,36 +250,41 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { /// Returns the final artifact path for the host (`/…/target/debug`) pub fn host_dest(&self) -> &Path { - self.host.dest() + self.host.artifact_dir().dest() } - /// Returns the root of the build output tree for the host (`/…/target`) - pub fn host_root(&self) -> &Path { - self.host.root() + /// Returns the root of the build output tree for the host (`/…/build-dir`) + pub fn host_build_root(&self) -> &Path { + self.host.build_dir().root() } /// Returns the host `deps` directory path. pub fn host_deps(&self, unit: &Unit) -> PathBuf { let dir = self.pkg_dir(unit); - self.host.deps(&dir) + self.host.build_dir().deps(&dir) } /// Returns the directories where Rust crate dependencies are found for the /// specified unit. pub fn deps_dir(&self, unit: &Unit) -> PathBuf { let dir = self.pkg_dir(unit); - self.layout(unit.kind).deps(&dir) + self.layout(unit.kind).build_dir().deps(&dir) } /// Directory where the fingerprint for the given unit should go. pub fn fingerprint_dir(&self, unit: &Unit) -> PathBuf { let dir = self.pkg_dir(unit); - self.layout(unit.kind).fingerprint(&dir) + self.layout(unit.kind).build_dir().fingerprint(&dir) } /// Directory where incremental output for the given unit should go. pub fn incremental_dir(&self, unit: &Unit) -> &Path { - self.layout(unit.kind).incremental() + self.layout(unit.kind).build_dir().incremental() + } + + /// Directory where timing output should go. + pub fn timings_dir(&self) -> &Path { + self.host.artifact_dir().timings() } /// Returns the path for a file in the fingerprint directory. @@ -314,7 +319,9 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { assert!(!unit.mode.is_run_custom_build()); assert!(self.metas.contains_key(unit)); let dir = self.pkg_dir(unit); - self.layout(CompileKind::Host).build_script(&dir) + self.layout(CompileKind::Host) + .build_dir() + .build_script(&dir) } /// Returns the directory for compiled artifacts files. @@ -338,7 +345,11 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { invalid ), }; - self.layout(unit.kind).artifact().join(dir).join(kind) + self.layout(unit.kind) + .build_dir() + .artifact() + .join(dir) + .join(kind) } /// Returns the directory where information about running a build script @@ -348,7 +359,9 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { assert!(unit.target.is_custom_build()); assert!(unit.mode.is_run_custom_build()); let dir = self.pkg_dir(unit); - self.layout(unit.kind).build_script_execution(&dir) + self.layout(unit.kind) + .build_dir() + .build_script_execution(&dir) } /// Returns the "`OUT_DIR`" directory for running a build script. @@ -367,7 +380,7 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { bcx: &BuildContext<'_, '_>, ) -> CargoResult { assert!(target.is_bin()); - let dest = self.layout(kind).dest(); + let dest = self.layout(kind).artifact_dir().dest(); let info = bcx.target_data.info(kind); let (file_types, _) = info .rustc_outputs( @@ -435,11 +448,14 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> { let filename = file_type.uplift_filename(&unit.target); let uplift_path = if unit.target.is_example() { // Examples live in their own little world. - self.layout(unit.kind).examples().join(filename) + self.layout(unit.kind) + .artifact_dir() + .examples() + .join(filename) } else if unit.target.is_custom_build() { self.build_script_dir(unit).join(filename) } else { - self.layout(unit.kind).dest().join(filename) + self.layout(unit.kind).artifact_dir().dest().join(filename) }; if from_path == uplift_path { // This can happen with things like examples that reside in the diff --git a/src/cargo/core/compiler/build_runner/mod.rs b/src/cargo/core/compiler/build_runner/mod.rs index bb3bf67fe2e..1bee67f23db 100644 --- a/src/cargo/core/compiler/build_runner/mod.rs +++ b/src/cargo/core/compiler/build_runner/mod.rs @@ -401,7 +401,7 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> { let layout = files.layout(kind); self.compilation .root_output - .insert(kind, layout.dest().to_path_buf()); + .insert(kind, layout.artifact_dir().dest().to_path_buf()); if self.bcx.gctx.cli_unstable().build_dir_new_layout { for (unit, _) in self.bcx.unit_graph.iter() { let dep_dir = self.files().deps_dir(unit); @@ -411,7 +411,7 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> { } else { self.compilation .deps_output - .insert(kind, layout.legacy_deps().to_path_buf()); + .insert(kind, layout.build_dir().legacy_deps().to_path_buf()); } } Ok(()) diff --git a/src/cargo/core/compiler/layout.rs b/src/cargo/core/compiler/layout.rs index 6049e90ec22..d0207db8aea 100644 --- a/src/cargo/core/compiler/layout.rs +++ b/src/cargo/core/compiler/layout.rs @@ -111,38 +111,8 @@ use std::path::{Path, PathBuf}; /// /// See module docs for more information. pub struct Layout { - /// The root directory: `/path/to/target`. - /// If cross compiling: `/path/to/target/$TRIPLE`. - root: PathBuf, - /// The final artifact destination: `$root/debug` (or `release`). - dest: PathBuf, - /// The directory with rustc artifacts: `$dest/deps` - deps: PathBuf, - /// The directory for build scripts: `$dest/build` - build: PathBuf, - /// The directory for artifacts, i.e. binaries, cdylibs, staticlibs: `$dest/deps/artifact` - artifact: PathBuf, - /// The directory for incremental files: `$dest/incremental` - incremental: PathBuf, - /// The directory for fingerprints: `$dest/.fingerprint` - fingerprint: PathBuf, - /// The directory for examples: `$dest/examples` - examples: PathBuf, - /// The directory for pre-uplifted examples: `$build-dir/debug/examples` - build_examples: PathBuf, - /// The directory for rustdoc output: `$root/doc` - doc: PathBuf, - /// The directory for temporary data of integration tests and benches: `$dest/tmp` - tmp: PathBuf, - /// The lockfile for a build (`.cargo-lock`). Will be unlocked when this - /// struct is `drop`ped. - _lock: FileLock, - /// Same as `_lock` but for the build directory. - /// - /// Will be `None` when the build-dir and target-dir are the same path as we cannot - /// lock the same path twice. - _build_lock: Option, - is_new_layout: bool, + artifact_dir: ArtifactDirLayout, + build_dir: BuildDirLayout, } impl Layout { @@ -182,9 +152,10 @@ impl Layout { // For now we don't do any more finer-grained locking on the artifact // directory, so just lock the entire thing for the duration of this // compile. - let lock = dest.open_rw_exclusive_create(".cargo-lock", ws.gctx(), "build directory")?; + let artifact_dir_lock = + dest.open_rw_exclusive_create(".cargo-lock", ws.gctx(), "build directory")?; - let build_lock = if root != build_root { + let build_dir_lock = if root != build_root { Some(build_dest.open_rw_exclusive_create( ".cargo-lock", ws.gctx(), @@ -201,23 +172,112 @@ impl Layout { let artifact = deps.join("artifact"); Ok(Layout { - deps, - build: build_dest.join("build"), - artifact, - incremental: build_dest.join("incremental"), - fingerprint: build_dest.join(".fingerprint"), - examples: dest.join("examples"), - build_examples: build_dest.join("examples"), - doc: root.join("doc"), - tmp: build_root.join("tmp"), - root, - dest, - _lock: lock, - _build_lock: build_lock, - is_new_layout, + artifact_dir: ArtifactDirLayout { + dest: dest.clone(), + examples: dest.join("examples"), + doc: root.join("doc"), + timings: root.join("cargo-timings"), + _lock: artifact_dir_lock, + }, + build_dir: BuildDirLayout { + root: build_root.clone(), + deps, + build: build_dest.join("build"), + artifact, + incremental: build_dest.join("incremental"), + fingerprint: build_dest.join(".fingerprint"), + examples: build_dest.join("examples"), + tmp: build_root.join("tmp"), + _lock: build_dir_lock, + is_new_layout, + }, }) } + /// Makes sure all directories stored in the Layout exist on the filesystem. + pub fn prepare(&mut self) -> CargoResult<()> { + self.artifact_dir.prepare()?; + self.build_dir.prepare()?; + + Ok(()) + } + + pub fn artifact_dir(&self) -> &ArtifactDirLayout { + &self.artifact_dir + } + + pub fn build_dir(&self) -> &BuildDirLayout { + &self.build_dir + } +} + +pub struct ArtifactDirLayout { + /// The final artifact destination: `/debug` (or `release`). + dest: PathBuf, + /// The directory for examples + examples: PathBuf, + /// The directory for rustdoc output + doc: PathBuf, + /// The directory for --timings output + timings: PathBuf, + /// The lockfile for a build (`.cargo-lock`). Will be unlocked when this + /// struct is `drop`ped. + _lock: FileLock, +} + +impl ArtifactDirLayout { + /// Makes sure all directories stored in the Layout exist on the filesystem. + pub fn prepare(&mut self) -> CargoResult<()> { + paths::create_dir_all(&self.examples)?; + + Ok(()) + } + /// Fetch the destination path for final artifacts (`/…/target/debug`). + pub fn dest(&self) -> &Path { + &self.dest + } + /// Fetch the examples path. + pub fn examples(&self) -> &Path { + &self.examples + } + /// Fetch the doc path. + pub fn doc(&self) -> &Path { + &self.doc + } + /// Fetch the cargo-timings path. + pub fn timings(&self) -> &Path { + &self.timings + } +} + +pub struct BuildDirLayout { + /// The root directory: `/path/to/build-dir`. + /// If cross compiling: `/path/to/build-dir/$TRIPLE`. + root: PathBuf, + /// The directory with rustc artifacts + deps: PathBuf, + /// The primary directory for build files + build: PathBuf, + /// The directory for artifacts, i.e. binaries, cdylibs, staticlibs + artifact: PathBuf, + /// The directory for incremental files + incremental: PathBuf, + /// The directory for fingerprints + fingerprint: PathBuf, + /// The directory for pre-uplifted examples: `build-dir/debug/examples` + examples: PathBuf, + /// The directory for temporary data of integration tests and benches + tmp: PathBuf, + /// The lockfile for a build (`.cargo-lock`). Will be unlocked when this + /// struct is `drop`ped. + /// + /// Will be `None` when the build-dir and target-dir are the same path as we cannot + /// lock the same path twice. + _lock: Option, + is_new_layout: bool, +} + +impl BuildDirLayout { /// Makes sure all directories stored in the Layout exist on the filesystem. pub fn prepare(&mut self) -> CargoResult<()> { if !self.is_new_layout { @@ -226,16 +286,10 @@ impl Layout { } paths::create_dir_all(&self.incremental)?; paths::create_dir_all(&self.examples)?; - paths::create_dir_all(&self.build_examples)?; paths::create_dir_all(&self.build)?; Ok(()) } - - /// Fetch the destination path for final artifacts (`/…/target/debug`). - pub fn dest(&self) -> &Path { - &self.dest - } /// Fetch the deps path. pub fn deps(&self, pkg_dir: &str) -> PathBuf { if self.is_new_layout { @@ -248,22 +302,13 @@ impl Layout { pub fn legacy_deps(&self) -> &Path { &self.deps } - /// Fetch the examples path. - pub fn examples(&self) -> &Path { - &self.examples - } - /// Fetch the build examples path. - pub fn build_examples(&self) -> &Path { - &self.build_examples - } - /// Fetch the doc path. - pub fn doc(&self) -> &Path { - &self.doc - } - /// Fetch the root path (`/…/target`). pub fn root(&self) -> &Path { &self.root } + /// Fetch the build examples path. + pub fn examples(&self) -> &Path { + &self.examples + } /// Fetch the incremental path. pub fn incremental(&self) -> &Path { &self.incremental diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 48862882c05..adeae259af7 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -781,7 +781,11 @@ fn prepare_rustc(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> CargoResult } if unit.target.is_test() || unit.target.is_bench() { - let tmp = build_runner.files().layout(unit.kind).prepare_tmp()?; + let tmp = build_runner + .files() + .layout(unit.kind) + .build_dir() + .prepare_tmp()?; base.env("CARGO_TARGET_TMPDIR", tmp.display().to_string()); } diff --git a/src/cargo/core/compiler/output_depinfo.rs b/src/cargo/core/compiler/output_depinfo.rs index a62d9a0e8ac..77c9775ec5e 100644 --- a/src/cargo/core/compiler/output_depinfo.rs +++ b/src/cargo/core/compiler/output_depinfo.rs @@ -58,7 +58,7 @@ fn add_deps_for_unit( let dep_info_loc = fingerprint::dep_info_loc(build_runner, unit); if let Some(paths) = fingerprint::parse_dep_info( unit.pkg.root(), - build_runner.files().host_root(), + build_runner.files().host_build_root(), &dep_info_loc, )? { for path in paths.files.into_keys() { diff --git a/src/cargo/core/compiler/timings.rs b/src/cargo/core/compiler/timings.rs index 4f8b2b82b39..999c1305815 100644 --- a/src/cargo/core/compiler/timings.rs +++ b/src/cargo/core/compiler/timings.rs @@ -441,7 +441,7 @@ impl<'gctx> Timings<'gctx> { ) -> CargoResult<()> { let duration = self.start.elapsed().as_secs_f64(); let timestamp = self.start_str.replace(&['-', ':'][..], ""); - let timings_path = build_runner.files().host_root().join("cargo-timings"); + let timings_path = build_runner.files().timings_dir(); paths::create_dir_all(&timings_path)?; let filename = timings_path.join(format!("cargo-timing-{}.html", timestamp)); let mut f = BufWriter::new(paths::create(&filename)?); diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index 1ab8dd5e937..a70972fae1b 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -200,7 +200,7 @@ fn clean_specs( // Clean fingerprints. for (_, layout) in &layouts_with_host { - let dir = escape_glob_path(layout.legacy_fingerprint())?; + let dir = escape_glob_path(layout.build_dir().legacy_fingerprint())?; clean_ctx .rm_rf_package_glob_containing_hash(&pkg.name(), &Path::new(&dir).join(&pkg_dir))?; } @@ -209,7 +209,7 @@ fn clean_specs( if target.is_custom_build() { // Get both the build_script_build and the output directory. for (_, layout) in &layouts_with_host { - let dir = escape_glob_path(layout.build())?; + let dir = escape_glob_path(layout.build_dir().build())?; clean_ctx.rm_rf_package_glob_containing_hash( &pkg.name(), &Path::new(&dir).join(&pkg_dir), @@ -227,7 +227,7 @@ fn clean_specs( ] { for (compile_kind, layout) in &layouts { if clean_ctx.gctx.cli_unstable().build_dir_new_layout { - let dir = layout.build_unit(&pkg.name()); + let dir = layout.build_dir().build_unit(&pkg.name()); clean_ctx.rm_rf_glob(&dir)?; continue; } @@ -237,12 +237,18 @@ fn clean_specs( .info(*compile_kind) .rustc_outputs(mode, target.kind(), triple, clean_ctx.gctx)?; let (dir, uplift_dir) = match target.kind() { - TargetKind::ExampleBin | TargetKind::ExampleLib(..) => { - (layout.build_examples(), Some(layout.examples())) - } + TargetKind::ExampleBin | TargetKind::ExampleLib(..) => ( + layout.build_dir().examples(), + Some(layout.artifact_dir().examples()), + ), // Tests/benchmarks are never uplifted. - TargetKind::Test | TargetKind::Bench => (layout.legacy_deps(), None), - _ => (layout.legacy_deps(), Some(layout.dest())), + TargetKind::Test | TargetKind::Bench => { + (layout.build_dir().legacy_deps(), None) + } + _ => ( + layout.build_dir().legacy_deps(), + Some(layout.artifact_dir().dest()), + ), }; let mut dir_glob_str = escape_glob_path(dir)?; let dir_glob = Path::new(&dir_glob_str); @@ -289,7 +295,7 @@ fn clean_specs( } // TODO: what to do about build_script_build? - let dir = escape_glob_path(layout.incremental())?; + let dir = escape_glob_path(layout.build_dir().incremental())?; let incremental = Path::new(&dir).join(format!("{}-*", crate_name)); clean_ctx.rm_rf_glob(&incremental)?; }