Auto merge of #103503 - thomcc:tvos-support, r=workingjubilee

Support Apple tvOS in libstd

This target has existed in the compiler for a while, was `no_std`-only previously (even requiring `#![feature(restricted_std)]`). Apple tvOS is essentially the same as iOS, down to using the same version numbering, so there's no reason for this to be a `no_std`-only target the way it is currently.

Not yet tested much (I have an Apple TV, but haven't tested that this can deploy and run programs on it, nor the simulator). Uses the implementation strategy as the watchOS support in https://github.com/rust-lang/rust/pull/98101 and etc. That is, no `std::os::` interfaces aside from those in `std::os::unix`.

Includes an update to libc in order to pull in https://github.com/rust-lang/libc/pull/2958.
This commit is contained in:
bors 2023-06-21 22:45:37 +00:00
commit f272fc3a86
33 changed files with 313 additions and 50 deletions

View File

@ -1,10 +1,10 @@
use super::apple_base::{opts, Arch};
use super::apple_base::{opts, tvos_llvm_target, Arch};
use crate::spec::{FramePointer, Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::Arm64;
Target {
llvm_target: "arm64-apple-tvos".into(),
llvm_target: tvos_llvm_target(arch).into(),
pointer_width: 64,
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
arch: arch.target_arch(),

View File

@ -30,6 +30,9 @@ fn macos_link_environment_unmodified() {
for target in all_macos_targets {
// macOS targets should only remove information for cross-compiling, but never
// for the host.
assert_eq!(target.link_env_remove, crate::spec::cvs!["IPHONEOS_DEPLOYMENT_TARGET"]);
assert_eq!(
target.link_env_remove,
crate::spec::cvs!["IPHONEOS_DEPLOYMENT_TARGET", "TVOS_DEPLOYMENT_TARGET"],
);
}
}

View File

@ -240,7 +240,12 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]>
// Remove the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
// may occur when we're linking a custom build script while targeting iOS for example.
if let Ok(sdkroot) = env::var("SDKROOT") {
if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform")
if sdkroot.contains("iPhoneOS.platform")
|| sdkroot.contains("iPhoneSimulator.platform")
|| sdkroot.contains("AppleTVOS.platform")
|| sdkroot.contains("AppleTVSimulator.platform")
|| sdkroot.contains("WatchOS.platform")
|| sdkroot.contains("WatchSimulator.platform")
{
env_remove.push("SDKROOT".into())
}
@ -249,6 +254,7 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]>
// "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",
// although this is apparently ignored when using the linker at "/usr/bin/ld".
env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".into());
env_remove.push("TVOS_DEPLOYMENT_TARGET".into());
env_remove.into()
} else {
// Otherwise if cross-compiling for a different OS/SDK, remove any part
@ -299,6 +305,16 @@ fn tvos_lld_platform_version() -> String {
format!("{major}.{minor}")
}
pub fn tvos_llvm_target(arch: Arch) -> String {
let (major, minor) = tvos_deployment_target();
format!("{}-apple-tvos{}.{}.0", arch.target_name(), major, minor)
}
pub fn tvos_sim_llvm_target(arch: Arch) -> String {
let (major, minor) = tvos_deployment_target();
format!("{}-apple-tvos{}.{}.0-simulator", arch.target_name(), major, minor)
}
fn watchos_deployment_target() -> (u32, u32) {
// If you are looking for the default deployment target, prefer `rustc --print deployment-target`.
from_set_deployment_target("WATCHOS_DEPLOYMENT_TARGET").unwrap_or((5, 0))

View File

@ -1,12 +1,13 @@
use super::apple_base::{opts, Arch};
use super::apple_base::{opts, tvos_sim_llvm_target, Arch};
use crate::spec::{StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let arch = Arch::X86_64_sim;
Target {
llvm_target: "x86_64-apple-tvos".into(),
llvm_target: tvos_sim_llvm_target(arch).into(),
pointer_width: 64,
data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".into(),
data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
.into(),
arch: arch.target_arch(),
options: TargetOptions {
max_atomic_width: Some(128),

View File

@ -238,7 +238,7 @@ impl fmt::Debug for c_void {
not(target_arch = "s390x"),
not(target_arch = "x86_64")
),
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")),
target_family = "wasm",
target_arch = "asmjs",
target_os = "uefi",
@ -267,7 +267,7 @@ pub struct VaListImpl<'f> {
not(target_arch = "s390x"),
not(target_arch = "x86_64")
),
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")),
target_family = "wasm",
target_arch = "asmjs",
target_os = "uefi",
@ -292,7 +292,7 @@ impl<'f> fmt::Debug for VaListImpl<'f> {
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
#[cfg(all(
target_arch = "aarch64",
not(any(target_os = "macos", target_os = "ios")),
not(any(target_os = "macos", target_os = "ios", target_os = "tvos")),
not(target_os = "uefi"),
not(windows),
))]
@ -389,7 +389,10 @@ pub struct VaList<'a, 'f: 'a> {
not(target_arch = "s390x"),
not(target_arch = "x86_64")
),
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
all(
target_arch = "aarch64",
any(target_os = "macos", target_os = "ios", target_os = "tvos")
),
target_family = "wasm",
target_arch = "asmjs",
target_os = "uefi",
@ -404,7 +407,10 @@ pub struct VaList<'a, 'f: 'a> {
target_arch = "s390x",
target_arch = "x86_64"
),
any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
any(
not(target_arch = "aarch64"),
not(any(target_os = "macos", target_os = "ios", target_os = "tvos"))
),
not(target_family = "wasm"),
not(target_arch = "asmjs"),
not(target_os = "uefi"),
@ -422,7 +428,7 @@ pub struct VaList<'a, 'f: 'a> {
not(target_arch = "s390x"),
not(target_arch = "x86_64")
),
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios", target_os = "tvos")),
target_family = "wasm",
target_arch = "asmjs",
target_os = "uefi",
@ -449,7 +455,10 @@ impl<'f> VaListImpl<'f> {
target_arch = "s390x",
target_arch = "x86_64"
),
any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
any(
not(target_arch = "aarch64"),
not(any(target_os = "macos", target_os = "ios", target_os = "tvos"))
),
not(target_family = "wasm"),
not(target_arch = "asmjs"),
not(target_os = "uefi"),

View File

@ -18,6 +18,7 @@ fn main() {
|| target.contains("illumos")
|| target.contains("apple-darwin")
|| target.contains("apple-ios")
|| target.contains("apple-tvos")
|| target.contains("apple-watchos")
|| target.contains("uwp")
|| target.contains("windows")
@ -48,7 +49,6 @@ fn main() {
// - mipsel-sony-psp
// - nvptx64-nvidia-cuda
// - arch=avr
// - tvos (aarch64-apple-tvos, x86_64-apple-tvos)
// - uefi (x86_64-unknown-uefi, i686-unknown-uefi)
// - JSON targets
// - Any new targets that have not been explicitly added above.

View File

@ -1640,6 +1640,10 @@ fn test_file_times() {
use crate::os::ios::fs::FileTimesExt;
#[cfg(target_os = "macos")]
use crate::os::macos::fs::FileTimesExt;
#[cfg(target_os = "tvos")]
use crate::os::tvos::fs::FileTimesExt;
#[cfg(target_os = "tvos")]
use crate::os::tvos::fs::FileTimesExt;
#[cfg(target_os = "watchos")]
use crate::os::watchos::fs::FileTimesExt;
#[cfg(windows)]
@ -1651,9 +1655,21 @@ fn test_file_times() {
let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345);
let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321);
times = times.set_accessed(accessed).set_modified(modified);
#[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(
windows,
target_os = "macos",
target_os = "ios",
target_os = "watchos",
target_os = "tvos",
))]
let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
#[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(
windows,
target_os = "macos",
target_os = "ios",
target_os = "watchos",
target_os = "tvos",
))]
{
times = times.set_created(created);
}
@ -1678,7 +1694,13 @@ fn test_file_times() {
let metadata = file.metadata().unwrap();
assert_eq!(metadata.accessed().unwrap(), accessed);
assert_eq!(metadata.modified().unwrap(), modified);
#[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(
windows,
target_os = "macos",
target_os = "ios",
target_os = "watchos",
target_os = "tvos",
))]
{
assert_eq!(metadata.created().unwrap(), created);
}

View File

@ -6,7 +6,7 @@ use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
use crate::time::SystemTime;
#[allow(deprecated)]
use crate::os::ios::raw;
use super::raw;
/// OS-specific extensions to [`fs::Metadata`].
///

View File

@ -137,6 +137,9 @@ pub mod redox;
pub mod solaris;
#[cfg(target_os = "solid_asp3")]
pub mod solid;
#[cfg(target_os = "tvos")]
#[path = "ios/mod.rs"]
pub(crate) mod tvos;
#[cfg(target_os = "vita")]
pub mod vita;
#[cfg(target_os = "vxworks")]

View File

@ -73,6 +73,8 @@ mod platform {
pub use crate::os::redox::*;
#[cfg(target_os = "solaris")]
pub use crate::os::solaris::*;
#[cfg(target_os = "tvos")]
pub use crate::os::tvos::*;
#[cfg(target_os = "vita")]
pub use crate::os::vita::*;
#[cfg(target_os = "vxworks")]
@ -96,6 +98,7 @@ pub mod thread;
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "macos",
target_os = "netbsd",

View File

@ -11,6 +11,7 @@ use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Owned
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "tvos",
target_os = "macos",
target_os = "watchos",
target_os = "netbsd",
@ -30,6 +31,7 @@ use crate::time::Duration;
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "tvos",
target_os = "macos",
target_os = "watchos",
target_os = "netbsd",
@ -238,6 +240,7 @@ impl UnixStream {
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "tvos",
target_os = "macos",
target_os = "watchos",
target_os = "netbsd",

View File

@ -36,7 +36,7 @@ pub use self::impl_linux::peer_cred;
))]
pub use self::impl_bsd::peer_cred;
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub use self::impl_mac::peer_cred;
#[cfg(any(target_os = "linux", target_os = "android"))]
@ -98,7 +98,7 @@ pub mod impl_bsd {
}
}
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub mod impl_mac {
use super::UCred;
use crate::os::unix::io::AsRawFd;

View File

@ -8,6 +8,7 @@ use libc::{getegid, geteuid, getpid};
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "tvos",
target_os = "macos",
target_os = "watchos",
target_os = "openbsd"
@ -26,7 +27,13 @@ fn test_socket_pair() {
}
#[test]
#[cfg(any(target_os = "linux", target_os = "ios", target_os = "macos", target_os = "watchos"))]
#[cfg(any(
target_os = "linux",
target_os = "ios",
target_os = "macos",
target_os = "watchos",
target_os = "tvos",
))]
fn test_socket_pair_pids(arg: Type) -> RetType {
// Create two connected sockets and get their peer credentials.
let (sock_a, sock_b) = UnixStream::pair().unwrap();

View File

@ -85,7 +85,7 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
cfg_if::cfg_if! {
if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "watchos"), not(target_os = "netbsd")))] {
if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "netbsd")))] {
// ARM EHABI personality routine.
// https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
//

View File

@ -168,7 +168,7 @@ mod imp {
}
}
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
mod imp {
use super::Args;
use crate::ffi::CStr;
@ -209,7 +209,7 @@ mod imp {
// for i in (0..[args count])
// res.push([args objectAtIndex:i])
// res
#[cfg(any(target_os = "ios", target_os = "watchos"))]
#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn args() -> Args {
use crate::ffi::OsString;
use crate::mem;

View File

@ -31,6 +31,17 @@ pub mod os {
pub const EXE_EXTENSION: &str = "";
}
#[cfg(target_os = "tvos")]
pub mod os {
pub const FAMILY: &str = "unix";
pub const OS: &str = "tvos";
pub const DLL_PREFIX: &str = "lib";
pub const DLL_SUFFIX: &str = ".dylib";
pub const DLL_EXTENSION: &str = "dylib";
pub const EXE_SUFFIX: &str = "";
pub const EXE_EXTENSION: &str = "";
}
#[cfg(target_os = "watchos")]
pub mod os {
pub const FAMILY: &str = "unix";

View File

@ -44,6 +44,7 @@ const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
target_os = "tvos",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
@ -69,6 +70,7 @@ const fn max_iov() -> usize {
target_os = "emscripten",
target_os = "freebsd",
target_os = "ios",
target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@ -181,6 +183,7 @@ impl FileDesc {
target_os = "fuchsia",
target_os = "illumos",
target_os = "ios",
target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@ -222,6 +225,7 @@ impl FileDesc {
#[cfg(any(
all(target_os = "android", target_pointer_width = "32"),
target_os = "ios",
target_os = "tvos",
target_os = "macos",
))]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
@ -320,6 +324,7 @@ impl FileDesc {
target_os = "fuchsia",
target_os = "illumos",
target_os = "ios",
target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@ -361,6 +366,7 @@ impl FileDesc {
#[cfg(any(
all(target_os = "android", target_pointer_width = "32"),
target_os = "ios",
target_os = "tvos",
target_os = "macos",
))]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {

View File

@ -32,6 +32,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
all(target_os = "linux", target_env = "gnu"),
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
))]
use crate::sys::weak::syscall;
@ -43,6 +44,7 @@ use libc::{c_int, mode_t};
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "solaris",
all(target_os = "linux", target_env = "gnu")
@ -360,7 +362,7 @@ pub struct FilePermissions {
pub struct FileTimes {
accessed: Option<SystemTime>,
modified: Option<SystemTime>,
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
created: Option<SystemTime>,
}
@ -519,6 +521,7 @@ impl FileAttr {
target_os = "openbsd",
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
))]
pub fn created(&self) -> io::Result<SystemTime> {
@ -530,6 +533,7 @@ impl FileAttr {
target_os = "openbsd",
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "vita",
)))]
@ -611,7 +615,7 @@ impl FileTimes {
self.modified = Some(t);
}
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
pub fn set_created(&mut self, t: SystemTime) {
self.created = Some(t);
}
@ -895,6 +899,7 @@ impl DirEntry {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "linux",
target_os = "emscripten",
@ -928,6 +933,7 @@ impl DirEntry {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "netbsd",
target_os = "openbsd",
@ -946,6 +952,7 @@ impl DirEntry {
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "netbsd",
target_os = "openbsd",
@ -1107,11 +1114,21 @@ impl File {
cvt_r(|| unsafe { os_fsync(self.as_raw_fd()) })?;
return Ok(());
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
))]
unsafe fn os_fsync(fd: c_int) -> c_int {
libc::fcntl(fd, libc::F_FULLFSYNC)
}
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "watchos")))]
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
)))]
unsafe fn os_fsync(fd: c_int) -> c_int {
libc::fsync(fd)
}
@ -1121,7 +1138,12 @@ impl File {
cvt_r(|| unsafe { os_datasync(self.as_raw_fd()) })?;
return Ok(());
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
))]
unsafe fn os_datasync(fd: c_int) -> c_int {
libc::fcntl(fd, libc::F_FULLFSYNC)
}
@ -1140,6 +1162,7 @@ impl File {
target_os = "android",
target_os = "freebsd",
target_os = "ios",
target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@ -1249,7 +1272,7 @@ impl File {
io::ErrorKind::Unsupported,
"setting file times not supported",
))
} else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] {
} else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3];
let mut num_times = 0;
let mut attrlist: libc::attrlist = unsafe { mem::zeroed() };
@ -1709,6 +1732,7 @@ fn open_to_and_set_permissions(
target_os = "android",
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
)))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
@ -1736,7 +1760,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
}
}
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
use crate::sync::atomic::{AtomicBool, Ordering};

View File

@ -32,6 +32,7 @@ impl LazyInit for AllocatedCondvar {
if #[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "l4re",
target_os = "android",
@ -124,6 +125,7 @@ impl Condvar {
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "android",
target_os = "espidf",
@ -158,6 +160,7 @@ impl Condvar {
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "android",
target_os = "espidf",

View File

@ -87,6 +87,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
// The poll on Darwin doesn't set POLLNVAL for closed fds.
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "redox",
target_os = "l4re",
@ -387,7 +388,7 @@ cfg_if::cfg_if! {
} else if #[cfg(target_os = "macos")] {
#[link(name = "System")]
extern "C" {}
} else if #[cfg(any(target_os = "ios", target_os = "watchos"))] {
} else if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
#[link(name = "System")]
#[link(name = "objc")]
#[link(name = "Security", kind = "framework")]

View File

@ -63,7 +63,13 @@ extern "C" {
#[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")]
#[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
#[cfg_attr(
any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "watchos"),
any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "freebsd",
target_os = "watchos"
),
link_name = "__error"
)]
#[cfg_attr(target_os = "haiku", link_name = "_errnop")]
@ -375,7 +381,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
Ok(PathBuf::from(OsString::from_vec(e)))
}
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn current_exe() -> io::Result<PathBuf> {
unsafe {
let mut sz: u32 = 0;
@ -609,6 +615,7 @@ pub fn home_dir() -> Option<PathBuf> {
#[cfg(any(
target_os = "android",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "emscripten",
target_os = "redox",
@ -623,6 +630,7 @@ pub fn home_dir() -> Option<PathBuf> {
#[cfg(not(any(
target_os = "android",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "emscripten",
target_os = "redox",

View File

@ -15,6 +15,8 @@ use crate::sys::weak::raw_syscall;
#[cfg(any(
target_os = "macos",
target_os = "watchos",
target_os = "tvos",
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
@ -28,7 +30,12 @@ use libc::RTP_ID as pid_t;
#[cfg(not(target_os = "vxworks"))]
use libc::{c_int, pid_t};
#[cfg(not(any(target_os = "vxworks", target_os = "l4re")))]
#[cfg(not(any(
target_os = "vxworks",
target_os = "l4re",
target_os = "tvos",
target_os = "watchos",
)))]
use libc::{gid_t, uid_t};
cfg_if::cfg_if! {
@ -84,7 +91,6 @@ impl Command {
if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
return Ok((ret, ours));
}
let (input, output) = sys::pipe::anon_pipe()?;
// Whatever happens after the fork is almost for sure going to touch or
@ -166,9 +172,31 @@ impl Command {
crate::sys_common::process::wait_with_output(proc, pipes)
}
// WatchOS and TVOS headers mark the `fork`/`exec*` functions with
// `__WATCHOS_PROHIBITED __TVOS_PROHIBITED`, and indicate that the
// `posix_spawn*` functions should be used instead. It isn't entirely clear
// what `PROHIBITED` means here (e.g. if calls to these functions are
// allowed to exist in dead code), but it sounds bad, so we go out of our
// way to avoid that all-together.
#[cfg(any(target_os = "tvos", target_os = "watchos"))]
const ERR_APPLE_TV_WATCH_NO_FORK_EXEC: Error = io::const_io_error!(
ErrorKind::Unsupported,
"`fork`+`exec`-based process spawning is not supported on this target",
);
#[cfg(any(target_os = "tvos", target_os = "watchos"))]
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
}
// Attempts to fork the process. If successful, returns Ok((0, -1))
// in the child, and Ok((child_pid, -1)) in the parent.
#[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))]
#[cfg(not(any(
target_os = "linux",
target_os = "watchos",
target_os = "tvos",
all(target_os = "nto", target_env = "nto71"),
)))]
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
cvt(libc::fork()).map(|res| (res, -1))
}
@ -339,6 +367,7 @@ impl Command {
// allocation). Instead we just close it manually. This will never
// have the drop glue anyway because this code never returns (the
// child will either exec() or invoke libc::exit)
#[cfg(not(any(target_os = "tvos", target_os = "watchos")))]
unsafe fn do_exec(
&mut self,
stdio: ChildPipes,
@ -445,8 +474,19 @@ impl Command {
Err(io::Error::last_os_error())
}
#[cfg(any(target_os = "tvos", target_os = "watchos"))]
unsafe fn do_exec(
&mut self,
_stdio: ChildPipes,
_maybe_envp: Option<&CStringArray>,
) -> Result<!, io::Error> {
return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
}
#[cfg(not(any(
target_os = "macos",
target_os = "tvos",
target_os = "watchos",
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
@ -464,6 +504,9 @@ impl Command {
// directly.
#[cfg(any(
target_os = "macos",
// FIXME: `target_os = "ios"`?
target_os = "tvos",
target_os = "watchos",
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
@ -550,7 +593,7 @@ impl Command {
}
let addchdir = match self.get_cwd() {
Some(cwd) => {
if cfg!(target_os = "macos") {
if cfg!(any(target_os = "macos", target_os = "tvos", target_os = "watchos")) {
// There is a bug in macOS where a relative executable
// path like "../myprogram" will cause `posix_spawn` to
// successfully launch the program, but erroneously return

View File

@ -14,6 +14,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
unix,
not(target_os = "macos"),
not(target_os = "ios"),
not(target_os = "tvos"),
not(target_os = "watchos"),
not(target_os = "openbsd"),
not(target_os = "freebsd"),
@ -198,7 +199,7 @@ mod imp {
// once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is
// only used on iOS where direct access to `/dev/urandom` is blocked by the
// sandbox.
#[cfg(any(target_os = "ios", target_os = "watchos"))]
#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
mod imp {
use crate::io;
use crate::ptr;

View File

@ -150,7 +150,7 @@ impl Thread {
}
}
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn set_name(name: &CStr) {
unsafe {
let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name);
@ -283,7 +283,13 @@ impl Drop for Thread {
}
}
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
#[cfg(any(
target_os = "linux",
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
))]
fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
let mut result = [0; MAX_WITH_NUL];
for (src, dst) in cstr.to_bytes().iter().zip(&mut result[..MAX_WITH_NUL - 1]) {
@ -299,6 +305,7 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
target_os = "emscripten",
target_os = "fuchsia",
target_os = "ios",
target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "solaris",

View File

@ -46,6 +46,7 @@ unsafe fn wait_timeout(
#[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "espidf",
target_os = "horizon",
@ -73,6 +74,7 @@ unsafe fn wait_timeout(
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "espidf",
target_os = "horizon",
@ -120,6 +122,7 @@ impl Parker {
if #[cfg(any(
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos",
target_os = "l4re",
target_os = "android",

View File

@ -219,7 +219,8 @@ impl From<__timespec64> for Timespec {
#[cfg(any(
all(target_os = "macos", any(not(target_arch = "aarch64"))),
target_os = "ios",
target_os = "watchos"
target_os = "watchos",
target_os = "tvos"
))]
mod inner {
use crate::sync::atomic::{AtomicU64, Ordering};
@ -339,7 +340,8 @@ mod inner {
#[cfg(not(any(
all(target_os = "macos", any(not(target_arch = "aarch64"))),
target_os = "ios",
target_os = "watchos"
target_os = "watchos",
target_os = "tvos"
)))]
mod inner {
use crate::fmt;

View File

@ -28,7 +28,7 @@ use crate::ptr;
use crate::sync::atomic::{self, AtomicPtr, Ordering};
// We can use true weak linkage on ELF targets.
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))]
pub(crate) macro weak {
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
@ -43,7 +43,7 @@ pub(crate) macro weak {
}
// On non-ELF targets, use the dlsym approximation of weak linkage.
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))]
pub(crate) use self::dlsym as weak;
pub(crate) struct ExternWeak<F: Copy> {

View File

@ -18,7 +18,7 @@ use crate::ffi::{c_int, c_void};
cfg_if::cfg_if! {
if #[cfg(any(
target_os = "dragonfly", target_os = "freebsd",
target_os = "ios", target_os = "macos", target_os = "watchos",
target_os = "ios", target_os = "tvos", target_os = "macos", target_os = "watchos",
target_os = "openbsd", target_os = "netbsd", target_os = "illumos",
target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] {
use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;

View File

@ -42,6 +42,7 @@ fn test_named_thread() {
all(target_os = "linux", target_env = "gnu"),
target_os = "macos",
target_os = "ios",
target_os = "tvos",
target_os = "watchos"
))]
#[test]

View File

@ -117,7 +117,7 @@ extern "C" {
}
cfg_if::cfg_if! {
if #[cfg(any(target_os = "ios", target_os = "watchos", target_os = "netbsd", not(target_arch = "arm")))] {
if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "netbsd", not(target_arch = "arm")))] {
// Not ARM EHABI
#[repr(C)]
#[derive(Copy, Clone, PartialEq)]

View File

@ -16,6 +16,7 @@
- [Target Tier Policy](target-tier-policy.md)
- [Template for Target-specific Documentation](platform-support/TEMPLATE.md)
- [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md)
- [\*-apple-tvos](platform-support/apple-tvos.md)
- [\*-apple-watchos\*](platform-support/apple-watchos.md)
- [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
- [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md)

View File

@ -214,7 +214,7 @@ host tools.
target | std | host | notes
-------|:---:|:----:|-------
`aarch64-apple-ios-macabi` | ? | | Apple Catalyst on ARM64
`aarch64-apple-tvos` | * | | ARM64 tvOS
[`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ? | | ARM64 tvOS
[`aarch64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | ARM64 Apple WatchOS Simulator
[`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3
[`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon
@ -316,7 +316,7 @@ target | std | host | notes
`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL
[`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly
`x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64
`x86_64-apple-tvos` | * | | x86 64-bit tvOS
[`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS
[`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS |
[`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |

View File

@ -0,0 +1,85 @@
# `*-apple-tvos`
- aarch64-apple-tvos
- x86_64-apple-tvos
**Tier: 3**
Apple tvOS targets:
- Apple tvOS on aarch64
- Apple tvOS Simulator on x86_64
## Target maintainers
* [@thomcc](https://github.com/thomcc)
## Requirements
These targets are cross-compiled. You will need appropriate versions of Xcode
and the SDKs for tvOS (`AppleTVOS.sdk`) and/or the tvOS Simulator
(`AppleTVSimulator.sdk`) to build a toolchain and target these platforms.
The targets support most (see below) of the standard library including the
allocator to the best of my knowledge, however they are very new, not yet
well-tested, and it is possible that there are various bugs.
In theory we support back to tvOS version 7.0, although the actual minimum
version you can target may be newer than this, for example due to the versions
of Xcode and your SDKs.
As with the other Apple targets, `rustc` respects the common environment
variables used by Xcode to configure this, in this case
`TVOS_DEPLOYMENT_TARGET`.
#### Incompletely supported library functionality
As mentioned, "most" of the standard library is supported, which means that some portions
are known to be unsupported. The following APIs are currently known to have
missing or incomplete support:
- `std::process::Command`'s API will return an error if it is configured in a
manner which cannot be performed using `posix_spawn` -- this is because the
more flexible `fork`/`exec`-based approach is prohibited on these platforms in
favor of `posix_spawn{,p}` (which still probably will get you rejected from
app stores, so is likely sideloading-only). A concrete set of cases where this
will occur is difficult to enumerate (and would quickly become stale), but in
some cases it may be worked around by tweaking the manner in which `Command`
is invoked.
## Building the target
The targets can be built by enabling them for a `rustc` build in `config.toml`, by adding, for example:
```toml
[build]
build-stage = 1
target = ["aarch64-apple-tvos", "x86_64-apple-tvos"]
```
It's possible that cargo under `-Zbuild-std` may also be used to target them.
## Building Rust programs
*Note: Building for this target requires the corresponding TVOS SDK, as provided by Xcode.*
Rust programs can be built for these targets
```text
$ rustc --target aarch64-apple-tvos your-code.rs
...
$ rustc --target x86_64-apple-tvos your-code.rs
```
## Testing
There is no support for running the Rust or standard library testsuite on tvOS
or the simulators at the moment. Testing has mostly been done manually with
builds of static libraries called from Xcode or a simulator.
It hopefully will be possible to improve this in the future.
## Cross-compilation toolchains and C code
This target can be cross-compiled from x86_64 or aarch64 macOS hosts.
Other hosts are not supported for cross-compilation, but might work when also
providing the required Xcode SDK.