浏览代码

fix(cli): improve vs build tools detection (#6982)

* fix(cli): improve vs build tools detection

* clean up

* typos

* changefile

* patch instead of minor

* update vswhere

* use vswhere instead of custom logic. update wording

* sort and dedup manually
Fabian-Lars 2 年之前
父节点
当前提交
c7056d1b20
共有 5 个文件被更改,包括 54 次插入21 次删除
  1. 5 0
      .changes/tauri-info-msvc-detection.md
  2. 1 0
      tooling/cli/Cargo.lock
  3. 1 0
      tooling/cli/Cargo.toml
  4. 二进制
      tooling/cli/scripts/vswhere.exe
  5. 47 21
      tooling/cli/src/info/env_system.rs

+ 5 - 0
.changes/tauri-info-msvc-detection.md

@@ -0,0 +1,5 @@
+---
+'cli.rs': 'patch'
+---
+
+Improve Visual Studio installation detection in `tauri info` command to check for the necessary components instead of whole workloads. This also fixes the detection of minimal installations and auto-installations done by `rustup`.

+ 1 - 0
tooling/cli/Cargo.lock

@@ -3393,6 +3393,7 @@ dependencies = [
  "anyhow",
  "axum",
  "base64 0.21.0",
+ "cc",
  "clap",
  "colored",
  "common-path",

+ 1 - 0
tooling/cli/Cargo.toml

@@ -84,6 +84,7 @@ itertools = "0.10"
 
 [target."cfg(windows)".dependencies]
 winapi = { version = "0.3", features = [ "handleapi", "processenv", "winbase", "wincon", "winnt" ] }
+cc = "1"
 
 [target."cfg(unix)".dependencies]
 libc = "0.2"

二进制
tooling/cli/scripts/vswhere.exe


+ 47 - 21
tooling/cli/src/info/env_system.rs

@@ -20,7 +20,7 @@ struct VsInstanceInfo {
 const VSWHERE: &[u8] = include_bytes!("../../scripts/vswhere.exe");
 
 #[cfg(windows)]
-fn build_tools_version() -> crate::Result<Option<Vec<String>>> {
+fn build_tools_version() -> crate::Result<Vec<String>> {
   let mut vswhere = std::env::temp_dir();
   vswhere.push("vswhere.exe");
 
@@ -30,32 +30,60 @@ fn build_tools_version() -> crate::Result<Option<Vec<String>>> {
       let _ = file.write_all(VSWHERE);
     }
   }
-  let output = Command::new(vswhere)
+
+  // Check if there are Visual Studio installations that have the "MSVC - C++ Buildtools" and "Windows SDK" components.
+  // Both the Windows 10 and Windows 11 SDKs work so we need to query it twice.
+  let output_sdk10 = Command::new(&vswhere)
+    .args([
+      "-prerelease",
+      "-products",
+      "*",
+      "-requires",
+      "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
+      "-requires",
+      "Microsoft.VisualStudio.Component.Windows10SDK.*",
+      "-format",
+      "json",
+    ])
+    .output()?;
+
+  let output_sdk11 = Command::new(vswhere)
     .args([
       "-prerelease",
       "-products",
       "*",
-      "-requiresAny",
       "-requires",
-      "Microsoft.VisualStudio.Workload.NativeDesktop",
+      "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
       "-requires",
-      "Microsoft.VisualStudio.Workload.VCTools",
+      "Microsoft.VisualStudio.Component.Windows11SDK.*",
       "-format",
       "json",
     ])
     .output()?;
-  Ok(if output.status.success() {
-    let stdout = String::from_utf8_lossy(&output.stdout);
-    let instances: Vec<VsInstanceInfo> = serde_json::from_str(&stdout)?;
-    Some(
-      instances
-        .iter()
-        .map(|i| i.display_name.clone())
-        .collect::<Vec<String>>(),
-    )
-  } else {
-    None
-  })
+
+  let mut instances: Vec<VsInstanceInfo> = Vec::new();
+
+  if output_sdk10.status.success() {
+    let stdout = String::from_utf8_lossy(&output_sdk10.stdout);
+    let found: Vec<VsInstanceInfo> = serde_json::from_str(&stdout)?;
+    instances.extend(found);
+  }
+
+  if output_sdk11.status.success() {
+    let stdout = String::from_utf8_lossy(&output_sdk11.stdout);
+    let found: Vec<VsInstanceInfo> = serde_json::from_str(&stdout)?;
+    instances.extend(found);
+  }
+
+  let mut instances: Vec<String> = instances
+    .iter()
+    .map(|i| i.display_name.clone())
+    .collect::<Vec<String>>();
+
+  instances.sort_unstable();
+  instances.dedup();
+
+  Ok(instances)
 }
 
 #[cfg(windows)]
@@ -190,13 +218,11 @@ pub fn items() -> Vec<SectionItem> {
     #[cfg(windows)]
     SectionItem::new(
       || {
-        let build_tools = build_tools_version()
-          .unwrap_or_default()
-          .unwrap_or_default();
+        let build_tools = build_tools_version().unwrap_or_default();
         if build_tools.is_empty() {
           Some((
             format!(
-              "Couldn't detect Visual Studio or Visual Studio Build Tools. Download from {}",
+              "Couldn't detect any Visual Studio or VS Build Tools instance with MSVC and SDK components. Download from {}",
               "https://aka.ms/vs/17/release/vs_BuildTools.exe".cyan()
             ),
             Status::Error,