diff --git a/Cargo.lock b/Cargo.lock index 302c1cc6ea..ce6bdffefb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13213,6 +13213,7 @@ dependencies = [ "fs", "futures 0.3.31", "git", + "git2", "git_hosting_providers", "gpui", "gpui_tokio", diff --git a/crates/remote/src/ssh_session.rs b/crates/remote/src/ssh_session.rs index 2653a19bd9..ff51cfda71 100644 --- a/crates/remote/src/ssh_session.rs +++ b/crates/remote/src/ssh_session.rs @@ -314,20 +314,6 @@ pub struct SshPlatform { pub arch: &'static str, } -impl SshPlatform { - pub fn triple(&self) -> Option { - Some(format!( - "{}-{}", - self.arch, - match self.os { - "linux" => "unknown-linux-gnu", - "macos" => "apple-darwin", - _ => return None, - } - )) - } -} - pub trait SshClientDelegate: Send + Sync { fn ask_password(&self, prompt: String, tx: oneshot::Sender, cx: &mut AsyncApp); fn get_download_params( @@ -2068,6 +2054,7 @@ impl SshRemoteConnection { cx: &mut AsyncApp, ) -> Result { use smol::process::{Command, Stdio}; + use std::env::VarError; async fn run_cmd(command: &mut Command) -> Result<()> { let output = command @@ -2082,70 +2069,37 @@ impl SshRemoteConnection { Ok(()) } + let triple = format!( + "{}-{}", + self.ssh_platform.arch, + match self.ssh_platform.os { + "linux" => "unknown-linux-musl", + "macos" => "apple-darwin", + _ => anyhow::bail!("can't cross compile for: {:?}", self.ssh_platform), + } + ); + let mut rust_flags = match std::env::var("RUSTFLAGS") { + Ok(val) => val, + Err(VarError::NotPresent) => String::new(), + Err(e) => { + log::error!("Failed to get env var `RUSTFLAGS` value: {e}"); + String::new() + } + }; + if self.ssh_platform.os == "linux" { + rust_flags.push_str(" -C target-feature=+crt-static"); + } + if build_remote_server.contains("mold") { + rust_flags.push_str(" -C link-arg=-fuse-ld=mold"); + } + if self.ssh_platform.arch == std::env::consts::ARCH && self.ssh_platform.os == std::env::consts::OS { delegate.set_status(Some("Building remote server binary from source"), cx); log::info!("building remote server binary from source"); - run_cmd(Command::new("cargo").args([ - "build", - "--package", - "remote_server", - "--features", - "debug-embed", - "--target-dir", - "target/remote_server", - ])) - .await?; - - delegate.set_status(Some("Compressing binary"), cx); - - run_cmd(Command::new("gzip").args([ - "-9", - "-f", - "target/remote_server/debug/remote_server", - ])) - .await?; - - let path = std::env::current_dir()?.join("target/remote_server/debug/remote_server.gz"); - return Ok(path); - } - let Some(triple) = self.ssh_platform.triple() else { - anyhow::bail!("can't cross compile for: {:?}", self.ssh_platform); - }; - smol::fs::create_dir_all("target/remote_server").await?; - - if build_remote_server.contains("cross") { - #[cfg(target_os = "windows")] - use util::paths::SanitizedPath; - - delegate.set_status(Some("Installing cross.rs for cross-compilation"), cx); - log::info!("installing cross"); - run_cmd(Command::new("cargo").args([ - "install", - "cross", - "--git", - "https://github.com/cross-rs/cross", - ])) - .await?; - - delegate.set_status( - Some(&format!( - "Building remote server binary from source for {} with Docker", - &triple - )), - cx, - ); - log::info!("building remote server binary from source for {}", &triple); - - // On Windows, the binding needs to be set to the canonical path - #[cfg(target_os = "windows")] - let src = - SanitizedPath::from(smol::fs::canonicalize("./target").await?).to_glob_string(); - #[cfg(not(target_os = "windows"))] - let src = "./target"; run_cmd( - Command::new("cross") + Command::new("cargo") .args([ "build", "--package", @@ -2157,73 +2111,126 @@ impl SshRemoteConnection { "--target", &triple, ]) - .env( - "CROSS_CONTAINER_OPTS", - format!("--mount type=bind,src={src},dst=/app/target"), - ), + .env("RUSTFLAGS", &rust_flags), ) .await?; } else { - let which = cx - .background_spawn(async move { which::which("zig") }) - .await; - - if which.is_err() { - #[cfg(not(target_os = "windows"))] - { - 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" - ) - } + if build_remote_server.contains("cross") { #[cfg(target_os = "windows")] - { - anyhow::bail!( - "zig not found on $PATH, install zig (use `winget install -e --id zig.zig` or see https://ziglang.org/learn/getting-started or use zigup) or pass ZED_BUILD_REMOTE_SERVER=cross to use cross" - ) + use util::paths::SanitizedPath; + + delegate.set_status(Some("Installing cross.rs for cross-compilation"), cx); + log::info!("installing cross"); + run_cmd(Command::new("cargo").args([ + "install", + "cross", + "--git", + "https://github.com/cross-rs/cross", + ])) + .await?; + + delegate.set_status( + Some(&format!( + "Building remote server binary from source for {} with Docker", + &triple + )), + cx, + ); + log::info!("building remote server binary from source for {}", &triple); + + // On Windows, the binding needs to be set to the canonical path + #[cfg(target_os = "windows")] + let src = + SanitizedPath::from(smol::fs::canonicalize("./target").await?).to_glob_string(); + #[cfg(not(target_os = "windows"))] + let src = "./target"; + run_cmd( + Command::new("cross") + .args([ + "build", + "--package", + "remote_server", + "--features", + "debug-embed", + "--target-dir", + "target/remote_server", + "--target", + &triple, + ]) + .env( + "CROSS_CONTAINER_OPTS", + format!("--mount type=bind,src={src},dst=/app/target"), + ) + .env("RUSTFLAGS", &rust_flags), + ) + .await?; + } else { + let which = cx + .background_spawn(async move { which::which("zig") }) + .await; + + if which.is_err() { + #[cfg(not(target_os = "windows"))] + { + 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" + ) + } + #[cfg(target_os = "windows")] + { + anyhow::bail!( + "zig not found on $PATH, install zig (use `winget install -e --id zig.zig` or 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("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, + ]) + .env("RUSTFLAGS", &rust_flags), + ) + .await?; } - - 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("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 bin_path = Path::new("target") + .join("remote_server") + .join(&triple) + .join("debug") + .join("remote_server"); - let mut path = format!("target/remote_server/{triple}/debug/remote_server").into(); - if !build_remote_server.contains("nocompress") { + let path = if !build_remote_server.contains("nocompress") { delegate.set_status(Some("Compressing binary"), cx); #[cfg(not(target_os = "windows"))] { - run_cmd(Command::new("gzip").args([ - "-9", - "-f", - &format!("target/remote_server/{}/debug/remote_server", triple), - ])) - .await?; + run_cmd(Command::new("gzip").args(["-9", "-f", &bin_path.to_string_lossy()])) + .await?; } #[cfg(target_os = "windows")] { @@ -2237,17 +2244,19 @@ impl SshRemoteConnection { "a", "-tgzip", &gz_path, - &format!("target/remote_server/{}/debug/remote_server", triple), + &bin_path.to_string_lossy(), ])) .await?; } - path = std::env::current_dir()?.join(format!( - "target/remote_server/{triple}/debug/remote_server.gz" - )); - } + let mut archive_path = bin_path; + archive_path.set_extension("gz"); + std::env::current_dir()?.join(archive_path) + } else { + bin_path + }; - return Ok(path); + Ok(path) } } diff --git a/crates/remote_server/Cargo.toml b/crates/remote_server/Cargo.toml index b780f57ab4..443c47919f 100644 --- a/crates/remote_server/Cargo.toml +++ b/crates/remote_server/Cargo.toml @@ -37,6 +37,7 @@ fs.workspace = true futures.workspace = true git.workspace = true git_hosting_providers.workspace = true +git2 = { workspace = true, features = ["vendored-libgit2"] } gpui.workspace = true gpui_tokio.workspace = true http_client.workspace = true @@ -85,7 +86,7 @@ node_runtime = { workspace = true, features = ["test-support"] } project = { workspace = true, features = ["test-support"] } remote = { workspace = true, features = ["test-support"] } language_model = { workspace = true, features = ["test-support"] } -lsp = { workspace = true, features=["test-support"] } +lsp = { workspace = true, features = ["test-support"] } unindent.workspace = true serde_json.workspace = true zlog.workspace = true @@ -95,4 +96,4 @@ cargo_toml.workspace = true toml.workspace = true [package.metadata.cargo-machete] -ignored = ["rust-embed", "paths"] +ignored = ["git2", "rust-embed", "paths"]