Fix cross-compilation to macOS

This commit is contained in:
Aleksi Juvani 2019-09-07 21:02:27 +03:00
parent 6dc763eed5
commit 995d9857bd
4 changed files with 62 additions and 50 deletions

View File

@ -1,4 +1,4 @@
use std::{env, io, path::Path, process::Command};
use std::{env, path::Path};
use crate::spec::{LinkArgs, TargetOptions};
@ -52,18 +52,19 @@ pub fn macos_llvm_target(arch: &str) -> String {
format!("{}-apple-macosx{}.{}.0", arch, major, minor)
}
pub fn sysroot(sdk: &str) -> Result<String, String> {
let actual_sdk_path = sdk_path(sdk)?;
#[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(actual_sdk_path);
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(match sdk {
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")
@ -71,24 +72,40 @@ pub fn sysroot(sdk: &str) -> Result<String, String> {
"macosx" | "macosx10.15" if sdk_root.contains("iPhoneOS.platform")
|| sdk_root.contains("iPhoneSimulator.platform") => actual_sdk_path,
_ => sdk_root,
})
}))
}
Ok(actual_sdk_path)
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 =
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[..]))
}
},
);
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)),

View File

@ -35,16 +35,19 @@ fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
let arch_name = arch.to_string();
let sdk_root = super::apple_base::sysroot(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)
}

View File

@ -1,20 +1,16 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
let sysroot = super::apple_base::sysroot("macosx")?;
let mut base = super::apple_base::opts();
base.cpu = "yonah".to_string();
base.max_atomic_width = Some(64);
base.pre_link_args.insert(
LinkerFlavor::Gcc,
vec![
"-m32".to_string(),
"-isysroot".to_string(),
sysroot.clone(),
"-Wl,-syslibroot".to_string(),
sysroot,
],
);
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;

View File

@ -1,21 +1,17 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
pub fn target() -> TargetResult {
let sysroot = super::apple_base::sysroot("macosx")?;
let mut base = super::apple_base::opts();
base.cpu = "core2".to_string();
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(),
"-isysroot".to_string(),
sysroot.clone(),
"-Wl,-syslibroot".to_string(),
sysroot,
],
);
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