Skip to content

Commit 35c4aae

Browse files
committed
Added tvOS as a backend
1 parent 59eb49d commit 35c4aae

File tree

4 files changed

+170
-0
lines changed

4 files changed

+170
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use super::apple_tvos_base::{opts, Arch};
2+
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
3+
4+
pub fn target() -> TargetResult {
5+
let base = opts(Arch::Arm64)?;
6+
Ok(Target {
7+
llvm_target: "arm64-apple-tvos".to_string(),
8+
target_endian: "little".to_string(),
9+
target_pointer_width: "64".to_string(),
10+
target_c_int_width: "32".to_string(),
11+
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".to_string(),
12+
arch: "aarch64".to_string(),
13+
target_os: "tvos".to_string(),
14+
target_env: String::new(),
15+
target_vendor: "apple".to_string(),
16+
linker_flavor: LinkerFlavor::Gcc,
17+
options: TargetOptions {
18+
features: "+neon,+fp-armv8,+cyclone".to_string(),
19+
eliminate_frame_pointer: false,
20+
max_atomic_width: Some(128),
21+
abi_blacklist: super::arm_base::abi_blacklist(),
22+
..base
23+
},
24+
})
25+
}
+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
2+
use std::env;
3+
use std::io;
4+
use std::path::Path;
5+
use std::process::Command;
6+
7+
use Arch::*;
8+
9+
#[allow(non_camel_case_types)]
10+
#[derive(Copy, Clone)]
11+
pub enum Arch {
12+
Arm64,
13+
X86_64,
14+
}
15+
16+
impl Arch {
17+
pub fn to_string(self) -> &'static str {
18+
match self {
19+
Arm64 => "arm64",
20+
X86_64 => "x86_64",
21+
}
22+
}
23+
}
24+
25+
pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
26+
// Following what clang does
27+
// (https://github.com/llvm/llvm-project/blob/
28+
// 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
29+
// to allow the SDK path to be set. (For clang, xcrun sets
30+
// SDKROOT; for rustc, the user or build system can set it, or we
31+
// can fall back to checking for xcrun on PATH.)
32+
if let Some(sdkroot) = env::var("SDKROOT").ok() {
33+
let p = Path::new(&sdkroot);
34+
match sdk_name {
35+
// Ignore `SDKROOT` if it's clearly set for the wrong platform.
36+
"appletvos"
37+
if sdkroot.contains("TVSimulator.platform")
38+
|| sdkroot.contains("MacOSX.platform") =>
39+
{
40+
()
41+
}
42+
"appletvsimulator"
43+
if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") =>
44+
{
45+
()
46+
}
47+
// Ignore `SDKROOT` if it's not a valid path.
48+
_ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (),
49+
_ => return Ok(sdkroot),
50+
}
51+
}
52+
let res =
53+
Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
54+
|output| {
55+
if output.status.success() {
56+
Ok(String::from_utf8(output.stdout).unwrap())
57+
} else {
58+
let error = String::from_utf8(output.stderr);
59+
let error = format!("process exit with error: {}", error.unwrap());
60+
Err(io::Error::new(io::ErrorKind::Other, &error[..]))
61+
}
62+
},
63+
);
64+
65+
match res {
66+
Ok(output) => Ok(output.trim().to_string()),
67+
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
68+
}
69+
}
70+
71+
fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
72+
let sdk_name = match arch {
73+
Arm64 => "appletvos",
74+
X86_64 => "appletvsimulator",
75+
};
76+
77+
let arch_name = arch.to_string();
78+
79+
let sdk_root = get_sdk_root(sdk_name)?;
80+
81+
let mut args = LinkArgs::new();
82+
args.insert(
83+
LinkerFlavor::Gcc,
84+
vec![
85+
"-arch".to_string(),
86+
arch_name.to_string(),
87+
"-isysroot".to_string(),
88+
sdk_root.clone(),
89+
"-Wl,-syslibroot".to_string(),
90+
sdk_root,
91+
],
92+
);
93+
94+
Ok(args)
95+
}
96+
97+
fn target_cpu(arch: Arch) -> String {
98+
match arch {
99+
Arm64 => "cyclone",
100+
X86_64 => "core2",
101+
}
102+
.to_string()
103+
}
104+
105+
fn link_env_remove(arch: Arch) -> Vec<String> {
106+
match arch {
107+
Arm64 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
108+
}
109+
}
110+
111+
pub fn opts(arch: Arch) -> Result<TargetOptions, String> {
112+
let pre_link_args = build_pre_link_args(arch)?;
113+
Ok(TargetOptions {
114+
cpu: target_cpu(arch),
115+
dynamic_linking: false,
116+
executables: true,
117+
pre_link_args,
118+
link_env_remove: link_env_remove(arch),
119+
has_elf_tls: false,
120+
eliminate_frame_pointer: false,
121+
..super::apple_base::opts()
122+
})
123+
}

src/librustc_target/spec/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub mod abi;
4848
mod android_base;
4949
mod apple_base;
5050
mod apple_ios_base;
51+
mod apple_tvos_base;
5152
mod arm_base;
5253
mod cloudabi_base;
5354
mod dragonfly_base;
@@ -434,6 +435,8 @@ supported_targets! {
434435
("armv7-apple-ios", armv7_apple_ios),
435436
("armv7s-apple-ios", armv7s_apple_ios),
436437
("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
438+
("aarch64-apple-tvos", aarch64_apple_tvos),
439+
("x86_64-apple-tvos", x86_64_apple_tvos),
437440

438441
("armebv7r-none-eabi", armebv7r_none_eabi),
439442
("armebv7r-none-eabihf", armebv7r_none_eabihf),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use super::apple_tvos_base::{opts, Arch};
2+
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
3+
4+
pub fn target() -> TargetResult {
5+
let base = opts(Arch::X86_64)?;
6+
Ok(Target {
7+
llvm_target: "x86_64-apple-tvos".to_string(),
8+
target_endian: "little".to_string(),
9+
target_pointer_width: "64".to_string(),
10+
target_c_int_width: "32".to_string(),
11+
data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".to_string(),
12+
arch: "x86_64".to_string(),
13+
target_os: "tvos".to_string(),
14+
target_env: String::new(),
15+
target_vendor: "apple".to_string(),
16+
linker_flavor: LinkerFlavor::Gcc,
17+
options: TargetOptions { max_atomic_width: Some(64), stack_probes: true, ..base },
18+
})
19+
}

0 commit comments

Comments
 (0)