Skip to content

Commit b92d360

Browse files
committed
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.
2 parents 33cde4a + 97ba4c9 commit b92d360

10 files changed

+157
-12
lines changed

src/librustc_metadata/creader.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ impl<'a> CrateLoader<'a> {
783783
Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
784784
Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
785785
};
786-
if !supported_targets.contains(&&*self.sess.target.target.llvm_target) {
786+
if !supported_targets.contains(&&*self.sess.opts.target_triple.triple()) {
787787
self.sess.err(&format!("{:?}Sanitizer only works with the `{}` target",
788788
sanitizer,
789789
supported_targets.join("` or `")
@@ -794,7 +794,7 @@ impl<'a> CrateLoader<'a> {
794794
// firstyear 2017 - during testing I was unable to access an OSX machine
795795
// to make this work on different crate types. As a result, today I have
796796
// only been able to test and support linux as a target.
797-
if self.sess.target.target.llvm_target == "x86_64-unknown-linux-gnu" {
797+
if self.sess.opts.target_triple.triple() == "x86_64-unknown-linux-gnu" {
798798
if !self.sess.crate_types.borrow().iter().all(|ct| {
799799
match *ct {
800800
// Link the runtime

src/librustc_target/spec/apple_base.rs

+25-7
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,7 @@ pub fn opts() -> TargetOptions {
1414
//
1515
// Here we detect what version is being requested, defaulting to 10.7. ELF
1616
// TLS is flagged as enabled if it looks to be supported.
17-
let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok();
18-
let version = deployment_target.as_ref().and_then(|s| {
19-
let mut i = s.splitn(2, '.');
20-
i.next().and_then(|a| i.next().map(|b| (a, b)))
21-
}).and_then(|(a, b)| {
22-
a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok()
23-
}).unwrap_or((10, 7));
17+
let version = macos_deployment_target().unwrap_or((10, 7));
2418

2519
TargetOptions {
2620
// macOS has -dead_strip, which doesn't rely on function_sections
@@ -40,3 +34,27 @@ pub fn opts() -> TargetOptions {
4034
.. Default::default()
4135
}
4236
}
37+
38+
fn macos_deployment_target() -> Option<(u32, u32)> {
39+
let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok();
40+
let version = deployment_target.as_ref().and_then(|s| {
41+
let mut i = s.splitn(2, '.');
42+
i.next().and_then(|a| i.next().map(|b| (a, b)))
43+
}).and_then(|(a, b)| {
44+
a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok()
45+
});
46+
47+
version
48+
}
49+
50+
pub fn macos_llvm_target(arch: &str) -> String {
51+
let version = macos_deployment_target();
52+
let llvm_target = match version {
53+
Some((major, minor)) => {
54+
format!("{}-apple-macosx{}.{}.0", arch, major, minor)
55+
},
56+
None => format!("{}-apple-darwin", arch)
57+
};
58+
59+
llvm_target
60+
}

src/librustc_target/spec/i686_apple_darwin.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ pub fn target() -> TargetResult {
88
base.stack_probes = true;
99
base.eliminate_frame_pointer = false;
1010

11+
// Clang automatically chooses a more specific target based on
12+
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
13+
// correctly, we do too.
14+
let arch = "i686";
15+
let llvm_target = super::apple_base::macos_llvm_target(&arch);
16+
1117
Ok(Target {
12-
llvm_target: "i686-apple-darwin".to_string(),
18+
llvm_target: llvm_target,
1319
target_endian: "little".to_string(),
1420
target_pointer_width: "32".to_string(),
1521
target_c_int_width: "32".to_string(),

src/librustc_target/spec/x86_64_apple_darwin.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,19 @@ pub fn target() -> TargetResult {
88
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
99
base.stack_probes = true;
1010

11+
// Clang automatically chooses a more specific target based on
12+
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
13+
// correctly, we do too.
14+
let arch = "x86_64";
15+
let llvm_target = super::apple_base::macos_llvm_target(&arch);
16+
1117
Ok(Target {
12-
llvm_target: "x86_64-apple-darwin".to_string(),
18+
llvm_target: llvm_target,
1319
target_endian: "little".to_string(),
1420
target_pointer_width: "64".to_string(),
1521
target_c_int_width: "32".to_string(),
1622
data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
17-
arch: "x86_64".to_string(),
23+
arch: arch.to_string(),
1824
target_os: "macos".to_string(),
1925
target_env: String::new(),
2026
target_vendor: "apple".to_string(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// Checks that we correctly modify the target when MACOSX_DEPLOYMENT_TARGET is set.
3+
// See issue #60235.
4+
5+
// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib
6+
// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9
7+
#![feature(no_core, lang_items)]
8+
#![no_core]
9+
10+
#[lang="sized"]
11+
trait Sized { }
12+
#[lang="freeze"]
13+
trait Freeze { }
14+
#[lang="copy"]
15+
trait Copy { }
16+
17+
#[repr(C)]
18+
pub struct Bool {
19+
b: bool,
20+
}
21+
22+
// CHECK: target triple = "i686-apple-macosx10.9.0"
23+
#[no_mangle]
24+
pub extern "C" fn structbool() -> Bool {
25+
Bool { b: true }
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// Checks that we leave the target alone MACOSX_DEPLOYMENT_TARGET is unset.
3+
// See issue #60235.
4+
5+
// compile-flags: -O --target=i686-apple-darwin --crate-type=rlib
6+
// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
7+
#![feature(no_core, lang_items)]
8+
#![no_core]
9+
10+
#[lang="sized"]
11+
trait Sized { }
12+
#[lang="freeze"]
13+
trait Freeze { }
14+
#[lang="copy"]
15+
trait Copy { }
16+
17+
#[repr(C)]
18+
pub struct Bool {
19+
b: bool,
20+
}
21+
22+
// CHECK: target triple = "i686-apple-darwin"
23+
#[no_mangle]
24+
pub extern "C" fn structbool() -> Bool {
25+
Bool { b: true }
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// Checks that we correctly modify the target when MACOSX_DEPLOYMENT_TARGET is set.
3+
// See issue #60235.
4+
5+
// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib
6+
// rustc-env:MACOSX_DEPLOYMENT_TARGET=10.9
7+
#![feature(no_core, lang_items)]
8+
#![no_core]
9+
10+
#[lang="sized"]
11+
trait Sized { }
12+
#[lang="freeze"]
13+
trait Freeze { }
14+
#[lang="copy"]
15+
trait Copy { }
16+
17+
#[repr(C)]
18+
pub struct Bool {
19+
b: bool,
20+
}
21+
22+
// CHECK: target triple = "x86_64-apple-macosx10.9.0"
23+
#[no_mangle]
24+
pub extern "C" fn structbool() -> Bool {
25+
Bool { b: true }
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// Checks that we leave the target alone when MACOSX_DEPLOYMENT_TARGET is unset.
3+
// See issue #60235.
4+
5+
// compile-flags: -O --target=x86_64-apple-darwin --crate-type=rlib
6+
// unset-rustc-env:MACOSX_DEPLOYMENT_TARGET
7+
#![feature(no_core, lang_items)]
8+
#![no_core]
9+
10+
#[lang="sized"]
11+
trait Sized { }
12+
#[lang="freeze"]
13+
trait Freeze { }
14+
#[lang="copy"]
15+
trait Copy { }
16+
17+
#[repr(C)]
18+
pub struct Bool {
19+
b: bool,
20+
}
21+
22+
// CHECK: target triple = "x86_64-apple-darwin"
23+
#[no_mangle]
24+
pub extern "C" fn structbool() -> Bool {
25+
Bool { b: true }
26+
}

src/tools/compiletest/src/header.rs

+8
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,9 @@ pub struct TestProps {
305305
pub extern_private: Vec<String>,
306306
// Environment settings to use for compiling
307307
pub rustc_env: Vec<(String, String)>,
308+
// Environment variables to unset prior to compiling.
309+
// Variables are unset before applying 'rustc_env'.
310+
pub unset_rustc_env: Vec<String>,
308311
// Environment settings to use during execution
309312
pub exec_env: Vec<(String, String)>,
310313
// Lines to check if they appear in the expected debugger output
@@ -373,6 +376,7 @@ impl TestProps {
373376
extern_private: vec![],
374377
revisions: vec![],
375378
rustc_env: vec![],
379+
unset_rustc_env: vec![],
376380
exec_env: vec![],
377381
check_lines: vec![],
378382
build_aux_docs: false,
@@ -499,6 +503,10 @@ impl TestProps {
499503
self.rustc_env.push(ee);
500504
}
501505

506+
if let Some(ev) = config.parse_name_value_directive(ln, "unset-rustc-env") {
507+
self.unset_rustc_env.push(ev);
508+
}
509+
502510
if let Some(cl) = config.parse_check_line(ln) {
503511
self.check_lines.push(cl);
504512
}

src/tools/compiletest/src/runtest.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,9 @@ impl<'test> TestCx<'test> {
17031703
add_extern_priv(&private_lib, true);
17041704
}
17051705

1706+
self.props.unset_rustc_env.clone()
1707+
.iter()
1708+
.fold(&mut rustc, |rustc, v| rustc.env_remove(v));
17061709
rustc.envs(self.props.rustc_env.clone());
17071710
self.compose_and_run(
17081711
rustc,

0 commit comments

Comments
 (0)