mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
Add support for target.'cfg(..)'.linker
This commit is contained in:
parent
80eca0e58f
commit
55f0163fb2
@ -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::{
|
||||
@ -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
|
||||
|
@ -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> {
|
||||
@ -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<_, _>>>()?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -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`.
|
||||
@ -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, linker)) = 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,
|
||||
linker.definition
|
||||
);
|
||||
}
|
||||
Ok(matching_linker.map(|(_k, linker)| linker.val.clone().resolve_program(bcx.config)))
|
||||
}
|
||||
|
@ -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))?,
|
||||
});
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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] [..]
|
||||
",
|
||||
|
Loading…
x
Reference in New Issue
Block a user