本文主要参考正点原子的QT开发手册,仅作为个人学习笔记使用。
请用正点原子 I.MX6U 开发板进行实验,注意是用出厂系统,包括出厂内核(zImage modules)、设备树(dtb)出厂文件系统!
重要的事情得说三遍!
本篇使用的是正点原子 I.MX6U 出厂系统进行实验!
本篇使用的是正点原子 I.MX6U 出厂系统进行实验!
本篇使用的是正点原子 I.MX6U 出厂系统进行实验!
为什么强调是要使用默认的出厂系统?因为初学者做 Linux 驱动实验时会移植自己的内核,包括设备树和文件系统。这些与出厂系统有很大的差异!无法保证您的驱动是否可用!或者文件系统 Qt 库完整!好比如说,初学者连自己的屏触摸驱动都没有移植或者没写对,到时触摸一出问题本章无法继续!也不需要自己移植 Qt 到其他文件系统里测试。如果您能力可以,请自行测试!使用其他文件系统缺少 Qt 库的情况是发生在经常初学者身上的!本章针对正点原子的I.MX6U 出厂系统进行实验,笔者在 Ubuntu 上实验,也已经在正点原子 I.MX6U 开发板上出厂系统验证可行!
本章将编写与开发板相关的实例,涉及到的都是初学者或者开发者经常需要使用的硬件接口或者硬件资源!例子比较精简实用,对开发实际项目有很大的帮助!
本章适用于正点原子 ALPHA 或者 MINI 开发板。
搭建 I.MX6U 的 Qt 开发环境,正点原子已经早有相关文档,写的很详细。请大家先熟悉正点原子 I.MX6U 的 Qt 开发环境。交叉编译 Qt 应用程序有两种方法。一种是直接在终端使用命令行编译 Qt 项目。一种是在 Qt Creator 里搭建交叉编译套件的方法来编译 Qt 项目。请大家根据个人的喜好可两者都熟悉或者使用其中一种即可!本教程更倾向使用命令行编译 Qt 项目,在Ubuntu 直接运行仿真,再交叉编译到开发板上运行查看实际效果即可!
使用命令行编译
请参考开发板光盘 A-基础资料/【正点原子】I.MX6U 用户快速体验 V1.x.pdf 第四章第 4.6小节,使用命令行编译的方法。不过此方法需要拷贝执行文件到板子上运行。
在 Qt Creator 搭建交叉环境搭建
请参考开发板光盘 A-基础资料/【正点原子】I.MX6U 出厂系统 Qt 交叉编译环境搭建V1.x.pdf。推荐使用在 Qt Creator 搭建调试环境。可以远程连接开发板运行。但若结果不正确时(比如需要环境变量,路径等),建议拷贝执行文件到开发板上运行。
文档地址参考:
正点原子I.MX6U文档: 正点原子I.MX6U文档(保持最新)
QT程序和普通的C++程序在开发阶段、编译链接阶段以及放到嵌入式设备上运行的阶段,有什么区别吗?
Qt 程序与普通 C++ 程序在开发、编译和运行阶段存在显著差异,主要源于 Qt 框架的特性和嵌入式系统的资源限制。以下是详细对比:
一、开发阶段差异
特性 普通 C++ 程序 Qt 程序 GUI 开发 需手动实现窗口系统(如 X11、Win32 API) 使用 Qt 内置的跨平台 GUI 组件(如 QWidget、QML) 开发工具 文本编辑器 + 编译器(如 Vim + g++) Qt Creator(集成设计器、调试器、代码生成工具) 信号与槽机制 需手动实现回调函数 内置信号与槽(Signal & Slot)机制,简化事件处理 UI 设计 手动编写布局代码 使用 Qt Designer 可视化设计 UI,生成 .ui 文件 资源管理 手动处理文件路径 使用 Qt 资源系统(.qrc)打包图片、字体等资源 国际化支持 需自行实现字符串翻译 内置 lupdate/lrelease 工具,支持多语言翻译 二、编译链接阶段差异
特性 普通 C++ 程序 Qt 程序 预处理步骤 直接编译 .cpp 文件 需先通过 moc(元对象编译器)处理 Qt 特有的关键字(如 Q_OBJECT) 编译依赖 仅需标准 C++ 库(如 libstdc++) 依赖 Qt 库(如 QtCore、QtGui、 QtWidgets) 链接选项 简单链接系统库 需链接 Qt 库,可能需要指定 OpenGL 等额外依赖 交叉编译复杂度 中等(配置交叉编译器路径) 高(需为目标平台构建 Qt 库,配置 sysroot) 编译产物大小 通常较小(取决于依赖) 较大(Qt 库体积约 100MB+,需优化或裁剪) 三、运行阶段差异
特性 普通 C++ 程序 Qt 程序 运行依赖 仅需系统基础库(如 libc、libstdc++) 依赖完整的 Qt 库(需部署到目标设备) 内存占用 较低(取决于程序复杂度) 较高(Qt 框架本身占用约 10-20MB 内存) 图形系统 依赖 X11 或其他窗口系统(如 Wayland) 支持多种显示后端(X11、EGLFS、Wayland、Framebuffer) 启动时间 通常较快 较慢(Qt 初始化开销较大) 资源优化需求 一般不需要特殊优化 需通过 -reduce-relocations、qtdeploy 等工具裁剪不必要的组件 输入系统支持 需自行处理键盘、鼠标事件 内置支持多种输入设备(触摸屏、键盘、遥控器) 四、嵌入式设备上的特殊考虑
资源限制
内存:Qt 程序需预留足够内存(至少 64MB+),可通过
-no-gui
等选项减少内存占用。存储:部署精简版 Qt 库(如仅包含必要模块),或使用文件系统压缩(如 SquashFS)。
图形加速
普通 C++:需自行实现 OpenGL ES 调用(如使用 EGL)。
Qt:通过
-opengl es2
配置启用 GPU 加速,需确保设备有兼容的驱动。部署方式
普通 C++:直接复制可执行文件和依赖库。
Qt:需打包 Qt 库、插件和资源,可使用 Qt Installer Framework 或自定义脚本。
系统集成
普通 C++:可能作为后台服务运行(如守护进程)。
Qt:通常作为前台应用,需配置窗口管理器或直接使用 EGLFS 模式。
进一步参考:
【Q&A】QT编译过程和C++编译过程的区别?_qt rcc extractor-CSDN博客
Qt 项目编译流程总结 - Jeffxue - 博客园
根据《【正点原子】I.MX6U 移植Qt5.12.9 V1.1》 文档,可以知道,我们是可以使用通用的C++交叉编译工具链来编译QT程序的。
QT移植过程大概如下:
确保有通用的C++交叉编译工具链;
下载并编译QT库,然后放到开发板的根文件系统中,要进行一些环境变量和配置项的设置;
直接在ubuntu上使用QT Creator编写QT的应用程序,配置好交叉编译工具链以及qmake,之后可以使用QT Creator或者命令行的方式去编译QT程序,得到的可执行文件,也放到开发板的根文件系统中;
执行QT程序;
注意:
为什么还有移植QT库到开发板,直接全都编译链接到QT应用程序不可以吗?
Qt 库既可以是动态链接库(.so/.dll),也可以是静态链接库(.a/.lib),具体取决于编译时的配置选项。以下是详细说明:
一、默认编译方式:动态链接库
当你从源码编译 Qt 时,默认生成动态链接库(如 Linux 上的
.so
文件,Windows 上的.dll
文件)。例如:# 编译动态链接的 Qt 库(默认方式) ./configure -release ... make && make install
动态链接库的优点:
减小应用体积:应用只需包含少量导入信息,无需嵌入完整的 Qt 代码。
共享运行时:多个应用可共享同一套 Qt 库,节省内存。
便于更新:修复库漏洞时,只需替换系统中的
.so
文件。二、静态编译方式:静态链接库
若需要将 Qt 库静态链接到应用程序,需在编译 Qt 时添加
-static
选项:# 编译静态链接的 Qt 库 ./configure -static -release ... make && make install
静态链接库的特点:
增大应用体积:Qt 库代码会被完整嵌入到应用中,导致单个应用体积显著增加(例如从几 MB 变为数十 MB)。
无需依赖系统库:应用可独立运行,无需在目标设备上预先安装 Qt 库。
法律合规要求:若使用 LGPL 协议的 Qt,需提供应用的源代码(包括修改过的 Qt 代码)。
Qt 库默认以动态链接库形式提供,这是主流做法,因为它能减小应用体积、节省内存并简化维护。静态链接仅在特定场景下使用(如嵌入式设备需独立运行),且需注意部分模块的限制和法律合规问题。
再参考下《【正点原子】I.MX6U 出厂系统Qt交叉编译环境搭建 V1.6》
这里面使用的交叉编译工具链是这个fsl-imx-x11-glibc-x86_64-meta-toolchain-qt5-cortexa7hf-neon-toolchain-4.1.15-2.1.0.sh
问题来了:
fsl-imx-x11-glibc-x86_64-meta-toolchain-qt5-cortexa7hf-neon-toolchain-4.1.15-2.1.0. sh和arm-linux-gnueabihf-g++有什么区别
fsl-imx-x11-glibc-x86_64-meta-toolchain-qt5-cortexa7hf-neon-toolchain-4.1.15-2.1.0.sh
和arm-linux-gnueabihf-g++
都是用于 ARM 架构的交叉编译工具,但存在以下核心区别:一、定位与功能范围
特性 fsl-imx-x11-qt5 工具链 arm-linux-gnueabihf-g++ 来源 NXP(飞思卡尔)官方提供的完整工具链 通用 ARM 交叉编译工具(如 Ubuntu 包) 功能范围 一站式解决方案,包含:
- Qt5 库
- X11/Wayland 显示系统
- GPU/VPU 驱动
- 系统根目录(sysroot)仅包含基础编译器和标准库(如 libc、libstdc++) 目标硬件 专为 i.MX6/7/8 系列芯片优化 通用 ARM 设备(需手动适配特定芯片) 适用场景 i.MX 平台的 Qt 应用开发 简单 ARM 程序或无需复杂依赖的项目 二、技术细节对比
1. 编译器与工具链组件
fsl-imx-x11-qt5 工具链:
# 核心组件 arm-poky-linux-gnueabi-g++ # 基于特定版本的 GCC(如 6.3.0) qmake/qt5 # 预配置的 Qt 工具链 sysroot/ # 包含 i.MX 平台的系统库和头文件
arm-linux-gnueabihf-g++:
# 通常通过包管理器安装 sudo apt install g++-arm-linux-gnueabihf
2. 系统根目录(sysroot)
fsl-imx-x11-qt5 工具链:
包含 i.MX 平台的专用库(如 GPU 驱动
libimxegl.so
)。预配置 X11/Wayland 显示系统的头文件和库。
arm-linux-gnueabihf-g++:
仅包含通用 ARM 系统库(如
libc
、libstdc++
)。若需使用特定芯片的驱动,需手动从目标设备复制相关文件。
3. Qt 集成
fsl-imx-x11-qt5 工具链:
预编译并优化的 Qt5 库,支持:
EGLFS/X11 显示后端
OpenGL ES 2.0/3.0 加速
硬件视频解码(VPU)
直接使用
qmake
即可编译 Qt 应用。arm-linux-gnueabihf-g++:
需手动编译 Qt 库,且需正确配置:
# 手动配置示例 ./configure -opengl es2 -device linux-arm-gnueabi-g++ \ -sysroot /path/to/sysroot ...
4. 编译选项
fsl-imx-x11-qt5 工具链:
# 默认启用的优化选项 -march=armv7-a -mfpu=neon -mfloat-abi=hard -D__FSL_SECURE_BOOT__ -D__ARM_NEON__
arm-linux-gnueabihf-g++:
# 需手动指定优化选项 g++ -march=armv7-a -mfpu=neon -mfloat-abi=hard ...
三、使用流程对比
1. 编译 Qt 应用
使用 fsl-imx-x11-qt5 工具链:
# 1. 导入环境变量 source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi # 2. 直接编译 Qt 项目 qmake -project qmake make
使用 arm-linux-gnueabihf-g++:
# 1. 手动编译 Qt 库(耗时且复杂) ./configure -device linux-arm-gnueabi-g++ -sysroot ... make -j4 && make install # 2. 使用自定义 Qt 工具链编译项目 /path/to/custom/qt/bin/qmake -project /path/to/custom/qt/bin/qmake make
2. 处理硬件依赖
fsl-imx-x11-qt5 工具链:
// 直接使用 i.MX 特定的 API #include
EGLSurfaceCreate(...);
arm-linux-gnueabihf-g++:
// 需手动包含头文件并链接库 #include
// 需手动指定 -L/path/to/lib -limxegl 四、适用场景建议
场景 fsl-imx-x11-qt5 工具链 arm-linux-gnueabihf-g++ i.MX 平台 Qt 开发 ✅ 推荐(开箱即用) ❌ 需大量手动配置 硬件加速(GPU/VPU) ✅ 预配置驱动和优化选项 ❌ 需手动集成驱动 快速原型开发 ✅ 节省配置时间 ❌ 需自行解决依赖 非 Qt 项目 ❌ 工具链体积庞大 ✅ 轻量级,仅需基础编译 跨平台支持 ❌ 仅支持 i.MX 系列芯片 ✅ 通用 ARM 架构 五、总结
选择 fsl-imx-x11-qt5 工具链:若开发 i.MX 平台的 Qt 应用,特别是需要硬件加速或 X11/Wayland 支持。
选择 arm-linux-gnueabihf-g++:若开发简单 ARM 程序,或需自行控制所有依赖的编译过程。
关键点:fsl 工具链是为 i.MX 平台深度定制的 “一站式” 解决方案,而
arm-linux-gnueabihf-g++
是通用工具,需开发者自行处理复杂依赖。
为什么使用fsl-imx-x11-qt5 工具链不需要手动部署QT库?
使用 fsl-imx-x11-qt5 工具链 无需手动部署 Qt 库的核心原因在于:该工具链已将 Qt 库与目标设备的系统环境深度集成,并通过以下机制实现自动化部署:
一、sysroot 机制
fsl-imx-x11-qt5 工具链包含一个完整的 sysroot(系统根目录),其中预装有:
Qt 库文件(如
libQt5Core.so
、libQt5Gui.so
)系统依赖库(如
libEGL.so
、libGLESv2.so
)头文件(如
/usr/include/QtCore
)插件和资源(如
/usr/lib/qt5/plugins
)当你编译应用时,工具链会自动将这些文件打包到目标系统中,无需手动复制。
二、环境变量配置
工具链通过
environment-setup-*
脚本预配置环境变量:# 导入工具链环境 source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi # 关键环境变量 export PATH=$PATH:/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi export SYSROOT=/opt/fsl-imx-x11/4.1.15-2.1.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi export LD_LIBRARY_PATH=$SYSROOT/usr/lib:$LD_LIBRARY_PATH
这些变量告诉编译器和链接器:
从哪里获取 Qt 头文件和库
运行时如何查找动态库(通过
LD_LIBRARY_PATH
)三、预构建的根文件系统
fsl-imx-x11-qt5 工具链通常与 预构建的根文件系统(rootfs) 配套:
rootfs 中已包含 Qt 库和必要的依赖项
部署时,只需将 rootfs 烧写到设备,无需额外操作
例如,使用 Yocto Project 构建的 rootfs 会自动包含:
rootfs/ ├── usr/ │ ├── lib/ │ │ ├── libQt5Core.so.5 │ │ ├── libQt5Gui.so.5 │ │ └── ... │ └── plugins/ │ ├── platforms/ │ └── imageformats/ └── etc/ └── profile.d/ # 包含 Qt 环境配置脚本
fsl-imx-x11-qt5 工具链通过 sysroot 集成、环境变量配置和预构建 rootfs 实现了 Qt 库的自动化部署。这种设计使开发者无需手动处理库文件,显著降低了嵌入式开发的复杂度。
关键点:工具链的核心价值在于将 Qt 与 i.MX 平台的硬件驱动、系统库进行了深度适配,确保编译出的应用能直接在目标设备上运行。
使用fsl-imx-x11-qt5 工具链还需要额外移植根文件系统吗?
使用 fsl-imx-x11-qt5 工具链通常不需要额外移植根文件系统,但在一些特殊情况下可能需要。具体分析如下:
通常不需要额外移植:fsl-imx-x11-qt5 工具链一般是基于 Yocto 项目构建的3。Yocto 在构建工具链时,会生成一个包含了所需库和工具的根文件系统3。该工具链的 sysroot 中已包含了编译和运行相关程序所需的文件和库,如 Qt 库、系统依赖库、头文件等,并且工具链的环境变量配置也会指向这个 sysroot,使得编译出的程序能够找到所需资源,所以正常情况下无需额外移植根文件系统。
特殊情况可能需要:如果目标设备的硬件平台与工具链默认支持的不完全匹配,或者对根文件系统有特殊定制需求,如需要添加特定的驱动、服务或自定义的应用程序等,可能就需要额外移植根文件系统。另外,如果原有的根文件系统损坏或不完整,也需要重新移植一个合适的根文件系统,此时可以在工具链生成的根文件系统基础上进行修改和定制,然后再移植到目标设备。