在 MCU 上,LVGL 没有任何依赖:把编译器指向源码就可以了。而一旦来到 MPU,情况很快就变了:
在 Linux 上构建可能会牵扯进 Wayland、libdrm、EGL、OpenGL ES、xkbcommon、libinput、FreeType 等等。
更麻烦的是,具体牵扯进哪些库,取决于你在 lv_conf.h 里打开了什么。
手工把这份清单写进自己的构建脚本既繁琐又容易出错,而且只要有人改动一个配置选项,它立刻就过时了。
所以 LVGL v9.6 替你把它记录下来。安装 LVGL 时会一并装上 lvgl.pc 和 lvglConfig.cmake,
里面已经列出了它编译时链接的每一个库。基于它构建应用因此变成了一行命令:
gcc main.c -o main $(pkg-config --cflags --static --libs lvgl)bash无论用哪种方式,你都不需要自己维护一份依赖清单;即使换一套功能集重新构建 LVGL,同样的这几行依然有效。
第一篇介绍了 LVGL 如何解析 lv_conf.h 来自动查找并拉取依赖。
这是那项工作的第二个回报:既然 LVGL 已经清楚地知道自己需要什么,它就可以把这份信息传递给所有基于它构建的人。
链接已安装库的两种方式#
假设你已经把 LVGL 构建并安装为静态库,并启用了 SDL2 和 FreeType。要编译一个小程序来链接它, 编译器需要三样东西:LVGL 的头文件、LVGL 库本身,以及 LVGL 依赖的其他所有库。 在 Linux 上通常有两种方式把这三样交给编译器,LVGL 现在都支持。
第一种是 pkg-config。库会安装一个简短的 .pc 文件来描述自己,你向 pkg-config 询问编译选项:
pkg-config --cflags --libs lvgl
# -I/usr/local/include -L/usr/local/lib -llvglbash把输出粘贴到应用的构建命令里就能完成链接。
第二种是 CMake 的 find_package。库会安装一个 lvglConfig.cmake 文件,你的项目直接使用它:
find_package(lvgl REQUIRED)
target_link_libraries(app PRIVATE lvgl::lvgl)cmake两者承担着同样的职责:必须列出 LVGL 依赖的每一个库。这一点在静态链接 LVGL 时尤为重要,
因为此时最终的链接过程必须一次性解析所有符号,包括来自 SDL2、FreeType 和 C 数学库的符号。
.pc 文件把它们记录在 Requires.private 和 Libs.private 字段中,CMake 则通过 find_dependency 调用来处理。
生成配置文件#
由于这份清单会随配置而变化,这两个文件都不可能作为固定文本发布,只能生成。 而这恰恰是最容易的一步:LVGL 为了构建自身,本来就要推导出自己的依赖,所以它只需要顺手记下用到的东西。
第一篇里介绍的依赖处理流程,已经会逐个遍历每一个可选库并决定如何满足它。
生成步骤就搭载在这个流程上。每解析完一个依赖,LVGL 就记录下游项目该如何找到同一个库:
供 find_package 使用的 CMake 包名,以及供 Requires 使用的 pkg-config 模块名。
配置结束时,这些记录会直接写入生成的 lvgl.pc 和 lvglConfig.cmake。
结果始终与你实际构建的内容一致:用 SDL2 和 FreeType 编译 LVGL,生成的 lvgl.pc 里就会列出 sdl2 和 freetype2。
在你的项目中使用#
这一切从外部完全看不到。你只需安装一次 LVGL,然后按平时的方式链接它。
先构建并安装。这里我们用 Kconfig defconfig 选定功能集,并安装到系统标准库目录中:
cmake -B build -GNinja \
-DLV_BUILD_USE_KCONFIG=ON \
-DLV_BUILD_DEFCONFIG_PATH=configs/defconfigs/linux.defconfig
cmake --build build
cmake --install buildbash这会把 lvgl.pc 和 lvglConfig.cmake 放到 pkg-config 和 CMake 默认搜索的标准路径下,与头文件和库文件放在一起。
应用程序本身就是一个普通的 LVGL 程序,和本系列第一篇中用到的完全一样。
#include <lvgl/lvgl.h>
int main(void)
{
lv_init();
lv_display_t * disp = lv_sdl_window_create(800, 600);
if(!disp) {
return 1;
}
lv_sdl_mouse_create();
lv_obj_t * button = lv_button_create(lv_screen_active());
lv_obj_t * label = lv_label_create(button);
lv_label_set_text_static(label, "Click Me!");
lv_obj_center(button);
while(1) {
lv_timer_handler();
lv_sleep_ms(5);
}
return 0;
}c用哪种方式构建都可以,取决于你的项目:
# --static 会一并引入 Requires.private 和 Libs.private
gcc main.c -o main $(pkg-config --cflags --static --libs lvgl)bash无论用哪种方式,你都不需要在自己的构建里重复一遍 LVGL 的依赖清单。你编译进 LVGL 的 SDL2 和 FreeType 会自动被引入。
小结#
这里其实没什么需要新发明的东西。这项工作的大部分,只是把 LVGL 本来就掌握的信息保留下来,
而不是在构建结束后把它们丢掉。换来的好处是少维护一份清单:无论 LVGL 是用什么构建出来的,
pkg-config 和 find_package 都会把它交到你的编译器手里。
在最后一篇中,我们会把这些生成的文件交给包管理器。我们将在一个全新的 Ubuntu 系统上添加 LVGL 软件源,
只用 apt 就让同一个程序跑起来。
- 50 行代码上手 LVGL v9.6
- 2安装 LVGL,依赖一并奉上当前位置
- 3apt install lvgl
- 4在 RZ/G2L 上用 Ubuntu 运行 LVGL


