生态、安装与第一个窗口
GPUI 是 Zed 团队维护的 Rust 桌面 UI 框架。它的目标不是包一层 WebView,而是直接使用平台窗口、文本系统与 GPU 渲染后端来绘制原生桌面应用。官方文档把它描述为混合 immediate/retained mode 的 GPU 加速 UI 框架,这意味着你会在 render 中声明当前状态应该长成什么样,同时由 GPUI 保留实体、窗口、焦点、事件和资源等运行时状态。
什么时候适合选 GPUI
适合:
- 你想写 Rust 原生桌面应用,并且愿意接受较新的 API。
- 应用需要复杂文本、键盘操作、高刷新率 UI 或类编辑器交互。
- 团队能承受 pre-1.0 框架的升级成本。
- 你希望从 Zed 的真实工程实践中学习 UI 架构。
不太适合:
- 你需要非常稳定的长期 ABI/API。
- 你需要大量现成业务组件、成熟设计器或企业级可视化工具。
- 你只想把网页快速打包成桌面端,这类场景 Tauri 往往更直接。
依赖选择
GPUI 本身可以直接使用 gpui 和 gpui_platform。本教程以 GitHub 上 zed-industries/zed 的最新 main 为准,不以 crates.io 的滞后版本为准。官方 README 可能展示 version = "*" 的发布版写法,但当前实践应改成 git 依赖;为了让构建可复现,建议锁定到你验证过的 Zed 提交:
[dependencies]
gpui = { git = "https://github.com/zed-industries/zed", rev = "04de6dab7c890d815e316f2f9554f9eeeaf8ebb2" }
gpui_platform = { git = "https://github.com/zed-industries/zed", rev = "04de6dab7c890d815e316f2f9554f9eeeaf8ebb2", features = ["font-kit", "wayland", "x11"] }
如果你只在单平台构建,可以按官方 README 缩减 gpui_platform features:
- macOS:
features = ["font-kit"] - Linux / FreeBSD:至少启用
wayland或x11 - Windows:通常不需要额外 feature
如果你想像 HiPoster 一样快速构建复杂表单、菜单、Tab、输入框、可拖拽分栏和主题,建议同时使用 gpui-component。
HiPoster 采用 git 依赖,和 GPUI Component 官方文档的安装方式一致:
[dependencies]
gpui = { git = "https://github.com/zed-industries/zed" }
gpui_platform = { git = "https://github.com/zed-industries/zed", features = ["font-kit"] }
gpui-component = { git = "https://github.com/longbridge/gpui-component" }
gpui-component-assets = { git = "https://github.com/longbridge/gpui-component" }
reqwest = { version = "0.12", features = ["json", "multipart"] }
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0"
directories = "6.0"
如果项目要用 gpui-component,还要注意组件库本身会跟随它验证过的 Zed 提交。2026-07-06 检查到 gpui-component main 为 372446c007672cabe1b8d9a2dba547f8c2646049,其 workspace 里固定的 Zed revision 是 1d217ee39d381ac101b7cf49d3d22451ac1093fe。这意味着:纯 GPUI 教程以 Zed 最新 main 为准;使用组件库时,以能同时编译 gpui-component 和你的应用的 Zed revision 为准。
平台准备
macOS:
- 安装 Xcode 或 Xcode Command Line Tools。
- GPUI 使用 Metal 渲染,打包
.app时还要处理Info.plist、图标和签名。
Linux:
- 启用
gpui_platform的wayland、x11或两者。 - 确认系统有图形栈、Vulkan/OpenGL 相关运行库和字体配置。
- 打包时按发行版处理
.desktop、图标和依赖。
Windows:
- 使用 MSVC toolchain。
- 安装 Visual Studio Build Tools 2022,并选择 Desktop development with C++。
- 从 Developer PowerShell for VS 2022 构建,避免找不到
cl.exe、SDK 或链接器。
最小窗口
一个 GPUI 应用的启动流程是:
- 创建
Application。 - 在
run回调里拿到App上下文。 - 调用
open_window创建窗口。 - 用
cx.new创建实现了Render的根视图。
use gpui::{div, prelude::*, px, size, App, Bounds, Context, Window};
use gpui::{WindowBounds, WindowOptions};
use gpui_platform::application;
struct HelloGpui;
impl Render for HelloGpui {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.size_full()
.flex()
.items_center()
.justify_center()
.text_xl()
.child("Hello GPUI")
}
}
fn main() {
application().run(|cx: &mut App| {
let bounds = Bounds::centered(None, size(px(800.), px(480.)), cx);
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|_, cx| cx.new(|_| HelloGpui),
)
.expect("open window");
cx.activate(true);
});
}
使用 GPUI Component 的启动方式
HiPoster 使用 GPUI Component,因此入口多了三件事:
- 用
gpui_platform::application()选择平台后端。 - 调用
gpui_component::init(cx)初始化组件库的主题和全局设置。 - 用
Root::new(view, window, cx)包住窗口第一层视图。
use gpui::*;
use gpui_component::{button::*, Root};
struct HelloComponent;
impl Render for HelloComponent {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
div()
.v_flex()
.size_full()
.items_center()
.justify_center()
.gap_2()
.child("Hello GPUI Component")
.child(Button::new("ok").primary().label("OK"))
}
}
fn main() {
gpui_platform::application().run(move |cx| {
gpui_component::init(cx);
cx.spawn(async move |cx| {
cx.open_window(WindowOptions::default(), |window, cx| {
let view = cx.new(|_| HelloComponent);
cx.new(|cx| Root::new(view, window, cx))
})
.expect("open window");
})
.detach();
});
}
这个版本更接近 HiPoster,也更适合后面教程里的复杂应用。
GPUI 的三个层次
学习 GPUI 时可以把它分成三层:
Entity:有身份的状态,由 GPUI 运行时持有。View:实现Render的Entity,每次需要绘制时返回元素树。Element:具体绘制与布局单元,例如div()、Button、Input、TabBar。
这三个层次决定了 GPUI 的日常写法:状态放在结构体里,结构体由 cx.new 变成 Entity<T>,界面由 render 根据状态生成元素树。下一章我们把这个模型落到一个真实项目结构里。