Skip to content

Commit

Permalink
Add run-make test to check the SDK version(s) that rustc produces
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Sep 29, 2024
1 parent 0bebedd commit 8964c48
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
1 change: 1 addition & 0 deletions tests/run-make/apple-sdk-version/foo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main() {}
86 changes: 86 additions & 0 deletions tests/run-make/apple-sdk-version/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//! Test codegen when setting SDK version 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/issues/129432.

//@ only-apple

use run_make_support::{apple_os, cmd, run_in_tmpdir, rustc, target};

/// Run vtool to check the `sdk` 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, but both name the relevant variable `sdk`.
#[track_caller]
fn has_sdk_version(file: &str, version: &str) {
cmd("vtool")
.arg("-show-build")
.arg(file)
.run()
.assert_stdout_contains(format!("sdk {version}"));
}

fn main() {
// Fetch rustc's inferred deployment target.
let current_deployment_target =
rustc().target(target()).print("deployment-target").run().stdout_utf8();
let current_deployment_target =
current_deployment_target.strip_prefix("deployment_target=").unwrap().trim();

// Fetch current SDK version via. xcrun.
//
// Assumes a standard Xcode distribution, where e.g. the macOS SDK's Mac Catalyst
// and the iPhone Simulator version is the same as for the iPhone SDK.
let sdk_name = match apple_os() {
"macos" => "macosx",
"ios" => "iphoneos",
"watchos" => "watchos",
"tvos" => "appletvos",
"visionos" => "xros",
_ => unreachable!(),
};
let current_sdk_version =
cmd("xcrun").arg("--show-sdk-version").arg("--sdk").arg(sdk_name).run().stdout_utf8();
let current_sdk_version = current_sdk_version.trim();

// Check the SDK version in the object file produced by the codegen backend.
rustc().target(target()).crate_type("lib").emit("obj").input("foo.rs").output("foo.o").run();
// Set to 0, which means not set or "n/a".
has_sdk_version("foo.o", "n/a");

// Test that version makes it to the linker.
for (crate_type, file_ext) in [("bin", ""), ("dylib", ".dylib")] {
// Non-simulator watchOS targets don't support dynamic linking,
// for simplicity we disable the test on all watchOS targets.
if crate_type == "dylib" && apple_os() == "watchos" {
continue;
}

// Test with clang
let file_name = format!("foo_cc{file_ext}");
rustc()
.target(target())
.crate_type("bin")
.arg("-Clinker-flavor=gcc")
.input("foo.rs")
.output(&file_name)
.run();
has_sdk_version(&file_name, current_sdk_version);

// Test with ld64
let file_name = format!("foo_ld{file_ext}");
rustc()
.target(target())
.crate_type("bin")
.arg("-Clinker-flavor=ld")
.input("foo.rs")
.output(&file_name)
.run();
// FIXME(madsmtm): This uses the current deployment target
// instead of the current SDK version like Clang does.
// https://github.com/rust-lang/rust/issues/129432
has_sdk_version(&file_name, current_deployment_target);
}
}

0 comments on commit 8964c48

Please sign in to comment.