Qt5.11.2 & VS2017 & 64位版本 静态编译
1、问题描述:
小伙伴们有没有也遇到过,自己使用Qt库开发的小程序,在自己电脑上跑得很欢快。
但当想要把编译好的.exe可执行文件发给朋友玩玩的时候,发现在没有安装Qt或者VS环境的电脑上是跑不了的。
究其原因,这是因为大家在编译程序时,大多使用的是动态编译。
简单来讲,就是编译好的程序在运行时另外还需要加上一堆的dll库文件,否则运行就会报错。
如果想将生成的程序连同所需要的依赖库一起完整地打包成一个.exe可执行程序,那就需要使用静态编译的方式。
然而,当使用VS编译Qt程序时,运行库选择多线程(/MT)(表示采用多线程静态链接库的方式)进行编译时,
发现编译是不能通过的。会有如下的错误提示:
Qqtmain.lib(qtmain_win.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MD_DynamicRelease”不匹配值“MT_StaticRelease”
原因在于安装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文件夹。
-
进入选中的文件夹之后,找到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选项设置主机平台和用于构建Qt源码的编译器(对于Windows机器,可以使用MinGW或Visual Studio工具链来编译Qt)
configure.bat -platform win32-g++
configure.bat -platform win32-msvc· -static 选项表示编译静态库;
. -debug-and-release 当然如果你只需要release版本,此选项可以改成"-release"
· -prefix 该选项是用于指定编译完后的安装目录,此目录不需要事先创建,建议路径不要太长。
. -qt 指定编译一些第三方库。
这个过程不需要很久,执行完结果如图:
-
执行jom命令。(这时候可以先去喝杯咖啡或者做做其他事情~~ )
-
jom执行完毕之后,最后再输入jom install安装。 如果没有意外,那么我们就会在之前设定好的路径下看到编译好的文件。
至此,整个Qt源码编译过程也就结束了(过程说简单也简单,但我却搞了两三天,就因为前面环境没搭好)
但别高兴得太早,这还没结束呢。。我们必须得建立一个测试程序运行起来才算成功!
4、安装和配置
-
点击菜单栏上的“Qt VS Tools > Qt Options”打开Qt选项窗口;
-
然后将我们编译好的Qt版本(E:\Qt5.11.2\Qt-msvc2017-x64-static)添加进来。
-
我们创建一个Qt应用程序进行测试。
5、整理下遇到的一些问题
-
问题一:使用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)
- 附加依赖项改成:Qt5AccessibilitySupport.lib;Qt5Network.lib;qtpcre2.lib;qtmain.lib;qwindows.lib;Qt5Widgets.lib;Qt5Core.lib;Qt5Gui.lib;Qt5PlatformCompositorSupport.lib;Qt5EventDispatcherSupport.lib;Qt5FontDatabaseSupport.lib;Qt5ThemeSupport.lib;Qt5WindowsUIAutomationSupport.lib;qgif.lib;qico.lib;qjpeg.lib;qtfreetype.lib;qtharfbuzz.lib;qtlibpng.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") #pragma comment(lib, "wtsapi32.lib") #pragma comment(lib, "Wsock32.lib") #pragma comment(lib, "Imm32.lib") #pragma comment(lib, "Winmm.lib") #pragma comment(lib, "ws2_32.lib")
距离成功我们又进一步了,继续编译。。(如果依然会报类似的错误提示,可以自行尝试继续添加其他一些必要的依赖文件试试!)
- 附加库目录改成:$(QTDIR)\lib; $(QTDIR)\plugins\imageformats; $(QTDIR)\plugins\platforms;%(AdditionalLibraryDirectories)
-
问题四:
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) ```
继续执行,发现可以了~ 成功了!