Skip to content

Commit 2e9eba7

Browse files
committed
Set environment variables for linker instead of sysroot
1 parent 995d985 commit 2e9eba7

File tree

4 files changed

+64
-81
lines changed

4 files changed

+64
-81
lines changed
Lines changed: 13 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{env, path::Path};
1+
use std::env;
22

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

@@ -52,62 +52,18 @@ pub fn macos_llvm_target(arch: &str) -> String {
5252
format!("{}-apple-macosx{}.{}.0", arch, major, minor)
5353
}
5454

55-
#[cfg(target_os = "macos")]
56-
pub fn sysroot(sdk: &str) -> Result<Option<String>, String> {
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 actual_sdk_path = sdk_path(sdk)?;
60-
let sdk_root_p = Path::new(&sdk_root);
61-
// Ignore `SDKROOT` if it's not a valid path.
62-
if !sdk_root_p.is_absolute() || sdk_root_p == Path::new("/") || !sdk_root_p.exists() {
63-
return Ok(Some(actual_sdk_path));
55+
pub fn macos_link_env() -> Vec<(String, String)> {
56+
let mut env = Vec::with_capacity(2);
57+
// Ignore the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
58+
// may occur when we're linking a custom build script while targeting iOS for example.
59+
if let Some(sdkroot) = env::var("SDKROOT").ok() {
60+
if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") {
61+
env.push(("SDKROOT".to_string(), String::new()))
6462
}
65-
// Ignore `SDKROOT` if it's clearly set for the wrong platform, which may occur when we're
66-
// compiling a custom build script while targeting iOS for example.
67-
return Ok(Some(match sdk {
68-
"iphoneos" if sdk_root.contains("iPhoneSimulator.platform")
69-
|| sdk_root.contains("MacOSX.platform") => actual_sdk_path,
70-
"iphonesimulator" if sdk_root.contains("iPhoneOS.platform")
71-
|| sdk_root.contains("MacOSX.platform") => actual_sdk_path,
72-
"macosx" | "macosx10.15" if sdk_root.contains("iPhoneOS.platform")
73-
|| sdk_root.contains("iPhoneSimulator.platform") => actual_sdk_path,
74-
_ => sdk_root,
75-
}))
76-
}
77-
Ok(None)
78-
}
79-
80-
// `xcrun` is only available on macOS.
81-
#[cfg(not(target_os = "macos"))]
82-
pub fn sysroot(_sdk: &str) -> Result<Option<String>, String> {
83-
if let Some(sdk_root) = env::var("SDKROOT").ok() {
84-
let sdk_root_p = Path::new(&sdk_root);
85-
// Use `SDKROOT` only if it's a valid path.
86-
if sdk_root_p.is_absolute() && sdk_root_p != Path::new("/") && sdk_root_p.exists() {
87-
return Ok(Some(sdk_root));
88-
}
89-
}
90-
Ok(None)
91-
}
92-
93-
#[cfg(target_os = "macos")]
94-
fn sdk_path(sdk_name: &str) -> Result<String, String> {
95-
let res = std::process::Command::new("xcrun")
96-
.arg("--show-sdk-path")
97-
.arg("-sdk")
98-
.arg(sdk_name)
99-
.output()
100-
.and_then(|output| {
101-
if output.status.success() {
102-
Ok(String::from_utf8(output.stdout).unwrap())
103-
} else {
104-
let error = String::from_utf8(output.stderr);
105-
let error = format!("process exit with error: {}", error.unwrap());
106-
Err(std::io::Error::new(std::io::ErrorKind::Other, &error[..]))
107-
}
108-
});
109-
match res {
110-
Ok(output) => Ok(output.trim().to_string()),
111-
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
11263
}
64+
// Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at
65+
// "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",
66+
// although this is apparently ignored when using the linker at "/usr/bin/ld".
67+
env.push(("IPHONEOS_DEPLOYMENT_TARGET".to_string(), String::new()));
68+
env
11369
}

src/librustc_target/spec/apple_ios_base.rs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
use std::env;
2+
use std::io;
3+
use std::path::Path;
4+
use std::process::Command;
15
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
26

37
use Arch::*;
@@ -26,6 +30,42 @@ impl Arch {
2630
}
2731
}
2832

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+
2969
fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
3070
let sdk_name = match arch {
3171
Armv7 | Armv7s | Arm64 => "iphoneos",
@@ -35,19 +75,16 @@ fn build_pre_link_args(arch: Arch) -> Result<LinkArgs, String> {
3575

3676
let arch_name = arch.to_string();
3777

78+
let sdk_root = get_sdk_root(sdk_name)?;
79+
3880
let mut args = LinkArgs::new();
39-
args.insert(LinkerFlavor::Gcc, vec!["-arch".to_string(), arch_name.to_string()]);
40-
if let Some(sdk_root) = super::apple_base::sysroot(sdk_name)? {
41-
args.insert(
42-
LinkerFlavor::Gcc,
43-
vec![
44-
"-isysroot".to_string(),
45-
sdk_root.clone(),
46-
"-Wl,-syslibroot".to_string(),
47-
sdk_root
48-
],
49-
);
50-
}
81+
args.insert(LinkerFlavor::Gcc,
82+
vec!["-arch".to_string(),
83+
arch_name.to_string(),
84+
"-isysroot".to_string(),
85+
sdk_root.clone(),
86+
"-Wl,-syslibroot".to_string(),
87+
sdk_root]);
5188

5289
Ok(args)
5390
}

src/librustc_target/spec/i686_apple_darwin.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,7 @@ pub fn target() -> TargetResult {
55
base.cpu = "yonah".to_string();
66
base.max_atomic_width = Some(64);
77
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]);
8-
if let Some(sysroot) = super::apple_base::sysroot("macosx")? {
9-
base.pre_link_args.insert(
10-
LinkerFlavor::Gcc,
11-
vec!["-isysroot".to_string(), sysroot.clone(), "-Wl,-syslibroot".to_string(), sysroot],
12-
);
13-
}
8+
base.link_env.extend(super::apple_base::macos_link_env());
149
base.stack_probes = true;
1510
base.eliminate_frame_pointer = false;
1611

src/librustc_target/spec/x86_64_apple_darwin.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,7 @@ pub fn target() -> TargetResult {
66
base.max_atomic_width = Some(128); // core2 support cmpxchg16b
77
base.eliminate_frame_pointer = false;
88
base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
9-
if let Some(sysroot) = super::apple_base::sysroot("macosx")? {
10-
base.pre_link_args.insert(
11-
LinkerFlavor::Gcc,
12-
vec!["-isysroot".to_string(), sysroot.clone(), "-Wl,-syslibroot".to_string(), sysroot],
13-
);
14-
}
9+
base.link_env.extend(super::apple_base::macos_link_env());
1510
base.stack_probes = true;
1611

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

0 commit comments

Comments
 (0)