From ac30a8b0dff0c3694472ad452142e1d1b352e850 Mon Sep 17 00:00:00 2001 From: Hiroki Tagato Date: Mon, 23 Jun 2025 05:23:17 +0900 Subject: [PATCH] Improve FreeBSD support (#33162) This PR contains a set of changes for improving FreeBSD support (#15309, #29550) and is a kind of follow up to the PR #20480 which added an initial support for FreeBSD. A summary of changes is as follows: - Add some more freebsd conditionals which seem missing in the previous PR. - Implement `anonymous_fd()` and `current_path()` functions for FreeBSD. - Improve detection of FreeBSD in telemetry and GPU detection. - Temporarily disable LiveKit/WebRTC support to make build succeed. - Remove support for flatpak since it is Linux-only packaging format. Adding `RUSTFLAGS="-C link-dead-code"` does not seem necessary anymore. It builds fine without the flag. Known issues: - Integrated terminal is painfully laggy and virtually unusable in my environment. This might be specific to my setup. - I cannot input Japanese using IME. When I type characters, they appear on the screen. But when I hit return key, they disappears. Seems the same issue as #15409. My environment is MATE desktop on X11 on FreeBSD 14.2 on Intel Core i5-7260U integrated graphics. P.S. For those who might be interested, a work-in-progress FreeBSD port and binary packages are available at https://github.com/tagattie/FreeBSD-Zed Release Notes: - N/A --------- Co-authored-by: Peter Tripp --- crates/cli/src/main.rs | 10 ++++---- crates/client/src/telemetry.rs | 12 ++++++++-- crates/docs_preprocessor/src/main.rs | 2 +- crates/feedback/src/system_specs.rs | 4 ++-- crates/fs/src/fs.rs | 23 ++++++++++++++++++- .../gpui/src/platform/blade/blade_renderer.rs | 5 +++- crates/livekit_client/Cargo.toml | 2 +- crates/livekit_client/src/lib.rs | 10 ++++---- 8 files changed, 50 insertions(+), 18 deletions(-) diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 752ecb2f010e60e409af9296f98e20234a29902a..a97985e69293b3b37f0eceab6183c869102975cc 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -134,7 +134,7 @@ fn main() -> Result<()> { util::prevent_root_execution(); // Exit flatpak sandbox if needed - #[cfg(any(target_os = "linux", target_os = "freebsd"))] + #[cfg(target_os = "linux")] { flatpak::try_restart_to_host(); flatpak::ld_extra_libs(); @@ -158,7 +158,7 @@ fn main() -> Result<()> { paths::set_custom_data_dir(dir); } - #[cfg(any(target_os = "linux", target_os = "freebsd"))] + #[cfg(target_os = "linux")] let args = flatpak::set_bin_if_no_escape(args); let app = Detect::detect(args.zed.as_deref()).context("Bundle detection")?; @@ -374,7 +374,7 @@ fn anonymous_fd(path: &str) -> Option { let file = unsafe { fs::File::from_raw_fd(fd) }; return Some(file); } - #[cfg(target_os = "macos")] + #[cfg(any(target_os = "macos", target_os = "freebsd"))] { use std::os::{ fd::{self, FromRawFd}, @@ -392,7 +392,7 @@ fn anonymous_fd(path: &str) -> Option { let file = unsafe { fs::File::from_raw_fd(fd) }; return Some(file); } - #[cfg(not(any(target_os = "linux", target_os = "macos")))] + #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "freebsd")))] { _ = path; // not implemented for bsd, windows. Could be, but isn't yet @@ -537,7 +537,7 @@ mod linux { } } -#[cfg(any(target_os = "linux", target_os = "freebsd"))] +#[cfg(target_os = "linux")] mod flatpak { use std::ffi::OsString; use std::path::PathBuf; diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index d6e5d6932c31c30ccd87d1d43f428e61236f16a3..4983fda5efa034c73326c627f555180afe753dfa 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -83,10 +83,14 @@ pub fn os_name() -> String { { "macOS".to_string() } - #[cfg(any(target_os = "linux", target_os = "freebsd"))] + #[cfg(target_os = "linux")] { format!("Linux {}", gpui::guess_compositor()) } + #[cfg(target_os = "freebsd")] + { + format!("FreeBSD {}", gpui::guess_compositor()) + } #[cfg(target_os = "windows")] { @@ -120,8 +124,12 @@ pub fn os_version() -> String { file } else if let Ok(file) = std::fs::read_to_string(&Path::new("/usr/lib/os-release")) { file + } else if let Ok(file) = std::fs::read_to_string(&Path::new("/var/run/os-release")) { + file } else { - log::error!("Failed to load /etc/os-release, /usr/lib/os-release"); + log::error!( + "Failed to load /etc/os-release, /usr/lib/os-release, or /var/run/os-release" + ); "".to_string() }; let mut name = "unknown"; diff --git a/crates/docs_preprocessor/src/main.rs b/crates/docs_preprocessor/src/main.rs index c76ffd52a5a53ad70c4ed12b76f8c45f00ba6366..8ec27a02a79180800d76cd1f483f91ee97d15c5e 100644 --- a/crates/docs_preprocessor/src/main.rs +++ b/crates/docs_preprocessor/src/main.rs @@ -171,7 +171,7 @@ fn find_action_by_name(name: &str) -> Option<&ActionDef> { fn find_binding(os: &str, action: &str) -> Option { let keymap = match os { "macos" => &KEYMAP_MACOS, - "linux" => &KEYMAP_LINUX, + "linux" | "freebsd" => &KEYMAP_LINUX, _ => unreachable!("Not a valid OS: {}", os), }; diff --git a/crates/feedback/src/system_specs.rs b/crates/feedback/src/system_specs.rs index a76855b20c02ee516dd5e385869fdcaa085cbf05..7c002d90e94ed5c44a1076aac2788fc8d1150eaa 100644 --- a/crates/feedback/src/system_specs.rs +++ b/crates/feedback/src/system_specs.rs @@ -133,7 +133,7 @@ impl Display for SystemSpecs { } fn try_determine_available_gpus() -> Option { - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "freebsd"))] { return std::process::Command::new("vulkaninfo") .args(&["--summary"]) @@ -152,7 +152,7 @@ fn try_determine_available_gpus() -> Option { }) .or(Some("Failed to run `vulkaninfo --summary`".to_string())); } - #[cfg(not(target_os = "linux"))] + #[cfg(not(any(target_os = "linux", target_os = "freebsd")))] { return None; } diff --git a/crates/fs/src/fs.rs b/crates/fs/src/fs.rs index 9a5aa8e1251c4b03e29c5b0d047669f51e1f10bb..a76ccee2bf8374429f57f28f729d5e4e44046ec9 100644 --- a/crates/fs/src/fs.rs +++ b/crates/fs/src/fs.rs @@ -272,7 +272,7 @@ impl FileHandle for std::fs::File { Ok(path) } - #[cfg(any(target_os = "linux", target_os = "freebsd"))] + #[cfg(target_os = "linux")] fn current_path(&self, _: &Arc) -> Result { let fd = self.as_fd(); let fd_path = format!("/proc/self/fd/{}", fd.as_raw_fd()); @@ -287,6 +287,27 @@ impl FileHandle for std::fs::File { Ok(new_path) } + #[cfg(target_os = "freebsd")] + fn current_path(&self, _: &Arc) -> Result { + use std::{ + ffi::{CStr, OsStr}, + os::unix::ffi::OsStrExt, + }; + + let fd = self.as_fd(); + let mut kif: libc::kinfo_file = unsafe { std::mem::zeroed() }; + kif.kf_structsize = libc::KINFO_FILE_SIZE; + + let result = unsafe { libc::fcntl(fd.as_raw_fd(), libc::F_KINFO, &mut kif) }; + if result == -1 { + anyhow::bail!("fcntl returned -1".to_string()); + } + + let c_str = unsafe { CStr::from_ptr(kif.kf_path.as_ptr()) }; + let path = PathBuf::from(OsStr::from_bytes(c_str.to_bytes())); + Ok(path) + } + #[cfg(target_os = "windows")] fn current_path(&self, _: &Arc) -> Result { anyhow::bail!("unimplemented") diff --git a/crates/gpui/src/platform/blade/blade_renderer.rs b/crates/gpui/src/platform/blade/blade_renderer.rs index 6fe1cfc33cb7cc05e7ba69b9e2df89940d29e700..cac47434ae308f7de7123baf26527ccb0da3321d 100644 --- a/crates/gpui/src/platform/blade/blade_renderer.rs +++ b/crates/gpui/src/platform/blade/blade_renderer.rs @@ -421,7 +421,10 @@ impl BladeRenderer { /// Like `update_drawable_size` but skips the check that the size has changed. This is useful in /// cases like restoring a window from minimization where the size is the same but the /// renderer's swap chain needs to be recreated. - #[cfg_attr(any(target_os = "macos", target_os = "linux"), allow(dead_code))] + #[cfg_attr( + any(target_os = "macos", target_os = "linux", target_os = "freebsd"), + allow(dead_code) + )] pub fn update_drawable_size_even_if_unchanged(&mut self, size: Size) { self.update_drawable_size_impl(size, true); } diff --git a/crates/livekit_client/Cargo.toml b/crates/livekit_client/Cargo.toml index 67a504ed6cb217bb510e5494280048d4c5855371..2762d61f8919711637bf7971d1e59b9bfa9b8845 100644 --- a/crates/livekit_client/Cargo.toml +++ b/crates/livekit_client/Cargo.toml @@ -39,7 +39,7 @@ tokio-tungstenite.workspace = true util.workspace = true workspace-hack.workspace = true -[target.'cfg(not(all(target_os = "windows", target_env = "gnu")))'.dependencies] +[target.'cfg(not(any(all(target_os = "windows", target_env = "gnu"), target_os = "freebsd")))'.dependencies] libwebrtc = { rev = "80bb8f4c9112789f7c24cc98d8423010977806a6", git = "https://github.com/zed-industries/livekit-rust-sdks" } livekit = { rev = "80bb8f4c9112789f7c24cc98d8423010977806a6", git = "https://github.com/zed-industries/livekit-rust-sdks", features = [ "__rustls-tls" diff --git a/crates/livekit_client/src/lib.rs b/crates/livekit_client/src/lib.rs index c35c83f228a59a9627ca6787d05f4e140261f8d5..d6074f6edbbe9deaaafb6fa4bbee96a402c8fe53 100644 --- a/crates/livekit_client/src/lib.rs +++ b/crates/livekit_client/src/lib.rs @@ -6,32 +6,32 @@ pub use remote_video_track_view::{RemoteVideoTrackView, RemoteVideoTrackViewEven #[cfg(not(any( test, feature = "test-support", - all(target_os = "windows", target_env = "gnu") + any(all(target_os = "windows", target_env = "gnu"), target_os = "freebsd") )))] mod livekit_client; #[cfg(not(any( test, feature = "test-support", - all(target_os = "windows", target_env = "gnu") + any(all(target_os = "windows", target_env = "gnu"), target_os = "freebsd") )))] pub use livekit_client::*; #[cfg(any( test, feature = "test-support", - all(target_os = "windows", target_env = "gnu") + any(all(target_os = "windows", target_env = "gnu"), target_os = "freebsd") ))] mod mock_client; #[cfg(any( test, feature = "test-support", - all(target_os = "windows", target_env = "gnu") + any(all(target_os = "windows", target_env = "gnu"), target_os = "freebsd") ))] pub mod test; #[cfg(any( test, feature = "test-support", - all(target_os = "windows", target_env = "gnu") + any(all(target_os = "windows", target_env = "gnu"), target_os = "freebsd") ))] pub use mock_client::*;