Skip to content

Commit

Permalink
Add support for target.'cfg(..)'.linker
Browse files Browse the repository at this point in the history
  • Loading branch information
Rustin170506 committed Aug 25, 2023
1 parent 80eca0e commit 647c5a7
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 19 deletions.
10 changes: 0 additions & 10 deletions src/cargo/core/compiler/build_context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::util::errors::CargoResult;
use crate::util::interning::InternedString;
use crate::util::Rustc;
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;

mod target_info;
pub use self::target_info::{
Expand Down Expand Up @@ -120,15 +119,6 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
&self.target_data.rustc
}

/// Gets the user-specified linker for a particular host or target.
pub fn linker(&self, kind: CompileKind) -> Option<PathBuf> {
self.target_data
.target_config(kind)
.linker
.as_ref()
.map(|l| l.val.clone().resolve_program(self.config))
}

/// Gets the host architecture triple.
///
/// For example, x86_64-unknown-linux-gnu, would be
Expand Down
50 changes: 50 additions & 0 deletions src/cargo/core/compiler/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ pub struct Compilation<'cfg> {
primary_rustc_process: Option<ProcessBuilder>,

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

impl<'cfg> Compilation<'cfg> {
Expand Down Expand Up @@ -150,6 +152,13 @@ impl<'cfg> Compilation<'cfg> {
.chain(Some(&CompileKind::Host))
.map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))
.collect::<CargoResult<HashMap<_, _>>>()?,
target_linkers: bcx
.build_config
.requested_kinds
.iter()
.chain(Some(&CompileKind::Host))
.map(|kind| Ok((*kind, target_linker(bcx, *kind)?)))
.collect::<CargoResult<HashMap<_, _>>>()?,
})
}

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

/// 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())
}

/// Returns a [`ProcessBuilder`] appropriate for running a process for the
/// target platform. This is typically used for `cargo run` and `cargo
/// test`.
Expand Down Expand Up @@ -441,3 +455,39 @@ fn target_runner(
)
}))
}

/// Gets the user-specified linker for a particular host or target from the configuration.
fn target_linker(bcx: &BuildContext<'_, '_>, kind: CompileKind) -> CargoResult<Option<PathBuf>> {
// Try host.linker and target.{}.linker.
if let Some(path) = bcx
.target_data
.target_config(kind)
.linker
.as_ref()
.map(|l| l.val.clone().resolve_program(bcx.config))
{
return Ok(Some(path));
}

// Try target.'cfg(...)'.linker.
let target_cfg = bcx.target_data.info(kind).cfg();
let mut cfgs = bcx
.config
.target_cfgs()?
.iter()
.filter_map(|(key, cfg)| cfg.linker.as_ref().map(|linker| (key, linker)))
.filter(|(key, _linker)| CfgExpr::matches_key(key, target_cfg));
let matching_linker = cfgs.next();
if let Some((key, runner)) = cfgs.next() {
anyhow::bail!(
"several matching instances of `target.'cfg(..)'.linker` in configurations\n\
first match `{}` located in {}\n\
second match `{}` located in {}",
matching_linker.unwrap().0,
matching_linker.unwrap().1.definition,
key,
runner.definition
);
}
Ok(matching_linker.map(|(_k, linker)| linker.val.clone().resolve_program(bcx.config)))
}
2 changes: 1 addition & 1 deletion src/cargo/core/compiler/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
unit: unit.clone(),
args,
unstable_opts,
linker: self.bcx.linker(unit.kind),
linker: self.compilation.target_linker(unit.kind).clone(),
script_meta,
env: artifact::get_env(&self, self.unit_deps(unit))?,
});
Expand Down
7 changes: 2 additions & 5 deletions src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,11 +299,8 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
cmd.env(&var, value);
}

if let Some(linker) = &bcx.target_data.target_config(unit.kind).linker {
cmd.env(
"RUSTC_LINKER",
linker.val.clone().resolve_program(bcx.config),
);
if let Some(linker) = &cx.compilation.target_linker(unit.kind) {
cmd.env("RUSTC_LINKER", linker);
}

if let Some(links) = unit.pkg.manifest().links() {
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/core/compiler/fingerprint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1426,7 +1426,7 @@ fn calculate_normal(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Finger
let m = unit.pkg.manifest().metadata();
let metadata = util::hash_u64((&m.authors, &m.description, &m.homepage, &m.repository));
let mut config = StableHasher::new();
if let Some(linker) = cx.bcx.linker(unit.kind) {
if let Some(linker) = cx.compilation.target_linker(unit.kind) {
linker.hash(&mut config);
}
if unit.mode.is_doc() && cx.bcx.config.cli_unstable().rustdoc_map {
Expand Down
5 changes: 4 additions & 1 deletion src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,10 @@ fn build_base_args(cx: &Context<'_, '_>, cmd: &mut ProcessBuilder, unit: &Unit)
cmd,
"-C",
"linker=",
bcx.linker(unit.kind).as_ref().map(|s| s.as_ref()),
cx.compilation
.target_linker(unit.kind)
.as_ref()
.map(|s| s.as_ref()),
);
if incremental {
let dir = cx.files().layout(unit.kind).incremental().as_os_str();
Expand Down
1 change: 1 addition & 0 deletions src/cargo/util/config/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::path::PathBuf;
pub struct TargetCfgConfig {
pub runner: OptValue<PathAndArgs>,
pub rustflags: OptValue<StringList>,
pub linker: OptValue<ConfigRelativePath>,
// This is here just to ignore fields from normal `TargetConfig` because
// all `[target]` tables are getting deserialized, whether they start with
// `cfg(` or not.
Expand Down
1 change: 0 additions & 1 deletion tests/testsuite/tool_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,6 @@ fn cfg_ignored_fields() {
[WARNING] unused key `ar` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `foo` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `invalid` in [target] config table `cfg(not(target_os = \"none\"))`
[WARNING] unused key `linker` in [target] config table `cfg(not(target_os = \"none\"))`
[CHECKING] foo v0.0.1 ([..])
[FINISHED] [..]
",
Expand Down

0 comments on commit 647c5a7

Please sign in to comment.