From 691f645ecd38d346fb047bbcb148694bd82c6a92 Mon Sep 17 00:00:00 2001 From: Aleksi Juvani Date: Sat, 7 Sep 2019 17:18:10 +0300 Subject: [PATCH 1/6] 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 53364e72bfe3a..aa5080aaaf6e6 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 6d3900c0b203f..db4a818083183 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 7d804ea53fb31..a60c007212474 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 182103440f035..b72d037565b5b 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 From 6dc763eed59295d0907a2780d66d4adf6f41a644 Mon Sep 17 00:00:00 2001 From: Aleksi Juvani Date: Sat, 7 Sep 2019 19:04:59 +0300 Subject: [PATCH 2/6] Fix nits --- src/librustc_target/spec/apple_base.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index aa5080aaaf6e6..297e64d4aebaa 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -54,24 +54,24 @@ pub fn macos_llvm_target(arch: &str) -> String { 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 + // 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 + // 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 { + // 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(match sdk { "iphoneos" if sdk_root.contains("iPhoneSimulator.platform") - || sdk_root.contains("MacOSX.platform") => return Ok(actual_sdk_path), + || sdk_root.contains("MacOSX.platform") => actual_sdk_path, "iphonesimulator" if sdk_root.contains("iPhoneOS.platform") - || sdk_root.contains("MacOSX.platform") => return Ok(actual_sdk_path), + || sdk_root.contains("MacOSX.platform") => 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), - } + || sdk_root.contains("iPhoneSimulator.platform") => actual_sdk_path, + _ => sdk_root, + }) } Ok(actual_sdk_path) } From 995d9857bdae6da200703e3aefbc39f5eded299b Mon Sep 17 00:00:00 2001 From: Aleksi Juvani Date: Sat, 7 Sep 2019 21:02:27 +0300 Subject: [PATCH 3/6] Fix cross-compilation to macOS --- src/librustc_target/spec/apple_base.rs | 55 ++++++++++++------- src/librustc_target/spec/apple_ios_base.rs | 21 ++++--- src/librustc_target/spec/i686_apple_darwin.rs | 18 +++--- .../spec/x86_64_apple_darwin.rs | 18 +++--- 4 files changed, 62 insertions(+), 50 deletions(-) diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index 297e64d4aebaa..a8d6290aa433b 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -1,4 +1,4 @@ -use std::{env, io, path::Path, process::Command}; +use std::{env, path::Path}; use crate::spec::{LinkArgs, TargetOptions}; @@ -52,18 +52,19 @@ pub fn macos_llvm_target(arch: &str) -> String { format!("{}-apple-macosx{}.{}.0", arch, major, minor) } -pub fn sysroot(sdk: &str) -> Result { - let actual_sdk_path = sdk_path(sdk)?; +#[cfg(target_os = "macos")] +pub fn sysroot(sdk: &str) -> Result, 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(actual_sdk_path); + 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(match sdk { + 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") @@ -71,24 +72,40 @@ pub fn sysroot(sdk: &str) -> Result { "macosx" | "macosx10.15" if sdk_root.contains("iPhoneOS.platform") || sdk_root.contains("iPhoneSimulator.platform") => actual_sdk_path, _ => sdk_root, - }) + })) } - Ok(actual_sdk_path) + Ok(None) } +// `xcrun` is only available on macOS. +#[cfg(not(target_os = "macos"))] +pub fn sysroot(_sdk: &str) -> Result, 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)); + } + } + Ok(None) +} + +#[cfg(target_os = "macos")] 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[..])) - } - }, - ); + 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)), diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs index db4a818083183..801736944f4f8 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_ios_base.rs @@ -35,16 +35,19 @@ fn build_pre_link_args(arch: Arch) -> Result { let arch_name = arch.to_string(); - let sdk_root = super::apple_base::sysroot(sdk_name)?; - let mut args = LinkArgs::new(); - args.insert(LinkerFlavor::Gcc, - vec!["-arch".to_string(), - arch_name.to_string(), - "-isysroot".to_string(), - sdk_root.clone(), - "-Wl,-syslibroot".to_string(), - sdk_root]); + 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 + ], + ); + } Ok(args) } diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs index a60c007212474..b08ed56025208 100644 --- a/src/librustc_target/spec/i686_apple_darwin.rs +++ b/src/librustc_target/spec/i686_apple_darwin.rs @@ -1,20 +1,16 @@ 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(), - "-isysroot".to_string(), - sysroot.clone(), - "-Wl,-syslibroot".to_string(), - sysroot, - ], - ); + 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.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 b72d037565b5b..f299c27e7e1ef 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -1,21 +1,17 @@ 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(), - "-isysroot".to_string(), - sysroot.clone(), - "-Wl,-syslibroot".to_string(), - sysroot, - ], - ); + 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.stack_probes = true; // Clang automatically chooses a more specific target based on From 2e9eba7f380f5fd99df92deaa03e00faa519b1a4 Mon Sep 17 00:00:00 2001 From: Aleksi Juvani Date: Tue, 10 Sep 2019 09:53:59 +0300 Subject: [PATCH 4/6] Set environment variables for linker instead of sysroot --- src/librustc_target/spec/apple_base.rs | 70 ++++--------------- src/librustc_target/spec/apple_ios_base.rs | 61 ++++++++++++---- src/librustc_target/spec/i686_apple_darwin.rs | 7 +- .../spec/x86_64_apple_darwin.rs | 7 +- 4 files changed, 64 insertions(+), 81 deletions(-) diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index a8d6290aa433b..e2632fc14148f 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -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, 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)); +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())) } - // 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, 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)); - } - } - Ok(None) -} - -#[cfg(target_os = "macos")] -fn sdk_path(sdk_name: &str) -> Result { - 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 } diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs index 801736944f4f8..6d3900c0b203f 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_ios_base.rs @@ -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 { + // 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", @@ -35,19 +75,16 @@ fn build_pre_link_args(arch: Arch) -> Result { 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) } diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs index b08ed56025208..ba44cdccb7c48 100644 --- a/src/librustc_target/spec/i686_apple_darwin.rs +++ b/src/librustc_target/spec/i686_apple_darwin.rs @@ -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; diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs index f299c27e7e1ef..442c2650bbba1 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -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 From e715d03275cb83a3fd7aeb8f4c62661d4c690464 Mon Sep 17 00:00:00 2001 From: Aleksi Juvani Date: Thu, 12 Sep 2019 13:47:17 +0300 Subject: [PATCH 5/6] Remove env vars instead of setting them to an empty string --- src/librustc_codegen_ssa/back/command.rs | 16 ++++++++++++++++ src/librustc_codegen_ssa/back/link.rs | 3 +++ src/librustc_target/spec/apple_base.rs | 12 ++++++------ src/librustc_target/spec/i686_apple_darwin.rs | 2 +- src/librustc_target/spec/mod.rs | 7 ++++++- src/librustc_target/spec/x86_64_apple_darwin.rs | 2 +- 6 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/librustc_codegen_ssa/back/command.rs b/src/librustc_codegen_ssa/back/command.rs index 340cc772e5f07..596978f002b66 100644 --- a/src/librustc_codegen_ssa/back/command.rs +++ b/src/librustc_codegen_ssa/back/command.rs @@ -14,6 +14,7 @@ pub struct Command { program: Program, args: Vec, env: Vec<(OsString, OsString)>, + env_remove: Vec, } #[derive(Clone)] @@ -41,6 +42,7 @@ impl Command { program, args: Vec::new(), env: Vec::new(), + env_remove: Vec::new(), } } @@ -75,6 +77,17 @@ impl Command { self.env.push((key.to_owned(), value.to_owned())); } + pub fn env_remove(&mut self, key: K) -> &mut Command + where K: AsRef, + { + self._env_remove(key.as_ref()); + self + } + + fn _env_remove(&mut self, key: &OsStr) { + self.env_remove.push(key.to_owned()); + } + pub fn output(&mut self) -> io::Result { self.command().output() } @@ -100,6 +113,9 @@ impl Command { }; ret.args(&self.args); ret.envs(self.env.clone()); + for k in &self.env_remove { + ret.env_remove(k); + } return ret } diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 8603d61fb5453..74cde92974c04 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -532,6 +532,9 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, for &(ref k, ref v) in &sess.target.target.options.link_env { cmd.env(k, v); } + for k in &sess.target.target.options.link_env_remove { + cmd.env_remove(k); + } if sess.opts.debugging_opts.print_link_args { println!("{:?}", &cmd); diff --git a/src/librustc_target/spec/apple_base.rs b/src/librustc_target/spec/apple_base.rs index e2632fc14148f..f7551aa768dfc 100644 --- a/src/librustc_target/spec/apple_base.rs +++ b/src/librustc_target/spec/apple_base.rs @@ -52,18 +52,18 @@ pub fn macos_llvm_target(arch: &str) -> String { format!("{}-apple-macosx{}.{}.0", arch, major, minor) } -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 +pub fn macos_link_env_remove() -> Vec { + let mut env_remove = Vec::with_capacity(2); + // Remove 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())) + env_remove.push("SDKROOT".to_string()) } } // 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 + env_remove.push("IPHONEOS_DEPLOYMENT_TARGET".to_string()); + env_remove } diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs index ba44cdccb7c48..27d05823bf21e 100644 --- a/src/librustc_target/spec/i686_apple_darwin.rs +++ b/src/librustc_target/spec/i686_apple_darwin.rs @@ -5,7 +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()]); - base.link_env.extend(super::apple_base::macos_link_env()); + base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); base.stack_probes = true; base.eliminate_frame_pointer = false; diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 503d8a08b6f4f..82e74f317de23 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -580,8 +580,10 @@ pub struct TargetOptions { /// user-defined libraries. pub post_link_args: LinkArgs, - /// Environment variables to be set before invoking the linker. + /// Environment variables to be set for the linker invocation. pub link_env: Vec<(String, String)>, + /// Environment variables to be removed for the linker invocation. + pub link_env_remove: Vec, /// Extra arguments to pass to the external assembler (when used) pub asm_args: Vec, @@ -843,6 +845,7 @@ impl Default for TargetOptions { post_link_objects_crt: Vec::new(), late_link_args: LinkArgs::new(), link_env: Vec::new(), + link_env_remove: Vec::new(), archive_format: "gnu".to_string(), custom_unwind_resume: false, allow_asm: true, @@ -1118,6 +1121,7 @@ impl Target { key!(post_link_objects_crt, list); key!(post_link_args, link_args); key!(link_env, env); + key!(link_env_remove, list); key!(asm_args, list); key!(cpu); key!(features); @@ -1334,6 +1338,7 @@ impl ToJson for Target { target_option_val!(post_link_objects_crt); target_option_val!(link_args - post_link_args); target_option_val!(env - link_env); + target_option_val!(link_env_remove); target_option_val!(asm_args); target_option_val!(cpu); target_option_val!(features); diff --git a/src/librustc_target/spec/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs index 442c2650bbba1..d059e44c5c82a 100644 --- a/src/librustc_target/spec/x86_64_apple_darwin.rs +++ b/src/librustc_target/spec/x86_64_apple_darwin.rs @@ -6,7 +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()]); - base.link_env.extend(super::apple_base::macos_link_env()); + base.link_env_remove.extend(super::apple_base::macos_link_env_remove()); base.stack_probes = true; // Clang automatically chooses a more specific target based on From fe6d626abcc6ca994f0554bb78858ccd2b33dcfd Mon Sep 17 00:00:00 2001 From: Aleksi Juvani Date: Thu, 12 Sep 2019 15:23:59 +0300 Subject: [PATCH 6/6] Ignore linker env vars set for macOS on iOS targets --- src/librustc_target/spec/apple_ios_base.rs | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs index 6d3900c0b203f..fdbb1bd5db34b 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_ios_base.rs @@ -38,9 +38,18 @@ pub fn get_sdk_root(sdk_name: &str) -> Result { // 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 p = Path::new(&sdkroot); + match sdk_name { + // Ignore `SDKROOT` if it's clearly set for the wrong platform. + "iphoneos" if sdkroot.contains("iPhoneSimulator.platform") + || sdkroot.contains("MacOSX.platform") => (), + "iphonesimulator" if sdkroot.contains("iPhoneOS.platform") + || sdkroot.contains("MacOSX.platform") => (), + "macosx10.15" if sdkroot.contains("iPhoneOS.platform") + || sdkroot.contains("iPhoneSimulator.platform") => (), + // Ignore `SDKROOT` if it's not a valid path. + _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (), + _ => return Ok(sdkroot), } } let res = Command::new("xcrun") @@ -100,6 +109,13 @@ fn target_cpu(arch: Arch) -> String { }.to_string() } +fn link_env_remove(arch: Arch) -> Vec { + match arch { + Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()], + X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()], + } +} + pub fn opts(arch: Arch) -> Result { let pre_link_args = build_pre_link_args(arch)?; Ok(TargetOptions { @@ -107,6 +123,7 @@ pub fn opts(arch: Arch) -> Result { dynamic_linking: false, executables: true, pre_link_args, + link_env_remove: link_env_remove(arch), has_elf_tls: false, eliminate_frame_pointer: false, .. super::apple_base::opts()