Set environment variables for linker instead of sysroot
This commit is contained in:
parent
995d9857bd
commit
2e9eba7f38
4 changed files with 64 additions and 81 deletions
|
@ -1,4 +1,4 @@
|
|||
use std::{env, path::Path};
|
||||
use std::env;
|
||||
|
||||
use crate::spec::{LinkArgs, TargetOptions};
|
||||
|
||||
|
@ -52,62 +52,18 @@ pub fn macos_llvm_target(arch: &str) -> String {
|
|||
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));
|
||||
pub fn macos_link_env() -> Vec<(String, String)> {
|
||||
let mut env = Vec::with_capacity(2);
|
||||
// Ignore the `SDKROOT` environment variable if it's clearly set for the wrong platform, which
|
||||
// may occur when we're linking a custom build script while targeting iOS for example.
|
||||
if let Some(sdkroot) = env::var("SDKROOT").ok() {
|
||||
if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("iPhoneSimulator.platform") {
|
||||
env.push(("SDKROOT".to_string(), String::new()))
|
||||
}
|
||||
}
|
||||
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)),
|
||||
}
|
||||
// Additionally, `IPHONEOS_DEPLOYMENT_TARGET` must not be set when using the Xcode linker at
|
||||
// "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld",
|
||||
// although this is apparently ignored when using the linker at "/usr/bin/ld".
|
||||
env.push(("IPHONEOS_DEPLOYMENT_TARGET".to_string(), String::new()));
|
||||
env
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
use std::env;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
|
||||
|
||||
use Arch::*;
|
||||
|
@ -26,6 +30,42 @@ 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",
|
||||
|
@ -35,19 +75,16 @@ 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()]);
|
||||
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
|
||||
],
|
||||
);
|
||||
}
|
||||
args.insert(LinkerFlavor::Gcc,
|
||||
vec!["-arch".to_string(),
|
||||
arch_name.to_string(),
|
||||
"-isysroot".to_string(),
|
||||
sdk_root.clone(),
|
||||
"-Wl,-syslibroot".to_string(),
|
||||
sdk_root]);
|
||||
|
||||
Ok(args)
|
||||
}
|
||||
|
|
|
@ -5,12 +5,7 @@ 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.link_env.extend(super::apple_base::macos_link_env());
|
||||
base.stack_probes = true;
|
||||
base.eliminate_frame_pointer = false;
|
||||
|
||||
|
|
|
@ -6,12 +6,7 @@ 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.link_env.extend(super::apple_base::macos_link_env());
|
||||
base.stack_probes = true;
|
||||
|
||||
// Clang automatically chooses a more specific target based on
|
||||
|
|
Loading…
Reference in a new issue