构建一个真正、完全静态的Qt 5框架和应用程序(Qt 5.8之后)

Building a truly, fully static Qt 5 framework and application (post Qt 5.8)

本文关键字:Qt 框架 应用程序 之后 静态 一个 构建      更新时间:2023-10-16

正如标题所暗示的那样,目标是成功地构建Qt框架和Qt应用程序,以产生没有外部依赖关系的单个可执行二进制文件。

我的动机是,自从构建系统在Qt 5.8中得到"改进"以来,我就无法真正完成一个成功的静态Qt构建。甚至在此之前,虽然构建静态Qt框架毫不费力,但它并没有真正产生没有外部依赖的可执行二进制文件。仍然有许多库必须捆绑,只有Qt库是静态链接的。

回到Qt 5.8之前的日子,我能够通过以下配置获得成功的静态Qt构建:

配置 -c++

std c++11 -prefix E:\Qt\Qt58s -platform win32-g++-release -opensource -static -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -no-compile-examples -no-icu -opengl desktop -skip qtscript -nomake examples -nomake tests -skip qtwayland -skip qtwebview -skip qtwebengine -skip qtwebchannel -no-qml-debug -confirm-license -L E:\msys64\mingw64\lib -qt-sql-psql -qt-sql-mysql -l mysqlclient -I E:\msys64\mingw64\include\mariadb

总结一下配置,它仅限于发布版本,省略了任何平台提供的库,并选择使用Qt捆绑的库。删除 icu 作为二进制膨胀的重要来源,以及缩短构建时间的测试和示例,以及不使用 GCC 构建的 Web 引擎。此外,该配置选择包括postgres和mysql驱动程序支持,后者通过mariadb客户端库。

这个构建配置一如既往地成功地用于Qt 5的几个次要版本,但它从未真正产生过无依赖的可执行文件。我仍然必须在PRO文件中手动链接psql和mysql库,并且我仍然必须至少包含gcc运行时库。

虽然通过向 PRO 文件添加QMAKE_LFLAGS += -static-libgcc -static-libstdc++来静态链接运行时库已被证明是成功的,但这仅处理那些特定的库。

在"大规模"上,通过QMAKE_LFLAGS += -static添加静态链接器标志从未导致过成功的构建,而是导致内部链接到相同库的不同库之间的链接错误和冲突。

但话又说回来,Qt 5.8 重新设计了构建系统配置以改进它。像许多"改进"一样,它实际上被破坏了,没有可行的方法来选择配置中的第三方库,而是必须手动破解各种 JSON 配置文件。

从那以后,这个错误得到了修复,导致我继续努力创建一个完全静态的Qt构建。现在使用以下配置:

配置 -前缀 E:\Qt\Qt591s -c++std c++11 -platform win32-g++ -release -opensource -static -static-runtime -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -no-compile-examples -no-icu -opengl desktop -skip qtscript -nomake examples -nomake tests -skip qtwayland -skip qtwebview -skip qtwebengine -skip qtwebchannel -no-qml-debug -confirm-license -sql-psql -sql-mysql MYSQL_INCDIR=E:\msys64\mingw64\include\mariadb MYSQL_LIBDIR=E:\msys64\mingw64\lib MYSQL_LIBS="-l mysqlclient" -L E:\msys64\mingw64\lib

区别在于使用新语法指定第三方库,并添加-static-runtime标志。后来证明这是配置失败的原因,因为 mysql 无法解决间接依赖关系,据称如果显式包含整个依赖树,这应该可以工作。

渴望得到一个工作版本,我只是省略了-static-runtime,事实上,我终于得到了一个工作配置。但我还没有完全到达那里,因为构建失败了,没有有意义的输出来表示原因。

下一步是尝试通过使用-silent配置标志来限制编译输出,不幸的是,这导致编译过程中的构建失败 5 秒,揭示了一个长期存在的错误,该错误阻止了此标志与 GCC 一起使用,无论您是构建 Qt 还是 Qt 应用程序。

接下来,我尝试使用单个线程进行构建,希望我能减少输出混乱,甚至可能深入了解构建失败的原因。唉,无济于事。我所能从输出中取出的只是构建在 libjpg 步骤失败。这促使我删除了所有指定捆绑库用法的标志,这让我通过了 libjpg,只是在平台插件上构建失败,对原因知之甚少。

作为最后的手段,我尝试删除大多数可能有问题的配置标志,包括静态构建,希望至少获得成功的"常规构建,它也失败了:

配置 -前缀 E:\Qt\ Qt591test -c++std c++11 -platform win32-g++ -release -opensource -no-compile-examples -no-icu -opengl desktop -skip qtscript -nomake examples -nomake tests -skip qtwayland -skip qtwebview -skip qtwebengine -skip qtwebchannel -no-qml-debug - confirm-license

给我留下以下输出:

g++ -fno-keep-inline-dllexport -pipe -O2 -std=c++11 -fno-exceptions -Wex
tra -Wall -W -Wvla -Wdate-time -Wshift-overflow=2 -Wduplicated-cond -dM -E -o .m
ocreleasemoc_predefs.h e:shareqt-everywhere-opensource-src-5.9.1qtbasemksp
ecsfeaturesdatadummy.cpp
g++ -c -fno-keep-inline-dllexport -pipe -O2 -std=c++11 -fno-exceptions -
Wextra -Wall -W -Wvla -Wdate-time -Wshift-overflow=2 -Wduplicated-cond -DUNICODE
-DQT_NO_CAST_FROM_ASCII -DLIBEGL_NAME=libEGL -DLIBGLESV2_NAME=libGLESv2 -DQT_NO
_NARROWING_CONVERSIONS_IN_CONNECT -DQT_NO_EXCEPTIONS -DQT_NO_DEBUG -DQT_PLUGIN -
DQT_EVENTDISPATCHER_SUPPORT_LIB -DQT_ACCESSIBILITY_SUPPORT_LIB -DQT_FONTDATABASE
_SUPPORT_LIB -DQT_THEME_SUPPORT_LIB -DQT_GUI_LIB -DQT_CORE_LIB -IE:shareqt-eve
rywhere-opensource-src-5.9.1qtbasesrcpluginsplatformsdirect2d -I. -IE:shar
eqt-everywhere-opensource-src-5.9.1qtbasesrcpluginsplatformswindows -IE:s
hareqt-everywhere-opensource-src-5.9.1qtbasesrc3rdpartywintab -IE:shareqt
-everywhere-opensource-src-5.9.1qtbaseinclude -IE:shareqt-everywhere-opensou
rce-src-5.9.1qtbaseincludeQtEventDispatcherSupport -IE:shareqt-everywhere-o
pensource-src-5.9.1qtbaseincludeQtEventDispatcherSupport5.9.1 -IE:shareqt-
everywhere-opensource-src-5.9.1qtbaseincludeQtEventDispatcherSupport5.9.1Qt
EventDispatcherSupport -I........include -I........includeQtEventDispat
cherSupport -IE:shareqt-everywhere-opensource-src-5.9.1qtbaseincludeQtAcces
sibilitySupport -IE:shareqt-everywhere-opensource-src-5.9.1qtbaseincludeQtA
ccessibilitySupport5.9.1 -IE:shareqt-everywhere-opensource-src-5.9.1qtbasei
ncludeQtAccessibilitySupport5.9.1QtAccessibilitySupport -I........include
QtAccessibilitySupport -IE:shareqt-everywhere-opensource-src-5.9.1qtbaseinc
ludeQtFontDatabaseSupport -IE:shareqt-everywhere-opensource-src-5.9.1qtbase
includeQtFontDatabaseSupport5.9.1 -IE:shareqt-everywhere-opensource-src-5.9.
1qtbaseincludeQtFontDatabaseSupport5.9.1QtFontDatabaseSupport -I........
includeQtFontDatabaseSupport -IE:shareqt-everywhere-opensource-src-5.9.1qtb
aseincludeQtThemeSupport -IE:shareqt-everywhere-opensource-src-5.9.1qtbase
includeQtThemeSupport5.9.1 -IE:shareqt-everywhere-opensource-src-5.9.1qtbas
eincludeQtThemeSupport5.9.1QtThemeSupport -I........includeQtThemeSuppo
rt -IE:shareqt-everywhere-opensource-src-5.9.1qtbaseincludeQtGui5.9.1 -IE:
shareqt-everywhere-opensource-src-5.9.1qtbaseincludeQtGui5.9.1QtGui -I..
......includeQtGui5.9.1 -I........includeQtGui5.9.1QtGui -IE:share
qt-everywhere-opensource-src-5.9.1qtbaseincludeQtGui -I........includeQt
Gui -IE:shareqt-everywhere-opensource-src-5.9.1qtbaseincludeQtCore5.9.1 -I
E:shareqt-everywhere-opensource-src-5.9.1qtbaseincludeQtCore5.9.1QtCore -
I........includeQtCore5.9.1 -I........includeQtCore5.9.1QtCore -IE:
shareqt-everywhere-opensource-src-5.9.1qtbaseincludeQtCore -I........in
cludeQtCore -I.mocrelease -IE:shareqt-everywhere-opensource-src-5.9.1qtbase
mkspecswin32-g++ -o .objreleasemoc_qwindowsdirect2dnativeinterface.o .mocre
leasemoc_qwindowsdirect2dnativeinterface.cpp
g++ -Wl,-s -shared -Wl,-subsystem,windows -Wl,--out-implib,E:tmpbuildq
tbasepluginsplatformslibqdirect2d.a -o ........pluginsplatformsqdirect2
d.dll object_script.qdirect2d.Release  -ldwmapi -ld2d1 -ld3d11 -ldwrite -lVersio
n -lwinspool -limm32 -lwinmm -loleaut32 -lshlwapi -lshell32 -LE:tmpbuildqtbase
lib E:tmpbuildqtbaseliblibQt5EventDispatcherSupport.a E:tmpbuildqtbaseli
blibQt5AccessibilitySupport.a E:tmpbuildqtbaseliblibQt5FontDatabaseSupport.
a -lole32 -ladvapi32 -luuid E:tmpbuildqtbaseliblibqtfreetype.a E:tmpbuildq
tbaseliblibqtlibpng.a -lz E:tmpbuildqtbaseliblibQt5ThemeSupport.a -lglu32
-lopengl32 -lgdi32 -luser32 E:tmpbuildqtbaseliblibQt5Gui.a E:tmpbuildqtbas
eliblibQt5Core.a .objreleaseqdirect2d_resource_res.o
windres -i qjpeg_resource.rc -o .objreleaseqjpeg_resource_res.o --incl
ude-dir=. -DUNICODE -DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT -DQT_NO_EXCEPTIONS
-DQT_NO_DEBUG -DQT_PLUGIN -DQT_GUI_LIB -DQT_CORE_LIB
E:tmpbuildqtbasebinmoc.exe -DUNICODE -DQT_NO_NARROWING_CONVERSIONS_I
N_CONNECT -DQT_NO_EXCEPTIONS -DQT_NO_DEBUG -DQT_PLUGIN -DQT_GUI_LIB -DQT_CORE_LI
B --include .moc/release/moc_predefs.h -IE:/share/qt-everywhere-opensource-src-5
.9.1/qtbase/mkspecs/win32-g++ -IE:/share/qt-everywhere-opensource-src-5.9.1/qtba
se/src/plugins/imageformats/jpeg -IE:/share/qt-everywhere-opensource-src-5.9.1/q
tbase/src/3rdparty/libjpeg -IE:/share/qt-everywhere-opensource-src-5.9.1/qtbase/
include/QtGui/5.9.1 -IE:/share/qt-everywhere-opensource-src-5.9.1/qtbase/include
/QtGui/5.9.1/QtGui -IE:/tmpbuild/qtbase/include/QtGui/5.9.1 -IE:/tmpbuild/qtbase
/include/QtGui/5.9.1/QtGui -IE:/share/qt-everywhere-opensource-src-5.9.1/qtbase/
include -IE:/share/qt-everywhere-opensource-src-5.9.1/qtbase/include/QtGui -IE:/
tmpbuild/qtbase/include -IE:/tmpbuild/qtbase/include/QtGui -IE:/share/qt-everywh
ere-opensource-src-5.9.1/qtbase/include/QtCore/5.9.1 -IE:/share/qt-everywhere-op
ensource-src-5.9.1/qtbase/include/QtCore/5.9.1/QtCore -IE:/tmpbuild/qtbase/inclu
de/QtCore/5.9.1 -IE:/tmpbuild/qtbase/include/QtCore/5.9.1/QtCore -IE:/share/qt-e
verywhere-opensource-src-5.9.1/qtbase/include/QtCore -IE:/tmpbuild/qtbase/includ
e/QtCore -I. -IE:/msys64/mingw64/include/c++/7.1.0 -IE:/msys64/mingw64/include/c
++/7.1.0/x86_64-w64-mingw32 -IE:/msys64/mingw64/include/c++/7.1.0/backward -IE:/
msys64/mingw64/lib/gcc/x86_64-w64-mingw32/7.1.0/include -IE:/msys64/mingw64/incl
ude -IE:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/7.1.0/include-fixed -IE:/msys
64/mingw64/x86_64-w64-mingw32/include E:shareqt-everywhere-opensource-src-5.9.
1qtbasesrcpluginsimageformatsjpegmain.h -o .mocreleasemoc_main.cpp
g++ -c -fno-keep-inline-dllexport -pipe -O2 -std=c++11 -fno-exceptions -
Wextra -Wall -W -Wvla -Wdate-time -Wshift-overflow=2 -Wduplicated-cond -DUNICODE
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT -DQT_NO_EXCEPTIONS -DQT_NO_DEBUG -DQT_
PLUGIN -DQT_GUI_LIB -DQT_CORE_LIB -IE:shareqt-everywhere-opensource-src-5.9.1
qtbasesrcpluginsimageformatsjpeg -I. -IE:shareqt-everywhere-opensource-src
-5.9.1qtbasesrc3rdpartylibjpeg -IE:shareqt-everywhere-opensource-src-5.9.1
qtbaseincludeQtGui5.9.1 -IE:shareqt-everywhere-opensource-src-5.9.1qtbase
includeQtGui5.9.1QtGui -I........includeQtGui5.9.1 -I........inclu
deQtGui5.9.1QtGui -IE:shareqt-everywhere-opensource-src-5.9.1qtbaseinclud
e -IE:shareqt-everywhere-opensource-src-5.9.1qtbaseincludeQtGui -I......
..include -I........includeQtGui -IE:shareqt-everywhere-opensource-src-5
.9.1qtbaseincludeQtCore5.9.1 -IE:shareqt-everywhere-opensource-src-5.9.1q
tbaseincludeQtCore5.9.1QtCore -I........includeQtCore5.9.1 -I......
..includeQtCore5.9.1QtCore -IE:shareqt-everywhere-opensource-src-5.9.1qtb
aseincludeQtCore -I........includeQtCore -I.mocrelease -IE:shareqt-eve
rywhere-opensource-src-5.9.1qtbasemkspecswin32-g++ -o .objreleasemoc_main.o
.mocreleasemoc_main.cpp
g++ -Wl,-s -shared -Wl,-subsystem,windows -Wl,--out-implib,E:tmpbuildq
tbasepluginsimageformatslibqjpeg.a -o ........pluginsimageformatsqjpeg.
dll object_script.qjpeg.Release  -lglu32 -lopengl32 -lgdi32 -luser32 -LE:tmpbui
ldqtbaselib E:tmpbuildqtbaseliblibQt5Gui.a E:tmpbuildqtbaseliblibQt5Co
re.a .objreleaseqjpeg_resource_res.o
jom: E:tmpbuildqtbaseMakefile [sub-qmake-qmake-aux-pro-make_first] Error 2
jom: E:tmpbuildMakefile [module-qtbase-make_first] Error 2

在这一点上,我想重申,在Qt 5.8之前,我已经使用相同的工具链在多个版本上成功构建了。

我的主要开发平台是Windows,我使用MSYS2作为构建环境和主要工具链,使用GCC 5.3.0。我也一直在使用 MSYS2 为 psql 和 mariadbclient 提供的开发库,以节省自己构建它们的需要。我也针对安卓和Linux,所以这个问题适用于这3个平台。我不针对macos或ios,所以虽然作为OP对我没有直接好处,但这些平台上的信息可能仍然对某些人可用。

那么,有谁能接受挑战来指导像我这样的新闻,度过一个真正的、完全静态的Qt构建的困难?

我目前正在为最新版本(目前是 5.9.1)苦苦挣扎,但这个问题也应该与未来的版本相关,这可能会引入自己的怪癖。

一个月后,我取得了一些进展,虽然不是OP标题的位置,但尽管如此,我现在能够使用我的自定义SQL库和工作SQL在静态或动态配置中一致地构建Qt。

罪魁祸首实际上是jom,根据配置的不同,它在不同的部分总是失败。我尝试了几个版本,它们都失败了。我尝试了许多不同的、逐渐更保守的配置选项,我什至尝试了非常缓慢的单线程构建。都失败了。

然而,使用mingw32-make以 100% 的成功率工作,我意外地发现,在使用jom多年后,作为最后的手段,因为它据称更快。但是,make也支持使用相同的-j coreCount参数并行构建,因此在没有jom的情况下,快速Qt构建仍然是一个选项。

每当我取得更多进展时,我都会回来更新这个......传奇仍在继续。