-Z linker-flavor

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
This commit is contained in:
Jorge Aparicio 2017-02-21 14:47:15 -05:00
parent c438c1fb39
commit 9d11b089ad
89 changed files with 598 additions and 240 deletions

View File

@ -19,7 +19,7 @@ pub use self::DebugInfoLevel::*;
use session::{early_error, early_warn, Session};
use session::search_paths::SearchPaths;
use rustc_back::PanicStrategy;
use rustc_back::{LinkerFlavor, PanicStrategy};
use rustc_back::target::Target;
use lint;
use middle::cstore;
@ -641,12 +641,14 @@ macro_rules! options {
Some("either `panic` or `abort`");
pub const parse_sanitizer: Option<&'static str> =
Some("one of: `address`, `leak`, `memory` or `thread`");
pub const parse_linker_flavor: Option<&'static str> =
Some(::rustc_back::LinkerFlavor::one_of());
}
#[allow(dead_code)]
mod $mod_set {
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer};
use rustc_back::PanicStrategy;
use rustc_back::{LinkerFlavor, PanicStrategy};
$(
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
@ -777,6 +779,14 @@ macro_rules! options {
}
true
}
fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
match v.and_then(LinkerFlavor::from_str) {
Some(lf) => *slote = Some(lf),
_ => return false,
}
true
}
}
) }
@ -979,6 +989,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"pass `-install_name @rpath/...` to the macOS linker"),
sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED],
"Use a sanitizer"),
linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
"Linker flavor"),
}
pub fn default_lib_output() -> CrateType {

View File

@ -36,7 +36,7 @@ use syntax::{ast, codemap};
use syntax::feature_gate::AttributeType;
use syntax_pos::{Span, MultiSpan};
use rustc_back::PanicStrategy;
use rustc_back::{LinkerFlavor, PanicStrategy};
use rustc_back::target::Target;
use rustc_data_structures::flock;
use llvm;
@ -363,6 +363,9 @@ impl Session {
pub fn panic_strategy(&self) -> PanicStrategy {
self.opts.cg.panic.unwrap_or(self.target.target.options.panic_strategy)
}
pub fn linker_flavor(&self) -> LinkerFlavor {
self.opts.debugging_opts.linker_flavor.unwrap_or(self.target.target.linker_flavor)
}
pub fn no_landing_pads(&self) -> bool {
self.opts.debugging_opts.no_landing_pads || self.panic_strategy() == PanicStrategy::Abort
}

View File

@ -52,6 +52,48 @@ pub mod dynamic_lib;
use serialize::json::{Json, ToJson};
macro_rules! linker_flavor {
($(($variant:ident, $string:expr),)+) => {
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
RustcEncodable, RustcDecodable)]
pub enum LinkerFlavor {
$($variant,)+
}
impl LinkerFlavor {
pub const fn one_of() -> &'static str {
concat!("one of: ", $($string, " ",)+)
}
pub fn from_str(s: &str) -> Option<Self> {
Some(match s {
$($string => LinkerFlavor::$variant,)+
_ => return None,
})
}
pub fn desc(&self) -> &str {
match *self {
$(LinkerFlavor::$variant => $string,)+
}
}
}
impl ToJson for LinkerFlavor {
fn to_json(&self) -> Json {
self.desc().to_json()
}
}
}
}
linker_flavor! {
(Em, "em"),
(Gcc, "gcc"),
(Ld, "ld"),
(Msvc, "msvc"),
}
#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
pub enum PanicStrategy {
Unwind,

View 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,

View 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

View 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

View 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

View 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

View 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;

View 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()

View 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 {

View 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

View 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(),

View 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(),

View 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

View 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

View 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 {
}
})
}

View 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),

View 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

View 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 {
}
})
}

View 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

View 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),

View 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,
})
}

View 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()

View 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()

View 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,

View 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

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,

View 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

View 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(),

View 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(),

View 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(),

View 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(),

View 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(),

View 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(),

View 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(),

View 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(),

View File

@ -50,7 +50,7 @@ use std::default::Default;
use std::io::prelude::*;
use syntax::abi::{Abi, lookup as lookup_abi};
use PanicStrategy;
use {LinkerFlavor, PanicStrategy};
mod android_base;
mod apple_base;
@ -72,6 +72,7 @@ mod thumb_base;
mod fuchsia_base;
mod redox_base;
pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>;
pub type TargetResult = Result<Target, String>;
macro_rules! supported_targets {
@ -241,6 +242,8 @@ pub struct Target {
pub arch: String,
/// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
pub data_layout: String,
/// Linker flavor
pub linker_flavor: LinkerFlavor,
/// Optional settings with defaults.
pub options: TargetOptions,
}
@ -261,7 +264,7 @@ pub struct TargetOptions {
/// Linker arguments that are unconditionally passed *before* any
/// user-defined libraries.
pub pre_link_args: Vec<String>,
pub pre_link_args: LinkArgs,
/// Objects to link before all others, always found within the
/// sysroot folder.
pub pre_link_objects_exe: Vec<String>, // ... when linking an executable
@ -269,13 +272,13 @@ pub struct TargetOptions {
/// Linker arguments that are unconditionally passed after any
/// user-defined but before post_link_objects. Standard platform
/// libraries that should be always be linked to, usually go here.
pub late_link_args: Vec<String>,
pub late_link_args: LinkArgs,
/// Objects to link after all others, always found within the
/// sysroot folder.
pub post_link_objects: Vec<String>,
/// Linker arguments that are unconditionally passed *after* any
/// user-defined libraries.
pub post_link_args: Vec<String>,
pub post_link_args: LinkArgs,
/// Extra arguments to pass to the external assembler (when used)
pub asm_args: Vec<String>,
@ -412,8 +415,8 @@ impl Default for TargetOptions {
is_builtin: false,
linker: option_env!("CFG_DEFAULT_LINKER").unwrap_or("cc").to_string(),
ar: option_env!("CFG_DEFAULT_AR").unwrap_or("ar").to_string(),
pre_link_args: Vec::new(),
post_link_args: Vec::new(),
pre_link_args: LinkArgs::new(),
post_link_args: LinkArgs::new(),
asm_args: Vec::new(),
cpu: "generic".to_string(),
features: "".to_string(),
@ -445,7 +448,7 @@ impl Default for TargetOptions {
pre_link_objects_exe: Vec::new(),
pre_link_objects_dll: Vec::new(),
post_link_objects: Vec::new(),
late_link_args: Vec::new(),
late_link_args: LinkArgs::new(),
archive_format: "gnu".to_string(),
custom_unwind_resume: false,
lib_allocation_crate: "alloc_system".to_string(),
@ -529,6 +532,10 @@ impl Target {
target_os: get_req_field("os")?,
target_env: get_opt_field("env", ""),
target_vendor: get_opt_field("vendor", "unknown"),
linker_flavor: LinkerFlavor::from_str(&*get_req_field("linker-flavor")?)
.ok_or_else(|| {
format!("linker flavor must be {}", LinkerFlavor::one_of())
})?,
options: Default::default(),
};
@ -579,17 +586,49 @@ impl Target {
.map(|s| s.to_string() );
}
} );
($key_name:ident, LinkerFlavor) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.find(&name[..]).and_then(|o| o.as_string().map(|s| {
LinkerFlavor::from_str(&s).ok_or_else(|| {
Err(format!("'{}' is not a valid value for linker-flavor. \
Use 'em', 'gcc', 'ld' or 'msvc.", s))
})
})).unwrap_or(Ok(()))
} );
($key_name:ident, link_args) => ( {
let name = (stringify!($key_name)).replace("_", "-");
if let Some(obj) = obj.find(&name[..]).and_then(|o| o.as_object()) {
let mut args = LinkArgs::new();
for (k, v) in obj {
let k = LinkerFlavor::from_str(&k).ok_or_else(|| {
format!("{}: '{}' is not a valid value for linker-flavor. \
Use 'em', 'gcc', 'ld' or 'msvc'", name, k)
})?;
let v = v.as_array().map(|a| {
a
.iter()
.filter_map(|o| o.as_string())
.map(|s| s.to_owned())
.collect::<Vec<_>>()
}).unwrap_or(vec![]);
args.insert(k, v);
}
base.options.$key_name = args;
}
} );
}
key!(is_builtin, bool);
key!(linker);
key!(ar);
key!(pre_link_args, list);
key!(pre_link_args, link_args);
key!(pre_link_objects_exe, list);
key!(pre_link_objects_dll, list);
key!(late_link_args, list);
key!(late_link_args, link_args);
key!(post_link_objects, list);
key!(post_link_args, list);
key!(post_link_args, link_args);
key!(asm_args, list);
key!(cpu);
key!(features);
@ -734,6 +773,16 @@ impl ToJson for Target {
d.insert(name.to_string(), self.options.$attr.to_json());
}
} );
(link_args - $attr:ident) => ( {
let name = (stringify!($attr)).replace("_", "-");
if default.$attr != self.options.$attr {
let obj = self.options.$attr
.iter()
.map(|(k, v)| (k.desc().to_owned(), v.clone()))
.collect::<BTreeMap<_, _>>();
d.insert(name.to_string(), obj.to_json());
}
} );
}
target_val!(llvm_target);
@ -743,18 +792,18 @@ impl ToJson for Target {
target_val!(target_os, "os");
target_val!(target_env, "env");
target_val!(target_vendor, "vendor");
target_val!(arch);
target_val!(data_layout);
target_val!(linker_flavor);
target_option_val!(is_builtin);
target_option_val!(linker);
target_option_val!(ar);
target_option_val!(pre_link_args);
target_option_val!(link_args - pre_link_args);
target_option_val!(pre_link_objects_exe);
target_option_val!(pre_link_objects_dll);
target_option_val!(late_link_args);
target_option_val!(link_args - late_link_args);
target_option_val!(post_link_objects);
target_option_val!(post_link_args);
target_option_val!(link_args - post_link_args);
target_option_val!(asm_args);
target_option_val!(cpu);
target_option_val!(features);

View 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()
}

View 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()

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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

View 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),

View 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

View 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),

View 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,
})
}

View 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()
],

View 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()

View 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,
})
}

View 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

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View 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,
})
}

View File

@ -422,3 +422,4 @@ impl Drop for OperandBundleDef {
}
}
}
#[link(name = "ffi")] extern {}

View 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);

View 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::archive;
use back::symbol_export::{self, ExportedSymbols};
use middle::dependency_format::Linkage;
use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
use rustc_back::LinkerFlavor;
use session::Session;
use session::config::{self, CrateType, OptLevel, DebugInfoLevel};
use serialize::{json, Encoder};
@ -45,25 +46,39 @@ impl<'a, 'tcx> LinkerInfo {
pub fn to_linker(&'a self,
cmd: Command,
sess: &'a Session) -> Box<Linker+'a> {
if sess.target.target.options.is_like_msvc {
Box::new(MsvcLinker {
cmd: cmd,
sess: sess,
info: self
}) as Box<Linker>
} else if sess.target.target.options.is_like_emscripten {
Box::new(EmLinker {
cmd: cmd,
sess: sess,
info: self
}) as Box<Linker>
} else {
Box::new(GnuLinker {
cmd: cmd,
sess: sess,
info: self,
hinted_static: false,
}) as Box<Linker>
match sess.linker_flavor() {
LinkerFlavor::Msvc => {
Box::new(MsvcLinker {
cmd: cmd,
sess: sess,
info: self
}) as Box<Linker>
}
LinkerFlavor::Em => {
Box::new(EmLinker {
cmd: cmd,
sess: sess,
info: self
}) as Box<Linker>
}
LinkerFlavor::Gcc => {
Box::new(GccLinker {
cmd: cmd,
sess: sess,
info: self,
hinted_static: false,
is_ld: false,
}) as Box<Linker>
}
LinkerFlavor::Ld => {
Box::new(GccLinker {
cmd: cmd,
sess: sess,
info: self,
hinted_static: false,
is_ld: true,
}) as Box<Linker>
}
}
}
}
@ -100,14 +115,32 @@ pub trait Linker {
fn finalize(&mut self) -> Command;
}
pub struct GnuLinker<'a> {
pub struct GccLinker<'a> {
cmd: Command,
sess: &'a Session,
info: &'a LinkerInfo,
hinted_static: bool, // Keeps track of the current hinting mode.
// Link as ld
is_ld: bool,
}
impl<'a> GnuLinker<'a> {
impl<'a> GccLinker<'a> {
/// Argument that must be passed *directly* to the linker
///
/// These arguments need to be prepended with '-Wl,' when a gcc-style linker is used
fn linker_arg<S>(&mut self, arg: S) -> &mut Self
where S: AsRef<OsStr>
{
if !self.is_ld {
let mut os = OsString::from("-Wl,");
os.push(arg.as_ref());
self.cmd.arg(os);
} else {
self.cmd.arg(arg);
}
self
}
fn takes_hints(&self) -> bool {
!self.sess.target.target.options.is_like_osx
}
@ -119,7 +152,7 @@ impl<'a> GnuLinker<'a> {
fn hint_static(&mut self) {
if !self.takes_hints() { return }
if !self.hinted_static {
self.cmd.arg("-Wl,-Bstatic");
self.linker_arg("-Bstatic");
self.hinted_static = true;
}
}
@ -127,13 +160,13 @@ impl<'a> GnuLinker<'a> {
fn hint_dynamic(&mut self) {
if !self.takes_hints() { return }
if self.hinted_static {
self.cmd.arg("-Wl,-Bdynamic");
self.linker_arg("-Bdynamic");
self.hinted_static = false;
}
}
}
impl<'a> Linker for GnuLinker<'a> {
impl<'a> Linker for GccLinker<'a> {
fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg("-l").arg(lib); }
fn link_staticlib(&mut self, lib: &str) { self.hint_static(); self.cmd.arg("-l").arg(lib); }
fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
@ -164,27 +197,26 @@ impl<'a> Linker for GnuLinker<'a> {
self.hint_static();
let target = &self.sess.target.target;
if !target.options.is_like_osx {
self.cmd.arg("-Wl,--whole-archive")
.arg("-l").arg(lib)
.arg("-Wl,--no-whole-archive");
self.linker_arg("--whole-archive").cmd.arg("-l").arg(lib);
self.linker_arg("--no-whole-archive");
} else {
// -force_load is the macOS equivalent of --whole-archive, but it
// involves passing the full path to the library to link.
let mut v = OsString::from("-Wl,-force_load,");
let mut v = OsString::from("-force_load,");
v.push(&archive::find_library(lib, search_path, &self.sess));
self.cmd.arg(&v);
self.linker_arg(&v);
}
}
fn link_whole_rlib(&mut self, lib: &Path) {
self.hint_static();
if self.sess.target.target.options.is_like_osx {
let mut v = OsString::from("-Wl,-force_load,");
let mut v = OsString::from("-force_load,");
v.push(lib);
self.cmd.arg(&v);
self.linker_arg(&v);
} else {
self.cmd.arg("-Wl,--whole-archive").arg(lib)
.arg("-Wl,--no-whole-archive");
self.linker_arg("--whole-archive").cmd.arg(lib);
self.linker_arg("--no-whole-archive");
}
}
@ -204,10 +236,10 @@ impl<'a> Linker for GnuLinker<'a> {
// for partial linking when using multiple codegen units (-r). So we
// insert it here.
if self.sess.target.target.options.is_like_osx {
self.cmd.arg("-Wl,-dead_strip");
self.linker_arg("-dead_strip");
} else if self.sess.target.target.options.is_like_solaris {
self.cmd.arg("-Wl,-z");
self.cmd.arg("-Wl,ignore");
self.linker_arg("-z");
self.linker_arg("ignore");
// If we're building a dylib, we don't use --gc-sections because LLVM
// has already done the best it can do, and we also don't want to
@ -215,7 +247,7 @@ impl<'a> Linker for GnuLinker<'a> {
// --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
// reduction.
} else if !keep_metadata {
self.cmd.arg("-Wl,--gc-sections");
self.linker_arg("--gc-sections");
}
}
@ -226,7 +258,7 @@ impl<'a> Linker for GnuLinker<'a> {
// need a numeric argument, but other linkers do.
if self.sess.opts.optimize == config::OptLevel::Default ||
self.sess.opts.optimize == config::OptLevel::Aggressive {
self.cmd.arg("-Wl,-O1");
self.linker_arg("-O1");
}
}
@ -235,13 +267,16 @@ impl<'a> Linker for GnuLinker<'a> {
}
fn no_default_libraries(&mut self) {
self.cmd.arg("-nodefaultlibs");
if !self.is_ld {
self.cmd.arg("-nodefaultlibs");
}
}
fn build_dylib(&mut self, out_filename: &Path) {
// On mac we need to tell the linker to let this library be rpathed
if self.sess.target.target.options.is_like_osx {
self.cmd.args(&["-dynamiclib", "-Wl,-dylib"]);
self.cmd.arg("-dynamiclib");
self.linker_arg("-dylib");
// Note that the `osx_rpath_install_name` option here is a hack
// purely to support rustbuild right now, we should get a more
@ -249,9 +284,9 @@ impl<'a> Linker for GnuLinker<'a> {
// the right `-Wl,-install_name` with an `@rpath` in it.
if self.sess.opts.cg.rpath ||
self.sess.opts.debugging_opts.osx_rpath_install_name {
let mut v = OsString::from("-Wl,-install_name,@rpath/");
let mut v = OsString::from("-install_name,@rpath/");
v.push(out_filename.file_name().unwrap());
self.cmd.arg(&v);
self.linker_arg(&v);
}
} else {
self.cmd.arg("-shared");
@ -307,11 +342,20 @@ impl<'a> Linker for GnuLinker<'a> {
}
if self.sess.target.target.options.is_like_osx {
arg.push("-Wl,-exported_symbols_list,");
if !self.is_ld {
arg.push("-Wl,")
}
arg.push("-exported_symbols_list,");
} else if self.sess.target.target.options.is_like_solaris {
arg.push("-Wl,-M,");
if !self.is_ld {
arg.push("-Wl,")
}
arg.push("-M,");
} else {
arg.push("-Wl,--version-script=");
if !self.is_ld {
arg.push("-Wl,")
}
arg.push("--version-script=");
}
arg.push(&path);
@ -319,7 +363,7 @@ impl<'a> Linker for GnuLinker<'a> {
}
fn subsystem(&mut self, subsystem: &str) {
self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem));
self.cmd.arg(&format!("--subsystem,{}", subsystem));
}
fn finalize(&mut self) -> Command {

View 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",

View 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",

View 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",