Auto merge of #60378 - froydnj:apple-target-modifications, r=michaelwoerister

conditionally modify darwin targets to macosx targets with versions

We need this behavior so that Rust LLVM IR objects match the target triple for Clang LLVM IR objects.  This matching then convinces the linker that yes, you really can do cross-language LTO with objects from different compilers.

The newly-added tests seem to pass locally on x86_64-unknown-linux-gnu.  I haven't done a full test run or tried the new compiler in an cross-language LTO setup yet.
This commit is contained in:
bors 2019-05-08 08:26:48 +00:00
commit b92d360c6c
10 changed files with 157 additions and 12 deletions

View File

@ -783,7 +783,7 @@ fn inject_sanitizer_runtime(&mut self) {
Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
};
if !supported_targets.contains(&&*self.sess.target.target.llvm_target) {
if !supported_targets.contains(&&*self.sess.opts.target_triple.triple()) {
self.sess.err(&format!("{:?}Sanitizer only works with the `{}` target",
sanitizer,
supported_targets.join("` or `")
@ -794,7 +794,7 @@ fn inject_sanitizer_runtime(&mut self) {
// firstyear 2017 - during testing I was unable to access an OSX machine
// to make this work on different crate types. As a result, today I have
// only been able to test and support linux as a target.
if self.sess.target.target.llvm_target == "x86_64-unknown-linux-gnu" {
if self.sess.opts.target_triple.triple() == "x86_64-unknown-linux-gnu" {
if !self.sess.crate_types.borrow().iter().all(|ct| {
match *ct {
// Link the runtime

View File

@ -14,13 +14,7 @@ pub fn opts() -> TargetOptions {
//
// 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));
let version = macos_deployment_target().unwrap_or((10, 7));
TargetOptions {
// macOS has -dead_strip, which doesn't rely on function_sections
@ -40,3 +34,27 @@ pub fn opts() -> TargetOptions {
.. Default::default()
}
}
fn macos_deployment_target() -> Option<(u32, u32)> {
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()
});
version
}
pub fn macos_llvm_target(arch: &str) -> String {
let version = macos_deployment_target();
let llvm_target = match version {
Some((major, minor)) => {
format!("{}-apple-macosx{}.{}.0", arch, major, minor)
},
None => format!("{}-apple-darwin", arch)
};
llvm_target
}

View File

@ -8,8 +8,14 @@ pub fn target() -> TargetResult {
base.stack_probes = true;
base.eliminate_frame_pointer = false;
// Clang automatically chooses a more specific target based on
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
// correctly, we do too.
let arch = "i686";
let llvm_target = super::apple_base::macos_llvm_target(&arch);
Ok(Target {
llvm_target: "i686-apple-darwin".to_string(),
llvm_target: llvm_target,
target_endian: "little".to_string(),
target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(),

View File

@ -8,13 +8,19 @@ pub fn target() -> TargetResult {
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
base.stack_probes = true;
// Clang automatically chooses a more specific target based on
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
// correctly, we do too.
let arch = "x86_64";
let llvm_target = super::apple_base::macos_llvm_target(&arch);
Ok(Target {
llvm_target: "x86_64-apple-darwin".to_string(),
llvm_target: llvm_target,
target_endian: "little".to_string(),
target_pointer_width: "64".to_string(),
target_c_int_width: "32".to_string(),
data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
arch: "x86_64".to_string(),
arch: arch.to_string(),
target_os: "macos".to_string(),
target_env: String::new(),
target_vendor: "apple".to_string(),

View File

@ -0,0 +1,26 @@
//
// Checks that we correctly modify the target when MACOSX_DEPLOYMENT_TARGET is set.
// See issue #60235.
// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib
// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9
#![feature(no_core, lang_items)]
#![no_core]
#[lang="sized"]
trait Sized { }
#[lang="freeze"]
trait Freeze { }
#[lang="copy"]
trait Copy { }
#[repr(C)]
pub struct Bool {
b: bool,
}
// CHECK: target triple = "i686-apple-macosx10.9.0"
#[no_mangle]
pub extern "C" fn structbool() -> Bool {
Bool { b: true }
}

View File

@ -0,0 +1,26 @@
//
// Checks that we leave the target alone MACOSX_DEPLOYMENT_TARGET is unset.
// See issue #60235.
// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib
// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
#![feature(no_core, lang_items)]
#![no_core]
#[lang="sized"]
trait Sized { }
#[lang="freeze"]
trait Freeze { }
#[lang="copy"]
trait Copy { }
#[repr(C)]
pub struct Bool {
b: bool,
}
// CHECK: target triple = "i686-apple-darwin"
#[no_mangle]
pub extern "C" fn structbool() -> Bool {
Bool { b: true }
}

View File

@ -0,0 +1,26 @@
//
// Checks that we correctly modify the target when MACOSX_DEPLOYMENT_TARGET is set.
// See issue #60235.
// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib
// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9
#![feature(no_core, lang_items)]
#![no_core]
#[lang="sized"]
trait Sized { }
#[lang="freeze"]
trait Freeze { }
#[lang="copy"]
trait Copy { }
#[repr(C)]
pub struct Bool {
b: bool,
}
// CHECK: target triple = "x86_64-apple-macosx10.9.0"
#[no_mangle]
pub extern "C" fn structbool() -> Bool {
Bool { b: true }
}

View File

@ -0,0 +1,26 @@
//
// Checks that we leave the target alone when MACOSX_DEPLOYMENT_TARGET is unset.
// See issue #60235.
// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib
// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
#![feature(no_core, lang_items)]
#![no_core]
#[lang="sized"]
trait Sized { }
#[lang="freeze"]
trait Freeze { }
#[lang="copy"]
trait Copy { }
#[repr(C)]
pub struct Bool {
b: bool,
}
// CHECK: target triple = "x86_64-apple-darwin"
#[no_mangle]
pub extern "C" fn structbool() -> Bool {
Bool { b: true }
}

View File

@ -305,6 +305,9 @@ pub struct TestProps {
pub extern_private: Vec<String>,
// Environment settings to use for compiling
pub rustc_env: Vec<(String, String)>,
// Environment variables to unset prior to compiling.
// Variables are unset before applying 'rustc_env'.
pub unset_rustc_env: Vec<String>,
// Environment settings to use during execution
pub exec_env: Vec<(String, String)>,
// Lines to check if they appear in the expected debugger output
@ -373,6 +376,7 @@ pub fn new() -> Self {
extern_private: vec![],
revisions: vec![],
rustc_env: vec![],
unset_rustc_env: vec![],
exec_env: vec![],
check_lines: vec![],
build_aux_docs: false,
@ -499,6 +503,10 @@ fn load_from(&mut self, testfile: &Path, cfg: Option<&str>, config: &Config) {
self.rustc_env.push(ee);
}
if let Some(ev) = config.parse_name_value_directive(ln, "unset-rustc-env") {
self.unset_rustc_env.push(ev);
}
if let Some(cl) = config.parse_check_line(ln) {
self.check_lines.push(cl);
}

View File

@ -1703,6 +1703,9 @@ fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) ->
add_extern_priv(&private_lib, true);
}
self.props.unset_rustc_env.clone()
.iter()
.fold(&mut rustc, |rustc, v| rustc.env_remove(v));
rustc.envs(self.props.rustc_env.clone());
self.compose_and_run(
rustc,