Set an environment variable for tests to find executables.

This commit is contained in:
Eric Huss 2019-12-11 08:26:08 -08:00
parent db0dac507e
commit 3489428921
4 changed files with 104 additions and 1 deletions

View File

@ -10,7 +10,7 @@ use log::info;
use super::{BuildContext, CompileKind, Context, FileFlavor, Layout}; use super::{BuildContext, CompileKind, Context, FileFlavor, Layout};
use crate::core::compiler::{CompileMode, CompileTarget, Unit}; use crate::core::compiler::{CompileMode, CompileTarget, Unit};
use crate::core::{TargetKind, Workspace}; use crate::core::{Target, TargetKind, Workspace};
use crate::util::{self, CargoResult}; use crate::util::{self, CargoResult};
/// The `Metadata` is a hash used to make unique file names for each unit in a build. /// The `Metadata` is a hash used to make unique file names for each unit in a build.
@ -241,6 +241,36 @@ impl<'a, 'cfg: 'a> CompilationFiles<'a, 'cfg> {
} }
} }
/// Returns the path to the executable binary for the given bin target.
///
/// This should only to be used when a `Unit` is not available.
pub fn bin_link_for_target(
&self,
target: &Target,
kind: CompileKind,
bcx: &BuildContext<'_, '_>,
) -> CargoResult<PathBuf> {
assert!(target.is_bin());
let dest = self.layout(kind).dest();
let info = bcx.info(kind);
let file_types = info
.file_types(
"bin",
FileFlavor::Normal,
&TargetKind::Bin,
kind.short_name(bcx),
)?
.expect("target must support `bin`");
let file_type = file_types
.iter()
.filter(|file_type| file_type.flavor == FileFlavor::Normal)
.next()
.expect("target must support `bin`");
Ok(dest.join(file_type.filename(target.name())))
}
/// Returns the filenames that the given unit will generate. /// Returns the filenames that the given unit will generate.
pub(super) fn outputs( pub(super) fn outputs(
&self, &self,

View File

@ -876,6 +876,23 @@ fn build_base_args<'a, 'cfg>(
cmd.arg("-Zforce-unstable-if-unmarked") cmd.arg("-Zforce-unstable-if-unmarked")
.env("RUSTC_BOOTSTRAP", "1"); .env("RUSTC_BOOTSTRAP", "1");
} }
// Add `CARGO_BIN_` environment variables for building tests.
if unit.target.is_test() || unit.target.is_bench() {
for bin_target in unit
.pkg
.manifest()
.targets()
.iter()
.filter(|target| target.is_bin())
{
let exe_path = cx
.files()
.bin_link_for_target(bin_target, unit.kind, cx.bcx)?;
let key = format!("CARGO_BIN_EXE_{}", bin_target.crate_name().to_uppercase());
cmd.env(&key, exe_path);
}
}
Ok(()) Ok(())
} }

View File

@ -187,6 +187,15 @@ let version = env!("CARGO_PKG_VERSION");
* `OUT_DIR` — If the package has a build script, this is set to the folder where the build * `OUT_DIR` — If the package has a build script, this is set to the folder where the build
script should place its output. See below for more information. script should place its output. See below for more information.
(Only set during compilation.) (Only set during compilation.)
* `CARGO_BIN_EXE_<name>` The absolute path to a binary target's executable.
This is only set when building an [integration test] or benchmark. This may
be used with the [`env` macro] to find the executable to run for testing
purposes. The `<name>` is the name of the binary converted to uppercase, and
`-` converted to `_`. Binaries are automatically built when the test is
built, unless the binary has required features that are not enabled.
[integration test]: manifest.md#integration-tests
[`env` macro]: ../../std/macro.env.html
#### Dynamic library paths #### Dynamic library paths

View File

@ -3995,3 +3995,50 @@ fn panic_abort_test_profile_inherits() {
.with_status(0) .with_status(0)
.run(); .run();
} }
#[cargo_test]
fn bin_env_for_test() {
// Test for the `CARGO_BIN_` environment variables for tests.
//
// Note: The Unicode binary uses a `[[bin]]` definition because different
// filesystems normalize utf-8 in different ways. For example, HFS uses
// "gru\u{308}ßen" and APFS uses "gr\u{fc}ßen". Defining it in TOML forces
// one form to be used.
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.1.0"
edition = "2018"
[[bin]]
name = 'grüßen'
path = 'src/bin/grussen.rs'
"#,
)
.file("src/bin/foo.rs", "fn main() {}")
.file("src/bin/with-dash.rs", "fn main() {}")
.file("src/bin/grussen.rs", "fn main() {}")
.build();
let bin_path = |name| p.bin(name).to_string_lossy().replace("\\", "\\\\");
p.change_file(
"tests/check_env.rs",
&r#"
#[test]
fn run_bins() {
assert_eq!(env!("CARGO_BIN_EXE_FOO"), "<FOO_PATH>");
assert_eq!(env!("CARGO_BIN_EXE_WITH_DASH"), "<WITH_DASH_PATH>");
assert_eq!(env!("CARGO_BIN_EXE_GRÜSSEN"), "<GRÜSSEN_PATH>");
}
"#
.replace("<FOO_PATH>", &bin_path("foo"))
.replace("<WITH_DASH_PATH>", &bin_path("with-dash"))
.replace("<GRÜSSEN_PATH>", &bin_path("grüßen")),
);
p.cargo("test --test check_env").run();
p.cargo("check --test check_env").run();
}