Skip to content

Commit

Permalink
Seperated build directory from target directory
Browse files Browse the repository at this point in the history
This commits implements the seperation of the intermidate artifact
directory (called "build directory") from the target directory. (see rust-lang#14125)
  • Loading branch information
ranger-ross committed Feb 2, 2025
1 parent df6c978 commit b915b95
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 56 deletions.
2 changes: 1 addition & 1 deletion src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ fn prepare_metabuild(
let path = unit
.pkg
.manifest()
.metabuild_path(build_runner.bcx.ws.target_dir());
.metabuild_path(build_runner.bcx.ws.build_dir());
paths::create_dir_all(path.parent().unwrap())?;
paths::write_if_changed(path, &output)?;
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/core/compiler/fingerprint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1857,7 +1857,7 @@ pub fn dep_info_loc(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> Path
/// Returns an absolute path that target directory.
/// All paths are rewritten to be relative to this.
fn target_root(build_runner: &BuildRunner<'_, '_>) -> PathBuf {
build_runner.bcx.ws.target_dir().into_path_unlocked()
build_runner.bcx.ws.build_dir().into_path_unlocked()
}

/// Reads the value from the old fingerprint hash file and compare.
Expand Down
4 changes: 2 additions & 2 deletions src/cargo/core/compiler/future_incompat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl OnDiskReports {
}
let on_disk = serde_json::to_vec(&self).unwrap();
if let Err(e) = ws
.target_dir()
.build_dir()
.open_rw_exclusive_create(
FUTURE_INCOMPAT_FILE,
ws.gctx(),
Expand All @@ -191,7 +191,7 @@ impl OnDiskReports {

/// Loads the on-disk reports.
pub fn load(ws: &Workspace<'_>) -> CargoResult<OnDiskReports> {
let report_file = match ws.target_dir().open_ro_shared(
let report_file = match ws.build_dir().open_ro_shared(
FUTURE_INCOMPAT_FILE,
ws.gctx(),
"Future incompatible report",
Expand Down
35 changes: 30 additions & 5 deletions src/cargo/core/compiler/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ pub struct Layout {
/// 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<FileLock>,
}

impl Layout {
Expand All @@ -150,15 +155,22 @@ impl Layout {
dest: &str,
) -> CargoResult<Layout> {
let mut root = ws.target_dir();
let mut build_root = ws.build_dir();
if let Some(target) = target {
root.push(target.short_name());
build_root.push(target.short_name());
}
let build_dest = build_root.join(dest);
let dest = root.join(dest);
// If the root directory doesn't already exist go ahead and create it
// here. Use this opportunity to exclude it from backups as well if the
// system supports it since this is a freshly created folder.
//
paths::create_dir_all_excluded_from_backups_atomic(root.as_path_unlocked())?;
if root != build_root {
paths::create_dir_all_excluded_from_backups_atomic(build_root.as_path_unlocked())?;
}

// Now that the excluded from backups target root is created we can create the
// actual destination (sub)subdirectory.
paths::create_dir_all(dest.as_path_unlocked())?;
Expand All @@ -167,23 +179,36 @@ impl Layout {
// 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 build_lock = if root != build_root {
Some(build_dest.open_rw_exclusive_create(
".cargo-lock",
ws.gctx(),
"build directory",
)?)
} else {
None
};
let root = root.into_path_unlocked();
let build_root = build_root.into_path_unlocked();
let dest = dest.into_path_unlocked();
let deps = dest.join("deps");
let build_dest = build_dest.as_path_unlocked();
let deps = build_dest.join("deps");
let artifact = deps.join("artifact");

Ok(Layout {
deps,
build: dest.join("build"),
build: build_dest.join("build"),
artifact,
incremental: dest.join("incremental"),
fingerprint: dest.join(".fingerprint"),
incremental: build_dest.join("incremental"),
fingerprint: build_dest.join(".fingerprint"),
examples: dest.join("examples"),
doc: root.join("doc"),
tmp: root.join("tmp"),
tmp: build_root.join("tmp"),
root,
dest,
_lock: lock,
_build_lock: build_lock,
})
}

Expand Down
4 changes: 2 additions & 2 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ fn rustc(
let exec = exec.clone();

let root_output = build_runner.files().host_dest().to_path_buf();
let target_dir = build_runner.bcx.ws.target_dir().into_path_unlocked();
let target_dir = build_runner.bcx.ws.build_dir().into_path_unlocked();
let pkg_root = unit.pkg.root().to_path_buf();
let cwd = rustc
.get_cwd()
Expand Down Expand Up @@ -555,7 +555,7 @@ fn link_targets(
let path = unit
.pkg
.manifest()
.metabuild_path(build_runner.bcx.ws.target_dir());
.metabuild_path(build_runner.bcx.ws.build_dir());
target.set_src_path(TargetSourcePath::Path(path));
}

Expand Down
4 changes: 1 addition & 3 deletions src/cargo/core/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,9 +418,7 @@ impl<'gctx> Workspace<'gctx> {
if !self.gctx().cli_unstable().build_dir {
return self.target_dir();
}
self.build_dir
.clone()
.unwrap_or_else(|| self.default_target_dir())
self.build_dir.clone().unwrap_or_else(|| self.target_dir())
}

fn default_target_dir(&self) -> Filesystem {
Expand Down
12 changes: 11 additions & 1 deletion src/cargo/ops/cargo_clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub struct CleanContext<'gctx> {
/// Cleans various caches.
pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
let mut target_dir = ws.target_dir();
let mut build_dir = ws.build_dir();
let gctx = opts.gctx;
let mut clean_ctx = CleanContext::new(gctx);
clean_ctx.dry_run = opts.dry_run;
Expand All @@ -67,6 +68,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
// that profile.
let dir_name = profiles.get_dir_name();
target_dir = target_dir.join(dir_name);
build_dir = build_dir.join(dir_name);
}

// If we have a spec, then we need to delete some packages, otherwise, just
Expand All @@ -75,7 +77,15 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
// Note that we don't bother grabbing a lock here as we're just going to
// blow it all away anyway.
if opts.spec.is_empty() {
clean_ctx.remove_paths(&[target_dir.into_path_unlocked()])?;
let paths: &[PathBuf] = if gctx.cli_unstable().build_dir && build_dir != target_dir {
&[
target_dir.into_path_unlocked(),
build_dir.into_path_unlocked(),
]
} else {
&[target_dir.into_path_unlocked()]
};
clean_ctx.remove_paths(paths)?;
} else {
clean_specs(
&mut clean_ctx,
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_package/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ fn do_package<'a>(
};

let mut local_reg = if ws.gctx().cli_unstable().package_workspace {
let reg_dir = ws.target_dir().join("package").join("tmp-registry");
let reg_dir = ws.build_dir().join("package").join("tmp-registry");
sid.map(|sid| TmpRegistry::new(ws.gctx(), reg_dir, sid))
.transpose()?
} else {
Expand Down
20 changes: 16 additions & 4 deletions src/cargo/ops/cargo_package/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,14 @@ pub fn run_verify(

tar.file().seek(SeekFrom::Start(0))?;
let f = GzDecoder::new(tar.file());
let dst = tar
.parent()
.join(&format!("{}-{}", pkg.name(), pkg.version()));
let dst = if gctx.cli_unstable().build_dir {
ws.build_dir()
.as_path_unlocked()
.join(&format!("package/{}-{}", pkg.name(), pkg.version()))
} else {
tar.parent()
.join(&format!("{}-{}", pkg.name(), pkg.version()))
};
if dst.exists() {
paths::remove_dir_all(&dst)?;
}
Expand All @@ -63,7 +68,14 @@ pub fn run_verify(
let mut src = PathSource::new(&dst, id, ws.gctx());
let new_pkg = src.root_package()?;
let pkg_fingerprint = hash_all(&dst)?;
let mut ws = Workspace::ephemeral(new_pkg, gctx, None, true)?;

let target_dir = if gctx.cli_unstable().build_dir {
Some(ws.build_dir())
} else {
None
};

let mut ws = Workspace::ephemeral(new_pkg, gctx, target_dir, true)?;
if let Some(local_reg) = local_reg {
ws.add_local_overlay(
local_reg.upstream,
Expand Down
7 changes: 2 additions & 5 deletions src/cargo/util/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,11 +421,8 @@ impl GlobalContext {

/// Gets the path to the `rustc` executable.
pub fn load_global_rustc(&self, ws: Option<&Workspace<'_>>) -> CargoResult<Rustc> {
let cache_location = ws.map(|ws| {
ws.target_dir()
.join(".rustc_info.json")
.into_path_unlocked()
});
let cache_location =
ws.map(|ws| ws.build_dir().join(".rustc_info.json").into_path_unlocked());
let wrapper = self.maybe_get_tool("rustc_wrapper", &self.build_config()?.rustc_wrapper);
let rustc_workspace_wrapper = self.maybe_get_tool(
"rustc_workspace_wrapper",
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/util/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ pub fn print_available_tests(ws: &Workspace<'_>, options: &CompileOptions) -> Ca
pub fn path_args(ws: &Workspace<'_>, unit: &Unit) -> (PathBuf, PathBuf) {
let src = match unit.target.src_path() {
TargetSourcePath::Path(path) => path.to_path_buf(),
TargetSourcePath::Metabuild => unit.pkg.manifest().metabuild_path(ws.target_dir()),
TargetSourcePath::Metabuild => unit.pkg.manifest().metabuild_path(ws.build_dir()),
};
assert!(src.is_absolute());
if unit.pkg.package_id().source_id().is_path() {
Expand Down
Loading

0 comments on commit b915b95

Please sign in to comment.