mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-21 19:33:16 +00:00
rustc_target: Refactor linker flavor inference
Go through an intermediate pair of `cc`and `lld` hints instead of mapping CLI options to `LinkerFlavor` directly, and use the target's default linker flavor as a reference.
This commit is contained in:
parent
498553fc04
commit
2013ccc218
@ -23,7 +23,7 @@ use rustc_session::utils::NativeLibKind;
|
||||
use rustc_session::{filesearch, Session};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
|
||||
use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy};
|
||||
use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld, PanicStrategy};
|
||||
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo};
|
||||
|
||||
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
|
||||
@ -1302,44 +1302,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|
||||
let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| {
|
||||
sess.emit_fatal(errors::LinkerFileStem);
|
||||
});
|
||||
|
||||
// Remove any version postfix.
|
||||
let stem = stem
|
||||
.rsplit_once('-')
|
||||
.and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs))
|
||||
.unwrap_or(stem);
|
||||
|
||||
// GCC/Clang can have an optional target prefix.
|
||||
let flavor = if stem == "emcc" {
|
||||
LinkerFlavor::EmCc
|
||||
} else if stem == "gcc"
|
||||
|| stem.ends_with("-gcc")
|
||||
|| stem == "g++"
|
||||
|| stem.ends_with("-g++")
|
||||
|| stem == "clang"
|
||||
|| stem.ends_with("-clang")
|
||||
|| stem == "clang++"
|
||||
|| stem.ends_with("-clang++")
|
||||
{
|
||||
LinkerFlavor::from_cli(LinkerFlavorCli::Gcc, &sess.target)
|
||||
} else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") {
|
||||
LinkerFlavor::WasmLld(Cc::No)
|
||||
} else if stem == "ld" || stem.ends_with("-ld") {
|
||||
LinkerFlavor::from_cli(LinkerFlavorCli::Ld, &sess.target)
|
||||
} else if stem == "ld.lld" {
|
||||
LinkerFlavor::Gnu(Cc::No, Lld::Yes)
|
||||
} else if stem == "link" {
|
||||
LinkerFlavor::Msvc(Lld::No)
|
||||
} else if stem == "lld-link" {
|
||||
LinkerFlavor::Msvc(Lld::Yes)
|
||||
} else if stem == "lld" || stem == "rust-lld" {
|
||||
let lld_flavor = sess.target.linker_flavor.lld_flavor();
|
||||
LinkerFlavor::from_cli(LinkerFlavorCli::Lld(lld_flavor), &sess.target)
|
||||
} else {
|
||||
// fall back to the value in the target spec
|
||||
sess.target.linker_flavor
|
||||
};
|
||||
|
||||
let flavor = sess.target.linker_flavor.with_linker_hints(stem);
|
||||
Some((linker, flavor))
|
||||
}
|
||||
(None, None) => None,
|
||||
@ -1349,7 +1312,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|
||||
// linker and linker flavor specified via command line have precedence over what the target
|
||||
// specification specifies
|
||||
let linker_flavor =
|
||||
sess.opts.cg.linker_flavor.map(|flavor| LinkerFlavor::from_cli(flavor, &sess.target));
|
||||
sess.opts.cg.linker_flavor.map(|flavor| sess.target.linker_flavor.with_cli_hints(flavor));
|
||||
if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -205,15 +205,11 @@ impl ToJson for LldFlavor {
|
||||
}
|
||||
|
||||
impl LinkerFlavor {
|
||||
pub fn from_cli(cli: LinkerFlavorCli, target: &TargetOptions) -> LinkerFlavor {
|
||||
Self::from_cli_impl(cli, target.linker_flavor.lld_flavor(), target.linker_flavor.is_gnu())
|
||||
}
|
||||
|
||||
/// The passed CLI flavor is preferred over other args coming from the default target spec,
|
||||
/// so this function can produce a flavor that is incompatible with the current target.
|
||||
/// FIXME: Produce errors when `-Clinker-flavor` is set to something incompatible
|
||||
/// with the current target.
|
||||
fn from_cli_impl(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> LinkerFlavor {
|
||||
/// At this point the target's reference linker flavor doesn't yet exist and we need to infer
|
||||
/// it. The inference always succeds and gives some result, and we don't report any flavor
|
||||
/// incompatibility errors for json target specs. The CLI flavor is used as the main source
|
||||
/// of truth, other flags are used in case of ambiguities.
|
||||
fn from_cli_json(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> LinkerFlavor {
|
||||
match cli {
|
||||
LinkerFlavorCli::Gcc => match lld_flavor {
|
||||
LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::Yes, Lld::No),
|
||||
@ -257,6 +253,72 @@ impl LinkerFlavor {
|
||||
}
|
||||
}
|
||||
|
||||
fn infer_cli_hints(cli: LinkerFlavorCli) -> (Option<Cc>, Option<Lld>) {
|
||||
match cli {
|
||||
LinkerFlavorCli::Gcc | LinkerFlavorCli::Em => (Some(Cc::Yes), None),
|
||||
LinkerFlavorCli::Lld(_) => (Some(Cc::No), Some(Lld::Yes)),
|
||||
LinkerFlavorCli::Ld | LinkerFlavorCli::Msvc => (Some(Cc::No), Some(Lld::No)),
|
||||
LinkerFlavorCli::BpfLinker | LinkerFlavorCli::PtxLinker => (None, None),
|
||||
}
|
||||
}
|
||||
|
||||
fn infer_linker_hints(linker_stem: &str) -> (Option<Cc>, Option<Lld>) {
|
||||
// Remove any version postfix.
|
||||
let stem = linker_stem
|
||||
.rsplit_once('-')
|
||||
.and_then(|(lhs, rhs)| rhs.chars().all(char::is_numeric).then_some(lhs))
|
||||
.unwrap_or(linker_stem);
|
||||
|
||||
// GCC/Clang can have an optional target prefix.
|
||||
if stem == "emcc"
|
||||
|| stem == "gcc"
|
||||
|| stem.ends_with("-gcc")
|
||||
|| stem == "g++"
|
||||
|| stem.ends_with("-g++")
|
||||
|| stem == "clang"
|
||||
|| stem.ends_with("-clang")
|
||||
|| stem == "clang++"
|
||||
|| stem.ends_with("-clang++")
|
||||
{
|
||||
(Some(Cc::Yes), None)
|
||||
} else if stem == "wasm-ld"
|
||||
|| stem.ends_with("-wasm-ld")
|
||||
|| stem == "ld.lld"
|
||||
|| stem == "lld"
|
||||
|| stem == "rust-lld"
|
||||
|| stem == "lld-link"
|
||||
{
|
||||
(Some(Cc::No), Some(Lld::Yes))
|
||||
} else if stem == "ld" || stem.ends_with("-ld") || stem == "link" {
|
||||
(Some(Cc::No), Some(Lld::No))
|
||||
} else {
|
||||
(None, None)
|
||||
}
|
||||
}
|
||||
|
||||
fn with_hints(self, (cc_hint, lld_hint): (Option<Cc>, Option<Lld>)) -> LinkerFlavor {
|
||||
match self {
|
||||
LinkerFlavor::Gnu(cc, lld) => {
|
||||
LinkerFlavor::Gnu(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
|
||||
}
|
||||
LinkerFlavor::Darwin(cc, lld) => {
|
||||
LinkerFlavor::Darwin(cc_hint.unwrap_or(cc), lld_hint.unwrap_or(lld))
|
||||
}
|
||||
LinkerFlavor::WasmLld(cc) => LinkerFlavor::WasmLld(cc_hint.unwrap_or(cc)),
|
||||
LinkerFlavor::Unix(cc) => LinkerFlavor::Unix(cc_hint.unwrap_or(cc)),
|
||||
LinkerFlavor::Msvc(lld) => LinkerFlavor::Msvc(lld_hint.unwrap_or(lld)),
|
||||
LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => self,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_cli_hints(self, cli: LinkerFlavorCli) -> LinkerFlavor {
|
||||
self.with_hints(LinkerFlavor::infer_cli_hints(cli))
|
||||
}
|
||||
|
||||
pub fn with_linker_hints(self, linker_stem: &str) -> LinkerFlavor {
|
||||
self.with_hints(LinkerFlavor::infer_linker_hints(linker_stem))
|
||||
}
|
||||
|
||||
pub fn lld_flavor(self) -> LldFlavor {
|
||||
match self {
|
||||
LinkerFlavor::Gnu(..)
|
||||
@ -1801,7 +1863,7 @@ impl TargetOptions {
|
||||
}
|
||||
|
||||
fn update_from_cli(&mut self) {
|
||||
self.linker_flavor = LinkerFlavor::from_cli_impl(
|
||||
self.linker_flavor = LinkerFlavor::from_cli_json(
|
||||
self.linker_flavor_json,
|
||||
self.lld_flavor_json,
|
||||
self.linker_is_gnu_json,
|
||||
@ -1815,12 +1877,7 @@ impl TargetOptions {
|
||||
] {
|
||||
args.clear();
|
||||
for (flavor, args_json) in args_json {
|
||||
// Cannot use `from_cli` due to borrow checker.
|
||||
let linker_flavor = LinkerFlavor::from_cli_impl(
|
||||
*flavor,
|
||||
self.lld_flavor_json,
|
||||
self.linker_is_gnu_json,
|
||||
);
|
||||
let linker_flavor = self.linker_flavor.with_cli_hints(*flavor);
|
||||
// Normalize to no lld to avoid asserts.
|
||||
let linker_flavor = match linker_flavor {
|
||||
LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
|
||||
|
Loading…
Reference in New Issue
Block a user