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
This commit is contained in:
Jubilee 2024-09-09 00:17:49 -07:00 committed by GitHub
commit fd938c7441
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 177 additions and 27 deletions

View File

@ -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::{

View File

@ -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 {

View File

@ -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

View File

@ -0,0 +1 @@
fn main() {}

View File

@ -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);
}
});
}

View File

@ -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)

View File

@ -1,4 +0,0 @@
#![crate_type = "cdylib"]
#[allow(dead_code)]
fn something_and_nothing() {}