Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve linker detection for ld64.lld for Apple devices #86064

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 78 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,7 @@ fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
LinkerFlavor::Ld
} else if stem == "link" || stem == "lld-link" {
LinkerFlavor::Msvc
} else if stem == "lld" || stem == "rust-lld" {
} else if stem == "lld" || stem == "ld64" || stem == "rust-lld" {
LinkerFlavor::Lld(sess.target.lld_flavor)
} else {
// fall back to the value in the target spec
Expand Down Expand Up @@ -1905,6 +1905,10 @@ fn add_order_independent_options(
) {
add_apple_sdk(cmd, sess, flavor);

// NO-OPT-OUT, OBJECT-FILES-NO
add_apple_platform_version(cmd, sess, flavor);

// NO-OPT-OUT
add_link_script(cmd, sess, tmpdir, crate_type);

if sess.target.is_like_fuchsia && crate_type == CrateType::Executable {
Expand Down Expand Up @@ -2183,7 +2187,11 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(

// Converts a library file-stem into a cc -l argument
fn unlib<'a>(target: &Target, stem: &'a str) -> &'a str {
if stem.starts_with("lib") && !target.is_like_windows { &stem[3..] } else { stem }
if stem.starts_with("lib") && !target.is_like_windows {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change was by rustfmt.

&stem[3..]
} else {
stem
}
}

// Adds the static "rlib" versions of all crates to the command line.
Expand Down Expand Up @@ -2504,3 +2512,71 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> {
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
}
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LLVM linker requires the platform_version option. The Apple linker also supports it.

fn add_apple_platform_version(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
let arch = &sess.target.arch;
let os = &sess.target.os;
let llvm_target = &sess.target.llvm_target;
if sess.target.vendor != "apple" || flavor != LinkerFlavor::Lld(LldFlavor::Ld64) {
return;
}
let sdk_name = match (arch.as_str(), os.as_str()) {
("aarch64", "tvos") => "appletvos",
("x86_64", "tvos") => "appletvsimulator",
("arm", "ios") => "iphoneos",
("aarch64", "ios") if llvm_target.contains("macabi") => "macosx",
("aarch64", "ios") if llvm_target.contains("sim") => "iphonesimulator",
("aarch64", "ios") => "iphoneos",
("x86", "ios") => "iphonesimulator",
("x86_64", "ios") if llvm_target.contains("macabi") => "macosx",
("x86_64", "ios") => "iphonesimulator",
(_, "macos") => "macosx",
_ => {
sess.err(&format!("unsupported arch `{}` for os `{}`", arch, os));
return;
}
};

let sdk_path = match get_apple_sdk_root(sdk_name) {
Ok(s) => s,
Err(e) => {
sess.err(&e);
return;
}
};

let platform_version = match get_apple_platform_version(sdk_name) {
Ok(s) => s,
Err(e) => {
sess.err(&e);
return;
}
};

let path = format!("{}/usr/lib", &sdk_path);
cmd.args(&["-syslibroot", &sdk_path]);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an implementation of -isysroot for ld64.

cmd.args(&["-L", &path]);
cmd.args(&["-platform_version", os, &platform_version, &platform_version]);
}

fn get_apple_platform_version(sdk_name: &str) -> Result<String, String> {
let res = Command::new("xcrun")
.arg("--show-sdk-platform-version")
.arg("-sdk")
.arg(sdk_name)
.output()
.and_then(|output| {
if output.status.success() {
Ok(String::from_utf8(output.stdout).unwrap())
} else {
let error = String::from_utf8(output.stderr);
let error = format!("process exit with error: {}", error.unwrap());
Err(io::Error::new(io::ErrorKind::Other, &error[..]))
}
});

match res {
Ok(output) => Ok(output.trim().to_string()),
Err(e) => Err(format!("failed to get {} SDK platform version: {}", sdk_name, e)),
}
}
4 changes: 3 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ impl<'a> GccLinker<'a> {
fn build_dylib(&mut self, out_filename: &Path) {
// On mac we need to tell the linker to let this library be rpathed
if self.sess.target.is_like_osx {
self.cmd.arg("-dynamiclib");
if self.sess.target.lld_flavor != LldFlavor::Ld64 {
self.cmd.arg("-dynamiclib");
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems be only needed for gcc. -dynamiclib is an gcc option.

}
self.linker_arg("-dylib");

// Note that the `osx_rpath_install_name` option here is a hack
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_target/src/spec/apple_base.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::env;

use crate::spec::{SplitDebuginfo, TargetOptions};
use crate::spec::{LldFlavor, SplitDebuginfo, TargetOptions};

pub fn opts(os: &str) -> TargetOptions {
// ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
Expand Down Expand Up @@ -35,6 +35,7 @@ pub fn opts(os: &str) -> TargetOptions {
abi_return_struct_as_int: true,
emit_debug_gdb_scripts: false,
eh_frame_header: false,
lld_flavor: LldFlavor::Ld64,

// The historical default for macOS targets is to run `dsymutil` which
// generates a packed version of debuginfo split from the main file.
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
use crate::spec::{LinkerFlavor, LldFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};

pub fn target() -> Target {
let mut base = super::apple_base::opts("macos");
Expand All @@ -9,6 +9,10 @@ pub fn target() -> Target {
LinkerFlavor::Gcc,
vec!["-m64".to_string(), "-arch".to_string(), "x86_64".to_string()],
);
base.pre_link_args.insert(
Copy link
Author

@tschuett tschuett Jun 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be needed for other Apple devices, but I have no hardware.

LinkerFlavor::Lld(LldFlavor::Ld64),
vec!["-arch".to_string(), "x86_64".to_string()],
);
base.link_env_remove.extend(super::apple_base::macos_link_env_remove());
// don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
base.stack_probes = StackProbeType::Call;
Expand Down