Qt5.11.2 & VS2017 & 64位版本靜態編譯及使用
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官網(地址:
下載後是一個壓縮檔案,將它解壓到一個空間較大的磁碟下面。一會靜態編譯需要佔用大量磁碟空間。(謹慎起見,請至少保證該磁碟下有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)” ([email protected]@@[email protected]@XZ) 中被引用
Qt5Core.lib(qglobal.obj) : error LNK2019: 無法解析的外部符號 WSAStartup,該符號在函式 “public: __cdecl QWindowsSockInit::QWindowsSockInit(void)” ([email protected]@[email protected]) 中被引用
Qt5Core.lib(qglobal.obj) : error LNK2019: 無法解析的外部符號 WSACleanup,該符號在函式 “public: __cdecl QWindowsSockInit::~QWindowsSockInit(void)” ([email protected]@[email protected]) 中被引用原因及解決方法:
顯然,這是因為有些依賴庫我們沒新增好~-
附加庫目錄改成:$(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)
繼續執行,發現可以了~ 成功了!