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

Defer Apple SDKROOT detection to link time. #77202

Merged
merged 3 commits into from
Oct 1, 2020
Merged
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
86 changes: 86 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1524,6 +1524,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
// NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
add_pre_link_args(cmd, sess, flavor);

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

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

Expand Down Expand Up @@ -2083,3 +2086,86 @@ fn are_upstream_rust_objects_already_included(sess: &Session) -> bool {
config::Lto::No | config::Lto::ThinLocal => false,
}
}

fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
let arch = &sess.target.target.arch;
let os = &sess.target.target.target_os;
let llvm_target = &sess.target.target.llvm_target;
if sess.target.target.target_vendor != "apple"
|| !matches!(os.as_str(), "ios" | "tvos")
|| flavor != LinkerFlavor::Gcc
{
return;
}
let sdk_name = match (arch.as_str(), os.as_str()) {
("aarch64", "tvos") => "appletvos",
("x86_64", "tvos") => "appletvsimulator",
("arm", "ios") => "iphoneos",
("aarch64", "ios") => "iphoneos",
("x86", "ios") => "iphonesimulator",
("x86_64", "ios") if llvm_target.contains("macabi") => "macosx10.15",
("x86_64", "ios") => "iphonesimulator",
_ => {
sess.err(&format!("unsupported arch `{}` for os `{}`", arch, os));
return;
}
};
let sdk_root = match get_apple_sdk_root(sdk_name) {
Ok(s) => s,
Err(e) => {
sess.err(&e);
return;
}
};
let arch_name = llvm_target.split('-').next().expect("LLVM target must have a hyphen");
cmd.args(&["-arch", arch_name, "-isysroot", &sdk_root, "-Wl,-syslibroot", &sdk_root]);
}

fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> {
// Following what clang does
// (https://github.com/llvm/llvm-project/blob/
// 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
// to allow the SDK path to be set. (For clang, xcrun sets
// SDKROOT; for rustc, the user or build system can set it, or we
// can fall back to checking for xcrun on PATH.)
if let Ok(sdkroot) = env::var("SDKROOT") {
let p = Path::new(&sdkroot);
match sdk_name {
// Ignore `SDKROOT` if it's clearly set for the wrong platform.
"appletvos"
if sdkroot.contains("TVSimulator.platform")
|| sdkroot.contains("MacOSX.platform") => {}
"appletvsimulator"
if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {}
"iphoneos"
if sdkroot.contains("iPhoneSimulator.platform")
|| sdkroot.contains("MacOSX.platform") => {}
"iphonesimulator"
if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => {
}
"macosx10.15"
if sdkroot.contains("iPhoneOS.platform")
|| sdkroot.contains("iPhoneSimulator.platform") => {}
// Ignore `SDKROOT` if it's not a valid path.
_ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
_ => return Ok(sdkroot),
}
}
let res =
Command::new("xcrun").arg("--show-sdk-path").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 path: {}", sdk_name, e)),
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/spec/aarch64_apple_ios.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::apple_sdk_base::{opts, AppleOS, Arch};
use super::apple_sdk_base::{opts, Arch};
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
let base = opts(Arch::Arm64, AppleOS::iOS)?;
let base = opts(Arch::Arm64);
Ok(Target {
llvm_target: "arm64-apple-ios".to_string(),
target_endian: "little".to_string(),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::apple_sdk_base::{opts, AppleOS, Arch};
use super::apple_sdk_base::{opts, Arch};
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
let base = opts(Arch::Arm64, AppleOS::tvOS)?;
let base = opts(Arch::Arm64);
Ok(Target {
llvm_target: "arm64-apple-tvos".to_string(),
target_endian: "little".to_string(),
Expand Down
116 changes: 4 additions & 112 deletions compiler/rustc_target/src/spec/apple_sdk_base.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
use std::env;
use std::io;
use std::path::Path;
use std::process::Command;
use crate::spec::TargetOptions;

use Arch::*;
#[allow(non_camel_case_types)]
Expand All @@ -16,108 +12,6 @@ pub enum Arch {
X86_64_macabi,
}

#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum AppleOS {
tvOS,
iOS,
}

impl Arch {
pub fn to_string(self) -> &'static str {
match self {
Armv7 => "armv7",
Armv7s => "armv7s",
Arm64 => "arm64",
I386 => "i386",
X86_64 => "x86_64",
X86_64_macabi => "x86_64",
}
}
}

pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
// Following what clang does
// (https://github.com/llvm/llvm-project/blob/
// 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
// to allow the SDK path to be set. (For clang, xcrun sets
// SDKROOT; for rustc, the user or build system can set it, or we
// can fall back to checking for xcrun on PATH.)
if let Ok(sdkroot) = env::var("SDKROOT") {
let p = Path::new(&sdkroot);
match sdk_name {
// Ignore `SDKROOT` if it's clearly set for the wrong platform.
"appletvos"
if sdkroot.contains("TVSimulator.platform")
|| sdkroot.contains("MacOSX.platform") => {}
"appletvsimulator"
if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {}
"iphoneos"
if sdkroot.contains("iPhoneSimulator.platform")
|| sdkroot.contains("MacOSX.platform") => {}
"iphonesimulator"
if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => {
}
"macosx10.15"
if sdkroot.contains("iPhoneOS.platform")
|| sdkroot.contains("iPhoneSimulator.platform") => {}
// Ignore `SDKROOT` if it's not a valid path.
_ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
_ => return Ok(sdkroot),
}
}
let res =
Command::new("xcrun").arg("--show-sdk-path").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 path: {}", sdk_name, e)),
}
}

fn build_pre_link_args(arch: Arch, os: AppleOS) -> Result<LinkArgs, String> {
let sdk_name = match (arch, os) {
(Arm64, AppleOS::tvOS) => "appletvos",
(X86_64, AppleOS::tvOS) => "appletvsimulator",
(Armv7, AppleOS::iOS) => "iphoneos",
(Armv7s, AppleOS::iOS) => "iphoneos",
(Arm64, AppleOS::iOS) => "iphoneos",
(I386, AppleOS::iOS) => "iphonesimulator",
(X86_64, AppleOS::iOS) => "iphonesimulator",
(X86_64_macabi, AppleOS::iOS) => "macosx10.15",
_ => unreachable!(),
};

let arch_name = arch.to_string();

let sdk_root = get_sdk_root(sdk_name)?;

let mut args = LinkArgs::new();
args.insert(
LinkerFlavor::Gcc,
vec![
"-arch".to_string(),
arch_name.to_string(),
"-isysroot".to_string(),
sdk_root.clone(),
"-Wl,-syslibroot".to_string(),
sdk_root,
],
);

Ok(args)
}

fn target_cpu(arch: Arch) -> String {
match arch {
Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
Expand All @@ -137,15 +31,13 @@ fn link_env_remove(arch: Arch) -> Vec<String> {
}
}

pub fn opts(arch: Arch, os: AppleOS) -> Result<TargetOptions, String> {
let pre_link_args = build_pre_link_args(arch, os)?;
Ok(TargetOptions {
pub fn opts(arch: Arch) -> TargetOptions {
TargetOptions {
cpu: target_cpu(arch),
executables: true,
pre_link_args,
link_env_remove: link_env_remove(arch),
has_elf_tls: false,
eliminate_frame_pointer: false,
..super::apple_base::opts()
})
}
}
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/spec/armv7_apple_ios.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::apple_sdk_base::{opts, AppleOS, Arch};
use super::apple_sdk_base::{opts, Arch};
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
let base = opts(Arch::Armv7, AppleOS::iOS)?;
let base = opts(Arch::Armv7);
Ok(Target {
llvm_target: "armv7-apple-ios".to_string(),
target_endian: "little".to_string(),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/spec/armv7s_apple_ios.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::apple_sdk_base::{opts, AppleOS, Arch};
use super::apple_sdk_base::{opts, Arch};
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
let base = opts(Arch::Armv7s, AppleOS::iOS)?;
let base = opts(Arch::Armv7s);
Ok(Target {
llvm_target: "armv7s-apple-ios".to_string(),
target_endian: "little".to_string(),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/spec/i386_apple_ios.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::apple_sdk_base::{opts, AppleOS, Arch};
use super::apple_sdk_base::{opts, Arch};
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
let base = opts(Arch::I386, AppleOS::iOS)?;
let base = opts(Arch::I386);
Ok(Target {
llvm_target: "i386-apple-ios".to_string(),
target_endian: "little".to_string(),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/spec/x86_64_apple_ios.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::apple_sdk_base::{opts, AppleOS, Arch};
use super::apple_sdk_base::{opts, Arch};
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
let base = opts(Arch::X86_64, AppleOS::iOS)?;
let base = opts(Arch::X86_64);
Ok(Target {
llvm_target: "x86_64-apple-ios".to_string(),
target_endian: "little".to_string(),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::apple_sdk_base::{opts, AppleOS, Arch};
use super::apple_sdk_base::{opts, Arch};
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
let base = opts(Arch::X86_64_macabi, AppleOS::iOS)?;
let base = opts(Arch::X86_64_macabi);
Ok(Target {
llvm_target: "x86_64-apple-ios13.0-macabi".to_string(),
target_endian: "little".to_string(),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::apple_sdk_base::{opts, AppleOS, Arch};
use super::apple_sdk_base::{opts, Arch};
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};

pub fn target() -> TargetResult {
let base = opts(Arch::X86_64, AppleOS::iOS)?;
let base = opts(Arch::X86_64);
Ok(Target {
llvm_target: "x86_64-apple-tvos".to_string(),
target_endian: "little".to_string(),
Expand Down
17 changes: 8 additions & 9 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Specifically, these platforms are required to have each of the following:

target | std | host | notes
-------|-----|------|-------
`aarch64-apple-ios` | ✓[^apple] | | ARM64 iOS
`aarch64-apple-ios` | ✓ | | ARM64 iOS
`aarch64-fuchsia` | ✓ | | ARM64 Fuchsia
`aarch64-linux-android` | ✓ | | ARM64 Android
`aarch64-pc-windows-msvc` | ✓ | | ARM64 Windows MSVC
Expand Down Expand Up @@ -122,7 +122,7 @@ target | std | host | notes
`wasm32-unknown-emscripten` | ✓ | | WebAssembly via Emscripten
`wasm32-unknown-unknown` | ✓ | | WebAssembly
`wasm32-wasi` | ✓ | | WebAssembly with WASI
`x86_64-apple-ios` | ✓[^apple] | | 64-bit x86 iOS
`x86_64-apple-ios` | ✓ | | 64-bit x86 iOS
`x86_64-fortanix-unknown-sgx` | ✓ | | [Fortanix ABI] for 64-bit Intel SGX
`x86_64-fuchsia` | ✓ | | 64-bit Fuchsia
`x86_64-linux-android` | ✓ | | 64-bit x86 Android
Expand All @@ -146,7 +146,7 @@ not available.
target | std | host | notes
-------|-----|------|-------
`aarch64-apple-darwin` | ? | | ARM64 macOS
`aarch64-apple-tvos` | *[^apple] | | ARM64 tvOS
`aarch64-apple-tvos` | * | | ARM64 tvOS
`aarch64-unknown-cloudabi` | ✓ | | ARM64 CloudABI
`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
`aarch64-unknown-hermit` | ? | |
Expand All @@ -158,16 +158,16 @@ target | std | host | notes
`armv4t-unknown-linux-gnueabi` | ? | |
`armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
`armv6-unknown-netbsd-eabihf` | ? | |
`armv7-apple-ios` | ✓[^apple] | | ARMv7 iOS, Cortex-a8
`armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8
`armv7-unknown-cloudabi-eabihf` | ✓ | | ARMv7 CloudABI, hardfloat
`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
`armv7-unknown-netbsd-eabihf` | ? | |
`armv7-wrs-vxworks-eabihf` | ? | |
`armv7a-none-eabihf` | * | | ARM Cortex-A, hardfloat
`armv7s-apple-ios` | ✓[^apple] | |
`armv7s-apple-ios` | ✓ | |
`avr-unknown-gnu-atmega328` | ✗ | | AVR. Requires `-Z build-std=core`
`hexagon-unknown-linux-musl` | ? | |
`i386-apple-ios` | ✓[^apple] | | 32-bit x86 iOS
`i386-apple-ios` | ✓ | | 32-bit x86 iOS
`i686-apple-darwin` | ✓ | ✓ | 32-bit OSX (10.7+, Lion+)
`i686-pc-windows-msvc` | ✓ | | 32-bit Windows XP support
`i686-unknown-cloudabi` | ✓ | | 32-bit CloudABI
Expand Down Expand Up @@ -203,8 +203,8 @@ target | std | host | notes
`thumbv7a-uwp-windows-msvc` | ✓ | |
`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL
`thumbv4t-none-eabi` | * | | ARMv4T T32
`x86_64-apple-ios-macabi` | ✓[^apple] | | Apple Catalyst
`x86_64-apple-tvos` | *[^apple] | | x86 64-bit tvOS
`x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst
`x86_64-apple-tvos` | * | | x86 64-bit tvOS
`x86_64-linux-kernel` | * | | Linux kernel modules
`x86_64-pc-solaris` | ? | |
`x86_64-pc-windows-msvc` | ✓ | | 64-bit Windows XP support
Expand All @@ -221,4 +221,3 @@ target | std | host | notes
`x86_64-wrs-vxworks` | ? | |

[runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets
[^apple]: These targets are only available on macOS.
2 changes: 0 additions & 2 deletions src/tools/tier-check/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ fn main() {
let doc_targets: HashSet<_> = doc_targets_md
.lines()
.filter(|line| line.starts_with('`') && line.contains('|'))
// These platforms only exist on macos.
.filter(|line| !line.contains("[^apple]") || cfg!(target_os = "macos"))
.map(|line| line.split('`').skip(1).next().expect("expected target code span"))
.collect();

Expand Down