Skip to content

Commit 2af0c91

Browse files
committed
Seperated build directory from target directory
This commits implements the seperation of the intermidate artifact directory (called "build directory") from the target directory. (see #14125)
1 parent 0de4c37 commit 2af0c91

File tree

13 files changed

+159
-96
lines changed

13 files changed

+159
-96
lines changed

src/cargo/core/compiler/build_runner/compilation_files.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> {
217217
} else if unit.target.is_custom_build() {
218218
self.build_script_dir(unit)
219219
} else if unit.target.is_example() {
220-
self.layout(unit.kind).examples().to_path_buf()
220+
self.layout(unit.kind).build_examples().to_path_buf()
221221
} else if unit.artifact.is_true() {
222222
self.artifact_dir(unit)
223223
} else {

src/cargo/core/compiler/custom_build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ fn prepare_metabuild(
11241124
let path = unit
11251125
.pkg
11261126
.manifest()
1127-
.metabuild_path(build_runner.bcx.ws.target_dir());
1127+
.metabuild_path(build_runner.bcx.ws.build_dir());
11281128
paths::create_dir_all(path.parent().unwrap())?;
11291129
paths::write_if_changed(path, &output)?;
11301130
Ok(())

src/cargo/core/compiler/fingerprint/dep_info.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ pub struct RustcDepInfo {
5151
pub enum DepInfoPathType {
5252
/// src/, e.g. src/lib.rs
5353
PackageRootRelative,
54-
/// target/debug/deps/lib...
54+
/// {build-dir}/debug/deps/lib...
5555
/// or an absolute path /.../sysroot/...
56-
TargetRootRelative,
56+
BuildRootRelative,
5757
}
5858

5959
/// Same as [`RustcDepInfo`] except avoids absolute paths as much as possible to
@@ -126,7 +126,7 @@ impl EncodedDepInfo {
126126
for _ in 0..nfiles {
127127
let ty = match read_u8(bytes)? {
128128
0 => DepInfoPathType::PackageRootRelative,
129-
1 => DepInfoPathType::TargetRootRelative,
129+
1 => DepInfoPathType::BuildRootRelative,
130130
_ => return None,
131131
};
132132
let path_bytes = read_bytes(bytes)?;
@@ -210,7 +210,7 @@ impl EncodedDepInfo {
210210
for (ty, file, checksum_info) in self.files.iter() {
211211
match ty {
212212
DepInfoPathType::PackageRootRelative => dst.push(0),
213-
DepInfoPathType::TargetRootRelative => dst.push(1),
213+
DepInfoPathType::BuildRootRelative => dst.push(1),
214214
}
215215
write_bytes(dst, paths::path2bytes(file)?);
216216
write_bool(dst, checksum_info.is_some());
@@ -292,14 +292,14 @@ pub fn translate_dep_info(
292292
cargo_dep_info: &Path,
293293
rustc_cwd: &Path,
294294
pkg_root: &Path,
295-
target_root: &Path,
295+
build_root: &Path,
296296
rustc_cmd: &ProcessBuilder,
297297
allow_package: bool,
298298
env_config: &Arc<HashMap<String, OsString>>,
299299
) -> CargoResult<()> {
300300
let depinfo = parse_rustc_dep_info(rustc_dep_info)?;
301301

302-
let target_root = crate::util::try_canonicalize(target_root)?;
302+
let build_root = crate::util::try_canonicalize(build_root)?;
303303
let pkg_root = crate::util::try_canonicalize(pkg_root)?;
304304
let mut on_disk_info = EncodedDepInfo::default();
305305
on_disk_info.env = depinfo.env;
@@ -351,8 +351,8 @@ pub fn translate_dep_info(
351351
let canon_file =
352352
crate::util::try_canonicalize(&abs_file).unwrap_or_else(|_| abs_file.clone());
353353

354-
let (ty, path) = if let Ok(stripped) = canon_file.strip_prefix(&target_root) {
355-
(DepInfoPathType::TargetRootRelative, stripped)
354+
let (ty, path) = if let Ok(stripped) = canon_file.strip_prefix(&build_root) {
355+
(DepInfoPathType::BuildRootRelative, stripped)
356356
} else if let Ok(stripped) = canon_file.strip_prefix(&pkg_root) {
357357
if !allow_package {
358358
return None;
@@ -362,7 +362,7 @@ pub fn translate_dep_info(
362362
// It's definitely not target root relative, but this is an absolute path (since it was
363363
// joined to rustc_cwd) and as such re-joining it later to the target root will have no
364364
// effect.
365-
(DepInfoPathType::TargetRootRelative, &*abs_file)
365+
(DepInfoPathType::BuildRootRelative, &*abs_file)
366366
};
367367
Some((ty, path.to_owned()))
368368
};
@@ -472,7 +472,7 @@ pub fn parse_rustc_dep_info(rustc_dep_info: &Path) -> CargoResult<RustcDepInfo>
472472
/// indicates that the crate should likely be rebuilt.
473473
pub fn parse_dep_info(
474474
pkg_root: &Path,
475-
target_root: &Path,
475+
build_root: &Path,
476476
dep_info: &Path,
477477
) -> CargoResult<Option<RustcDepInfo>> {
478478
let Ok(data) = paths::read_bytes(dep_info) else {
@@ -487,7 +487,7 @@ pub fn parse_dep_info(
487487
ret.files
488488
.extend(info.files.into_iter().map(|(ty, path, checksum_info)| {
489489
(
490-
make_absolute_path(ty, pkg_root, target_root, path),
490+
make_absolute_path(ty, pkg_root, build_root, path),
491491
checksum_info.and_then(|(file_len, checksum)| {
492492
Checksum::from_str(&checksum).ok().map(|c| (file_len, c))
493493
}),
@@ -499,13 +499,13 @@ pub fn parse_dep_info(
499499
fn make_absolute_path(
500500
ty: DepInfoPathType,
501501
pkg_root: &Path,
502-
target_root: &Path,
502+
build_root: &Path,
503503
path: PathBuf,
504504
) -> PathBuf {
505505
match ty {
506506
DepInfoPathType::PackageRootRelative => pkg_root.join(path),
507507
// N.B. path might be absolute here in which case the join will have no effect
508-
DepInfoPathType::TargetRootRelative => target_root.join(path),
508+
DepInfoPathType::BuildRootRelative => build_root.join(path),
509509
}
510510
}
511511

@@ -678,7 +678,7 @@ mod encoded_dep_info {
678678
fn gen_test(checksum: bool) {
679679
let checksum = checksum.then_some((768, "c01efc669f09508b55eced32d3c88702578a7c3e".into()));
680680
let lib_rs = (
681-
DepInfoPathType::TargetRootRelative,
681+
DepInfoPathType::BuildRootRelative,
682682
PathBuf::from("src/lib.rs"),
683683
checksum.clone(),
684684
);
@@ -691,7 +691,7 @@ mod encoded_dep_info {
691691
assert_eq!(EncodedDepInfo::parse(&data).unwrap(), depinfo);
692692

693693
let mod_rs = (
694-
DepInfoPathType::TargetRootRelative,
694+
DepInfoPathType::BuildRootRelative,
695695
PathBuf::from("src/mod.rs"),
696696
checksum.clone(),
697697
);

src/cargo/core/compiler/fingerprint/mod.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ impl LocalFingerprint {
839839
mtime_cache: &mut HashMap<PathBuf, FileTime>,
840840
checksum_cache: &mut HashMap<PathBuf, Checksum>,
841841
pkg: &Package,
842-
target_root: &Path,
842+
build_root: &Path,
843843
cargo_exe: &Path,
844844
gctx: &GlobalContext,
845845
) -> CargoResult<Option<StaleItem>> {
@@ -852,8 +852,8 @@ impl LocalFingerprint {
852852
// the `dep_info` file itself whose mtime represents the start of
853853
// rustc.
854854
LocalFingerprint::CheckDepInfo { dep_info, checksum } => {
855-
let dep_info = target_root.join(dep_info);
856-
let Some(info) = parse_dep_info(pkg_root, target_root, &dep_info)? else {
855+
let dep_info = build_root.join(dep_info);
856+
let Some(info) = parse_dep_info(pkg_root, build_root, &dep_info)? else {
857857
return Ok(Some(StaleItem::MissingFile(dep_info)));
858858
};
859859
for (key, previous) in info.env.iter() {
@@ -910,7 +910,7 @@ impl LocalFingerprint {
910910
LocalFingerprint::RerunIfChanged { output, paths } => Ok(find_stale_file(
911911
mtime_cache,
912912
checksum_cache,
913-
&target_root.join(output),
913+
&build_root.join(output),
914914
paths.iter().map(|p| (pkg_root.join(p), None)),
915915
false,
916916
)),
@@ -1153,7 +1153,7 @@ impl Fingerprint {
11531153
mtime_cache: &mut HashMap<PathBuf, FileTime>,
11541154
checksum_cache: &mut HashMap<PathBuf, Checksum>,
11551155
pkg: &Package,
1156-
target_root: &Path,
1156+
build_root: &Path,
11571157
cargo_exe: &Path,
11581158
gctx: &GlobalContext,
11591159
) -> CargoResult<()> {
@@ -1261,7 +1261,7 @@ impl Fingerprint {
12611261
mtime_cache,
12621262
checksum_cache,
12631263
pkg,
1264-
target_root,
1264+
build_root,
12651265
cargo_exe,
12661266
gctx,
12671267
)? {
@@ -1449,13 +1449,13 @@ fn calculate(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResult
14491449

14501450
// After we built the initial `Fingerprint` be sure to update the
14511451
// `fs_status` field of it.
1452-
let target_root = target_root(build_runner);
1452+
let build_root = build_root(build_runner);
14531453
let cargo_exe = build_runner.bcx.gctx.cargo_exe()?;
14541454
fingerprint.check_filesystem(
14551455
&mut build_runner.mtime_cache,
14561456
&mut build_runner.checksum_cache,
14571457
&unit.pkg,
1458-
&target_root,
1458+
&build_root,
14591459
cargo_exe,
14601460
build_runner.bcx.gctx,
14611461
)?;
@@ -1493,7 +1493,7 @@ fn calculate_normal(
14931493
};
14941494

14951495
// Afterwards calculate our own fingerprint information.
1496-
let target_root = target_root(build_runner);
1496+
let build_root = build_root(build_runner);
14971497
let local = if unit.mode.is_doc() || unit.mode.is_doc_scrape() {
14981498
// rustdoc does not have dep-info files.
14991499
let fingerprint = pkg_fingerprint(build_runner.bcx, &unit.pkg).with_context(|| {
@@ -1505,7 +1505,7 @@ fn calculate_normal(
15051505
vec![LocalFingerprint::Precalculated(fingerprint)]
15061506
} else {
15071507
let dep_info = dep_info_loc(build_runner, unit);
1508-
let dep_info = dep_info.strip_prefix(&target_root).unwrap().to_path_buf();
1508+
let dep_info = dep_info.strip_prefix(&build_root).unwrap().to_path_buf();
15091509
vec![LocalFingerprint::CheckDepInfo {
15101510
dep_info,
15111511
checksum: build_runner.bcx.gctx.cli_unstable().checksum_freshness,
@@ -1714,7 +1714,7 @@ fn build_script_local_fingerprints(
17141714
// longstanding bug, in Cargo. Recent refactorings just made it painfully
17151715
// obvious.
17161716
let pkg_root = unit.pkg.root().to_path_buf();
1717-
let target_dir = target_root(build_runner);
1717+
let build_dir = build_root(build_runner);
17181718
let env_config = Arc::clone(build_runner.bcx.gctx.env_config()?);
17191719
let calculate =
17201720
move |deps: &BuildDeps, pkg_fingerprint: Option<&dyn Fn() -> CargoResult<String>>| {
@@ -1747,7 +1747,7 @@ fn build_script_local_fingerprints(
17471747
// them all here.
17481748
Ok(Some(local_fingerprints_deps(
17491749
deps,
1750-
&target_dir,
1750+
&build_dir,
17511751
&pkg_root,
17521752
&env_config,
17531753
)))
@@ -1783,7 +1783,7 @@ fn build_script_override_fingerprint(
17831783
/// [`RunCustomBuild`]: crate::core::compiler::CompileMode::RunCustomBuild
17841784
fn local_fingerprints_deps(
17851785
deps: &BuildDeps,
1786-
target_root: &Path,
1786+
build_root: &Path,
17871787
pkg_root: &Path,
17881788
env_config: &Arc<HashMap<String, OsString>>,
17891789
) -> Vec<LocalFingerprint> {
@@ -1796,7 +1796,7 @@ fn local_fingerprints_deps(
17961796
// absolute prefixes from them.
17971797
let output = deps
17981798
.build_script_output
1799-
.strip_prefix(target_root)
1799+
.strip_prefix(build_root)
18001800
.unwrap()
18011801
.to_path_buf();
18021802
let paths = deps
@@ -1854,10 +1854,10 @@ pub fn dep_info_loc(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> Path
18541854
build_runner.files().fingerprint_file_path(unit, "dep-")
18551855
}
18561856

1857-
/// Returns an absolute path that target directory.
1857+
/// Returns an absolute path that build directory.
18581858
/// All paths are rewritten to be relative to this.
1859-
fn target_root(build_runner: &BuildRunner<'_, '_>) -> PathBuf {
1860-
build_runner.bcx.ws.target_dir().into_path_unlocked()
1859+
fn build_root(build_runner: &BuildRunner<'_, '_>) -> PathBuf {
1860+
build_runner.bcx.ws.build_dir().into_path_unlocked()
18611861
}
18621862

18631863
/// Reads the value from the old fingerprint hash file and compare.

src/cargo/core/compiler/layout.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,20 @@ pub struct Layout {
128128
fingerprint: PathBuf,
129129
/// The directory for examples: `$dest/examples`
130130
examples: PathBuf,
131+
/// The directory for pre-uplifted examples: `$build-dir/debug/examples`
132+
build_examples: PathBuf,
131133
/// The directory for rustdoc output: `$root/doc`
132134
doc: PathBuf,
133135
/// The directory for temporary data of integration tests and benches: `$dest/tmp`
134136
tmp: PathBuf,
135137
/// The lockfile for a build (`.cargo-lock`). Will be unlocked when this
136138
/// struct is `drop`ped.
137139
_lock: FileLock,
140+
/// Same as `_lock` but for the build directory.
141+
///
142+
/// Will be `None` when the build-dir and target-dir are the same path as we cannot
143+
/// lock the same path twice.
144+
_build_lock: Option<FileLock>,
138145
}
139146

140147
impl Layout {
@@ -150,15 +157,22 @@ impl Layout {
150157
dest: &str,
151158
) -> CargoResult<Layout> {
152159
let mut root = ws.target_dir();
160+
let mut build_root = ws.build_dir();
153161
if let Some(target) = target {
154162
root.push(target.short_name());
163+
build_root.push(target.short_name());
155164
}
165+
let build_dest = build_root.join(dest);
156166
let dest = root.join(dest);
157167
// If the root directory doesn't already exist go ahead and create it
158168
// here. Use this opportunity to exclude it from backups as well if the
159169
// system supports it since this is a freshly created folder.
160170
//
161171
paths::create_dir_all_excluded_from_backups_atomic(root.as_path_unlocked())?;
172+
if root != build_root {
173+
paths::create_dir_all_excluded_from_backups_atomic(build_root.as_path_unlocked())?;
174+
}
175+
162176
// Now that the excluded from backups target root is created we can create the
163177
// actual destination (sub)subdirectory.
164178
paths::create_dir_all(dest.as_path_unlocked())?;
@@ -167,23 +181,37 @@ impl Layout {
167181
// directory, so just lock the entire thing for the duration of this
168182
// compile.
169183
let lock = dest.open_rw_exclusive_create(".cargo-lock", ws.gctx(), "build directory")?;
184+
185+
let build_lock = if root != build_root {
186+
Some(build_dest.open_rw_exclusive_create(
187+
".cargo-lock",
188+
ws.gctx(),
189+
"build directory",
190+
)?)
191+
} else {
192+
None
193+
};
170194
let root = root.into_path_unlocked();
195+
let build_root = build_root.into_path_unlocked();
171196
let dest = dest.into_path_unlocked();
172-
let deps = dest.join("deps");
197+
let build_dest = build_dest.as_path_unlocked();
198+
let deps = build_dest.join("deps");
173199
let artifact = deps.join("artifact");
174200

175201
Ok(Layout {
176202
deps,
177-
build: dest.join("build"),
203+
build: build_dest.join("build"),
178204
artifact,
179-
incremental: dest.join("incremental"),
180-
fingerprint: dest.join(".fingerprint"),
205+
incremental: build_dest.join("incremental"),
206+
fingerprint: build_dest.join(".fingerprint"),
181207
examples: dest.join("examples"),
208+
build_examples: build_dest.join("examples"),
182209
doc: root.join("doc"),
183-
tmp: root.join("tmp"),
210+
tmp: build_root.join("tmp"),
184211
root,
185212
dest,
186213
_lock: lock,
214+
_build_lock: build_lock,
187215
})
188216
}
189217

@@ -193,6 +221,7 @@ impl Layout {
193221
paths::create_dir_all(&self.incremental)?;
194222
paths::create_dir_all(&self.fingerprint)?;
195223
paths::create_dir_all(&self.examples)?;
224+
paths::create_dir_all(&self.build_examples)?;
196225
paths::create_dir_all(&self.build)?;
197226

198227
Ok(())
@@ -210,6 +239,10 @@ impl Layout {
210239
pub fn examples(&self) -> &Path {
211240
&self.examples
212241
}
242+
/// Fetch the build examples path.
243+
pub fn build_examples(&self) -> &Path {
244+
&self.build_examples
245+
}
213246
/// Fetch the doc path.
214247
pub fn doc(&self) -> &Path {
215248
&self.doc

0 commit comments

Comments
 (0)