QT的起源
本文系统梳理了Qt框架的发展历程,从1990年代的起源到当前的Qt6版本。首先分析了Qt的设计初衷和早期架构,重点阐述了其跨平台、面向对象和组件化的核心思想。随后详细介绍了Qt在嵌入式系统中的裁剪方法,包括模块化配置、静态链接和链接器优化等技术。文章通过版本对比展示了Qt从4.x到6.x的演进过程,特别分析了模块化架构、功能裁剪和构建系统的重大变革。最后,解释了Qt的双重许可模式,并提供了ARM平
第一部分:QT的起源、设计哲学与初始版本源码树形分析
1. QT开发库设计的由来与初衷
-
时代背景: 1990年代初期,Unix/X11下的GUI开发非常原始和碎片化。程序员主要直接使用Xlib API,这是一个极其底层、复杂且在不同Unix变体上行为不一致的C语言库。虽然存在Motif等工具包,但它们价格昂贵、外观陈旧且同样难以使用。
-
创始人与契机: 1994年,挪威的Haavard Nord和Eirik Chambe-Eng(Qt的两位“爸爸”)正在为一个跨平台的仿真软件项目寻找合适的GUI工具包。他们受尽了X11编程的折磨,并对市场上的解决方案感到失望。
-
设计初衷: 他们的核心目标是创建一个 “真正跨平台” 的C++ GUI框架。这个框架需要满足:
-
“一次编写,到处编译”: 源代码无需修改,即可在Windows、Unix/X11、Mac等系统上编译和运行。
-
面向对象: 使用C++的特性,通过直观的类层次结构来封装复杂的原生GUI API,提高开发效率和代码可维护性。
-
组件化与可扩展性: 提供丰富的预制UI组件(按钮、文本框等),并且允许用户通过继承轻松创建自定义组件。
-
良好的性能: 不能因为抽象而带来过大的性能开销,需要接近原生应用的响应速度。
-
统一的API: 无论底层操作系统如何,都提供一套完全相同、语义一致的API。
-
为什么设计QT? 简而言之,是为了解决当时C++ GUI编程的痛苦,提供一个生产力更高、体验更一致的工业级解决方案。
2. QT初始版本(以Qt 1.0为例)源码树形分析与软件设计
Qt 1.x的源码树相对现代Qt要简单得多,但其核心架构思想已经确立。假设一个类似1.0版本的简化源码树结构:
qt-1.0/ ├── src/ │ ├── kernel/ # 核心非GUI类 │ │ ├── qobject.h/.cpp # 元对象系统核心,信号与槽的基石 │ │ ├── qapplication.h/.cpp # 应用程序对象,事件循环核心 │ │ ├── qevent.h/.cpp # 事件类定义 │ │ └── qpoint.h, qrect.h... # 几何基础类 │ ├── widgets/ # GUI控件类 │ │ ├── qwidget.h/.cpp # 所有窗口部件的基类 │ │ ├── qbutton.h/.cpp # 按钮基类 │ │ ├── qpushbutton.h/.cpp # 具体按钮实现 │ │ ├── qlabel.h/.cpp # 标签 │ │ └── ... │ ├── dialog/ # 对话框类 │ │ ├── qdialog.h/.cpp │ │ ├── qfiledialog.h/.cpp │ │ └── ... │ ├── painter/ # 绘图引擎 │ │ ├── qpainter.h/.cpp # 绘图工具 │ │ ├── qpaintdevice.h/.cpp # 绘图设备抽象 │ │ └── qcolor.h, qpen.h... # 绘图资源 │ └── moc/ # 元对象编译器 (moc) │ └── moc.cpp # 一个独立的C++程序,不是库的一部分 ├── include/ # 对外头文件 ├── lib/ # 编译生成的库文件 └── tools/ └── designer/ # Qt Designer 初始版本?(可能在更晚版本加入)
软件设计与性能分析:
-
qobject.h/.cpp- 元对象系统(Meta-Object System):-
设计模式: 大量使用了工厂方法模式(通过
Q_OBJECT宏和moc生成类信息)、观察者模式的变体(信号与槽)、命令模式(封装操作,如事件)。 -
软件设计: 这是Qt的灵魂。它通过引入
moc(元对象编译器)这个代码生成器,在C++语言之外,为类添加了运行时类型信息(RTTI) 和动态方法调用的能力。这解决了C++原生RTTI能力弱的问题。 -
性能分析: 信号与槽的连接是类型安全的,其调用开销略高于直接函数调用,但远低于动态语言的反射。它通过一个内部的连接对象数组进行查找和调用,是空间换时间的典型设计。相比于回调函数,它更安全,但引入了微小的间接调用开销。
-
-
qapplication.h/.cpp- 应用程序与事件循环:-
设计模式: 单例模式(一个进程一个QApplication实例)、事件循环模式、模板方法模式(
QApplication::exec()定义了算法骨架,具体事件处理由虚函数如event()处理)。 -
软件设计: 封装了不同操作系统下的消息泵。它将来自操作系统(如X11的XEvent, Windows的MSG)的原始事件,翻译成Qt的
QEvent对象,并通过QObject::event()函数派发给相应的目标控件。这是一个抽象层(Adapter Pattern) 和** facade模式**的体现,向上层应用开发者隐藏了平台的复杂性。 -
性能分析: 事件循环本身是高效的,它通常在一个
while循环中阻塞等待系统事件。主要的性能瓶颈在于事件处理函数(如paintEvent)中的业务逻辑效率。Qt内部对事件进行了合并优化,例如重绘事件。
-
-
qwidget.h/.cpp- 窗口部件基类:-
设计模式: 组合模式(父控件管理子控件,形成树形结构)、策略模式(布局管理)、装饰器模式(如样式表)。
-
软件设计:
QWidget是所有UI元素的基类。它持有一个QWidget* parent指针,天然构成了一棵对象树。当父对象析构时,会自动析构所有子对象,这是一种责任链模式的应用,简化了内存管理。它内部还包含一个指向底层平台窗口的句柄(如X11的Window)。 -
性能分析: 窗口部件的树形结构决定了事件传递和绘制的顺序。一个深层次的控件树可能会增加事件传递的路径。Qt的绘图是增量且局部的,通常只重绘
update()或repaint()请求的区域(脏区域),这是GUI性能的关键优化。
-
-
qpainter.h/.cpp- 绘图引擎:-
设计模式: 策略模式(不同的绘图设备,如屏幕、位图、打印机,使用相同的
QPainter接口)、状态模式(保存/恢复画笔、画刷等状态)。 -
软件设计:
QPainter是一个统一抽象的2D绘图API。它不关心底层是使用X11的Xlib、Windows的GDI,还是macOS的Quartz2D。这是桥接模式的完美体现,将抽象(绘图命令)与实现(平台特定的绘图操作)分离。 -
性能分析: 在X11上,早期Qt可能直接使用Xlib,后来转向XRender等更现代的扩展以改善性能和字体渲染。在内存中绘图(
QPixmap)通常很快,而直接向屏幕绘图则受限于图形驱动和硬件。QPainter进行了大量优化,如路径简化、坐标转换的矩阵运算等。
-
第二部分:QT手动裁剪与最小化物理空间
1. 场景:为何会产生“裁剪”这个概念?
裁剪概念的产生源于嵌入式系统和资源受限设备的兴起。
-
核心场景:
-
嵌入式Linux设备: 如工业控制器、车载信息娱乐系统、智能家电、物联网网关等。这些设备的共同特点是:
-
存储空间有限: Flash/ROM可能只有几十MB甚至几MB。
-
内存有限: RAM可能只有128MB或更少。
-
CPU性能较弱: 通常是ARM/MIPS等低功耗处理器。
-
-
启动时间要求: 设备要求快速启动,较小的库加载更快。
-
安全与维护: 更少的代码意味着更小的攻击面和更少的潜在bug。
-
在这些场景下,一个完整的Qt库(可能超过100MB)是完全不可接受的。因此,必须有一种方法,只保留应用程序真正用到的功能,剔除所有无关代码,从而将最终的库文件(.so)和应用程序体积降到最低。
2. 使QT .so库体积最小的裁剪方法
要达到最小的物理空间,需要一套组合拳,从编译配置到代码编写多管齐下。
-
编译期配置:
configure脚本 这是最核心、最有效的裁剪手段。在编译Qt源码时,运行./configure并传入大量参数来禁用不需要的模块和功能。-
禁用整个模块:
-no-sql-mysql -no-sql-psql -no-qt3d -no-multimedia -no-positioning -no-webengine ...
-
优化编译选项:
-release -optimize-size -no-pch -no-feature-<featurename> ...
-optimize-size让编译器以空间优化为首要目标。-no-pch禁用预编译头文件,虽然会减慢编译速度,但可能减少中间文件复杂度。-no-feature-<featurename>可以禁用更细粒度的功能,所有可用的feature可以通过-list-features查看。 -
静态链接 vs 动态链接:
-
静态链接: 使用
-static。编译器会将你用到的、且未被禁用的Qt代码直接打包进最终的可执行文件。这通常会产生一个比动态链接方式下“应用程序+所有.so”总和更小的体积,因为链接器可以只提取你用到的目标文件中的代码段,并进行更激进的死代码消除。这是获得最小化空间的终极手段。 -
动态链接: 生成多个.so文件。优点是共享,多个应用可以共用一份Qt库。但为了最小化单个.so,你需要将Qt本身也编译成多个更小的、模块化的.so。
-
-
-
链接期优化:链接器死代码消除 这是与静态链接配合使用的关键技术。
-
原理: 当静态链接时,链接器可以看到所有的目标文件(.o)。它会从你的
main函数开始,分析整个调用图,只将那些最终被调用到的函数和数据链接到最终的可执行文件中。未被调用的函数(例如,你从未使用过QFileDialog,那么相关的代码就会被当作“死代码”剔除)。 -
要求: 要使此技术效果最佳,要求代码在编译时使用
-ffunction-sections -fdata-sections选项,链接时使用-Wl,--gc-sections。这样每个函数和数据都会在独立的“section”中,便于链接器精确剔除。
-
-
源代码级优化:
-
避免使用宏大的头文件: 例如,使用
<QWidget>会引入大量声明。如果只需要字符串,就只包含<QString>。 -
谨慎使用模板和内联函数: 它们会“爆炸”式地增加代码体积。
-
使用Qt的轻量级类: 例如,在不需要隐式共享的场景下,考虑使用
QStringView替代QString。
-
-
使用工具进行分析:
-
nm,objdump: 分析二进制文件中的符号,查看哪些函数被链接进去了。 -
bloaty: 一个专门用于分析二进制文件各个部分大小的工具,可以精确到哪个源文件、哪个函数占了多少空间。
-
总结最小化流程:
-
分析你的应用,明确需要哪些Qt模块和功能。
-
使用极简的
configure命令,禁用所有不需要的模块和功能。 -
选择静态链接,并开启编译器和链接器的尺寸优化选项。
-
编译你的应用和Qt库。
-
使用工具分析生成的可执行文件,持续迭代,剔除不必要的代码引用。
3.至今最后一版免费开源版本QT 5.15.2
Qt 5.15.x 的最后一个开源版本(包括 5.15.2, 5.15.13 等)的授权许可是 LGPLv3 和 GPL。只要选择遵守 LGPLv3 条款,就可以免费用于商业闭源项目。
将遵循以下步骤,并在ARM32和ARM64架构上进行对比:
-
环境准备与源码获取
-
配置参数的深度解析与最小化配置
-
编译与安装
-
ARM32与ARM64的树形分析与对比
-
最终优化与验证
3.1. 环境准备与源码获取
首先,你需要一个针对目标架构(ARM32/ARM64)的交叉编译工具链。例如,对于ARM64,可能是 aarch64-linux-gnu-g++,对于ARM32,可能是 arm-linux-gnueabihf-g++。
获取Qt源码: 推荐使用安装程序或Git获取指定版本的源码,例如Qt 5.15 LTS或Qt 6.2+。
wget https://download.qt.io/official_releases/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz tar -xf qt-everywhere-src-5.15.2.tar.xz cd qt-everywhere-src-5.15.2
3.2. 配置参数的深度解析与最小化配置
这是裁剪的核心。创建一个配置脚本来确保可重复性。
创建配置脚本:configure_minimal.sh
#!/bin/bash # 定义变量 BUILD_DIR="build-minimal" INSTALL_DIR="/opt/qt-minimal-5.15.2-arm64" # 根据架构修改,如 ...-arm32 QT_SRC_DIR="$(pwd)" # 设置交叉编译工具链 (示例为ARM64,请根据你的工具链修改) export TOOLCHAIN_DIR="/path/to/your/toolchain" export PATH=$TOOLCHAIN_DIR/bin:$PATH export CROSS_COMPILE="aarch64-linux-gnu-" export SYSROOT="/path/to/your/target/sysroot" # 目标板的根文件系统 # 对于ARM32,工具链可能类似: # export CROSS_COMPILE="arm-linux-gnueabihf-" # 创建构建和安装目录 mkdir -p $BUILD_DIR cd $BUILD_DIR # 核心配置命令 $QT_SRC_DIR/configure \ -prefix $INSTALL_DIR \ -platform linux-g++ \ -xplatform linux-aarch64-gnu-g++ \ # 对于ARM32,使用对应的设备描述符,例如: # -xplatform linux-arm-gnueabi-g++ \ -sysroot $SYSROOT \ \ ### 编译模式和优化 ### -release \ # 发布模式,去除调试符号和断言 -optimize-size \ # 优化目标为尺寸而非速度 -no-pch \ # 禁用预编译头文件,减少复杂性和依赖 -ltcg \ # 链接时代码生成,更激进的死代码消除(Qt5部分版本/Qt6支持) -reduce-relocations \ # 减少重定位,优化动态库大小 \ ### 静态链接配置 (实现最小体积的终极手段) ### -static \ # 生成静态库 -static-runtime \ # 静态链接C++运行时库 \ ### 核心功能裁剪:禁用几乎所有非核心GUI模块 ### -no-opengl \ -no-dbus \ -no-icu \ -no-glib \ -no-gif \ -no-ico \ -no-libjpeg \ -no-libpng \ -no-compile-examples \ -no-sql-db2 -no-sql-ibase -no-sql-mysql -no-sql-oci -no-sql-odbc -no-sql-psql -no-sql-sqlite \ -no-qt3d \ -no-activeqt \ -no-multimedia \ -no-network \ -no-positioning \ -no-printsupport \ # 注意:如果你的“初始显示控件”需要打印,则保留 -no-sensors \ -no-serialport \ -no-sql \ -no-testlib \ -no-webkit -no-webengine -no-widgets \ # 注意:-no-widgets 会移除所有GUI控件,这里*需要*控件,所以不能加! -no-xml \ -no-xcb \ # 禁用X11,使用LinuxFB直接操作帧缓冲区 \ ### 细粒度功能裁剪 (-no-feature-*) ### # 这些是获得极致体积的关键 -no-feature-accessibility \ -no-feature-animation \ -no-feature-clipboard \ -no-feature-colordialog \ -no-feature-commandlinkbutton \ -no-feature-concurrent \ -no-feature-dial \ -no-feature-filedialog \ -no-feature-fontdialog \ -no-feature-freetype \ -no-feature-ftp \ -no-feature-gestures \ -no-feature-graphicsview \ -no-feature-http \ -no-feature-imageformat-bmp \ -no-feature-imageformat-jpeg \ -no-feature-imageformat-png \ -no-feature-imageformat-ppm \ -no-feature-imageformat-xbm \ -no-feature-imageformat-xpm \ -no-feature-im \ -no-feature-inputdialog \ -no-feature-itemviews \ -no-feature-keysequenceedit \ -no-feature-lcdnumber \ -no-feature-mdiarea \ -no-feature-messagebox \ -no-feature-paintdebug \ -no-feature-progressdialog \ -no-feature-proxymodel \ -no-feature-sessionmanager \ -no-feature-socks5 \ -no-feature-sqlmodel \ -no-feature-statemachine \ -no-feature-syntaxhighlighter \ -no-feature-textbrowser \ -no-feature-textmarkdownwriter \ -no-feature-textodfwriter \ -no-feature-toolbar \ -no-feature-toolbutton \ -no-feature-tooltip \ -no-feature-undo \ -no-feature-wizard \ -no-feature-css \ \ ### 强制启用最小核心GUI和LinuxFB ### -gui \ -widgets \ # 必须启用,因为依赖初始控件(QPushButton, QLabel等) -qt-zlib \ # 使用内置的最小zlib -qt-freetype \ # 使用内置的freetype(如果必须渲染文字) -linuxfb \ # 使用Linux帧缓冲区,最轻量的显示后端 \ -nomake examples -nomake tests -nomake tools # 不编译示例和工具 echo "Configuration complete. Now run 'make -j$(nproc)' and 'make install'."
关键点解释:
-
-static与-static-runtime: 这是实现最小体积的最关键决策。静态链接允许链接器进行全局死代码消除,只将应用程序实际调用的代码打包进去。 -
-no-feature-*: 这些参数比-no-<module>更细致。例如,即使你保留了-widgets模块,也可以通过-no-feature-filedialog来移除QFileDialog相关的所有代码。通过./configure -list-features可以查看所有可裁剪的功能。 -
-linuxfb: 对于无X11/Wayland的嵌入式环境,这是最直接的显示方式,依赖最少,体积最小。 -
-optimize-size -no-pch -ltcg: 这一套组合拳从编译器、链接器层面全方位优化尺寸。
3.3. 编译与安装
给脚本执行权限并运行。
chmod +x configure_minimal.sh ./configure_minimal.sh
在 $BUILD_DIR 中开始编译:
# 使用所有CPU核心编译,加快速度 make -j$(nproc) # 安装到配置时指定的 $INSTALL_DIR make install
编译完成后,在 $INSTALL_DIR 目录下就是你裁剪后的Qt库。
3.4. ARM32与ARM64的树形分析与对比
分别对ARM32和ARM64执行上述流程,然后在安装目录下使用 tree 和 du 命令进行分析。
树形结构分析 (tree 命令)
ARM64 最小化安装目录结构 (示例):
/opt/qt-minimal-5.15.2-arm64/ ├── bin/ │ ├── moc # 元对象编译器 (宿主机的二进制文件,体积固定) │ ├── qmake # 构建工具 (宿主机的二进制文件,体积固定) │ └── ... ├── lib/ │ ├── libQt5Core.a # 核心库,静态库 │ ├── libQt5Gui.a # GUI库,静态库 │ ├── libQt5Widgets.a # 控件库,静态库 │ └── ... └── ...
ARM32 最小化安装目录结构: 结构完全一致,只是库文件是针对ARM32架构编译的。
关键观察:
-
由于使用静态编译,最终的输出是
.a文件,而不是.so。目标是最终应用程序的体积,而不是动态库的体积。 -
工具(如
moc,qmake)是运行在宿主机上的,它们的体积与目标架构无关,是固定的。
体积对比分析 (du -sh 和 ls -lh 命令)
假设编译一个只显示一个按钮的极简程序 main.cpp:
#include <QApplication>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPushButton button("Minimal Qt");
button.show();
return a.exec();
}
使用安装目录下的 qmake 和 make 来编译它。
编译应用程序 (在宿主机上,使用刚编译的Qt):
export QT_INSTALL_DIR=/opt/qt-minimal-5.15.2-arm64 $QT_INSTALL_DIR/bin/qmake -project $QT_INSTALL_DIR/bin/qmake make -j$(nproc)
使用 aarch64-linux-gnu-strip 对生成的最终可执行文件进行剥离,去除所有符号表和调试信息。
然后,分析最终的可执行文件:
| 架构 | 最终可执行文件大小 (Strip后) | 主要组成部分 (使用 bloaty 分析) |
|---|---|---|
| ARM64 | ~ 4-6 MB | - [.text] 段: 主要的程序代码 (来自你的app和Qt) - [.rodata] 段: 只读数据 (字符串常量等) - [.data] / [.bss]: 已初始化/未初始化数据 |
| ARM32 | ~ 3-5 MB | 同上 |
对比分析与结论:
-
体积差异原因:
-
指令集: ARM64是64位指令集,通常指令本身占用的空间会比ARM32的32位指令稍大。
-
寄存器数量: ARM64有更多的通用寄存器,可能会减少对栈的访问,但指令编码格式可能不同。
-
对齐要求: 64位系统对内存地址对齐的要求可能更严格,可能引入少量填充。
-
结果: 在进行了极致裁剪后,ARM64的可执行文件通常比ARM32大 10%~30%。这个差距已经通过静态链接和死代码消除被大大缩小。
-
-
树形结构对比结论:
-
结构一致性: 两个架构的安装目录树形结构完全一致。这证明了Qt构建系统的一致性。
-
内容本质差异: 唯一的区别在于
lib/目录下的静态库文件内容,它们包含了不同CPU架构的机器码。从文件系统树来看,没有差异。
-
3.5. 最终优化与验证
-
链接器优化: 确保在编译你的应用程序时,在
.pro文件或Makefile中传递了链接器优化标志。QMAKE_LFLAGS += -Wl,--gc-sections QMAKE_CFLAGS += -ffunction-sections -fdata-sections QMAKE_CXXFLAGS += -ffunction-sections -fdata-sections
这允许链接器移除未被使用的函数和数据段。
-
使用分析工具:
-
bloaty: 强烈推荐。它可以告诉你可执行文件中哪个符号、哪个源文件占用了最多空间。bloaty your_minimal_app -n 20 --domain=compileunits
-
aarch64-linux-gnu-nm/arm-linux-gnueabihf-nm: 查看二进制文件中的符号。aarch64-linux-gnu-nm --size-sort your_minimal_app | tail -20
这可以列出最大的符号。
-
-
验证功能: 将编译好的最小可执行文件放到目标板上运行,确保按钮能正常显示和响应。使用
top或ps查看其内存占用,也会非常小。
通过这套完整的流程,你可以为ARM32和ARM64嵌入式平台生成一个仅包含最基本显示控件的、体积最小的Qt应用程序。核心在于静态链接、激进的模块和功能裁剪以及链接器级别的死代码消除。
在 Qt 4.0 时代,ARM64 架构还没有正式支持,可以通过交叉编译的方式让 Qt 4.0 在 ARM64 上运行。以下是详细的配置方案:
4.Qt 4.0 ARM64 强制移植配置
#!/bin/bash
# Qt 4.0 ARM64 强制移植配置脚本
# 注意:这需要自定义工具链和补丁
# 定义变量
BUILD_DIR="build-qt4-arm64-forced"
INSTALL_DIR="/opt/qt4-forced-arm64"
QT_SRC_DIR="$(pwd)"
# 设置 ARM64 交叉编译工具链
export TOOLCHAIN_DIR="/path/to/aarch64-toolchain"
export PATH=$TOOLCHAIN_DIR/bin:$PATH
export CROSS_COMPILE="aarch64-linux-gnu-"
export SYSROOT="/path/to/arm64-sysroot"
# 设置编译器和工具
export CC="${CROSS_COMPILE}gcc"
export CXX="${CROSS_COMPILE}g++"
export AR="${CROSS_COMPILE}ar"
export STRIP="${CROSS_COMPILE}strip"
export RANLIB="${CROSS_COMPILE}ranlib"
# 创建构建目录
mkdir -p $BUILD_DIR
cd $BUILD_DIR
# 应用必要的补丁(如果需要)
echo "Applying ARM64 compatibility patches..."
# patch -p1 < ../qt4-arm64-atomic.patch
# Qt 4.0 ARM64 强制配置
$QT_SRC_DIR/configure \
### 基础架构配置 ###
-prefix $INSTALL_DIR \
-platform linux-g++ \
-xplatform linux-g++ \ # 使用通用的 linux-g++,手动覆盖工具链
-sysroot $SYSROOT \
\
### 工具链手动覆盖 ###
-cc $CC \
-cxx $CXX \
-ar $AR \
-strip $STRIP \
\
### ARM64 特定优化 ###
-release \
-no-debug \
-optimize-size \
-no-exceptions \
-no-rtti \
\
### 静态链接配置 ###
-static \
-qt3support \
\
### 架构特性调整 ###
-no-mmx \
-no-3dnow \
-no-sse \
-no-sse2 \
-no-neon \ # ARM64 可能需要处理 NEON 支持
\
### 核心模块裁剪 ###
-no-opengl \
-no-webkit \
-no-script \
-no-scripttools \
-no-multimedia \
-no-audio-backend \
-no-phonon \
-no-svg \
-no-xmlpatterns \
-no-dbus \
-no-openssl \
-no-glib \
-no-icu \
-no-pch \
\
### 数据库支持裁剪 ###
-no-sql-ibase \
-no-sql-mysql \
-no-sql-odbc \
-no-sql-psql \
-no-sql-sqlite \
\
### 图像格式裁剪 ###
-no-gif \
-no-libmng \
-no-libjpeg \
-no-libpng \
-no-tiff \
\
### 显示和输入配置 ###
-qt-gfx-linuxfb \
-no-gfx-vnc \
-no-gfx-qvfb \
-qt-mouse-tslib \ # 触摸屏支持
-qt-kbd-tty \
\
### 强制启用核心功能 ###
-qt-gui \
-qt-zlib \
-no-freetype \
\
### 构建控制 ###
-nomake examples \
-nomake demos \
-nomake tools \
\
### 兼容性选项 ###
-no-accessibility \
-no-stl \
-no-largefile \
-DQT_ARCH_ARMV8 \ # 强制定义 ARMv8 架构
-DQT_NO_ATOMIC_ARM64 \ # 如果原子操作有问题则禁用
echo "Qt 4.0 ARM64 forced configuration complete."
必要的补丁文件
由于 Qt 4.0 原生不支持 ARM64,可能需要创建补丁文件:
4.1. ARM64 原子操作补丁 qt4-arm64-atomic.patch
--- src/corelib/arch/qatomic_arm.h
+++ src/corelib/arch/qatomic_arm.h
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QATOMIC_ARM64_H
+#define QATOMIC_ARM64_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_LINUX
+# include <asm/unistd.h>
+#endif
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_CC_GNU)
+
+/* ARM64 asm implementation */
+
+template <int size> struct QAtomicOpsBySize;
+
+template <> struct QAtomicOpsBySize<4> {
+ static inline Q_ALWAYS_INLINE bool isTestAndSetNative() { return true; }
+ static inline Q_ALWAYS_INLINE bool isTestAndSetWaitFree() { return true; }
+
+ static inline Q_ALWAYS_INLINE bool testAndSetRelaxed(int &_q_value, int expectedValue, int newValue)
+ {
+ int result;
+ __asm__ __volatile__(
+ "0: ldaxr %w0, [%1]\n"
+ " cmp %w0, %w2\n"
+ " b.ne 1f\n"
+ " stlxr %w0, %w3, [%1]\n"
+ " cbnz %w0, 0b\n"
+ "1:"
+ : "=&r" (result)
+ : "r" (&_q_value), "r" (expectedValue), "r" (newValue)
+ : "memory", "cc");
+ return result == 0;
+ }
+
+ // 添加其他必要的原子操作...
+};
+
+#endif // Q_CC_GNU
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QATOMIC_ARM64_H
4.2. 配置脚本增强版
创建更完整的配置脚本 configure_qt4_arm64_advanced.sh:
#!/bin/bash
# Qt 4.0 ARM64 高级强制移植配置
# 定义变量
BUILD_DIR="build-qt4-arm64-advanced"
INSTALL_DIR="/opt/qt4-arm64-advanced"
QT_SRC_DIR="$(pwd)"
# ARM64 工具链配置
export TOOLCHAIN_DIR="/usr/aarch64-linux-gnu"
export CROSS_COMPILE="aarch64-linux-gnu-"
export SYSROOT="${TOOLCHAIN_DIR}"
export CC="${CROSS_COMPILE}gcc"
export CXX="${CROSS_COMPILE}g++"
export AR="${CROSS_COMPILE}ar"
export STRIP="${CROSS_COMPILE}strip"
export RANLIB="${CROSS_COMPILE}ranlib"
export LD="${CROSS_COMPILE}ld"
export OBJCOPY="${CROSS_COMPILE}objcopy"
# 设置编译标志
export CFLAGS="-march=armv8-a -mtune=cortex-a53 -O2 -fPIC"
export CXXFLAGS="-march=armv8-a -mtune=cortex-a53 -O2 -fPIC"
export LDFLAGS="-Wl,-O1 -Wl,--as-needed"
# 创建构建目录
mkdir -p $BUILD_DIR
cd $BUILD_DIR
echo "=== Qt 4.0 ARM64 Forced Porting ==="
echo "Toolchain: $CC"
echo "Sysroot: $SYSROOT"
echo "Build dir: $BUILD_DIR"
echo "Install dir: $INSTALL_DIR"
# 创建自定义的 mkspec(关键步骤)
mkdir -p mkspecs/linux-arm64-g++
cat > mkspecs/linux-arm64-g++/qmake.conf << 'EOF'
MAKEFILE_GENERATOR = UNIX
TARGET_PLATFORM = unix
TEMPLATE = app
CONFIG += qt warn_on release incremental link_prl
QT += core gui
QMAKE_CC = aarch64-linux-gnu-gcc
QMAKE_CXX = aarch64-linux-gnu-g++
QMAKE_LINK = aarch64-linux-gnu-g++
QMAKE_LINK_SHLIB = aarch64-linux-gnu-g++
QMAKE_AR = aarch64-linux-gnu-ar cqs
QMAKE_OBJCOPY = aarch64-linux-gnu-objcopy
QMAKE_STRIP = aarch64-linux-gnu-strip
QMAKE_CFLAGS = -march=armv8-a -mtune=cortex-a53 -O2 -fPIC
QMAKE_CXXFLAGS = -march=armv8-a -mtune=cortex-a53 -O2 -fPIC
QMAKE_LFLAGS = -Wl,-O1
load(qt_config)
EOF
# 配置命令
$QT_SRC_DIR/configure \
-verbose \
-prefix $INSTALL_DIR \
-platform linux-g++ \
-xplatform linux-arm64-g++ \
-sysroot $SYSROOT \
\
-release \
-optimize-size \
-no-debug \
-no-exceptions \
-no-rtti \
\
-static \
-qt3support \
\
# 架构特定调整
-no-mmx -no-3dnow -no-sse -no-sse2 \
\
# 模块裁剪
-no-opengl \
-no-webkit \
-no-script \
-no-scripttools \
-no-multimedia \
-no-svg \
-no-dbus \
-no-openssl \
-no-glib \
-no-icu \
\
# 显示配置
-qt-gfx-linuxfb \
-no-gfx-vnc \
-no-gfx-qvfb \
\
# 输入配置
-qt-mouse-tslib \
-qt-kbd-tty \
\
# 核心功能
-qt-gui \
-qt-zlib \
-no-freetype \
-no-libjpeg \
-no-libpng \
\
# 构建控制
-nomake examples \
-nomake demos \
-nomake tools \
\
# 兼容性
-no-accessibility \
-no-stl \
-no-largefile \
-D__ARM_ARCH_8__ \
-D__aarch64__
# 检查配置结果
if [ $? -eq 0 ]; then
echo "=== Configuration successful ==="
echo "Run: make -j$(nproc) && make install"
else
echo "=== Configuration failed ==="
echo "Check the config.log for details"
fi
构建和调试步骤
4.2.1. 准备工具链
# 在 Ubuntu/Debian 上安装 ARM64 工具链 sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
4.2.2. 应用补丁和配置
# 应用必要的补丁 cd qt-everywhere-opensource-src-4.0.0 patch -p1 < ../qt4-arm64-atomic.patch # 运行配置脚本 chmod +x configure_qt4_arm64_advanced.sh ./configure_qt4_arm64_advanced.sh
4.2.3. 处理常见编译错误
错误1:原子操作不支持
# 在 src/corelib/arch/ 创建 qatomic_arm64.h # 使用上面提供的补丁内容
错误2:汇编语法错误
# 修改 src/corelib/arch/qatomic_arm.cpp # 将 ARM32 汇编替换为 ARM64 汇编
错误3:类型大小不匹配
# 在配置时添加定义 -DQT_POINTER_SIZE=8 \ -D__LP64__=1 \
4.2.4. 测试应用程序
// 简单的测试程序 test_arm64.cpp
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QLabel label("Qt 4.0 running on ARM64!");
label.show();
return app.exec();
}
编译测试程序:
export QT_INSTALL_DIR=/opt/qt4-arm64-advanced $QT_INSTALL_DIR/bin/qmake -project $QT_INSTALL_DIR/bin/qmake make # 检查生成的二进制文件 file test_arm64 # 应该显示:test_arm64: ELF 64-bit LSB executable, ARM aarch64, version 1...
注意事项
-
原子操作:Qt 4.0 的原子操作需要为 ARM64 重新实现
-
字节序:ARM64 是小端架构,与 Qt 4.0 的假设一致
-
对齐要求:ARM64 有严格的对齐要求
-
系统调用:可能需要调整系统调用号
-
浮点运算:ARM64 使用不同的浮点寄存器组
这种方法虽然复杂,但可以让 Qt 4.0 在 ARM64 架构上运行,适合特定的嵌入式或遗留系统迁移场景。
5.Qt 4.x 版本关键变更分析
| 版本 | 引入模块 | 移除/废弃模块 | 功能变更 |
|---|---|---|---|
| 4.0 (2005) | - QtNetwork - QtSql - QtXml - QtOpenGL - QtSvg - QtTest | - Qt 3.x 的兼容类开始废弃 - 旧的绘画系统 | - 完全模块化架构 - 新的绘画系统 Arthur - 新的构建系统 qmake |
| 4.1 (2005) | - QtWebKit (技术预览版) - QtUiTools | - WebKit 集成 - 插件系统改进 | |
| 4.2 (2006) | - QtDBus - QtHelp | - D-Bus 支持 - 帮助系统 | |
| 4.3 (2007) | - QtScript | - ECMAScript 支持 - 性能优化 | |
| 4.4 (2008) | - QtWebKit (正式版) - QtMultimedia - Phonon 模块 | - 多媒体框架 - 并发编程支持 | |
| 4.5 (2009) | - QtScriptTools | - WebKit 性能大幅提升 - 新的动画框架 | |
| 4.6 (2009) | - QtDeclarative (技术预览) - QtMobility | - QML 引入 - 移动设备支持 | |
| 4.7 (2010) | - QtDeclarative (正式版) | - QML 成熟 - 新的图形视图框架 | |
| 4.8 (2011) | - 部分 Qt 3.x 兼容类完全移除 | - 最后 LTS 版本 - 性能优化 |
Qt 4.0 最小裁剪配置脚本
#!/bin/bash # Qt 4.0 最小化裁剪配置脚本 # 注意:Qt 4.x 时代的配置选项与现代 Qt 5/6 有很大差异 # 定义变量 BUILD_DIR="build-qt4-minimal" INSTALL_DIR="/opt/qt-minimal-4.0-arm" QT_SRC_DIR="$(pwd)" # 设置交叉编译工具链 (ARM32 示例) export TOOLCHAIN_DIR="/path/to/your/arm-toolchain" export PATH=$TOOLCHAIN_DIR/bin:$PATH export CROSS_COMPILE="arm-linux-gnueabi-" export SYSROOT="/path/to/your/arm-sysroot" # 创建构建目录 mkdir -p $BUILD_DIR cd $BUILD_DIR # Qt 4.0 核心配置命令 $QT_SRC_DIR/configure \ ### 基础配置 ### -prefix $INSTALL_DIR \ -platform linux-g++ \ -xplatform linux-arm-g++ \ -embedded arm \ -sysroot $SYSROOT \ \ ### 编译模式和优化 ### -release \ # 发布模式 -no-debug \ # 禁用调试 -no-exceptions \ # 禁用异常(减少体积) -no-rtti \ # 禁用 RTTI(减少体积) -optimize-size \ # 尺寸优化 \ ### 静态链接配置 ### -static \ # 静态链接 -qt3support \ # 注意:Qt4 默认包含 Qt3 支持,需要显式禁用 \ ### 核心模块裁剪 ### -no-opengl \ # 禁用 OpenGL -no-webkit \ # 禁用 WebKit(4.0 还没有,但保留兼容性) -no-script \ # 禁用脚本 -no-scripttools \ # 禁用脚本工具 -no-multimedia \ # 禁用多媒体 -no-audio-backend \ # 禁用音频后端 -no-phonon \ # 禁用 Phonon -no-phonon-backend \ # 禁用 Phonon 后端 -no-svg \ # 禁用 SVG -no-xmlpatterns \ # 禁用 XML 模式 -no-dbus \ # 禁用 D-Bus -no-nas-sound \ # 禁用 NAS 声音 -no-openssl \ # 禁用 SSL -no-glib \ # 禁用 Glib -no-gstreamer \ # 禁用 GStreamer -no-icu \ # 禁用 ICU -no-pch \ # 禁用预编译头文件 \ ### 数据库支持裁剪 ### -no-sql-ibase \ -no-sql-mysql \ -no-sql-odbc \ -no-sql-psql \ -no-sql-sqlite \ -no-sql-sqlite2 \ \ ### 图像格式裁剪 ### -no-gif \ -no-libmng \ -no-libjpeg \ -no-libpng \ -no-tiff \ -no-mmx \ -no-3dnow \ -no-sse \ -no-sse2 \ \ ### 字体和样式裁剪 ### -no-freetype \ -no-fontconfig \ -no-sm \ # 禁用会话管理 -no-xshape \ -no-xsync \ -no-xinerama \ -no-xcursor \ -no-xfixes \ -no-xrandr \ -no-xrender \ -no-mitshm \ -no-xinput \ -no-nis \ -no-cups \ -no-iconv \ \ ### 显示后端配置 ### -qt-gfx-linuxfb \ # Linux 帧缓冲区 -no-gfx-vnc \ -no-gfx-transformed \ -no-gfx-qvfb \ -no-gfx-multiscreen \ \ ### 鼠标和输入设备 ### -qt-mouse-pc \ -no-mouse-linuxtp \ -no-mouse-tslib \ -no-mouse-qvfb \ -no-mouse-pc \ \ ### 键盘输入 ### -qt-kbd-tty \ # TTY 键盘 -no-kbd-qvfb \ -no-kbd-sl5000 \ \ ### 强制启用最小核心功能 ### -qt-gui \ # 启用 GUI 模块 -qt-sql-sqlite \ # 使用内置 SQLite(如果需要) -qt-zlib \ # 使用内置 zlib \ ### 构建控制 ### -nomake examples \ # 不编译示例 -nomake demos \ # 不编译演示 -nomake docs \ # 不编译文档 -nomake tools \ # 不编译工具 \ ### Qt 4 特定的配置 ### -depths 8,16,32 \ # 指定颜色深度 -no-largefile \ # 禁用大文件支持 -no-accessibility \ # 禁用无障碍支持 -no-stl \ # 禁用 STL(激进裁剪) -no-openssl \ # 禁用 OpenSSL -no-nis \ # 禁用 NIS -no-cups \ # 禁用 CUPS 打印支持 -no-iconv \ # 禁用 iconv -no-pcre \ # 禁用 PCRE echo "Qt 4.0 minimal configuration complete." echo "Now run: make -j$(nproc) && make install"
Qt 4.x 配置与现代 Qt 的主要差异
5.1. 配置系统差异
# Qt 4.x 特有的选项 -embedded arm # 嵌入式目标指定 -depths 8,16,32 # 颜色深度控制 -qt-gfx-linuxfb # 显示后端配置方式不同 -qt-mouse-pc # 输入设备配置 # 与现代 Qt 不同的选项 -no-qt3support # Qt4 需要显式禁用 Qt3 兼容 -no-stl # 可禁用 STL(激进做法) -no-exceptions # 可禁用异常 -no-rtti # 可禁用 RTTI
5.2. 模块化程度差异
-
Qt 4.0 模块化刚刚开始,很多功能还在核心库中
-
功能裁剪主要通过
-no-<feature>而非-no-feature-<featurename> -
没有细粒度的特性系统,裁剪相对粗放
5.3. 编译优化差异
# Qt 4.x 可用的激进优化 -no-exceptions # 现代 Qt 通常不建议使用 -no-rtti # 可能影响某些功能 -no-stl # 现代 Qt 已不可用
5.4. 目标平台配置
# Qt 4.x 的嵌入式配置方式 -embedded arm -xplatform linux-arm-g++ -qt-gfx-linuxfb -qt-mouse-tslib # 触摸屏支持
构建和执行
-
准备环境:
chmod +x configure_qt4_minimal.sh ./configure_qt4_minimal.sh
-
编译安装:
cd build-qt4-minimal make -j$(nproc) make install
-
验证结果:
# 检查安装目录 ls -la $INSTALL_DIR/lib # 应该只看到核心的静态库:libQtCore.a, libQtGui.a 等
这个 Qt 4.0 的最小化配置体现了早期 Qt 嵌入式开发的典型做法,与现代 Qt 相比,配置选项更加直接但功能粒度较粗。
6.从 Qt 4.x 到当前 Qt 6.x 时代,configure 指令功能模块的主要变化历程:
| 时期 / 版本 | 引入的主要功能 / 模块 (代表性) | 移除 / 废弃的功能 / 模块 (代表性) | configure 系统的核心变化与影响 |
|---|---|---|---|
| Qt 4.x (2005) | • 模块化:-qt-gui (QtGui), -qt-network (QtNetwork), -qt-sql (QtSql), -qt-xml (QtXml), -qt-webkit (QtWebKit, 4.4), -qt-script (QtScript), -qt-multimedia (QtMultimedia, 4.4), -qt-declarative (QtDeclarative, QML基础, 4.7) • 图形:-qt-opengl (QtOpenGL) • 图像格式:-qt-svg (QtSvg) |
• 开始废弃一些更陈旧的、Qt 3.x 时代的兼容接口和类。 | • 奠定模块化基础:configure 开始支持通过 -no-<module> 参数排除整个模块,如 -no-webkit 。 • 嵌入式裁剪:引入 -qconfig 选项,允许通过自定义头文件(如 qconfig-small.h)精细裁剪特性(Feature),这是 Qt Lite 概念的早期实践 。 |
| Qt 5.x (2012) | • 模块拆分与新增:-qt-widgets (从 QtGui 拆分), -qt-quick (QtQuick), -qt-3d (Qt3D), -qt-serialport (QtSerialPort, 5.1), -qt-webengine (QtWebEngine, 基于 Chromium, 5.6 替代 QtWebKit) • 移动与嵌入式:-qt-bluetooth (QtBluetooth, 5.2), -qt-positioning (QtPositioning, 5.2) |
• -qt-webkit:在 5.6 版本被标记为废弃,并由 QtWebEngine 替代 。 • -script 等:QtScript 等相关模块开始被废弃,QML 和 JavaScript 成为更主流的脚本方案。 |
• Qt Lite 项目:在 Qt 5.8 引入 -feature-<name> 和 -no-feature-<name> 参数,支持在模块内进行更细粒度的功能裁剪(如 -no-feature-clipboard)。可通过 ./configure -list-features 查看列表 。 • 构建部分:支持 -nomake examples 和 -nomake tests 来跳过示例和测试的编译 。 |
| Qt 6.x (2020) | • 现代化模块:-qt-quick3d (QtQuick3D), -qt-shadertools (QtShaderTools), -qt-languageserver (QtLanguageServer) • 兼容性模块:-qt-5compat (Qt5Compat) • 网络与通信:-qt-httpserver (QtHttpServer, 6.3), -qt-grpc (QtGrpc, 6.3) |
• 大量废弃模块:QtScript 被完全移除。在 6.0 初期,QtWebEngine 也暂时缺席(6.2 回归)。 • 构建系统革命:qmake 不再是 Qt 自身的构建工具。 | • 构建系统切换:configure 成为 CMake 的封装器 。所有配置最终由 CMake 处理。 • 新的配置选项:引入如 -link-time-optimization (LTO)、-gc-binaries 等用于优化和缩减体积的选项 。 • 模块管理:使用 -skip 和 -submodules 来排除或包含子模块 。 |
Qt 5.x 之前版本的配置特点
由于资料有限,对于 Qt 1.x 到 3.x 的时代,只能勾勒出其配置系统的大致轮廓:
-
Qt 3.x 及更早版本:那时的 Qt 库相对单一和集中。
configure脚本的选项远没有现在丰富,主要侧重于基础性的配置,例如:-
指定安装路径(
-prefix)。 -
选择编译类型(
-release或-debug)。 -
启用或禁用有限的组件,比如可能包括对 OpenGL 的支持。
-
调整平台特定的设置。
-
其核心思想是 "全部构建"或"少量排除",缺乏后来版本中精细的模块化和裁剪能力。
-
最新版 Qt 6 配置指令精要总结
进入 Qt 6 时代,配置指令全面转向以 CMake 为底层。以下是当前进行定制化构建,尤其是为了裁剪体积时,最核心和剩下常用的指令分类:
-
构建模式与优化
-
-static:生成静态链接库,是减少依赖和最终发布体积的关键。 -
-release:使用发布模式编译,移除调试符号。 -
-optimize-size:优化目标为尺寸而非速度。 -
-link-time-optimization(LTO):链接时优化,有助于进一步减小体积和提升性能。 -
-gc-binaries:与编译器标志(如-ffunction-sections -fdata-sections)和链接器标志(如-Wl,--gc-sections)结合,移除未使用的代码。
-
-
模块管理
-
-submodules <module1,module2,...>:仅编译指定的子模块及其依赖。 -
-skip <module>:从构建中排除指定的子模块。 -
-nomake examples和-nomake tests:不编译示例和测试,节省时间。
-
-
功能级裁剪
-
-no-feature-<featurename>:禁用 Qt 模块内部的特定功能,这是实现精细裁剪的利器。使用./configure -list-features查看所有可用特性。
-
-
第三方库
-
-system-<lib>或-qt-<lib>:选择使用系统上的第三方库还是 Qt 捆绑的库,例如-system-zlib。
-
-
平台与工具链
-
-prefix <dir>:指定安装目录。 -
-sysroot <dir>:指定目标系统的根目录,对交叉编译至关重要。 -
通过
-DCMAKE_TOOLCHAIN_FILE=path传递工具链文件给 CMake。
-
Qt 的 configure 系统演进史,是一部从 "大而全" 到 "精细可控" 的进化史:
-
Qt 4.x 开启了模块化,并针对嵌入式引入了初步的特性裁剪(
-qconfig)。 -
Qt 5.x 深化了模块化,并通过 Qt Lite 项目带来了革命性的功能级裁剪(
-no-feature-xxx)。 -
Qt 6.x 则完成了构建系统的现代化,全面转向 CMake,并将所有配置统一于此。
7.Qt模块与功能变更完整追踪方法
7.1. 获取历史数据的权威方法
# 获取完整的Qt历史仓库(巨大,约4GB+) git clone https://code.qt.io/qt/qt5.git cd qt5 # 查看模块引入的历史记录 git log --oneline --grep="Add.*module" --all git log --oneline --grep="Remove.*module" --all # 分析特定模块的历史 git log --oneline -- src/qt3d/ git log --oneline -- src/qtwebengine/
7.2. Qt主要版本模块演进树形分析
Qt 4.x 时代 (2005-2011)
基础模块结构:
qt4/ ├── core/ # QtCore - 1995年最初引入 ├── gui/ # QtGui - 1995年最初引入 ├── network/ # QtNetwork - Qt 4.0 (2005) ├── sql/ # QtSql - Qt 4.0 (2005) ├── xml/ # QtXml - Qt 4.0 (2005) ├── opengl/ # QtOpenGL - Qt 4.0 (2005) ├── svg/ # QtSvg - Qt 4.0 (2005) ├── script/ # QtScript - Qt 4.3 (2007) ├── webkit/ # QtWebKit - Qt 4.4 (2008) ✨新增 ├── multimedia/ # QtMultimedia - Qt 4.4 (2008) ✨新增 ├── declarative/ # QtDeclarative (QML) - Qt 4.7 (2010) ✨新增 └── scripttools/ # QtScriptTools - Qt 4.5 (2009)
关键patch示例:
-
commit 123abc (2008):
Add QtWebKit module - Web rendering engine based on WebKit -
commit 456def (2010):
Introduce QtDeclarative module for QML support
Qt 5.x 时代 (2012-2020)
模块化重构 - Qt 5.0 (2012):
qt5/ ├── base/ │ ├── core/ # QtCore │ ├── gui/ # QtGui (拆分出窗口系统无关部分) │ ├── widgets/ # QtWidgets ✨新增 (从QtGui拆分) │ ├── network/ # QtNetwork │ └── ... ├── addons/ │ ├── qt3d/ # Qt3D - Qt 5.0 ✨新增 │ ├── qtquick1/ # QtQuick1 (兼容Qt4 QML) │ ├── qtserialport/ # QtSerialPort - Qt 5.1 ✨新增 │ └── ... ├── graphics/ │ ├── qtdeclarative/ # QtQml, QtQuick ✨重构 │ └── ... └── ...
Qt 5.x 版本关键变更:
| 版本 | 引入模块 | 移除/废弃模块 | 功能变更 |
|---|---|---|---|
| 5.0 (2012) | - QtWidgets - QtQml - QtQuick - Qt3D - QtLocation - QtSensors | - QtWebKit (标记为废弃) - QtScript (开始废弃) | - 图形架构重构 - QML成为一等公民 |
| 5.1 (2013) | - QtSerialPort - QtXmlPatterns | - Android/iOS支持 | |
| 5.2 (2013) | - QtBluetooth - QtNfc - QtPositioning | - WinRT支持 | |
| 5.4 (2015) | - QtWinExtras - QtMacExtras - QtX11Extras | - 高性能Shader效果 | |
| 5.6 (2016) | - QtWebEngine ✨新增 (替代WebKit) | - QtWebKit (正式移除) | - 长期支持版本 |
| 5.7 (2016) | - QtGamepad - Qt3DAnimation - Qt3DExtras | - 3D功能增强 | |
| 5.9 (2017) | - QtRemoteObjects - QtSpeech | - LTS版本 - 进程间通信增强 | |
| 5.12 (2018) | - QtShaderTools - QtWaylandCompositor | - QtScriptTools (废弃) | - 现代图形管线 |
| 5.15 (2020) | - QtLottie - QtQuick3D | - 最后5.x LTS |
Qt 6.x 时代 (2020-现在)
架构重大重构 - Qt 6.0 (2020):
qt6/ ├── qtbase/ # 核心基础模块重构 ├── qt5compat/ # Qt5兼容模块 ✨新增 ├── qtshadertools/ # 着色器工具 (提升为核心) ├── qtquick3d/ # 3D渲染 (从附加模块提升) ├── qtmultimedia/ # 多媒体重构 ├── qtpositioning/ # 定位服务 ├── qtnetwork/ # 网络栈现代化 ├── qtlanguageserver/ # 语言服务器协议 ✨新增 └── ...
Qt 6.x 版本关键变更:
| 版本 | 引入模块 | 移除/废弃模块 | 功能变更 |
|---|---|---|---|
| 6.0 (2020) | - qt5compat - qtlanguageserver - qtquick3dphysics | - QtScript (完全移除) - QtWebEngine (暂不包含) - QtMultimediaWidgets (移除) | - CMake构建系统 - C++17要求 - 新图形架构 |
| 6.2 (2021) | - QtWebEngine ✨回归 - QtPdf - QtQuick3D | - WebEngine回归 - 3D功能增强 | |
| 6.3 (2022) | - QtHttpServer - QtGrpc - QtQuick3DParticleEffects | - 微服务支持 - gRPC集成 | |
| 6.4 (2022) | - QtPositioningQuick - QtSpacialAudio | - 部分Qt5兼容类 | - 定位服务增强 - 空间音频 |
| 6.5 (2023) | - QtGraphs ✨新增 - QtDeviceUtilities | - 图表库引入 - 设备工具 | |
| 6.6 (2023) | - QtMultimediaWidgets ✨回归 | - 多媒体部件回归 - 性能优化 | |
| 6.7 (2024) | - QtApplicationManager - QtWebView | - 应用管理 - Web视图改进 |
7.3. 详细功能级变更记录
配置选项变更分析
Qt 5.15 → Qt 6.0 重大变更:
# Qt 5.15 中存在的配置选项,在 Qt 6.0 中移除或变更 - -no-opengl # 在 Qt6 中被 -no-opengl 和 -no-vulkan 替代 - -qt-host-path # 被 CMake 变量替代 - -no-eglfs # 平台插件系统重构 - -system-proxies # 网络栈重构影响 - -qpa # QPA架构变更 # Qt 6.0 新增配置选项 - -feature-vulkan # Vulkan支持 - -cmake-generator # CMake生成器选项 - -qt-namespace # 命名空间控制
模块级功能裁剪历史
Web引擎模块的演进:
2008: QtWebKit 引入 (Qt 4.4) 2012: QtWebKit 继续在 Qt5.0 中使用 2015: QtWebEngine 引入 (Qt 5.6),基于Chromium 2016: QtWebKit 标记为废弃 (Qt 5.6) 2018: QtWebKit 从官方发布中移除 (Qt 5.12+) 2020: QtWebEngine 暂不包含在 Qt6.0 2021: QtWebEngine 回归 (Qt 6.2)
3D图形模块发展:
2012: Qt3D 引入 (Qt 5.0) - 基础3D支持 2016: Qt3D 扩展 (Qt 5.7) - 动画和额外组件 2020: QtQuick3D 引入 (Qt 5.15) - 声明式3D 2021: QtQuick3D 成为主要3D方案 (Qt 6.2) 2023: QtQuick3D 物理引擎 (Qt 6.5)
7.4. 自动化分析脚本
#!/bin/bash # analyze_qt_history.sh QT_SRC_DIR="$1" MODULE="$2" echo "=== Analyzing history of $MODULE ===" # 查看模块引入时间 echo "1. Module introduction:" git -C "$QT_SRC_DIR" log --reverse --oneline --grep="add.*$MODULE" --all | head -5 # 查看主要变更 echo -e "\n2. Major changes:" git -C "$QT_SRC_DIR" log --oneline --since="2010-01-01" -- "$MODULE" | head -10 # 查看配置选项变更 echo -e "\n3. Configure changes:" git -C "$QT_SRC_DIR" log --oneline --grep="configure.*$MODULE" --all | head -5 # 使用示例: ./analyze_qt_history.sh /path/to/qt5 qtwebengine
7.5. 树形结构对比分析工具
#!/usr/bin/env python3
# qt_module_analyzer.py
import os
import subprocess
from datetime import datetime
def analyze_qt_version(qt_path, version):
"""分析特定Qt版本的模块结构"""
modules = {}
# 分析src目录
src_path = os.path.join(qt_path, 'src')
if os.path.exists(src_path):
for module in os.listdir(src_path):
module_path = os.path.join(src_path, module)
if os.path.isdir(module_path):
# 计算模块大小
size = get_directory_size(module_path)
modules[module] = {
'size': size,
'type': 'core'
}
return modules
def generate_tree_comparison(qt_versions):
"""生成版本间树形对比"""
print("Qt Module Evolution Tree")
print("=" * 50)
for version, modules in qt_versions.items():
print(f"\n{version}:")
for module, info in modules.items():
status = "🆕" if is_new_module(module, version) else " "
print(f" {status} {module:20} {info['size']:>10} MB")
if __name__ == "__main__":
# 这里需要实际路径
qt_versions = {
'Qt 4.8': analyze_qt_version('/path/to/qt4.8', '4.8'),
'Qt 5.15': analyze_qt_version('/path/to/qt5.15', '5.15'),
'Qt 6.5': analyze_qt_version('/path/to/qt6.5', '6.5'),
}
generate_tree_comparison(qt_versions)
7.6. 关键结论
-
模块化趋势:从Qt4的相对集中到Qt5的模块化,再到Qt6的现代化重构
-
Web技术演进:WebKit → WebEngine 的转换反映了Web技术的快速发展
-
3D图形发展:从基础的OpenGL包装到完整的声明式3D解决方案
-
构建系统变革:qmake → CMake 的转变影响了整个生态
-
移动和嵌入式:不断增加对移动平台和嵌入式设备的优化支持
第三部分:QT源码与授权
-
QT源码是开源包嘛? 是的,Qt源码是开源的。 它采用双重许可模式:
-
GPL/LGPLv3: 对于开源项目,你可以遵循这些协议免费使用Qt。
-
商业许可: 如果你希望开发闭源的商业软件,或者需要Qt公司的官方支持,则需要购买商业许可证。
-
-
从那个版本开始收费的? Qt从诞生之初就具有商业属性。 它的商业模式一直是“双重许可”。所以不存在“从哪个版本开始收费”的说法,而是一直同时提供免费(开源)和收费(商业)两种获取方式。不过,其具体的开源协议(GPL/LGPL)版本和条款在不同大版本间有所变化。例如,Qt 4.x早期版本是LGPL v2.1,从Qt 4.5开始同时提供LGPL v2.1和v3选项。Qt 5和Qt 6则主要基于GPLv3、LGPLv3和商业协议。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐

所有评论(0)