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::interning::InternedString;
|
||||||
use crate::util::Rustc;
|
use crate::util::Rustc;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
mod target_info;
|
mod target_info;
|
||||||
pub use self::target_info::{
|
pub use self::target_info::{
|
||||||
@ -120,15 +119,6 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
|
|||||||
&self.target_data.rustc
|
&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.
|
/// Gets the host architecture triple.
|
||||||
///
|
///
|
||||||
/// For example, x86_64-unknown-linux-gnu, would be
|
/// For example, x86_64-unknown-linux-gnu, would be
|
||||||
|
@ -104,6 +104,8 @@ pub struct Compilation<'cfg> {
|
|||||||
primary_rustc_process: Option<ProcessBuilder>,
|
primary_rustc_process: Option<ProcessBuilder>,
|
||||||
|
|
||||||
target_runners: HashMap<CompileKind, Option<(PathBuf, Vec<String>)>>,
|
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> {
|
impl<'cfg> Compilation<'cfg> {
|
||||||
@ -150,6 +152,13 @@ impl<'cfg> Compilation<'cfg> {
|
|||||||
.chain(Some(&CompileKind::Host))
|
.chain(Some(&CompileKind::Host))
|
||||||
.map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))
|
.map(|kind| Ok((*kind, target_runner(bcx, *kind)?)))
|
||||||
.collect::<CargoResult<HashMap<_, _>>>()?,
|
.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())
|
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
|
/// Returns a [`ProcessBuilder`] appropriate for running a process for the
|
||||||
/// target platform. This is typically used for `cargo run` and `cargo
|
/// target platform. This is typically used for `cargo run` and `cargo
|
||||||
/// test`.
|
/// 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(),
|
unit: unit.clone(),
|
||||||
args,
|
args,
|
||||||
unstable_opts,
|
unstable_opts,
|
||||||
linker: self.bcx.linker(unit.kind),
|
linker: self.compilation.target_linker(unit.kind).clone(),
|
||||||
script_meta,
|
script_meta,
|
||||||
env: artifact::get_env(&self, self.unit_deps(unit))?,
|
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);
|
cmd.env(&var, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(linker) = &bcx.target_data.target_config(unit.kind).linker {
|
if let Some(linker) = &cx.compilation.target_linker(unit.kind) {
|
||||||
cmd.env(
|
cmd.env("RUSTC_LINKER", linker);
|
||||||
"RUSTC_LINKER",
|
|
||||||
linker.val.clone().resolve_program(bcx.config),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(links) = unit.pkg.manifest().links() {
|
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 m = unit.pkg.manifest().metadata();
|
||||||
let metadata = util::hash_u64((&m.authors, &m.description, &m.homepage, &m.repository));
|
let metadata = util::hash_u64((&m.authors, &m.description, &m.homepage, &m.repository));
|
||||||
let mut config = StableHasher::new();
|
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);
|
linker.hash(&mut config);
|
||||||
}
|
}
|
||||||
if unit.mode.is_doc() && cx.bcx.config.cli_unstable().rustdoc_map {
|
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,
|
cmd,
|
||||||
"-C",
|
"-C",
|
||||||
"linker=",
|
"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 {
|
if incremental {
|
||||||
let dir = cx.files().layout(unit.kind).incremental().as_os_str();
|
let dir = cx.files().layout(unit.kind).incremental().as_os_str();
|
||||||
|
@ -12,6 +12,7 @@ use std::path::PathBuf;
|
|||||||
pub struct TargetCfgConfig {
|
pub struct TargetCfgConfig {
|
||||||
pub runner: OptValue<PathAndArgs>,
|
pub runner: OptValue<PathAndArgs>,
|
||||||
pub rustflags: OptValue<StringList>,
|
pub rustflags: OptValue<StringList>,
|
||||||
|
pub linker: OptValue<ConfigRelativePath>,
|
||||||
// This is here just to ignore fields from normal `TargetConfig` because
|
// This is here just to ignore fields from normal `TargetConfig` because
|
||||||
// all `[target]` tables are getting deserialized, whether they start with
|
// all `[target]` tables are getting deserialized, whether they start with
|
||||||
// `cfg(` or not.
|
// `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 `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 `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 `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 ([..])
|
[CHECKING] foo v0.0.1 ([..])
|
||||||
[FINISHED] [..]
|
[FINISHED] [..]
|
||||||
",
|
",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user