diff --git a/src/cargo/core/compiler/compilation.rs b/src/cargo/core/compiler/compilation.rs index f94d750a18f..c533c5b7390 100644 --- a/src/cargo/core/compiler/compilation.rs +++ b/src/cargo/core/compiler/compilation.rs @@ -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}; @@ -127,7 +128,8 @@ pub struct Compilation<'gctx> { /// `rustc_workspace_wrapper_process` primary_rustc_process: Option, - target_runners: HashMap)>>, + /// The runner to use for each host or target process. + runners: HashMap)>>, /// The linker to use for each host or target. target_linkers: HashMap>, @@ -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::>>()?; + if !bcx.gctx.target_applies_to_host()? { + // 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(), @@ -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::>>()?, + runners, target_linkers: bcx .build_config .requested_kinds @@ -238,7 +250,10 @@ impl<'gctx> Compilation<'gctx> { // Only use host runner when -Zhost-config is enabled // to ensure `target..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); @@ -251,7 +266,15 @@ impl<'gctx> Compilation<'gctx> { } pub fn target_runner(&self, kind: CompileKind) -> Option<&(PathBuf, Vec)> { - 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. @@ -446,8 +469,6 @@ fn target_runner( bcx: &BuildContext<'_, '_>, kind: CompileKind, ) -> CargoResult)>> { - // 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()))); @@ -516,3 +537,8 @@ fn target_linker(bcx: &BuildContext<'_, '_>, kind: CompileKind) -> CargoResult CompileKind { + let target = CompileTarget::new(host, false).expect("must be a host tuple"); + CompileKind::Target(target) +} diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs index befd6496893..5f19e8ca179 100644 --- a/tests/testsuite/build_script.rs +++ b/tests/testsuite/build_script.rs @@ -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 diff --git a/tests/testsuite/tool_paths.rs b/tests/testsuite/tool_paths.rs index 0849f6375c6..9da5027d3df 100644 --- a/tests/testsuite/tool_paths.rs +++ b/tests/testsuite/tool_paths.rs @@ -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();