Skip to content

Commit 55f0163

Browse files
committed
Add support for target.'cfg(..)'.linker
1 parent 80eca0e commit 55f0163

File tree

8 files changed

+59
-19
lines changed

8 files changed

+59
-19
lines changed

src/cargo/core/compiler/build_context/mod.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use crate::util::errors::CargoResult;
1010
use crate::util::interning::InternedString;
1111
use crate::util::Rustc;
1212
use std::collections::{HashMap, HashSet};
13-
use std::path::PathBuf;
1413

1514
mod target_info;
1615
pub use self::target_info::{
@@ -120,15 +119,6 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
120119
&self.target_data.rustc
121120
}
122121

123-
/// Gets the user-specified linker for a particular host or target.
124-
pub fn linker(&self, kind: CompileKind) -> Option<PathBuf> {
125-
self.target_data
126-
.target_config(kind)
127-
.linker
128-
.as_ref()
129-
.map(|l| l.val.clone().resolve_program(self.config))
130-
}
131-
132122
/// Gets the host architecture triple.
133123
///
134124
/// For example, x86_64-unknown-linux-gnu, would be

src/cargo/core/compiler/compilation.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ pub struct Compilation<'cfg> {
104104
primary_rustc_process: Option<ProcessBuilder>,
105105

106106
target_runners: HashMap<CompileKind, Option<(PathBuf, Vec<String>)>>,
107+
/// The linker to use for each host or target.
108+
target_linkers: HashMap<CompileKind, Option<PathBuf>>,
107109
}
108110

109111
impl<'cfg> Compilation<'cfg> {
@@ -150,6 +152,13 @@ impl<'cfg> Compilation<'cfg> {
150152
.chain(Some(&CompileKind::Host))
151153
.map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))
152154
.collect::<CargoResult<HashMap<_, _>>>()?,
155+
target_linkers: bcx
156+
.build_config
157+
.requested_kinds
158+
.iter()
159+
.chain(Some(&CompileKind::Host))
160+
.map(|kind| Ok((*kind, target_linker(bcx, *kind)?)))
161+
.collect::<CargoResult<HashMap<_, _>>>()?,
153162
})
154163
}
155164

@@ -221,6 +230,11 @@ impl<'cfg> Compilation<'cfg> {
221230
self.target_runners.get(&kind).and_then(|x| x.as_ref())
222231
}
223232

233+
/// Gets the user-specified linker for a particular host or target.
234+
pub fn target_linker(&self, kind: CompileKind) -> Option<PathBuf> {
235+
self.target_linkers.get(&kind).and_then(|x| x.clone())
236+
}
237+
224238
/// Returns a [`ProcessBuilder`] appropriate for running a process for the
225239
/// target platform. This is typically used for `cargo run` and `cargo
226240
/// test`.
@@ -441,3 +455,39 @@ fn target_runner(
441455
)
442456
}))
443457
}
458+
459+
/// Gets the user-specified linker for a particular host or target from the configuration.
460+
fn target_linker(bcx: &BuildContext<'_, '_>, kind: CompileKind) -> CargoResult<Option<PathBuf>> {
461+
// Try host.linker and target.{}.linker.
462+
if let Some(path) = bcx
463+
.target_data
464+
.target_config(kind)
465+
.linker
466+
.as_ref()
467+
.map(|l| l.val.clone().resolve_program(bcx.config))
468+
{
469+
return Ok(Some(path));
470+
}
471+
472+
// Try target.'cfg(...)'.linker.
473+
let target_cfg = bcx.target_data.info(kind).cfg();
474+
let mut cfgs = bcx
475+
.config
476+
.target_cfgs()?
477+
.iter()
478+
.filter_map(|(key, cfg)| cfg.linker.as_ref().map(|linker| (key, linker)))
479+
.filter(|(key, _linker)| CfgExpr::matches_key(key, target_cfg));
480+
let matching_linker = cfgs.next();
481+
if let Some((key, linker)) = cfgs.next() {
482+
anyhow::bail!(
483+
"several matching instances of `target.'cfg(..)'.linker` in configurations\n\
484+
first match `{}` located in {}\n\
485+
second match `{}` located in {}",
486+
matching_linker.unwrap().0,
487+
matching_linker.unwrap().1.definition,
488+
key,
489+
linker.definition
490+
);
491+
}
492+
Ok(matching_linker.map(|(_k, linker)| linker.val.clone().resolve_program(bcx.config)))
493+
}

src/cargo/core/compiler/context/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
272272
unit: unit.clone(),
273273
args,
274274
unstable_opts,
275-
linker: self.bcx.linker(unit.kind),
275+
linker: self.compilation.target_linker(unit.kind).clone(),
276276
script_meta,
277277
env: artifact::get_env(&self, self.unit_deps(unit))?,
278278
});

src/cargo/core/compiler/custom_build.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,8 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
299299
cmd.env(&var, value);
300300
}
301301

302-
if let Some(linker) = &bcx.target_data.target_config(unit.kind).linker {
303-
cmd.env(
304-
"RUSTC_LINKER",
305-
linker.val.clone().resolve_program(bcx.config),
306-
);
302+
if let Some(linker) = &cx.compilation.target_linker(unit.kind) {
303+
cmd.env("RUSTC_LINKER", linker);
307304
}
308305

309306
if let Some(links) = unit.pkg.manifest().links() {

src/cargo/core/compiler/fingerprint/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1426,7 +1426,7 @@ fn calculate_normal(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Finger
14261426
let m = unit.pkg.manifest().metadata();
14271427
let metadata = util::hash_u64((&m.authors, &m.description, &m.homepage, &m.repository));
14281428
let mut config = StableHasher::new();
1429-
if let Some(linker) = cx.bcx.linker(unit.kind) {
1429+
if let Some(linker) = cx.compilation.target_linker(unit.kind) {
14301430
linker.hash(&mut config);
14311431
}
14321432
if unit.mode.is_doc() && cx.bcx.config.cli_unstable().rustdoc_map {

src/cargo/core/compiler/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1117,7 +1117,10 @@ fn build_base_args(cx: &Context<'_, '_>, cmd: &mut ProcessBuilder, unit: &Unit)
11171117
cmd,
11181118
"-C",
11191119
"linker=",
1120-
bcx.linker(unit.kind).as_ref().map(|s| s.as_ref()),
1120+
cx.compilation
1121+
.target_linker(unit.kind)
1122+
.as_ref()
1123+
.map(|s| s.as_ref()),
11211124
);
11221125
if incremental {
11231126
let dir = cx.files().layout(unit.kind).incremental().as_os_str();

src/cargo/util/config/target.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::path::PathBuf;
1212
pub struct TargetCfgConfig {
1313
pub runner: OptValue<PathAndArgs>,
1414
pub rustflags: OptValue<StringList>,
15+
pub linker: OptValue<ConfigRelativePath>,
1516
// This is here just to ignore fields from normal `TargetConfig` because
1617
// all `[target]` tables are getting deserialized, whether they start with
1718
// `cfg(` or not.

tests/testsuite/tool_paths.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,6 @@ fn cfg_ignored_fields() {
393393
[WARNING] unused key `ar` in [target] config table `cfg(not(target_os = \"none\"))`
394394
[WARNING] unused key `foo` in [target] config table `cfg(not(target_os = \"none\"))`
395395
[WARNING] unused key `invalid` in [target] config table `cfg(not(target_os = \"none\"))`
396-
[WARNING] unused key `linker` in [target] config table `cfg(not(target_os = \"none\"))`
397396
[CHECKING] foo v0.0.1 ([..])
398397
[FINISHED] [..]
399398
",

0 commit comments

Comments
 (0)