Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
5 changes: 4 additions & 1 deletion src/cargo/core/compiler/build_runner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,10 @@ impl<'a, 'gctx> BuildRunner<'a, 'gctx> {
unit: unit.clone(),
args,
unstable_opts,
linker: self.compilation.target_linker(unit.kind).clone(),
linker: self
.compilation
.target_linker(unit.kind)
.map(|p| p.to_path_buf()),
script_metas,
env: artifact::get_env(&self, unit, self.unit_deps(unit))?,
});
Expand Down
45 changes: 36 additions & 9 deletions src/cargo/core/compiler/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::collections::{BTreeSet, HashMap};
use std::ffi::{OsStr, OsString};
use std::path::Path;
use std::path::PathBuf;

use cargo_platform::CfgExpr;
Expand Down Expand Up @@ -158,6 +159,19 @@ impl<'gctx> Compilation<'gctx> {
let kind = explicit_host_kind(&host);
runners.insert(kind, target_runner(bcx, kind)?);
}

let mut target_linkers = bcx
.build_config
.requested_kinds
.iter()
.chain(Some(&CompileKind::Host))
.map(|kind| Ok((*kind, target_linker(bcx, *kind)?)))
.collect::<CargoResult<HashMap<_, _>>>()?;
if !bcx.gctx.target_applies_to_host()? {
// See above reason in runner why we do this.
let kind = explicit_host_kind(&host);
target_linkers.insert(kind, target_linker(bcx, kind)?);
}
Ok(Compilation {
native_dirs: BTreeSet::new(),
root_output: HashMap::new(),
Expand All @@ -176,13 +190,7 @@ impl<'gctx> Compilation<'gctx> {
rustc_workspace_wrapper_process,
primary_rustc_process,
runners,
target_linkers: bcx
.build_config
.requested_kinds
.iter()
.chain(Some(&CompileKind::Host))
.map(|kind| Ok((*kind, target_linker(bcx, *kind)?)))
.collect::<CargoResult<HashMap<_, _>>>()?,
target_linkers,
lint_warning_count: 0,
})
}
Expand Down Expand Up @@ -277,9 +285,28 @@ impl<'gctx> Compilation<'gctx> {
self.runners.get(&kind).and_then(|x| x.as_ref())
}

/// Gets the `[host.linker]` for host build target (build scripts and proc macros).
pub fn host_linker(&self) -> Option<&Path> {
self.target_linkers
.get(&CompileKind::Host)
.and_then(|x| x.as_ref())
.map(|x| x.as_path())
}

/// Gets the user-specified linker for a particular host or target.
pub fn target_linker(&self, kind: CompileKind) -> Option<PathBuf> {
self.target_linkers.get(&kind).and_then(|x| x.clone())
pub fn target_linker(&self, kind: CompileKind) -> Option<&Path> {
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.linker` won't be accidentally applied to normal builds
explicit_host_kind(&self.host)
} else {
kind
};
self.target_linkers
.get(&kind)
.and_then(|x| x.as_ref())
.map(|x| x.as_path())
}

/// Returns a [`ProcessBuilder`] appropriate for running a process for the
Expand Down
7 changes: 6 additions & 1 deletion src/cargo/core/compiler/fingerprint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1635,7 +1635,12 @@ fn calculate_normal(
unit.pkg.manifest().lint_rustflags(),
));
let mut config = StableHasher::new();
if let Some(linker) = build_runner.compilation.target_linker(unit.kind) {
let linker = if unit.target.for_host() && !build_runner.bcx.gctx.target_applies_to_host()? {
build_runner.compilation.host_linker()
} else {
build_runner.compilation.target_linker(unit.kind)
};
if let Some(linker) = linker {
linker.hash(&mut config);
}
if unit.mode.is_doc() && build_runner.bcx.gctx.cli_unstable().rustdoc_map {
Expand Down
20 changes: 10 additions & 10 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1414,16 +1414,16 @@ fn build_base_args(

unit.kind.add_target_arg(cmd);

opt(
cmd,
"-C",
"linker=",
build_runner
.compilation
.target_linker(unit.kind)
.as_ref()
.map(|s| s.as_ref()),
);
opt(cmd, "-C", "linker=", {
Comment thread
epage marked this conversation as resolved.
Outdated
if unit.target.for_host() && !bcx.gctx.target_applies_to_host()? {
build_runner.compilation.host_linker().map(|s| s.as_ref())
} else {
build_runner
.compilation
.target_linker(unit.kind)
.map(|s| s.as_ref())
}
});
if incremental {
let dir = build_runner.files().incremental_dir(&unit);
opt(cmd, "-C", "incremental=", Some(dir.as_os_str()));
Expand Down
53 changes: 53 additions & 0 deletions tests/testsuite/cross_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1299,3 +1299,56 @@ fn always_emit_warnings_as_warnings_when_learning_target_info() {
"#]])
.run();
}

#[cargo_test]
fn host_linker_does_not_apply_to_binary_build() {
// `host.linker` should only apply to build scripts, not to normal binary builds.
let target = rustc_host();
let p = project()
.file(
".cargo/config.toml",
&format!(
r#"
[host]
linker = "nonexistent-host-linker"
[target.{target}]
linker = "nonexistent-target-linker"
"#,
),
)
.file("src/main.rs", "fn main() {}")
.build();

p.cargo("build -Z target-applies-to-host -Z host-config --target")
.arg(&target)
.masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"])
.with_status(101)
// Need to omit some MSVC-specific diagnostics
// because rustc prints extra stuff when linker was not found.
// https://github.com/rust-lang/rust/blob/7ad4e69ad585d8ff214f7b42d01f1959eda08f40/compiler/rustc_codegen_ssa/src/back/link.rs?plain=1#L971-L975
.with_stderr_data(str![[r#"
[COMPILING] foo v0.0.1 ([ROOT]/foo)
[ERROR] linker `nonexistent-target-linker` not found
|
= [NOTE] [NOT_FOUND]
...
"#]])
.run();

// with target-applies-to-host=false,
// host.linker should not be applied but target.linker
p.cargo("build -Z target-applies-to-host -Z host-config")
.masquerade_as_nightly_cargo(&["target-applies-to-host", "host-config"])
.with_status(101)
// Need to omit some MSVC-specific diagnostics
// because rustc prints extra stuff when linker was not found.
// https://github.com/rust-lang/rust/blob/7ad4e69ad585d8ff214f7b42d01f1959eda08f40/compiler/rustc_codegen_ssa/src/back/link.rs?plain=1#L971-L975
.with_stderr_data(str![[r#"
[COMPILING] foo v0.0.1 ([ROOT]/foo)
[ERROR] linker `nonexistent-target-linker` not found
|
= [NOTE] [NOT_FOUND]
...
"#]])
.run();
}