Skip to content

Commit 8282fa2

Browse files
committed
Add support for CARGO_TARGET_DIR_PREFIX
This change adds support for a new environment variable, CARGO_TARGET_DIR_PREFIX, to cargo. This variable, when set, is treated as a prefix to the target directory. This change addresses rust-lang#5544. TODO: Definitely not finished. This patch needs more tests and may need additional config.toml support (?).
1 parent a1a4ad3 commit 8282fa2

File tree

4 files changed

+82
-0
lines changed

4 files changed

+82
-0
lines changed

src/cargo/util/config.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use core::{CliUnstable, Shell, SourceId, Workspace};
2828
use ops;
2929
use url::Url;
3030
use util::errors::{internal, CargoResult, CargoResultExt};
31+
use util::important_paths::find_root_manifest_for_wd;
3132
use util::paths;
3233
use util::toml as cargo_toml;
3334
use util::Filesystem;
@@ -290,6 +291,25 @@ impl Config {
290291
Ok(Some(dir.clone()))
291292
} else if let Some(dir) = env::var_os("CARGO_TARGET_DIR") {
292293
Ok(Some(Filesystem::new(self.cwd.join(dir))))
294+
} else if let Some(dir) = env::var_os("CARGO_TARGET_DIR_PREFIX") {
295+
let prefix = Path::new(&dir);
296+
if !prefix.is_absolute() {
297+
bail!("CARGO_TARGET_DIR_PREFIX must describe an absolute path");
298+
}
299+
// We need to take into consideration that `self.cwd` may
300+
// point to a directory other than the one containing
301+
// Cargo.toml. We definitely want to stay relative to the
302+
// latter.
303+
let mut cwd = find_root_manifest_for_wd(&self.cwd)?;
304+
let result = cwd.pop();
305+
assert!(result);
306+
307+
match cwd.strip_prefix("/") {
308+
Ok(cwd) => Ok(Some(Filesystem::new(prefix.join(&cwd).join("target")))),
309+
// FIXME: This logic is probably not safe on Windows. Not sure how
310+
// to make a path relative there.
311+
Err(_) => bail!("Current directory must be an absolute path"),
312+
}
293313
} else if let Some(val) = self.get_path("build.target-dir")? {
294314
let val = self.cwd.join(val.val);
295315
Ok(Some(Filesystem::new(val)))

src/doc/src/reference/environment-variables.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ system:
1313
checkouts of crates. By default these are stored under `$HOME/.cargo`, but
1414
this variable overrides the location of this directory. Once a crate is cached
1515
it is not removed by the clean command.
16+
* `CARGO_TARGET_DIR_PREFIX` — Prefix to the location where to place all
17+
generated artifacts. The current working directory will be appended to this
18+
prefix to form the final path for generated artifacts. Note that
19+
`CARGO_TARGET_DIR`, if set, takes precedence over this variable.
1620
* `CARGO_TARGET_DIR` — Location of where to place all generated artifacts,
1721
relative to the current working directory.
1822
* `RUSTC` — Instead of running `rustc`, Cargo will execute this specified

tests/testsuite/build.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3006,6 +3006,63 @@ fn explicit_color_config_is_propagated_to_rustc() {
30063006
).run();
30073007
}
30083008

3009+
#[test]
3010+
fn custom_target_dir_prefix() {
3011+
fn test(cwd: &str) {
3012+
let tmpdir = tempfile::Builder::new()
3013+
.tempdir()
3014+
.unwrap()
3015+
.path()
3016+
.to_path_buf();
3017+
3018+
let p = project()
3019+
.file(
3020+
"Cargo.toml",
3021+
r#"
3022+
[package]
3023+
name = "foo"
3024+
version = "0.0.1"
3025+
authors = []
3026+
"#,
3027+
)
3028+
.file("src/main.rs", "fn main() {}")
3029+
.build();
3030+
3031+
let root = p.root();
3032+
let root_suffix = root.strip_prefix("/").unwrap();
3033+
let exe_name = format!("foo{}", env::consts::EXE_SUFFIX);
3034+
3035+
p.cargo("build")
3036+
.env("CARGO_TARGET_DIR_PREFIX", tmpdir.clone())
3037+
.cwd(p.root().join(cwd))
3038+
.run();
3039+
3040+
assert!(
3041+
tmpdir
3042+
.clone()
3043+
.join(root_suffix)
3044+
.join("target/debug")
3045+
.join(&exe_name)
3046+
.is_file()
3047+
);
3048+
assert!(!&p.root().join("target/debug").join(&exe_name).is_file());
3049+
3050+
p.cargo("build").run();
3051+
assert!(
3052+
tmpdir
3053+
.clone()
3054+
.join(root_suffix)
3055+
.join("target/debug")
3056+
.join(&exe_name)
3057+
.is_file()
3058+
);
3059+
assert!(&p.root().join("target/debug").join(&exe_name).is_file())
3060+
};
3061+
3062+
test(".");
3063+
test("src");
3064+
}
3065+
30093066
#[test]
30103067
fn compiler_json_error_format() {
30113068
let p = project()

tests/testsuite/support/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,7 @@ fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
14681468
.env_remove("GIT_AUTHOR_EMAIL")
14691469
.env_remove("GIT_COMMITTER_NAME")
14701470
.env_remove("GIT_COMMITTER_EMAIL")
1471+
.env_remove("CARGO_TARGET_DIR_PREFIX") // we assume no prefix
14711472
.env_remove("CARGO_TARGET_DIR") // we assume 'target'
14721473
.env_remove("MSYSTEM"); // assume cmd.exe everywhere on windows
14731474
p

0 commit comments

Comments
 (0)