从零开始在 Linux 上编译运行 lvgljs 图形界面项目

项目简介

lvgljs 是一个用 JavaScript/React 语法操作 LVGL(轻量级通用图形库)的开源项目。它将 LVGL 的 C 语言 UI 组件封装成了类似 React 的组件化接口,开发者可以用 JSX 编写嵌入式 UI,渲染到 SDL2 模拟器或真实的嵌入式设备上。

技术栈:

  • JavaScript 运行时:txiki.js(基于 QuickJS + libuv + curl)
  • 图形引擎:LVGL(嵌入式 GUI 库)
  • 前端框架:自定义 React Reconciler(virtual DOM → LVGL C 调用)
  • 构建工具:CMake(native 层) + esbuild(JS 层)

一、环境准备

1.1 安装系统依赖

bash 复制代码
sudo apt update
sudo apt install -y \
    git \
    cmake \
    nodejs \
    npm \
    libsdl2-dev \
    libcurl4-openssl-dev \
    libffi-dev \
    libtool \
    autoconf \
    automake \
    texinfo

各依赖说明:

包名 用途
git 克隆代码、拉取 git 子模块
cmake CMake >= 3.16,构建 native 层
nodejs / npm 运行 esbuild、打包 JS bundle
libsdl2-dev SDL2 模拟器显示驱动
libcurl4-openssl-dev txiki.js HTTP 客户端依赖
libffi-dev 外部 FFI 库(解决 CMake 4.x 兼容问题)
libtool autoconf automake texinfo libffi 源码构建工具链

1.2 克隆代码并初始化子模块

bash 复制代码
git clone https://github.com/lvgl/lv_binding_js.git
cd lv_binding_js
git submodule update --recursive --init

这一步会拉取三个关键子模块:

  • deps/lvgl --- LVGL 图形库
  • deps/lv_drivers --- LVGL 输入/显示驱动
  • deps/txiki --- JavaScript 运行时

二、修改构建配置(关键步骤)

项目的 Makefile 设计时针对标准 CMake 版本,在Ubuntu26.04系统上,CMake 4.x 环境下需要做两处修改。

打开项目根目录的 Makefile,找到 simulator 目标,将 cmake 命令修改为:

makefile 复制代码
simulator:
	@mkdir -p $(BUILD_SIM)
	cmake -B "$(BUILD_SIM)" -DCMAKE_BUILD_TYPE=Simulator  -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DUSE_EXTERNAL_FFI=ON "-DCMAKE_C_FLAGS=-Wno-error=discarded-qualifiers -Wno-error=unterminated-string-initialization"
	cmake --build $(BUILD_SIM) -j

修改说明:

参数 原因
-DUSE_EXTERNAL_FFI=ON CMake 4.x 与 libffi 的 autotools 构建系统不兼容,使用系统已安装的 libffi
-Wno-error=discarded-qualifiers txiki 依赖的 quickjs 代码中有 const 限定符警告被 -Werror 拦截
-Wno-error=unterminated-string-initialization 同上,quickjs 中字符串初始化警告被当作错误

三、编译并运行

3.1 一键编译模拟器

bash 复制代码
make simulator

这一步骤会:

  1. 创建 build/ 目录
  2. 运行 CMake 配置(Simulator 模式会自动链接 SDL2)
  3. 编译 txiki.js、LVGL、lv_drivers 和项目自身的 C++ 绑定层

编译产物为 build/lvgljs 可执行文件。

3.2 打包 JS Bundle

bash 复制代码
npm install          # 安装前端依赖(首次运行一次即可)
npm run bundle      # 用 esbuild 将 .jsx/.tsx 打包成 .js

build.js 会扫描 demo/*/index.jsxtest/*/index.jsx,将所有 JSX/TSX 文件打包为可被 txiki.js 执行的纯 JavaScript 文件。

3.3 运行 Demo

bash 复制代码
# 默认运行 widgets 示例
make demo

# 运行其他 demo
make demo PROJECT=hello_world
make demo PROJECT=calculator

也可以手动指定路径:

bash 复制代码
./build/lvgljs run demo/widgets/index.js

3.4 热重载开发模式

同时打开两个终端窗口:

bash 复制代码
# 终端 1:监视 JSX 文件变化,自动重新打包
npm run bundle:watch

# 终端 2:监视编译产物变化,自动重新运行
npm run sim:watch -- demo/widgets/index.js

四、项目结构一览

复制代码
lvgljs/
├── CMakeLists.txt          # C++ 构建配置
├── Makefile                # 便捷构建入口
├── build.js               # esbuild JS 打包脚本
├── package.json            # npm 依赖配置
│
├── src/
│   ├── engine/             # C++ 应用入口
│   │   ├── engine.cpp      # main():初始化 txiki.js + 暴露 lvgljs 对象
│   │   └── hal/
│   │       ├── simulator/  # SDL2 模拟器 HAL
│   │       └── device/     # 嵌入式 framebuffer HAL
│   │
│   └── render/
│       ├── native/         # C++ LVGL 绑定层
│       │   ├── bootstrap/  # 初始化所有组件/事件绑定
│       │   └── components/ # 各个 LVGL 组件的 C++ 包装
│       └── react/         # JavaScript UI 框架
│           ├── core/      # Reconciler、样式、动画、主题
│           └── components/ # Button、Text、View 等 React 组件
│
├── deps/
│   ├── lvgl/              # LVGL 图形库(子模块)
│   ├── lv_drivers/       # LVGL 驱动(子模块)
│   └── txiki/             # txiki.js 运行时(子模块)
│
├── demo/
│   ├── widgets/           # 组件展示 demo
│   ├── hello_world/      # 入门 hello world
│   └── calculator/       # 计算器 demo
│
└── doc/                   # 详细文档
    ├── build/             # 构建指南
    ├── component/         # 各组件 API 文档
    └── style/             # CSS 样式文档

五、编写自己的 UI

项目提供了类似 React 的组件化接口。使用前确保 npm run bundle 已执行过(或者开 bundle:watch),然后编写 JSX 文件:

tsx 复制代码
import { Button, Render, Text, View } from "lvgljs-ui";
import React from "react";

function App() {
  return (
    <View style={{ "background-color": "#1a1a2e", "flex-direction": "column", "align-items": "center", "justify-content": "center" }}>
      <Text style={{ color: "#ffffff", "font-size": 24 }}>
        Hello lvgljs!
      </Text>
      <Button style={{ "margin-top": 20, "background-color": "#e94560" }}>
        <Text>Click Me</Text>
      </Button>
    </View>
  );
}

Render.render(<App />);

将文件放到 demo/myapp/index.jsx,运行:

bash 复制代码
npm run bundle
./build/lvgljs run demo/myapp/index.js

六、可能遇到的问题

问题 解决方案
Could NOT find CURL sudo apt install libcurl4-openssl-dev
Could NOT find SDL2 sudo apt install libsdl2-dev
LIBTOOL is undefined sudo apt install libtool autoconf automake
makeinfo: command not found sudo apt install texinfo
quickjs ... discarded-qualifiers Makefile cmake 命令加 -DCMAKE_C_FLAGS=-Wno-error=discarded-qualifiers
unterminated-string-initialization 同上,加 -Wno-error=unterminated-string-initialization
libffi configure failed cmake 命令加 -DUSE_EXTERNAL_FFI=ON + sudo apt install libffi-dev

七、总结

整个流程可以归纳为 4 条命令:

bash 复制代码
# 1. 安装依赖(一次性)
sudo apt install git cmake nodejs npm libsdl2-dev libcurl4-openssl-dev \
    libffi-dev libtool autoconf automake texinfo

# 2. 拉取代码和子模块,网络不好的话自己想办法
git clone https://github.com/lvgl/lv_binding_js.git && cd lv_binding_js
git submodule update --recursive --init

# 3. 安装 JS 依赖
npm install

# 4. 编译 + 打包 + 运行
make simulator && npm run bundle && make demo

修改 Makefile 这一步只在 CMake 4.x + Ubuntu 最新版系统上需要。如果是较老版本的 CMake(3.16~3.28),项目原生的 Makefile 应该是可以直接使用的,make setup && make simulator 即可成功编译。

相关推荐
A小辣椒20 小时前
TShark:Wireshark CLI 功能
linux
A小辣椒1 天前
TShark:基础知识
linux
AlfredZhao1 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao2 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334662 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪2 天前
linux 拷贝文件或目录到指定的位置
linux
大树883 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠3 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质3 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush43 天前
嵌入式linux学习记录十四、术语
linux·嵌入式