Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/cargo/core/compiler/artifact.rs
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need an FCP

Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,40 @@ use std::ffi::OsString;
/// if artifacts are present.
pub fn get_env(
build_runner: &BuildRunner<'_, '_>,
unit: &Unit,
dependencies: &[UnitDep],
) -> CargoResult<HashMap<String, OsString>> {
let mut env = HashMap::new();

// Add `CARGO_BIN_EXE_` environment variables for building tests.
//
// These aren't built for `cargo check`, so can't use `dependencies`
if unit.target.is_test() || unit.target.is_bench() {
for bin_target in unit
.pkg
.manifest()
.targets()
.iter()
.filter(|target| target.is_bin())
{
let name = bin_target
.binary_filename()
.unwrap_or_else(|| bin_target.name().to_string());

// For `cargo check` builds we do not uplift the CARGO_BIN_EXE_ artifacts to the
// artifact-dir. We do not want to provide a path to a non-existent binary but we still
// need to provide *something* so `env!("CARGO_BIN_EXE_...")` macros will compile.
let exe_path = build_runner
.files()
.bin_link_for_target(bin_target, unit.kind, build_runner.bcx)?
.map(|path| path.as_os_str().to_os_string())
.unwrap_or_else(|| OsString::from(format!("placeholder:{name}")));

let key = format!("CARGO_BIN_EXE_{name}");
env.insert(key, exe_path);
}
}

for unit_dep in dependencies.iter().filter(|d| d.unit.artifact.is_true()) {
for artifact_path in build_runner
.outputs(&unit_dep.unit)?
Expand Down
16 changes: 9 additions & 7 deletions src/cargo/core/compiler/build_runner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
unstable_opts,
linker: self.compilation.target_linker(unit.kind).clone(),
script_metas,
env: artifact::get_env(&self, self.unit_deps(unit))?,
env: artifact::get_env(&self, unit, self.unit_deps(unit))?,
});
}

Expand Down Expand Up @@ -316,17 +316,17 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
if unit.mode == CompileMode::Test {
self.compilation
.tests
.push(self.unit_output(unit, &output.path));
.push(self.unit_output(unit, &output.path)?);
} else if unit.target.is_executable() {
self.compilation
.binaries
.push(self.unit_output(unit, bindst));
.push(self.unit_output(unit, bindst)?);
} else if unit.target.is_cdylib()
&& !self.compilation.cdylibs.iter().any(|uo| uo.unit == *unit)
{
self.compilation
.cdylibs
.push(self.unit_output(unit, bindst));
.push(self.unit_output(unit, bindst)?);
}
}
Ok(())
Expand Down Expand Up @@ -554,13 +554,15 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {

/// Returns a [`UnitOutput`] which represents some information about the
/// output of a unit.
pub fn unit_output(&self, unit: &Unit, path: &Path) -> UnitOutput {
pub fn unit_output(&self, unit: &Unit, path: &Path) -> CargoResult<UnitOutput> {
let script_metas = self.find_build_script_metadatas(unit);
UnitOutput {
let env = artifact::get_env(&self, unit, self.unit_deps(unit))?;
Ok(UnitOutput {
unit: unit.clone(),
path: path.to_path_buf(),
script_metas,
}
env,
})
}

/// Check if any output file name collision happens.
Expand Down
4 changes: 3 additions & 1 deletion src/cargo/core/compiler/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ pub struct Doctest {
}

/// Information about the output of a unit.
#[derive(Ord, PartialOrd, Eq, PartialEq)]
pub struct UnitOutput {
/// The unit that generated this output.
pub unit: Unit,
Expand All @@ -63,6 +62,9 @@ pub struct UnitOutput {
///
/// This is used for indexing [`Compilation::extra_env`].
pub script_metas: Option<Vec<UnitHash>>,

/// Environment variables to set in the unit's process.
pub env: HashMap<String, OsString>,
}

/// A structure returning the result of a compilation.
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ fn build_work(build_runner: &mut BuildRunner<'_, '_>, unit: &Unit) -> CargoResul
.inherit_jobserver(&build_runner.jobserver);

// Find all artifact dependencies and make their file and containing directory discoverable using environment variables.
for (var, value) in artifact::get_env(build_runner, dependencies)? {
for (var, value) in artifact::get_env(build_runner, unit, dependencies)? {
cmd.env(&var, value);
}

Expand Down
27 changes: 1 addition & 26 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1441,31 +1441,6 @@ fn build_base_args(
.env("RUSTC_BOOTSTRAP", "1");
}

// Add `CARGO_BIN_EXE_` 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())
{
// For `cargo check` builds we do not uplift the CARGO_BIN_EXE_ artifacts to the
// artifact-dir. We do not want to provide a path to a non-existent binary but we still
// need to provide *something* so `env!("CARGO_BIN_EXE_...")` macros will compile.
let exe_path = build_runner
.files()
.bin_link_for_target(bin_target, unit.kind, build_runner.bcx)?
.map(|path| path.as_os_str().to_os_string())
.unwrap_or_else(|| OsString::from(format!("placeholder:{}", bin_target.name())));

let name = bin_target
.binary_filename()
.unwrap_or(bin_target.name().to_string());
let key = format!("CARGO_BIN_EXE_{}", name);
cmd.env(&key, exe_path);
}
}
Ok(())
}

Expand Down Expand Up @@ -1769,7 +1744,7 @@ fn build_deps_args(
cmd.arg(arg);
}

for (var, env) in artifact::get_env(build_runner, deps)? {
for (var, env) in artifact::get_env(build_runner, unit, deps)? {
cmd.env(&var, env);
}

Expand Down
1 change: 1 addition & 0 deletions src/cargo/ops/cargo_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub fn run(
unit,
path,
script_metas,
env: _env,
} = &compile.binaries[0];
let exe = match path.strip_prefix(gctx.cwd()) {
Ok(path) if path.file_name() == Some(path.as_os_str()) => Path::new(".").join(path),
Expand Down
11 changes: 10 additions & 1 deletion src/cargo/ops/cargo_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::util::errors::CargoResult;
use crate::util::{CliError, CliResult, GlobalContext, add_path_args};
use anyhow::format_err;
use cargo_util::{ProcessBuilder, ProcessError};
use std::collections::HashMap;
use std::ffi::OsString;
use std::fmt::Write;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -103,7 +104,7 @@ pub fn run_benches(ws: &Workspace<'_>, options: &TestOptions, args: &[&str]) ->

fn compile_tests<'a>(ws: &Workspace<'a>, options: &TestOptions) -> CargoResult<Compilation<'a>> {
let mut compilation = ops::compile(ws, &options.compile_opts)?;
compilation.tests.sort();
compilation.tests.sort_by_key(|u| u.unit.clone());
Ok(compilation)
}

Expand All @@ -126,6 +127,7 @@ fn run_unit_tests(
unit,
path,
script_metas,
env,
} in compilation.tests.iter()
{
let (exe_display, mut cmd) = cmd_builds(
Expand All @@ -134,6 +136,7 @@ fn run_unit_tests(
unit,
path,
script_metas.as_ref(),
env,
test_args,
compilation,
"unittests",
Expand Down Expand Up @@ -287,6 +290,7 @@ fn display_no_run_information(
unit,
path,
script_metas,
env,
} in compilation.tests.iter()
{
let (exe_display, cmd) = cmd_builds(
Expand All @@ -295,6 +299,7 @@ fn display_no_run_information(
unit,
path,
script_metas.as_ref(),
env,
test_args,
compilation,
exec_type,
Expand All @@ -319,6 +324,7 @@ fn cmd_builds(
unit: &Unit,
path: &PathBuf,
script_metas: Option<&Vec<UnitHash>>,
env: &HashMap<String, OsString>,
test_args: &[&str],
compilation: &Compilation<'_>,
exec_type: &str,
Expand Down Expand Up @@ -348,6 +354,9 @@ fn cmd_builds(
if unit.target.harness() && gctx.shell().verbosity() == Verbosity::Quiet {
cmd.arg("--quiet");
}
for (key, val) in env.iter() {
cmd.env(key, val);
}

Ok((exe_display, cmd))
}
Expand Down
3 changes: 3 additions & 0 deletions tests/testsuite/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5216,6 +5216,9 @@ fn bin_env_for_test() {
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üßen"), "<GRÜSSEN_PATH>");
assert_eq!(std::env::var("CARGO_BIN_EXE_foo").ok().as_deref(), Some("<FOO_PATH>"));
assert_eq!(std::env::var("CARGO_BIN_EXE_with-dash").ok().as_deref(), Some("<WITH_DASH_PATH>"));
assert_eq!(std::env::var("CARGO_BIN_EXE_grüßen").ok().as_deref(), Some("<GRÜSSEN_PATH>"));
}
"#
.replace("<FOO_PATH>", &bin_path("foo"))
Expand Down