.into())
}
};
- let err = match util::process(&command).args(&args[1..]).exec() {
+
+ let cargo_exe = config.cargo_exe()?;
+ let err = match util::process(&command)
+ .env(cargo::CARGO_ENV, cargo_exe)
+ .args(&args[1..])
+ .exec() {
Ok(()) => return Ok(()),
Err(e) => e,
};
pub use util::{CargoError, CargoResult, CliError, CliResult, human, Config, ChainError};
+pub const CARGO_ENV: &'static str = "CARGO";
+
macro_rules! bail {
($($fmt:tt)*) => (
return Err(::util::human(&format_args!($($fmt)*)))
let metadata = pkg.manifest().metadata();
+ let cargo_exe = self.config.cargo_exe()?;
+ cmd.env(::CARGO_ENV, cargo_exe);
+
cmd.env("CARGO_MANIFEST_DIR", pkg.root())
.env("CARGO_PKG_VERSION_MAJOR", &pkg.version().major.to_string())
.env("CARGO_PKG_VERSION_MINOR", &pkg.version().minor.to_string())
rustc: LazyCell<Rustc>,
values: LazyCell<HashMap<String, ConfigValue>>,
cwd: PathBuf,
+ cargo_exe: LazyCell<PathBuf>,
rustdoc: LazyCell<PathBuf>,
extra_verbose: Cell<bool>,
frozen: Cell<bool>,
rustc: LazyCell::new(),
cwd: cwd,
values: LazyCell::new(),
+ cargo_exe: LazyCell::new(),
rustdoc: LazyCell::new(),
extra_verbose: Cell::new(false),
frozen: Cell::new(false),
self.rustc.get_or_try_init(|| Rustc::new(self.get_tool("rustc")?))
}
+ pub fn cargo_exe(&self) -> CargoResult<&Path> {
+ self.cargo_exe.get_or_try_init(||
+ env::current_exe().and_then(|path| path.canonicalize())
+ .chain_error(|| {
+ human("couldn't get the path to cargo executable")
+ })
+ ).map(AsRef::as_ref)
+ }
+
pub fn values(&self) -> CargoResult<&HashMap<String, ConfigValue>> {
self.values.get_or_try_init(|| self.load_values())
}
# Environment variables Cargo sets for crates
-Cargo exposes these environment variables to your crate when it is compiled. To get the
-value of any of these variables in a Rust program, do this:
+Cargo exposes these environment variables to your crate when it is compiled.
+Note that this applies for test binaries as well.
+To get the value of any of these variables in a Rust program, do this:
```
let version = env!("CARGO_PKG_VERSION");
`version` will now contain the value of `CARGO_PKG_VERSION`.
+* `CARGO` - Path to the `cargo` binary performing the build.
* `CARGO_MANIFEST_DIR` - The directory containing the manifest of your package.
* `CARGO_PKG_VERSION` - The full version of your package.
* `CARGO_PKG_VERSION_MAJOR` - The major version of your package.
[links]: build-script.html#the-links-manifest-key
[profile]: manifest.html#the-profile-sections
[clang]:http://clang.llvm.org/docs/CrossCompilation.html#target-triple
+
+# Environment variables Cargo sets for 3rd party subcommands
+
+Cargo exposes this environment variable to 3rd party subcommands
+(ie. programs named `cargo-foobar` placed in `$PATH`):
+
+* `CARGO` - Path to the `cargo` binary performing the build.
+extern crate cargo;
extern crate cargotest;
extern crate hamcrest;
use cargotest::cargo_process;
use cargotest::support::paths::{self, CargoPathExt};
-use cargotest::support::{execs, project, ProjectBuilder};
-use hamcrest::{assert_that};
+use cargotest::support::{execs, project, ProjectBuilder, basic_bin_manifest};
+use hamcrest::{assert_that, existing_file};
#[cfg_attr(windows,allow(dead_code))]
enum FakeKind<'a> {
#[cfg(unix)]
#[test]
fn list_command_resolves_symlinks() {
- use cargotest::support::cargo_dir;
+ use cargotest::support::cargo_exe;
let proj = project("list-non-overlapping");
let proj = fake_file(proj, Path::new("path-test"), "cargo-2",
- FakeKind::Symlink{target:&cargo_dir().join("cargo")});
+ FakeKind::Symlink{target:&cargo_exe()});
let mut pr = cargo_process();
let mut path = path();
assert!(contents.contains(r#"authors = ["foo <bar>"]"#));
}
+#[test]
+fn cargo_subcommand_env() {
+ use cargotest::support::cargo_exe;
+
+ let src = format!(r#"
+ use std::env;
+
+ fn main() {{
+ println!("{{}}", env::var("{}").unwrap());
+ }}
+ "#, cargo::CARGO_ENV);
+
+ let p = project("cargo-envtest")
+ .file("Cargo.toml", &basic_bin_manifest("cargo-envtest"))
+ .file("src/main.rs", &src);
+
+ let target_dir = p.target_debug_dir();
+
+ assert_that(p.cargo_process("build"), execs().with_status(0));
+ assert_that(&p.bin("cargo-envtest"), existing_file());
+
+ let mut pr = cargo_process();
+ let cargo = cargo_exe().canonicalize().unwrap();
+ let mut path = path();
+ path.push(target_dir);
+ let path = env::join_paths(path.iter()).unwrap();
+
+ assert_that(pr.arg("envtest").env("PATH", &path),
+ execs().with_status(0).with_stdout(cargo.to_str().unwrap()));
+}
+
#[test]
fn cargo_help() {
assert_that(cargo_process(),
}
pub fn cargo_process() -> cargo::util::ProcessBuilder {
- process(&support::cargo_dir().join("cargo"))
+ process(&support::cargo_exe())
}
pub fn sleep_ms(ms: u64) {
assert!(self.is_build.get(),
"call `.build()` before calling `.cargo()`, \
or use `.cargo_process()`");
- let mut p = self.process(&cargo_dir().join("cargo"));
+ let mut p = self.process(&cargo_exe());
p.arg(cmd);
return p;
}
})
}
+pub fn cargo_exe() -> PathBuf {
+ cargo_dir().join(format!("cargo{}", env::consts::EXE_SUFFIX))
+}
+
/// Returns an absolute path in the filesystem that `path` points to. The
/// returned path does not contain any symlinks in its hierarchy.
/*
use std::env;
use cargo::util::ProcessBuilder;
-use cargotest::support::{execs, paths, cargo_dir};
+use cargotest::support::{execs, paths, cargo_exe};
use hamcrest::{assert_that, existing_file, existing_dir, is_not};
use tempdir::TempDir;
fn cargo_process(s: &str) -> ProcessBuilder {
- let mut p = cargotest::process(&cargo_dir().join("cargo"));
+ let mut p = cargotest::process(&cargo_exe());
p.arg(s).cwd(&paths::root()).env("HOME", &paths::home());
p
}
use std::path::{Path, PathBuf};
use cargotest::{cargo_process, process};
-use cargotest::support::{project, execs, paths, git, path2url, cargo_dir};
+use cargotest::support::{project, execs, paths, git, path2url, cargo_exe};
use flate2::read::GzDecoder;
use hamcrest::{assert_that, existing_file, contains};
use tar::Archive;
"#).unwrap();
std::mem::drop(file);
- let mut pro = process(&cargo_dir().join("cargo"));
+ let mut pro = process(&cargo_exe());
pro.arg("package").cwd(p.root());
// Check that cargo rebuilds the tarball
use std::str;
use cargotest::{sleep_ms, is_nightly};
-use cargotest::support::{project, execs, basic_bin_manifest, basic_lib_manifest};
+use cargotest::support::{project, execs, basic_bin_manifest, basic_lib_manifest, cargo_exe};
use cargotest::support::paths::CargoPathExt;
use cargotest::support::registry::Package;
use hamcrest::{assert_that, existing_file, is_not};
assert_that(p.cargo_process("test").arg("--all").arg("-v"),
execs().with_status(0));
}
+
+#[test]
+fn cargo_test_env() {
+ let src = format!(r#"
+ #![crate_type = "rlib"]
+
+ #[test]
+ fn env_test() {{
+ use std::env;
+ println!("{{}}", env::var("{}").unwrap());
+ }}
+ "#, cargo::CARGO_ENV);
+
+ let p = project("env_test")
+ .file("Cargo.toml", &basic_lib_manifest("env_test"))
+ .file("src/lib.rs", &src);
+
+ let mut pr = p.cargo_process("test");
+ let cargo = cargo_exe().canonicalize().unwrap();
+ assert_that(pr.args(&["--lib", "--", "--nocapture"]),
+ execs().with_status(0).with_stdout(format!("
+running 1 test
+{}
+test env_test ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+", cargo.to_str().unwrap())));
+}