Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
62 changes: 61 additions & 1 deletion src/librustc_target/spec/apple_base.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::env;
use std::{env, path::Path};

use crate::spec::{LinkArgs, TargetOptions};

Expand Down Expand Up @@ -51,3 +51,63 @@ pub fn macos_llvm_target(arch: &str) -> String {
let (major, minor) = macos_deployment_target();
format!("{}-apple-macosx{}.{}.0", arch, major, minor)
}

#[cfg(target_os = "macos")]
pub fn sysroot(sdk: &str) -> Result<Option<String>, String> {
// Like Clang, allow the `SDKROOT` environment variable used by Xcode to define the sysroot.
if let Some(sdk_root) = env::var("SDKROOT").ok() {
let actual_sdk_path = sdk_path(sdk)?;
let sdk_root_p = Path::new(&sdk_root);
// Ignore `SDKROOT` if it's not a valid path.
if !sdk_root_p.is_absolute() || sdk_root_p == Path::new("/") || !sdk_root_p.exists() {
return Ok(Some(actual_sdk_path));
}
// Ignore `SDKROOT` if it's clearly set for the wrong platform, which may occur when we're
// compiling a custom build script while targeting iOS for example.
return Ok(Some(match sdk {
"iphoneos" if sdk_root.contains("iPhoneSimulator.platform")
|| sdk_root.contains("MacOSX.platform") => actual_sdk_path,
"iphonesimulator" if sdk_root.contains("iPhoneOS.platform")
|| sdk_root.contains("MacOSX.platform") => actual_sdk_path,
"macosx" | "macosx10.15" if sdk_root.contains("iPhoneOS.platform")
|| sdk_root.contains("iPhoneSimulator.platform") => actual_sdk_path,
_ => sdk_root,
}))
}
Ok(None)
}

// `xcrun` is only available on macOS.
#[cfg(not(target_os = "macos"))]
pub fn sysroot(_sdk: &str) -> Result<Option<String>, String> {
if let Some(sdk_root) = env::var("SDKROOT").ok() {
let sdk_root_p = Path::new(&sdk_root);
// Use `SDKROOT` only if it's a valid path.
if sdk_root_p.is_absolute() && sdk_root_p != Path::new("/") && sdk_root_p.exists() {
return Ok(Some(sdk_root));
}
}
Ok(None)
}

#[cfg(target_os = "macos")]
fn sdk_path(sdk_name: &str) -> Result<String, String> {
let res = std::process::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(std::io::Error::new(std::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)),
}
}
61 changes: 12 additions & 49 deletions src/librustc_target/spec/apple_ios_base.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
use std::env;
use std::io;
use std::path::Path;
use std::process::Command;
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};

use Arch::*;
Expand Down Expand Up @@ -30,42 +26,6 @@ impl Arch {
}
}

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 Some(sdkroot) = env::var("SDKROOT").ok() {
let sdkroot_path = Path::new(&sdkroot);
if sdkroot_path.is_absolute() && sdkroot_path != Path::new("/") && sdkroot_path.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) -> Result<LinkArgs, String> {
let sdk_name = match arch {
Armv7 | Armv7s | Arm64 => "iphoneos",
Expand All @@ -75,16 +35,19 @@ fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {

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]);
args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), arch_name.to_string()]);
if let Some(sdk_root) = super::apple_base::sysroot(sdk_name)? {
args.insert(
LinkerFlavor::Gcc,
vec![
"-isysroot".to_string(),
sdk_root.clone(),
"-Wl,-syslibroot".to_string(),
sdk_root
],
);
}

Ok(args)
}
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_target/spec/i686_apple_darwin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ pub fn target() -> TargetResult {
base.cpu = "yonah".to_string();
base.max_atomic_width = Some(64);
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
if let Some(sysroot) = super::apple_base::sysroot("macosx")? {
base.pre_link_args.insert(
LinkerFlavor::Gcc,
vec!["-isysroot".to_string(), sysroot.clone(), "-Wl,-syslibroot".to_string(), sysroot],
);
}
base.stack_probes = true;
base.eliminate_frame_pointer = false;

Expand Down
6 changes: 6 additions & 0 deletions src/librustc_target/spec/x86_64_apple_darwin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ pub fn target() -> TargetResult {
base.max_atomic_width = Some(128); // core2 support cmpxchg16b
base.eliminate_frame_pointer = false;
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
if let Some(sysroot) = super::apple_base::sysroot("macosx")? {
base.pre_link_args.insert(
LinkerFlavor::Gcc,
vec!["-isysroot".to_string(), sysroot.clone(), "-Wl,-syslibroot".to_string(), sysroot],
);
}
base.stack_probes = true;

// Clang automatically chooses a more specific target based on
Expand Down