解剖 Robius Demo 之 Wechat 应用
上一节回顾
在Robius:用 Rust 开发多平台应用一文介绍了 Robius 的愿景和未来的一些规划,Robius 是一个完全开源的、去中心化的、由社区驱动的项目,旨在让 Rust 成为多平台应用开发的理想选择,本章节,我们一起来解剖 Robius 里的 Wechat 应用 Demo。
Makepad 项目介绍
在开始解剖 Wechat 项目之前,我们先来学习一下所使用的 Makepad 项目的基本知识。
- Makepad 包括 Makepad Framework 和 Makepad Studio。
- Makepad Framework 是一个跨平台的
UI 框架。包括多个 crate,顶级 crate 是 makepad-widgets。有关 Makepad Framework 的更多详细解释,请参阅makepad-widgets组件介绍。 - Makepad Studio 是使用 Makepad Framework 构建的一个
IDE 原型。它仍然在重度开发中,但我们的最终目标是创建一个可以在运行时更改应用程序设计的 IDE。Makepad Studio 的主 crate 是 makepad-studio。有关更多信息,请参阅makepad-studio章节介绍。
makepad-widgets介绍
- 这是 Makepad Framework 的顶级 crate,它是一个为 Rust 开发的下一代 UI 框架。使用 Makepad Framework 构建的应用程序可以在本地和 web 上运行,完全在 GPU 上渲染,并支持名为 live design 的新颖功能。
- Live design 意味着 Makepad Framework 为其他应用程序(例如 IDE)提供基础设施,使其可以挂载到您的应用程序并在线运行时更改其设计。为此,Makepad Framework 应用程序的样式使用 DSL 描述。编写的代码通过使用 proc_macros 与主要 Rust 代码紧密集成。
- 一个具有 live design 意识的 IDE 检测
DSL代码中发生的更改,而不是 Rust 代码,因此,它可以在触发完整重新编译之前将更改发送到应用程序,使其更新自身。(makepad-studio crate 包含一个可以最终实现此功能的 IDE 原型,但仍在进行大量开发。) - 此 crate 包含一组基本控件,几乎每个应用程序都需要。在撰写本文时,支持的控件有:窗口、下拉菜单、停靠栏、分割器、标签栏、框架、滚动条、文件树、标签、按钮、复选框、单选框、颜色选择器
- 除了这些控件外,此 crate 还包含两个低级 crate 的重导出,分别是 makepad-draw-2d(包含所有与绘制应用程序相关的代码)和 makepad-platform(包含所有特定于平台的代码)。最后,它包含一组基本字体。
简而言之,要在 Makepad Framework 中构建应用程序,大多数时候,这个 crate 是您唯一需要的。
注意事项:尽管 Makepad 框架已经足够完整,可以让你使用它来编写自己的应用程序,但目前它
仍然处于激烈的开发阶段。目前,我们只支持Mac和Web(尽管我们很快就会添加对 Windows 和 Linux 的支持)。在此阶段,我们无法保证 API 的稳定性。请在使用 Makepad 框架为自己的应用程序时牢记这一点。最后,我们在字体渲染、国际化等领域仍然缺乏许多功能。
makepad-studio介绍
- 这是一个使用 Makepad 框架编写的 IDE 原型。关于 Makepad 框架的解释,请参阅 makepad-widgets 组件介绍。
- 最终目标是将其开发成为一个支持实时设计意识的 IDE。这样的 IDE 能够检测到描述应用程序样式的 DSL 代码(而非本地 Rust 代码)发生更改时,无需重新编译,而是将更改发送到 DSL 代码的应用程序,使其自行更新。
- 尽管如此,这个组件目前
仍然处于激烈的开发阶段。在撰写本文时,它具有一个带有选项卡的工作栏系统,一个带有折叠的文件树,以及一个基本代码编辑器,支持语法高亮。我们目前的主要挑战是重新设计 IDE,使其具有适当的扩展模型和沙箱化。
环境准备
安装 Makepad
- 构建 Makepad 组件之前,首先,需要安装
Rust,Rust的安装指南请参考:https://www.rust-lang.org/tools/install - 本地构建通常会使用
stable版本的 Rust 工具链,然而,Makepad 在运行时生成的一些错误(尤其是来自 DSL 的错误)除非你使用nightly版本的 Rust 工具链,否则,不会包含行信息。此外,Makepad 的Web构建目前仅在nightly版本工作。因此,建议您使用nightly版本的 Rust 工具链来构建 Makepad。 - 对于非标准构建目标(
ios、android、wasm),需要安装一个名为cargo-makepad的构建工具,有两种安装方式。- 仓库安装:
git clone https://github.com/makepad/makepad.git && cd makepad && cargo install --path=./tools/cargo_makepad cargo安装:cargo install cargo-makepad(推荐用该方法,省心)
- 仓库安装:
cargo-makepad工具安装成功后,可根据平台所需安装相应的工具链,具体命令如下:1
2
3cargo makepad wasm install-toolchain
cargo makepad ios install-toolchain
cargo makepad android --abi=all install-toolchain
在 iOS 安装 makepad_wechat 应用
鉴于
iOS模拟器的安装过程相对较为复杂,本章节将仅针对iOS模拟器的安装进行讲解。而Android的安装过程类似,因此不再赘述。
clone源码1
git clone https://github.com/project-robius/makepad_wechat.git
iOS安装应用前准备在
iOS模拟器上安装应用1
2cd ~/makepad_wechat
cargo makepad ios --org=rs.robius --app=WeChat run-sim -p makepad_wechat --release在
iOS设备上安装应用1
2cd ~/makepad_wechat
cargo makepad ios --ios-version=16 --org-id=<ORGIDVALUE> --org=rs.robius --app=WeChat run-device -p makepad_wechat --release其中,
--org-id:这是位于~/Library/MobileDevice/Provisioning Profiles目录中的**.mobileprovision文件中的 ApplicationIdentifierPrefix的 值。它应该是一个 10 位数的字母数字值。 以下是在
iOS模拟器安装成功运行效果图
makepad_wechat 应用源码解读
源码结构分析

Demo 源码目录整体较为简洁,具体解析如下:
resources:资源目录,主要存放字体、图标、图片等。src: 源码目录,主要包含程序启动、模块定义以及数据交互等main.rs: 服务启动入口,实际上是调用app.rs的app_main方法。app.rs: 应用程序入口,由 Makepad 提供的app_main!宏提供服务,同时,使用live_design!来定义应用需要用到的相关组件以及布局。api.rs: 定义聊天应用相关结构体,例如,ChatEntry、MessagePreview、MessageDirection、MessageEntry和Db等,以及mock相关应用使用到的数据和方法。contacts: 定义联系人组件以及其相关布局discover: 定义发现组件以及其相关布局home: 定义首页(聊天列表)组件以及其相关布局profile: 定义我的组件以及其相关布局shared: 一些公共组件的定义,比如,header、搜索框、弹出菜单等等
项目依赖分析
从 Cargo.toml 文件分析,Demo 项目主要引入了 makepad-widgets 依赖。初步浏览了所有源代码,由于没有第三方服务相关调用,因此,暂不需要其他依赖。
1 | [dependencies] |
app.rs 框架分析
关键源码框架解读如下:
live_design!宏: 定义了一个live_design函数,该函数将一个Live DSL代码块注册到live系统中。宏中的代码被序列化为一个字符串,稍后由live系统解析。新创建的 Rust 结构体的字段被初始化为对应默认值,Makepad 的live系统应用该结构的Live DSL定义,覆盖所有Live DSL有定义的字段。导入了相关的模块和主题,并且定义应用相关组件及布局。app_main!(App): 定义了所有支持平台(Web、Android和桌面)的应用程序入口点。为了实现跨平台支持,代码必须是宏生成的,不能是一个简单的fn main()函数。struct App { ... }: 使用derive(Live)过程宏来生成将live_design DSL反序列化为App结构体的粘合剂。在 Makepad 的术语中,这被称为将live DSL应用到Rust 结构体,该示例包含了两个字段:一个WidgetRef类型的ui,用于存储组件;一个HashMap类型的navigation_destinations,用于存储导航目标。impl LiveHook for App { ... }: 为App实现LiveHook特质,定义了before_live_design钩子函数,该函数在生命周期开始前执行,App的LiveHook实现允许在连接到Live DSL的各种对象生命周期阶段时进行挂载。。impl AppMain for App { ... }:AppMain是为App实现的特质。它提供了从系统进入应用程序的唯一入口点:fn handle_event。该特质提供了鼠标、计时器和滑动事件,这些事件被传递到UI树中进行处理。该示例中,Event::Draw事件是系统请求应用程序生成必要渲染结构的地方。
1 | live_design! { |
由于 Makepad 文档较少,我们需要花费更多时间来分析其底层设计。
以上就是关于
Robius Demo中的如果您喜欢这篇文章,欢迎关注微信公众号《猿禹宙》、点赞、转发和赞赏。每一位读者的认可都是我持续创作的动力。
