Qt5.11.2 & VS2017 & 64位版本 静态编译
小伙伴们有没有遇到过,自己使用Qt库开发的小程序,在本地电脑上跑得很欢快,但是当想要把编译好的.exe可执行文件发给朋友玩玩的时候,发现在没有安装Qt或者VS环境的电脑上是跑不了的。究其原因,这是因为大家在编译程序时,使用的是动态编译。也就是说,编译好的程序在运行时还需要另外加上相应的DLL库文件,否则就会出错。而如果想将生成的程序连同所需要的依赖库一起完整地打包成一个.exe可执行程序,那就需要使用静态编译。
1、问题描述:
使用VS编译程序时,运行库选择多线程(/MT),表示采用多线程静态release的方式进行编译。
但是,发现编译是不能通过的。
qtmain.lib(qtmain_win.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MD_DynamicRelease”不匹配值“MT_StaticRelease”
原因在于安装Qt时默认使用的是动态库,而且官方并没有提供编译好的静态库下载。
但我们可以自己下载Qt源码下来,自己重新编译,生成静态库,这样我们开发的Qt程序也就能完成静态的编译了。以后也就只需要编译成一个exe,就能满地跑了哈~(自己动手尝试一下,还是挺好玩的)
2、下载源码包
首先,我们需要从Qt官网(地址:http://download.qt.io/archive/qt/5.11/5.11.2/single/ )下载对应的Qt源码。在这里,我以在Windows下编译Qt程序为例。
下载后是一个压缩文件,将它解压到一个空间较大的磁盘下面。一会静态编译需要占用大量磁盘空间。(谨慎起见,请至少保证该磁盘下有10G左右空间。)
3、编译环境
以下是编译时需要的工具,在编译之前,请务必安装!
安装都比较简单。这里直接给出官网下载的链接。最后记得添加到环境变量(安装时把‘’添加到PATH环境“选项勾起就可以了,或者在安装后手动添加也可以)。
建议安装jom,来替换nmake进行编译,可以充分利用CPU多核的能力,否则估计你会中途吐血的。
jom是nmake的多线程版,nmake不支持多线程,单线程编译速度太慢了。
4、编译源码库
以上东西都准备好以后,接下来我们可以开始编译源码了。
-
在编译之前记得先将所有的杀毒软件关掉(避免误杀)。
-
然后进入解压后的Qt源码文件夹下的qtbase/mkspecs下,找到win32-msvc文件夹。
-
另外顺便说下,如果是想编译较早些时候的Qt源码,源码下载下来后会发现里面没有这个文件夹。而是这样的:
这时候只需要根据你安装的Qt版本进行选择就可以了。 -
进入选中的文件夹之后,找到qmake.conf文件并使用文本编辑器打开。
-
我们再根据它include的内容定位到相应的文件。
include(../common/msvc-desktop.conf)
-
找到相应的文件后,修改其内容。在这里也就是msvc-desktop.conf这个文件。
找到以下标志。将原来的:
QMAKE_CFLAGS_RELEASE = $$QMAKE_CFLAGS_OPTIMIZE -MD QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -Zi -MD QMAKE_CFLAGS_DEBUG = -Zi -MDd
修改成:
QMAKE_CFLAGS_RELEASE = $$QMAKE_CFLAGS_OPTIMIZE -MT QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -Zi -MT QMAKE_CFLAGS_DEBUG = -Zi -MTd
即将MD改成MT,MDd改成MTd,动态改成静态
-
在开始菜单中,找到“适用于 VS 2017 的 x64 本机工具命令提示“ 或者 “x64 Native Tools Command Prompt for VS 2017”。
-
将当前目录切换到源码解压后的目录下。比如我的是在E盘下的qt-everywhere-src-5.11.2这个文件夹。
-
接下来,将执行关键的几个命令。首先执行configure命令。复制并执行以下命令:
configure.bat -mp -confirm-license -opensource -platform win32-msvc -debug-and-release -static -force-asserts -prefix E:\Qt5.11.2\Qt-msvc2017-x64-static -static-runtime -silent -opengl desktop -qt-sqlite -qt-pcre -qt-zlib -qt-freetype -qt-harfbuzz -qt-libpng -qt-libjpeg -nomake examples -nomake tests
· 其中 -platform win32-msvc 在前面也有提到过的,根据我们安装Qt的版本选择即可;
· -static 表示编译静态库;
· E:\Qt5.11.2\Qt-msvc2017-x64-static 是编译完后的安装目录,此目录不需要事先创建,建议路径不要太长。
这个过程不需要很久,执行完结果如图: -
执行jom命令。(这时候可以先去喝杯咖啡或者做做其他事情~~ )
-
jom执行完毕之后,最后再输入jom install安装。 如果没有意外,那么我们就会在之前设定好的路径下看到编译好的文件。
至此,整个Qt源码编译过程也就结束了(过程说简单也简单,但我却搞了两三天,就因为前面环境没搭好)
但别高兴得太早,这还没结束呢。。我们必须得建立一个测试程序运行起来才算成功!
4、安装和配置
-
点击菜单栏上的“Qt VS Tools > Qt Options”打开Qt选项窗口;
-
然后将我们编译好的Qt版本(E:\Qt5.11.2\Qt-msvc2017-x64-static)添加进来。
-
我们创建一个Qt应用程序进行测试。
-
整理遇到的问题。
使用Release方式编译,编译不通过!
错误一:Qt5Core.lib(qobject.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MT_StaticRelease”不匹配值“MD_DynamicRelease”(main.obj 中)
原因及解决方法:
- 因为我们编译的Qt5.11.2的VC运行库是MT和MTd,工程向导创建的缺省是MD和MDd。也就是我们需要把运行库对应的值改了。
错误二:
LINK : warning LNK4098: 默认库“LIBCMT”与其他库的使用冲突;请使用 /NODEFAULTLIB:library
原因及解决方法:
- 在同一个项目中,所有的源文件必须链接相同的VC运行时库。如果某一文件用了MTd版本,而其他文件用MT版本的库,也就是说用了不同的库,就会导致这个警告的出现。 添加一下命令行可解决:
/NODEFAULTLIB:“libcmt.lib”
错误三:
Qt5Core.lib(qglobal.obj) : error LNK2019: 无法解析的外部符号 gethostname,该符号在函数 “public: static class QString __cdecl QSysInfo::machineHostName(void)” (?machineHostName@QSysInfo@@SA?AVQString@@XZ) 中被引用
Qt5Core.lib(qglobal.obj) : error LNK2019: 无法解析的外部符号 WSAStartup,该符号在函数 “public: __cdecl QWindowsSockInit::QWindowsSockInit(void)” (??0QWindowsSockInit@@QEAA@XZ) 中被引用
Qt5Core.lib(qglobal.obj) : error LNK2019: 无法解析的外部符号 WSACleanup,该符号在函数 “public: __cdecl QWindowsSockInit::~QWindowsSockInit(void)” (??1QWindowsSockInit@@QEAA@XZ) 中被引用原因及解决方法:
显然,这是因为有些依赖库我们没添加好~-
附加库目录改成:$(QTDIR)\lib; $(QTDIR)\plugins\imageformats; $(QTDIR)\plugins\platforms;%(AdditionalLibraryDirectories)
-
附加依赖项改成:qtmain.lib;qwindows.lib;Qt5Widgets.lib;Qt5Core.lib;Qt5Gui.lib;Qt5PlatformCompositorSupport.lib;Qt5EventDispatcherSupport.lib;Qt5FontDatabaseSupport.lib;Qt5ThemeSupport.lib;Qt5WindowsUIAutomationSupport.lib;qgif.lib;qicns.lib;qico.lib;qjpeg.lib;qsvg.lib;qtga.lib;qtiff.lib;qwbmp.lib;qwebp.lib;qtfreetype.lib;qtharfbuzz.lib;qtlibpng.lib;qtopenwnn.lib;qtpcre2.lib;qttcime.lib;winspool.lib;shlwapi.lib;rpcrt4.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;glu32.lib;opengl32.lib;gdi32.lib;kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;mpr.lib;%(AdditionalDependencies)
- 在main.cpp文件中加入代码:
#pragma comment(lib, "version.lib") #pragma comment(lib, "Netapi32.lib") #pragma comment(lib, "userenv.lib") #pragma comment(lib, "msvcrtd.lib") #pragma comment(lib, "Dwmapi.lib")
距离成功我们又进一步了,继续编译。。
错误四:
qt.qpa.plugin: Could not find the Qt platform plugin “windows” in “”
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.原因及解决方法:
-
插件无法加载,加载plugin的办法:
使用宏 Q_IMPORT_PLUGIN,在main.cpp中增加代码如下:#include <QtCore/QtPlugin> Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
继续执行,发现可以了~ 成功了!