从零开始在 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 即可成功编译。

相关推荐
小生不才yz28 分钟前
Shell脚本精读 · S13-01 | POSIX sh 与 Bash:语法对照表
linux
阿拉斯攀登44 分钟前
平台设备驱动:platform bus 与设备树
linux·嵌入式硬件·嵌入式·linux驱动·字符设备驱动
阿拉斯攀登1 小时前
并发与同步:自旋锁、信号量、互斥锁
linux·网络·嵌入式硬件·linux驱动·字符设备驱动
网络小白不怕黑1 小时前
10.邮件服务器搭建并脚本实现监控httpd状态
linux·运维·服务器
TTBIGDATA1 小时前
【Ambari Plus】15.Livy 安装
大数据·运维·hadoop·ambari·hdp·cdh·bigtop
CN_HW2 小时前
Nginx 流量镜像配置文档-双轨国产化
服务器·前端·网络
java_logo2 小时前
5 分钟共享打印机:用 Docker 一键部署 CUPS
运维·docker·容器·cups·网络打印机·共享打印机·docker部署cups
Macbethad2 小时前
基于TwinCAT的半导体刻蚀设备SCADA管理程序技术方案
运维·网络·数据库
Carlos_Xu2 小时前
Linux基础-基础命令
linux
风曦Kisaki2 小时前
# Linux实战笔记-HIS项目实战Day01:版本控制与Git基础
linux·笔记·git