about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/std/src/os/unix/process.rs2
-rw-r--r--library/std/src/process.rs16
-rw-r--r--library/std/src/process/tests.rs102
-rw-r--r--library/std/src/sys/process/unix/unix/tests.rs1
-rw-r--r--library/std/tests/process_spawning.rs1
-rw-r--r--src/doc/rustc-dev-guide/src/tests/running.md31
-rw-r--r--src/doc/rustc/src/platform-support/apple-ios.md22
-rw-r--r--src/doc/rustc/src/platform-support/apple-tvos.md13
-rw-r--r--src/doc/rustc/src/platform-support/apple-visionos.md13
-rw-r--r--src/doc/rustc/src/platform-support/apple-watchos.md13
-rw-r--r--src/tools/remote-test-server/src/main.rs19
-rw-r--r--tests/ui/backtrace/apple-no-dsymutil.rs1
-rw-r--r--tests/ui/backtrace/dylib-dep.rs4
-rw-r--r--tests/ui/backtrace/line-tables-only.rs4
-rw-r--r--tests/ui/command/command-current-dir.rs2
-rw-r--r--tests/ui/command/command-exec.rs2
-rw-r--r--tests/ui/command/command-pre-exec.rs2
-rw-r--r--tests/ui/command/command-uid-gid.rs2
-rw-r--r--tests/ui/compiletest-self-test/test-aux-bin.rs1
-rw-r--r--tests/ui/cross-crate/exporting-impl-from-root-causes-ice-2472.rs5
-rw-r--r--tests/ui/issues/issue-45731.rs4
-rw-r--r--tests/ui/process/core-run-destroy.rs4
-rw-r--r--tests/ui/process/env-funky-keys.rs19
-rw-r--r--tests/ui/process/fds-are-cloexec.rs11
-rw-r--r--tests/ui/process/println-with-broken-pipe.rs4
-rw-r--r--tests/ui/process/process-envs.rs4
-rw-r--r--tests/ui/process/process-panic-after-fork.rs2
-rw-r--r--tests/ui/process/process-remove-from-env.rs4
-rw-r--r--tests/ui/process/process-sigpipe.rs4
-rw-r--r--tests/ui/process/process-spawn-failure.rs4
-rw-r--r--tests/ui/runtime/backtrace-debuginfo.rs4
-rw-r--r--tests/ui/runtime/on-broken-pipe/child-processes.rs1
-rw-r--r--tests/ui/runtime/on-broken-pipe/inherit.rs1
33 files changed, 245 insertions, 77 deletions
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 09429af06e3..5b7b5a8ea80 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -406,8 +406,10 @@ pub trait ChildExt: Sealed {
     /// use libc::SIGTERM;
     ///
     /// fn main() -> io::Result<()> {
+    ///     # if cfg!(not(all(target_vendor = "apple", not(target_os = "macos")))) {
     ///     let child = Command::new("cat").stdin(Stdio::piped()).spawn()?;
     ///     child.send_signal(SIGTERM)?;
+    ///     # }
     ///     Ok(())
     /// }
     /// ```
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 48265de90c4..0883e56342c 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -532,6 +532,7 @@ impl fmt::Debug for ChildStderr {
 /// to be changed (for example, by adding arguments) prior to spawning:
 ///
 /// ```
+/// # if cfg!(not(all(target_vendor = "apple", not(target_os = "macos")))) {
 /// use std::process::Command;
 ///
 /// let output = if cfg!(target_os = "windows") {
@@ -548,6 +549,7 @@ impl fmt::Debug for ChildStderr {
 /// };
 ///
 /// let hello = output.stdout;
+/// # }
 /// ```
 ///
 /// `Command` can be reused to spawn multiple processes. The builder methods
@@ -1348,7 +1350,7 @@ impl Output {
     ///
     /// ```
     /// #![feature(exit_status_error)]
-    /// # #[cfg(all(unix, not(target_os = "android")))] {
+    /// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] {
     /// use std::process::Command;
     /// assert!(Command::new("false").output().unwrap().exit_ok().is_err());
     /// # }
@@ -1695,7 +1697,7 @@ impl From<io::Stdout> for Stdio {
     /// # Ok(())
     /// # }
     /// #
-    /// # if cfg!(all(unix, not(target_os = "android"))) {
+    /// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// #     test().unwrap();
     /// # }
     /// ```
@@ -1724,7 +1726,7 @@ impl From<io::Stderr> for Stdio {
     /// # Ok(())
     /// # }
     /// #
-    /// # if cfg!(all(unix, not(target_os = "android"))) {
+    /// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// #     test().unwrap();
     /// # }
     /// ```
@@ -1800,7 +1802,7 @@ impl ExitStatus {
     ///
     /// ```
     /// #![feature(exit_status_error)]
-    /// # if cfg!(unix) {
+    /// # if cfg!(all(unix, not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// use std::process::Command;
     ///
     /// let status = Command::new("ls")
@@ -1907,7 +1909,7 @@ impl crate::sealed::Sealed for ExitStatusError {}
 ///
 /// ```
 /// #![feature(exit_status_error)]
-/// # if cfg!(all(unix, not(target_os = "android"))) {
+/// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
 /// use std::process::{Command, ExitStatusError};
 ///
 /// fn run(cmd: &str) -> Result<(), ExitStatusError> {
@@ -1950,7 +1952,7 @@ impl ExitStatusError {
     ///
     /// ```
     /// #![feature(exit_status_error)]
-    /// # #[cfg(all(unix, not(target_os = "android")))] {
+    /// # #[cfg(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos")))))] {
     /// use std::process::Command;
     ///
     /// let bad = Command::new("false").status().unwrap().exit_ok().unwrap_err();
@@ -1975,7 +1977,7 @@ impl ExitStatusError {
     /// ```
     /// #![feature(exit_status_error)]
     ///
-    /// # if cfg!(all(unix, not(target_os = "android"))) {
+    /// # if cfg!(all(unix, not(target_os = "android"), not(all(target_vendor = "apple", not(target_os = "macos"))))) {
     /// use std::num::NonZero;
     /// use std::process::Command;
     ///
diff --git a/library/std/src/process/tests.rs b/library/std/src/process/tests.rs
index 5879914ca20..12c5130defe 100644
--- a/library/std/src/process/tests.rs
+++ b/library/std/src/process/tests.rs
@@ -5,7 +5,15 @@ use crate::mem::MaybeUninit;
 use crate::str;
 
 fn known_command() -> Command {
-    if cfg!(windows) { Command::new("help") } else { Command::new("echo") }
+    if cfg!(windows) {
+        Command::new("help")
+    } else if cfg!(all(target_vendor = "apple", not(target_os = "macos"))) {
+        // iOS/tvOS/watchOS/visionOS have a very limited set of commandline
+        // binaries available.
+        Command::new("log")
+    } else {
+        Command::new("echo")
+    }
 }
 
 #[cfg(target_os = "android")]
@@ -19,7 +27,10 @@ fn shell_cmd() -> Command {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn smoke() {
     let p = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 0"]).spawn()
@@ -41,7 +52,10 @@ fn smoke_failure() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn exit_reported_right() {
     let p = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).spawn()
@@ -56,7 +70,10 @@ fn exit_reported_right() {
 
 #[test]
 #[cfg(unix)]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn signal_reported_right() {
     use crate::os::unix::process::ExitStatusExt;
 
@@ -80,7 +97,10 @@ pub fn run_output(mut cmd: Command) -> String {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn stdout_works() {
     if cfg!(target_os = "windows") {
         let mut cmd = Command::new("cmd");
@@ -94,7 +114,11 @@ fn stdout_works() {
 }
 
 #[test]
-#[cfg_attr(any(windows, target_os = "vxworks"), ignore)]
+#[cfg_attr(windows, ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn set_current_dir_works() {
     // On many Unix platforms this will use the posix_spawn path.
     let mut cmd = shell_cmd();
@@ -116,7 +140,11 @@ fn set_current_dir_works() {
 }
 
 #[test]
-#[cfg_attr(any(windows, target_os = "vxworks"), ignore)]
+#[cfg_attr(windows, ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn stdin_works() {
     let mut p = shell_cmd()
         .arg("-c")
@@ -134,7 +162,10 @@ fn stdin_works() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn child_stdout_read_buf() {
     let mut cmd = if cfg!(target_os = "windows") {
         let mut cmd = Command::new("cmd");
@@ -165,7 +196,10 @@ fn child_stdout_read_buf() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_process_status() {
     let mut status = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).status().unwrap()
@@ -191,7 +225,10 @@ fn test_process_output_fail_to_start() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_process_output_output() {
     let Output { status, stdout, stderr } = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "echo hello"]).output().unwrap()
@@ -206,7 +243,10 @@ fn test_process_output_output() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_process_output_error() {
     let Output { status, stdout, stderr } = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "mkdir ."]).output().unwrap()
@@ -221,7 +261,10 @@ fn test_process_output_error() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_finish_once() {
     let mut prog = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
@@ -232,7 +275,10 @@ fn test_finish_once() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_finish_twice() {
     let mut prog = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "exit 1"]).spawn().unwrap()
@@ -244,7 +290,10 @@ fn test_finish_twice() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_wait_with_output_once() {
     let prog = if cfg!(target_os = "windows") {
         Command::new("cmd").args(&["/C", "echo hello"]).stdout(Stdio::piped()).spawn().unwrap()
@@ -279,7 +328,10 @@ pub fn env_cmd() -> Command {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_override_env() {
     use crate::env;
 
@@ -302,7 +354,10 @@ fn test_override_env() {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_add_to_env() {
     let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
     let output = String::from_utf8_lossy(&result.stdout).to_string();
@@ -314,7 +369,10 @@ fn test_add_to_env() {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no shell available"
+)]
 fn test_capture_env_at_spawn() {
     use crate::env;
 
@@ -378,7 +436,10 @@ fn test_interior_nul_in_current_dir_is_error() {
 
 // Regression tests for #30862.
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no `env` cmd available"
+)]
 fn test_interior_nul_in_env_key_is_error() {
     match env_cmd().env("has-some-\0\0s-inside", "value").spawn() {
         Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
@@ -387,7 +448,10 @@ fn test_interior_nul_in_env_key_is_error() {
 }
 
 #[test]
-#[cfg_attr(target_os = "vxworks", ignore)]
+#[cfg_attr(
+    any(target_os = "vxworks", all(target_vendor = "apple", not(target_os = "macos"))),
+    ignore = "no `env` cmd available"
+)]
 fn test_interior_nul_in_env_value_is_error() {
     match env_cmd().env("key", "has-some-\0\0s-inside").spawn() {
         Err(e) => assert_eq!(e.kind(), ErrorKind::InvalidInput),
diff --git a/library/std/src/sys/process/unix/unix/tests.rs b/library/std/src/sys/process/unix/unix/tests.rs
index f4d6ac6b4e3..663ba61f966 100644
--- a/library/std/src/sys/process/unix/unix/tests.rs
+++ b/library/std/src/sys/process/unix/unix/tests.rs
@@ -51,6 +51,7 @@ fn exitstatus_display_tests() {
 
 #[test]
 #[cfg_attr(target_os = "emscripten", ignore)]
+#[cfg_attr(any(target_os = "tvos", target_os = "watchos"), ignore = "fork is prohibited")]
 fn test_command_fork_no_unwind() {
     let got = catch_unwind(|| {
         let mut c = Command::new("echo");
diff --git a/library/std/tests/process_spawning.rs b/library/std/tests/process_spawning.rs
index 43b45cb2d2b..93f73ccad3e 100644
--- a/library/std/tests/process_spawning.rs
+++ b/library/std/tests/process_spawning.rs
@@ -7,6 +7,7 @@ mod common;
 #[test]
 // Process spawning not supported by Miri, Emscripten and wasi
 #[cfg_attr(any(miri, target_os = "emscripten", target_os = "wasi"), ignore)]
+#[cfg_attr(any(target_os = "tvos", target_os = "watchos"), ignore = "fork is prohibited")]
 fn issue_15149() {
     // If we're the parent, copy our own binary to a new directory.
     let my_path = env::current_exe().unwrap();
diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md
index 317b65f98cd..482f3c42578 100644
--- a/src/doc/rustc-dev-guide/src/tests/running.md
+++ b/src/doc/rustc-dev-guide/src/tests/running.md
@@ -339,9 +339,34 @@ results.  The Docker image is set up to launch `remote-test-server` and the
 build tools use `remote-test-client` to communicate with the server to
 coordinate running tests (see [src/bootstrap/src/core/build_steps/test.rs]).
 
-> **TODO**
->
-> - Is there any support for using an iOS emulator?
+To run on the iOS/tvOS/watchOS/visionOS simulator, we can similarly treat it as
+a "remote" machine. A curious detail here is that the network is shared between
+the simulator instance and the host macOS, so we can use the local loopback
+address `127.0.0.1`. Something like the following should work:
+
+```sh
+# Build the test server for the iOS simulator:
+./x build src/tools/remote-test-server --target aarch64-apple-ios-sim
+
+# If you already have a simulator instance open, copy the device UUID from:
+xcrun simctl list devices booted
+UDID=01234567-89AB-CDEF-0123-456789ABCDEF
+
+# Alternatively, create and boot a new simulator instance:
+xcrun simctl list runtimes
+xcrun simctl list devicetypes
+UDID=$(xcrun simctl create $CHOSEN_DEVICE_TYPE $CHOSEN_RUNTIME)
+xcrun simctl boot $UDID
+# See https://nshipster.com/simctl/ for details.
+
+# Spawn the runner on port 12345:
+xcrun simctl spawn $UDID ./build/host/stage2-tools/aarch64-apple-ios-sim/release/remote-test-server -v --bind 127.0.0.1:12345
+
+# In a new terminal, run tests via the runner:
+export TEST_DEVICE_ADDR="127.0.0.1:12345"
+./x test --host='' --target aarch64-apple-ios-sim --skip tests/debuginfo
+# FIXME(madsmtm): Allow debuginfo tests to work (maybe needs `.dSYM` folder to be copied to the target?).
+```
 
 [armhf-gnu]: https://github.com/rust-lang/rust/tree/master/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
 [QEMU]: https://www.qemu.org/
diff --git a/src/doc/rustc/src/platform-support/apple-ios.md b/src/doc/rustc/src/platform-support/apple-ios.md
index 586afa65226..3ac14704754 100644
--- a/src/doc/rustc/src/platform-support/apple-ios.md
+++ b/src/doc/rustc/src/platform-support/apple-ios.md
@@ -66,6 +66,11 @@ Rust programs can be built for these targets by specifying `--target`, if
 $ rustc --target aarch64-apple-ios your-code.rs
 ```
 
+Or if using Cargo and `-Zbuild-std`:
+```console
+$ cargo +nightly build -Zbuild-std --target armv7s-apple-ios
+```
+
 The simulator variants can be differentiated from the variants running
 on-device with the `target_env = "sim"` cfg (or `target_abi = "sim"` before
 Rust CURRENT_RUSTC_VERSION).
@@ -73,7 +78,7 @@ Rust CURRENT_RUSTC_VERSION).
 ```rust
 if cfg!(all(target_vendor = "apple", target_env = "sim")) {
     // Do something on the iOS/tvOS/visionOS/watchOS Simulator.
-} {
+} else {
     // Everything else, like Windows and non-Simulator iOS.
 }
 ```
@@ -82,8 +87,15 @@ This is similar to the `TARGET_OS_SIMULATOR` define in C code.
 
 ## Testing
 
-There is no support for running the Rust or standard library testsuite at the
-moment. Testing has mostly been done manually with builds of static libraries
-embedded into applications called from Xcode or a simulator.
+Running and testing your code naturally requires either an actual device
+running iOS, or the equivalent Xcode simulator environment. There exists
+several tools in the ecosystem for running a Cargo project on one of these.
+One of these tools is [`cargo-dinghy`]. [madsmtm/objc2#459] contains a more
+exhaustive list.
+
+See also [testing on emulators in the `rustc-dev-guide`][test-sim] for
+instructions on running the standard library's test suite.
 
-It hopefully will be possible to improve this in the future.
+[`cargo-dinghy`]: https://github.com/sonos/dinghy
+[madsmtm/objc2#459]: https://github.com/madsmtm/objc2/issues/459
+[test-sim]: https://rustc-dev-guide.rust-lang.org/tests/running.html#testing-on-emulators
diff --git a/src/doc/rustc/src/platform-support/apple-tvos.md b/src/doc/rustc/src/platform-support/apple-tvos.md
index 193d6466612..a952d8e230d 100644
--- a/src/doc/rustc/src/platform-support/apple-tvos.md
+++ b/src/doc/rustc/src/platform-support/apple-tvos.md
@@ -65,17 +65,8 @@ Using the unstable `-Zbuild-std` with a nightly Cargo may also work.
 
 ## Building Rust programs
 
-Rust programs can be built for these targets by specifying `--target`, if
-`rustc` has been built with support for them. For example:
-
-```console
-$ rustc --target aarch64-apple-tvos your-code.rs
-```
+See [the instructions for iOS](./apple-ios.md#building-rust-programs).
 
 ## Testing
 
-There is no support for running the Rust or standard library testsuite at the
-moment. Testing has mostly been done manually with builds of static libraries
-embedded into applications called from Xcode or a simulator.
-
-It hopefully will be possible to improve this in the future.
+See [the instructions for iOS](./apple-ios.md#testing).
diff --git a/src/doc/rustc/src/platform-support/apple-visionos.md b/src/doc/rustc/src/platform-support/apple-visionos.md
index ed96912da7a..2ac069248ee 100644
--- a/src/doc/rustc/src/platform-support/apple-visionos.md
+++ b/src/doc/rustc/src/platform-support/apple-visionos.md
@@ -46,20 +46,11 @@ be fixed in [#124560](https://github.com/rust-lang/rust/pull/124560).
 
 ## Building Rust programs
 
-Rust programs can be built for these targets by specifying `--target`, if
-`rustc` has been built with support for them. For example:
-
-```console
-$ rustc --target aarch64-apple-visionos-sim your-code.rs
-```
+See [the instructions for iOS](./apple-ios.md#building-rust-programs).
 
 ## Testing
 
-There is no support for running the Rust or standard library testsuite at the
-moment. Testing has mostly been done manually with builds of static libraries
-embedded into applications called from Xcode or a simulator.
-
-It hopefully will be possible to improve this in the future.
+See [the instructions for iOS](./apple-ios.md#testing).
 
 ## Cross-compilation toolchains and C code
 
diff --git a/src/doc/rustc/src/platform-support/apple-watchos.md b/src/doc/rustc/src/platform-support/apple-watchos.md
index 6ac09d0d1e5..c1a00961425 100644
--- a/src/doc/rustc/src/platform-support/apple-watchos.md
+++ b/src/doc/rustc/src/platform-support/apple-watchos.md
@@ -50,17 +50,8 @@ Using the unstable `-Zbuild-std` with a nightly Cargo may also work.
 
 ## Building Rust programs
 
-Rust programs can be built for these targets by specifying `--target`, if
-`rustc` has been built with support for them. For example:
-
-```console
-$ rustc --target aarch64-apple-watchos-sim your-code.rs
-```
+See [the instructions for iOS](./apple-ios.md#building-rust-programs).
 
 ## Testing
 
-There is no support for running the Rust or standard library testsuite at the
-moment. Testing has mostly been done manually with builds of static libraries
-embedded into applications called from Xcode or a simulator.
-
-It hopefully will be possible to improve this in the future.
+See [the instructions for iOS](./apple-ios.md#testing).
diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs
index 67a7ad6f3b4..5ec5e6e2898 100644
--- a/src/tools/remote-test-server/src/main.rs
+++ b/src/tools/remote-test-server/src/main.rs
@@ -53,6 +53,10 @@ impl Config {
             batch: false,
             bind: if cfg!(target_os = "android") || cfg!(windows) {
                 ([0, 0, 0, 0], 12345).into()
+            } else if cfg!(target_env = "sim") {
+                // iOS/tvOS/watchOS/visionOS simulators share network device
+                // with the host machine.
+                ([127, 0, 0, 1], 12345).into()
             } else {
                 ([10, 0, 2, 15], 12345).into()
             },
@@ -262,10 +266,17 @@ fn handle_run(socket: TcpStream, work: &Path, tmp: &Path, lock: &Mutex<()>, conf
     cmd.args(args);
     cmd.envs(env);
 
-    // On windows, libraries are just searched in the executable directory,
-    // system directories, PWD, and PATH, in that order. PATH is the only one
-    // we can change for this.
-    let library_path = if cfg!(windows) { "PATH" } else { "LD_LIBRARY_PATH" };
+    let library_path = if cfg!(windows) {
+        // On windows, libraries are just searched in the executable directory,
+        // system directories, PWD, and PATH, in that order. PATH is the only
+        // one we can change for this.
+        "PATH"
+    } else if cfg!(target_vendor = "apple") {
+        // On Apple platforms, the environment variable is named differently.
+        "DYLD_LIBRARY_PATH"
+    } else {
+        "LD_LIBRARY_PATH"
+    };
 
     // Support libraries were uploaded to `work` earlier, so make sure that's
     // in `LD_LIBRARY_PATH`. Also include our own current dir which may have
diff --git a/tests/ui/backtrace/apple-no-dsymutil.rs b/tests/ui/backtrace/apple-no-dsymutil.rs
index e5aeced25ca..00c8349d129 100644
--- a/tests/ui/backtrace/apple-no-dsymutil.rs
+++ b/tests/ui/backtrace/apple-no-dsymutil.rs
@@ -3,6 +3,7 @@
 //@ compile-flags:-Cstrip=none
 //@ compile-flags:-g -Csplit-debuginfo=unpacked
 //@ only-apple
+//@ ignore-remote needs the compiler-produced `.o` file to be copied to the device
 
 use std::process::Command;
 use std::str;
diff --git a/tests/ui/backtrace/dylib-dep.rs b/tests/ui/backtrace/dylib-dep.rs
index 05fdb9afef8..cf420ec8d06 100644
--- a/tests/ui/backtrace/dylib-dep.rs
+++ b/tests/ui/backtrace/dylib-dep.rs
@@ -7,6 +7,10 @@
 //@ ignore-android FIXME #17520
 //@ ignore-fuchsia Backtraces not symbolized
 //@ ignore-musl musl doesn't support dynamic libraries (at least when the original test was written).
+//@ ignore-ios needs the `.dSYM` files to be moved to the device
+//@ ignore-tvos needs the `.dSYM` files to be moved to the device
+//@ ignore-watchos needs the `.dSYM` files to be moved to the device
+//@ ignore-visionos needs the `.dSYM` files to be moved to the device
 //@ needs-unwind
 //@ ignore-backends: gcc
 //@ compile-flags: -g -Copt-level=0 -Cstrip=none -Cforce-frame-pointers=yes
diff --git a/tests/ui/backtrace/line-tables-only.rs b/tests/ui/backtrace/line-tables-only.rs
index 6624c71e184..5863cc1d17d 100644
--- a/tests/ui/backtrace/line-tables-only.rs
+++ b/tests/ui/backtrace/line-tables-only.rs
@@ -11,6 +11,10 @@
 //@ ignore-android FIXME #17520
 //@ ignore-fuchsia Backtraces not symbolized
 //@ ignore-emscripten Requires custom symbolization code
+//@ ignore-ios needs the `.dSYM` files to be moved to the device
+//@ ignore-tvos needs the `.dSYM` files to be moved to the device
+//@ ignore-watchos needs the `.dSYM` files to be moved to the device
+//@ ignore-visionos needs the `.dSYM` files to be moved to the device
 //@ needs-unwind
 //@ aux-build: line-tables-only-helper.rs
 
diff --git a/tests/ui/command/command-current-dir.rs b/tests/ui/command/command-current-dir.rs
index e264cbe4d70..a6b51df5f17 100644
--- a/tests/ui/command/command-current-dir.rs
+++ b/tests/ui/command/command-current-dir.rs
@@ -2,6 +2,8 @@
 //@ no-prefer-dynamic We move the binary around, so do not depend dynamically on libstd
 //@ needs-subprocess
 //@ ignore-fuchsia Needs directory creation privilege
+//@ ignore-tvos `Command::current_dir` requires fork, which is prohibited
+//@ ignore-watchos `Command::current_dir` requires fork, which is prohibited
 
 use std::env;
 use std::fs;
diff --git a/tests/ui/command/command-exec.rs b/tests/ui/command/command-exec.rs
index 77336377e88..870f8b047b9 100644
--- a/tests/ui/command/command-exec.rs
+++ b/tests/ui/command/command-exec.rs
@@ -3,6 +3,8 @@
 //@ only-unix (this is a unix-specific test)
 //@ needs-subprocess
 //@ ignore-fuchsia no execvp syscall provided
+//@ ignore-tvos execvp is prohibited
+//@ ignore-watchos execvp is prohibited
 
 use std::env;
 use std::os::unix::process::CommandExt;
diff --git a/tests/ui/command/command-pre-exec.rs b/tests/ui/command/command-pre-exec.rs
index 7299f357bd0..a62ab0b5ed6 100644
--- a/tests/ui/command/command-pre-exec.rs
+++ b/tests/ui/command/command-pre-exec.rs
@@ -2,6 +2,8 @@
 //@ only-unix (this is a unix-specific test)
 //@ needs-subprocess
 //@ ignore-fuchsia no execvp syscall
+//@ ignore-tvos execvp is prohibited
+//@ ignore-watchos execvp is prohibited
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/command/command-uid-gid.rs b/tests/ui/command/command-uid-gid.rs
index f54a0f50708..ef0653eb2cb 100644
--- a/tests/ui/command/command-uid-gid.rs
+++ b/tests/ui/command/command-uid-gid.rs
@@ -1,6 +1,8 @@
 //@ run-pass
 //@ ignore-android
 //@ ignore-fuchsia no '/bin/sh', '/bin/ls'
+//@ ignore-tvos `Command::uid/gid` requires fork, which is prohibited
+//@ ignore-watchos `Command::uid/gid` requires fork, which is prohibited
 //@ needs-subprocess
 
 #![feature(rustc_private)]
diff --git a/tests/ui/compiletest-self-test/test-aux-bin.rs b/tests/ui/compiletest-self-test/test-aux-bin.rs
index c1c28e12b3b..9ac17e6e146 100644
--- a/tests/ui/compiletest-self-test/test-aux-bin.rs
+++ b/tests/ui/compiletest-self-test/test-aux-bin.rs
@@ -1,4 +1,5 @@
 //@ ignore-cross-compile because aux-bin does not yet support it
+//@ ignore-remote because aux-bin does not yet support it
 //@ aux-bin: print-it-works.rs
 //@ run-pass
 
diff --git a/tests/ui/cross-crate/exporting-impl-from-root-causes-ice-2472.rs b/tests/ui/cross-crate/exporting-impl-from-root-causes-ice-2472.rs
index 86d637b579d..c6cfae1e545 100644
--- a/tests/ui/cross-crate/exporting-impl-from-root-causes-ice-2472.rs
+++ b/tests/ui/cross-crate/exporting-impl-from-root-causes-ice-2472.rs
@@ -1,6 +1,9 @@
 //@ run-pass
 //@ aux-build:exporting-impl-from-root-causes-ice-2472-b.rs
-
+//@ ignore-ios FIXME(madsmtm): For some reason the necessary dylib isn't copied to the remote?
+//@ ignore-tvos FIXME(madsmtm): For some reason the necessary dylib isn't copied to the remote?
+//@ ignore-watchos FIXME(madsmtm): For some reason the necessary dylib isn't copied to the remote?
+//@ ignore-visionos FIXME(madsmtm): For some reason the necessary dylib isn't copied to the remote?
 
 extern crate exporting_impl_from_root_causes_ice_2472_b as lib;
 
diff --git a/tests/ui/issues/issue-45731.rs b/tests/ui/issues/issue-45731.rs
index 49335362dd0..db11d1dbef1 100644
--- a/tests/ui/issues/issue-45731.rs
+++ b/tests/ui/issues/issue-45731.rs
@@ -1,6 +1,10 @@
 //@ run-pass
 #![allow(unused_variables)]
 //@ compile-flags:--test -g
+//@ ignore-ios needs the `.dSYM` files to be moved to the device
+//@ ignore-tvos needs the `.dSYM` files to be moved to the device
+//@ ignore-watchos needs the `.dSYM` files to be moved to the device
+//@ ignore-visionos needs the `.dSYM` files to be moved to the device
 
 #[cfg(target_vendor = "apple")]
 #[test]
diff --git a/tests/ui/process/core-run-destroy.rs b/tests/ui/process/core-run-destroy.rs
index f4be54da8fe..f381997ef79 100644
--- a/tests/ui/process/core-run-destroy.rs
+++ b/tests/ui/process/core-run-destroy.rs
@@ -8,6 +8,10 @@
 //@ needs-subprocess
 //@ ignore-vxworks no 'cat' and 'sleep'
 //@ ignore-fuchsia no 'cat'
+//@ ignore-ios no 'cat' and 'sleep'
+//@ ignore-tvos no 'cat' and 'sleep'
+//@ ignore-watchos no 'cat' and 'sleep'
+//@ ignore-visionos no 'cat' and 'sleep'
 
 // N.B., these tests kill child processes. Valgrind sees these children as leaking
 // memory, which makes for some *confusing* logs. That's why these are here
diff --git a/tests/ui/process/env-funky-keys.rs b/tests/ui/process/env-funky-keys.rs
index a4a71c94020..193659bea29 100644
--- a/tests/ui/process/env-funky-keys.rs
+++ b/tests/ui/process/env-funky-keys.rs
@@ -1,8 +1,7 @@
 //@ run-pass
 //@ edition: 2021
-// Ignore this test on Android, because it segfaults there.
 
-//@ ignore-android
+//@ ignore-android segfaults
 //@ ignore-windows
 //@ ignore-wasm32 no execve
 //@ ignore-sgx no execve
@@ -24,6 +23,9 @@ use std::ptr;
 fn main() {
     if env::args_os().count() == 2 {
         for (key, value) in env::vars_os() {
+            if key == "DYLD_ROOT_PATH" {
+                continue;
+            }
             panic!("found env value {:?} {:?}", key, value);
         }
         return;
@@ -35,7 +37,18 @@ fn main() {
                                        .as_bytes()).unwrap();
     let filename: *const c_char = current_exe.as_ptr();
     let argv: &[*const c_char] = &[filename, filename, ptr::null()];
-    let envp: &[*const c_char] = &[c"FOOBAR".as_ptr(), ptr::null()];
+
+    let root;
+    let envp: &[*const c_char] = if cfg!(all(target_vendor = "apple", target_env = "sim")) {
+        // Workaround: iOS/tvOS/watchOS/visionOS simulators need the root path
+        // from the current process.
+        root = format!("DYLD_ROOT_PATH={}\0", std::env::var("DYLD_ROOT_PATH").unwrap());
+        &[c"FOOBAR".as_ptr(), root.as_ptr().cast(), ptr::null()]
+    } else {
+        // Try to set an environment variable without a value.
+        &[c"FOOBAR".as_ptr(), ptr::null()]
+    };
+
     unsafe {
         execve(filename, &argv[0], &envp[0]);
     }
diff --git a/tests/ui/process/fds-are-cloexec.rs b/tests/ui/process/fds-are-cloexec.rs
index f6678379dd6..0fae7c2b502 100644
--- a/tests/ui/process/fds-are-cloexec.rs
+++ b/tests/ui/process/fds-are-cloexec.rs
@@ -74,8 +74,15 @@ fn child(args: &[String]) {
         let fd: libc::c_int = arg.parse().unwrap();
         unsafe {
             assert_eq!(libc::read(fd, b.as_mut_ptr() as *mut _, 2), -1);
-            assert_eq!(io::Error::last_os_error().raw_os_error(),
-                       Some(libc::EBADF));
+            let raw = io::Error::last_os_error().raw_os_error();
+            if cfg!(all(target_vendor = "apple", not(target_os = "macos"))) {
+                // Workaround: iOS/tvOS/watchOS/visionOS seems to treat `tcp6`
+                // as a directory?
+                if raw == Some(libc::EISDIR) {
+                    continue;
+                }
+            }
+            assert_eq!(raw, Some(libc::EBADF));
         }
     }
 }
diff --git a/tests/ui/process/println-with-broken-pipe.rs b/tests/ui/process/println-with-broken-pipe.rs
index 58b83a2dd9a..e87e2077370 100644
--- a/tests/ui/process/println-with-broken-pipe.rs
+++ b/tests/ui/process/println-with-broken-pipe.rs
@@ -5,6 +5,10 @@
 //@ ignore-fuchsia
 //@ ignore-horizon
 //@ ignore-android
+//@ ignore-ios no 'head'
+//@ ignore-tvos no 'head'
+//@ ignore-watchos no 'head'
+//@ ignore-visionos no 'head'
 //@ ignore-backends: gcc
 //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC"
 //@ compile-flags: -Zon-broken-pipe=error
diff --git a/tests/ui/process/process-envs.rs b/tests/ui/process/process-envs.rs
index 98052f1d3a5..cbe16704a8e 100644
--- a/tests/ui/process/process-envs.rs
+++ b/tests/ui/process/process-envs.rs
@@ -2,6 +2,10 @@
 //@ needs-subprocess
 //@ ignore-vxworks no 'env'
 //@ ignore-fuchsia no 'env'
+//@ ignore-ios no 'env'
+//@ ignore-tvos no 'env'
+//@ ignore-watchos no 'env'
+//@ ignore-visionos no 'env'
 
 use std::process::Command;
 use std::env;
diff --git a/tests/ui/process/process-panic-after-fork.rs b/tests/ui/process/process-panic-after-fork.rs
index 6e0267e0a54..653ff6ce314 100644
--- a/tests/ui/process/process-panic-after-fork.rs
+++ b/tests/ui/process/process-panic-after-fork.rs
@@ -3,6 +3,8 @@
 //@ only-unix
 //@ needs-subprocess
 //@ ignore-fuchsia no fork
+//@ ignore-tvos fork is prohibited
+//@ ignore-watchos fork is prohibited
 
 #![feature(rustc_private)]
 #![feature(never_type)]
diff --git a/tests/ui/process/process-remove-from-env.rs b/tests/ui/process/process-remove-from-env.rs
index c1a2b2daf5b..68c3909b15a 100644
--- a/tests/ui/process/process-remove-from-env.rs
+++ b/tests/ui/process/process-remove-from-env.rs
@@ -2,6 +2,10 @@
 //@ needs-subprocess
 //@ ignore-vxworks no 'env'
 //@ ignore-fuchsia no 'env'
+//@ ignore-ios no 'env'
+//@ ignore-tvos no 'env'
+//@ ignore-watchos no 'env'
+//@ ignore-visionos no 'env'
 
 use std::process::Command;
 use std::env;
diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs
index 3ecf271599d..574d79ee1dd 100644
--- a/tests/ui/process/process-sigpipe.rs
+++ b/tests/ui/process/process-sigpipe.rs
@@ -15,6 +15,10 @@
 
 //@ ignore-vxworks no 'sh'
 //@ ignore-fuchsia no 'sh'
+//@ ignore-ios no 'sh'
+//@ ignore-tvos no 'sh'
+//@ ignore-watchos no 'sh'
+//@ ignore-visionos no 'sh'
 //@ needs-threads
 //@ only-unix SIGPIPE is a unix feature
 
diff --git a/tests/ui/process/process-spawn-failure.rs b/tests/ui/process/process-spawn-failure.rs
index 0950b044c97..ac2c34bc783 100644
--- a/tests/ui/process/process-spawn-failure.rs
+++ b/tests/ui/process/process-spawn-failure.rs
@@ -9,6 +9,10 @@
 //@ ignore-vxworks no 'ps'
 //@ ignore-fuchsia no 'ps'
 //@ ignore-nto no 'ps'
+//@ ignore-ios no 'ps'
+//@ ignore-tvos no 'ps'
+//@ ignore-watchos no 'ps'
+//@ ignore-visionos no 'ps'
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/runtime/backtrace-debuginfo.rs b/tests/ui/runtime/backtrace-debuginfo.rs
index 5fb9943d6c3..5e91f22aec0 100644
--- a/tests/ui/runtime/backtrace-debuginfo.rs
+++ b/tests/ui/runtime/backtrace-debuginfo.rs
@@ -11,6 +11,10 @@
 //@ compile-flags:-Cstrip=none
 //@ needs-subprocess
 //@ ignore-fuchsia Backtrace not symbolized, trace different line alignment
+//@ ignore-ios needs the `.dSYM` files to be moved to the device
+//@ ignore-tvos needs the `.dSYM` files to be moved to the device
+//@ ignore-watchos needs the `.dSYM` files to be moved to the device
+//@ ignore-visionos needs the `.dSYM` files to be moved to the device
 
 // FIXME(#117097): backtrace (possibly unwinding mechanism) seems to be different on at least
 // `i686-mingw` (32-bit windows-gnu)? cc #128911.
diff --git a/tests/ui/runtime/on-broken-pipe/child-processes.rs b/tests/ui/runtime/on-broken-pipe/child-processes.rs
index c0c8ad4e2f5..b7022e1b09d 100644
--- a/tests/ui/runtime/on-broken-pipe/child-processes.rs
+++ b/tests/ui/runtime/on-broken-pipe/child-processes.rs
@@ -1,5 +1,6 @@
 //@ revisions: default error kill inherit
 //@ ignore-cross-compile because aux-bin does not yet support it
+//@ ignore-remote because aux-bin does not yet support it
 //@ only-unix because SIGPIPE is a unix thing
 //@ ignore-backends: gcc
 //@ run-pass
diff --git a/tests/ui/runtime/on-broken-pipe/inherit.rs b/tests/ui/runtime/on-broken-pipe/inherit.rs
index f3c8140eaae..e99c7c7a0fe 100644
--- a/tests/ui/runtime/on-broken-pipe/inherit.rs
+++ b/tests/ui/runtime/on-broken-pipe/inherit.rs
@@ -1,4 +1,5 @@
 //@ ignore-cross-compile because aux-bin does not yet support it
+//@ ignore-remote because aux-bin does not yet support it
 //@ only-unix because SIGPIPE is a unix thing
 //@ aux-bin: assert-inherit-sig_dfl.rs
 //@ aux-bin: assert-inherit-sig_ign.rs