Default to cargo-zigbuild for ZED_BUILD_REMOTE_SERVER (#33391)

Cole Miller created

Follow-up to #31467. `cargo-zigbuild` will be installed if it's not
there already, but you have to install Zig yourself. Pass
`ZED_BUILD_REMOTE_SERVER=cross` to use the old way.

Release Notes:

- N/A

Change summary

Cargo.lock                       |  1 
crates/remote/Cargo.toml         |  1 
crates/remote/src/ssh_session.rs | 64 +++++++++++++++++++++------------
3 files changed, 43 insertions(+), 23 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -13168,6 +13168,7 @@ dependencies = [
  "thiserror 2.0.12",
  "urlencoding",
  "util",
+ "which 6.0.3",
  "workspace-hack",
 ]
 

crates/remote/Cargo.toml 🔗

@@ -41,6 +41,7 @@ tempfile.workspace = true
 thiserror.workspace = true
 urlencoding.workspace = true
 util.workspace = true
+which.workspace = true
 workspace-hack.workspace = true
 
 [dev-dependencies]

crates/remote/src/ssh_session.rs 🔗

@@ -2030,27 +2030,7 @@ impl SshRemoteConnection {
         };
         smol::fs::create_dir_all("target/remote_server").await?;
 
-        if build_remote_server.contains("zigbuild") {
-            delegate.set_status(
-                Some(&format!(
-                    "Building remote binary from source for {triple} with Zig"
-                )),
-                cx,
-            );
-            log::info!("building remote binary from source for {triple} with Zig");
-            run_cmd(Command::new("cargo").args([
-                "zigbuild",
-                "--package",
-                "remote_server",
-                "--features",
-                "debug-embed",
-                "--target-dir",
-                "target/remote_server",
-                "--target",
-                &triple,
-            ]))
-            .await?;
-        } else {
+        if build_remote_server.contains("cross") {
             delegate.set_status(Some("Installing cross.rs for cross-compilation"), cx);
             log::info!("installing cross");
             run_cmd(Command::new("cargo").args([
@@ -2088,12 +2068,50 @@ impl SshRemoteConnection {
                     ),
             )
             .await?;
-        }
+        } else {
+            let which = cx
+                .background_spawn(async move { which::which("zig") })
+                .await;
+
+            if which.is_err() {
+                anyhow::bail!(
+                    "zig not found on $PATH, install zig (see https://ziglang.org/learn/getting-started or use zigup) or pass ZED_BUILD_REMOTE_SERVER=cross to use cross"
+                )
+            }
+
+            delegate.set_status(Some("Adding rustup target for cross-compilation"), cx);
+            log::info!("adding rustup target");
+            run_cmd(Command::new("rustup").args(["target", "add"]).arg(&triple)).await?;
 
-        delegate.set_status(Some("Compressing binary"), cx);
+            delegate.set_status(Some("Installing cargo-zigbuild for cross-compilation"), cx);
+            log::info!("installing cargo-zigbuild");
+            run_cmd(Command::new("cargo").args(["install", "--locked", "cargo-zigbuild"])).await?;
+
+            delegate.set_status(
+                Some(&format!(
+                    "Building remote binary from source for {triple} with Zig"
+                )),
+                cx,
+            );
+            log::info!("building remote binary from source for {triple} with Zig");
+            run_cmd(Command::new("cargo").args([
+                "zigbuild",
+                "--package",
+                "remote_server",
+                "--features",
+                "debug-embed",
+                "--target-dir",
+                "target/remote_server",
+                "--target",
+                &triple,
+            ]))
+            .await?;
+        };
 
         let mut path = format!("target/remote_server/{triple}/debug/remote_server").into();
         if !build_remote_server.contains("nocompress") {
+            delegate.set_status(Some("Compressing binary"), cx);
+
             run_cmd(Command::new("gzip").args([
                 "-9",
                 "-f",