Skip to content

Commit

Permalink
-Z linker-flavor
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Jorge Aparicio committed Apr 7, 2017
1 parent c438c1f commit 9d11b08
Show file tree
Hide file tree
Showing 89 changed files with 598 additions and 240 deletions.
16 changes: 14 additions & 2 deletions src/librustc/session/config.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
}
) }

Expand Down Expand Up @@ -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 {
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/session/mod.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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
}
Expand Down
42 changes: 42 additions & 0 deletions src/librustc_back/lib.rs
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/target/aarch64_apple_ios.rs
Expand Up @@ -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};

Expand All @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/target/aarch64_linux_android.rs
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/target/aarch64_unknown_freebsd.rs
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/target/aarch64_unknown_fuchsia.rs
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/target/aarch64_unknown_linux_gnu.rs
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_back/target/android_base.rs
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_back/target/apple_base.rs
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down
15 changes: 11 additions & 4 deletions src/librustc_back/target/apple_ios_base.rs
Expand Up @@ -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::*;

Expand Down Expand Up @@ -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"
Expand All @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/target/arm_linux_androideabi.rs
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/target/arm_unknown_linux_gnueabi.rs
Expand Up @@ -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 {
Expand All @@ -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(),
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
Expand Up @@ -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 {
Expand All @@ -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(),
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/target/arm_unknown_linux_musleabi.rs
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_back/target/arm_unknown_linux_musleabihf.rs
Expand Up @@ -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 {
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs
Expand Up @@ -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 {
Expand All @@ -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(),
Expand All @@ -31,4 +33,3 @@ pub fn target() -> TargetResult {
}
})
}

2 changes: 2 additions & 0 deletions src/librustc_back/target/armv7_apple_ios.rs
Expand Up @@ -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};

Expand All @@ -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),
Expand Down

0 comments on commit 9d11b08

Please sign in to comment.