裁剪模块
Qt5 的项目目录结构跟 Qt4 相比有很大区别,它定义了模块,把 Qt 核心部分和其它模块分开,例如:3D、多媒体、串口总线、web、qml。其中核心部分代码在 qtbase 文件夹内。
Qt5 源码内有两个 'configure' 脚本文件,一个在源码根目录,一个在qtbase文件夹。执行根目录的 'configure' 脚本可以配置添加 3D、qml等模块,执行 qtbase 目录的 'configure' 只配置核心模块。
默认编译所有模块,如果不想编译某个模块,使用-skip xxx跳过模块编译。例如:
1. $ ./configure -skip 3d -skip activeqt -skip multimedia
裁剪样例和测试
Qt 源码自带测试项目和样例项目,这部分代码没必要完全编译,如果想通过样例项目学习Qt,可以单独拷贝出去使用Qt Creator 编译。
使用下面两个参数禁用样例和测试编译,减少编译项。
1. $ ./configure ... -nomake examples -nomake tests -nomake tools
核心代码特性裁剪
去掉 qml 调试、去掉 dbus opengl pulseaudio 等等。
1 | $ ./configure ... -no-qml-debug -no-accessibility -no-dbus -no-opengl -qt-pcre -no-pulseaudio |
批量裁剪大量特性
在 5.6.0 版本的 configure 脚本里有一个选项 -qconfig 这个选项可以选择一种配置,有 minimal small medium large 和 full 几种选项参数可选。默认 full 。
比如 small 选项,将不编译Qt自带的标准对话框,QSetting、QLibrary,不支持 bmp jpeg ppm xbm 等等图片格式,不支持编码,不支持翻译,不支持各种model,不支持动作、剪切板、拖放、快捷键等等等。
详细内容查看 "qtbase/src/corelib/global/qconfig-{minimal,small,medium,large}.h" 几个文件。
1 | $ ./configure ... -qconfig minimal |
既然 -qconfig 选项的几种参数都有个对应的h文件,我们编辑自己是文件是不是也可以?
我们从 qconfig-minimal.h 文件拷贝个备份
1 2 | $ cp qtbase/src/corelib/global/qconfig-minimal.h qtbase/src/corelib/global/qconfig-lau.h $ vim qtbase/src/corelib/global/qconfig-lau.h |
因为Qt告诉我们那个已经是最小化的配置了,那么我们在最小的配置的基础上进行编辑。打开文件后,文件内容很整洁,类似如下结构
1 2 3 | #ifndef QT_NO_XXX # define QT_NO_XXX #endif |
意思很明显,就是不配置 XXX ,不编译 XXX 进目标库。然后把文件中我们需要用到的部分行删掉,保存文件。配置如下修改就使用我们自己定义的了。
1 | $ ./configure ... -qconfig lau |
自从 Qt5.8 configure 放弃了 qconfig 使用了新的裁剪方法 -- feature。
feature 裁剪
configure 脚本还有个选项 -feature- 和 -no-feature- 分别用于启用某个特性和关闭某个特性。可用的参数见文件 "qtbase/src/corelib/global/qfeatures.txt"。
1. $ ./configure ... -no-feature-cursor -no-feature-imageformat-bmp -no-feature-settings
优先级顺序
不知道是 Qt 团队的故意还是疏忽,大量特性在qconfig 和 features.txt里面同时存在,某些在 configure 脚本选项里面也有。如果同时有设置而且既有启用又有禁用,那么这时候,启用优先;如果既没有定义启用又没定义禁用,禁用优先。
一次有效裁剪的完整配置命令
$ ./configure -opensource -confirm-license -qt-xcb -skip 3d -skip activeqt -skip androidextras -skip canvas3d -skip connectivity -skip datavis3d -skip declarative -skip doc -skip gamepad -skip graphicaleffects -skip imageformats -skip location -skip macextras -skip multimedia -skip networkauth -skip purchasing -skip quickcontrols -skip quickcontrols2 -skip remoteobjects -skip script -skip scxml -skip sensors -skip speech -skip tools -skip translations -skip virtualkeyboard -skip wayland -skip webchannel -skip webengine -skip websockets -skip webview -skip winextras -skip x11extras -skip xmlpatterns -nomake examples -nomake tests -nomake tools -no-qml-debug -no-dbus -no-opengl -qt-pcre -no-cups -no-testlib -no-feature-pdf -no-feature-accessibility -no-feature-bearermanagement -no-feature-big_codecs -no-feature-calendarwidget -no-feature-clipboard -no-feature-codecs -no-feature-colordialog -no-feature-colornames -no-feature-columnview -no-feature-combobox -no-feature-commandlineparser -no-feature-commandlinkbutton -no-feature-concurrent -no-feature-contextmenu -no-feature-cssparser -no-feature-cups -no-feature-cursor -no-feature-datawidgetmapper -no-feature-datetimeedit -no-feature-datetimeparser -no-feature-desktopservices -no-feature-dial -no-feature-dirmodel -no-feature-dockwidget -no-feature-draganddrop -no-feature-effects -no-feature-errormessage -no-feature-filedialog -no-feature-filesystemiterator -no-feature-filesystemmodel -no-feature-filesystemwatcher -no-feature-fontcombobox -no-feature-fontdialog -no-feature-formlayout -no-feature-ftp -no-feature-gestures -no-feature-highdpiscaling -no-feature-http -no-feature-identityproxymodel -no-feature-im -no-feature-image_heuristic_mask -no-feature-image_text -no-feature-imageformat_ppm -no-feature-imageformat_xbm -no-feature-imageformat_xpm -no-feature-imageformatplugin -no-feature-inputdialog -no-feature-keysequenceedit -no-feature-lcdnumber -no-feature-mdiarea -no-feature-menubar -no-feature-mimetype -no-feature-movie -no-feature-networkdiskcache -no-feature-networkproxy -no-feature-paint_debug -no-feature-pdf -no-feature-picture -no-feature-printdialog -no-feature-printpreviewdialog -no-feature-printpreviewwidget -no-feature-progressbar -no-feature-progressdialog -no-feature-scroller -no-feature-sessionmanager -no-feature-shortcut -no-feature-sizegrip -no-feature-socks5 -no-feature-sortfilterproxymodel -no-feature-spinbox -no-feature-splitter -no-feature-standarditemmodel -no-feature-statemachine -no-feature-statusbar -no-feature-statustip -no-feature-stringlistmodel -no-feature-syntaxhighlighter -no-feature-systemtrayicon -no-feature-tabletevent -no-feature-tableview -no-feature-tablewidget -no-feature-textbrowser -no-feature-textcodec -no-feature-textodfwriter -no-feature-toolbar -no-feature-toolbox -no-feature-tooltip -no-feature-topleveldomain -no-feature-treeview -no-feature-treewidget -no-feature-undocommand -no-feature-undogroup -no-feature-undostack -no-feature-undoview -no-feature-whatsthis -no-feature-wheelevent -no-feature-wizard
裁剪过程中,不可避免的有些想当然的时候,想当然的认为去掉某个特性可以使编译出来的目标库文件更小一点儿。一个原则是:若非就去掉,如果使用系统库优先。
往往某个特性被另外一个特性依赖,这种依赖判断 configure 处理的并不好,配置过程能顺利过去,但是编译的时候可能出现未定义的情况出现,就有可能是因为某个特性缺少。需要自己去判断需要哪个。
目标库大小的问题
经过多次反复尝试,并不会出现如我们想象的那样,使编译出来的目标库文件缩水50%,实际操作中很难做到。因为大部分常用类 "QString" "QVariant" "QMetaType" "QSetting" "QObject" "QCoreApplication" "QGuiApplication" "QPainter" "QEvent" "QImage" ... 都特别大,而且不支持裁剪。