在去年4月份的时候,我写过一篇动态编译Qt5.6.0的文章,当时是为了解决webkit不能在winxp下面跑的问题,动态编译有一个缺点,就是发布的时候,要携带一大堆dll,使安装包的体积增大。而静态编译能够解决这个问题,但是静态编译也有缺点,那就是编译时间很长,而且每次不管哪个模块有改动,就必须重新编译链接整个项目。现在Qt最新版本已经到5.8.0RC了,但5.6.2应该是最后一个支持xp的版本了,5.7.0源码里configure已经去掉了-target xp这个选项。
注意:闭源项目链接静态Qt库并发布软件是违反LGPL协议的,请遵守此协议,否则因此造成的任何后果,与本文作者无关。
一、准备
需要的工具和上篇文章里面列出来的差不多,除了下面几个
1、qt-everywhere-opensource-src-5.6.2源码
2、Precompiled ICU已经静态编译好的icu,注意下载vs2013版本的,我下载的是icu-58.2-vs2013.7z
3、win_flex_bison,编译webkit需要
二、获取webkit源码
先解压5.6.2的源码到C:Qtqt-everywhere-opensource-src-5.6.2,打开CMD转到此目录,输入Git clone git://code.qt.io/qt/qtwebkit.git下载源码,由于是国外地址,请留意上篇文章的提示。下载完成之后,再执行:git checkout 5.6.2,注意checkout这一步是必须的,每个Qt版本都有对应的webkit版本,不执行这一步下载的webkit源码应该是当前的最新版本5.8.0RC对应的源码,编译很可能会出问题。
三、编译openssl
编译过程和上篇文章大致相同,不过静态编译的时候要用ms/nt.mak,而不是ms/ntdll.mak,另外安装目录(-prefix),我这里是:C:Qtopenssl-static,其他操作参考上篇文章即可。
四、编译Qt5.6.2
打开VS2013的x86命令提示工具,执行以下命令(确保Python,ruby,perl,jom已经添加到了PATH):
- SET ICU_DATA=C:Qticu-58.2-vs2013data
- SET PATH=C:Qticu-58.2-vs2013in;C:Qticu-58.2-vs2013lib;C:Qtwin_flex_bison-latest;C:Qtqt-everywhere-opensource-src-5.6.2qtbasein;C:Qtqt-everywhere-opensource-src-5.6.2gnuwin32in;%PATH%
然后创建C:Qtuild-Qt5.6.2-msvc2013-static-x86-debug和C:Qtuild-Qt5.6.2-msvc2013-static-x86-release两个目录,用于分别编译debug和release两个版本,再创建C:QtQt5.6.2-msvc2013-static-x86目录,作为Qt的安装目录
修改C:Qtqt-everywhere-opensource-src-5.6.0qtbasemkspecscommonmsvc-desktop.conf的74行和75行为:/SUBSYSTEM:CONSOLE",5.01" 和 /SUBSYSTEM:WINDOWS",5.01"
修改C:Qtqt-everywhere-opensource-src-5.6.2qtwebkitSourceWebCoreplatformqtQtTestSupport.h的28行和30行:
- #if defined(BUILDING_WEBKIT)
- #define TESTSUPPORT_EXPORT //Q_DECL_EXPORT
- #else
- #define TESTSUPPORT_EXPORT //Q_DECL_IMPORT
- #endif
把Q_DECL_EXPORT和Q_DECL_IMPORT注释掉,这个是导出DLL用的,静态编译没有这个东西。
注意:编译webkit只能用VS2013,否则webkit不会被编译:参考C:Qtqt-everywhere-opensource-src-5.6.2qtwebkitToolsqmakemkspecsfeaturesconfigure.prf文件第132行:
如果你的编译器不是VS2013,webkit构建的时候会自动跳过。。这也是一个坑,笔者之前用VS2015去编译,就发现了这个问题。
编译debug版本
转到C:Qtuild-Qt5.6.2-msvc2013-static-x86-debug
执行:"../qt-everywhere-opensource-src-5.6.2/configure.bat" -prefix C:/Qt/Qt5.6.2-msvc2013-static-x86 -debug -platform win32-msvc2013 -opensource -static -static-runtime -nomake examples -nomake tests -skip qtwebengine -skip qtwebview -accessibility -plugin-sql-odbc -plugin-sql-sqlite -opengl desktop -target xp -largefile -qt-zlib -qt-pcre -icu -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -rtti -ssl -openssl-linked -mp -I C:Qtopenssl-staticinclude -I C:Qticu-58.2-vs2013include -L C:Qtopenssl-staticlib -L C:Qticu-58.2-vs2013lib -l gdi32 -D _USING_V110_SDK71_ -D U_STATIC_IMPLEMENTATION
输入y接受协议,等待配置完成
执行:jom或者nmake
编译完成后,如果没有出现错误,执行,nmake install
编译release版本
转到 C:Qtuild-Qt5.6.2-msvc2013-static-x86-release
执行:"../qt-everywhere-opensource-src-5.6.2/configure.bat" -prefix C:/Qt/Qt5.6.2-msvc2013-static-x86 -release -platform win32-msvc2013 -opensource -static -static-runtime -ltcg -nomake examples -nomake tests -skip qtwebengine -skip qtwebview -accessibility -plugin-sql-odbc -plugin-sql-sqlite -opengl desktop -target xp -largefile -qt-zlib -qt-pcre -icu -qt-libpng -qt-libjpeg -qt-freetype -qt-harfbuzz -rtti -ssl -openssl-linked -mp -I C:Qtopenssl-staticinclude -I C:Qticu-58.2-vs2013include -L C:Qtopenssl-staticlib -L C:Qticu-58.2-vs2013lib -l gdi32 -D _USING_V110_SDK71_ -D U_STATIC_IMPLEMENTATION
输入y接受协议,等待配置完成
执行:jom或者nmake
编译完成后,如果没有出现错误,执行,nmake install
注意:
1、configure.bat执行之后,可能会出现一堆警告:
C:Qtuild-Qt5.6.2-msvc2013-static-x86-debug/qtbase/mkspecs/qconfig.pri:22: Extra characters after test expression.
...
原因是Qt的构建脚本有问题,编辑C:Qtuild-Qt5.6.2-msvc2013-static-x86-debug/qtbase/mkspecs/qconfig.pri
Qt的构建脚本,在获取cl编译器的版本号时,字符串截取有问题,手动编辑一下,改成下面这样即可:
2、nmake install之后,C:Qtuild-Qt5.6.2-msvc2013-static-x86-debug和C:Qtuild-Qt5.6.2-msvc2013-static-x86-release两个构建目录不能删除
因为之后编译项目的时候,会链接到一些lib,比如webkit1.lib,这些lib,install的时候并没有安装到C:QtQt5.6.2-msvc2013-static-x86lib
看到这里有人肯定会问为什么不一起编译debug和release,其实是可以的,直接把release版本的configure命令-release改为-debug-and-release即可。
五、测试运行
用QtCreator新建一个项目,创建一个QWebView,然后加载http://www.baidu.com/
- CONFIG(release, debug|release): QMAKE_LFLAGS += /LTCG
- QMAKE_LFLAGS += /IGNORE:4099
- QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE",5.01"
- QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS",5.01"
- DEFINES += _USING_V110_SDK71_
- DEFINES += U_STATIC_IMPLEMENTATION
注意在pro里面增加上面的代码,/IGNORE:4099表示忽略没有找到pdb的警告,因为这个预编译好的icu是没有自带pdb的,如果不加这一项,编译的时候会出现很多没有找到pdb的警告。我们通常也不会去调试icu的代码,所以忽略这个警告对我们没有什么影响。
U_STATIC_IMPLEMENTATION这个宏是静态链接icu要使用的,请参考icu的帮助文档
项目构建之后,生成的exe有54M!下图是运行结果,笔者在xp系统上也测试过,能正常运行。
http://blog.csdn.net/kenier/article/details/54598698