Skip to content

Commit 691f645

Browse files
committed
Fix sysroot on macOS when cross-compiling and SDKROOT is set
Fixes rust-lang/cargo#7283 Closes rust-lang/cargo#7284 r? @alexcrichton
1 parent da13f06 commit 691f645

File tree

4 files changed

+67
-44
lines changed

4 files changed

+67
-44
lines changed

src/librustc_target/spec/apple_base.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::env;
1+
use std::{env, io, path::Path, process::Command};
22

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

@@ -51,3 +51,46 @@ pub fn macos_llvm_target(arch: &str) -> String {
5151
let (major, minor) = macos_deployment_target();
5252
format!("{}-apple-macosx{}.{}.0", arch, major, minor)
5353
}
54+
55+
pub fn sysroot(sdk: &str) -> Result<String, String> {
56+
let actual_sdk_path = sdk_path(sdk)?;
57+
// Like Clang, allow the SDKROOT environment variable used by Xcode to define the sysroot
58+
if let Some(sdk_root) = env::var("SDKROOT").ok() {
59+
let sdk_root_p = Path::new(&sdk_root);
60+
// Ignore SDKROOT if it's not a valid path
61+
if !sdk_root_p.is_absolute() || sdk_root_p == Path::new("/") || !sdk_root_p.exists() {
62+
return Ok(actual_sdk_path);
63+
}
64+
// Ignore SDKROOT if it's clearly set for the wrong platform, which may occur when we're
65+
// compiling a custom build script while targeting iOS for example
66+
match sdk {
67+
"iphoneos" if sdk_root.contains("iPhoneSimulator.platform")
68+
|| sdk_root.contains("MacOSX.platform") => return Ok(actual_sdk_path),
69+
"iphonesimulator" if sdk_root.contains("iPhoneOS.platform")
70+
|| sdk_root.contains("MacOSX.platform") => return Ok(actual_sdk_path),
71+
"macosx" | "macosx10.15" if sdk_root.contains("iPhoneOS.platform")
72+
|| sdk_root.contains("iPhoneSimulator.platform") => return Ok(actual_sdk_path),
73+
_ => return Ok(sdk_root),
74+
}
75+
}
76+
Ok(actual_sdk_path)
77+
}
78+
79+
fn sdk_path(sdk_name: &str) -> Result<String, String> {
80+
let res =
81+
Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
82+
|output| {
83+
if output.status.success() {
84+
Ok(String::from_utf8(output.stdout).unwrap())
85+
} else {
86+
let error = String::from_utf8(output.stderr);
87+
let error = format!("process exit with error: {}", error.unwrap());
88+
Err(io::Error::new(io::ErrorKind::Other, &error[..]))
89+
}
90+
},
91+
);
92+
match res {
93+
Ok(output) => Ok(output.trim().to_string()),
94+
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
95+
}
96+
}

src/librustc_target/spec/apple_ios_base.rs

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
use std::env;
2-
use std::io;
3-
use std::path::Path;
4-
use std::process::Command;
51
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
62

73
use Arch::*;
@@ -30,42 +26,6 @@ impl Arch {
3026
}
3127
}
3228

33-
pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
34-
// Following what clang does
35-
// (https://github.com/llvm/llvm-project/blob/
36-
// 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
37-
// to allow the SDK path to be set. (For clang, xcrun sets
38-
// SDKROOT; for rustc, the user or build system can set it, or we
39-
// can fall back to checking for xcrun on PATH.)
40-
if let Some(sdkroot) = env::var("SDKROOT").ok() {
41-
let sdkroot_path = Path::new(&sdkroot);
42-
if sdkroot_path.is_absolute() && sdkroot_path != Path::new("/") && sdkroot_path.exists() {
43-
return Ok(sdkroot);
44-
}
45-
}
46-
let res = Command::new("xcrun")
47-
.arg("--show-sdk-path")
48-
.arg("-sdk")
49-
.arg(sdk_name)
50-
.output()
51-
.and_then(|output| {
52-
if output.status.success() {
53-
Ok(String::from_utf8(output.stdout).unwrap())
54-
} else {
55-
let error = String::from_utf8(output.stderr);
56-
let error = format!("process exit with error: {}",
57-
error.unwrap());
58-
Err(io::Error::new(io::ErrorKind::Other,
59-
&error[..]))
60-
}
61-
});
62-
63-
match res {
64-
Ok(output) => Ok(output.trim().to_string()),
65-
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e))
66-
}
67-
}
68-
6929
fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
7030
let sdk_name = match arch {
7131
Armv7 | Armv7s | Arm64 => "iphoneos",
@@ -75,7 +35,7 @@ fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
7535

7636
let arch_name = arch.to_string();
7737

78-
let sdk_root = get_sdk_root(sdk_name)?;
38+
let sdk_root = super::apple_base::sysroot(sdk_name)?;
7939

8040
let mut args = LinkArgs::new();
8141
args.insert(LinkerFlavor::Gcc,

src/librustc_target/spec/i686_apple_darwin.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
11
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
22

33
pub fn target() -> TargetResult {
4+
let sysroot = super::apple_base::sysroot("macosx")?;
45
let mut base = super::apple_base::opts();
56
base.cpu = "yonah".to_string();
67
base.max_atomic_width = Some(64);
7-
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
8+
base.pre_link_args.insert(
9+
LinkerFlavor::Gcc,
10+
vec![
11+
"-m32".to_string(),
12+
"-isysroot".to_string(),
13+
sysroot.clone(),
14+
"-Wl,-syslibroot".to_string(),
15+
sysroot,
16+
],
17+
);
818
base.stack_probes = true;
919
base.eliminate_frame_pointer = false;
1020

src/librustc_target/spec/x86_64_apple_darwin.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
22

33
pub fn target() -> TargetResult {
4+
let sysroot = super::apple_base::sysroot("macosx")?;
45
let mut base = super::apple_base::opts();
56
base.cpu = "core2".to_string();
67
base.max_atomic_width = Some(128); // core2 support cmpxchg16b
78
base.eliminate_frame_pointer = false;
8-
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
9+
base.pre_link_args.insert(
10+
LinkerFlavor::Gcc,
11+
vec![
12+
"-m64".to_string(),
13+
"-isysroot".to_string(),
14+
sysroot.clone(),
15+
"-Wl,-syslibroot".to_string(),
16+
sysroot,
17+
],
18+
);
919
base.stack_probes = true;
1020

1121
// Clang automatically chooses a more specific target based on

0 commit comments

Comments
 (0)