about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2024-09-09 00:17:49 -0700
committerGitHub <noreply@github.com>2024-09-09 00:17:49 -0700
commitfd938c74418d2c37f4ecc5cd15076ed1354768f9 (patch)
tree9f91d715882c32fada64d3fcf87671256a917f7e
parent97d62ac2e1a6ca6e73b66498e020554ade0deeaa (diff)
parentc788dcc674c3067461e1dcfc33a52fe73bd409ba (diff)
downloadrust-fd938c74418d2c37f4ecc5cd15076ed1354768f9.tar.gz
rust-fd938c74418d2c37f4ecc5cd15076ed1354768f9.zip
Rollup merge of #130068 - madsmtm:deployment-target-test, r=jieyouxu
Test codegen when setting deployment target

Test our codegen in different scenarios when setting the deployment target. There are many places here where this is still incorrect, these will be fixed in https://github.com/rust-lang/rust/pull/129342, https://github.com/rust-lang/rust/pull/129367 and https://github.com/rust-lang/rust/pull/129369. See https://github.com/rust-lang/rust/issues/129432 for the bigger picture.

Tested locally using:
```console
./x test tests/run-make/apple-deployment-target --target="aarch64-apple-darwin,aarch64-apple-ios,aarch64-apple-ios-macabi,aarch64-apple-ios-sim,aarch64-apple-tvos,aarch64-apple-tvos-sim,aarch64-apple-visionos,aarch64-apple-visionos-sim,aarch64-apple-watchos,aarch64-apple-watchos-sim,arm64_32-apple-watchos,armv7s-apple-ios,i386-apple-ios,x86_64-apple-darwin,x86_64-apple-ios,x86_64-apple-ios-macabi,x86_64-apple-tvos,x86_64-apple-watchos-sim,x86_64h-apple-darwin"
```

The only Apple targets that aren't tested by the above command are:
- `arm64e-apple-darwin`, failed to build, see https://github.com/rust-lang/cc-rs/issues/1205.
- `armv7k-apple-watchos`, failed to link, see https://github.com/rust-lang/rust/issues/130071.
- `arm64e-apple-ios`, failed to link, see https://github.com/rust-lang/rust/issues/130085.
- `i686-apple-darwin`, requires a bit of setup and an older machine, see [the docs](https://doc.rust-lang.org/nightly/rustc/platform-support/i686-apple-darwin.html).
- `i386-apple-ios` requires you to set `IPHONEOS_DEPLOYMENT_TARGET=10.0` for the test helpers to work, will be fixed by https://github.com/rust-lang/cc-rs/issues/1030.

But all of this is as it was before this PR.

Fixes https://github.com/rust-lang/rust/issues/47825, since we now have a test that compiles a `dylib` for `aarch64-apple-ios`.

Split out from https://github.com/rust-lang/rust/pull/129342, see that for a little bit of the review that this has gone through already.

r? petrochenkov

```@rustbot``` label O-apple
-rw-r--r--src/tools/run-make-support/src/lib.rs2
-rw-r--r--src/tools/run-make-support/src/targets.rs18
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt1
-rw-r--r--tests/run-make/apple-deployment-target/foo.rs1
-rw-r--r--tests/run-make/apple-deployment-target/rmake.rs157
-rw-r--r--tests/run-make/macos-deployment-target/Makefile21
-rw-r--r--tests/run-make/macos-deployment-target/with_deployment_target.rs4
7 files changed, 177 insertions, 27 deletions
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index fefafb95b33..980bd37dca8 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -73,7 +73,7 @@ pub use env::{env_var, env_var_os, set_current_dir};
 pub use run::{cmd, run, run_fail, run_with_args};
 
 /// Helpers for checking target information.
-pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname};
+pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname, apple_os};
 
 /// Helpers for building names of output artifacts that are potentially target-specific.
 pub use artifact_names::{
diff --git a/src/tools/run-make-support/src/targets.rs b/src/tools/run-make-support/src/targets.rs
index 5dcb0b83430..896abb73fc1 100644
--- a/src/tools/run-make-support/src/targets.rs
+++ b/src/tools/run-make-support/src/targets.rs
@@ -28,6 +28,24 @@ pub fn is_darwin() -> bool {
     target().contains("darwin")
 }
 
+/// Get the target OS on Apple operating systems.
+#[must_use]
+pub fn apple_os() -> &'static str {
+    if target().contains("darwin") {
+        "macos"
+    } else if target().contains("ios") {
+        "ios"
+    } else if target().contains("tvos") {
+        "tvos"
+    } else if target().contains("watchos") {
+        "watchos"
+    } else if target().contains("visionos") {
+        "visionos"
+    } else {
+        panic!("not an Apple OS")
+    }
+}
+
 /// Check if `component` is within `LLVM_COMPONENTS`
 #[must_use]
 pub fn llvm_components_contain(component: &str) -> bool {
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
index 22d1e93bf39..50d21c7ed4c 100644
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt
@@ -6,7 +6,6 @@ run-make/incr-add-rust-src-component/Makefile
 run-make/issue-84395-lto-embed-bitcode/Makefile
 run-make/jobserver-error/Makefile
 run-make/libs-through-symlinks/Makefile
-run-make/macos-deployment-target/Makefile
 run-make/split-debuginfo/Makefile
 run-make/symbol-mangling-hashed/Makefile
 run-make/translation/Makefile
diff --git a/tests/run-make/apple-deployment-target/foo.rs b/tests/run-make/apple-deployment-target/foo.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make/apple-deployment-target/foo.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make/apple-deployment-target/rmake.rs b/tests/run-make/apple-deployment-target/rmake.rs
new file mode 100644
index 00000000000..b2d1af65177
--- /dev/null
+++ b/tests/run-make/apple-deployment-target/rmake.rs
@@ -0,0 +1,157 @@
+//! Test codegen when setting deployment targets on Apple platforms.
+//!
+//! This is important since its a compatibility hazard. The linker will
+//! generate load commands differently based on what minimum OS it can assume.
+//!
+//! See https://github.com/rust-lang/rust/pull/105123.
+
+//@ only-apple
+
+use run_make_support::{apple_os, cmd, run_in_tmpdir, rustc, target};
+
+/// Run vtool to check the `minos` field in LC_BUILD_VERSION.
+///
+/// On lower deployment targets, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS and similar
+/// are used instead of LC_BUILD_VERSION - these have a `version` field, so also check that.
+#[track_caller]
+fn minos(file: &str, version: &str) {
+    cmd("vtool")
+        .arg("-show-build")
+        .arg(file)
+        .run()
+        .assert_stdout_contains_regex(format!("(minos|version) {version}"));
+}
+
+fn main() {
+    // These versions should generally be higher than the default versions
+    let (env_var, example_version, higher_example_version) = match apple_os() {
+        "macos" => ("MACOSX_DEPLOYMENT_TARGET", "12.0", "13.0"),
+        // armv7s-apple-ios and i386-apple-ios only supports iOS 10.0
+        "ios" if target() == "armv7s-apple-ios" || target() == "i386-apple-ios" => {
+            ("IPHONEOS_DEPLOYMENT_TARGET", "10.0", "10.0")
+        }
+        "ios" => ("IPHONEOS_DEPLOYMENT_TARGET", "15.0", "16.0"),
+        "watchos" => ("WATCHOS_DEPLOYMENT_TARGET", "7.0", "9.0"),
+        "tvos" => ("TVOS_DEPLOYMENT_TARGET", "14.0", "15.0"),
+        "visionos" => ("XROS_DEPLOYMENT_TARGET", "1.1", "1.2"),
+        _ => unreachable!(),
+    };
+    let default_version =
+        rustc().target(target()).env_remove(env_var).print("deployment-target").run().stdout_utf8();
+    let default_version = default_version.strip_prefix("deployment_target=").unwrap().trim();
+
+    // Test that version makes it to the object file.
+    run_in_tmpdir(|| {
+        let rustc = || {
+            let mut rustc = rustc();
+            rustc.target(target());
+            rustc.crate_type("lib");
+            rustc.emit("obj");
+            rustc.input("foo.rs");
+            rustc.output("foo.o");
+            rustc
+        };
+
+        rustc().env(env_var, example_version).run();
+        minos("foo.o", example_version);
+
+        // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator.
+        if !target().contains("macabi") && !target().contains("sim") {
+            rustc().env_remove(env_var).run();
+            minos("foo.o", default_version);
+        }
+    });
+
+    // Test that version makes it to the linker when linking dylibs.
+    run_in_tmpdir(|| {
+        // Certain watchOS targets don't support dynamic linking, so we disable the test on those.
+        if apple_os() == "watchos" {
+            return;
+        }
+
+        let rustc = || {
+            let mut rustc = rustc();
+            rustc.target(target());
+            rustc.crate_type("dylib");
+            rustc.input("foo.rs");
+            rustc.output("libfoo.dylib");
+            rustc
+        };
+
+        rustc().env(env_var, example_version).run();
+        minos("libfoo.dylib", example_version);
+
+        // FIXME(madsmtm): Deployment target is not currently passed properly to linker
+        // rustc().env_remove(env_var).run();
+        // minos("libfoo.dylib", default_version);
+
+        // Test with ld64 instead
+
+        rustc().arg("-Clinker-flavor=ld").env(env_var, example_version).run();
+        minos("libfoo.dylib", example_version);
+
+        rustc().arg("-Clinker-flavor=ld").env_remove(env_var).run();
+        minos("libfoo.dylib", default_version);
+    });
+
+    // Test that version makes it to the linker when linking executables.
+    run_in_tmpdir(|| {
+        let rustc = || {
+            let mut rustc = rustc();
+            rustc.target(target());
+            rustc.crate_type("bin");
+            rustc.input("foo.rs");
+            rustc.output("foo");
+            rustc
+        };
+
+        // FIXME(madsmtm): Doesn't work on watchOS for some reason?
+        if !target().contains("watchos") {
+            rustc().env(env_var, example_version).run();
+            minos("foo", example_version);
+
+            // FIXME(madsmtm): Deployment target is not currently passed properly to linker
+            // rustc().env_remove(env_var).run();
+            // minos("foo", default_version);
+        }
+
+        // Test with ld64 instead
+
+        rustc().arg("-Clinker-flavor=ld").env(env_var, example_version).run();
+        minos("foo", example_version);
+
+        rustc().arg("-Clinker-flavor=ld").env_remove(env_var).run();
+        minos("foo", default_version);
+    });
+
+    // Test that changing the deployment target busts the incremental cache.
+    run_in_tmpdir(|| {
+        let rustc = || {
+            let mut rustc = rustc();
+            rustc.target(target());
+            rustc.incremental("incremental");
+            rustc.crate_type("lib");
+            rustc.emit("obj");
+            rustc.input("foo.rs");
+            rustc.output("foo.o");
+            rustc
+        };
+
+        // FIXME(madsmtm): Incremental cache is not yet busted
+        // https://github.com/rust-lang/rust/issues/118204
+        let higher_example_version = example_version;
+        let default_version = example_version;
+
+        rustc().env(env_var, example_version).run();
+        minos("foo.o", example_version);
+
+        rustc().env(env_var, higher_example_version).run();
+        minos("foo.o", higher_example_version);
+
+        // FIXME(madsmtm): Doesn't work on Mac Catalyst and the simulator.
+        if !target().contains("macabi") && !target().contains("sim") {
+            rustc().env_remove(env_var).run();
+            minos("foo.o", default_version);
+        }
+    });
+}
diff --git a/tests/run-make/macos-deployment-target/Makefile b/tests/run-make/macos-deployment-target/Makefile
deleted file mode 100644
index 757ca699535..00000000000
--- a/tests/run-make/macos-deployment-target/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-# only-macos
-#
-# Check that a set deployment target actually makes it to the linker.
-# This is important since its a compatibility hazard. The linker will
-# generate load commands differently based on what minimum OS it can assume.
-
-include ../tools.mk
-
-ifeq ($(strip $(shell uname -m)),arm64)
-	GREP_PATTERN = "minos 11.0"
-else
- 	GREP_PATTERN = "version 10.13"
-endif
-
-OUT_FILE=$(TMPDIR)/with_deployment_target.dylib
-all:
-	env MACOSX_DEPLOYMENT_TARGET=10.13 $(RUSTC) with_deployment_target.rs -o $(OUT_FILE)
-# XXX: The check is for either the x86_64 minimum OR the aarch64 minimum (M1 starts at macOS 11).
-# They also use different load commands, so we let that change with each too. The aarch64 check
-# isn't as robust as the x86 one, but testing both seems unneeded.
-	vtool -show-build $(OUT_FILE) | $(CGREP) -e $(GREP_PATTERN)
diff --git a/tests/run-make/macos-deployment-target/with_deployment_target.rs b/tests/run-make/macos-deployment-target/with_deployment_target.rs
deleted file mode 100644
index 342fe0ecbcf..00000000000
--- a/tests/run-make/macos-deployment-target/with_deployment_target.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#![crate_type = "cdylib"]
-
-#[allow(dead_code)]
-fn something_and_nothing() {}