Skip to content

Fix sysroot on macOS when cross-compiling and SDKROOT is set #64254

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

Merged
merged 6 commits into from Sep 13, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
45 changes: 44 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, io, path::Path, process::Command};

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

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

pub fn sysroot(sdk: &str) -> Result<String, String> {
let actual_sdk_path = sdk_path(sdk)?;
// Like Clang, allow the SDKROOT environment variable used by Xcode to define the sysroot
if let Some(sdk_root) = env::var("SDKROOT").ok() {
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);
}
// 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
match sdk {
"iphoneos" if sdk_root.contains("iPhoneSimulator.platform")
|| sdk_root.contains("MacOSX.platform") => return Ok(actual_sdk_path),
"iphonesimulator" if sdk_root.contains("iPhoneOS.platform")
|| sdk_root.contains("MacOSX.platform") => return Ok(actual_sdk_path),
"macosx" | "macosx10.15" if sdk_root.contains("iPhoneOS.platform")
|| sdk_root.contains("iPhoneSimulator.platform") => return Ok(actual_sdk_path),
_ => return Ok(sdk_root),
}
}
Ok(actual_sdk_path)
}

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[..]))
}
},
);
match res {
Ok(output) => Ok(output.trim().to_string()),
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
}
}
42 changes: 1 addition & 41 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,7 +35,7 @@ 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 sdk_root = super::apple_base::sysroot(sdk_name)?;

let mut args = LinkArgs::new();
args.insert(LinkerFlavor::Gcc,
Expand Down
12 changes: 11 additions & 1 deletion src/librustc_target/spec/i686_apple_darwin.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
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()]);
base.pre_link_args.insert(
LinkerFlavor::Gcc,
vec![
"-m32".to_string(),
"-isysroot".to_string(),
sysroot.clone(),
"-Wl,-syslibroot".to_string(),
sysroot,
],
);
base.stack_probes = true;
base.eliminate_frame_pointer = false;

Expand Down
12 changes: 11 additions & 1 deletion src/librustc_target/spec/x86_64_apple_darwin.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
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()]);
base.pre_link_args.insert(
LinkerFlavor::Gcc,
vec![
"-m64".to_string(),
"-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