
去年年底接了塊 STM32MP157 的板子做一個帶觸摸屏的工業 HMI。GUI 選的 FLTK原因是整個畫面不復雜Qt 那一整套動態庫放上去有點浪費而 FLTK 編譯出來干干凈凈控件繪制在嵌入式場景下又足夠利索。板子跑的是 OpenSTLinux系統起來之后界面確實能出但總感覺哪里不對勁。后來扒了一下系統里 FLTK 的版本發現是 1.3.x而 OpenSTLinux 的顯示環境默認是 Weston/Wayland1.3 自己是沒法直接上 Wayland 的。說白了應用是在 XWayland 上轉了一層才畫出來的。這事剛開始還能忍等我開始高頻切換頁面、做動畫縮放的時候幀率明顯往下掉。最后我下決心把 FLTK 升到 1.4.x不但在源碼層面重新交叉編譯了一遍還把它接回了 OpenSTLinux 的 Yocto 構建體系讓下一次燒錄系統時不再是臨時手動補丁。這篇把整個更新過程、里面涉及的選擇邏輯、以及我踩過的坑寫出來給同樣在 OpenSTLinux 上做 FLTK 應用開發的朋友一個參考。無論你是第一次接觸這套環境還是已經跑過幾個 Demo這篇應該都能幫你少走一點彎路。1. 這次更新到底想解決什么自帶 FLTK 1.3 在 OpenSTLinux 上的憋屈1.1 OpenSTLinux 的顯示棧和 FLTK 的尷尬處境OpenSTLinux 是 ST 基于 Yocto 做的嵌入式 Linux 發行版主要面向 STM32MP1 系列微處理器。默認的圖形棧是 Weston也就是 Wayland 合成器。這一點很關鍵你在板子上看到的桌面、窗口列表、觸摸事件本質上都是 Weston 在管理。而 FLTK 1.3.x 是在 Wayland 還沒成氣候的時候定型的它的原生后端是 X11。所以在 OpenSTLinux 默認環境下運行 FLTK 應用常見路徑是FLTK 應用 → X11 庫 → XWayland → Weston → DRM/KMS → LCD 屏。這一層 XWayland 轉譯并不是免費的。每一次控件的重繪、每一次觸摸事件的上報都要在 X11 協議和 Wayland 協議之間做轉換。靜態界面看不出什么問題一旦動畫多起來CPU 占用和幀率表現都很難看。1.2 升級到 FLTK 1.4 之后到底能拿到什么FLTK 1.4 最重要的變化就是提供了原生 Wayland 后端。應用可以不再借道 XWayland而是直接和 Weston 通信走 Wayland 協議的 buffer 提交、直接渲染。資源占用和繪制延遲都是實打實的改善。除了 Wayland 后端1.4 還帶來了高 DPI 支持、對 Cairo 和 Pango 的更好集成、以及一套統一的Fl_Wayland_Window_Driver之類的內部驅動架構。對于一個 7 寸、10 寸這種小尺寸但分辨率很高的工業屏來說高 DPI 支持尤其有用。以前的 1.3 版本在 1080p 的屏上如果系統默認縮放不是 1字體和控件經常會發虛要么就得自己在應用里把所有坐標人工縮放極其痛苦。提示如果你現在的應用還在用 FLTK 1.3 并且沒有改動計劃那先別急著升。FLTK 1.4 的個別 API 做了清理比如Fl::set_color相關的一些舊接口要留意。升級前先翻一遍官方 CHANGES 文件重點看1.4.0的 API 變化列表。2. 動手前先摸底顯示鏈路、SDK 和當前 FLTK 安裝狀態2.1 板子上先把現狀看清楚我拿到板子第一件事是確認當前系統里實際跑的是哪套東西。不要憑印象猜版本因為 OpenSTLinux 不同的小版本也可能帶不同的組件。先把這幾條命令都跑一遍uname -a cat /etc/os-release weston --version ls /usr/lib/libfltk* /usr/lib/*/libfltk* 2/dev/null fltk-config --version 2/dev/null || echo no fltk-config in PATH我當時看到的輸出是 FLTK 1.3.5weston 8.0.x系統里沒有獨立的fltk-config庫文件直接躺在/usr/lib下。fltk-config都沒有說明這個包是用 Yocto 配方裝的但配方的打包方式比較裸沒把配置文件導出到 PATH 里。這也是后面要重新整理配方的理由之一。除了版本還要搞清楚當前顯示通道。STM32MP1 的顯示接口有 RGB、DSI、LVDS 等幾種但不管哪種在 Linux 側最后都落在 DRM/KMS 上。直接看內核日志和 Weston 啟動參數dmesg | grep -i drm cat /proc/cmdline ps -ef | grep westonweston進程的啟動參數里一般會帶--backenddrm-backend.so或類似的東西。drm-backend意味著 Weston 直接管理顯示設備這是最干凈的路徑。如果你看到--backendx11-backend.so那就說明 Weston 自己還在 X11 上跑這個更新意義就大打折扣得先解決 Weston 的啟動配置。2.2 交叉編譯 SDK 是不是已經就位OpenSTLinux 的 SDK 和環境變量是分開的。如果你是第一次用找不到環境文件很正常我一開始也是到處翻find /opt -name environment-setup* 2/dev/null找到后手動 source 一下source /opt/ST/stm32mp1/4.1.0/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabisource 完以后一定要驗證別省這一步echo $CC echo $CXX echo $SDKTARGETSYSROOT環境變量正常CC應該指向形如arm-ostl-linux-gnueabi-gcc的交叉編譯器SDKTARGETSYSROOT指向 SDK 的 sysroot 目錄。這個 sysroot 就是目標板文件系統的根編譯出來的動態庫、配置文件最終都該往里放。2.3 確認 Wayland 相關開發包是否在 sysroot 里FLTK 1.4 編譯 Wayland 后端時需要wayland-client、wayland-protocols、libdecor這些開發庫。OpenSTLinux 的 SDK 一般會帶 Wayland 協議頭文件但libdecor不一定帶。先查$ pkg-config --exists wayland-client echo yes || echo no $ pkg-config --exists libdecor-0 echo yes || echo no如果libdecor沒有編譯 FLTK 時不強制但窗口標題欄和邊框就出不來。嵌入式工業 HMI 一般都會去掉系統裝飾所以哪怕沒有也能跑。不過我建議還是把libdecor裝上否則以后想在窗口上加個關閉按鈕都麻煩。注意用 SD 卡系統直接在板子上編譯并不推薦。STM32MP157 的 Cortex-A7 跑編譯也能過但一次完整編譯要二三十分鐘起而且板上的空間和散熱都是問題。交叉編譯是更合理的選擇。3. 用 ST SDK 從源碼交叉編譯 FLTK 1.4 的完整路子3.1 為什么優先用 SDK 自帶的環境而不是手寫工具鏈文件OpenSTLinux SDK 除了設置CC、CXX之外還有個容易被忽略的點它把pkg-config的搜索路徑、sysroot 的鏈接參數、目標 CPU 架構的浮點優化都配好了。如果繞過這套環境自己寫 CMake 工具鏈文件很容易出現“編譯過了跑起來崩了”的情況尤其是 NEON 浮點指令集這類細節手動配置非常容易漏。所以我建議的原則是能用source environment-setup-*就不要自己造工具鏈文件。在 ST 這套環境里直接用cmake并依賴環境變量即可不需要額外指定CMAKE_TOOLCHAIN_FILE。3.2 具體編譯命令和 CMake 開關的意義我從 GitHub releases 下載了 FLTK 1.4 的源碼包解壓后開始構建wget https://github.com/fltk/fltk/archive/refs/tags/release-1.4.0.tar.gz tar xf release-1.4.0.tar.gz cd fltk-release-1.4.0 mkdir -p build cd build接著執行 CMake 配置。我當時的參數是這樣cmake ../ \ -DCMAKE_INSTALL_PREFIX${SDKTARGETSYSROOT}/usr \ -DCMAKE_BUILD_TYPERelease \ -DOPTION_USE_WAYLANDON \ -DOPTION_USE_X11OFF \ -DOPTION_USE_GLOFF \ -DOPTION_USE_CAIROON \ -DOPTION_USE_PANGOON這幾個開關不是隨便寫的逐個解釋CMAKE_INSTALL_PREFIX裝到 SDK 的 sysroot 里去。這樣交叉編譯應用時find_package(FLTK)才能找到新版本庫。OPTION_USE_WAYLANDON打開原生 Wayland 后端。這是這次升級的核心。OPTION_USE_X11OFF因為目標環境就是 Weston帶 X11 后端會讓庫變大、鏈接依賴變多。但我們也有一個項目要用 X11 后端那個項目里我單獨編了一份帶 X11 的包放在/usr/local/fltk_x11。兩塊不沖突。OPTION_USE_GLOFF默認 FLTK 1.4 如果檢測到 EGL/OpenGL ES會把 GL 窗口后端一起編進去。STM32MP1 的 GPU 雖然支持 OpenGL ES 2.0但我做的是純 2D HMI不打算讓 GPU 參與關掉 GL 可以減少一層依賴也避免在 Weston 里額外初始化 EGL 出問題。OPTION_USE_CAIROONCairo 的 2D 繪制后端。FLTK 官方一說數據繪制可能用到打開更穩。OPTION_USE_PANGOONPango 負責字體布局和文本渲染。嵌入式環境里如果沒有這個中文字體的處理會各種別扭。然后編譯安裝make -j$(nproc) make installmake install之后sysroot 里的 FLTK 就是 1.4.0 了。驗證一下${SDKTARGETSYSROOT}/usr/bin/fltk-config --version這個版本號正確說明庫和配置腳本都已經落到 sysroot。3.3 鏈接階段常見錯誤和缺包裝庫的排查交叉編譯 FLTK 時最常碰到的問題是鏈接期報缺符號比如undefined reference to wl_compositor_interface這類多半是 Wayland protocol 的代碼生成文件沒找到或者是鏈接時沒有加-lwayland-client。在 OpenSTLinux SDK 里正常不會缺但如果你用了非 SDK 的pkg-config路徑就會踩。其次比較隱蔽的是libdecor。如果 sysroot 里沒有libdecor-0.pcFLTK 1.4 的 CMake 會自動禁用窗口裝飾編譯不會失敗但到了板子上你發現所有窗口既沒有標題欄也無法拖動。這不是 bug是依賴缺失。如果不需要裝飾可以忽略如果需要得先把libdecor交叉編譯好裝進 sysroot再回頭編 FLTK。還有libxkbcommon。Wayland 后端處理鍵盤映射時依賴它OpenSTLinux SDK 通常已經帶上但如果你的自定義 sysroot 比較干凈記得補。提示每次改完 sysroot 里的庫最好重新跑一次source environment-setup-*再執行make clean make。這套 SDK 的pkg-config緩存有時候不夠聰明環境切來切去容易拿到舊路徑。4. 讓更新在下次燒錄后還活著把 FLTK 配方接進 Yocto4.1 為什么不建議在板子上直接 make install 了事很多人的做法是交叉編譯完把.so文件 scp 到板子上或者做個 rootfs 補丁包。這種做法做原型驗證沒問題但做產品固件就麻煩大了。下次重新燒寫官方鏡像所有改動全部消失還得手動再來一遍。OpenSTLinux 本身是 Yocto 發行版正規做法是把 FLTK 新版本做成一個 recipe讓bitbake把更新固化到鏡像里。以后重新生成鏡像一燒進去就是新版本。4.2 如何用 Custom Layer 管理 FLTK 配方如果你的 OpenSTLinux 工程里還沒有自己的層先初始化一個bitbake-layers create-layer meta-custom bitbake-layers add-layer meta-custom在meta-custom/recipes-graphics/fltk下建配方。如果工程里原本有 FLTK 的舊配方最省事的辦法是直接用devtool升級source openstlinux-environment # 進入構建環境 devtool modify fltkdevtool modify會把當前配方源碼解出來然后你可以檢查VERSION和SRC_URI。如果舊版本是 FLTK 1.3.x源碼地址遷移到了 GitHub releases需要手動更新SRC_URI https://github.com/fltk/fltk/archive/refs/tags/release-1.4.0.tar.gz PV 1.4.0如果沒有舊配方手動寫一個fltk_1.4.0.bb也行SUMMARY Fast Light Toolkit HOMEPAGE https://www.fltk.org/ LICENSE LGPL-2.0-with-exceptions LIC_FILES_CHKSUM file://COPYING;md5xxx SRC_URI https://github.com/fltk/fltk/archive/refs/tags/release-${PV}.tar.gz SRC_URI[sha256sum] xxx S ${WORKDIR}/fltk-release-${PV} DEPENDS libdecor wayland wayland-native wayland-protocols pango fontconfig inherit cmake EXTRA_OECMAKE -DOPTION_USE_WAYLANDON -DOPTION_USE_X11OFF -DOPTION_USE_GLOFFLIC_FILE_CHKSUM的 md5 值需要你下載解壓后自己md5sum算一下。不同版本源碼里的 COPYING 文件可能變化別省略這一步。寫好后執行devtool build fltk構建成功后再用devtool finish fltk meta-custom把改動提交到層里最后重新生成鏡像bitbake st-image-weston燒錄新鏡像板子上就是新 FLTK。4.3 版本跳躍時最容易出的問題FLTK 1.3 到 1.4 的包名和文件布局有變化主要體現在fltk-config的路徑和默認參數變了。庫文件名從libfltk.so.1.3變成了libfltk.so.1.4如果舊應用里硬編碼了libfltk.so.1.3啟動會直接報找不到共享庫。舊的fltk2相關兼容代碼如果應用里引用了需要做適配。如果你的應用是通過 CMake 的find_package(FLTK)方式鏈接的那在新 sysroot 下重新編譯一次即可鏈接對象會自動找到新版本。注意在 Yocto 里升級一個庫一定要把這個庫的 ABI 變更檢查清楚。FLTK 1.4 在 ABI 上沒有刻意完全兼容 1.3使用舊頭文件編譯出來的 .so 不要直接混用。5. 上板驗證時容易翻車的幾個細節5.1 跑起來之后先做的三件事系統燒完板子起來以后先確認環境確實生效再跑應用。第一檢查版本fltk-config --version ldconfig -p | grep fltk第二確認 Wayland 后端被正確使用。不加任何配置時FLTK 1.4 會自己判斷是否處于 Wayland 會話里。可以打印一個帶窗口的演示程序比如官方 democd /usr/share/fltk/test ./demo如果界面正常出現再用weston-log或者其他調試工具看客戶端是不是走了 wayland 協議。最簡單的方式是在啟動應用前設置環境變量export FLTK_BACKENDwayland ./your_app第三檢查觸摸。FLTK 1.4 在 Wayland 后端下觸摸事件來自wl_touch協議跟 X11 下的多點觸控路徑完全不同。如果觸摸沒反應優先查 Weston 的 libinput 配置而不是查 FLTK。5.2 X11 后端和 Wayland 后端混用時的運行時切換FLTK 1.4 允許同一個程序里同時編入 X11 和 Wayland 兩個后端。你可以在程序啟動時通過FLTK_BACKEND環境變量切換# 強制走 Wayland export FLTK_BACKENDwayland # 強制走 XWayland export FLTK_BACKENDx11如果你像我一樣有部分老代碼依賴 X11 特有行為這個特性在調試階段特別有用。可以先在x11后端跑確認不是應用邏輯問題再切到wayland后端對比表現。需要小心的是兩邊后端對窗口坐標、縮放、全屏的處理有細微差異。比如 X11 后端下Fl_Window::fullscreen()是直接告訴 X serverWayland 后端下則需要通過xdg_surface協議協商。同一個 API表現并不完全一致。5.3 我碰到的幾個隱蔽問題先說字體。FLTK 1.4 的 Wayland 后端走 Pango fontconfig 渲染文字。如果板子上的 fontconfig 沒有配置中文字體中文全部變方框。這個問題 1.3 在 X11 下不常見因為 X11 后端做了 FreeType 字體 fallback。升級后必須確認fc-list | grep -i cjk如果輸出為空就得在鏡像里加入中文字體包比如packagegroup-fonts-truetype或手動拷貝一個字體的.ttc文件到/usr/share/fonts再執行fc-cache -f。再有就是libdecor的插件路徑。如果你用 Yocto 構建時libdecor沒有作為插件安裝應用啟動后不報錯但所有窗口都沒有標題欄。解決辦法是確認鏡像里包含libdecor的.so插件文件并在啟動應用前看一眼日志有沒有類似libdecor: No plugin found的提示。最后一個是 GPU 和 GL 的坑。STM32MP1 雖然帶 GPU但如果你在編譯 FLTK 時開了OPTION_USE_GLON應用啟動時 Weston 會嘗試給客戶端分配 EGL 表面。如果格式不匹配可能出現黑屏或者白屏但應用本身沒崩潰。這種問題最難排查。我后來干脆把 GL 關了純軟件渲染雖然大尺寸窗口的拖動性能略遜一點但整個系統穩定很多。5.4 更新完成后的一點實測對比我把同一套壓力測試界面反復切換頁面、實時曲線刷新、拖拽窗口跑了一遍FLTK 1.3.5 XWaylandCPU 占用最高到 68%刷新曲線時有可感知的撕裂。FLTK 1.4.0 原生 WaylandCPU 占用控制在 35% 左右界面刷新明顯流暢觸摸拖拽也沒有了之前的“粘手感”。這個結果在我的 7 寸屏和 10 寸屏上都復現了。最后分享一個小習慣更新 FLTK 這件事本身不復雜真正值錢的是要把整個流程固化下來。我現在每次接到新的嵌入式 GUI 項目第一件事不是寫代碼而是先確認 GUI 庫和顯示后端的關系再決定要不要在 Yocto 層面做升級。FLTK 在 OpenSTLinux 上的這套流程后面換到 Qt、換到模擬器環境也都能復用看清顯示鏈路準備好交叉編譯環境把改動收進 Yocto 配方然后花更多時間在實機驗證上。希望這篇能讓你少走幾個我走過的彎路。