编译构建LVGL-Rust,用rust开发LVGL

本文最后更新于 2024年2月12日 凌晨

这是一个使用lvgl/lv_binding_rust使用Rust开发LVGL的尝试。

相比于slint要求的300KB ram,Lvgl只要求最低16K,因此它在嵌入式的地位目前还是无法取代的。

那么,开始吧!

编译构建LVGL-Rust

Step1.准备工作

1.Ubuntu或者任意linux桌面环境,WSL也可,我使用的是Ubuntu20.04

为什么非得Linux呢?如果你想节省一个下午,那就装一个Linux吧!lvgl/lv_binding_rust项目的setup根本没有为Windows考虑,在Windows上用SDL跑通模拟器也相当麻烦!除非你有足够的能力,否则不要使用Windows。Mac倒可以尝试,本文不涉及。

2.VSCode,rust analyser插件等

3.良好的网络环境,可以方便地使用github

3.git和使用git的能力

Step2.跑通embedded-graphics

Lvgl底层使用embedded-graphics,无论是模拟器还是屏幕。所以先跑通embedded-graphics能省去排查问题的时间。这里先跑通模拟器。

embedded-graphics/embedded-graphics: A no_std graphics library for embedded applications

模拟器:

embedded-graphics/simulator

配置SDL

Linux (apt)

1
sudo apt install libsdl2-dev

macOS (brew)

1
brew install sdl2

使用 Apple 芯片或自定义安装目录的用户需要设置 LIBRARY_PATH,以便链接器找到已安装的 SDL2 包:

1
export LIBRARY_PATH="$LIBRARY_PATH:$(brew --prefix)/lib"

更多信息: SDL2 documentation.

Windows

如果你只想跑embedded-graphics,可以尝试。Windows 的安装过程比较复杂,但是确实可以。请参阅 the Rust-SDL2 crate’s README以获取说明。有多种方法可以使它工作,但可能最简单的方法是按照这里所示的复制二进制文件。

尝试运行

配置好后,我们克隆工程到本地:

1
git clone https://github.com/embedded-graphics/examples.git

然后用Vscode打开这个目录下的examples/eg-07

![2024-02-11 23-45-56](lvgl-rust-build/2024-02-11 23-45-56.png)

命令行运行cargo run –example demo-analog-clock,也可以直接在vscode里面运行这个main,查看是否能出来模拟界面。

2024-02-11 23-47-54

如果不行,请按照log来排查再进行下一步。

Step3.跑通LVGL-Rust

此篇建议参考readme:lvgl/lv_binding_rust

搭建工程

cargo new一个项目。Cargo.toml依赖如下

1
2
3
4
5
6
7
8
9
10
[dependencies]
lvgl = { version = "0.6.2", features = ["alloc"] }
lvgl-sys = "0.6.2"
cty = "0.2.2"
embedded-graphics = "0.7.1"
cstr_core = { version = "0.2.6", default-features = false, features = ["alloc"] }
bitflags = "2.3.2"
paste = "1.0.12"
ctor = "0.2.2"
embedded-graphics-simulator = "0.3.0"

(我这里使用的是0.6.2,请注意你的版本,截止至2024年2月,该项目已有10个月没有新release,3个月没有人维护。)

Release Release 0.6.2这里下载source code压缩包,将里面的demo.rs代码复制到main.rs

建立include文件夹,将压缩包里的examples/include文件夹的文件复制过来,这是lv_conf,和c语言配置LVGL是一样的,但是注意修改完后要重新编译这个crate或者全部重新编译,它并不会识别这文件的变更。否则修改无效。

建立fonts文件夹,把压缩包里的fonts复制过来。

lvgl建议开启alloc featue,这样才能使用label.set_text(CString::new("Loading...")

但是否使用lvgl_alloc看君习惯,这是lvgl内部实现的堆内存管理器。

编译

安装Clang

1
sudo apt install build-essential llvm clang

构建需要设置以下环境变量:

DEP_LV_CONFIG_PATH:包含用于配置 LVGL 库的 lv_conf.h 头文件的目录路径。

(可选)LVGL_FONTS_DIR:生成用于 LVGL 的自定义字体的目录。 使用方法请参阅文档。

(可选)LVGL_INCLUDE:如果使用驱动程序功能,则在构建期间包含的 C 头文件,以逗号分隔。 默认为/usr/include、/usr/local/include。

(可选)LVGL_LINK:如果使用驱动程序功能,则在构建期间链接的 C 库,以逗号分隔。 默认为 SDL2。

编译命令:

1
DEP_LV_CONFIG_PATH=`pwd`/xxx/xxx cargo build

rust-analyzer插件

按照上面的进行,rust语法提示是加载不出来的,下面的状态栏的rust-analyzer服务还是个错误,接下来我们解决插件的问题。

进入settings,找到rust-analyzer插件。点击Edit in settings.json

2024-02-11 23-52-26

settings.json中我们要设置环境变量,因为我没找到这些环境变量执行命令时是在哪个目录(似乎不是项目根目录),而且settings.json也是在插件下的而不是项目下的,我暂且使用绝对路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"editor.fontSize": 20,
"rust-analyzer.cargo.extraEnv": {
"DEP_LV_CONFIG_PATH":"/home/your_user_name/path/to/your/dir/include",
"LVGL_FONTS_DIR":"/home/your_user_name/path/to/your/dir/fonts"
},
"rust-analyzer.runnables.extraEnv": {
"DEP_LV_CONFIG_PATH":"/home/your_user_name/path/to/your/dir/include",
"LVGL_FONTS_DIR":"/home/your_user_name/path/to/your/dir/fonts"
},
"rust-analyzer.check.extraEnv": {
"DEP_LV_CONFIG_PATH":"/home/your_user_name/path/to/your/dir/include",
"LVGL_FONTS_DIR":"/home/your_user_name/path/to/your/dir/fonts
},
"rust-analyzer.server.extraEnv": {
"DEP_LV_CONFIG_PATH":"/home/your_user_name/path/to/your/dir/include",
"LVGL_FONTS_DIR":"/home/your_user_name/path/to/your/dir/fonts"
},
"diffEditor.hideUnchangedRegions.enabled": true,
"cmake.configureOnOpen": false
}

然后稍等一会等插件加载好,就有代码提示和run啦!点击run,成功!

2024-02-12 00-10-48

再跑个example bar

![2024-02-12 00-21-11](lvgl-rust-build/2024-02-12 00-21-11.png)

另外,用lvgl内置字体需开启nightly feature。

Step4.嵌入式环境

lvgl/lv_binding_rust有这么个内容:

我们在构建时使用 bindgen 来生成 LittleVGL 的绑定。在为 no_std 构建时,cargo 有一个问题,所以我们需要使用一个变通方法来构建 lvgl-rs。该问题正在rust-lang/cargo#7915跟踪。

1
DEP_LV_CONFIG_PATH=`pwd` cargo build -Zfeatures=build_dep

unsafe_no_autoinit 特性也必须在为裸机目标构建时启用。请参阅 Cargo.toml 中的文档以了解使用说明。

原文:

We make use of bindgen for generating the bindings to LittlevGL at build time. There is a problem in cargo when building for no_std, so we need to use a workaround to build “lvgl-rs”. The mainstrem issue in cargo is being tracked at rust-lang/cargo#7915.

1
$ DEP_LV_CONFIG_PATH=`pwd` cargo build -Zfeatures=build_dep

The unsafe_no_autoinit feature must also be enabled when building for baremetal targets. See its documentation in Cargo.toml for notes on usage.

其它

截止至2024年2月,该项目已有10个月没有新release(最新release版本为0.6.2),3个月没有人维护了。

下一个版本0.7.0的issue汇总:Tracking issue for 0.7.0

master分支可能因为正在施工,直接编译的话会出错。

image-20240212010615191

这是因为函数改了,但是demo没改。

之前:

1
2
3
4
5
6
fn set_width(&mut self, w: u32) -> LvResult<()> {
unsafe {
lvgl_sys::lv_obj_set_width(self.raw()?.as_mut(), w as lvgl_sys::lv_coord_t);
}
Ok(())
}

现在:

1
2
3
4
5
fn set_width(&mut self, w: u32) {
unsafe {
lvgl_sys::lv_obj_set_width(self.raw().as_mut(), w as lvgl_sys::lv_coord_t);
}
}

但是现在实现的Features也差不多了,主要是lv_fs没有实现,没法显示图片。

具体坑多不多,还得试试才知道,目前看issue的话,还是有点让人担心。

目前似乎只能让lvgl和embedded-graphics分管不同的界面,来达到更好的效果。


编译构建LVGL-Rust,用rust开发LVGL
https://decaday.github.io/blog/lvgl-rust-build/
作者
星期十
发布于
2024年2月11日
更新于
2024年2月12日
许可协议