apple_bindgen/
sdk.rs

1// TODO: change this module to thin wrapper of apple_sdk::SdkPath and related utilities
2
3use apple_sdk::Platform;
4use std::{
5    path::{Path, PathBuf},
6    str::FromStr,
7};
8use thiserror::Error;
9
10#[non_exhaustive]
11#[derive(Debug, Error)]
12pub enum SdkPathError {
13    #[error("apple_sdk::Error")]
14    AppleSdkError(apple_sdk::Error),
15    #[error("path is not sdk path")]
16    InvalidPath(PathBuf),
17    #[error("xcrun lookup failed")]
18    XcrunError(std::io::Error),
19}
20
21#[derive(Debug, Clone)]
22pub struct SdkPath(PathBuf);
23
24impl SdkPath {
25    pub fn path(&self) -> &Path {
26        &self.0
27    }
28}
29
30impl TryFrom<&Platform> for SdkPath {
31    type Error = SdkPathError;
32
33    fn try_from(platform: &Platform) -> Result<Self, Self::Error> {
34        use std::process::Command;
35        let output = Command::new("xcrun")
36            .args(&[
37                "--sdk",
38                &platform.filesystem_name().to_lowercase(),
39                "--show-sdk-path",
40            ])
41            .output()
42            .map_err(SdkPathError::XcrunError)?
43            .stdout;
44        let path = std::str::from_utf8(&output)
45            .expect("invalid output from `xcrun`")
46            .trim_end();
47        Ok(Self(PathBuf::from(path)))
48    }
49}
50
51impl TryFrom<PathBuf> for SdkPath {
52    type Error = SdkPathError;
53    fn try_from(path: PathBuf) -> Result<Self, Self::Error> {
54        let s = path
55            .to_str()
56            .expect("sdk path is always convertible to utf-8 string");
57        if !s.ends_with(".sdk") {
58            return Err(SdkPathError::InvalidPath(path));
59        }
60        let path = std::path::PathBuf::from(s);
61        if !path.exists() {
62            return Err(SdkPathError::InvalidPath(path));
63        }
64        Ok(Self(path))
65    }
66}
67
68impl TryFrom<&str> for SdkPath {
69    type Error = SdkPathError;
70    fn try_from(s: &str) -> Result<Self, Self::Error> {
71        let platform = Platform::from_str(s).map_err(SdkPathError::AppleSdkError)?;
72        SdkPath::try_from(&platform)
73    }
74}