Skip to content
Merged
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
52 changes: 39 additions & 13 deletions src/cargo/core/compiler/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use cargo_util::{ProcessBuilder, paths};

use crate::core::Package;
use crate::core::compiler::BuildContext;
use crate::core::compiler::CompileTarget;
use crate::core::compiler::RustdocFingerprint;
use crate::core::compiler::apply_env_config;
use crate::core::compiler::{CompileKind, Unit, UnitHash};
Expand Down Expand Up @@ -127,7 +128,8 @@ pub struct Compilation<'gctx> {
/// `rustc_workspace_wrapper_process`
primary_rustc_process: Option<ProcessBuilder>,

target_runners: HashMap<CompileKind, Option<(PathBuf, Vec<String>)>>,
/// The runner to use for each host or target process.
runners: HashMap<CompileKind, Option<(PathBuf, Vec<String>)>>,
/// The linker to use for each host or target.
target_linkers: HashMap<CompileKind, Option<PathBuf>>,

Expand All @@ -140,6 +142,22 @@ impl<'gctx> Compilation<'gctx> {
let rustc_process = bcx.rustc().process();
let primary_rustc_process = bcx.build_config.primary_unit_rustc.clone();
let rustc_workspace_wrapper_process = bcx.rustc().workspace_process();
let host = bcx.host_triple().to_string();
let mut runners = bcx
.build_config
.requested_kinds
.iter()
.chain(Some(&CompileKind::Host))
.map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))
.collect::<CargoResult<HashMap<_, _>>>()?;
if !bcx.gctx.target_applies_to_host()? {
Copy link
Member Author

Choose a reason for hiding this comment

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

The previous iteration was a premature fix because requested_kinds contains only CompileKind::Host when in non-cross-compilation mode. We need to insert target config with explicit target key here to ensure they are picked up.

See also the new tests in tool_paths.rs.

// When `target-applies-to-host=false`, and without `--target`,
// there will be only `CompileKind::Host` in requested_kinds.
// Need to insert target config explicitly for target-applies-to-host=false
// to find the correct configs.
let kind = explicit_host_kind(&host);
runners.insert(kind, target_runner(bcx, kind)?);
}
Ok(Compilation {
native_dirs: BTreeSet::new(),
root_output: HashMap::new(),
Expand All @@ -153,17 +171,11 @@ impl<'gctx> Compilation<'gctx> {
to_doc_test: Vec::new(),
rustdoc_fingerprints: None,
gctx: bcx.gctx,
host: bcx.host_triple().to_string(),
host,
rustc_process,
rustc_workspace_wrapper_process,
primary_rustc_process,
target_runners: bcx
.build_config
.requested_kinds
.iter()
.chain(Some(&CompileKind::Host))
.map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))
.collect::<CargoResult<HashMap<_, _>>>()?,
runners,
target_linkers: bcx
.build_config
.requested_kinds
Expand Down Expand Up @@ -238,7 +250,10 @@ impl<'gctx> Compilation<'gctx> {
// Only use host runner when -Zhost-config is enabled
// to ensure `target.<host>.runner` does not wrap build scripts.
let builder = if !self.gctx.target_applies_to_host()?
&& let Some((runner, args)) = self.target_runner(CompileKind::Host)
&& let Some((runner, args)) = self
.runners
.get(&CompileKind::Host)
.and_then(|x| x.as_ref())
{
let mut builder = ProcessBuilder::new(runner);
builder.args(args);
Expand All @@ -251,7 +266,15 @@ impl<'gctx> Compilation<'gctx> {
}

pub fn target_runner(&self, kind: CompileKind) -> Option<&(PathBuf, Vec<String>)> {
self.target_runners.get(&kind).and_then(|x| x.as_ref())
let target_applies_to_host = self.gctx.target_applies_to_host().unwrap_or(true);
let kind = if !target_applies_to_host && kind.is_host() {
// Use explicit host target triple when `target-applies-to-host=false`
// This ensures `host.runner` won't be accidentally applied to `cargo run` / `cargo test`.
explicit_host_kind(&self.host)
} else {
kind
};
self.runners.get(&kind).and_then(|x| x.as_ref())
}

/// Gets the user-specified linker for a particular host or target.
Expand Down Expand Up @@ -446,8 +469,6 @@ fn target_runner(
bcx: &BuildContext<'_, '_>,
kind: CompileKind,
) -> CargoResult<Option<(PathBuf, Vec<String>)>> {
// Try host.runner / target.{}.runner via target_config, which routes
// through host_config for CompileKind::Host when -Zhost-config is enabled.
if let Some(runner) = bcx.target_data.target_config(kind).runner.as_ref() {
let path = runner.val.path.clone().resolve_program(bcx.gctx);
return Ok(Some((path, runner.val.args.clone())));
Expand Down Expand Up @@ -516,3 +537,8 @@ fn target_linker(bcx: &BuildContext<'_, '_>, kind: CompileKind) -> CargoResult<O
}
Ok(matching_linker.map(|(_k, linker)| linker.val.clone().resolve_program(bcx.gctx)))
}

fn explicit_host_kind(host: &str) -> CompileKind {
let target = CompileTarget::new(host, false).expect("must be a host tuple");
CompileKind::Target(target)
}
47 changes: 47 additions & 0 deletions tests/testsuite/build_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,53 @@ Caused by:
.run();
}

#[cargo_test]
fn host_runner_does_not_apply_to_cargo_run() {
// `host.runner` should only wrap build scripts, not `cargo run`.
let target = rustc_host();
let p = project()
.file(
".cargo/config.toml",
r#"
[host]
runner = "nonexistent-host-runner"
"#,
)
.file("src/main.rs", "fn main() { println!(\"hello\"); }")
.build();

// with --target
p.cargo("run -Z target-applies-to-host -Z host-config --target")
.arg(&target)
.masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"])
.with_stderr_data(str![[r#"
[COMPILING] foo v0.0.1 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
[RUNNING] `target/[HOST_TARGET]/debug/foo[EXE]`

"#]])
.with_stdout_data(str![[r#"
hello

"#]])
.run();

// without --target
p.cargo("run -Z target-applies-to-host -Z host-config")
.masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"])
.with_stderr_data(str![[r#"
[COMPILING] foo v0.0.1 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
[RUNNING] `target/debug/foo[EXE]`

"#]])
.with_stdout_data(str![[r#"
hello

"#]])
.run();
}

#[cargo_test]
fn target_runner_does_not_apply_to_build_script() {
// Regression test for https://github.com/rust-lang/miri/issues/4855
Expand Down
37 changes: 37 additions & 0 deletions tests/testsuite/tool_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,43 @@ fn custom_runner_env_true() {
.run();
}

#[cargo_test]
fn custom_runner_target_applies_to_host() {
// This ensures that without `--target` (non-cross-target mode)
// Cargo still respects targe configuration.
let target = rustc_host();

let p = project()
.file("src/main.rs", "fn main() {}")
.file(
".cargo/config.toml",
&format!(
r#"
[target.{}]
runner = "nonexistent-runner -r"
"#,
target
),
)
.build();

p.cargo("run -Z target-applies-to-host")
.masquerade_as_nightly_cargo(&["target-applies-to-host"])
.env("CARGO_TARGET_APPLIES_TO_HOST", "false")
.with_status(101)
.with_stderr_data(str![[r#"
[COMPILING] foo v0.0.1 ([ROOT]/foo)
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
[RUNNING] `nonexistent-runner -r target/debug/foo[EXE]`
[ERROR] could not execute process `nonexistent-runner -r target/debug/foo[EXE]` (never executed)

Caused by:
[NOT_FOUND]

"#]])
.run();
}

#[cargo_test]
fn custom_linker_env() {
let p = project().file("src/main.rs", "fn main() {}").build();
Expand Down