Skip to content

Commit

Permalink
Rollup merge of rust-lang#111384 - bmisiak:issue-106021-fix, r=petroc…
Browse files Browse the repository at this point in the history
…henkov

Fix linking Mac Catalyst by including LC_BUILD_VERSION in object files

Hello. My first rustc PR!

Issue rust-lang#106021 prevents Rust code from being linked into Mac Catalyst applications. Apple's LD has started requiring object files to contain version information about the platform they were built for, such as:
* the "deployment target" (minimum supported OS version),
* the SDK version
* the type of the platform (macOS/iOS/catalyst/tvOS/watchOS all have a different number).

This is currently only enforced when building for Mac Catalyst.

Rust uses the `object` crate which added support for including this information starting with `0.31.0`. ~~I upgraded it along with `thorin-dwp` so that everything depends on 0.31.
Apparently 0.31 [pulls in](gimli-rs/object#463) `ruzstd` due to a [new ELF standard](https://maskray.me/blog/2022-09-09-zstd-compressed-debug-sections) because its `compression` feature is enabled by thorin. If you find this objectionable, let me know what the best way to avoid pulling in those dependencies might be.~~

**(`object` upgraded in rust-lang#111413

I then added two commits:
* The first one adds very basic, hard-coded support for calling `set_macho_build_version` for `-macabi` (Catalyst) targets, where it claims deployment target of Catalyst 14.0 and SDK of 16.2.
* The second weaves the versioning through `rust_target::spec::TargetOptions`, so that we can stick to specifying all target-related info in one place.

Kudos to ``@ara4n`` for writing [this gist](https://gist.github.com/ara4n/320a53ea768aba51afad4c9ed2168536).
  • Loading branch information
matthiaskrgr committed May 26, 2023
2 parents c86212f + a61f026 commit 42c7b8a
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
32 changes: 32 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
};

let mut file = write::Object::new(binary_format, architecture, endianness);
if sess.target.is_like_osx {
if let Some(build_version) = macho_object_build_version_for_target(&sess.target) {
file.set_macho_build_version(build_version)
}
}
let e_flags = match architecture {
Architecture::Mips => {
let arch = match sess.target.options.cpu.as_ref() {
Expand Down Expand Up @@ -258,6 +263,33 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
Some(file)
}

/// Apple's LD, when linking for Mac Catalyst, requires object files to
/// contain information about what they were built for (LC_BUILD_VERSION):
/// the platform (macOS/watchOS etc), minimum OS version, and SDK version.
/// This returns a `MachOBuildVersion` if necessary for the target.
fn macho_object_build_version_for_target(
target: &Target,
) -> Option<object::write::MachOBuildVersion> {
if !target.llvm_target.ends_with("-macabi") {
return None;
}
/// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz"
/// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200
fn pack_version((major, minor): (u32, u32)) -> u32 {
(major << 16) | (minor << 8)
}

let platform = object::macho::PLATFORM_MACCATALYST;
let min_os = (14, 0);
let sdk = (16, 2);

let mut build_version = object::write::MachOBuildVersion::default();
build_version.platform = platform;
build_version.minos = pack_version(min_os);
build_version.sdk = pack_version(sdk);
Some(build_version)
}

pub enum MetadataPosition {
First,
Last,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::apple_base::{opts, Arch};
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};

pub fn target() -> Target {
let llvm_target = "arm64-apple-ios-macabi";
let llvm_target = "arm64-apple-ios14.0-macabi";

let arch = Arch::Arm64_macabi;
let mut base = opts("ios", arch);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::apple_base::{opts, Arch};
use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};

pub fn target() -> Target {
let llvm_target = "x86_64-apple-ios-macabi";
let llvm_target = "x86_64-apple-ios14.0-macabi";

let arch = Arch::X86_64_macabi;
let mut base = opts("ios", arch);
Expand Down

0 comments on commit 42c7b8a

Please sign in to comment.