Skip to content

Commit 83912a0

Browse files
committed
Auto merge of #4852 - jtgeibel:cargo-install-target-dir, r=alexcrichton
Always respect `CARGO_TARGET_DIR` during `cargo install` This aligns the behavior of crates.io and `--git` sources with that of `--path` regarding the `CARGO_TARGET_DIR` and `CARGO_BUILD_TARGET_DIR` environment variables. If neither environment variable is set, then a temporary directory is still used when installing from crates.io or `--git`. As discussed in #4725, this can be used to enable caching of artifacts between continuous integration builds. /cc @alexcrichton, @ishanjain28
2 parents 4deca32 + a81b143 commit 83912a0

File tree

4 files changed

+42
-2
lines changed

4 files changed

+42
-2
lines changed

src/bin/install.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ As a special convenience, omitting the <crate> specification entirely will
100100
install the crate in the current directory. That is, `install` is equivalent to
101101
the more explicit `install --path .`.
102102
103+
If the source is crates.io or `--git` then by default the crate will be built
104+
in a temporary target directory. To avoid this, the target directory can be
105+
specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
106+
path. In particular, this can be useful for caching build artifacts on
107+
continuous integration systems.
108+
103109
The `--list` option will list all installed packages (and their versions).
104110
";
105111

src/cargo/ops/cargo_install.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,17 @@ fn install_one(root: &Filesystem,
159159
};
160160

161161
let mut td_opt = None;
162+
let mut needs_cleanup = false;
162163
let overidden_target_dir = if source_id.is_path() {
163164
None
165+
} else if let Some(dir) = config.target_dir()? {
166+
Some(dir)
164167
} else if let Ok(td) = TempDir::new("cargo-install") {
165168
let p = td.path().to_owned();
166169
td_opt = Some(td);
167170
Some(Filesystem::new(p))
168171
} else {
172+
needs_cleanup = true;
169173
Some(Filesystem::new(config.cwd().join("target-install")))
170174
};
171175

@@ -311,7 +315,7 @@ fn install_one(root: &Filesystem,
311315

312316
// Reaching here means all actions have succeeded. Clean up.
313317
installed.success();
314-
if !source_id.is_path() {
318+
if needs_cleanup {
315319
// Don't bother grabbing a lock as we're going to blow it all away
316320
// anyway.
317321
let target_dir = ws.target_dir().into_path_unlocked();

src/etc/man/cargo-install.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ will install the crate in the current directory.
4242
That is, \f[I]install\f[] is equivalent to the more explicit "install
4343
\-\-path .".
4444
.PP
45+
If the source is crates.io or \f[B]\-\-git\f[] then by default the crate will be built in a temporary target directory.
46+
To avoid this, the target directory can be specified by setting the \f[B]CARGO_TARGET_DIR\f[] environment variable to a relative path.
47+
In particular, this can be useful for caching build artifacts on continuous integration systems.
48+
.PP
4549
The \f[B]\-\-list\f[] option will list all installed packages (and their
4650
versions).
4751
.SH OPTIONS

tests/install.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use cargotest::support::git;
1111
use cargotest::support::paths;
1212
use cargotest::support::registry::Package;
1313
use cargotest::support::{project, execs};
14-
use hamcrest::{assert_that, is_not};
14+
use hamcrest::{assert_that, existing_dir, is_not};
1515

1616
fn cargo_process(s: &str) -> ProcessBuilder {
1717
let mut p = cargotest::cargo_process();
@@ -988,3 +988,29 @@ error: some packages failed to uninstall
988988
assert_that(cargo_home(), is_not(has_installed_exe("foo")));
989989
assert_that(cargo_home(), is_not(has_installed_exe("bar")));
990990
}
991+
992+
#[test]
993+
fn custom_target_dir_for_git_source() {
994+
let p = git::repo(&paths::root().join("foo"))
995+
.file("Cargo.toml", r#"
996+
[package]
997+
name = "foo"
998+
version = "0.1.0"
999+
authors = []
1000+
"#)
1001+
.file("src/main.rs", "fn main() {}")
1002+
.build();
1003+
1004+
assert_that(cargo_process("install")
1005+
.arg("--git").arg(p.url().to_string()),
1006+
execs().with_status(0));
1007+
assert_that(&paths::root().join("target/release"),
1008+
is_not(existing_dir()));
1009+
1010+
assert_that(cargo_process("install").arg("--force")
1011+
.arg("--git").arg(p.url().to_string())
1012+
.env("CARGO_TARGET_DIR", "target"),
1013+
execs().with_status(0));
1014+
assert_that(&paths::root().join("target/release"),
1015+
existing_dir());
1016+
}

0 commit comments

Comments
 (0)