diff options
| author | bors <bors@rust-lang.org> | 2017-04-10 18:00:23 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-04-10 18:00:23 +0000 |
| commit | 3b5754e5ce73d24c6684b3ed0c68a557dfdd2f52 (patch) | |
| tree | 98b453d8c1e412c1ad0e74b0718a6d86deebbeae | |
| parent | 8493dd6d6e8f5e1280ae3dc05135a7e2897c36ac (diff) | |
| parent | e192fb3d892f04e90a78378bd772cc003304a887 (diff) | |
| download | rust-3b5754e5ce73d24c6684b3ed0c68a557dfdd2f52.tar.gz rust-3b5754e5ce73d24c6684b3ed0c68a557dfdd2f52.zip | |
Auto merge of #40018 - japaric:ld, r=alexcrichton
-Z linker-flavor (Please read the commit message first) This PR is an alternative to rust-lang/rust#36120 (internal lld linker). The main goal of this PR is to make it *possible* to use LLD as a linker to allow out of tree experimentation. Now that LLD is going to be shipped with LLVM 4.0, it should become easier to get a hold of LLD (hopefully, it will be packaged by Linux distros soon). Since LLD is a multiarch linker, it has the potential to make cross compilation easier (less tools need to be installed). Supposedly, LLD is also faster than the gold linker so LLD may improve build times where link times are significant (e.g. 100% incremental compilation reuse). The place where LLD shines is at linking Rust programs that don't depend on system libraries. For example, here's how you would link a bare metal ARM Cortex-M program: ``` $ xargo rustc --target thumbv7m-none-eabi -- -Z linker-flavor=ld -C linker=ld.lld -Z print-link-args "ld.lld" \ "-L" \ "$XARGO_HOME/lib/rustlib/thumbv7m-none-eabi/lib" \ "$PWD/target/thumbv7m-none-eabi/debug/deps/app-de1f86df314ad68c.0.o" \ "-o" \ "$PWD/target/thumbv7m-none-eabi/debug/deps/app-de1f86df314ad68c" \ "--gc-sections" \ "-L" \ "$PWD/target/thumbv7m-none-eabi/debug/deps" \ "-L" \ "$PWD/target/debug/deps" \ "-L" \ "$XARGO_HOME/lib/rustlib/thumbv7m-none-eabi/lib" \ "-Bstatic" \ "-Bdynamic" \ "$XARGO_HOME/lib/rustlib/thumbv7m-none-eabi/lib/libcore-11670d2bd4951fa7.rlib" $ file target/thumbv7m-none-eabi/debug/app app: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped, with debug_info ``` This doesn't require installing the `arm-none-eabi-gcc` toolchain. Even cooler (but I'm biased) is that you can link Rust programs that use [`steed`] (`steed` is a `std` re-implementation free of C dependencies for Linux systems) instead of `std` for a bunch of different architectures without having to install a single cross toolchain. [`steed`]: https://github.com/japaric/steed ``` $ xargo rustc --target aarch64-unknown-linux-steed --example hello --release -- -Z print-link-args "ld.lld" \ "-L" \ "$XARGO_HOME/lib/rustlib/aarch64-unknown-linux-steed/lib" \ "$PWD/target/aarch64-unknown-linux-steed/release/examples/hello-80c130ad884c0f8f.0.o" \ "-o" \ "$PWD/target/aarch64-unknown-linux-steed/release/examples/hello-80c130ad884c0f8f" \ "--gc-sections" \ "-L" \ "$PWD/target/aarch64-unknown-linux-steed/release/deps" \ "-L" \ "$PWD/target/release/deps" \ "-L" \ "$XARGO_HOME/lib/rustlib/aarch64-unknown-linux-steed/lib" \ "-Bstatic" \ "-Bdynamic" \ "/tmp/rustc.lAybk9Ltx93Q/libcompiler_builtins-589aede02de78434.rlib" $ file target/aarch64-unknown-linux-steed/release/examples/hello hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, not stripped, with debug_info ``` All these targets (architectures) worked with LLD: - [aarch64-unknown-linux-steed](https://github.com/japaric/steed/blob/lld/docker/aarch64-unknown-linux-steed.json) - [arm-unknown-linux-steedeabi](https://github.com/japaric/steed/blob/lld/docker/arm-unknown-linux-steedeabi.json) - [arm-unknown-linux-steedeabihf](https://github.com/japaric/steed/blob/lld/docker/arm-unknown-linux-steedeabihf.json) - [armv7-unknown-linux-steedeabihf](https://github.com/japaric/steed/blob/lld/docker/armv7-unknown-linux-steedeabihf.json) - [i686-unknown-linux-steed](https://github.com/japaric/steed/blob/lld/docker/i686-unknown-linux-steed.json) - [mips-unknown-linux-steed](https://github.com/japaric/steed/blob/lld/docker/mips-unknown-linux-steed.json) - [mipsel-unknown-linux-steed](https://github.com/japaric/steed/blob/lld/docker/mipsel-unknown-linux-steed.json) - [powerpc-unknown-linux-steed](https://github.com/japaric/steed/blob/lld/docker/powerpc-unknown-linux-steed.json) - [powerpc64-unknown-linux-steed](https://github.com/japaric/steed/blob/lld/docker/powerpc64-unknown-linux-steed.json) - [x86_64-unknown-linux-steed](https://github.com/japaric/steed/blob/lld/docker/x86_64-unknown-linux-steed.json) --- The case where lld is unergonomic is linking binaries that depend on system libraries. Like "Hello, world" for `x86_64-unknown-linux-gnu`. Because you have to pass as linker arguments: the path to the startup objects, the path to the dynamic linker and the library search paths. And all those are system specific so they can't be encoded in the target itself. ``` $ cargo \ rustc \ --release \ -- \ -C \ linker=ld.lld \ -Z \ linker-flavor=ld \ -C \ link-args='-dynamic-linker /lib64/ld-linux-x86-64.so.2 -L/usr/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1 /usr/lib/Scrt1.o /usr/lib/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtbeginS.o /usr/lib/gcc/x86_64-pc-linux-gnu/6.3.1/crtendS.o /usr/lib/crtn.o' ``` --- Another case where `-Z linker-flavor` may come in handy is directly calling Solaris' linker which is also a multiarch linker (or so I have heard). cc @binarycrusader cc @alexcrichton Heads up: [breaking-change] due to changes in the target specification format.
92 files changed, 682 insertions, 240 deletions
diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index d86766bac02..216daddabcd 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -108,6 +108,7 @@ - [link_llvm_intrinsics](link-llvm-intrinsics.md) - [linkage](linkage.md) - [linked_list_extras](linked-list-extras.md) +- [linker_flavor](linker-flavor.md) - [log_syntax](log-syntax.md) - [lookup_host](lookup-host.md) - [loop_break_value](loop-break-value.md) diff --git a/src/doc/unstable-book/src/linker-flavor.md b/src/doc/unstable-book/src/linker-flavor.md new file mode 100644 index 00000000000..39659602e01 --- /dev/null +++ b/src/doc/unstable-book/src/linker-flavor.md @@ -0,0 +1,61 @@ +# `linker-flavor` + +The tracking issue for this feature is: None + +------------------------ + +Every `rustc` target defaults to some linker. For example, Linux targets default +to gcc. In some cases, you may want to override the default; you can do that +with the unstable CLI argument: `-Z linker-flavor`. + +Here how you would use this flag to link a Rust binary for the +`thumbv7m-none-eabi` using LLD instead of GCC. + +``` text +$ xargo rustc --target thumbv7m-none-eabi -- \ + -C linker=ld.lld \ + -Z linker-flavor=ld \ + -Z print-link-args | tr ' ' '\n' +"ld.lld" +"-L" +"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib" +"$PWD/target/thumbv7m-none-eabi/debug/deps/app-512e9dbf385f233c.0.o" +"-o" +"$PWD/target/thumbv7m-none-eabi/debug/deps/app-512e9dbf385f233c" +"--gc-sections" +"-L" +"$PWD/target/thumbv7m-none-eabi/debug/deps" +"-L" +"$PWD/target/debug/deps" +"-L" +"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib" +"-Bstatic" +"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib/libcore-e1ccb7dfb1cb9ebb.rlib" +"-Bdynamic" +``` + +Whereas the default is: + +``` text +$ xargo rustc --target thumbv7m-none-eabi -- \ + -C link-arg=-nostartfiles \ + -Z print-link-args | tr ' ' '\n' +"arm-none-eabi-gcc" +"-L" +"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib" +"$PWD/target/thumbv7m-none-eabi/debug/deps/app-961e39416baa38d9.0.o" +"-o" +"$PWD/target/thumbv7m-none-eabi/debug/deps/app-961e39416baa38d9" +"-Wl,--gc-sections" +"-nodefaultlibs" +"-L" +"$PWD/target/thumbv7m-none-eabi/debug/deps" +"-L" +"$PWD/target/debug/deps" +"-L" +"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib" +"-Wl,-Bstatic" +"$SYSROOT/lib/rustlib/thumbv7m-none-eabi/lib/libcore-e1ccb7dfb1cb9ebb.rlib" +"-nostartfiles" +"-Wl,-Bdynamic" +``` diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index a0603c57952..ef825a6854c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -19,7 +19,7 @@ pub use self::DebugInfoLevel::*; use session::{early_error, early_warn, Session}; use session::search_paths::SearchPaths; -use rustc_back::PanicStrategy; +use rustc_back::{LinkerFlavor, PanicStrategy}; use rustc_back::target::Target; use lint; use middle::cstore; @@ -641,12 +641,14 @@ macro_rules! options { Some("either `panic` or `abort`"); pub const parse_sanitizer: Option<&'static str> = Some("one of: `address`, `leak`, `memory` or `thread`"); + pub const parse_linker_flavor: Option<&'static str> = + Some(::rustc_back::LinkerFlavor::one_of()); } #[allow(dead_code)] mod $mod_set { use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer}; - use rustc_back::PanicStrategy; + use rustc_back::{LinkerFlavor, PanicStrategy}; $( pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { @@ -777,6 +779,14 @@ macro_rules! options { } true } + + fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool { + match v.and_then(LinkerFlavor::from_str) { + Some(lf) => *slote = Some(lf), + _ => return false, + } + true + } } ) } @@ -979,6 +989,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "pass `-install_name @rpath/...` to the macOS linker"), sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED], "Use a sanitizer"), + linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED], + "Linker flavor"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 3ba82f34c32..70b2809ccbe 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -36,7 +36,7 @@ use syntax::{ast, codemap}; use syntax::feature_gate::AttributeType; use syntax_pos::{Span, MultiSpan}; -use rustc_back::PanicStrategy; +use rustc_back::{LinkerFlavor, PanicStrategy}; use rustc_back::target::Target; use rustc_data_structures::flock; use llvm; @@ -363,6 +363,9 @@ impl Session { pub fn panic_strategy(&self) -> PanicStrategy { self.opts.cg.panic.unwrap_or(self.target.target.options.panic_strategy) } + pub fn linker_flavor(&self) -> LinkerFlavor { + self.opts.debugging_opts.linker_flavor.unwrap_or(self.target.target.linker_flavor) + } pub fn no_landing_pads(&self) -> bool { self.opts.debugging_opts.no_landing_pads || self.panic_strategy() == PanicStrategy::Abort } diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 000e4eb59bf..6679cc73029 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -52,6 +52,48 @@ pub mod dynamic_lib; use serialize::json::{Json, ToJson}; +macro_rules! linker_flavor { + ($(($variant:ident, $string:expr),)+) => { + #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash, + RustcEncodable, RustcDecodable)] + pub enum LinkerFlavor { + $($variant,)+ + } + + impl LinkerFlavor { + pub const fn one_of() -> &'static str { + concat!("one of: ", $($string, " ",)+) + } + + pub fn from_str(s: &str) -> Option<Self> { + Some(match s { + $($string => LinkerFlavor::$variant,)+ + _ => return None, + }) + } + + pub fn desc(&self) -> &str { + match *self { + $(LinkerFlavor::$variant => $string,)+ + } + } + } + + impl ToJson for LinkerFlavor { + fn to_json(&self) -> Json { + self.desc().to_json() + } + } + } +} + +linker_flavor! { + (Em, "em"), + (Gcc, "gcc"), + (Ld, "ld"), + (Msvc, "msvc"), +} + #[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] pub enum PanicStrategy { Unwind, diff --git a/src/librustc_back/target/aarch64_apple_ios.rs b/src/librustc_back/target/aarch64_apple_ios.rs index 5ef79359140..802a8c77db0 100644 --- a/src/librustc_back/target/aarch64_apple_ios.rs +++ b/src/librustc_back/target/aarch64_apple_ios.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; use super::apple_ios_base::{opts, Arch}; @@ -22,6 +23,7 @@ pub fn target() -> TargetResult { target_os: "ios".to_string(), target_env: "".to_string(), target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { features: "+neon,+fp-armv8,+cyclone".to_string(), eliminate_frame_pointer: false, diff --git a/src/librustc_back/target/aarch64_linux_android.rs b/src/librustc_back/target/aarch64_linux_android.rs index 54eead94986..7d8610b4a36 100644 --- a/src/librustc_back/target/aarch64_linux_android.rs +++ b/src/librustc_back/target/aarch64_linux_android.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a @@ -28,6 +29,7 @@ pub fn target() -> TargetResult { target_os: "android".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { abi_blacklist: super::arm_base::abi_blacklist(), .. base diff --git a/src/librustc_back/target/aarch64_unknown_freebsd.rs b/src/librustc_back/target/aarch64_unknown_freebsd.rs index 3c5d6308ee6..c5cfff0be03 100644 --- a/src/librustc_back/target/aarch64_unknown_freebsd.rs +++ b/src/librustc_back/target/aarch64_unknown_freebsd.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -26,6 +27,7 @@ pub fn target() -> TargetResult { target_os: "freebsd".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { abi_blacklist: super::arm_base::abi_blacklist(), .. base diff --git a/src/librustc_back/target/aarch64_unknown_fuchsia.rs b/src/librustc_back/target/aarch64_unknown_fuchsia.rs index 6ba1732e67f..5d680504a02 100644 --- a/src/librustc_back/target/aarch64_unknown_fuchsia.rs +++ b/src/librustc_back/target/aarch64_unknown_fuchsia.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -23,6 +24,7 @@ pub fn target() -> TargetResult { target_os: "fuchsia".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { abi_blacklist: super::arm_base::abi_blacklist(), .. base diff --git a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs index 5f6335d405f..043bd881c72 100644 --- a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs +++ b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -26,6 +27,7 @@ pub fn target() -> TargetResult { arch: "aarch64".to_string(), target_os: "linux".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { abi_blacklist: super::arm_base::abi_blacklist(), .. base diff --git a/src/librustc_back/target/android_base.rs b/src/librustc_back/target/android_base.rs index 9791520e933..49baa1b96ce 100644 --- a/src/librustc_back/target/android_base.rs +++ b/src/librustc_back/target/android_base.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::TargetOptions; pub fn opts() -> TargetOptions { let mut base = super::linux_base::opts(); // Many of the symbols defined in compiler-rt are also defined in libgcc. // Android's linker doesn't like that by default. - base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string()); + base.pre_link_args + .get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--allow-multiple-definition".to_string()); base.is_like_android = true; base.position_independent_executables = true; base.has_elf_tls = false; diff --git a/src/librustc_back/target/apple_base.rs b/src/librustc_back/target/apple_base.rs index 3a551a2b124..159f93a74c6 100644 --- a/src/librustc_back/target/apple_base.rs +++ b/src/librustc_back/target/apple_base.rs @@ -10,7 +10,7 @@ use std::env; -use target::TargetOptions; +use target::{LinkArgs, TargetOptions}; pub fn opts() -> TargetOptions { // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 @@ -43,7 +43,7 @@ pub fn opts() -> TargetOptions { dll_prefix: "lib".to_string(), dll_suffix: ".dylib".to_string(), archive_format: "bsd".to_string(), - pre_link_args: Vec::new(), + pre_link_args: LinkArgs::new(), exe_allocation_crate: super::maybe_jemalloc(), has_elf_tls: version >= (10, 7), .. Default::default() diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs index 17492b8bdcb..2e7d30d969e 100644 --- a/src/librustc_back/target/apple_ios_base.rs +++ b/src/librustc_back/target/apple_ios_base.rs @@ -8,9 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use std::io; use std::process::Command; -use target::TargetOptions; +use target::{LinkArgs, TargetOptions}; use self::Arch::*; @@ -60,7 +61,7 @@ pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> { } } -fn build_pre_link_args(arch: Arch) -> Result<Vec<String>, String> { +fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> { let sdk_name = match arch { Armv7 | Armv7s | Arm64 => "iphoneos", I386 | X86_64 => "iphonesimulator" @@ -70,8 +71,14 @@ fn build_pre_link_args(arch: Arch) -> Result<Vec<String>, String> { let sdk_root = get_sdk_root(sdk_name)?; - Ok(vec!["-arch".to_string(), arch_name.to_string(), - "-Wl,-syslibroot".to_string(), sdk_root]) + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Gcc, + vec!["-arch".to_string(), + arch_name.to_string(), + "-Wl,-syslibroot".to_string(), + sdk_root]); + + Ok(args) } fn target_cpu(arch: Arch) -> String { diff --git a/src/librustc_back/target/arm_linux_androideabi.rs b/src/librustc_back/target/arm_linux_androideabi.rs index c7d2df4344c..bccd5a41ab1 100644 --- a/src/librustc_back/target/arm_linux_androideabi.rs +++ b/src/librustc_back/target/arm_linux_androideabi.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -24,6 +25,7 @@ pub fn target() -> TargetResult { target_os: "android".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { abi_blacklist: super::arm_base::abi_blacklist(), .. base diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs index 77d35edfbd0..165d34fe6c7 100644 --- a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs +++ b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -22,6 +23,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { features: "+v6".to_string(), diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs index b183412be19..731021d979b 100644 --- a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs +++ b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -22,6 +23,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { features: "+v6,+vfp2".to_string(), diff --git a/src/librustc_back/target/arm_unknown_linux_musleabi.rs b/src/librustc_back/target/arm_unknown_linux_musleabi.rs index 261d4353c7a..f81bcd78b03 100644 --- a/src/librustc_back/target/arm_unknown_linux_musleabi.rs +++ b/src/librustc_back/target/arm_unknown_linux_musleabi.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -29,6 +30,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "musl".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { abi_blacklist: super::arm_base::abi_blacklist(), .. base diff --git a/src/librustc_back/target/arm_unknown_linux_musleabihf.rs b/src/librustc_back/target/arm_unknown_linux_musleabihf.rs index 1443dcf5bad..6c47678ede6 100644 --- a/src/librustc_back/target/arm_unknown_linux_musleabihf.rs +++ b/src/librustc_back/target/arm_unknown_linux_musleabihf.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -29,6 +30,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "musl".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { abi_blacklist: super::arm_base::abi_blacklist(), .. base diff --git a/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs b/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs index 37216e20762..200c6ab74cc 100644 --- a/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs +++ b/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -21,6 +22,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { features: "+soft-float".to_string(), @@ -31,4 +33,3 @@ pub fn target() -> TargetResult { } }) } - diff --git a/src/librustc_back/target/armv7_apple_ios.rs b/src/librustc_back/target/armv7_apple_ios.rs index 9e9c4439306..4d874582832 100644 --- a/src/librustc_back/target/armv7_apple_ios.rs +++ b/src/librustc_back/target/armv7_apple_ios.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; use super::apple_ios_base::{opts, Arch}; @@ -22,6 +23,7 @@ pub fn target() -> TargetResult { target_os: "ios".to_string(), target_env: "".to_string(), target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { features: "+v7,+vfp3,+neon".to_string(), max_atomic_width: Some(64), diff --git a/src/librustc_back/target/armv7_linux_androideabi.rs b/src/librustc_back/target/armv7_linux_androideabi.rs index 36f409b7948..0c90e834006 100644 --- a/src/librustc_back/target/armv7_linux_androideabi.rs +++ b/src/librustc_back/target/armv7_linux_androideabi.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; // See https://developer.android.com/ndk/guides/abis.html#v7a @@ -27,6 +28,7 @@ pub fn target() -> TargetResult { target_os: "android".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { abi_blacklist: super::arm_base::abi_blacklist(), .. base diff --git a/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs b/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs index 96ccedd5bea..d3a6a68449c 100644 --- a/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs +++ b/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -21,6 +22,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { // Info about features at https://wiki.debian.org/ArmHardFloatPort @@ -32,4 +34,3 @@ pub fn target() -> TargetResult { } }) } - diff --git a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs index 8f66e6a4f58..5086cd44f7a 100644 --- a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs +++ b/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -30,6 +31,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "musl".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { abi_blacklist: super::arm_base::abi_blacklist(), .. base diff --git a/src/librustc_back/target/armv7s_apple_ios.rs b/src/librustc_back/target/armv7s_apple_ios.rs index 6edde6e73ef..96c89a7ed3b 100644 --- a/src/librustc_back/target/armv7s_apple_ios.rs +++ b/src/librustc_back/target/armv7s_apple_ios.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; use super::apple_ios_base::{opts, Arch}; @@ -22,6 +23,7 @@ pub fn target() -> TargetResult { target_os: "ios".to_string(), target_env: "".to_string(), target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { features: "+v7,+vfp4,+neon".to_string(), max_atomic_width: Some(64), diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs index 4d38b0d1705..b884d4e5410 100644 --- a/src/librustc_back/target/asmjs_unknown_emscripten.rs +++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs @@ -8,10 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{Target, TargetOptions}; +use LinkerFlavor; +use super::{LinkArgs, Target, TargetOptions}; use super::emscripten_base::{cmd}; pub fn target() -> Result<Target, String> { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Em, + vec!["-s".to_string(), + "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]); + let opts = TargetOptions { linker: cmd("emcc"), ar: cmd("emar"), @@ -24,7 +30,7 @@ pub fn target() -> Result<Target, String> { obj_is_bitcode: true, is_like_emscripten: true, max_atomic_width: Some(32), - post_link_args: vec!["-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()], + post_link_args: args, target_family: Some("unix".to_string()), .. Default::default() }; @@ -37,6 +43,7 @@ pub fn target() -> Result<Target, String> { target_vendor: "unknown".to_string(), data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(), arch: "asmjs".to_string(), + linker_flavor: LinkerFlavor::Em, options: opts, }) } diff --git a/src/librustc_back/target/dragonfly_base.rs b/src/librustc_back/target/dragonfly_base.rs index dca33e45af7..e44cd393289 100644 --- a/src/librustc_back/target/dragonfly_base.rs +++ b/src/librustc_back/target/dragonfly_base.rs @@ -8,26 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use target::TargetOptions; +use LinkerFlavor; +use target::{LinkArgs, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Gcc, vec![ + // GNU-style linkers will use this to omit linking to libraries + // which don't actually fulfill any relocations, but only for + // libraries which follow this flag. Thus, use it before + // specifying libraries to link to. + "-Wl,--as-needed".to_string(), + + // Always enable NX protection when it is available + "-Wl,-z,noexecstack".to_string(), + ]); + TargetOptions { dynamic_linking: true, executables: true, target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], + pre_link_args: args, position_independent_executables: true, exe_allocation_crate: super::maybe_jemalloc(), .. Default::default() diff --git a/src/librustc_back/target/freebsd_base.rs b/src/librustc_back/target/freebsd_base.rs index dca33e45af7..e44cd393289 100644 --- a/src/librustc_back/target/freebsd_base.rs +++ b/src/librustc_back/target/freebsd_base.rs @@ -8,26 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use target::TargetOptions; +use LinkerFlavor; +use target::{LinkArgs, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Gcc, vec![ + // GNU-style linkers will use this to omit linking to libraries + // which don't actually fulfill any relocations, but only for + // libraries which follow this flag. Thus, use it before + // specifying libraries to link to. + "-Wl,--as-needed".to_string(), + + // Always enable NX protection when it is available + "-Wl,-z,noexecstack".to_string(), + ]); + TargetOptions { dynamic_linking: true, executables: true, target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], + pre_link_args: args, position_independent_executables: true, exe_allocation_crate: super::maybe_jemalloc(), .. Default::default() diff --git a/src/librustc_back/target/fuchsia_base.rs b/src/librustc_back/target/fuchsia_base.rs index 8c517224201..c6207cdc4d9 100644 --- a/src/librustc_back/target/fuchsia_base.rs +++ b/src/librustc_back/target/fuchsia_base.rs @@ -8,30 +8,34 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use target::TargetOptions; +use LinkerFlavor; +use target::{LinkArgs, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Gcc, vec![ + // We want to be able to strip as much executable code as possible + // from the linker command line, and this flag indicates to the + // linker that it can avoid linking in dynamic libraries that don't + // actually satisfy any symbols up to that point (as with many other + // resolutions the linker does). This option only applies to all + // following libraries so we're sure to pass it as one of the first + // arguments. + // FIXME: figure out whether these linker args are desirable + //"-Wl,--as-needed".to_string(), + + // Always enable NX protection when it is available + //"-Wl,-z,noexecstack".to_string(), + ]); + TargetOptions { dynamic_linking: true, executables: true, target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: vec![ - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - // FIXME: figure out whether these linker args are desirable - //"-Wl,--as-needed".to_string(), - - // Always enable NX protection when it is available - //"-Wl,-z,noexecstack".to_string(), - ], + pre_link_args: args, position_independent_executables: true, exe_allocation_crate: "alloc_system".to_string(), has_elf_tls: true, diff --git a/src/librustc_back/target/i386_apple_ios.rs b/src/librustc_back/target/i386_apple_ios.rs index 319ada4f8e1..a6383179f3a 100644 --- a/src/librustc_back/target/i386_apple_ios.rs +++ b/src/librustc_back/target/i386_apple_ios.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; use super::apple_ios_base::{opts, Arch}; @@ -22,6 +23,7 @@ pub fn target() -> TargetResult { target_os: "ios".to_string(), target_env: "".to_string(), target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { max_atomic_width: Some(64), .. base diff --git a/src/librustc_back/target/i686_apple_darwin.rs b/src/librustc_back/target/i686_apple_darwin.rs index d3b09d9a0f1..6b14972e9f7 100644 --- a/src/librustc_back/target/i686_apple_darwin.rs +++ b/src/librustc_back/target/i686_apple_darwin.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::apple_base::opts(); base.cpu = "yonah".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m32".to_string()); + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]); Ok(Target { llvm_target: "i686-apple-darwin".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "macos".to_string(), target_env: "".to_string(), target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/i686_linux_android.rs b/src/librustc_back/target/i686_linux_android.rs index f8a8f5a3500..a5390cbfb72 100644 --- a/src/librustc_back/target/i686_linux_android.rs +++ b/src/librustc_back/target/i686_linux_android.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; // See https://developer.android.com/ndk/guides/abis.html#x86 @@ -31,6 +32,7 @@ pub fn target() -> TargetResult { target_os: "android".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/i686_pc_windows_gnu.rs b/src/librustc_back/target/i686_pc_windows_gnu.rs index 29477261392..4a736a93be7 100644 --- a/src/librustc_back/target/i686_pc_windows_gnu.rs +++ b/src/librustc_back/target/i686_pc_windows_gnu.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { @@ -18,7 +19,8 @@ pub fn target() -> TargetResult { // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. - base.pre_link_args.push("-Wl,--large-address-aware".to_string()); + base.pre_link_args + .get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--large-address-aware".to_string()); Ok(Target { llvm_target: "i686-pc-windows-gnu".to_string(), @@ -29,6 +31,7 @@ pub fn target() -> TargetResult { target_os: "windows".to_string(), target_env: "gnu".to_string(), target_vendor: "pc".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/i686_pc_windows_msvc.rs b/src/librustc_back/target/i686_pc_windows_msvc.rs index 2290d2057f1..17fe306804f 100644 --- a/src/librustc_back/target/i686_pc_windows_msvc.rs +++ b/src/librustc_back/target/i686_pc_windows_msvc.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { @@ -17,12 +18,13 @@ pub fn target() -> TargetResult { // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. - base.pre_link_args.push("/LARGEADDRESSAWARE".to_string()); + base.pre_link_args + .get_mut(&LinkerFlavor::Msvc).unwrap().push("/LARGEADDRESSAWARE".to_string()); // Ensure the linker will only produce an image if it can also produce a table of // the image's safe exception handlers. // https://msdn.microsoft.com/en-us/library/9a89h429.aspx - base.pre_link_args.push("/SAFESEH".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().push("/SAFESEH".to_string()); Ok(Target { llvm_target: "i686-pc-windows-msvc".to_string(), @@ -33,6 +35,7 @@ pub fn target() -> TargetResult { target_os: "windows".to_string(), target_env: "msvc".to_string(), target_vendor: "pc".to_string(), + linker_flavor: LinkerFlavor::Msvc, options: base, }) } diff --git a/src/librustc_back/target/i686_unknown_dragonfly.rs b/src/librustc_back/target/i686_unknown_dragonfly.rs index d8f8431e66e..052bc23c119 100644 --- a/src/librustc_back/target/i686_unknown_dragonfly.rs +++ b/src/librustc_back/target/i686_unknown_dragonfly.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::dragonfly_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m32".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); Ok(Target { llvm_target: "i686-unknown-dragonfly".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "dragonfly".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/i686_unknown_freebsd.rs b/src/librustc_back/target/i686_unknown_freebsd.rs index ddbc74f25c9..d77a9cca268 100644 --- a/src/librustc_back/target/i686_unknown_freebsd.rs +++ b/src/librustc_back/target/i686_unknown_freebsd.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::freebsd_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m32".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); Ok(Target { llvm_target: "i686-unknown-freebsd".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "freebsd".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/i686_unknown_haiku.rs b/src/librustc_back/target/i686_unknown_haiku.rs index 9078206c9e0..b0e67bd90dd 100644 --- a/src/librustc_back/target/i686_unknown_haiku.rs +++ b/src/librustc_back/target/i686_unknown_haiku.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::haiku_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m32".to_string()); + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]); Ok(Target { llvm_target: "i686-unknown-haiku".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "haiku".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/i686_unknown_linux_gnu.rs b/src/librustc_back/target/i686_unknown_linux_gnu.rs index bf9c28b0c10..3c5c1067626 100644 --- a/src/librustc_back/target/i686_unknown_linux_gnu.rs +++ b/src/librustc_back/target/i686_unknown_linux_gnu.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::linux_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m32".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); Ok(Target { llvm_target: "i686-unknown-linux-gnu".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/i686_unknown_linux_musl.rs b/src/librustc_back/target/i686_unknown_linux_musl.rs index ced59448f7f..3ed8c94d0bf 100644 --- a/src/librustc_back/target/i686_unknown_linux_musl.rs +++ b/src/librustc_back/target/i686_unknown_linux_musl.rs @@ -8,14 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::linux_musl_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m32".to_string()); - base.pre_link_args.push("-Wl,-melf_i386".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-melf_i386".to_string()); // The unwinder used by i686-unknown-linux-musl, the LLVM libunwind // implementation, apparently relies on frame pointers existing... somehow. @@ -40,6 +41,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "musl".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/i686_unknown_netbsd.rs b/src/librustc_back/target/i686_unknown_netbsd.rs index e7e2ee3f905..fc92e5aee6a 100644 --- a/src/librustc_back/target/i686_unknown_netbsd.rs +++ b/src/librustc_back/target/i686_unknown_netbsd.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::netbsd_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m32".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); Ok(Target { llvm_target: "i686-unknown-netbsdelf".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "netbsd".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/i686_unknown_openbsd.rs b/src/librustc_back/target/i686_unknown_openbsd.rs index 81efd37386a..7ef68bd6d9c 100644 --- a/src/librustc_back/target/i686_unknown_openbsd.rs +++ b/src/librustc_back/target/i686_unknown_openbsd.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::openbsd_base::opts(); base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m32".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); Ok(Target { llvm_target: "i686-unknown-openbsd".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "openbsd".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/le32_unknown_nacl.rs b/src/librustc_back/target/le32_unknown_nacl.rs index 891e7dda14a..f4265e0eb14 100644 --- a/src/librustc_back/target/le32_unknown_nacl.rs +++ b/src/librustc_back/target/le32_unknown_nacl.rs @@ -8,17 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{Target, TargetOptions, TargetResult}; +use LinkerFlavor; +use super::{LinkArgs, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { + let mut pre_link_args = LinkArgs::new(); + pre_link_args.insert(LinkerFlavor::Gcc, + vec!["--pnacl-exceptions=sjlj".to_string(), + "--target=le32-unknown-nacl".to_string(), + "-Wl,--start-group".to_string()]); + let mut post_link_args = LinkArgs::new(); + post_link_args.insert(LinkerFlavor::Gcc, + vec!["-Wl,--end-group".to_string()]); + let opts = TargetOptions { linker: "pnacl-clang".to_string(), ar: "pnacl-ar".to_string(), - pre_link_args: vec!["--pnacl-exceptions=sjlj".to_string(), - "--target=le32-unknown-nacl".to_string(), - "-Wl,--start-group".to_string()], - post_link_args: vec!["-Wl,--end-group".to_string()], + pre_link_args: pre_link_args, + post_link_args: post_link_args, dynamic_linking: false, executables: true, exe_suffix: ".pexe".to_string(), @@ -36,6 +44,7 @@ pub fn target() -> TargetResult { target_vendor: "unknown".to_string(), data_layout: "e-i64:64:64-p:32:32:32-v128:32:32".to_string(), arch: "le32".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: opts, }) } diff --git a/src/librustc_back/target/linux_base.rs b/src/librustc_back/target/linux_base.rs index 4b2ae9c8e69..722d2fa16ef 100644 --- a/src/librustc_back/target/linux_base.rs +++ b/src/librustc_back/target/linux_base.rs @@ -8,29 +8,33 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use target::TargetOptions; +use LinkerFlavor; +use target::{LinkArgs, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Gcc, vec![ + // We want to be able to strip as much executable code as possible + // from the linker command line, and this flag indicates to the + // linker that it can avoid linking in dynamic libraries that don't + // actually satisfy any symbols up to that point (as with many other + // resolutions the linker does). This option only applies to all + // following libraries so we're sure to pass it as one of the first + // arguments. + "-Wl,--as-needed".to_string(), + + // Always enable NX protection when it is available + "-Wl,-z,noexecstack".to_string(), + ]); + TargetOptions { dynamic_linking: true, executables: true, target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: vec![ - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - "-Wl,--as-needed".to_string(), - - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], + pre_link_args: args, position_independent_executables: true, exe_allocation_crate: super::maybe_jemalloc(), has_elf_tls: true, diff --git a/src/librustc_back/target/linux_musl_base.rs b/src/librustc_back/target/linux_musl_base.rs index 18cca425a32..236f2c1ef0a 100644 --- a/src/librustc_back/target/linux_musl_base.rs +++ b/src/librustc_back/target/linux_musl_base.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::TargetOptions; pub fn opts() -> TargetOptions { @@ -15,13 +16,13 @@ pub fn opts() -> TargetOptions { // Make sure that the linker/gcc really don't pull in anything, including // default objects, libs, etc. - base.pre_link_args.push("-nostdlib".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-nostdlib".to_string()); // At least when this was tested, the linker would not add the // `GNU_EH_FRAME` program header to executables generated, which is required // when unwinding to locate the unwinding information. I'm not sure why this // argument is *not* necessary for normal builds, but it can't hurt! - base.pre_link_args.push("-Wl,--eh-frame-hdr".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--eh-frame-hdr".to_string()); // There's a whole bunch of circular dependencies when dealing with MUSL // unfortunately. To put this in perspective libc is statically linked to @@ -45,8 +46,8 @@ pub fn opts() -> TargetOptions { // link everything as a group, not stripping anything out until everything // is processed. The linker will still perform a pass to strip out object // files but it won't do so until all objects/archives have been processed. - base.pre_link_args.push("-Wl,-(".to_string()); - base.post_link_args.push("-Wl,-)".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-(".to_string()); + base.post_link_args.insert(LinkerFlavor::Gcc, vec!["-Wl,-)".to_string()]); // When generating a statically linked executable there's generally some // small setup needed which is listed in these files. These are provided by diff --git a/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs b/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs index c284840ecb4..038a70ed6b1 100644 --- a/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs +++ b/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -20,6 +21,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { // NOTE(mips64r2) matches C toolchain cpu: "mips64r2".to_string(), diff --git a/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs b/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs index 17895836fe8..aed4c4fbb08 100644 --- a/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs +++ b/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -20,6 +21,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { // NOTE(mips64r2) matches C toolchain cpu: "mips64r2".to_string(), diff --git a/src/librustc_back/target/mips_unknown_linux_gnu.rs b/src/librustc_back/target/mips_unknown_linux_gnu.rs index a6d8fae2536..9ef61f9cadd 100644 --- a/src/librustc_back/target/mips_unknown_linux_gnu.rs +++ b/src/librustc_back/target/mips_unknown_linux_gnu.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -20,6 +21,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { cpu: "mips32r2".to_string(), features: "+mips32r2".to_string(), diff --git a/src/librustc_back/target/mips_unknown_linux_musl.rs b/src/librustc_back/target/mips_unknown_linux_musl.rs index e4a6d2a55d9..f54790bab97 100644 --- a/src/librustc_back/target/mips_unknown_linux_musl.rs +++ b/src/librustc_back/target/mips_unknown_linux_musl.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -20,6 +21,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "musl".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { cpu: "mips32r2".to_string(), features: "+mips32r2,+soft-float".to_string(), diff --git a/src/librustc_back/target/mips_unknown_linux_uclibc.rs b/src/librustc_back/target/mips_unknown_linux_uclibc.rs index ccc64ea393b..59c07efe0fd 100644 --- a/src/librustc_back/target/mips_unknown_linux_uclibc.rs +++ b/src/librustc_back/target/mips_unknown_linux_uclibc.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -20,6 +21,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "uclibc".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { cpu: "mips32r2".to_string(), features: "+mips32r2,+soft-float".to_string(), diff --git a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs index 9b8b1d5713f..ec19cc1a536 100644 --- a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs +++ b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -20,6 +21,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { cpu: "mips32".to_string(), diff --git a/src/librustc_back/target/mipsel_unknown_linux_musl.rs b/src/librustc_back/target/mipsel_unknown_linux_musl.rs index 5693bddd048..00085d18e6d 100644 --- a/src/librustc_back/target/mipsel_unknown_linux_musl.rs +++ b/src/librustc_back/target/mipsel_unknown_linux_musl.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -20,6 +21,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "musl".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { cpu: "mips32".to_string(), features: "+mips32,+soft-float".to_string(), diff --git a/src/librustc_back/target/mipsel_unknown_linux_uclibc.rs b/src/librustc_back/target/mipsel_unknown_linux_uclibc.rs index 3acade5a474..b3ca2edec1e 100644 --- a/src/librustc_back/target/mipsel_unknown_linux_uclibc.rs +++ b/src/librustc_back/target/mipsel_unknown_linux_uclibc.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -20,6 +21,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "uclibc".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { cpu: "mips32".to_string(), diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 559418d2c4f..ca6894a7b70 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -50,7 +50,7 @@ use std::default::Default; use std::io::prelude::*; use syntax::abi::{Abi, lookup as lookup_abi}; -use PanicStrategy; +use {LinkerFlavor, PanicStrategy}; mod android_base; mod apple_base; @@ -72,6 +72,7 @@ mod thumb_base; mod fuchsia_base; mod redox_base; +pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>; pub type TargetResult = Result<Target, String>; macro_rules! supported_targets { @@ -241,6 +242,8 @@ pub struct Target { pub arch: String, /// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM. pub data_layout: String, + /// Linker flavor + pub linker_flavor: LinkerFlavor, /// Optional settings with defaults. pub options: TargetOptions, } @@ -261,7 +264,7 @@ pub struct TargetOptions { /// Linker arguments that are unconditionally passed *before* any /// user-defined libraries. - pub pre_link_args: Vec<String>, + pub pre_link_args: LinkArgs, /// Objects to link before all others, always found within the /// sysroot folder. pub pre_link_objects_exe: Vec<String>, // ... when linking an executable @@ -269,13 +272,13 @@ pub struct TargetOptions { /// 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: Vec<String>, + pub late_link_args: LinkArgs, /// Objects to link after all others, always found within the /// sysroot folder. pub post_link_objects: Vec<String>, /// Linker arguments that are unconditionally passed *after* any /// user-defined libraries. - pub post_link_args: Vec<String>, + pub post_link_args: LinkArgs, /// Extra arguments to pass to the external assembler (when used) pub asm_args: Vec<String>, @@ -412,8 +415,8 @@ impl Default for TargetOptions { is_builtin: false, linker: option_env!("CFG_DEFAULT_LINKER").unwrap_or("cc").to_string(), ar: option_env!("CFG_DEFAULT_AR").unwrap_or("ar").to_string(), - pre_link_args: Vec::new(), - post_link_args: Vec::new(), + pre_link_args: LinkArgs::new(), + post_link_args: LinkArgs::new(), asm_args: Vec::new(), cpu: "generic".to_string(), features: "".to_string(), @@ -445,7 +448,7 @@ impl Default for TargetOptions { pre_link_objects_exe: Vec::new(), pre_link_objects_dll: Vec::new(), post_link_objects: Vec::new(), - late_link_args: Vec::new(), + late_link_args: LinkArgs::new(), archive_format: "gnu".to_string(), custom_unwind_resume: false, lib_allocation_crate: "alloc_system".to_string(), @@ -529,6 +532,10 @@ impl Target { target_os: get_req_field("os")?, target_env: get_opt_field("env", ""), target_vendor: get_opt_field("vendor", "unknown"), + linker_flavor: LinkerFlavor::from_str(&*get_req_field("linker-flavor")?) + .ok_or_else(|| { + format!("linker flavor must be {}", LinkerFlavor::one_of()) + })?, options: Default::default(), }; @@ -579,17 +586,49 @@ impl Target { .map(|s| s.to_string() ); } } ); + ($key_name:ident, LinkerFlavor) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name[..]).and_then(|o| o.as_string().map(|s| { + LinkerFlavor::from_str(&s).ok_or_else(|| { + Err(format!("'{}' is not a valid value for linker-flavor. \ + Use 'em', 'gcc', 'ld' or 'msvc.", s)) + }) + })).unwrap_or(Ok(())) + } ); + ($key_name:ident, link_args) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + if let Some(obj) = obj.find(&name[..]).and_then(|o| o.as_object()) { + let mut args = LinkArgs::new(); + for (k, v) in obj { + let k = LinkerFlavor::from_str(&k).ok_or_else(|| { + format!("{}: '{}' is not a valid value for linker-flavor. \ + Use 'em', 'gcc', 'ld' or 'msvc'", name, k) + })?; + + let v = v.as_array().map(|a| { + a + .iter() + .filter_map(|o| o.as_string()) + .map(|s| s.to_owned()) + .collect::<Vec<_>>() + }).unwrap_or(vec![]); + + args.insert(k, v); + } + base.options.$key_name = args; + } + } ); } key!(is_builtin, bool); key!(linker); key!(ar); - key!(pre_link_args, list); + key!(pre_link_args, link_args); key!(pre_link_objects_exe, list); key!(pre_link_objects_dll, list); - key!(late_link_args, list); + key!(late_link_args, link_args); key!(post_link_objects, list); - key!(post_link_args, list); + key!(post_link_args, link_args); key!(asm_args, list); key!(cpu); key!(features); @@ -734,6 +773,16 @@ impl ToJson for Target { d.insert(name.to_string(), self.options.$attr.to_json()); } } ); + (link_args - $attr:ident) => ( { + let name = (stringify!($attr)).replace("_", "-"); + if default.$attr != self.options.$attr { + let obj = self.options.$attr + .iter() + .map(|(k, v)| (k.desc().to_owned(), v.clone())) + .collect::<BTreeMap<_, _>>(); + d.insert(name.to_string(), obj.to_json()); + } + } ); } target_val!(llvm_target); @@ -743,18 +792,18 @@ impl ToJson for Target { target_val!(target_os, "os"); target_val!(target_env, "env"); target_val!(target_vendor, "vendor"); - target_val!(arch); target_val!(data_layout); + target_val!(linker_flavor); target_option_val!(is_builtin); target_option_val!(linker); target_option_val!(ar); - target_option_val!(pre_link_args); + target_option_val!(link_args - pre_link_args); target_option_val!(pre_link_objects_exe); target_option_val!(pre_link_objects_dll); - target_option_val!(late_link_args); + target_option_val!(link_args - late_link_args); target_option_val!(post_link_objects); - target_option_val!(post_link_args); + target_option_val!(link_args - post_link_args); target_option_val!(asm_args); target_option_val!(cpu); target_option_val!(features); diff --git a/src/librustc_back/target/netbsd_base.rs b/src/librustc_back/target/netbsd_base.rs index 57179a68afd..63245fcae76 100644 --- a/src/librustc_back/target/netbsd_base.rs +++ b/src/librustc_back/target/netbsd_base.rs @@ -8,26 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use target::TargetOptions; +use LinkerFlavor; +use target::{LinkArgs, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Gcc, vec![ + // GNU-style linkers will use this to omit linking to libraries + // which don't actually fulfill any relocations, but only for + // libraries which follow this flag. Thus, use it before + // specifying libraries to link to. + "-Wl,--as-needed".to_string(), + + // Always enable NX protection when it is available + "-Wl,-z,noexecstack".to_string(), + ]); + TargetOptions { dynamic_linking: true, executables: true, target_family: Some("unix".to_string()), linker_is_gnu: true, has_rpath: true, - pre_link_args: vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], + pre_link_args: args, position_independent_executables: true, .. Default::default() } diff --git a/src/librustc_back/target/openbsd_base.rs b/src/librustc_back/target/openbsd_base.rs index 12b8e8bdc88..2df9b8e03ff 100644 --- a/src/librustc_back/target/openbsd_base.rs +++ b/src/librustc_back/target/openbsd_base.rs @@ -8,10 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use target::TargetOptions; +use LinkerFlavor; +use target::{LinkArgs, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Gcc, vec![ + // GNU-style linkers will use this to omit linking to libraries + // which don't actually fulfill any relocations, but only for + // libraries which follow this flag. Thus, use it before + // specifying libraries to link to. + "-Wl,--as-needed".to_string(), + + // Always enable NX protection when it is available + "-Wl,-z,noexecstack".to_string(), + ]); + TargetOptions { dynamic_linking: true, executables: true, @@ -19,16 +32,7 @@ pub fn opts() -> TargetOptions { linker_is_gnu: true, has_rpath: true, is_like_openbsd: true, - pre_link_args: vec![ - // GNU-style linkers will use this to omit linking to libraries - // which don't actually fulfill any relocations, but only for - // libraries which follow this flag. Thus, use it before - // specifying libraries to link to. - "-Wl,--as-needed".to_string(), - - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string(), - ], + pre_link_args: args, position_independent_executables: true, exe_allocation_crate: "alloc_system".to_string(), .. Default::default() diff --git a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs index 909c5488dcb..55a5bfd1e67 100644 --- a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs +++ b/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::linux_base::opts(); base.cpu = "ppc64".to_string(); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); // see #36994 @@ -28,6 +29,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs index a692346ca0f..c22bc3b041a 100644 --- a/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs +++ b/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::linux_base::opts(); base.cpu = "ppc64le".to_string(); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); // see #36994 @@ -28,6 +29,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs index 284772c4331..677d198b1a3 100644 --- a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs +++ b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::linux_base::opts(); - base.pre_link_args.push("-m32".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string()); base.max_atomic_width = Some(32); // see #36994 @@ -27,6 +28,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/redox_base.rs b/src/librustc_back/target/redox_base.rs index c5e1e107753..f26a86d4bdc 100644 --- a/src/librustc_back/target/redox_base.rs +++ b/src/librustc_back/target/redox_base.rs @@ -8,25 +8,28 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use PanicStrategy; -use target::TargetOptions; +use {LinkerFlavor, PanicStrategy}; +use target::{LinkArgs, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { - TargetOptions { - pre_link_args: vec![ - // We want to be able to strip as much executable code as possible - // from the linker command line, and this flag indicates to the - // linker that it can avoid linking in dynamic libraries that don't - // actually satisfy any symbols up to that point (as with many other - // resolutions the linker does). This option only applies to all - // following libraries so we're sure to pass it as one of the first - // arguments. - "-Wl,--as-needed".to_string(), + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Gcc, vec![ + // We want to be able to strip as much executable code as possible + // from the linker command line, and this flag indicates to the + // linker that it can avoid linking in dynamic libraries that don't + // actually satisfy any symbols up to that point (as with many other + // resolutions the linker does). This option only applies to all + // following libraries so we're sure to pass it as one of the first + // arguments. + "-Wl,--as-needed".to_string(), + + // Always enable NX protection when it is available + "-Wl,-z,noexecstack".to_string() + ]); - // Always enable NX protection when it is available - "-Wl,-z,noexecstack".to_string() - ], + TargetOptions { + pre_link_args: args, executables: true, relocation_model: "static".to_string(), disable_redzone: true, diff --git a/src/librustc_back/target/s390x_unknown_linux_gnu.rs b/src/librustc_back/target/s390x_unknown_linux_gnu.rs index 671fb4f4319..cc8eb7c4e84 100644 --- a/src/librustc_back/target/s390x_unknown_linux_gnu.rs +++ b/src/librustc_back/target/s390x_unknown_linux_gnu.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { @@ -31,6 +32,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/sparc64_unknown_linux_gnu.rs b/src/librustc_back/target/sparc64_unknown_linux_gnu.rs index f627cc18f0b..1bd51ac6258 100644 --- a/src/librustc_back/target/sparc64_unknown_linux_gnu.rs +++ b/src/librustc_back/target/sparc64_unknown_linux_gnu.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/sparc64_unknown_netbsd.rs b/src/librustc_back/target/sparc64_unknown_netbsd.rs index f30cebbc2d5..bc65a17ce6e 100644 --- a/src/librustc_back/target/sparc64_unknown_netbsd.rs +++ b/src/librustc_back/target/sparc64_unknown_netbsd.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::netbsd_base::opts(); base.cpu = "v9".to_string(); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); Ok(Target { @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "netbsd".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/sparcv9_sun_solaris.rs b/src/librustc_back/target/sparcv9_sun_solaris.rs index c88e5a402f2..122b38968a9 100644 --- a/src/librustc_back/target/sparcv9_sun_solaris.rs +++ b/src/librustc_back/target/sparcv9_sun_solaris.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::solaris_base::opts(); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); // llvm calls this "v9" base.cpu = "v9".to_string(); base.max_atomic_width = Some(64); @@ -30,6 +31,7 @@ pub fn target() -> TargetResult { target_os: "solaris".to_string(), target_env: "".to_string(), target_vendor: "sun".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/thumbv6m_none_eabi.rs b/src/librustc_back/target/thumbv6m_none_eabi.rs index 6c22f985384..08bf145e551 100644 --- a/src/librustc_back/target/thumbv6m_none_eabi.rs +++ b/src/librustc_back/target/thumbv6m_none_eabi.rs @@ -10,6 +10,7 @@ // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture) +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -22,6 +23,7 @@ pub fn target() -> TargetResult { target_os: "none".to_string(), target_env: "".to_string(), target_vendor: "".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them diff --git a/src/librustc_back/target/thumbv7em_none_eabi.rs b/src/librustc_back/target/thumbv7em_none_eabi.rs index ddad4e3624f..13f9cc5f65f 100644 --- a/src/librustc_back/target/thumbv7em_none_eabi.rs +++ b/src/librustc_back/target/thumbv7em_none_eabi.rs @@ -19,6 +19,7 @@ // To opt-in to hardware accelerated floating point operations, you can use, for example, // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -31,6 +32,7 @@ pub fn target() -> TargetResult { target_os: "none".to_string(), target_env: "".to_string(), target_vendor: "".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { max_atomic_width: Some(32), diff --git a/src/librustc_back/target/thumbv7em_none_eabihf.rs b/src/librustc_back/target/thumbv7em_none_eabihf.rs index a9fac48e8e5..929b6db6fb2 100644 --- a/src/librustc_back/target/thumbv7em_none_eabihf.rs +++ b/src/librustc_back/target/thumbv7em_none_eabihf.rs @@ -18,6 +18,7 @@ // // To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -30,6 +31,7 @@ pub fn target() -> TargetResult { target_os: "none".to_string(), target_env: "".to_string(), target_vendor: "".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { // `+vfp4` is the lowest common denominator between the Cortex-M4 (vfp4-16) and the diff --git a/src/librustc_back/target/thumbv7m_none_eabi.rs b/src/librustc_back/target/thumbv7m_none_eabi.rs index ed61dd0459b..8d46e7cb907 100644 --- a/src/librustc_back/target/thumbv7m_none_eabi.rs +++ b/src/librustc_back/target/thumbv7m_none_eabi.rs @@ -10,6 +10,7 @@ // Targets the Cortex-M3 processor (ARMv7-M) +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { @@ -22,6 +23,7 @@ pub fn target() -> TargetResult { target_os: "none".to_string(), target_env: "".to_string(), target_vendor: "".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { max_atomic_width: Some(32), diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs index b1967fa8f37..a51f59d6ff1 100644 --- a/src/librustc_back/target/wasm32_unknown_emscripten.rs +++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs @@ -8,10 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{Target, TargetOptions}; +use LinkerFlavor; +use super::{LinkArgs, Target, TargetOptions}; use super::emscripten_base::{cmd}; pub fn target() -> Result<Target, String> { + let mut post_link_args = LinkArgs::new(); + post_link_args.insert(LinkerFlavor::Gcc, + vec!["-s".to_string(), + "BINARYEN=1".to_string(), + "-s".to_string(), + "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]); + let opts = TargetOptions { linker: cmd("emcc"), ar: cmd("emar"), @@ -26,8 +34,7 @@ pub fn target() -> Result<Target, String> { obj_is_bitcode: true, is_like_emscripten: true, max_atomic_width: Some(32), - post_link_args: vec!["-s".to_string(), "BINARYEN=1".to_string(), - "-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()], + post_link_args: post_link_args, target_family: Some("unix".to_string()), .. Default::default() }; @@ -40,6 +47,7 @@ pub fn target() -> Result<Target, String> { target_vendor: "unknown".to_string(), data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(), arch: "wasm32".to_string(), + linker_flavor: LinkerFlavor::Em, options: opts, }) } diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs index db02e142fcc..9bde24a28dd 100644 --- a/src/librustc_back/target/windows_base.rs +++ b/src/librustc_back/target/windows_base.rs @@ -8,26 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use target::TargetOptions; +use LinkerFlavor; +use target::{LinkArgs, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { - TargetOptions { - // FIXME(#13846) this should be enabled for windows - function_sections: false, - linker: "gcc".to_string(), - dynamic_linking: true, - executables: true, - dll_prefix: "".to_string(), - dll_suffix: ".dll".to_string(), - exe_suffix: ".exe".to_string(), - staticlib_prefix: "".to_string(), - staticlib_suffix: ".lib".to_string(), - no_default_libraries: true, - target_family: Some("windows".to_string()), - is_like_windows: true, - allows_weak_linkage: false, - pre_link_args: vec![ + let mut pre_link_args = LinkArgs::new(); + pre_link_args.insert(LinkerFlavor::Gcc, vec![ // And here, we see obscure linker flags #45. On windows, it has been // found to be necessary to have this flag to compile liblibc. // @@ -64,7 +51,34 @@ pub fn opts() -> TargetOptions { // Do not use the standard system startup files or libraries when linking "-nostdlib".to_string(), - ], + ]); + + let mut late_link_args = LinkArgs::new(); + late_link_args.insert(LinkerFlavor::Gcc, vec![ + "-lmingwex".to_string(), + "-lmingw32".to_string(), + "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc + "-lmsvcrt".to_string(), + "-luser32".to_string(), + "-lkernel32".to_string(), + ]); + + TargetOptions { + // FIXME(#13846) this should be enabled for windows + function_sections: false, + linker: "gcc".to_string(), + dynamic_linking: true, + executables: true, + dll_prefix: "".to_string(), + dll_suffix: ".dll".to_string(), + exe_suffix: ".exe".to_string(), + staticlib_prefix: "".to_string(), + staticlib_suffix: ".lib".to_string(), + no_default_libraries: true, + target_family: Some("windows".to_string()), + is_like_windows: true, + allows_weak_linkage: false, + pre_link_args: pre_link_args, pre_link_objects_exe: vec![ "crt2.o".to_string(), // mingw C runtime initialization for executables "rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs @@ -73,14 +87,7 @@ pub fn opts() -> TargetOptions { "dllcrt2.o".to_string(), // mingw C runtime initialization for dlls "rsbegin.o".to_string(), ], - late_link_args: vec![ - "-lmingwex".to_string(), - "-lmingw32".to_string(), - "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc - "-lmsvcrt".to_string(), - "-luser32".to_string(), - "-lkernel32".to_string(), - ], + late_link_args: late_link_args, post_link_objects: vec![ "rsend.o".to_string() ], diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs index efa215b419d..421f59aea93 100644 --- a/src/librustc_back/target/windows_msvc_base.rs +++ b/src/librustc_back/target/windows_msvc_base.rs @@ -8,10 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use target::TargetOptions; +use LinkerFlavor; +use target::{LinkArgs, TargetOptions}; use std::default::Default; pub fn opts() -> TargetOptions { + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Msvc, + vec!["/NOLOGO".to_string(), + "/NXCOMPAT".to_string()]); + TargetOptions { function_sections: true, linker: "link.exe".to_string(), @@ -56,10 +62,7 @@ pub fn opts() -> TargetOptions { target_family: Some("windows".to_string()), is_like_windows: true, is_like_msvc: true, - pre_link_args: vec![ - "/NOLOGO".to_string(), - "/NXCOMPAT".to_string(), - ], + pre_link_args: args, exe_allocation_crate: "alloc_system".to_string(), .. Default::default() diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_back/target/x86_64_apple_darwin.rs index b3c1561dbcc..8fd1b80430f 100644 --- a/src/librustc_back/target/x86_64_apple_darwin.rs +++ b/src/librustc_back/target/x86_64_apple_darwin.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { @@ -15,7 +16,7 @@ pub fn target() -> TargetResult { base.cpu = "core2".to_string(); base.max_atomic_width = Some(128); // core2 support cmpxchg16b base.eliminate_frame_pointer = false; - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); Ok(Target { llvm_target: "x86_64-apple-darwin".to_string(), @@ -26,6 +27,7 @@ pub fn target() -> TargetResult { target_os: "macos".to_string(), target_env: "".to_string(), target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_apple_ios.rs b/src/librustc_back/target/x86_64_apple_ios.rs index 7a58bb34ce7..bbd81fd86ff 100644 --- a/src/librustc_back/target/x86_64_apple_ios.rs +++ b/src/librustc_back/target/x86_64_apple_ios.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetOptions, TargetResult}; use super::apple_ios_base::{opts, Arch}; @@ -22,6 +23,7 @@ pub fn target() -> TargetResult { target_os: "ios".to_string(), target_env: "".to_string(), target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: TargetOptions { max_atomic_width: Some(64), .. base diff --git a/src/librustc_back/target/x86_64_pc_windows_gnu.rs b/src/librustc_back/target/x86_64_pc_windows_gnu.rs index 321585cd65e..10e88d88ee3 100644 --- a/src/librustc_back/target/x86_64_pc_windows_gnu.rs +++ b/src/librustc_back/target/x86_64_pc_windows_gnu.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::windows_base::opts(); base.cpu = "x86-64".to_string(); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); Ok(Target { @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "windows".to_string(), target_env: "gnu".to_string(), target_vendor: "pc".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_pc_windows_msvc.rs b/src/librustc_back/target/x86_64_pc_windows_msvc.rs index ea8909d213e..b07031c4bf1 100644 --- a/src/librustc_back/target/x86_64_pc_windows_msvc.rs +++ b/src/librustc_back/target/x86_64_pc_windows_msvc.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { @@ -24,6 +25,7 @@ pub fn target() -> TargetResult { target_os: "windows".to_string(), target_env: "msvc".to_string(), target_vendor: "pc".to_string(), + linker_flavor: LinkerFlavor::Msvc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs index 33137214396..eea4389cfd6 100644 --- a/src/librustc_back/target/x86_64_rumprun_netbsd.rs +++ b/src/librustc_back/target/x86_64_rumprun_netbsd.rs @@ -8,12 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::netbsd_base::opts(); base.cpu = "x86-64".to_string(); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.linker = "x86_64-rumprun-netbsd-gcc".to_string(); base.ar = "x86_64-rumprun-netbsd-ar".to_string(); base.max_atomic_width = Some(64); @@ -34,6 +35,7 @@ pub fn target() -> TargetResult { target_os: "netbsd".to_string(), target_env: "".to_string(), target_vendor: "rumprun".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_sun_solaris.rs b/src/librustc_back/target/x86_64_sun_solaris.rs index 8e4fd94e7bc..fe8691f3695 100644 --- a/src/librustc_back/target/x86_64_sun_solaris.rs +++ b/src/librustc_back/target/x86_64_sun_solaris.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::solaris_base::opts(); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "solaris".to_string(), target_env: "".to_string(), target_vendor: "sun".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_unknown_bitrig.rs b/src/librustc_back/target/x86_64_unknown_bitrig.rs index eda16c29466..5f87fe177a9 100644 --- a/src/librustc_back/target/x86_64_unknown_bitrig.rs +++ b/src/librustc_back/target/x86_64_unknown_bitrig.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::bitrig_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); Ok(Target { llvm_target: "x86_64-unknown-bitrig".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "bitrig".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_unknown_dragonfly.rs b/src/librustc_back/target/x86_64_unknown_dragonfly.rs index 194efb8fc23..96f608409ff 100644 --- a/src/librustc_back/target/x86_64_unknown_dragonfly.rs +++ b/src/librustc_back/target/x86_64_unknown_dragonfly.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::dragonfly_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); Ok(Target { llvm_target: "x86_64-unknown-dragonfly".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "dragonfly".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_unknown_freebsd.rs b/src/librustc_back/target/x86_64_unknown_freebsd.rs index b127bee163b..500629a1680 100644 --- a/src/librustc_back/target/x86_64_unknown_freebsd.rs +++ b/src/librustc_back/target/x86_64_unknown_freebsd.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::freebsd_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); Ok(Target { llvm_target: "x86_64-unknown-freebsd".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "freebsd".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_unknown_fuchsia.rs b/src/librustc_back/target/x86_64_unknown_fuchsia.rs index 08fe17a556e..6e37896d414 100644 --- a/src/librustc_back/target/x86_64_unknown_fuchsia.rs +++ b/src/librustc_back/target/x86_64_unknown_fuchsia.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::fuchsia_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); Ok(Target { llvm_target: "x86_64-unknown-fuchsia".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "fuchsia".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_unknown_haiku.rs b/src/librustc_back/target/x86_64_unknown_haiku.rs index 7cf0599037c..7fab9128b29 100644 --- a/src/librustc_back/target/x86_64_unknown_haiku.rs +++ b/src/librustc_back/target/x86_64_unknown_haiku.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::haiku_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]); Ok(Target { llvm_target: "x86_64-unknown-haiku".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "haiku".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs index f95bcb556e5..f73055cebaa 100644 --- a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs +++ b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::linux_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); Ok(Target { llvm_target: "x86_64-unknown-linux-gnu".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "gnu".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_unknown_linux_musl.rs b/src/librustc_back/target/x86_64_unknown_linux_musl.rs index c3bf9dcca6e..38b9c0bace5 100644 --- a/src/librustc_back/target/x86_64_unknown_linux_musl.rs +++ b/src/librustc_back/target/x86_64_unknown_linux_musl.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::linux_musl_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); Ok(Target { llvm_target: "x86_64-unknown-linux-musl".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "linux".to_string(), target_env: "musl".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_unknown_netbsd.rs b/src/librustc_back/target/x86_64_unknown_netbsd.rs index 87a7c184644..6fe2e3fc08e 100644 --- a/src/librustc_back/target/x86_64_unknown_netbsd.rs +++ b/src/librustc_back/target/x86_64_unknown_netbsd.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::netbsd_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); Ok(Target { llvm_target: "x86_64-unknown-netbsd".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "netbsd".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_unknown_openbsd.rs b/src/librustc_back/target/x86_64_unknown_openbsd.rs index e9d645b0d38..b292b5fc1e4 100644 --- a/src/librustc_back/target/x86_64_unknown_openbsd.rs +++ b/src/librustc_back/target/x86_64_unknown_openbsd.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::openbsd_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); Ok(Target { llvm_target: "x86_64-unknown-openbsd".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "openbsd".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_back/target/x86_64_unknown_redox.rs b/src/librustc_back/target/x86_64_unknown_redox.rs index cecac06b235..a693e76099b 100644 --- a/src/librustc_back/target/x86_64_unknown_redox.rs +++ b/src/librustc_back/target/x86_64_unknown_redox.rs @@ -8,13 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { let mut base = super::redox_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); - base.pre_link_args.push("-m64".to_string()); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); Ok(Target { llvm_target: "x86_64-unknown-redox".to_string(), @@ -25,6 +26,7 @@ pub fn target() -> TargetResult { target_os: "redox".to_string(), target_env: "".to_string(), target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, options: base, }) } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 12a1ffa2767..66380079a8b 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -707,13 +707,16 @@ fn link_natively(sess: &Session, outputs: &OutputFilenames, tmpdir: &Path) { info!("preparing {:?} from {:?} to {:?}", crate_type, objects, out_filename); + let flavor = sess.linker_flavor(); // The invocations of cc share some flags across platforms let (pname, mut cmd, extra) = get_linker(sess); cmd.env("PATH", command_path(sess, extra)); let root = sess.target_filesearch(PathKind::Native).get_lib_path(); - cmd.args(&sess.target.target.options.pre_link_args); + if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) { + cmd.args(args); + } let pre_link_objects = if crate_type == config::CrateTypeExecutable { &sess.target.target.options.pre_link_objects_exe @@ -739,11 +742,15 @@ fn link_natively(sess: &Session, objects, out_filename, outputs, trans); cmd = linker.finalize(); } - cmd.args(&sess.target.target.options.late_link_args); + if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) { + cmd.args(args); + } for obj in &sess.target.target.options.post_link_objects { cmd.arg(root.join(obj)); } - cmd.args(&sess.target.target.options.post_link_args); + if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) { + cmd.args(args); + } if sess.opts.debugging_opts.print_link_args { println!("{:?}", &cmd); diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index a178d17a7c2..61c57f00de7 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::collections::HashMap; -use std::ffi::OsString; +use std::ffi::{OsStr, OsString}; use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufWriter}; @@ -22,6 +22,7 @@ use back::archive; use back::symbol_export::{self, ExportedSymbols}; use middle::dependency_format::Linkage; use rustc::hir::def_id::{LOCAL_CRATE, CrateNum}; +use rustc_back::LinkerFlavor; use session::Session; use session::config::{self, CrateType, OptLevel, DebugInfoLevel}; use serialize::{json, Encoder}; @@ -45,25 +46,39 @@ impl<'a, 'tcx> LinkerInfo { pub fn to_linker(&'a self, cmd: Command, sess: &'a Session) -> Box<Linker+'a> { - if sess.target.target.options.is_like_msvc { - Box::new(MsvcLinker { - cmd: cmd, - sess: sess, - info: self - }) as Box<Linker> - } else if sess.target.target.options.is_like_emscripten { - Box::new(EmLinker { - cmd: cmd, - sess: sess, - info: self - }) as Box<Linker> - } else { - Box::new(GnuLinker { - cmd: cmd, - sess: sess, - info: self, - hinted_static: false, - }) as Box<Linker> + match sess.linker_flavor() { + LinkerFlavor::Msvc => { + Box::new(MsvcLinker { + cmd: cmd, + sess: sess, + info: self + }) as Box<Linker> + } + LinkerFlavor::Em => { + Box::new(EmLinker { + cmd: cmd, + sess: sess, + info: self + }) as Box<Linker> + } + LinkerFlavor::Gcc => { + Box::new(GccLinker { + cmd: cmd, + sess: sess, + info: self, + hinted_static: false, + is_ld: false, + }) as Box<Linker> + } + LinkerFlavor::Ld => { + Box::new(GccLinker { + cmd: cmd, + sess: sess, + info: self, + hinted_static: false, + is_ld: true, + }) as Box<Linker> + } } } } @@ -100,14 +115,32 @@ pub trait Linker { fn finalize(&mut self) -> Command; } -pub struct GnuLinker<'a> { +pub struct GccLinker<'a> { cmd: Command, sess: &'a Session, info: &'a LinkerInfo, hinted_static: bool, // Keeps track of the current hinting mode. + // Link as ld + is_ld: bool, } -impl<'a> GnuLinker<'a> { +impl<'a> GccLinker<'a> { + /// Argument that must be passed *directly* to the linker + /// + /// These arguments need to be prepended with '-Wl,' when a gcc-style linker is used + fn linker_arg<S>(&mut self, arg: S) -> &mut Self + where S: AsRef<OsStr> + { + if !self.is_ld { + let mut os = OsString::from("-Wl,"); + os.push(arg.as_ref()); + self.cmd.arg(os); + } else { + self.cmd.arg(arg); + } + self + } + fn takes_hints(&self) -> bool { !self.sess.target.target.options.is_like_osx } @@ -119,7 +152,7 @@ impl<'a> GnuLinker<'a> { fn hint_static(&mut self) { if !self.takes_hints() { return } if !self.hinted_static { - self.cmd.arg("-Wl,-Bstatic"); + self.linker_arg("-Bstatic"); self.hinted_static = true; } } @@ -127,13 +160,13 @@ impl<'a> GnuLinker<'a> { fn hint_dynamic(&mut self) { if !self.takes_hints() { return } if self.hinted_static { - self.cmd.arg("-Wl,-Bdynamic"); + self.linker_arg("-Bdynamic"); self.hinted_static = false; } } } -impl<'a> Linker for GnuLinker<'a> { +impl<'a> Linker for GccLinker<'a> { fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg("-l").arg(lib); } fn link_staticlib(&mut self, lib: &str) { self.hint_static(); self.cmd.arg("-l").arg(lib); } fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); } @@ -164,27 +197,26 @@ impl<'a> Linker for GnuLinker<'a> { self.hint_static(); let target = &self.sess.target.target; if !target.options.is_like_osx { - self.cmd.arg("-Wl,--whole-archive") - .arg("-l").arg(lib) - .arg("-Wl,--no-whole-archive"); + self.linker_arg("--whole-archive").cmd.arg("-l").arg(lib); + self.linker_arg("--no-whole-archive"); } else { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. - let mut v = OsString::from("-Wl,-force_load,"); + let mut v = OsString::from("-force_load,"); v.push(&archive::find_library(lib, search_path, &self.sess)); - self.cmd.arg(&v); + self.linker_arg(&v); } } fn link_whole_rlib(&mut self, lib: &Path) { self.hint_static(); if self.sess.target.target.options.is_like_osx { - let mut v = OsString::from("-Wl,-force_load,"); + let mut v = OsString::from("-force_load,"); v.push(lib); - self.cmd.arg(&v); + self.linker_arg(&v); } else { - self.cmd.arg("-Wl,--whole-archive").arg(lib) - .arg("-Wl,--no-whole-archive"); + self.linker_arg("--whole-archive").cmd.arg(lib); + self.linker_arg("--no-whole-archive"); } } @@ -204,10 +236,10 @@ impl<'a> Linker for GnuLinker<'a> { // for partial linking when using multiple codegen units (-r). So we // insert it here. if self.sess.target.target.options.is_like_osx { - self.cmd.arg("-Wl,-dead_strip"); + self.linker_arg("-dead_strip"); } else if self.sess.target.target.options.is_like_solaris { - self.cmd.arg("-Wl,-z"); - self.cmd.arg("-Wl,ignore"); + self.linker_arg("-z"); + self.linker_arg("ignore"); // If we're building a dylib, we don't use --gc-sections because LLVM // has already done the best it can do, and we also don't want to @@ -215,7 +247,7 @@ impl<'a> Linker for GnuLinker<'a> { // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67% // reduction. } else if !keep_metadata { - self.cmd.arg("-Wl,--gc-sections"); + self.linker_arg("--gc-sections"); } } @@ -226,7 +258,7 @@ impl<'a> Linker for GnuLinker<'a> { // need a numeric argument, but other linkers do. if self.sess.opts.optimize == config::OptLevel::Default || self.sess.opts.optimize == config::OptLevel::Aggressive { - self.cmd.arg("-Wl,-O1"); + self.linker_arg("-O1"); } } @@ -235,13 +267,16 @@ impl<'a> Linker for GnuLinker<'a> { } fn no_default_libraries(&mut self) { - self.cmd.arg("-nodefaultlibs"); + if !self.is_ld { + self.cmd.arg("-nodefaultlibs"); + } } fn build_dylib(&mut self, out_filename: &Path) { // On mac we need to tell the linker to let this library be rpathed if self.sess.target.target.options.is_like_osx { - self.cmd.args(&["-dynamiclib", "-Wl,-dylib"]); + self.cmd.arg("-dynamiclib"); + self.linker_arg("-dylib"); // Note that the `osx_rpath_install_name` option here is a hack // purely to support rustbuild right now, we should get a more @@ -249,9 +284,9 @@ impl<'a> Linker for GnuLinker<'a> { // the right `-Wl,-install_name` with an `@rpath` in it. if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name { - let mut v = OsString::from("-Wl,-install_name,@rpath/"); + let mut v = OsString::from("-install_name,@rpath/"); v.push(out_filename.file_name().unwrap()); - self.cmd.arg(&v); + self.linker_arg(&v); } } else { self.cmd.arg("-shared"); @@ -307,11 +342,20 @@ impl<'a> Linker for GnuLinker<'a> { } if self.sess.target.target.options.is_like_osx { - arg.push("-Wl,-exported_symbols_list,"); + if !self.is_ld { + arg.push("-Wl,") + } + arg.push("-exported_symbols_list,"); } else if self.sess.target.target.options.is_like_solaris { - arg.push("-Wl,-M,"); + if !self.is_ld { + arg.push("-Wl,") + } + arg.push("-M,"); } else { - arg.push("-Wl,--version-script="); + if !self.is_ld { + arg.push("-Wl,") + } + arg.push("--version-script="); } arg.push(&path); @@ -319,7 +363,7 @@ impl<'a> Linker for GnuLinker<'a> { } fn subsystem(&mut self, subsystem: &str) { - self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem)); + self.linker_arg(&format!("--subsystem,{}", subsystem)); } fn finalize(&mut self) -> Command { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c68e2ae3468..08762ccf04b 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -343,6 +343,9 @@ declare_features! ( // Used to preserve symbols (see llvm.used) (active, used, "1.18.0", Some(40289)), + + // Hack to document `-Z linker-flavor` in The Unstable Book + (active, linker_flavor, "1.18.0", Some(41142)), ); declare_features! ( diff --git a/src/test/compile-fail/feature-gate-linker-flavor.rs b/src/test/compile-fail/feature-gate-linker-flavor.rs new file mode 100644 index 00000000000..955ec39cda1 --- /dev/null +++ b/src/test/compile-fail/feature-gate-linker-flavor.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This is a fake compile fail test as there's no way to generate a +// `#![feature(linker_flavor)]` error. The only reason we have a `linker_flavor` +// feature gate is to be able to document `-Z linker-flavor` in the unstable +// book + +#[used] +fn foo() {} +//~^^ ERROR the `#[used]` attribute is an experimental feature + +fn main() {} diff --git a/src/test/run-make/target-specs/my-awesome-platform.json b/src/test/run-make/target-specs/my-awesome-platform.json index b7083c2776a..14515ad7f00 100644 --- a/src/test/run-make/target-specs/my-awesome-platform.json +++ b/src/test/run-make/target-specs/my-awesome-platform.json @@ -1,5 +1,6 @@ { "data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", + "linker-flavor": "gcc", "llvm-target": "i686-unknown-linux-gnu", "target-endian": "little", "target-pointer-width": "32", diff --git a/src/test/run-make/target-specs/my-incomplete-platform.json b/src/test/run-make/target-specs/my-incomplete-platform.json index 053f2dd6335..74787b28d22 100644 --- a/src/test/run-make/target-specs/my-incomplete-platform.json +++ b/src/test/run-make/target-specs/my-incomplete-platform.json @@ -1,5 +1,6 @@ { "data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32", + "linker-flavor": "gcc", "target-endian": "little", "target-pointer-width": "32", "arch": "x86", diff --git a/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json b/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json index 688bbe46bfa..cfe152f9e87 100644 --- a/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json +++ b/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json @@ -1,6 +1,7 @@ { "pre-link-args": ["-m64"], "data-layout": "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128", + "linker-flavor": "gcc", "llvm-target": "x86_64-unknown-linux-gnu", "target-endian": "little", "target-pointer-width": "64", |
