Skip to content

Commit 532cadd

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 0e7c5a9 commit 532cadd

File tree

4 files changed

+76
-1
lines changed

4 files changed

+76
-1
lines changed

src/cargo/util/config.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,17 @@ impl Config {
240240
pub fn target_dir(&self) -> CargoResult<Option<Filesystem>> {
241241
if let Some(dir) = env::var_os("CARGO_TARGET_DIR") {
242242
Ok(Some(Filesystem::new(self.cwd.join(dir))))
243+
} else if let Some(dir) = env::var_os("CARGO_TARGET_DIR_PREFIX") {
244+
let prefix = Path::new(&dir);
245+
if !prefix.is_absolute() {
246+
bail!("CARGO_TARGET_DIR_PREFIX must describe an absolute path");
247+
}
248+
match self.cwd.strip_prefix("/") {
249+
Ok(cwd) => Ok(Some(Filesystem::new(prefix.join(&cwd).join("target")))),
250+
// FIXME: This logic is probably not safe on Windows. Not sure how
251+
// to make a path relative there.
252+
Err(_) => bail!("CARGO_TARGET_DIR_PREFIX must describe an absolute path"),
253+
}
243254
} else if let Some(val) = self.get_path("build.target-dir")? {
244255
let val = self.cwd.join(val.val);
245256
Ok(Some(Filesystem::new(val)))

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,13 @@ 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,
17-
relative to the current working directory.
21+
relative to the current working directory. This variable supersedes the
22+
behavior of `CARGO_TARGET_DIR_PREFIX`.
1823
* `RUSTC` - Instead of running `rustc`, Cargo will execute this specified
1924
compiler instead.
2025
* `RUSTC_WRAPPER` - Instead of simply running `rustc`, Cargo will execute this

tests/testsuite/build.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3615,6 +3615,64 @@ fn dotdir_root() {
36153615
assert_that(p.cargo("build"), execs().with_status(0));
36163616
}
36173617

3618+
#[test]
3619+
fn custom_target_dir_prefix() {
3620+
let tmpdir = tempfile::Builder::new()
3621+
.tempdir()
3622+
.unwrap()
3623+
.path()
3624+
.to_path_buf();
3625+
3626+
let p = project("foo")
3627+
.file(
3628+
"Cargo.toml",
3629+
r#"
3630+
[package]
3631+
name = "foo"
3632+
version = "0.0.1"
3633+
authors = []
3634+
"#,
3635+
)
3636+
.file("src/main.rs", "fn main() {}")
3637+
.build();
3638+
3639+
let root = p.root();
3640+
let root_suffix = root.strip_prefix("/").unwrap();
3641+
let exe_name = format!("foo{}", env::consts::EXE_SUFFIX);
3642+
3643+
assert_that(
3644+
p.cargo("build")
3645+
.env("CARGO_TARGET_DIR_PREFIX", tmpdir.clone()),
3646+
execs().with_status(0),
3647+
);
3648+
assert_that(
3649+
tmpdir
3650+
.clone()
3651+
.join(root_suffix)
3652+
.join("target/debug")
3653+
.join(&exe_name),
3654+
existing_file(),
3655+
);
3656+
assert_that(
3657+
&p.root().join("target/debug").join(&exe_name),
3658+
is_not(existing_file()),
3659+
);
3660+
3661+
assert_that(p.cargo("build"), execs().with_status(0));
3662+
assert_that(
3663+
tmpdir
3664+
.clone()
3665+
.join(root_suffix)
3666+
.join("target/debug")
3667+
.join(&exe_name),
3668+
existing_file(),
3669+
);
3670+
assert_that(
3671+
&p.root().join("target/debug").join(&exe_name),
3672+
existing_file(),
3673+
);
3674+
}
3675+
36183676
#[test]
36193677
fn custom_target_dir() {
36203678
let p = project("foo")

tests/testsuite/cargotest/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
6262
.env_remove("GIT_AUTHOR_EMAIL")
6363
.env_remove("GIT_COMMITTER_NAME")
6464
.env_remove("GIT_COMMITTER_EMAIL")
65+
.env_remove("CARGO_TARGET_DIR_PREFIX") // we assume no prefix
6566
.env_remove("CARGO_TARGET_DIR") // we assume 'target'
6667
.env_remove("MSYSTEM"); // assume cmd.exe everywhere on windows
6768
return p;

0 commit comments

Comments
 (0)