Flutter 在嵌入式 Linux 的應(yīng)用
簡(jiǎn)介
在嵌入式 Linux 設(shè)備上常使用 Qt 作為開發(fā)圖形界面應(yīng)用的框架,隨著 web 和移動(dòng)端圖形框架技術(shù)快速發(fā)展,嵌入式 Linux 也可以從這些技術(shù)中受益。由 Google 開發(fā)的 Flutter 最初用于 Android 和 iOS 應(yīng)用開發(fā),后期加入 web、 Windwos 桌面和 Linux 桌面的支持。配合適當(dāng)?shù)匿秩疽妫?nbsp;Flutter 也可以運(yùn)行在嵌入式 Linux 設(shè)備上。文章將介紹如何在使用 Linux BSP 的 Verdin iMX8M Plus 上運(yùn)行 Flutter 應(yīng)用。
硬件介紹
本次演示使用基于 NXP iMX8M Plus SoC 的計(jì)算機(jī)模塊 Verdin iMX8M Plus。底板為 Dahlia,該底板可以直接使用 Verdin iMX8M Plus 的 HDMI 顯示輸出。屏幕則使用支持電容屏的 HDMI 顯示器,用于測(cè)試 Flutter 應(yīng)用的交互性。
Flutter 介紹
Flutter 使用 Dart 語(yǔ)言開發(fā),可以跨平臺(tái)運(yùn)行,支持 AOT(Ahead of time)預(yù)編譯,使應(yīng)用在設(shè)備上更高效地運(yùn)行。對(duì)于 Flutter 應(yīng)用,用戶通常只需要開發(fā) apps 代碼, Framework、 Engine 和 Embedder都油 Flutter SDK 提供。使用不同的 embedder, Flutter app 可以運(yùn)行在不同的平臺(tái)上。目前官方支持embedder 包括 Android, iOS, MacOS、 Windwos 桌面、 Linux 桌面、 Web 瀏覽器
Linux 桌面需要依賴 GTK 和 X11,現(xiàn)在的嵌入式 Linux 系統(tǒng)已經(jīng)普遍使用 Wayland,例如 NXP 的 iMX 處理器在新的 BSP 已經(jīng)不再支持 X11。對(duì)于嵌入式 Linux 系統(tǒng),可以使用下面兩個(gè)非官方的 embedder。
Flutter-elinux,這是由 Sony 維護(hù)的項(xiàng)目,支持 Arm64 和 X64 處理器??梢允褂?Wayland 或者 X11 后臺(tái),或者直接基于 DRM。
Flutter-pi是針對(duì)樹莓派開發(fā)和優(yōu)化的 embbeder,其不依賴于 X11 和 GTK 的任何組件。支持 KMS 和 DRI,3D 硬件加速??梢赃\(yùn)行在 ARMv7、ARMv8、x86 處理器上。Flutter-pi 擁有更活躍的社區(qū)和開發(fā)者。結(jié)合flutterpi_tool工具可以非常容易地開發(fā) flutter 應(yīng)用。
Verdin iMX8M Plus 的 Linux BSP 支持 KMS,其 CPU 也是 Armv8 架構(gòu)。因此,我們本次選用 Flutter-pi 作為 embedder。關(guān)于 Flutter-elinux 在 Toradex 模塊上的應(yīng)用,可以參考該文章。
添加 meta-flutter
meta-flutter提供了編譯 flutter-pi 以及 flutter demo 的文件。meta-flutter 依賴 meta-clang layer。Toradex Linux BSP v6 基于 Yocto Project 的 kirkstone 分支。首先,參考這里創(chuàng)建 Yocto Project 編譯環(huán)境。然后進(jìn)入 layers 文件夾,下載 meta-flutter 和 meta-clang。
$ git clone --branch kirkstone https://github.com/meta-flutter/meta-flutter.git $ git clone --branch kirkstone https://github.com/kraj/meta-clang.git
然后在 build/conf/bblayers.conf 文件的 BBLAYERS 中添加 meta-flutter 和 meta-clang 的路徑。
BBLAYERS ?= " \ ${BBLAYERS_NXP} \ ... ${TOPDIR}/../layers/meta-clang \ ${TOPDIR}/../layerss/meta-flutter \ "
在 build/conf/local.conf 文件的結(jié)尾添加以下內(nèi)容。
DEFAULT_TIMEZONE = "Asia/Shanghai" ENABLE_BINARY_LOCALE_GENERATION = "1" IMAGE_LINGUAS:append = " en-us en-gb es-us zh-cn" GLIBC_GENERATE_LOCALES:append = " en_US.UTF-8 es_US.UTF-8 en_GB.UTF-8 zh_CN.UTF-8" IMAGE_INSTALL:append = " tzdata-core tzdata-asia" DISTRO_FEATURES:append = " opengl wayland pam" PACKAGECONFIG:append:pn-weston = " remoting" PACKAGECONFIG:append:pn-flutter-engine = " profile debug" IMAGE_INSTALL:append = " flutter-auto packagegroup-flutter-test-apps \ flutter-pi flutter-gallery" IMAGE_INSTALL:remove = " packagegroup-tdx-qt5"
刪除 meta-flutter/recipes-platform/packagegroups/ packagegroup-flutter-test-apps.bb 中的 flutter-test-texture-egl。最后編譯 tdx-reference-multimedia-image 鏡像文件。
$ bitbake tdx-reference-multimedia-image
測(cè)試 Flutter 應(yīng)用
禁用自啟動(dòng)的 weston 服務(wù)。
root@verdin-imx8mp:~# systemctl stop weston.service root@verdin-imx8mp:~# systemctl disable weston.service
鏡像中的 /usr/share/flutter/gallery/3.16.5/release 中已經(jīng)包含一個(gè) flutter gallery 應(yīng)用,現(xiàn)在可以使用 flutter-pi 直接運(yùn)行。
root@verdin-imx8mp:# cd /usr/share/flutter/gallery/3.16.5/release root@verdin-imx8mp:# flutter-pi --release ./
在 HDMI 顯示器上可以看到 gallery 應(yīng)用的界面。
安裝 Flutter SDK 和 flutterpi_tool
在 Linux 電腦(例如 Ubuntu 23.04)上,首先安裝 Flutter SDK。由于 Flutter 和 flutter-pi 兩個(gè)項(xiàng)目更新都比較活躍,在安裝前需求確認(rèn) Flutter 版本。在這里查看 flutter-pi 目前使用的 Flutter 版本。例如撰寫文章時(shí)其為 3.16.7。在 Flutter SDK 手動(dòng)安裝頁(yè)面選擇對(duì)應(yīng)的版本進(jìn)行安裝,如 flutter_linux_3.16.7-stable.tar.xz。
$ sudo apt-get install clang cmake git ninja-build \ pkg-config libgtk-3-dev liblzma-dev libstdc++-12-dev $ cd FLUTTER_SDK_INSTALL_PATH $ tar vxf flutter_linux_3.16.7-stable.tar.xz $ export PATH="$PATH:`pwd`/flutter/bin" $ flutter doctor -v
上面的 flutter 環(huán)境診斷工具如果提示缺少 chrome 瀏覽器,可以安裝后再運(yùn)行。
$ sudo dpkg -i google-chrome-stable_current_amd64.deb $ flutter doctor -v
檢查 flutter 和 dart 命令是否都來(lái)自同一個(gè)的 SDK 安裝目錄。
$ which flutter dart /home/ben/flutter-sdk/flutter/bin/flutter /home/ben/flutter-sdk/flutter/bin/dart
安裝完 Flutter SDK 后使用下面命令安裝 flutterpi_tool
$ flutter pub global activate flutterpi_tool $ export PATH="$PATH":"$HOME/.pub-cache/bin"
使用下面命令測(cè)試
$ flutterpi_tool --help
如果已經(jīng)安裝好 Flutter SDK 和 flutterpi_tool,需要編譯其他 flutter 應(yīng)用時(shí),只需要進(jìn)入之前 Flutter SDK 的安裝目錄后執(zhí)行下面命令,重新配置編譯環(huán)境即可。
$ cd FLUTTER_SDK_INSTALL_PATH $ export PATH="$PATH:`pwd`/flutter/bin" $ export PATH="$PATH":"$HOME/.pub-cache/bin"
使用 flutterpi_tool 編譯應(yīng)用
借助 flutterpi_tool 可以非常簡(jiǎn)單的編譯 flutter 應(yīng)用,例如針對(duì) 64 位 Arm CPU 的編譯命令 flutterpi_tool build --arch=arm64 --cpu=pi4 --release,參數(shù)說(shuō)明如下:
參數(shù) | 說(shuō)明 |
Runtime mode | |
--debug | Build for debug mode. |
--profile | Build for profile mode. |
--release | Build for release mode. |
--debug-unoptimized | Build for debug mode and use unoptimized engine. (For stepping throughengine code) |
Target, --arch= | |
arm | Build for 32-bit ARM. (armv7-linux-gnueabihf) |
arm64 | Build for 64-bit ARM. (aarch64-linux-gnu) |
x64 | Build for x86-64. (x86_64-linux-gnu) |
Target, --cpu= | |
generic (default) | Don’t use a tuned engine. The generic engine will work on all CPUs of the specified architecture. |
pi3 | Use a Raspberry Pi 3 tuned engine. Compatible with arm and arm64. (-mcpu=cortex-a53+nocrypto -mtune=cortex-a53) |
pi4 | Use a Raspberry Pi 4 tuned engine. Compatible with arm and arm64. (-mcpu=cortex-a72+nocrypto -mtune=cortex-a72) |
下面是在 Linux 電腦上編譯 flutter gallery 應(yīng)用。由于 Verdin iMX8M Plus 是基于 arm64 的 Cortex-A53 CPU,因此選擇 --arch=arm64 和 --cpu=pi3 兩個(gè)參數(shù)。
$ git clone https://github.com/flutter/gallery.git flutter_gallery $ cd flutter_gallery/ $ git checkout 6a8d738c94d0710e229d726729c09fdb5ccaf7ed $ flutter pub get $ flutterpi_tool build --arch=arm64 --cpu=pi3 --release
編譯結(jié)束后,在 build/flutter_assets 目錄下可以看到如下文件。
build/flutter_assets/ ├── app.so ├── AssetManifest.bin ├── AssetManifest.json ├── FontManifest.json ├── fonts ├── icudtl.dat ├── libflutter_engine.so ├── NOTICES.Z ├── packages └── shaders
flutteri_tool 目前使用新的編譯方法生成的文件結(jié)構(gòu)尚不能直接使用 flutter_pi 在設(shè)備上直接運(yùn)行,需要重新調(diào)整文件位置,參考 Verdin iMX8M Plus 上的 /usr/share/flutter/gallery/3.16.5/release 的內(nèi)容。
release/ ├── data │ ├── flutter_assets │ └── icudtl.dat └── lib ├── libapp.so └── libflutter_engine.so
在 flutter_gallery/build/flutter_assets/ 目錄創(chuàng)建 data 和 lib 兩個(gè)文件夾,app.so 重命名為 libapp.so 后和 libflutter_engine.so 一起移動(dòng)到 lib 目錄。icudtl.dat 移動(dòng)到 data 目錄下。在 data 目錄下創(chuàng)建 flutter_assets 文件夾后,將 build/flutter_assets/ 中剩余的 AssetManifest.bin,AssetManifest.json,F(xiàn)ontManifest.json,fonts,NOTICES.Z,packages 和 shaders 均移動(dòng)到 data/flutter_assets 中。完場(chǎng)后將 data 和 lib 兩個(gè)目錄復(fù)制到 Verdin iMX8M Plus 上的 /home/root/flutter_gallery 目錄中,例如使用 scp 命令。
$ scp -r build/flutter_assets/ root@imx8mp_ip:/home/root/flutter_gallery
復(fù)制好文件后可以在 Verdin iMX8M Plus 上的 /home/root/flutter_gallery 看到以下內(nèi)容。
root@verdin-imx8mp-07320826:~/flutter_gallery# ls * data: flutter_assets icudtl.dat
lib: libapp.so libflutter_engine.so
運(yùn)行下面命令即可啟動(dòng)在電腦上編譯的 flutter 應(yīng)用。
root@verdin-imx8mp:~# flutter-pi --release /home/root/flutter_gallery/
總結(jié)
使用 Flutter 可以開發(fā)跨平臺(tái)應(yīng)用,并獲得流暢的本地運(yùn)行體驗(yàn),在移動(dòng)端和 Web 端都有廣泛的應(yīng)用。但是針對(duì)嵌入式 Linux 的 embedder 目前是第三方維護(hù)的,所以在實(shí)際應(yīng)用時(shí)需要做詳盡的測(cè)試。
提交
Verdin AM62 LVGL 移植
基于 NXP iMX8MM 測(cè)試 Secure Boot 功能
隆重推出 Aquila - 新一代 Toradex 計(jì)算機(jī)模塊
Verdin iMX8MP 調(diào)試串口更改
NXP iMX8MM Cortex-M4 核心 GPT Capture 測(cè)試