Skip to content

Commit 8964c48

Browse files
committed
Add run-make test to check the SDK version(s) that rustc produces
1 parent 0bebedd commit 8964c48

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}
+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
//! Test codegen when setting SDK version on Apple platforms.
2+
//!
3+
//! This is important since its a compatibility hazard. The linker will
4+
//! generate load commands differently based on what minimum OS it can assume.
5+
//!
6+
//! See https://github.com/rust-lang/rust/issues/129432.
7+
8+
//@ only-apple
9+
10+
use run_make_support::{apple_os, cmd, run_in_tmpdir, rustc, target};
11+
12+
/// Run vtool to check the `sdk` field in LC_BUILD_VERSION.
13+
///
14+
/// On lower deployment targets, LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS and similar
15+
/// are used instead of LC_BUILD_VERSION, but both name the relevant variable `sdk`.
16+
#[track_caller]
17+
fn has_sdk_version(file: &str, version: &str) {
18+
cmd("vtool")
19+
.arg("-show-build")
20+
.arg(file)
21+
.run()
22+
.assert_stdout_contains(format!("sdk {version}"));
23+
}
24+
25+
fn main() {
26+
// Fetch rustc's inferred deployment target.
27+
let current_deployment_target =
28+
rustc().target(target()).print("deployment-target").run().stdout_utf8();
29+
let current_deployment_target =
30+
current_deployment_target.strip_prefix("deployment_target=").unwrap().trim();
31+
32+
// Fetch current SDK version via. xcrun.
33+
//
34+
// Assumes a standard Xcode distribution, where e.g. the macOS SDK's Mac Catalyst
35+
// and the iPhone Simulator version is the same as for the iPhone SDK.
36+
let sdk_name = match apple_os() {
37+
"macos" => "macosx",
38+
"ios" => "iphoneos",
39+
"watchos" => "watchos",
40+
"tvos" => "appletvos",
41+
"visionos" => "xros",
42+
_ => unreachable!(),
43+
};
44+
let current_sdk_version =
45+
cmd("xcrun").arg("--show-sdk-version").arg("--sdk").arg(sdk_name).run().stdout_utf8();
46+
let current_sdk_version = current_sdk_version.trim();
47+
48+
// Check the SDK version in the object file produced by the codegen backend.
49+
rustc().target(target()).crate_type("lib").emit("obj").input("foo.rs").output("foo.o").run();
50+
// Set to 0, which means not set or "n/a".
51+
has_sdk_version("foo.o", "n/a");
52+
53+
// Test that version makes it to the linker.
54+
for (crate_type, file_ext) in [("bin", ""), ("dylib", ".dylib")] {
55+
// Non-simulator watchOS targets don't support dynamic linking,
56+
// for simplicity we disable the test on all watchOS targets.
57+
if crate_type == "dylib" && apple_os() == "watchos" {
58+
continue;
59+
}
60+
61+
// Test with clang
62+
let file_name = format!("foo_cc{file_ext}");
63+
rustc()
64+
.target(target())
65+
.crate_type("bin")
66+
.arg("-Clinker-flavor=gcc")
67+
.input("foo.rs")
68+
.output(&file_name)
69+
.run();
70+
has_sdk_version(&file_name, current_sdk_version);
71+
72+
// Test with ld64
73+
let file_name = format!("foo_ld{file_ext}");
74+
rustc()
75+
.target(target())
76+
.crate_type("bin")
77+
.arg("-Clinker-flavor=ld")
78+
.input("foo.rs")
79+
.output(&file_name)
80+
.run();
81+
// FIXME(madsmtm): This uses the current deployment target
82+
// instead of the current SDK version like Clang does.
83+
// https://github.com/rust-lang/rust/issues/129432
84+
has_sdk_version(&file_name, current_deployment_target);
85+
}
86+
}

0 commit comments

Comments
 (0)