Skip to content

Commit

Permalink
Use the linker directly on darwin,ios
Browse files Browse the repository at this point in the history
  • Loading branch information
tamird committed Nov 25, 2017
1 parent c30d8f2 commit 385c844
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 51 deletions.
2 changes: 1 addition & 1 deletion src/librustc_back/target/aarch64_apple_ios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn target() -> TargetResult {
target_os: "ios".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
linker_flavor: LinkerFlavor::Gcc,
linker_flavor: LinkerFlavor::Ld,
options: TargetOptions {
features: "+neon,+fp-armv8,+cyclone".to_string(),
eliminate_frame_pointer: false,
Expand Down
53 changes: 42 additions & 11 deletions src/librustc_back/target/apple_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,43 @@
// except according to those terms.

use std::env;
use std::io;
use std::process::Command;
use std::str;

use target::{LinkArgs, TargetOptions};
use target::TargetOptions;

pub fn xcrun(print_arg: &str, sdk_name: &str) -> io::Result<String> {
Command::new("xcrun").arg(print_arg).arg("--sdk").arg(sdk_name).output().and_then(|output| {
if output.status.success() {
Ok(str::from_utf8(&output.stdout[..]).unwrap().trim().to_string())
} else {
let error = format!(
"process exit with error: {}",
str::from_utf8(&output.stderr[..]).unwrap(),
);
Err(io::Error::new(io::ErrorKind::Other, &error[..]))
}
})
}

pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
xcrun("--show-sdk-path", sdk_name).map_err(|e| {
format!("failed to get {} SDK path: {}", sdk_name, e)
})
}

pub fn get_sdk_version(sdk_name: &str) -> Result<String, String> {
xcrun("--show-sdk-version", sdk_name).map_err(|e| {
format!("failed to get {} SDK version: {}", sdk_name, e)
})
}

pub fn get_deployment_target() -> String {
env::var("MACOSX_DEPLOYMENT_TARGET").or_else(|_e| {
get_sdk_version("macosx")
}).unwrap_or("10.7".to_string())
}

pub fn opts() -> TargetOptions {
// ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
Expand All @@ -22,15 +57,11 @@ pub fn opts() -> TargetOptions {
// MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate
// warnings about the usage of ELF TLS.
//
// Here we detect what version is being requested, defaulting to 10.7. ELF
// TLS is flagged as enabled if it looks to be supported.
let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok();
let version = deployment_target.as_ref().and_then(|s| {
let mut i = s.splitn(2, ".");
i.next().and_then(|a| i.next().map(|b| (a, b)))
}).and_then(|(a, b)| {
a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok()
}).unwrap_or((10, 7));
// Here we detect what version is being requested. ELF TLS is flagged as
// enabled if it looks to be supported.
let deployment_target = get_deployment_target();
let mut i = deployment_target.splitn(2, '.').map(|s| s.parse::<u32>().unwrap());
let version = (i.next().unwrap(), i.next().unwrap());

TargetOptions {
// macOS has -dead_strip, which doesn't rely on function_sections
Expand All @@ -43,9 +74,9 @@ pub fn opts() -> TargetOptions {
dll_prefix: "lib".to_string(),
dll_suffix: ".dylib".to_string(),
archive_format: "bsd".to_string(),
pre_link_args: LinkArgs::new(),
exe_allocation_crate: super::maybe_jemalloc(),
has_elf_tls: version >= (10, 7),
linker: "ld".to_string(),
.. Default::default()
}
}
32 changes: 3 additions & 29 deletions src/librustc_back/target/apple_ios_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
// except according to those terms.

use LinkerFlavor;
use std::io;
use std::process::Command;
use target::{LinkArgs, TargetOptions};

use self::Arch::*;
Expand All @@ -37,30 +35,6 @@ impl Arch {
}
}

pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
let res = Command::new("xcrun")
.arg("--show-sdk-path")
.arg("-sdk")
.arg(sdk_name)
.output()
.and_then(|output| {
if output.status.success() {
Ok(String::from_utf8(output.stdout).unwrap())
} else {
let error = String::from_utf8(output.stderr);
let error = format!("process exit with error: {}",
error.unwrap());
Err(io::Error::new(io::ErrorKind::Other,
&error[..]))
}
});

match res {
Ok(output) => Ok(output.trim().to_string()),
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e))
}
}

fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
let sdk_name = match arch {
Armv7 | Armv7s | Arm64 => "iphoneos",
Expand All @@ -69,13 +43,13 @@ fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {

let arch_name = arch.to_string();

let sdk_root = get_sdk_root(sdk_name)?;
let sdk_root = super::apple_base::get_sdk_root(sdk_name)?;

let mut args = LinkArgs::new();
args.insert(LinkerFlavor::Gcc,
args.insert(LinkerFlavor::Ld,
vec!["-arch".to_string(),
arch_name.to_string(),
"-Wl,-syslibroot".to_string(),
"-syslibroot".to_string(),
sdk_root]);

Ok(args)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_back/target/armv7_apple_ios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn target() -> TargetResult {
target_os: "ios".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
linker_flavor: LinkerFlavor::Gcc,
linker_flavor: LinkerFlavor::Ld,
options: TargetOptions {
features: "+v7,+vfp3,+neon".to_string(),
max_atomic_width: Some(64),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_back/target/armv7s_apple_ios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn target() -> TargetResult {
target_os: "ios".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
linker_flavor: LinkerFlavor::Gcc,
linker_flavor: LinkerFlavor::Ld,
options: TargetOptions {
features: "+v7,+vfp4,+neon".to_string(),
max_atomic_width: Some(64),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_back/target/i386_apple_ios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn target() -> TargetResult {
target_os: "ios".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
linker_flavor: LinkerFlavor::Gcc,
linker_flavor: LinkerFlavor::Ld,
options: TargetOptions {
max_atomic_width: Some(64),
stack_probes: true,
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_back/target/i686_apple_darwin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ 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.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
base.stack_probes = true;

Ok(Target {
Expand All @@ -28,7 +27,7 @@ pub fn target() -> TargetResult {
target_os: "macos".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
linker_flavor: LinkerFlavor::Gcc,
linker_flavor: LinkerFlavor::Ld,
options: base,
})
}
2 changes: 1 addition & 1 deletion src/librustc_back/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ use syntax::abi::{Abi, lookup as lookup_abi};
use {LinkerFlavor, PanicStrategy, RelroLevel};

mod android_base;
mod apple_base;
pub mod apple_base;
mod apple_ios_base;
mod arm_base;
mod bitrig_base;
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_back/target/x86_64_apple_darwin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ 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.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
base.stack_probes = true;

Ok(Target {
Expand All @@ -29,7 +28,7 @@ pub fn target() -> TargetResult {
target_os: "macos".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
linker_flavor: LinkerFlavor::Gcc,
linker_flavor: LinkerFlavor::Ld,
options: base,
})
}
2 changes: 1 addition & 1 deletion src/librustc_back/target/x86_64_apple_ios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn target() -> TargetResult {
target_os: "ios".to_string(),
target_env: "".to_string(),
target_vendor: "apple".to_string(),
linker_flavor: LinkerFlavor::Gcc,
linker_flavor: LinkerFlavor::Ld,
options: TargetOptions {
max_atomic_width: Some(64),
stack_probes: true,
Expand Down
22 changes: 21 additions & 1 deletion src/librustc_trans/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use rustc::middle::dependency_format::Linkage;
use rustc::session::Session;
use rustc::session::config::{self, CrateType, OptLevel, DebugInfoLevel};
use rustc::ty::TyCtxt;
use rustc_back::LinkerFlavor;
use rustc_back::{LinkerFlavor, target};
use serialize::{json, Encoder};

/// For all the linkers we support, and information they might
Expand Down Expand Up @@ -66,6 +66,7 @@ impl LinkerInfo {
info: self,
hinted_static: false,
is_ld: false,
building_executable: true,
}) as Box<Linker>
}
LinkerFlavor::Ld => {
Expand All @@ -75,6 +76,7 @@ impl LinkerInfo {
info: self,
hinted_static: false,
is_ld: true,
building_executable: true,
}) as Box<Linker>
}
LinkerFlavor::Binaryen => {
Expand Down Expand Up @@ -126,6 +128,8 @@ pub struct GccLinker<'a> {
hinted_static: bool, // Keeps track of the current hinting mode.
// Link as ld
is_ld: bool,
// Keeps track of product being an executable.
building_executable: bool,
}

impl<'a> GccLinker<'a> {
Expand Down Expand Up @@ -286,6 +290,8 @@ impl<'a> Linker for GccLinker<'a> {
}

fn build_dylib(&mut self, out_filename: &Path) {
self.building_executable = false;

// On mac we need to tell the linker to let this library be rpathed
if self.sess.target.target.options.is_like_osx {
self.linker_arg("-dylib");
Expand Down Expand Up @@ -371,6 +377,20 @@ impl<'a> Linker for GccLinker<'a> {
}

fn finalize(&mut self) -> Command {
if self.sess.target.target.options.is_like_osx && self.is_ld {
self.cmd.arg("-macosx_version_min");
let deployment_target = target::apple_base::get_deployment_target();
self.cmd.arg(&deployment_target);

if self.building_executable {
let mut i = deployment_target.splitn(2, '.').map(|s| s.parse::<u32>().unwrap());
let version = (i.next().unwrap(), i.next().unwrap());
if version < (10, 8) {
self.cmd.arg("-lcrt1.10.6.o");
}
}
}

self.hint_dynamic(); // Reset to default before returning the composed command line.
let mut cmd = Command::new("");
::std::mem::swap(&mut cmd, &mut self.cmd);
Expand Down

0 comments on commit 385c844

Please sign in to comment.