Skip to content

Commit c849440

Browse files
committed
feat(build-dir): Reorganize build-dir layout
1 parent 8603e30 commit c849440

File tree

6 files changed

+414
-240
lines changed

6 files changed

+414
-240
lines changed

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

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -230,17 +230,25 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> {
230230
self.export_dir.clone()
231231
}
232232

233-
/// Directory name to use for a package in the form `NAME-HASH`.
233+
/// Directory name to use for a package in the form `{NAME}{SEPERATOR}{HASH}`.
234+
///
235+
/// The seperator will usually be `/` making nested hashed directories, but will sometimes be
236+
/// `-` for backwards compatiblity (artifact directory)
234237
///
235238
/// Note that some units may share the same directory, so care should be
236239
/// taken in those cases!
237-
fn pkg_dir(&self, unit: &Unit) -> String {
240+
fn pkg_dir(&self, unit: &Unit, seperator: &str) -> String {
241+
let seperator = match self.ws.gctx().cli_unstable().build_dir_new_layout {
242+
true => seperator,
243+
false => "-",
244+
};
245+
238246
let name = unit.pkg.package_id().name();
239247
let meta = self.metas[unit];
240248
if let Some(c_extra_filename) = meta.c_extra_filename() {
241-
format!("{}-{}", name, c_extra_filename)
249+
format!("{}{}{}", name, seperator, c_extra_filename)
242250
} else {
243-
format!("{}-{}", name, self.target_short_hash(unit))
251+
format!("{}{}{}", name, seperator, self.target_short_hash(unit))
244252
}
245253
}
246254

@@ -256,20 +264,20 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> {
256264

257265
/// Returns the host `deps` directory path.
258266
pub fn host_deps(&self, unit: &Unit) -> PathBuf {
259-
let dir = self.pkg_dir(unit);
267+
let dir = self.pkg_dir(unit, "/");
260268
self.host.deps(&dir)
261269
}
262270

263271
/// Returns the directories where Rust crate dependencies are found for the
264272
/// specified unit.
265273
pub fn deps_dir(&self, unit: &Unit) -> PathBuf {
266-
let dir = self.pkg_dir(unit);
274+
let dir = self.pkg_dir(unit, "/");
267275
self.layout(unit.kind).deps(&dir)
268276
}
269277

270278
/// Directory where the fingerprint for the given unit should go.
271279
pub fn fingerprint_dir(&self, unit: &Unit) -> PathBuf {
272-
let dir = self.pkg_dir(unit);
280+
let dir = self.pkg_dir(unit, "/");
273281
self.layout(unit.kind).fingerprint(&dir)
274282
}
275283

@@ -309,7 +317,7 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> {
309317
assert!(unit.target.is_custom_build());
310318
assert!(!unit.mode.is_run_custom_build());
311319
assert!(self.metas.contains_key(unit));
312-
let dir = self.pkg_dir(unit);
320+
let dir = self.pkg_dir(unit, "/");
313321
self.layout(CompileKind::Host).build_script(&dir)
314322
}
315323

@@ -318,7 +326,7 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> {
318326
fn artifact_dir(&self, unit: &Unit) -> PathBuf {
319327
assert!(self.metas.contains_key(unit));
320328
assert!(unit.artifact.is_true());
321-
let dir = self.pkg_dir(unit);
329+
let dir = self.pkg_dir(unit, "-");
322330
let kind = match unit.target.kind() {
323331
TargetKind::Bin => "bin",
324332
TargetKind::Lib(lib_kinds) => match lib_kinds.as_slice() {
@@ -343,8 +351,8 @@ impl<'a, 'gctx: 'a> CompilationFiles<'a, 'gctx> {
343351
pub fn build_script_run_dir(&self, unit: &Unit) -> PathBuf {
344352
assert!(unit.target.is_custom_build());
345353
assert!(unit.mode.is_run_custom_build());
346-
let dir = self.pkg_dir(unit);
347-
self.layout(unit.kind).build().join(dir)
354+
let dir = self.pkg_dir(unit, "/");
355+
self.layout(unit.kind).build_script_execution(&dir)
348356
}
349357

350358
/// Returns the "`OUT_DIR`" directory for running a build script.

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ use std::sync::{Arc, Mutex};
66

77
use crate::core::PackageId;
88
use crate::core::compiler::compilation::{self, UnitOutput};
9-
use crate::core::compiler::{self, Unit, artifact};
9+
use crate::core::compiler::{self, CompileTarget, Unit, artifact};
1010
use crate::util::cache_lock::CacheLockMode;
1111
use crate::util::errors::CargoResult;
1212
use anyhow::{Context as _, bail};
13+
use cargo_util::paths;
1314
use filetime::FileTime;
1415
use itertools::Itertools;
1516
use jobserver::Client;
@@ -358,11 +359,18 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
358359
#[tracing::instrument(skip_all)]
359360
pub fn prepare_units(&mut self) -> CargoResult<()> {
360361
let dest = self.bcx.profiles.get_dir_name();
361-
let host_layout = Layout::new(self.bcx.ws, None, &dest)?;
362+
let host = &self.compilation.host;
363+
let host_target = CompileTarget::new(&host)?;
364+
let host_layout = if self.bcx.gctx.cli_unstable().build_dir_new_layout {
365+
Layout::new(self.bcx.ws, Some(host_target), &dest, true)?
366+
} else {
367+
Layout::new(self.bcx.ws, None, &dest, true)?
368+
};
362369
let mut targets = HashMap::new();
363370
for kind in self.bcx.all_kinds.iter() {
364371
if let CompileKind::Target(target) = *kind {
365-
let layout = Layout::new(self.bcx.ws, Some(target), &dest)?;
372+
let is_host = target == host_target;
373+
let layout = Layout::new(self.bcx.ws, Some(target), &dest, is_host)?;
366374
targets.insert(target, layout);
367375
}
368376
}
@@ -401,9 +409,17 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
401409
self.compilation
402410
.root_output
403411
.insert(kind, layout.dest().to_path_buf());
404-
self.compilation
405-
.deps_output
406-
.insert(kind, layout.legacy_deps().to_path_buf());
412+
if self.bcx.gctx.cli_unstable().build_dir_new_layout {
413+
for (unit, _) in self.bcx.unit_graph.iter() {
414+
let dep_dir = self.files().deps_dir(unit);
415+
paths::create_dir_all(&dep_dir)?;
416+
self.compilation.deps_output.insert(kind, dep_dir);
417+
}
418+
} else {
419+
self.compilation
420+
.deps_output
421+
.insert(kind, layout.legacy_deps().to_path_buf());
422+
}
407423
}
408424
Ok(())
409425
}

src/cargo/core/compiler/layout.rs

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ pub struct Layout {
142142
/// Will be `None` when the build-dir and target-dir are the same path as we cannot
143143
/// lock the same path twice.
144144
_build_lock: Option<FileLock>,
145+
is_new_layout: bool,
145146
}
146147

147148
impl Layout {
@@ -155,12 +156,23 @@ impl Layout {
155156
ws: &Workspace<'_>,
156157
target: Option<CompileTarget>,
157158
dest: &str,
159+
is_host_layout: bool,
158160
) -> CargoResult<Layout> {
161+
let is_new_layout = ws.gctx().cli_unstable().build_dir_new_layout;
159162
let mut root = ws.target_dir();
160163
let mut build_root = ws.build_dir();
161-
if let Some(target) = target {
162-
root.push(target.short_name());
163-
build_root.push(target.short_name());
164+
if is_new_layout {
165+
assert!(target.is_some());
166+
let short_name = target.as_ref().unwrap().short_name();
167+
if !is_host_layout {
168+
root.push(short_name);
169+
}
170+
build_root.push(short_name);
171+
} else {
172+
if let Some(target) = target {
173+
root.push(target.short_name());
174+
build_root.push(target.short_name());
175+
}
164176
}
165177
let build_dest = build_root.join(dest);
166178
let dest = root.join(dest);
@@ -212,14 +224,17 @@ impl Layout {
212224
dest,
213225
_lock: lock,
214226
_build_lock: build_lock,
227+
is_new_layout,
215228
})
216229
}
217230

218231
/// Makes sure all directories stored in the Layout exist on the filesystem.
219232
pub fn prepare(&mut self) -> CargoResult<()> {
220-
paths::create_dir_all(&self.deps)?;
233+
if !self.is_new_layout {
234+
paths::create_dir_all(&self.deps)?;
235+
paths::create_dir_all(&self.fingerprint)?;
236+
}
221237
paths::create_dir_all(&self.incremental)?;
222-
paths::create_dir_all(&self.fingerprint)?;
223238
paths::create_dir_all(&self.examples)?;
224239
paths::create_dir_all(&self.build_examples)?;
225240
paths::create_dir_all(&self.build)?;
@@ -232,8 +247,12 @@ impl Layout {
232247
&self.dest
233248
}
234249
/// Fetch the deps path.
235-
pub fn deps(&self, _pkg_dir: &str) -> PathBuf {
236-
self.deps.clone()
250+
pub fn deps(&self, pkg_dir: &str) -> PathBuf {
251+
if self.is_new_layout {
252+
self.build_unit(pkg_dir).join("deps")
253+
} else {
254+
self.deps.clone()
255+
}
237256
}
238257
/// Fetch the deps path. (old layout)
239258
pub fn legacy_deps(&self) -> &Path {
@@ -261,7 +280,11 @@ impl Layout {
261280
}
262281
/// Fetch the fingerprint path.
263282
pub fn fingerprint(&self, pkg_dir: &str) -> PathBuf {
264-
self.fingerprint.join(pkg_dir)
283+
if self.is_new_layout {
284+
self.build_unit(pkg_dir).join("fingerprint")
285+
} else {
286+
self.fingerprint.join(pkg_dir)
287+
}
265288
}
266289
/// Fetch the fingerprint path. (old layout)
267290
pub fn legacy_fingerprint(&self) -> &Path {
@@ -273,16 +296,28 @@ impl Layout {
273296
}
274297
/// Fetch the build script path.
275298
pub fn build_script(&self, pkg_dir: &str) -> PathBuf {
276-
self.build().join(pkg_dir)
299+
if self.is_new_layout {
300+
self.build_unit(pkg_dir).join("build-script")
301+
} else {
302+
self.build().join(pkg_dir)
303+
}
277304
}
278305
/// Fetch the build script execution path.
279306
pub fn build_script_execution(&self, pkg_dir: &str) -> PathBuf {
280-
self.build().join(pkg_dir)
307+
if self.is_new_layout {
308+
self.build_unit(pkg_dir).join("build-script-execution")
309+
} else {
310+
self.build().join(pkg_dir)
311+
}
281312
}
282313
/// Fetch the artifact path.
283314
pub fn artifact(&self) -> &Path {
284315
&self.artifact
285316
}
317+
/// Fetch the build unit path
318+
pub fn build_unit(&self, pkg_dir: &str) -> PathBuf {
319+
self.build().join(pkg_dir)
320+
}
286321
/// Create and return the tmp path.
287322
pub fn prepare_tmp(&self) -> CargoResult<&Path> {
288323
paths::create_dir_all(&self.tmp)?;

src/cargo/core/compiler/mod.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub mod unit_dependencies;
5656
pub mod unit_graph;
5757

5858
use std::borrow::Cow;
59-
use std::collections::{HashMap, HashSet};
59+
use std::collections::{BTreeMap, HashMap, HashSet};
6060
use std::env;
6161
use std::ffi::{OsStr, OsString};
6262
use std::fmt::Display;
@@ -69,6 +69,7 @@ use std::sync::{Arc, LazyLock};
6969
use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet};
7070
use anyhow::{Context as _, Error};
7171
use cargo_platform::{Cfg, Platform};
72+
use itertools::Itertools;
7273
use lazycell::LazyCell;
7374
use regex::Regex;
7475
use tracing::{debug, instrument, trace};
@@ -1664,18 +1665,35 @@ fn build_deps_args(
16641665
unit: &Unit,
16651666
) -> CargoResult<()> {
16661667
let bcx = build_runner.bcx;
1667-
cmd.arg("-L").arg(&{
1668-
let mut deps = OsString::from("dependency=");
1669-
deps.push(build_runner.files().deps_dir(unit));
1670-
deps
1671-
});
1668+
if build_runner.bcx.gctx.cli_unstable().build_dir_new_layout {
1669+
let mut map = BTreeMap::new();
1670+
1671+
// Recursively add all depenendency args to rustc process
1672+
add_dep_arg(&mut map, build_runner, unit);
1673+
1674+
let paths = map.into_iter().map(|(_, path)| path).sorted_unstable();
1675+
1676+
for path in paths {
1677+
cmd.arg("-L").arg(&{
1678+
let mut deps = OsString::from("dependency=");
1679+
deps.push(path);
1680+
deps
1681+
});
1682+
}
1683+
} else {
1684+
cmd.arg("-L").arg(&{
1685+
let mut deps = OsString::from("dependency=");
1686+
deps.push(build_runner.files().deps_dir(unit));
1687+
deps
1688+
});
1689+
}
16721690

16731691
// Be sure that the host path is also listed. This'll ensure that proc macro
16741692
// dependencies are correctly found (for reexported macros).
16751693
if !unit.kind.is_host() {
16761694
cmd.arg("-L").arg(&{
16771695
let mut deps = OsString::from("dependency=");
1678-
deps.push(build_runner.files().host_deps(&unit));
1696+
deps.push(build_runner.files().host_deps(unit));
16791697
deps
16801698
});
16811699
}
@@ -1751,6 +1769,21 @@ fn build_deps_args(
17511769
Ok(())
17521770
}
17531771

1772+
fn add_dep_arg<'a, 'b: 'a>(
1773+
map: &mut BTreeMap<&'a Unit, PathBuf>,
1774+
build_runner: &'b BuildRunner<'b, '_>,
1775+
unit: &'a Unit,
1776+
) {
1777+
if map.contains_key(&unit) {
1778+
return;
1779+
}
1780+
map.insert(&unit, build_runner.files().deps_dir(&unit));
1781+
1782+
for dep in build_runner.unit_deps(unit) {
1783+
add_dep_arg(map, build_runner, &dep.unit);
1784+
}
1785+
}
1786+
17541787
/// Adds extra rustc flags and environment variables collected from the output
17551788
/// of a build-script to the command to execute, include custom environment
17561789
/// variables and `cfg`.

src/cargo/ops/cargo_clean.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::core::compiler::{CompileKind, CompileMode, Layout, RustcTargetData};
1+
use crate::core::compiler::{CompileKind, CompileMode, CompileTarget, Layout, RustcTargetData};
22
use crate::core::profiles::Profiles;
33
use crate::core::{PackageIdSpec, PackageIdSpecQuery, TargetKind, Workspace};
44
use crate::ops;
@@ -116,15 +116,22 @@ fn clean_specs(
116116
let target_data = RustcTargetData::new(ws, &requested_kinds)?;
117117
let (pkg_set, resolve) = ops::resolve_ws(ws, dry_run)?;
118118
let prof_dir_name = profiles.get_dir_name();
119-
let host_layout = Layout::new(ws, None, &prof_dir_name)?;
119+
let host_target = CompileTarget::new(target_data.short_name(&CompileKind::Host))?;
120+
let host_layout = if clean_ctx.gctx.cli_unstable().build_dir_new_layout {
121+
Layout::new(ws, Some(host_target), &prof_dir_name, true)?
122+
} else {
123+
Layout::new(ws, None, &prof_dir_name, true)?
124+
};
120125
// Convert requested kinds to a Vec of layouts.
121126
let target_layouts: Vec<(CompileKind, Layout)> = requested_kinds
122127
.into_iter()
123128
.filter_map(|kind| match kind {
124-
CompileKind::Target(target) => match Layout::new(ws, Some(target), &prof_dir_name) {
125-
Ok(layout) => Some(Ok((kind, layout))),
126-
Err(e) => Some(Err(e)),
127-
},
129+
CompileKind::Target(target) => {
130+
match Layout::new(ws, Some(target), &prof_dir_name, false) {
131+
Ok(layout) => Some(Ok((kind, layout))),
132+
Err(e) => Some(Err(e)),
133+
}
134+
}
128135
CompileKind::Host => None,
129136
})
130137
.collect::<CargoResult<_>>()?;
@@ -228,6 +235,10 @@ fn clean_specs(
228235
for (compile_kind, layout) in &layouts {
229236
let triple = target_data.short_name(compile_kind);
230237

238+
if clean_ctx.gctx.cli_unstable().build_dir_new_layout {
239+
let dir = layout.build_unit(&pkg.name());
240+
clean_ctx.rm_rf_glob(&dir)?;
241+
}
231242
let (file_types, _unsupported) = target_data
232243
.info(*compile_kind)
233244
.rustc_outputs(mode, target.kind(), triple, clean_ctx.gctx)?;

0 commit comments

Comments
 (0)