tugger_windows/
sdk.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5use anyhow::{anyhow, Result};
6
7#[cfg(target_family = "windows")]
8use std::path::PathBuf;
9
10/// Convert the current binary's target architecture to a path used by the Windows SDK.
11///
12/// This can be used to resolve the path to host-native platform binaries in the
13/// Windows SDK.
14pub fn target_arch_to_windows_sdk_platform_path() -> Result<&'static str> {
15    if cfg!(target_arch = "x86") {
16        Ok("x86")
17    } else if cfg!(target_arch = "x86_64") {
18        Ok("x64")
19    } else if cfg!(target_arch = "arm") {
20        Ok("arm")
21    } else if cfg!(target_arch = "aarch64") {
22        Ok("arm64")
23    } else {
24        Err(anyhow!("target architecture not supported on Windows"))
25    }
26}
27
28/// Resolve the path to Windows SDK binaries for the current executable's architecture.
29///
30/// Will return `Err` if the path does not exist.
31#[cfg(target_family = "windows")]
32pub fn find_windows_sdk_current_arch_bin_path(
33    version: Option<find_winsdk::SdkVersion>,
34) -> Result<PathBuf> {
35    let sdk_info = find_winsdk::SdkInfo::find(version.unwrap_or(find_winsdk::SdkVersion::Any))?
36        .ok_or_else(|| anyhow!("could not locate Windows SDK"))?;
37
38    let bin_path = sdk_info.installation_folder().join("bin");
39
40    let candidates = [
41        sdk_info.product_version().to_string(),
42        format!("{}.0", sdk_info.product_version()),
43    ];
44
45    let version_path = candidates
46        .iter()
47        .filter_map(|p| {
48            let p = bin_path.join(p);
49
50            if p.exists() {
51                Some(p)
52            } else {
53                None
54            }
55        })
56        .next()
57        .ok_or_else(|| anyhow!("could not locate Windows SDK version path"))?;
58
59    let arch_path = version_path.join(target_arch_to_windows_sdk_platform_path()?);
60
61    if arch_path.exists() {
62        Ok(arch_path)
63    } else {
64        Err(anyhow!("{} does not exist", arch_path.display()))
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    #[cfg(target_family = "windows")]
71    use super::*;
72
73    #[cfg(target_family = "windows")]
74    #[test]
75    pub fn test_find_windows_sdk_current_arch_bin_path() -> Result<()> {
76        find_windows_sdk_current_arch_bin_path(None)?;
77
78        Ok(())
79    }
80}