From 58ff15c44c917fc9c732da67161e3144a0c122b0 Mon Sep 17 00:00:00 2001 From: Bas Zalmstra Date: Sun, 23 Jan 2022 20:09:04 +0100 Subject: [PATCH] fix: locate sdkroot required since big sur --- crates/mun_codegen/Cargo.toml | 1 + crates/mun_codegen/src/apple.rs | 39 ++++++++++++++++++++++++ crates/mun_codegen/src/lib.rs | 1 + crates/mun_codegen/src/linker.rs | 10 ++++++ crates/mun_target/src/spec/apple_base.rs | 5 +-- 5 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 crates/mun_codegen/src/apple.rs diff --git a/crates/mun_codegen/Cargo.toml b/crates/mun_codegen/Cargo.toml index 1bec71fb5..187811f19 100644 --- a/crates/mun_codegen/Cargo.toml +++ b/crates/mun_codegen/Cargo.toml @@ -33,6 +33,7 @@ inkwell = { version = "=0.1.0-beta.2", features = ["llvm11-0", "no-libffi-linkin by_address = "1.0.4" paths = { version="=0.1.0", path="../mun_paths", package="mun_paths"} smallvec = "1.6.1" +once_cell = "1.4.0" [dev-dependencies] abi = { path = "../mun_abi", package = "mun_abi" } diff --git a/crates/mun_codegen/src/apple.rs b/crates/mun_codegen/src/apple.rs new file mode 100644 index 000000000..498d462c2 --- /dev/null +++ b/crates/mun_codegen/src/apple.rs @@ -0,0 +1,39 @@ +use once_cell::sync::OnceCell; +use std::{ + env, io, + path::{Path, PathBuf}, + process::Command, +}; + +/// Finds the Apple SDK root directory by checking the `SDKROOT` environment variable or running +/// `xcrun --show-sdk-path`. The result is cached so multiple calls to this function should be +/// fast. +pub fn get_apple_sdk_root() -> Result<&'static Path, String> { + static SDK_PATH: OnceCell = OnceCell::new(); + + SDK_PATH + .get_or_try_init(|| { + if let Ok(sdkroot) = env::var("SDKROOT") { + return Ok(PathBuf::from(sdkroot)); + } + + let res = Command::new("xcrun") + .arg("--show-sdk-path") + .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(PathBuf::from(output.trim())), + Err(e) => Err(format!("failed to get SDK path: {}", e)), + } + }) + .map(AsRef::as_ref) +} diff --git a/crates/mun_codegen/src/lib.rs b/crates/mun_codegen/src/lib.rs index a433c13d9..54259a1ce 100644 --- a/crates/mun_codegen/src/lib.rs +++ b/crates/mun_codegen/src/lib.rs @@ -22,6 +22,7 @@ mod test; pub mod value; +mod apple; pub(crate) mod intrinsics; mod linker; mod module_group; diff --git a/crates/mun_codegen/src/linker.rs b/crates/mun_codegen/src/linker.rs index 222c8b687..4fb3e84a0 100644 --- a/crates/mun_codegen/src/linker.rs +++ b/crates/mun_codegen/src/linker.rs @@ -1,3 +1,4 @@ +use crate::apple::get_apple_sdk_root; use mun_target::spec; use mun_target::spec::LinkerFlavor; use std::fmt; @@ -11,6 +12,9 @@ pub enum LinkerError { /// Error in path conversion PathError(PathBuf), + + /// Could not locate platform SDK + PlatformSdkMissing(String), } impl fmt::Display for LinkerError { @@ -22,6 +26,9 @@ impl fmt::Display for LinkerError { "path contains invalid UTF-8 characters: {}", path.display() ), + LinkerError::PlatformSdkMissing(err) => { + write!(f, "could not find platform sdk: {}", err) + } } } } @@ -119,6 +126,9 @@ impl Linker for Ld64Linker { // Link as dynamic library self.args.push("-dylib".to_owned()); + + let sdk_root = get_apple_sdk_root().map_err(LinkerError::PlatformSdkMissing)?; + self.args.push(format!("-L{}/usr/lib", sdk_root.display())); self.args.push("-lsystem".to_owned()); // Specify output path diff --git a/crates/mun_target/src/spec/apple_base.rs b/crates/mun_target/src/spec/apple_base.rs index 27b944ab3..13a69f643 100644 --- a/crates/mun_target/src/spec/apple_base.rs +++ b/crates/mun_target/src/spec/apple_base.rs @@ -12,10 +12,7 @@ fn macos_deployment_target() -> (u32, u32) { let deployment_target = env::var("MACOSX_DEPLOYMENT_TARGET").ok(); let version = deployment_target .as_ref() - .and_then(|s| { - let mut i = s.splitn(2, '.'); - i.next().and_then(|a| i.next().map(|b| (a, b))) - }) + .and_then(|s| s.split_once('.')) .and_then(|(a, b)| { a.parse::() .and_then(|a| b.parse::().map(|b| (a, b)))