Skip to content

Commit 0806953

Browse files
committed
Auto merge of #3789 - vojtechkral:cargo_env, r=alexcrichton
Tell subprocesses the path to self in an env variable #3778 I'm just setting the env var on the process itself, letting subprocesses inherit that, as it's easier than setting for each subprocess individually. I'm not entirely sure this is the right spot though. Also, I should probably document this somewhere - what would be the best place?
2 parents 1389b33 + 015a08a commit 0806953

File tree

11 files changed

+109
-14
lines changed

11 files changed

+109
-14
lines changed

src/bin/cargo.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,12 @@ fn execute_external_subcommand(config: &Config, cmd: &str, args: &[String]) -> C
320320
.into())
321321
}
322322
};
323-
let err = match util::process(&command).args(&args[1..]).exec() {
323+
324+
let cargo_exe = config.cargo_exe()?;
325+
let err = match util::process(&command)
326+
.env(cargo::CARGO_ENV, cargo_exe)
327+
.args(&args[1..])
328+
.exec() {
324329
Ok(()) => return Ok(()),
325330
Err(e) => e,
326331
};

src/cargo/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ use term::color::{BLACK};
4242

4343
pub use util::{CargoError, CargoResult, CliError, CliResult, human, Config, ChainError};
4444

45+
pub const CARGO_ENV: &'static str = "CARGO";
46+
4547
macro_rules! bail {
4648
($($fmt:tt)*) => (
4749
return Err(::util::human(&format_args!($($fmt)*)))

src/cargo/ops/cargo_rustc/compilation.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ impl<'cfg> Compilation<'cfg> {
143143

144144
let metadata = pkg.manifest().metadata();
145145

146+
let cargo_exe = self.config.cargo_exe()?;
147+
cmd.env(::CARGO_ENV, cargo_exe);
148+
146149
cmd.env("CARGO_MANIFEST_DIR", pkg.root())
147150
.env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
148151
.env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string())

src/cargo/util/config.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub struct Config {
2828
rustc: LazyCell<Rustc>,
2929
values: LazyCell<HashMap<String, ConfigValue>>,
3030
cwd: PathBuf,
31+
cargo_exe: LazyCell<PathBuf>,
3132
rustdoc: LazyCell<PathBuf>,
3233
extra_verbose: Cell<bool>,
3334
frozen: Cell<bool>,
@@ -44,6 +45,7 @@ impl Config {
4445
rustc: LazyCell::new(),
4546
cwd: cwd,
4647
values: LazyCell::new(),
48+
cargo_exe: LazyCell::new(),
4749
rustdoc: LazyCell::new(),
4850
extra_verbose: Cell::new(false),
4951
frozen: Cell::new(false),
@@ -93,6 +95,15 @@ impl Config {
9395
self.rustc.get_or_try_init(|| Rustc::new(self.get_tool("rustc")?))
9496
}
9597

98+
pub fn cargo_exe(&self) -> CargoResult<&Path> {
99+
self.cargo_exe.get_or_try_init(||
100+
env::current_exe().and_then(|path| path.canonicalize())
101+
.chain_error(|| {
102+
human("couldn't get the path to cargo executable")
103+
})
104+
).map(AsRef::as_ref)
105+
}
106+
96107
pub fn values(&self) -> CargoResult<&HashMap<String, ConfigValue>> {
97108
self.values.get_or_try_init(|| self.load_values())
98109
}

src/doc/environment-variables.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,17 @@ configuration values, as described in [that documentation][config-env]
3030

3131
# Environment variables Cargo sets for crates
3232

33-
Cargo exposes these environment variables to your crate when it is compiled. To get the
34-
value of any of these variables in a Rust program, do this:
33+
Cargo exposes these environment variables to your crate when it is compiled.
34+
Note that this applies for test binaries as well.
35+
To get the value of any of these variables in a Rust program, do this:
3536

3637
```
3738
let version = env!("CARGO_PKG_VERSION");
3839
```
3940

4041
`version` will now contain the value of `CARGO_PKG_VERSION`.
4142

43+
* `CARGO` - Path to the `cargo` binary performing the build.
4244
* `CARGO_MANIFEST_DIR` - The directory containing the manifest of your package.
4345
* `CARGO_PKG_VERSION` - The full version of your package.
4446
* `CARGO_PKG_VERSION_MAJOR` - The major version of your package.
@@ -96,3 +98,10 @@ let out_dir = env::var("OUT_DIR").unwrap();
9698
[links]: build-script.html#the-links-manifest-key
9799
[profile]: manifest.html#the-profile-sections
98100
[clang]:http://clang.llvm.org/docs/CrossCompilation.html#target-triple
101+
102+
# Environment variables Cargo sets for 3rd party subcommands
103+
104+
Cargo exposes this environment variable to 3rd party subcommands
105+
(ie. programs named `cargo-foobar` placed in `$PATH`):
106+
107+
* `CARGO` - Path to the `cargo` binary performing the build.

tests/cargo.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
extern crate cargo;
12
extern crate cargotest;
23
extern crate hamcrest;
34

@@ -10,8 +11,8 @@ use std::str;
1011

1112
use cargotest::cargo_process;
1213
use cargotest::support::paths::{self, CargoPathExt};
13-
use cargotest::support::{execs, project, ProjectBuilder};
14-
use hamcrest::{assert_that};
14+
use cargotest::support::{execs, project, ProjectBuilder, basic_bin_manifest};
15+
use hamcrest::{assert_that, existing_file};
1516

1617
#[cfg_attr(windows,allow(dead_code))]
1718
enum FakeKind<'a> {
@@ -81,11 +82,11 @@ fn list_command_looks_at_path() {
8182
#[cfg(unix)]
8283
#[test]
8384
fn list_command_resolves_symlinks() {
84-
use cargotest::support::cargo_dir;
85+
use cargotest::support::cargo_exe;
8586

8687
let proj = project("list-non-overlapping");
8788
let proj = fake_file(proj, Path::new("path-test"), "cargo-2",
88-
FakeKind::Symlink{target:&cargo_dir().join("cargo")});
89+
FakeKind::Symlink{target:&cargo_exe()});
8990
let mut pr = cargo_process();
9091

9192
let mut path = path();
@@ -161,6 +162,37 @@ fn override_cargo_home() {
161162
assert!(contents.contains(r#"authors = ["foo <bar>"]"#));
162163
}
163164

165+
#[test]
166+
fn cargo_subcommand_env() {
167+
use cargotest::support::cargo_exe;
168+
169+
let src = format!(r#"
170+
use std::env;
171+
172+
fn main() {{
173+
println!("{{}}", env::var("{}").unwrap());
174+
}}
175+
"#, cargo::CARGO_ENV);
176+
177+
let p = project("cargo-envtest")
178+
.file("Cargo.toml", &basic_bin_manifest("cargo-envtest"))
179+
.file("src/main.rs", &src);
180+
181+
let target_dir = p.target_debug_dir();
182+
183+
assert_that(p.cargo_process("build"), execs().with_status(0));
184+
assert_that(&p.bin("cargo-envtest"), existing_file());
185+
186+
let mut pr = cargo_process();
187+
let cargo = cargo_exe().canonicalize().unwrap();
188+
let mut path = path();
189+
path.push(target_dir);
190+
let path = env::join_paths(path.iter()).unwrap();
191+
192+
assert_that(pr.arg("envtest").env("PATH", &path),
193+
execs().with_status(0).with_stdout(cargo.to_str().unwrap()));
194+
}
195+
164196
#[test]
165197
fn cargo_help() {
166198
assert_that(cargo_process(),

tests/cargotest/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
9595
}
9696

9797
pub fn cargo_process() -> cargo::util::ProcessBuilder {
98-
process(&support::cargo_dir().join("cargo"))
98+
process(&support::cargo_exe())
9999
}
100100

101101
pub fn sleep_ms(ms: u64) {

tests/cargotest/support/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl ProjectBuilder {
165165
assert!(self.is_build.get(),
166166
"call `.build()` before calling `.cargo()`, \
167167
or use `.cargo_process()`");
168-
let mut p = self.process(&cargo_dir().join("cargo"));
168+
let mut p = self.process(&cargo_exe());
169169
p.arg(cmd);
170170
return p;
171171
}
@@ -317,6 +317,10 @@ pub fn cargo_dir() -> PathBuf {
317317
})
318318
}
319319

320+
pub fn cargo_exe() -> PathBuf {
321+
cargo_dir().join(format!("cargo{}", env::consts::EXE_SUFFIX))
322+
}
323+
320324
/// Returns an absolute path in the filesystem that `path` points to. The
321325
/// returned path does not contain any symlinks in its hierarchy.
322326
/*

tests/init.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ use std::io::prelude::*;
88
use std::env;
99

1010
use cargo::util::ProcessBuilder;
11-
use cargotest::support::{execs, paths, cargo_dir};
11+
use cargotest::support::{execs, paths, cargo_exe};
1212
use hamcrest::{assert_that, existing_file, existing_dir, is_not};
1313
use tempdir::TempDir;
1414

1515
fn cargo_process(s: &str) -> ProcessBuilder {
16-
let mut p = cargotest::process(&cargo_dir().join("cargo"));
16+
let mut p = cargotest::process(&cargo_exe());
1717
p.arg(s).cwd(&paths::root()).env("HOME", &paths::home());
1818
p
1919
}

tests/package.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::io::prelude::*;
1111
use std::path::{Path, PathBuf};
1212

1313
use cargotest::{cargo_process, process};
14-
use cargotest::support::{project, execs, paths, git, path2url, cargo_dir};
14+
use cargotest::support::{project, execs, paths, git, path2url, cargo_exe};
1515
use flate2::read::GzDecoder;
1616
use hamcrest::{assert_that, existing_file, contains};
1717
use tar::Archive;
@@ -481,7 +481,7 @@ fn repackage_on_source_change() {
481481
"#).unwrap();
482482
std::mem::drop(file);
483483

484-
let mut pro = process(&cargo_dir().join("cargo"));
484+
let mut pro = process(&cargo_exe());
485485
pro.arg("package").cwd(p.root());
486486

487487
// Check that cargo rebuilds the tarball

0 commit comments

Comments
 (0)