mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 04:26:48 +00:00
Rollup merge of #100552 - petrochenkov:flavorcompat, r=lqd
rustc_target: Add a compatibility layer to separate internal and user-facing linker flavors
I want to do some refactorings in `rustc_target` - merge `lld_flavor` and `linker_is_gnu` into `linker_flavor`, support combination gcc+lld (https://github.com/rust-lang/rust/pull/96827).
This PR adds some compatibility infra that makes that possible without making any changes to user-facing interfaces - `-Clinker-flavor` values and json target specs. (For json target specs this infra may eventually go away since they are not very stable.)
The second commit does some light refactoring of internal linker flavors (applies changes from 53eca42973
that don't require mass-editing target specs).
This commit is contained in:
commit
edf79cb86b
@ -1173,13 +1173,6 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|
||||
// only the linker flavor is known; use the default linker for the selected flavor
|
||||
(None, Some(flavor)) => Some((
|
||||
PathBuf::from(match flavor {
|
||||
LinkerFlavor::Em => {
|
||||
if cfg!(windows) {
|
||||
"emcc.bat"
|
||||
} else {
|
||||
"emcc"
|
||||
}
|
||||
}
|
||||
LinkerFlavor::Gcc => {
|
||||
if cfg!(any(target_os = "solaris", target_os = "illumos")) {
|
||||
// On historical Solaris systems, "cc" may have
|
||||
@ -1194,11 +1187,17 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|
||||
}
|
||||
}
|
||||
LinkerFlavor::Ld => "ld",
|
||||
LinkerFlavor::Msvc => "link.exe",
|
||||
LinkerFlavor::Lld(_) => "lld",
|
||||
LinkerFlavor::PtxLinker => "rust-ptx-linker",
|
||||
LinkerFlavor::BpfLinker => "bpf-linker",
|
||||
LinkerFlavor::L4Bender => "l4-bender",
|
||||
LinkerFlavor::Msvc => "link.exe",
|
||||
LinkerFlavor::EmCc => {
|
||||
if cfg!(windows) {
|
||||
"emcc.bat"
|
||||
} else {
|
||||
"emcc"
|
||||
}
|
||||
}
|
||||
LinkerFlavor::Bpf => "bpf-linker",
|
||||
LinkerFlavor::Ptx => "rust-ptx-linker",
|
||||
}),
|
||||
flavor,
|
||||
)),
|
||||
@ -1208,7 +1207,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|
||||
});
|
||||
|
||||
let flavor = if stem == "emcc" {
|
||||
LinkerFlavor::Em
|
||||
LinkerFlavor::EmCc
|
||||
} else if stem == "gcc"
|
||||
|| stem.ends_with("-gcc")
|
||||
|| stem == "clang"
|
||||
@ -1236,7 +1235,8 @@ 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
|
||||
if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), sess.opts.cg.linker_flavor) {
|
||||
let linker_flavor = sess.opts.cg.linker_flavor.map(LinkerFlavor::from_cli);
|
||||
if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2113,11 +2113,11 @@ fn add_order_independent_options(
|
||||
});
|
||||
}
|
||||
|
||||
if flavor == LinkerFlavor::PtxLinker {
|
||||
if flavor == LinkerFlavor::Ptx {
|
||||
// Provide the linker with fallback to internal `target-cpu`.
|
||||
cmd.arg("--fallback-arch");
|
||||
cmd.arg(&codegen_results.crate_info.target_cpu);
|
||||
} else if flavor == LinkerFlavor::BpfLinker {
|
||||
} else if flavor == LinkerFlavor::Bpf {
|
||||
cmd.arg("--cpu");
|
||||
cmd.arg(&codegen_results.crate_info.target_cpu);
|
||||
cmd.arg("--cpu-features");
|
||||
|
@ -126,29 +126,26 @@ pub fn get_linker<'a>(
|
||||
// to the linker args construction.
|
||||
assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
|
||||
match flavor {
|
||||
LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
|
||||
Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
|
||||
}
|
||||
LinkerFlavor::Em => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
LinkerFlavor::Gcc => {
|
||||
Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false })
|
||||
as Box<dyn Linker>
|
||||
}
|
||||
|
||||
LinkerFlavor::Ld if sess.target.os == "l4re" => {
|
||||
Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
|
||||
}
|
||||
LinkerFlavor::Lld(LldFlavor::Ld)
|
||||
| LinkerFlavor::Lld(LldFlavor::Ld64)
|
||||
| LinkerFlavor::Ld => {
|
||||
Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true })
|
||||
as Box<dyn Linker>
|
||||
}
|
||||
|
||||
LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
|
||||
Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
|
||||
}
|
||||
LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
|
||||
|
||||
LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
|
||||
LinkerFlavor::BpfLinker => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
|
||||
LinkerFlavor::L4Bender => Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>,
|
||||
LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,10 +21,8 @@ use rustc_session::{build_session, getopts, DiagnosticOutput, Session};
|
||||
use rustc_span::edition::{Edition, DEFAULT_EDITION};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::SourceFileHashAlgorithm;
|
||||
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy};
|
||||
use rustc_target::spec::{
|
||||
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel,
|
||||
};
|
||||
use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel};
|
||||
use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::iter::FromIterator;
|
||||
@ -552,7 +550,7 @@ fn test_codegen_options_tracking_hash() {
|
||||
untracked!(link_args, vec![String::from("abc"), String::from("def")]);
|
||||
untracked!(link_self_contained, Some(true));
|
||||
untracked!(linker, Some(PathBuf::from("linker")));
|
||||
untracked!(linker_flavor, Some(LinkerFlavor::Gcc));
|
||||
untracked!(linker_flavor, Some(LinkerFlavorCli::Gcc));
|
||||
untracked!(no_stack_check, true);
|
||||
untracked!(remark, Passes::Some(vec![String::from("pass1"), String::from("pass2")]));
|
||||
untracked!(rpath, true);
|
||||
|
@ -12,8 +12,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
|
||||
use rustc_data_structures::stable_hasher::ToStableHashKey;
|
||||
use rustc_target::abi::{Align, TargetDataLayout};
|
||||
use rustc_target::spec::{LinkerFlavor, SplitDebuginfo, Target, TargetTriple, TargetWarnings};
|
||||
use rustc_target::spec::{PanicStrategy, SanitizerSet, TARGETS};
|
||||
use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
|
||||
use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
|
||||
|
||||
use crate::parse::{CrateCheckConfig, CrateConfig};
|
||||
use rustc_feature::UnstableFeatures;
|
||||
@ -2379,16 +2379,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
||||
}
|
||||
}
|
||||
|
||||
if cg.linker_flavor == Some(LinkerFlavor::L4Bender)
|
||||
&& !nightly_options::is_unstable_enabled(matches)
|
||||
{
|
||||
early_error(
|
||||
error_format,
|
||||
"`l4-bender` linker flavor is unstable, `-Z unstable-options` \
|
||||
flag must also be passed to explicitly use it",
|
||||
);
|
||||
}
|
||||
|
||||
let prints = collect_print_requests(&mut cg, &mut unstable_opts, matches, error_format);
|
||||
|
||||
let cg = cg;
|
||||
|
@ -5,7 +5,7 @@ use crate::lint;
|
||||
use crate::search_paths::SearchPath;
|
||||
use crate::utils::NativeLib;
|
||||
use rustc_errors::LanguageIdentifier;
|
||||
use rustc_target::spec::{CodeModel, LinkerFlavor, MergeFunctions, PanicStrategy, SanitizerSet};
|
||||
use rustc_target::spec::{CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet};
|
||||
use rustc_target::spec::{
|
||||
RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
|
||||
};
|
||||
@ -382,7 +382,7 @@ mod desc {
|
||||
"either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
|
||||
pub const parse_cfprotection: &str = "`none`|`no`|`n` (default), `branch`, `return`, or `full`|`yes`|`y` (equivalent to `branch` and `return`)";
|
||||
pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
|
||||
pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of();
|
||||
pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
|
||||
pub const parse_optimization_fuel: &str = "crate=integer";
|
||||
pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
|
||||
pub const parse_instrument_coverage: &str =
|
||||
@ -763,8 +763,8 @@ mod parse {
|
||||
true
|
||||
}
|
||||
|
||||
pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
|
||||
match v.and_then(LinkerFlavor::from_str) {
|
||||
pub(crate) fn parse_linker_flavor(slot: &mut Option<LinkerFlavorCli>, v: Option<&str>) -> bool {
|
||||
match v.and_then(LinkerFlavorCli::from_str) {
|
||||
Some(lf) => *slot = Some(lf),
|
||||
_ => return false,
|
||||
}
|
||||
@ -1139,7 +1139,7 @@ options! {
|
||||
on C toolchain installed in the system"),
|
||||
linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
|
||||
"system linker to link outputs with"),
|
||||
linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
|
||||
linker_flavor: Option<LinkerFlavorCli> = (None, parse_linker_flavor, [UNTRACKED],
|
||||
"linker flavor"),
|
||||
linker_plugin_lto: LinkerPluginLto = (LinkerPluginLto::Disabled,
|
||||
parse_linker_plugin_lto, [TRACKED],
|
||||
|
@ -2,6 +2,6 @@ use super::{wasm32_unknown_emscripten, LinkerFlavor, Target};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut target = wasm32_unknown_emscripten::target();
|
||||
target.add_post_link_args(LinkerFlavor::Em, &["-sWASM=0", "--memory-init-file", "0"]);
|
||||
target.add_post_link_args(LinkerFlavor::EmCc, &["-sWASM=0", "--memory-init-file", "0"]);
|
||||
target
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ pub fn opts(endian: Endian) -> TargetOptions {
|
||||
TargetOptions {
|
||||
allow_asm: true,
|
||||
endian,
|
||||
linker_flavor: LinkerFlavor::BpfLinker,
|
||||
linker_flavor: LinkerFlavor::Bpf,
|
||||
atomic_cas: false,
|
||||
dynamic_linking: true,
|
||||
no_builtins: true,
|
||||
|
@ -4,7 +4,7 @@ pub fn opts() -> TargetOptions {
|
||||
TargetOptions {
|
||||
os: "l4re".into(),
|
||||
env: "uclibc".into(),
|
||||
linker_flavor: LinkerFlavor::L4Bender,
|
||||
linker_flavor: LinkerFlavor::Ld,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
linker: Some("l4-bender".into()),
|
||||
linker_is_gnu: false,
|
||||
|
@ -92,14 +92,24 @@ mod windows_uwp_msvc_base;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub enum LinkerFlavor {
|
||||
Em,
|
||||
Gcc,
|
||||
L4Bender,
|
||||
Ld,
|
||||
Msvc,
|
||||
Lld(LldFlavor),
|
||||
PtxLinker,
|
||||
Msvc,
|
||||
EmCc,
|
||||
Bpf,
|
||||
Ptx,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub enum LinkerFlavorCli {
|
||||
Gcc,
|
||||
Ld,
|
||||
Lld(LldFlavor),
|
||||
Msvc,
|
||||
Em,
|
||||
BpfLinker,
|
||||
PtxLinker,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
@ -137,19 +147,40 @@ impl ToJson for LldFlavor {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for LinkerFlavor {
|
||||
fn to_json(&self) -> Json {
|
||||
self.desc().to_json()
|
||||
impl LinkerFlavor {
|
||||
pub fn from_cli(cli: LinkerFlavorCli) -> LinkerFlavor {
|
||||
match cli {
|
||||
LinkerFlavorCli::Gcc => LinkerFlavor::Gcc,
|
||||
LinkerFlavorCli::Ld => LinkerFlavor::Ld,
|
||||
LinkerFlavorCli::Lld(lld_flavor) => LinkerFlavor::Lld(lld_flavor),
|
||||
LinkerFlavorCli::Msvc => LinkerFlavor::Msvc,
|
||||
LinkerFlavorCli::Em => LinkerFlavor::EmCc,
|
||||
LinkerFlavorCli::BpfLinker => LinkerFlavor::Bpf,
|
||||
LinkerFlavorCli::PtxLinker => LinkerFlavor::Ptx,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_cli(self) -> LinkerFlavorCli {
|
||||
match self {
|
||||
LinkerFlavor::Gcc => LinkerFlavorCli::Gcc,
|
||||
LinkerFlavor::Ld => LinkerFlavorCli::Ld,
|
||||
LinkerFlavor::Lld(lld_flavor) => LinkerFlavorCli::Lld(lld_flavor),
|
||||
LinkerFlavor::Msvc => LinkerFlavorCli::Msvc,
|
||||
LinkerFlavor::EmCc => LinkerFlavorCli::Em,
|
||||
LinkerFlavor::Bpf => LinkerFlavorCli::BpfLinker,
|
||||
LinkerFlavor::Ptx => LinkerFlavorCli::PtxLinker,
|
||||
}
|
||||
}
|
||||
}
|
||||
macro_rules! flavor_mappings {
|
||||
($((($($flavor:tt)*), $string:expr),)*) => (
|
||||
impl LinkerFlavor {
|
||||
|
||||
macro_rules! linker_flavor_cli_impls {
|
||||
($(($($flavor:tt)*) $string:literal)*) => (
|
||||
impl LinkerFlavorCli {
|
||||
pub const fn one_of() -> &'static str {
|
||||
concat!("one of: ", $($string, " ",)*)
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> Option<Self> {
|
||||
pub fn from_str(s: &str) -> Option<LinkerFlavorCli> {
|
||||
Some(match s {
|
||||
$($string => $($flavor)*,)*
|
||||
_ => return None,
|
||||
@ -165,18 +196,23 @@ macro_rules! flavor_mappings {
|
||||
)
|
||||
}
|
||||
|
||||
flavor_mappings! {
|
||||
((LinkerFlavor::Em), "em"),
|
||||
((LinkerFlavor::Gcc), "gcc"),
|
||||
((LinkerFlavor::L4Bender), "l4-bender"),
|
||||
((LinkerFlavor::Ld), "ld"),
|
||||
((LinkerFlavor::Msvc), "msvc"),
|
||||
((LinkerFlavor::PtxLinker), "ptx-linker"),
|
||||
((LinkerFlavor::BpfLinker), "bpf-linker"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
|
||||
linker_flavor_cli_impls! {
|
||||
(LinkerFlavorCli::Gcc) "gcc"
|
||||
(LinkerFlavorCli::Ld) "ld"
|
||||
(LinkerFlavorCli::Lld(LldFlavor::Ld)) "ld.lld"
|
||||
(LinkerFlavorCli::Lld(LldFlavor::Ld64)) "ld64.lld"
|
||||
(LinkerFlavorCli::Lld(LldFlavor::Link)) "lld-link"
|
||||
(LinkerFlavorCli::Lld(LldFlavor::Wasm)) "wasm-ld"
|
||||
(LinkerFlavorCli::Msvc) "msvc"
|
||||
(LinkerFlavorCli::Em) "em"
|
||||
(LinkerFlavorCli::BpfLinker) "bpf-linker"
|
||||
(LinkerFlavorCli::PtxLinker) "ptx-linker"
|
||||
}
|
||||
|
||||
impl ToJson for LinkerFlavorCli {
|
||||
fn to_json(&self) -> Json {
|
||||
self.desc().to_json()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
|
||||
@ -467,6 +503,7 @@ impl fmt::Display for LinkOutputKind {
|
||||
}
|
||||
|
||||
pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<StaticCow<str>>>;
|
||||
pub type LinkArgsCli = BTreeMap<LinkerFlavorCli, Vec<StaticCow<str>>>;
|
||||
|
||||
/// Which kind of debuginfo does the target use?
|
||||
///
|
||||
@ -1210,19 +1247,21 @@ pub struct TargetOptions {
|
||||
pub abi: StaticCow<str>,
|
||||
/// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
|
||||
pub vendor: StaticCow<str>,
|
||||
/// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
|
||||
/// on the command line. Defaults to `LinkerFlavor::Gcc`.
|
||||
pub linker_flavor: LinkerFlavor,
|
||||
|
||||
/// Linker to invoke
|
||||
pub linker: Option<StaticCow<str>>,
|
||||
|
||||
/// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
|
||||
/// on the command line. Defaults to `LinkerFlavor::Gcc`.
|
||||
pub linker_flavor: LinkerFlavor,
|
||||
linker_flavor_json: LinkerFlavorCli,
|
||||
/// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker
|
||||
/// without clarifying its flavor in any way.
|
||||
/// FIXME: Merge this into `LinkerFlavor`.
|
||||
pub lld_flavor: LldFlavor,
|
||||
/// Whether the linker support GNU-like arguments such as -O. Defaults to true.
|
||||
/// FIXME: Merge this into `LinkerFlavor`.
|
||||
pub linker_is_gnu: bool,
|
||||
|
||||
/// Linker arguments that are passed *before* any user-defined libraries.
|
||||
pub pre_link_args: LinkArgs,
|
||||
/// Objects to link before and after all other object code.
|
||||
pub pre_link_objects: CrtObjects,
|
||||
pub post_link_objects: CrtObjects,
|
||||
@ -1231,24 +1270,31 @@ pub struct TargetOptions {
|
||||
pub post_link_objects_self_contained: CrtObjects,
|
||||
pub link_self_contained: LinkSelfContainedDefault,
|
||||
|
||||
/// Linker arguments that are passed *before* any user-defined libraries.
|
||||
pub pre_link_args: LinkArgs,
|
||||
pre_link_args_json: LinkArgsCli,
|
||||
/// Linker arguments that are unconditionally passed after any
|
||||
/// user-defined but before post-link objects. Standard platform
|
||||
/// libraries that should be always be linked to, usually go here.
|
||||
pub late_link_args: LinkArgs,
|
||||
late_link_args_json: LinkArgsCli,
|
||||
/// Linker arguments used in addition to `late_link_args` if at least one
|
||||
/// Rust dependency is dynamically linked.
|
||||
pub late_link_args_dynamic: LinkArgs,
|
||||
late_link_args_dynamic_json: LinkArgsCli,
|
||||
/// Linker arguments used in addition to `late_link_args` if all Rust
|
||||
/// dependencies are statically linked.
|
||||
pub late_link_args_static: LinkArgs,
|
||||
late_link_args_static_json: LinkArgsCli,
|
||||
/// Linker arguments that are unconditionally passed *after* any
|
||||
/// user-defined libraries.
|
||||
pub post_link_args: LinkArgs,
|
||||
post_link_args_json: LinkArgsCli,
|
||||
|
||||
/// Optional link script applied to `dylib` and `executable` crate types.
|
||||
/// This is a string containing the script, not a path. Can only be applied
|
||||
/// to linkers where `linker_is_gnu` is true.
|
||||
pub link_script: Option<StaticCow<str>>,
|
||||
|
||||
/// Environment variables to be set for the linker invocation.
|
||||
pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
|
||||
/// Environment variables to be removed for the linker invocation.
|
||||
@ -1333,8 +1379,6 @@ pub struct TargetOptions {
|
||||
/// Default supported version of DWARF on this platform.
|
||||
/// Useful because some platforms (osx, bsd) only want up to DWARF2.
|
||||
pub default_dwarf_version: u32,
|
||||
/// Whether the linker support GNU-like arguments such as -O. Defaults to true.
|
||||
pub linker_is_gnu: bool,
|
||||
/// The MinGW toolchain has a known issue that prevents it from correctly
|
||||
/// handling COFF object files with more than 2<sup>15</sup> sections. Since each weak
|
||||
/// symbol needs its own COMDAT section, weak linkage implies a large
|
||||
@ -1532,11 +1576,7 @@ fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'stati
|
||||
LinkerFlavor::Lld(lld_flavor) => {
|
||||
panic!("add_link_args: use non-LLD flavor for {:?}", lld_flavor)
|
||||
}
|
||||
LinkerFlavor::Gcc
|
||||
| LinkerFlavor::Em
|
||||
| LinkerFlavor::L4Bender
|
||||
| LinkerFlavor::BpfLinker
|
||||
| LinkerFlavor::PtxLinker => {}
|
||||
LinkerFlavor::Gcc | LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1554,6 +1594,36 @@ impl TargetOptions {
|
||||
fn add_post_link_args(&mut self, flavor: LinkerFlavor, args: &[&'static str]) {
|
||||
add_link_args(&mut self.post_link_args, flavor, args);
|
||||
}
|
||||
|
||||
fn update_from_cli(&mut self) {
|
||||
self.linker_flavor = LinkerFlavor::from_cli(self.linker_flavor_json);
|
||||
for (args, args_json) in [
|
||||
(&mut self.pre_link_args, &self.pre_link_args_json),
|
||||
(&mut self.late_link_args, &self.late_link_args_json),
|
||||
(&mut self.late_link_args_dynamic, &self.late_link_args_dynamic_json),
|
||||
(&mut self.late_link_args_static, &self.late_link_args_static_json),
|
||||
(&mut self.post_link_args, &self.post_link_args_json),
|
||||
] {
|
||||
*args = args_json
|
||||
.iter()
|
||||
.map(|(flavor, args)| (LinkerFlavor::from_cli(*flavor), args.clone()))
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
fn update_to_cli(&mut self) {
|
||||
self.linker_flavor_json = self.linker_flavor.to_cli();
|
||||
for (args, args_json) in [
|
||||
(&self.pre_link_args, &mut self.pre_link_args_json),
|
||||
(&self.late_link_args, &mut self.late_link_args_json),
|
||||
(&self.late_link_args_dynamic, &mut self.late_link_args_dynamic_json),
|
||||
(&self.late_link_args_static, &mut self.late_link_args_static_json),
|
||||
(&self.post_link_args, &mut self.post_link_args_json),
|
||||
] {
|
||||
*args_json =
|
||||
args.iter().map(|(flavor, args)| (flavor.to_cli(), args.clone())).collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TargetOptions {
|
||||
@ -1568,11 +1638,11 @@ impl Default for TargetOptions {
|
||||
env: "".into(),
|
||||
abi: "".into(),
|
||||
vendor: "unknown".into(),
|
||||
linker_flavor: LinkerFlavor::Gcc,
|
||||
linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
|
||||
linker_flavor: LinkerFlavor::Gcc,
|
||||
linker_flavor_json: LinkerFlavorCli::Gcc,
|
||||
lld_flavor: LldFlavor::Ld,
|
||||
pre_link_args: LinkArgs::new(),
|
||||
post_link_args: LinkArgs::new(),
|
||||
linker_is_gnu: true,
|
||||
link_script: None,
|
||||
asm_args: cvs![],
|
||||
cpu: "generic".into(),
|
||||
@ -1599,7 +1669,6 @@ impl Default for TargetOptions {
|
||||
is_like_msvc: false,
|
||||
is_like_wasm: false,
|
||||
default_dwarf_version: 4,
|
||||
linker_is_gnu: true,
|
||||
allows_weak_linkage: true,
|
||||
has_rpath: false,
|
||||
no_default_libraries: true,
|
||||
@ -1612,9 +1681,16 @@ impl Default for TargetOptions {
|
||||
pre_link_objects_self_contained: Default::default(),
|
||||
post_link_objects_self_contained: Default::default(),
|
||||
link_self_contained: LinkSelfContainedDefault::False,
|
||||
pre_link_args: LinkArgs::new(),
|
||||
pre_link_args_json: LinkArgsCli::new(),
|
||||
late_link_args: LinkArgs::new(),
|
||||
late_link_args_json: LinkArgsCli::new(),
|
||||
late_link_args_dynamic: LinkArgs::new(),
|
||||
late_link_args_dynamic_json: LinkArgsCli::new(),
|
||||
late_link_args_static: LinkArgs::new(),
|
||||
late_link_args_static_json: LinkArgsCli::new(),
|
||||
post_link_args: LinkArgs::new(),
|
||||
post_link_args_json: LinkArgsCli::new(),
|
||||
link_env: cvs![],
|
||||
link_env_remove: cvs![],
|
||||
archive_format: "gnu".into(),
|
||||
@ -2019,13 +2095,13 @@ impl Target {
|
||||
Some(Ok(()))
|
||||
})).unwrap_or(Ok(()))
|
||||
} );
|
||||
($key_name:ident, LinkerFlavor) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
|
||||
match LinkerFlavor::from_str(s) {
|
||||
($key_name:ident = $json_name:expr, LinkerFlavor) => ( {
|
||||
let name = $json_name;
|
||||
obj.remove(name).and_then(|o| o.as_str().and_then(|s| {
|
||||
match LinkerFlavorCli::from_str(s) {
|
||||
Some(linker_flavor) => base.$key_name = linker_flavor,
|
||||
_ => return Some(Err(format!("'{}' is not a valid value for linker-flavor. \
|
||||
Use {}", s, LinkerFlavor::one_of()))),
|
||||
Use {}", s, LinkerFlavorCli::one_of()))),
|
||||
}
|
||||
Some(Ok(()))
|
||||
})).unwrap_or(Ok(()))
|
||||
@ -2106,14 +2182,14 @@ impl Target {
|
||||
base.$key_name = args;
|
||||
}
|
||||
} );
|
||||
($key_name:ident, link_args) => ( {
|
||||
let name = (stringify!($key_name)).replace("_", "-");
|
||||
if let Some(val) = obj.remove(&name) {
|
||||
($key_name:ident = $json_name:expr, link_args) => ( {
|
||||
let name = $json_name;
|
||||
if let Some(val) = obj.remove(name) {
|
||||
let obj = val.as_object().ok_or_else(|| format!("{}: expected a \
|
||||
JSON object with fields per linker-flavor.", name))?;
|
||||
let mut args = LinkArgs::new();
|
||||
let mut args = LinkArgsCli::new();
|
||||
for (k, v) in obj {
|
||||
let flavor = LinkerFlavor::from_str(&k).ok_or_else(|| {
|
||||
let flavor = LinkerFlavorCli::from_str(&k).ok_or_else(|| {
|
||||
format!("{}: '{}' is not a valid value for linker-flavor. \
|
||||
Use 'em', 'gcc', 'ld' or 'msvc'", name, k)
|
||||
})?;
|
||||
@ -2199,19 +2275,20 @@ impl Target {
|
||||
key!(env);
|
||||
key!(abi);
|
||||
key!(vendor);
|
||||
key!(linker_flavor, LinkerFlavor)?;
|
||||
key!(linker, optional);
|
||||
key!(linker_flavor_json = "linker-flavor", LinkerFlavor)?;
|
||||
key!(lld_flavor, LldFlavor)?;
|
||||
key!(linker_is_gnu, bool);
|
||||
key!(pre_link_objects = "pre-link-objects", link_objects);
|
||||
key!(post_link_objects = "post-link-objects", link_objects);
|
||||
key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects);
|
||||
key!(post_link_objects_self_contained = "post-link-objects-fallback", link_objects);
|
||||
key!(link_self_contained = "crt-objects-fallback", link_self_contained)?;
|
||||
key!(pre_link_args, link_args);
|
||||
key!(late_link_args, link_args);
|
||||
key!(late_link_args_dynamic, link_args);
|
||||
key!(late_link_args_static, link_args);
|
||||
key!(post_link_args, link_args);
|
||||
key!(pre_link_args_json = "pre-link-args", link_args);
|
||||
key!(late_link_args_json = "late-link-args", link_args);
|
||||
key!(late_link_args_dynamic_json = "late-link-args-dynamic", link_args);
|
||||
key!(late_link_args_static_json = "late-link-args-static", link_args);
|
||||
key!(post_link_args_json = "post-link-args", link_args);
|
||||
key!(link_script, optional);
|
||||
key!(link_env, env);
|
||||
key!(link_env_remove, list);
|
||||
@ -2239,7 +2316,6 @@ impl Target {
|
||||
key!(is_like_msvc, bool);
|
||||
key!(is_like_wasm, bool);
|
||||
key!(default_dwarf_version, u32);
|
||||
key!(linker_is_gnu, bool);
|
||||
key!(allows_weak_linkage, bool);
|
||||
key!(has_rpath, bool);
|
||||
key!(no_default_libraries, bool);
|
||||
@ -2296,6 +2372,8 @@ impl Target {
|
||||
// This can cause unfortunate ICEs later down the line.
|
||||
return Err("may not set is_builtin for targets not built-in".into());
|
||||
}
|
||||
base.update_from_cli();
|
||||
|
||||
// Each field should have been read using `Json::remove` so any keys remaining are unused.
|
||||
let remaining_keys = obj.keys();
|
||||
Ok((
|
||||
@ -2387,42 +2465,44 @@ impl ToJson for Target {
|
||||
fn to_json(&self) -> Json {
|
||||
let mut d = serde_json::Map::new();
|
||||
let default: TargetOptions = Default::default();
|
||||
let mut target = self.clone();
|
||||
target.update_to_cli();
|
||||
|
||||
macro_rules! target_val {
|
||||
($attr:ident) => {{
|
||||
let name = (stringify!($attr)).replace("_", "-");
|
||||
d.insert(name, self.$attr.to_json());
|
||||
d.insert(name, target.$attr.to_json());
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! target_option_val {
|
||||
($attr:ident) => {{
|
||||
let name = (stringify!($attr)).replace("_", "-");
|
||||
if default.$attr != self.$attr {
|
||||
d.insert(name, self.$attr.to_json());
|
||||
if default.$attr != target.$attr {
|
||||
d.insert(name, target.$attr.to_json());
|
||||
}
|
||||
}};
|
||||
($attr:ident, $key_name:expr) => {{
|
||||
let name = $key_name;
|
||||
if default.$attr != self.$attr {
|
||||
d.insert(name.into(), self.$attr.to_json());
|
||||
($attr:ident, $json_name:expr) => {{
|
||||
let name = $json_name;
|
||||
if default.$attr != target.$attr {
|
||||
d.insert(name.into(), target.$attr.to_json());
|
||||
}
|
||||
}};
|
||||
(link_args - $attr:ident) => {{
|
||||
let name = (stringify!($attr)).replace("_", "-");
|
||||
if default.$attr != self.$attr {
|
||||
let obj = self
|
||||
(link_args - $attr:ident, $json_name:expr) => {{
|
||||
let name = $json_name;
|
||||
if default.$attr != target.$attr {
|
||||
let obj = target
|
||||
.$attr
|
||||
.iter()
|
||||
.map(|(k, v)| (k.desc().to_string(), v.clone()))
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
d.insert(name, obj.to_json());
|
||||
d.insert(name.to_string(), obj.to_json());
|
||||
}
|
||||
}};
|
||||
(env - $attr:ident) => {{
|
||||
let name = (stringify!($attr)).replace("_", "-");
|
||||
if default.$attr != self.$attr {
|
||||
let obj = self
|
||||
if default.$attr != target.$attr {
|
||||
let obj = target
|
||||
.$attr
|
||||
.iter()
|
||||
.map(|&(ref k, ref v)| format!("{k}={v}"))
|
||||
@ -2444,19 +2524,20 @@ impl ToJson for Target {
|
||||
target_option_val!(env);
|
||||
target_option_val!(abi);
|
||||
target_option_val!(vendor);
|
||||
target_option_val!(linker_flavor);
|
||||
target_option_val!(linker);
|
||||
target_option_val!(linker_flavor_json, "linker-flavor");
|
||||
target_option_val!(lld_flavor);
|
||||
target_option_val!(linker_is_gnu);
|
||||
target_option_val!(pre_link_objects);
|
||||
target_option_val!(post_link_objects);
|
||||
target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback");
|
||||
target_option_val!(post_link_objects_self_contained, "post-link-objects-fallback");
|
||||
target_option_val!(link_self_contained, "crt-objects-fallback");
|
||||
target_option_val!(link_args - pre_link_args);
|
||||
target_option_val!(link_args - late_link_args);
|
||||
target_option_val!(link_args - late_link_args_dynamic);
|
||||
target_option_val!(link_args - late_link_args_static);
|
||||
target_option_val!(link_args - post_link_args);
|
||||
target_option_val!(link_args - pre_link_args_json, "pre-link-args");
|
||||
target_option_val!(link_args - late_link_args_json, "late-link-args");
|
||||
target_option_val!(link_args - late_link_args_dynamic_json, "late-link-args-dynamic");
|
||||
target_option_val!(link_args - late_link_args_static_json, "late-link-args-static");
|
||||
target_option_val!(link_args - post_link_args_json, "post-link-args");
|
||||
target_option_val!(link_script);
|
||||
target_option_val!(env - link_env);
|
||||
target_option_val!(link_env_remove);
|
||||
@ -2485,7 +2566,6 @@ impl ToJson for Target {
|
||||
target_option_val!(is_like_msvc);
|
||||
target_option_val!(is_like_wasm);
|
||||
target_option_val!(default_dwarf_version);
|
||||
target_option_val!(linker_is_gnu);
|
||||
target_option_val!(allows_weak_linkage);
|
||||
target_option_val!(has_rpath);
|
||||
target_option_val!(no_default_libraries);
|
||||
|
@ -10,7 +10,7 @@ pub fn target() -> Target {
|
||||
options: TargetOptions {
|
||||
os: "cuda".into(),
|
||||
vendor: "nvidia".into(),
|
||||
linker_flavor: LinkerFlavor::PtxLinker,
|
||||
linker_flavor: LinkerFlavor::Ptx,
|
||||
// The linker can be installed from `crates.io`.
|
||||
linker: Some("rust-ptx-linker".into()),
|
||||
linker_is_gnu: false,
|
||||
|
@ -2,9 +2,11 @@ use super::super::*;
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
// Test target self-consistency and JSON encoding/decoding roundtrip.
|
||||
pub(super) fn test_target(target: Target, triple: &str) {
|
||||
pub(super) fn test_target(mut target: Target, triple: &str) {
|
||||
let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j);
|
||||
target.update_to_cli();
|
||||
target.check_consistency(triple);
|
||||
assert_eq!(Target::from_json(target.to_json()).map(|(j, _)| j), Ok(target));
|
||||
assert_eq!(recycled_target, Ok(target));
|
||||
}
|
||||
|
||||
impl Target {
|
||||
@ -22,10 +24,9 @@ impl Target {
|
||||
assert_eq!(self.is_like_osx, matches!(self.lld_flavor, LldFlavor::Ld64));
|
||||
assert_eq!(self.is_like_msvc, matches!(self.lld_flavor, LldFlavor::Link));
|
||||
assert_eq!(self.is_like_wasm, matches!(self.lld_flavor, LldFlavor::Wasm));
|
||||
assert_eq!(self.os == "l4re", matches!(self.linker_flavor, LinkerFlavor::L4Bender));
|
||||
assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::Em));
|
||||
assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::BpfLinker));
|
||||
assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::PtxLinker));
|
||||
assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::EmCc));
|
||||
assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::Bpf));
|
||||
assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::Ptx));
|
||||
|
||||
for args in [
|
||||
&self.pre_link_args,
|
||||
@ -65,17 +66,14 @@ impl Target {
|
||||
LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc
|
||||
)
|
||||
}
|
||||
(LinkerFlavor::L4Bender, LldFlavor::Ld) => {
|
||||
assert_matches!(flavor, LinkerFlavor::L4Bender)
|
||||
(LinkerFlavor::EmCc, LldFlavor::Wasm) => {
|
||||
assert_matches!(flavor, LinkerFlavor::EmCc)
|
||||
}
|
||||
(LinkerFlavor::Em, LldFlavor::Wasm) => {
|
||||
assert_matches!(flavor, LinkerFlavor::Em)
|
||||
(LinkerFlavor::Bpf, LldFlavor::Ld) => {
|
||||
assert_matches!(flavor, LinkerFlavor::Bpf)
|
||||
}
|
||||
(LinkerFlavor::BpfLinker, LldFlavor::Ld) => {
|
||||
assert_matches!(flavor, LinkerFlavor::BpfLinker)
|
||||
}
|
||||
(LinkerFlavor::PtxLinker, LldFlavor::Ld) => {
|
||||
assert_matches!(flavor, LinkerFlavor::PtxLinker)
|
||||
(LinkerFlavor::Ptx, LldFlavor::Ld) => {
|
||||
assert_matches!(flavor, LinkerFlavor::Ptx)
|
||||
}
|
||||
flavors => unreachable!("unexpected flavor combination: {:?}", flavors),
|
||||
}
|
||||
|
@ -5,13 +5,13 @@ pub fn target() -> Target {
|
||||
// Reset flags for non-Em flavors back to empty to satisfy sanity checking tests.
|
||||
let pre_link_args = LinkArgs::new();
|
||||
let post_link_args = TargetOptions::link_args(
|
||||
LinkerFlavor::Em,
|
||||
LinkerFlavor::EmCc,
|
||||
&["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"],
|
||||
);
|
||||
|
||||
let opts = TargetOptions {
|
||||
os: "emscripten".into(),
|
||||
linker_flavor: LinkerFlavor::Em,
|
||||
linker_flavor: LinkerFlavor::EmCc,
|
||||
// emcc emits two files - a .js file to instantiate the wasm and supply platform
|
||||
// functionality, and a .wasm file.
|
||||
exe_suffix: ".js".into(),
|
||||
|
Loading…
Reference in New Issue
Block a user