From 385c84477523d5f3d2f64fda459a50ab65f7a6a7 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 24 Nov 2017 22:00:34 -0500 Subject: [PATCH] Use the linker directly on darwin,ios Some logic to deal with macOS < 10.8 cribbed from: https://github.com/llvm-mirror/clang/blob/64309d1/lib/Driver/ToolChains/Darwin.cpp#L1910 Updates #11937. --- src/librustc_back/target/aarch64_apple_ios.rs | 2 +- src/librustc_back/target/apple_base.rs | 53 +++++++++++++++---- src/librustc_back/target/apple_ios_base.rs | 32 ++--------- src/librustc_back/target/armv7_apple_ios.rs | 2 +- src/librustc_back/target/armv7s_apple_ios.rs | 2 +- src/librustc_back/target/i386_apple_ios.rs | 2 +- src/librustc_back/target/i686_apple_darwin.rs | 3 +- src/librustc_back/target/mod.rs | 2 +- .../target/x86_64_apple_darwin.rs | 3 +- src/librustc_back/target/x86_64_apple_ios.rs | 2 +- src/librustc_trans/back/linker.rs | 22 +++++++- 11 files changed, 74 insertions(+), 51 deletions(-) diff --git a/src/librustc_back/target/aarch64_apple_ios.rs b/src/librustc_back/target/aarch64_apple_ios.rs index cff6eb534b1e5..152f73d518abc 100644 --- a/src/librustc_back/target/aarch64_apple_ios.rs +++ b/src/librustc_back/target/aarch64_apple_ios.rs @@ -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, diff --git a/src/librustc_back/target/apple_base.rs b/src/librustc_back/target/apple_base.rs index 159f93a74c683..ed6a46e56718f 100644 --- a/src/librustc_back/target/apple_base.rs +++ b/src/librustc_back/target/apple_base.rs @@ -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 { + 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 { + 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 { + 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 @@ -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::().and_then(|a| b.parse::().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::().unwrap()); + let version = (i.next().unwrap(), i.next().unwrap()); TargetOptions { // macOS has -dead_strip, which doesn't rely on function_sections @@ -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() } } diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs index 4b02d0b60b8b5..30b4ba39fcdea 100644 --- a/src/librustc_back/target/apple_ios_base.rs +++ b/src/librustc_back/target/apple_ios_base.rs @@ -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::*; @@ -37,30 +35,6 @@ impl Arch { } } -pub fn get_sdk_root(sdk_name: &str) -> Result { - 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 { let sdk_name = match arch { Armv7 | Armv7s | Arm64 => "iphoneos", @@ -69,13 +43,13 @@ fn build_pre_link_args(arch: Arch) -> Result { 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) diff --git a/src/librustc_back/target/armv7_apple_ios.rs b/src/librustc_back/target/armv7_apple_ios.rs index 67d3d12fb5776..80771f72a199e 100644 --- a/src/librustc_back/target/armv7_apple_ios.rs +++ b/src/librustc_back/target/armv7_apple_ios.rs @@ -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), diff --git a/src/librustc_back/target/armv7s_apple_ios.rs b/src/librustc_back/target/armv7s_apple_ios.rs index e4cc89ab21140..a81354921ccbb 100644 --- a/src/librustc_back/target/armv7s_apple_ios.rs +++ b/src/librustc_back/target/armv7s_apple_ios.rs @@ -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), diff --git a/src/librustc_back/target/i386_apple_ios.rs b/src/librustc_back/target/i386_apple_ios.rs index 82eae1a31a9ad..5d6cbf9676054 100644 --- a/src/librustc_back/target/i386_apple_ios.rs +++ b/src/librustc_back/target/i386_apple_ios.rs @@ -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, diff --git a/src/librustc_back/target/i686_apple_darwin.rs b/src/librustc_back/target/i686_apple_darwin.rs index 14937f9aa55b6..226f897ca0c5b 100644 --- a/src/librustc_back/target/i686_apple_darwin.rs +++ b/src/librustc_back/target/i686_apple_darwin.rs @@ -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 { @@ -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, }) } diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 7599a60ba5ada..3679b45d89e7c 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -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; diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_back/target/x86_64_apple_darwin.rs index 71ac360eb9906..b544283824b03 100644 --- a/src/librustc_back/target/x86_64_apple_darwin.rs +++ b/src/librustc_back/target/x86_64_apple_darwin.rs @@ -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 { @@ -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, }) } diff --git a/src/librustc_back/target/x86_64_apple_ios.rs b/src/librustc_back/target/x86_64_apple_ios.rs index eed99e3784ce0..4d53a66e62119 100644 --- a/src/librustc_back/target/x86_64_apple_ios.rs +++ b/src/librustc_back/target/x86_64_apple_ios.rs @@ -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, diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 1e5daead5a648..6ecd13b02c441 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -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 @@ -66,6 +66,7 @@ impl LinkerInfo { info: self, hinted_static: false, is_ld: false, + building_executable: true, }) as Box } LinkerFlavor::Ld => { @@ -75,6 +76,7 @@ impl LinkerInfo { info: self, hinted_static: false, is_ld: true, + building_executable: true, }) as Box } LinkerFlavor::Binaryen => { @@ -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> { @@ -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"); @@ -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::().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);