From 691f645ecd38d346fb047bbcb148694bd82c6a92 Mon Sep 17 00:00:00 2001 From: Aleksi Juvani Date: Sat, 7 Sep 2019 17:18:10 +0300 Subject: [PATCH] Fix sysroot on macOS when cross-compiling and SDKROOT is set Fixes rust-lang/cargo#7283 Closes rust-lang/cargo#7284 r? @alexcrichton --- src/librustc_target/spec/apple_base.rs | 45 ++++++++++++++++++- src/librustc_target/spec/apple_ios_base.rs | 42 +---------------- src/librustc_target/spec/i686_apple_darwin.rs | 12 ++++- .../spec/x86_64_apple_darwin.rs | 12 ++++- 4 files changed, 67 insertions(+), 44 deletions(-) diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index 53364e72bfe..aa5080aaaf6 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -1,4 +1,4 @@ -use std::env; +use std::{env, io, path::Path, process::Command}; use crate::spec::{LinkArgs, TargetOptions}; @@ -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 { + 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 { + 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)), + } +} diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs index 6d3900c0b20..db4a8180831 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_ios_base.rs @@ -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::*; @@ -30,42 +26,6 @@ impl Arch { } } -pub fn get_sdk_root(sdk_name: &str) -> Result { - // 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 { let sdk_name = match arch { Armv7 | Armv7s | Arm64 => "iphoneos", @@ -75,7 +35,7 @@ fn build_pre_link_args(arch: Arch) -> Result { 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, diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs index 7d804ea53fb..a60c0072124 100644 --- a/src/librustc_target/spec/i686_apple_darwin.rs +++ b/src/librustc_target/spec/i686_apple_darwin.rs @@ -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; diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs index 182103440f0..b72d037565b 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -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