]> git.lizzy.rs Git - rust.git/commitdiff
-Z linker-flavor
authorJorge Aparicio <japaricious@gmail.com>
Tue, 21 Feb 2017 19:47:15 +0000 (14:47 -0500)
committerJorge Aparicio <japaricious@gmail.com>
Fri, 7 Apr 2017 15:52:42 +0000 (10:52 -0500)
This patch adds a `-Z linker-flavor` flag to rustc which can be used to invoke
the linker using a different interface.

For example, by default rustc assumes that all the Linux targets will be linked
using GCC. This makes it impossible to use LLD as a linker using just `-C
linker=ld.lld` because that will invoke LLD with invalid command line
arguments. (e.g. rustc will pass -Wl,--gc-sections to LLD but LLD doesn't
understand that; --gc-sections would be the right argument)

With this patch one can pass `-Z linker-flavor=ld` to rustc to invoke the linker
using a LD-like interface. This way, `rustc -C linker=ld.lld -Z
linker-flavor=ld` will invoke LLD with the right arguments.

`-Z linker-flavor` accepts 4 different arguments: `em` (emcc), `ld`,
`gcc`, `msvc` (link.exe). `em`, `gnu` and `msvc` cover all the existing linker
interfaces. `ld` is a new flavor for interfacing GNU's ld and LLD.

This patch also changes target specifications. `linker-flavor` is now a
mandatory field that specifies the *default* linker flavor that the target will
use. This change also makes the linker interface *explicit*; before, it used to
be derived from other fields like linker-is-gnu, is-like-msvc,
is-like-emscripten, etc.

Another change to target specifications is that the fields `pre-link-args`,
`post-link-args` and `late-link-args` now expect a map from flavor to linker
arguments.

``` diff
-    "pre-link-args": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"],
+    "pre-link-args": {
+        "gcc": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"],
+        "ld": ["--as-needed", "-z,-noexecstack"],
+    },
```

[breaking-change]  for users of custom targets specifications

89 files changed:
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc_back/lib.rs
src/librustc_back/target/aarch64_apple_ios.rs
src/librustc_back/target/aarch64_linux_android.rs
src/librustc_back/target/aarch64_unknown_freebsd.rs
src/librustc_back/target/aarch64_unknown_fuchsia.rs
src/librustc_back/target/aarch64_unknown_linux_gnu.rs
src/librustc_back/target/android_base.rs
src/librustc_back/target/apple_base.rs
src/librustc_back/target/apple_ios_base.rs
src/librustc_back/target/arm_linux_androideabi.rs
src/librustc_back/target/arm_unknown_linux_gnueabi.rs
src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
src/librustc_back/target/arm_unknown_linux_musleabi.rs
src/librustc_back/target/arm_unknown_linux_musleabihf.rs
src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs
src/librustc_back/target/armv7_apple_ios.rs
src/librustc_back/target/armv7_linux_androideabi.rs
src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
src/librustc_back/target/armv7s_apple_ios.rs
src/librustc_back/target/asmjs_unknown_emscripten.rs
src/librustc_back/target/dragonfly_base.rs
src/librustc_back/target/freebsd_base.rs
src/librustc_back/target/fuchsia_base.rs
src/librustc_back/target/i386_apple_ios.rs
src/librustc_back/target/i686_apple_darwin.rs
src/librustc_back/target/i686_linux_android.rs
src/librustc_back/target/i686_pc_windows_gnu.rs
src/librustc_back/target/i686_pc_windows_msvc.rs
src/librustc_back/target/i686_unknown_dragonfly.rs
src/librustc_back/target/i686_unknown_freebsd.rs
src/librustc_back/target/i686_unknown_haiku.rs
src/librustc_back/target/i686_unknown_linux_gnu.rs
src/librustc_back/target/i686_unknown_linux_musl.rs
src/librustc_back/target/i686_unknown_netbsd.rs
src/librustc_back/target/i686_unknown_openbsd.rs
src/librustc_back/target/le32_unknown_nacl.rs
src/librustc_back/target/linux_base.rs
src/librustc_back/target/linux_musl_base.rs
src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs
src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs
src/librustc_back/target/mips_unknown_linux_gnu.rs
src/librustc_back/target/mips_unknown_linux_musl.rs
src/librustc_back/target/mips_unknown_linux_uclibc.rs
src/librustc_back/target/mipsel_unknown_linux_gnu.rs
src/librustc_back/target/mipsel_unknown_linux_musl.rs
src/librustc_back/target/mipsel_unknown_linux_uclibc.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/netbsd_base.rs
src/librustc_back/target/openbsd_base.rs
src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
src/librustc_back/target/powerpc_unknown_linux_gnu.rs
src/librustc_back/target/redox_base.rs
src/librustc_back/target/s390x_unknown_linux_gnu.rs
src/librustc_back/target/sparc64_unknown_linux_gnu.rs
src/librustc_back/target/sparc64_unknown_netbsd.rs
src/librustc_back/target/sparcv9_sun_solaris.rs
src/librustc_back/target/thumbv6m_none_eabi.rs
src/librustc_back/target/thumbv7em_none_eabi.rs
src/librustc_back/target/thumbv7em_none_eabihf.rs
src/librustc_back/target/thumbv7m_none_eabi.rs
src/librustc_back/target/wasm32_unknown_emscripten.rs
src/librustc_back/target/windows_base.rs
src/librustc_back/target/windows_msvc_base.rs
src/librustc_back/target/x86_64_apple_darwin.rs
src/librustc_back/target/x86_64_apple_ios.rs
src/librustc_back/target/x86_64_pc_windows_gnu.rs
src/librustc_back/target/x86_64_pc_windows_msvc.rs
src/librustc_back/target/x86_64_rumprun_netbsd.rs
src/librustc_back/target/x86_64_sun_solaris.rs
src/librustc_back/target/x86_64_unknown_bitrig.rs
src/librustc_back/target/x86_64_unknown_dragonfly.rs
src/librustc_back/target/x86_64_unknown_freebsd.rs
src/librustc_back/target/x86_64_unknown_fuchsia.rs
src/librustc_back/target/x86_64_unknown_haiku.rs
src/librustc_back/target/x86_64_unknown_linux_gnu.rs
src/librustc_back/target/x86_64_unknown_linux_musl.rs
src/librustc_back/target/x86_64_unknown_netbsd.rs
src/librustc_back/target/x86_64_unknown_openbsd.rs
src/librustc_back/target/x86_64_unknown_redox.rs
src/librustc_llvm/lib.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs
src/test/run-make/target-specs/my-awesome-platform.json
src/test/run-make/target-specs/my-incomplete-platform.json
src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json

index a0603c5795247c75fb98911daae1c1b3c7ddd284..ef825a6854cec9b4ad7ea1f30e8c66206f05a2ec 100644 (file)
@@ -19,7 +19,7 @@
 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 @@ mod $mod_desc {
             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 @@ fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
             }
             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 @@ fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
           "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 {
index 3ba82f34c3266a804fece8554e94707fb562c796..70b2809ccbed2ba0ada1744a840cb35605350101 100644 (file)
@@ -36,7 +36,7 @@
 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 @@ pub fn lto(&self) -> bool {
     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
     }
index 000e4eb59bf05c7f65981c10f58629c64030896d..6679cc73029c7e119edd15ff81fdb00f36d5c52d 100644 (file)
 
 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,
index 5ef79359140f775bc6bd6396c22926dfd0d04b5d..802a8c77db05bc3c77cad41642f91dfece4b24ff 100644 (file)
@@ -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,
index 54eead94986cc9b441854d5ccd207bdaa6d27d9a..7d8610b4a36841bc277d218bfd1e31c6c3ca610e 100644 (file)
@@ -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
index 3c5d6308ee6bad7b052ae03eb71991b809554c52..c5cfff0be03ad05851fb1461454492a264dc0b7b 100644 (file)
@@ -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
index 6ba1732e67f7930937fc493cda5ee3c4aa92b776..5d680504a02d00bff5bb9f1391977cdc4cf1447c 100644 (file)
@@ -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
index 5f6335d405f5ea40fe49b1e7827c51a9ecc6ead1..043bd881c7290c6062cde4331f495641e9b10b45 100644 (file)
@@ -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
index 9791520e9339bbd8ad6908b74e70256abbf83673..49baa1b96cee3b4bdf61dec87801898f386f7ea1 100644 (file)
@@ -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;
index 3a551a2b124b7cc69edc9856c2660f05a15178b9..159f93a74c68352276ec630b8a2d9b6b05259c9d 100644 (file)
@@ -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()
index 17492b8bdcb64bf6537b9e71964872d8639ca41a..2e7d30d969ec4b140c773d744f0e41ca0d9a161f 100644 (file)
@@ -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 {
index c7d2df4344cb1efad4e8b22e6e4551751e25cbb5..bccd5a41ab1155b64d7c5cb9baf1e17b4434613f 100644 (file)
@@ -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
index 77d35edfbd09cc465ef90a0a9afe03684a9d56d5..165d34fe6c7cee980c32489f0e8eec8ecfd35bf1 100644 (file)
@@ -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(),
index b183412be1934853bed150bfe546c3141d014cd3..731021d979bc4158db8115bcf560a20f9b569f8e 100644 (file)
@@ -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(),
index 261d4353c7a09f6b2623b2c109ed7df084e41cb0..f81bcd78b03aada993d5d78bb13b759df4685a9e 100644 (file)
@@ -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
index 1443dcf5bad418327f65be7807ee1bf31f4fe504..6c47678ede6adb4067417f33a56504dbc4c57e6d 100644 (file)
@@ -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
index 37216e20762d4970754319718206dcb94899f2b1..200c6ab74cc6db2a6c9dadd977b908a3a5aafe62 100644 (file)
@@ -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 {
         }
     })
 }
-
index 9e9c443930624311c36e6f8483f8624b5bcf9f13..4d8745828329431459dee1f0120ffff270a92bbf 100644 (file)
@@ -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),
index 36f409b7948c27ace4ef2e8b6698bff9036ac2f9..0c90e834006f16734761a850aa3fc694abdaf832 100644 (file)
@@ -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
index 96ccedd5bea5c4b59a0f6a37349d97550e8784c9..d3a6a68449c39f0ad217d7ed4108bbd4bf3e7538 100644 (file)
@@ -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 {
         }
     })
 }
-
index 8f66e6a4f58d484ac385ff5830575eb7fcb47436..5086cd44f7ac947522ba5688231a3e095c1fee24 100644 (file)
@@ -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
index 6edde6e73efd34415ce62bd70a9b77dd347dcfdc..96c89a7ed3bd58e21caebb77511832f1f1e35468 100644 (file)
@@ -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),
index 4d38b0d1705962afa24e58c81801073ea0569d67..b884d4e54101e8ef6eac7705b1f4048b2d99173a 100644 (file)
@@ -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,
     })
 }
index dca33e45af7c7ffc656b02609dedf9dc537b4fa5..e44cd393289be3a23afdd0911c4b2e5e5c7dcb6f 100644 (file)
@@ -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()
index dca33e45af7c7ffc656b02609dedf9dc537b4fa5..e44cd393289be3a23afdd0911c4b2e5e5c7dcb6f 100644 (file)
@@ -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()
index 8c517224201b2fe7b2e44b5a7812055c9a5cbfb0..c6207cdc4d9c18efa6a76a1102af11b7bb897024 100644 (file)
@@ -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,
index 319ada4f8e17c11b05f56aa50fdebd75c805aca2..a6383179f3ae60292fb2b9baf7d38430a6002a71 100644 (file)
@@ -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
index d3b09d9a0f1121354a76ce92cb56194e27b0b031..6b14972e9f7543d3613b8f0c8e16071c4f4b00ab 100644 (file)
@@ -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,
     })
 }
index f8a8f5a3500befb6a1d7a789e7fb2ff078d07421..a5390cbfb725803f68587dd303e2e664da7e9dff 100644 (file)
@@ -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,
     })
 }
index 29477261392079332e3e03ed3ba4b13c3fa3c992..4a736a93be7d7867fc9dd60d69c1e65cb72505ff 100644 (file)
@@ -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,
     })
 }
index 2290d2057f13076f28ae40ba66e9a9bbaeceaf3e..17fe306804f4a673abfe39d48dc16de527c1ca43 100644 (file)
@@ -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,
     })
 }
index d8f8431e66e7fa51b3937a8ced9dfedb78d09c3f..052bc23c119ea0a85e013153411d2aae42b69ff6 100644 (file)
@@ -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,
     })
 }
index ddbc74f25c9cdd9533283ea759a040239b808a26..d77a9cca2683d9904f50a90320b1093cf34ba035 100644 (file)
@@ -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,
     })
 }
index 9078206c9e069cf3b98ee93c19626d217299d0c3..b0e67bd90ddde351fbc689c37d2b61d69b34912f 100644 (file)
@@ -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,
     })
 }
index bf9c28b0c10e5ada26c1c2b13462aab4aeb4ff07..3c5c10676260ef9dd847589abd383bdfd51c17c0 100644 (file)
@@ -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,
     })
 }
index ced59448f7f65d83b3118368408ab92a471dc7b1..3ed8c94d0bf2a834c3798fe1897e5c00736ec04a 100644 (file)
@@ -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,
     })
 }
index e7e2ee3f9056a09f8af19394836052c9b8fc81e9..fc92e5aee6af1857bb603bbf65fa460eca8b54c6 100644 (file)
@@ -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,
     })
 }
index 81efd37386a0f9232148e4d83c068526f3c634be..7ef68bd6d9c3a3164c83a6817ca4fe863a0d2127 100644 (file)
@@ -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,
     })
 }
index 891e7dda14a2a4d931e3171966e97d4e7a53fb1e..f4265e0eb1462d2bd7bc5abf466088aa369ad869 100644 (file)
@@ -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,
     })
 }
index 4b2ae9c8e699c1e23ca0f056afff69d02faf1ea1..722d2fa16ef7a06a23689366bbf3af017cc0984f 100644 (file)
@@ -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,
index 18cca425a32c8c43452f34f304d3c8cc5cf4bbf3..236f2c1ef0aa3a983b1b3df47eca904fa8264d22 100644 (file)
@@ -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
index c284840ecb4bdbdc3b06714732a85fabbe51d93d..038a70ed6b17ee3e700405f71d6a988e8f9b094a 100644 (file)
@@ -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(),
index 17895836fe87b54dba7020dbd5b2d00be9c0ecfd..aed4c4fbb08deb90479fac1533c2d6e848b90847 100644 (file)
@@ -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(),
index a6d8fae2536cae8628ab3d3b09fb64553ff442d1..9ef61f9caddcdbaf6bd59001ca142f3e340f8d2b 100644 (file)
@@ -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(),
index e4a6d2a55d9813ea4ea188540edae6126447ff1d..f54790bab970b85b0c67d39b22386db08fca0e80 100644 (file)
@@ -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(),
index ccc64ea393b7885694640f22b6373ed7dfedf4f3..59c07efe0fdc1818fe7125413d9dceecf0a89c3d 100644 (file)
@@ -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(),
index 9b8b1d5713f1d950771a36d3da49fe750208d944..ec19cc1a536ad7f45a5b9efffdd6a8ec8630c291 100644 (file)
@@ -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(),
index 5693bddd0488a51c780e53dbc07c2e641748e345..00085d18e6d09eb7f8953993d866fc25e5b41a0d 100644 (file)
@@ -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(),
index 3acade5a474445f1431585dbc0d62a79fed5a369..b3ca2edec1eda57d60122665c2b3d6654d8e3fe7 100644 (file)
@@ -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(),
index 559418d2c4f5ffae02822040f3ed612b3d8b3085..ca6894a7b70411ae74cb94db2d386f09bc0aa3ae 100644 (file)
@@ -50,7 +50,7 @@
 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 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 @@ fn default() -> 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 @@ fn default() -> 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 @@ pub fn from_json(obj: Json) -> TargetResult {
             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 @@ macro_rules! key {
                         .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 @@ macro_rules! target_option_val {
                     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 @@ macro_rules! target_option_val {
         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);
index 57179a68afd8e9ccdc79bb1f459296277bca6339..63245fcae767b34841a6cf9448b21c2518ef1a6c 100644 (file)
@@ -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()
     }
index 12b8e8bdc88fd931e776664af40136cacf0afd81..2df9b8e03ff535866f8428d5ac9aa88f23693ba4 100644 (file)
@@ -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()
index 909c5488dcb70374eaae5535870fe9606428af24..55a5bfd1e674621bf02d294439bba4c10a1485a3 100644 (file)
@@ -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,
     })
 }
index a692346ca0ffeeb95a88bf2183f3eea8b6ca4f90..c22bc3b041a4ee2d41dd0903347015dbab12546b 100644 (file)
@@ -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,
     })
 }
index 284772c43319aedf193fd12af276ea1586adbd14..677d198b1a379a315158c8d13428fe5401ca4665 100644 (file)
@@ -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,
     })
 }
index c5e1e107753ffa80c56b543d5e04e29daa5c689b..f26a86d4bdc0f13c4bc60de2626eaf442e3e882b 100644 (file)
@@ -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,
index 671fb4f4319b35f5d1c592aee2ddf4145dac6524..cc8eb7c4e84243e281e54086220474d7f22c0366 100644 (file)
@@ -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,
     })
 }
index f627cc18f0b3d709dbdd513e0ad3de4fba6e2b43..1bd51ac62581f06ee4e5104607376285694473e5 100644 (file)
@@ -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,
     })
 }
index f30cebbc2d5a7e91c292eb875d10919794056b9f..bc65a17ce6ea93063743a2d44646133437201150 100644 (file)
@@ -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,
     })
 }
index c88e5a402f2f545e0719b0178848d9314730368d..122b38968a9c0355e74e258c11084408102be7fc 100644 (file)
@@ -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,
     })
 }
index 6c22f98538459ea5711308df1729b475ec60ab97..08bf145e5518ac8911a5ae34c676565437aaea80 100644 (file)
@@ -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
index ddad4e3624f3cef16a960f8f5058fcf82f2370e1..13f9cc5f65fb9bd3db0f2ba1fdd66b5a48e0a5c5 100644 (file)
@@ -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),
index a9fac48e8e5ac39c549ea88439af6d99851d8102..929b6db6fb2c60b7914139ddd3f80776c7d0d37e 100644 (file)
@@ -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
index ed61dd0459b4d7c23ac8a5012d83ba514d846a12..8d46e7cb90760bb5903a9b6dc29814edd8a18f91 100644 (file)
@@ -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),
index b1967fa8f37a7aea5c3052d48d45e24bfbbf4098..a51f59d6ff1925e9222fce68a01ef378c92dec12 100644 (file)
@@ -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,
     })
 }
index db02e142fcc8efac34aca9480845a87696be1cdf..9bde24a28dd9b253ed14c0a1a5f8e3fe4d244921 100644 (file)
@@ -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()
         ],
index efa215b419d7044fed385b8b176d2f664a6e3bc1..421f59aea93bf4acba458dd5622be1641f832746 100644 (file)
@@ -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()
index b3c1561dbcc0bb06f2556b1a68a1f34244388d41..8fd1b80430f44795aa62ff0749cc301988abfed3 100644 (file)
@@ -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,
     })
 }
index 7a58bb34ce7f6e67eeefb15074917a3ef5ab00c4..bbd81fd86ff578e2e2f9e4cb6576277f21879eb3 100644 (file)
@@ -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
index 321585cd65eb39020824daeaffc3da90b70164d9..10e88d88ee372c97fdb3b27c2479723cf1fa244c 100644 (file)
@@ -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,
     })
 }
index ea8909d213e80b79463cae221a7a634f679b5ca0..b07031c4bf1a3de5b13ba9d196a50b1d17860c8a 100644 (file)
@@ -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,
     })
 }
index 33137214396961a05e7fff8139bd7e341ad7da37..eea4389cfd64eaee7e5f8bfd79166ca552e470f6 100644 (file)
@@ -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,
     })
 }
index 8e4fd94e7bce4375afd14a991f5cb1b5cde92271..fe8691f36950dc5aa31807daf3de80a7e6eaaf7b 100644 (file)
@@ -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,
     })
 }
index eda16c29466b54ce5e8a2c2276dfb2ba261d034a..5f87fe177a98c04dfc21c04e5cfff594d06ff175 100644 (file)
@@ -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,
     })
 }
index 194efb8fc232254af9523d0ad249a1644bb46aa1..96f608409ffa7610ed9c28a3619f35b2b26e646c 100644 (file)
@@ -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,
     })
 }
index b127bee163b86ed5df3a610a3d00711eff51c024..500629a16808dd3f88125ec53dfd376bfb36c637 100644 (file)
@@ -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,
     })
 }
index 08fe17a556ecca1f74a5f81d7bc0a700ebd26eb0..6e37896d4148bd1790d10fc41b16f5a713db7b91 100644 (file)
@@ -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,
     })
 }
index 7cf0599037c1e97efd71fac637aac8fbfad3af4b..7fab9128b2952f538569539b637dafee5daf1d5c 100644 (file)
@@ -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,
     })
 }
index f95bcb556e57f0bf3ac2838e6c36f7acf67de42d..f73055cebaa2e2ff0f94a3cb2ce6eee402501989 100644 (file)
@@ -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,
     })
 }
index c3bf9dcca6ee4ff9e24d0e2522b3aae4a59a07e9..38b9c0bace52b1fe73530d66ab0f86549196706f 100644 (file)
@@ -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,
     })
 }
index 87a7c184644d57082215e8cf465c38674529f981..6fe2e3fc08e23e30de5bb716949d8d8d0a70c775 100644 (file)
@@ -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,
     })
 }
index e9d645b0d38f259f74f4a29d21aa2c1f3b08ba34..b292b5fc1e4e4720f6a771088509555b33299b4c 100644 (file)
@@ -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,
     })
 }
index cecac06b235275a6b18162e7b532c9168ff983c3..a693e76099bdafa27b8f013d58e56bd438cc50ac 100644 (file)
@@ -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,
     })
 }
index f300bf16145a736c92f95768eb911ada60f24c3e..6e34f551f5df7f669033345856bf468d6e845594 100644 (file)
@@ -422,3 +422,4 @@ fn drop(&mut self) {
         }
     }
 }
+#[link(name = "ffi")] extern {}
index 12a1ffa2767255aa325b6f3eff380d6fad49ca44..66380079a8b29038538e18324455f68bce83deb4 100644 (file)
@@ -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);
index a178d17a7c2d371f01e17ce87fc7cd22a41efab7..48e469e28ee31046021b92b839f2a27a95d6db98 100644 (file)
@@ -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::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 @@ pub fn new(scx: &SharedCrateContext<'a, 'tcx>,
     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 @@ fn takes_hints(&self) -> bool {
     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 @@ fn hint_static(&mut self) {
     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 @@ fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) {
         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 @@ fn gc_sections(&mut self, keep_metadata: bool) {
         // 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 @@ fn gc_sections(&mut self, keep_metadata: bool) {
         // --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 @@ fn optimize(&mut self) {
         // 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 @@ fn debuginfo(&mut self) {
     }
 
     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 @@ fn build_dylib(&mut self, out_filename: &Path) {
             // 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 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
         }
 
         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 @@ fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
     }
 
     fn subsystem(&mut self, subsystem: &str) {
-        self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem));
+        self.cmd.arg(&format!("--subsystem,{}", subsystem));
     }
 
     fn finalize(&mut self) -> Command {
index b7083c2776aeccd3f5575be4e55c25dc7222d0f9..14515ad7f00b91f9c4c140b6e5e15351d25968d2 100644 (file)
@@ -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",
index 053f2dd63358a9b9e832e5dbaaf7831e5752b445..74787b28d2233905382e8960af5b8ee003299867 100644 (file)
@@ -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",
index 688bbe46bfaf0593b6df26e2a1035ee0952ee272..cfe152f9e8728c0a3fb294de11c324d4210b9895 100644 (file)
@@ -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",