# React ui **Repository Path**: oneos-ability/react-ui ## Basic Information - **Project Name**: React ui - **Description**: OneOS移植react ui框架组件 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2024-11-27 - **Last Updated**: 2025-05-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 计算机系统能力大赛-操作系统-功能挑战赛 ## 项目描述 & 赛题介绍 #### Project ID: pro193-1466467 #### 学校名称:西北工业大学 #### 参赛队员:颜瑜(队长) 李柯辰   安 康  #### [赛题内容:](https://github.com/oscomp/proj193-port-reactui-on-OneOS.git) 移植react ui框架组件 1. JavaScript组件支撑,可直接选用OneOS目前支持的jerryScript和iotjs(但是与lv_binding_js不完全兼容),或选择**quickjs**(lv_binding_js的js执行引擎依赖)并自行移植到OneOS中; 2. 移植LVGL开源项目中的[lv_binding_js](https://github.com/lvgl/lv_binding_js)框架到[OneOS](https://gitee.com/cmcc-oneos/OneOS.git); 3. 输出与oneos轻应用框架one-evue的性能对比报告,如资源占用情况 ## 赛题解读 & 方案设计 #### Oneos 概述 1. OneOS是中国移动针对物联网领域推出的轻量级操作系统,具有可裁剪、跨平台、低功耗、高安全等特点,支持ARM Cortex-A和 Cortex-M、MIPS、RISC-V等主流芯片架构,兼容POSIX、CMSIS等标准接口,支持Javascript、MicroPython等高级语言开发模式,提供图形化开发工具,能够有效提升开发效率、降低开发成本,帮助用户快速开发稳定可靠、安全易用的物联网应用; 2. 目前,OnsOS支持jerryScript和iotjs运行环境,能够解析并执行js代码。   **目前**,OneOS操作系统使用LVGL和硬件驱动连接,完成图形化界面(UI)的操作和实现,开发人员需掌握C语言和LVGL框架API才能够设计和开发可视化应用程序,这不利于OneOS的实际应用和用户体验,为了解决这个问题,项目团队致力于实现能够使用前端js语言(react框架)在OneOS上轻松开发可视化应用程序的目标。   按照赛题要求,我们选择lv_binding_js框架作为移植对象,实现上述目标。 #### lv_binding_js 1. lv_binding_js框架是基于LVGL下的一个[开源项目](https://github.com/lvgl/lv_binding_js),用于支撑使用JavaScript编写LVGL。它使用react的虚拟DOM概念来操作LVGL UI组件,开发人员能够使用前端UI开发规范和习惯进行图形化界面开发,为用户提供简便快捷的开发体验; 2. lv_binding_js 运行依赖于[quickjs](https://github.com/bellard/quickjs.git)执行引擎。 #### quickjs 1. [quickjs](https://github.com/bellard/quickjs.git)是一个轻量且可嵌入的 JavaScript 引擎,它支持 ES2019 规范,包括 ES module、异步生成器以及 proxies等; 2. 它适用于嵌入式设备、移动应用程序和其他资源受限的环境,具有快速启动和低内存占用的特点。通过简单的API和扩展机制,开发人 员可以在应用程序中嵌入和扩展JavaScript功能。目前quickjs已经取得了广泛的应用,例如在ALiOS中同样采用了quickjs作为js执行引擎。 #### 方案设计   由于OneOS支持的js运行环境与lv_binding_js需要的目标环境不一致,因此需要解决OneOS和lv_binding_js的js执行环境适配问题。 ![赛题分析思路](image/赛题分析.png)   **方案一**:修改lv_binding_js框架中的实现逻辑和js执行机制,以适配iot.js运行环境,并运行到OneOS上;   **方案二**:移植quickjs执行引擎框架到OneOS,并支持lv_binding_js框架执行。   **总体而言**,方案一需要针对lv_binding_js的具体代码逻辑和实现进行调整,难度较大,团队经过调研和分析后认定方案二的可行性优于方案一。 ## 项目构建 & 开发实施 #### 环境准备 1. 安装编译工具OneOS-cube 下载地址:https://os.iot.10086.cn/download/tool, OneOS-cube的安装和使用可查看文档使用 2. 安装串口调试工具 [MobaXterm](https://mobaxterm.mobatek.net/) 3. 克隆项目到本地,OneOS项目仓库地址:https://gitee.com/cmcc-oneos/OneOS.git, 执行如下命令 ``` git clone https://gitee.com/cmcc-oneos/OneOS.git git clone https://gitlab.eduxiji.net/202310699111743/project1466467-178428.git ``` #### 构建项目 1. 进入目录 \project1466467-178428\OneOS\projects (该目录为OneOS源码所在路径),右键打开OneOS-cube 2. 执行如下命令,新建项目 ``` oos project ``` 3. 选择需要构建项目的开发板型号,我们选择 stm32h743-atk-apollo,如图所示。新建完成后,我们会在projects目录下看到生成的项目文件。 ![构建项目](image/构建项目1.png) ###### 连接开发板   我们使用的开发板型号为万耦天工stm32h743-atk-apollo,接通开发板电源,同时通过STM32下载器将宿主机与开发板连接,以便后续进行烧录。 ![硬件连接](image/硬件连接.png) ###### build 1. 进入 .\project1466467-178428\OneOS\projects\stm32h743-atk-apollo 目录,右键打开OneOS-cube,执行如下命令,可以对OneOS进行相应配置,启用相应的功能组件 ``` oos config ``` 我们需要对FileSystem进行配置,如图所示 ![FileSystem](image/FileSystem_config.png) 2. 完成配置后保存退出,执行如下命令开始build ``` oos build ``` 3. OneOS-cube支持将项目转换成keil工程,直接在keil进行编译和烧录,执行如下命令,也可执行```oos build```直接进行编译 ``` oos init -i keil ``` 4. OneOS-cube执行build成功后,会在 .\project1466467-178428\OneOS\projects\stm32h743-atk-apollo\out 目录下生成对应文件,如下图所示 ![build_out](image/build_out.png) 5. 烧录 可以使用keil进行烧录,也可以使用STM32烧录工具进行烧录,烧录的文件是out文件夹下生成的bin文件或elf文件。   至此,我们完成构建了一个**OneOS开发项目**,可以在其中编写配置文件、修改源码、开发组件等,并通过即时编译和烧录验证开发过程的正确性。 ### 开发实施 #### 1.虚拟机编译测试lv_binding_js   为了进一步熟悉和了解lv_binding_js的功能和设计逻辑,我们首先在虚拟机上进行编译,并测试了提供的demo,为下一步移植lv_binding_js作好准备。 1. lv_binding_js提供了[如何在Ubuntu上build的指导](https://gitee.com/the_trees_are_shallow/lv_binding_js/blob/master/doc/build/build-ubuntu-x86-simualtor.md),根据提示完成所需环境和工具安装。注意:根据我们测试发现除了提示中的工具外,还需要安装node才能正确编译lv_binding_js。 2. 下载源码到本地。要注意的是,由于lv_binding_js仓库中引用了其它仓库作为子模块,因此需要clone全部依赖的子模块仓库,否则会在编译过程中出现依赖缺失的错误,无法正确编译。 3. 尝试编译,如果出现报错,则根据报错信息修改```Cmakelist```中相关的路径信息,同时安装其它需要的工具,最终成功执行demo文件,结果如下图所示: ![ubuntu_lvgljs](image/ubuntu_lvgljs.png) #### 2.移植quickjs - OneOS 项目中采用组件的方式开发操作系统需要支持的功能,相关代码需要移动到```/OneOS/components/```路径下编译使用 - OneOS 项目使用Kconfig文件配置需要加入编译的组件属性,并在OneOS-cube提供了可视化的操作界面;另外,使用weave.yaml文件配置了需要加入编译的源码文件及其头文件引用路径以及宏依赖。 ##### 源码准备 1. 下载quickjs源码,可以到[quickjs开源仓库](https://github.com/bellard/quickjs.git)进行clone 2. 将quickjs文件夹移动到OneOS项目中的 \OneOS\components\ 路径下 ![quickjs_move](image/quickjs_move.png) ##### 编译配置 3. 进入OneOS-cube,打开quickjs组件加入编译 ![quickjs_component_config](image/quickjs_component_config.png) 4. 进入 \OneOS\components\ 路径,打开weave.yaml 文件,添加quickjs配置选项 ![quickjs_config_select](image/quickjs_config_select.png) 5. 进入quickjs文件夹,新建weave.yaml和Kconfig文件,具体内容如下: Kconfig文件: ![quickjs-Kconfig](image/quickjs_Kconfig.png) weave.yaml文件: ![quickjs_weave_yaml](image/quickjs_weave_ymal.png) 也可以将本仓库中的quickjs文件夹直接拷贝到目标路径 ##### 编译调试 6. 修改gcc编译配置,打开项目文件(\OneOS\projects\stm32h743-atk-apollo)路径下的settings-gcc.yaml文件,将其中对应代码替换为如下内容 ``` - ' -mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard -ffunction-sections -fdata-sections -D__ONEOS__ -Wno-array-bounds -Wno-format-truncation -D_GNU_SOURCE -DCONFIG_VERSION=\"2021-03-27\" -DCONFIG_BIGNUM' ``` ![setting_gcc_update](image/setting-gcc_change.png) 7. 修改 \OneOS\components\quickjs\quickjs.c 路径下 qjsc.c 文件的头文件引用部分,修改为如下所示: ``` #include #include #include #include #include #include #include #include #ifdef __ONEOS__ #include "oneos_amp_port.h" #else #include "fenv.h" #include "linux_jquick_mutex.h" #endif // __ONEOS__ #if defined(_WIN32) #include #include #endif #include #if defined(__APPLE__) #include #elif defined(__linux__) #include #endif #include "cutils.h" #include "list.h" #include "quickjs.h" #include "libregexp.h" #ifdef CONFIG_BIGNUM #include "libbf.h" #endif ``` 8. 添加shell执行入口函数 在```qjs.c```文件末尾加入如下代码,提供shell函数执行入口,保证能够通过shell脚本命令执行: ``` SH_CMD_EXPORT(quickjs, quickjs_main, "Show example quickjs"); ```   同时```qjs.c```中加入头文件引用,保证编译通过: ``` #include #include #include ``` #### 3. 移植lv_binding_js - 如前文提到的,lv_binding_js支持使用JavaScript编写LVGL,并使用react的虚拟DOM概念来操作LVGL UI组件,实现了按照前端编程语言习惯开发可视化应用程序。 - lv_binding_js源码结构如下图所示: ![lvgljs_code](image/lvgljs_code.png) ##### 源码准备 1. 执行如下命令,下载lv_binding_js框架源码到本地 ``` git clone https://github.com/lvgl/lv_binding_js --recurse-submodules ```   由于lv_binding_js仓库中引用了其它仓库作为子模块,因此需要clone全部依赖的子模块仓库,否则会在编译过程中出现依赖缺失的错误,无法正确编译。   如果上述命令出现错误或无法正常clone代码,可执行如下代码: ``` git clone https://gitee.com/the_trees_are_shallow/lv_binding_js.git --recurse-submodules ``` 2. 与第二阶段移植quickjs一样,将lv_binding_js代码加入```/OneOs/components/```路径下,作为组件进行开始和使用;接着编写配置文件将lv_binding_js加入编译,在```/OneOs/components/weave.yaml```最后一行加入 ``` - lv_binding_js ```   接着在```/OneOS/components/lv_binding_js```路径下新建**```weave.yaml```文件,添加如下代码: ``` # 组名 group_name: lv_binding_js # 依赖宏控 depend_macro: - USING_lv_binding_js add_subdirectory: - src/deps/libtuv - src/deps/lvgl8.2/yaml - src/deps/lv_drivers - src/jsruntime - src/utils - src/engine - src/render ```   接着在```/OneOS/components/lv_binding_js```路径下新建```Kconfig```文件,并添加如下代码: ``` menu "lv_binding_js" config USING_lv_binding_js bool "enable lv_binding_js" select USING_LVGL_8.2 default n menuconfig USING_LVGL_8.2 bool "Enable LVGL8.2" default n if USING_LVGL_8.2 source "$OS_ROOT/components/lv_binding_js/src/deps/lvgl8.2/Kconfig" endif endmenu ``` 3. lv_binding_js编译依赖其它组件和库,如源码结构图所示,为了便于统一管理和编译,我们将OneOS已经支持的**lvgl**、**libtuv**以及**quickjs**模块移入lv_binding_js目录下相应的位置,保证编译通过。 ##### 编译调试   由于lv_binding_js中代码结构较为庞大,因此我们在移植过程中采用了逐步编译的思路,将整体代码文件分为独立不相关的几个部分,然后通过weave.yaml文件配置的方式依次编译调试。 1. ```/src/utils```编译调试 - 新建配置文件```weave.yaml```,加入编译文件和头文件引用路径 - 注释```./utils/util.c```文件中```readlink() ```和 ```dirname()```函数的调用 - 保证```oos build```命令编译通过 2. ```/src/jsruntime```编译调试 - 除了quickjs的支持,lv_binding_js还需要编译当前路径下的```*.c```文件 - 新建配置文件```weave.yaml```,加入编译文件和头文件引用路径,具体内容请参考本仓库对应文件 - 由于其中的部分文件之间存在相互依赖关系,因此需要同时加入进行编译,具体可借助编译报错信息查看 - **注意**,由于此处需要依赖```components\lv_binding_js\src\deps\libtuv\include\uv.h```文件,然而部分函数没有声明却被直接调用,导致编译过程出现错误。原因是当前的```libtuv```中不存在相关函数的声明和实现,所以需要将```libuv```中对应路径下```uv.h```、```uv-common.c```、```uv-common.h```文件中缺少的函数声明和实现补充完整;同时在```fs.c```中确保被正确调用 3. 接下来的部分包含了```.cpp```文件,为了编译它们,需要**配置g++编译工具** 执行```oos config```命令,进入编译配置选择界面,打开c++编译支持选项,并保存退出,如下图所示 ![g++_config](image/g++_config.png) 4. ```/src/engine```编译调试 - 新建配置文件```weave.yaml```,加入编译文件和头文件引用路径 - 保证```oos build```命令编译通过 5. ```/src/render```编译调试 - 新建配置文件```weave.yaml```,加入编译文件和头文件引用路径,具体内容请参考本仓库对应文件 - 源文件中部分路径大小写不统一,需要改正 - 保证```oos build```命令编译通过 ##### js代码移植 - js代码作为脚本语言,不需要编译即可使用,同时quickjs已经支持执行js语言 - 编译链接通过后,将```render/react```文件夹通过SD卡的方式写入(复制)开发板,供后续测试使用 - 在```engine.cpp```文件末尾加入如下代码,提供shell函数**执行入口**,保证能够通过shell脚本命令执行: #### 4. 重难点及解决办法 ##### 重难点 - 环境不兼容 由于整个移植过程涉及到许多框架、库、编译工具以及操作系统,导致编译过程出现许多环境不兼容的报错(500+),主要表现在**变量和函数未声明、函数参数和返回值类型不统一、引用头文件不存在**等等; - ram溢出 整个代码全部编译完成后,发现**ram溢出**,导致链接错误 ![ram_overflow](image/ram_overflow.png) ##### 解决办法 - 对于环境不兼容导致的编译报错,如果相关变量和函数没有被进一步调用和执行,可以在报错位置选择暂时注释掉;或者选择自行声明并初始化;如果是库函数的函数,可以选择从windows和linux中寻找是否存在该函数。 - 对于ram溢出问题,选择加入外扩ram和flash,增加开发板ram,解决溢出问题。 ## 成果展示 & 结果分析 **可以直接使用本仓库[\project1466467-178428\OneOS\projects\stm32h743-atk-apollo\out]已经编译链接好的 bin 文件直接进行烧录到STM32H743 开发板中去,也可以自行编译链接生成 bin 和 elf 文件** #### build 1. 配置和调试完成后,进入 \OneOS\projects\stm32h743-atk-apollo 路径下,右键打开OneOS-cube,执行如下命令,清空当前编译内容 ``` oos clean ``` 2. 执行如下命令,等待编译完成 ``` oos build ``` 3. 等待编译(build)链接(link)完成后,项目文件中生成 out 文件夹及里面对应的文件,用于烧录 ![build_success](image/build_success.png) ![out](image/build_out.png) #### 测试quickjs 1. 将编译生成的 bin 文件烧录到开发板上(也) 2. 打开串口调试工具 MobaXterm ,进行代码调试 3. 打开 OneOS 下的shell终端,可以看到当前配置完成可以使用的脚本命令,其中包括我们刚刚编译进去的quiskjs ![image.png](image/quickjs_shell.png) 4. 新建js文件,执行quickjs脚本命令,测试quickjs执行情况 ![quickjs_success](image/quickjs_success.png) ## 总结 & 展望 - 项目完成后,OneOS支持运行```lv_binding_js```框架,支撑使用JavaScript编写LVGL,并支持react的虚拟DOM概念来操作LVGL UI组件,开发人员能够使用前端UI开发规范和习惯进行图形化界面开发,为用户提供简便快捷的开发体验,这对于嵌入式系统UI开发具有重要意义和应用价值; - ```lv_binding_js```目前支持**button**在内的20个控件,能够满足多数应用需求; - ```lv_binding_js```框架编译后生成的可执行文件相对较大,仍能满足嵌入式下有限资源的应用场景。 ![ram_analyse](image/ram_analyse.png)