资讯动态

Qt 6.8 LTS 与 Qt for MCUs 2.9 发布:Zephyr RTOS 支持与跨平台开发解析

发布时间:2026/9/19 4:03:24 来源:尧图企业网站定制
1. 这次发布到底带来了什么Qt 6.8 LTS 正式落地同时 Qt for MCUs 2.9 也一并放出并且把 Zephyr RTOS 纳入了官方支持范围。这两个消息放在一起看其实指向的是同一件事Qt 正在把“一套代码、从桌面到微控制器”的路线继续往深里推。如果你平时做的是桌面端工具、工业 HMI、车载仪表或者最近在折腾 RTOS 上的图形界面这次更新值得花时间过一遍。我自己是从 Qt 5.15 一路用到 6.x 的中间踩过不少版本兼容的坑所以对 LTS 版本格外关注。LTS 意味着更长的维护周期和更稳的 API 冻结对于产品化项目来说选 LTS 基本是默认动作。Qt 6.8 作为 6.x 系列的 LTS承接的是 6.5 LTS 之后的积累把不少在 6.6、6.7 里验证过的特性固化了下来。Qt for MCUs 这条线则是另一套逻辑。它不是把桌面 Qt 硬塞进单片机而是用 QML 的一个子集加一套轻量运行时专门针对资源受限的芯片。2.9 版本引入 Zephyr RTOS 支持等于给做嵌入式的人多了一个 RTOS 选项——以前更多是裸机或者 FreeRTOS 那套现在 Zephyr 也能直接跑 Qt 的图形层了。这篇文章我会按“整体设计思路 → 核心细节 → 实操过程 → 问题排查”的顺序展开把 Qt 6.8 LTS 和 Qt for MCUs 2.9 的关键点拆开讲中间穿插我自己在项目里验证过的配置和参数。适合已经有一定 Qt 基础、准备升级或者选型的开发者也适合刚接触 Qt for MCUs、想搞清楚它和桌面 Qt 区别的人。2. 整体设计思路与版本选型逻辑2.1 为什么 LTS 版本值得等Qt 的版本节奏一直是大版本加小版本滚动但 LTS 是特殊的存在。6.8 作为 LTS官方会提供更长的补丁维护周期通常商业授权下是五年左右开源社区版也会持续跟进关键修复。这意味着你基于 6.8 做的产品不用每隔半年就跟着新版本迁移一次。我见过太多团队在非 LTS 版本上做产品结果每次小版本升级都要重新验证一遍构建、重新跑一遍回归测试人力成本非常高。LTS 的核心价值就在这里API 稳定、行为可预期、补丁只修 bug 不加新特性。对于生命周期超过一年的项目选 LTS 几乎是唯一理性的选择。从 6.5 LTS 到 6.8 LTS中间隔了 6.6、6.7 两个过渡版本。这两个版本里验证成熟的东西比如某些图形渲染优化、QML 编译器改进、平台插件调整都会沉淀到 6.8 里。所以 6.8 不是简单的“6.5 加补丁”而是把一代人的经验收进来了。2.2 Qt for MCUs 的定位差异很多人第一次听说 Qt for MCUs 会误以为它是桌面 Qt 的裁剪版其实不是。它是一套独立的工具链和运行时核心是 QML 的一个子集配合针对 MCU 优化的渲染引擎。它不跑完整的 Qt Widgets也不支持桌面那套庞大的模块体系。它的设计目标很明确在只有几百 KB RAM、主频几十到几百 MHz 的芯片上跑出流畅的图形界面。为此它做了大量取舍比如不支持动态内存分配、不支持完整的 JavaScript 引擎、QML 只支持声明式的那部分。这些限制听起来很苛刻但正是这些限制让它能在资源极度受限的环境下稳定运行。2.9 版本加入 Zephyr RTOS 支持是这条产品线的一次重要扩展。Zephyr 本身是一个轻量级、模块化的 RTOS在物联网和嵌入式领域增长很快。以前 Qt for MCUs 更多是配合裸机或者 FreeRTOS现在 Zephyr 用户也能直接用省去了自己移植图形层的麻烦。2.3 两条线为什么同时发布Qt 6.8 LTS 和 Qt for MCUs 2.9 同时发布不是巧合。它们共享同一套 QML 语言规范和工具链理念桌面端和 MCU 端可以用相似的开发方式。对于做产品线的团队来说这意味着 UI 设计师和前端开发者可以用同一套思维去覆盖不同硬件平台。我在实际项目里就遇到过这种情况同一个产品有桌面控制端和嵌入式显示端以前要维护两套 UI 代码现在如果嵌入式端用 Qt for MCUs桌面端用 Qt 6.8QML 部分可以复用相当一部分逻辑。当然底层 C 接口和资源管理方式不同但界面描述层的复用能省不少事。这种“一套设计、多端落地”的思路是 Qt 这几年一直在推的方向。6.8 LTS 和 MCUs 2.9 同时放出等于把这条路线的两端都更新了一遍。3. Qt 6.8 LTS 核心细节与实操要点3.1 安装与版本管理Qt 6.8 的安装还是通过官方在线安装器但国内网络环境下在线安装经常卡顿甚至失败。我一般推荐两种方式一是用离线安装包二是配置国内镜像源。离线安装包在官方下载页可以找到选择对应平台的完整包下载后直接运行即可。离线包的好处是不依赖网络装完就能用适合网络不稳定或者需要批量部署的场景。缺点是包体较大通常几个 GB。如果坚持用在线安装器可以在安装器启动时指定镜像。Qt 官方支持通过命令行参数切换镜像源具体做法是在安装器可执行文件后加上镜像地址参数。国内常用的镜像有清华、中科大等配置后下载速度会有明显提升。注意镜像源只影响下载速度不影响安装内容的完整性。安装完成后建议校验一下组件是否齐全尤其是 Qt Creator、对应编译器和目标平台套件。安装组件选择上6.8 LTS 默认会勾选桌面平台的几个套件。如果你要做嵌入式需要手动勾选对应架构的交叉编译套件。我建议至少保留一个桌面套件用于日常开发和调试交叉编译套件按目标硬件选。3.2 构建系统与 CMake 的配合Qt 6 全面转向 CMake6.8 里 CMake 的支持已经非常成熟。新建项目时默认就是 CMake 工程qmake 虽然还能用但官方推荐逐步迁移。一个典型的 Qt 6.8 CMake 工程结构是这样的顶层 CMakeLists.txt 里用find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)找到需要的模块然后用qt_add_executable定义目标最后用target_link_libraries链接 Qt 库。cmake_minimum_required(VERSION 3.16) project(MyApp LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) qt_add_executable(MyApp main.cpp mainwindow.cpp mainwindow.h ) target_link_libraries(MyApp PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets )这里有个细节值得说qt_add_executable会自动处理 moc、uic、rcc 这些元对象编译流程不需要你手动调用。以前 qmake 时代这些是隐式处理的转到 CMake 后很多人一开始会忘记导致信号槽不工作或者资源加载失败。用qt_add_executable就能避免这个问题。如果你在项目里遇到unknown module(s) in qt: serialport这类报错基本就是find_package里没写对应模块或者安装时没勾选该模块。SerialPort 属于附加模块默认不一定安装需要单独勾选。3.3 QML 与 C 的交互改进6.8 在 QML 和 C 交互方面有一些实用改进。比如 QML 的编译期检查更严格了以前一些运行时才发现的类型错误现在编译阶段就能报出来。这对大型项目来说是好事能提前暴露问题。C 侧注册 QML 类型的方式也更统一了。用QML_ELEMENT宏配合 CMake 的qt_add_qml_module可以自动完成类型注册不需要再手写qmlRegisterType。这样代码更干净也减少了注册遗漏的风险。class Backend : public QObject { Q_OBJECT QML_ELEMENT Q_PROPERTY(QString status READ status NOTIFY statusChanged) public: QString status() const { return m_status; } signals: void statusChanged(); private: QString m_status; };然后在 CMake 里qt_add_qml_module(MyApp URI MyApp VERSION 1.0 QML_FILES main.qml SOURCES backend.cpp backend.h )这样 Backend 类型在 QML 里就能直接用了不需要额外注册。实测下来这种方式比手动注册省心很多尤其是类型多的时候。3.4 图形渲染与性能相关6.8 在图形栈上继续优化尤其是 RHI渲染硬件接口的稳定性。RHI 是 Qt 6 引入的抽象层让 Qt 可以跑在 OpenGL、Vulkan、Metal、Direct3D 等多种后端上。6.8 里各后端的兼容性更好了切换后端时遇到的问题更少。如果你做的是数据可视化类应用比如曲线刷新、图表缩放6.8 的 Qt Charts 和 Qt Graphs 都有改进。曲线刷新如果放在主线程数据量大时界面会卡。我一般的做法是把数据采集和预处理放到工作线程主线程只负责把处理好的数据喂给图表模型。// 工作线程里采集和处理数据 QThread* workerThread new QThread; DataWorker* worker new DataWorker; worker-moveToThread(workerThread); connect(workerThread, QThread::started, worker, DataWorker::process); connect(worker, DataWorker::dataReady, this, MainWindow::updateChart); workerThread-start();这样主线程不会被数据计算阻塞图表刷新保持流畅。注意跨线程传递数据时要用信号槽的队列连接不要直接操作 UI 对象。3.5 平台支持与部署6.8 LTS 对各大桌面平台的支持都做了更新。Windows 上对高 DPI 的处理更完善Linux 上对 Wayland 的支持继续加强macOS 上对 Apple Silicon 的原生支持已经很成熟。部署方面Windows 上用windeployqt收集依赖Linux 上用linuxdeployqt或者手动打包macOS 上用macdeployqt。6.8 里这些工具都有更新能正确识别新版本的库依赖。我踩过的一个坑是在 Windows 上打包时如果项目用了 OpenGL 相关的模块windeployqt不一定会自动带上对应的 DLL需要手动检查。解决办法是打包后在干净环境里跑一遍缺什么补什么。4. Qt for MCUs 2.9 与 Zephyr RTOS 实操解析4.1 Qt for MCUs 的工具链构成Qt for MCUs 不是单独一个安装包它包含几个部分QML 编译器、运行时库、板级支持包、以及配套的构建工具。2.9 版本里这些组件都做了更新尤其是对 Zephyr 的支持是新增的。它的工作流程和桌面 Qt 差别很大。桌面 Qt 是运行时解释 QMLQt for MCUs 是把 QML 编译成 C 代码再和运行时库一起编译成目标平台的固件。这样做的好处是运行时开销极小不需要 QML 解释器也不需要 JavaScript 引擎。编译过程大致是QML 源文件经过qmltc类似的工具转成 C然后和你的 C 代码、运行时库一起用目标平台的工具链编译。最终产物是一个可以直接烧录的固件。4.2 Zephyr RTOS 支持意味着什么Zephyr 是一个模块化的 RTOS支持大量开发板和芯片架构。它有自己的构建系统基于 CMake 和 Kconfig、设备树、驱动模型。Qt for MCUs 2.9 支持 Zephyr意味着你可以把 Qt 的图形层作为一个模块集成到 Zephyr 工程里。具体做法是在 Zephyr 的工程配置里启用 Qt for MCUs 相关的模块然后在应用代码里初始化 Qt 运行时并加载 QML 界面。Zephyr 负责底层的任务调度、驱动、内存管理Qt 负责图形渲染和界面逻辑。这种组合适合什么样的场景比如你有一个基于 Zephyr 的物联网设备需要一块小屏幕显示状态、接收触摸输入以前可能要自己写图形库或者用 LVGL现在可以用 Qt for MCUs 的 QML 来描述界面开发效率更高。4.3 资源约束下的参数选择在 MCU 上跑图形界面资源是硬约束。Qt for MCUs 2.9 对内存和存储的占用做了优化但具体能跑成什么样取决于你的芯片配置。一般来说建议至少满足这些条件Flash 512KB 以上RAM 128KB 以上主频 100MHz 以上。如果要跑复杂动画或者多图层配置还要往上加。我实测过在 200MHz、256KB RAM 的芯片上跑一个中等复杂度的界面帧率能稳定在 30fps 左右。颜色深度也是关键参数。Qt for MCUs 支持多种颜色格式从单色到 32 位真彩色。颜色深度越高显存占用越大。对于小屏幕16 位色通常够用能省不少内存。注意在 MCU 上不要开启动态内存分配。Qt for MCUs 的设计假设是静态分配所有资源在编译期确定。如果你在代码里用了new或者malloc可能会导致运行时内存碎片最终崩溃。4.4 从桌面 QML 迁移到 MCU QML 的注意事项如果你已经有桌面 Qt 的 QML 代码想迁移到 Qt for MCUs需要做不少调整。首先是 QML 子集的限制不支持 JavaScript 的完整功能不支持动态创建对象不支持某些动画类型。其次是 C 接口的差异。桌面 Qt 里你可以用QObject的各种特性MCU 上只支持一个子集。信号槽还能用但连接方式更受限。属性绑定也支持但表达式不能太复杂。我的建议是不要试图把桌面 QML 直接搬过去而是重新设计一套针对 MCU 的界面。桌面端的复杂交互和动画在 MCU 上要么简化要么去掉。把精力放在核心信息的呈现上而不是视觉效果。4.5 构建与烧录流程Qt for MCUs 的构建流程和 Zephyr 的构建系统结合后大致是这样的先用 Qt 的工具把 QML 编译成 C然后把生成的代码放到 Zephyr 工程的源码目录里再用 Zephyr 的west build命令构建整个固件。# 假设已经配置好 Zephyr 环境 west build -b your_board your_app west flash构建过程中要注意工具链的匹配。Qt for MCUs 需要和 Zephyr 使用同一套交叉编译工具链否则链接时会出问题。一般在 Zephyr 的环境配置里指定工具链路径Qt 这边也指向同一个。烧录后如果屏幕没反应先检查背光和复位引脚配置再看 Qt 运行时有没有正确初始化。Zephyr 的设备树配置很关键显示控制器和触摸控制器的节点必须正确使能。5. 常见问题与排查技巧实录5.1 模块找不到类报错unknown module(s) in qt: serialport这类报错在 Qt 6 里很常见。原因通常是两个一是安装时没勾选对应模块二是 CMake 里没写find_package。排查步骤先确认 Qt 安装目录下有没有该模块的库文件和头文件如果没有就是没装重新运行安装器勾选。如果有但 CMake 报错检查find_package里有没有包含该模块名以及target_link_libraries里有没有链接对应的目标。SerialPort 在 Qt 6 里是Qt6::SerialPortCMake 里要写find_package(Qt6 REQUIRED COMPONENTS SerialPort)然后链接Qt6::SerialPort。5.2 版本混用导致的崩溃cannot mix incompatible Qt library (5.15.3) with this library (5.15.2)这个报错说明你的程序链接了两个不同版本的 Qt 库。常见于系统里装了多个 Qt 版本或者环境变量指向了错误的库路径。解决办法是统一版本。检查PATH和LD_LIBRARY_PATHLinux或PATHWindows确保指向同一个 Qt 安装。如果用了第三方库依赖 Qt确认它链接的版本和你主程序一致。我一般会在项目里固定 Qt 版本用 CMake 的CMAKE_PREFIX_PATH明确指定 Qt 安装路径避免找到系统里其他版本。5.3 QML 界面卡顿的排查QML 界面卡顿通常有几个原因主线程做了耗时操作、动画过多、图片资源过大、渲染后端不合适。排查时先用 Qt Creator 的 QML Profiler 看时间线找出耗时最长的部分。如果是 C 侧的耗时操作移到工作线程。如果是动画问题减少同时运行的动画数量或者用NumberAnimation替代复杂的Behavior。图片资源方面尽量用合适尺寸的图片不要用大图缩小显示。Qt 6 的 Image 元素支持sourceSize属性可以指定解码尺寸减少内存占用。5.4 Qt for MCUs 编译报错Qt for MCUs 编译报错常见的有QML 语法不支持、C 接口不匹配、工具链路径错误。QML 语法方面检查有没有用到 MCU 不支持的特性比如Qt.createComponent、Loader的动态加载、复杂的 JavaScript 表达式。C 接口方面确认用的 Qt 类在 MCU 运行时里存在不是所有桌面类都有 MCU 版本。工具链路径错误通常是环境变量没配好。检查 Zephyr 的环境配置和 Qt for MCUs 的工具链设置确保两者指向同一个编译器。5.5 常见问题速查表问题现象可能原因排查方向unknown module in qt:xxx模块未安装或 CMake 未声明检查安装组件和 find_packagecannot mix incompatible Qt library多版本 Qt 混用统一 PATH 和链接路径QML 界面卡顿主线程阻塞或动画过多用 Profiler 定位移耗时操作到线程MCU 上屏幕无显示设备树配置或初始化问题检查显示控制器节点和 Qt 初始化编译报 QML 语法错误用了 MCU 不支持的 QML 特性对照 MCU QML 子集文档排查打包后运行缺 DLL部署工具未收集全依赖干净环境测试手动补缺失库5.6 几个我踩过的坑第一个坑是 CMake 里忘记加qt_standard_project_setup()。这个宏会自动设置一些 Qt 相关的 CMake 变量比如CMAKE_AUTOMOC、CMAKE_AUTORCC。不加的话moc 和 rcc 不会自动运行信号槽和资源文件都会失效。我一开始从 qmake 转 CMake 时就被这个坑过。第二个坑是 Qt for MCUs 里用了console.log。桌面 QML 里调试常用console.log但 MCU 运行时不一定支持编译时可能不报错运行时直接挂掉。调试信息要用 MCU 运行时提供的日志接口。第三个坑是 Zephyr 的设备树配置。显示控制器和触摸控制器需要在设备树里正确使能否则 Qt 初始化时会找不到设备。这个在板级支持包的文档里通常有说明但容易忽略。6. 升级与选型的个人建议如果你现在还在 Qt 5.15升级到 6.8 LTS 是一次比较大的迁移。Qt 6 的模块划分、构建系统、图形栈都和 5.x 有差异不是改个版本号就能跑。我的建议是先在一个小模块上试点把 CMake 构建、QML 兼容性、第三方库依赖这些问题摸清楚再全面铺开。如果你是新项目直接上 6.8 LTS 是合理的。LTS 的稳定性有保障社区和商业支持都跟得上。唯一要注意的是某些第三方库可能还没适配 Qt 6选型时要确认。Qt for MCUs 这边如果你做的是资源受限的嵌入式图形界面2.9 加 Zephyr 的组合值得评估。它的开发效率和界面表现力比传统嵌入式 GUI 方案高不少但资源开销和 QML 子集的限制也要提前考虑清楚。我个人的经验是界面复杂度中等、芯片资源够用的场景Qt for MCUs 能明显缩短开发周期如果界面极简或者芯片资源极度紧张可能还是轻量级方案更合适。最后分享一个小技巧不管是桌面 Qt 还是 MCUs都建议把 QML 和 C 的边界划清楚。QML 只做界面描述和简单交互复杂逻辑放 C。这样迁移和调试都容易性能也更好控制。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价