1. 程式人生 > >mingw qt(可以去掉mingwm10.dll、libgcc_s_dw2-1.dll、libstdc++-6.dll的依賴,官方的mingw默認都是動態鏈接gcc的庫而TDM是靜態鏈接gcc庫,tdm版本更好用)

mingw qt(可以去掉mingwm10.dll、libgcc_s_dw2-1.dll、libstdc++-6.dll的依賴,官方的mingw默認都是動態鏈接gcc的庫而TDM是靜態鏈接gcc庫,tdm版本更好用)

單獨 option web blank debugging 信息 pre internal 類庫

原文地址:mingw qt作者:孫1東

不使用Qt SDK,使用mingw編譯qt源代碼所遇問題及解決方法:

configure -fast -release -no-exceptions -no-rtti -no-stl -no-qt3support -no-opengl -no-multimedia -no-webkit -no-script -no-scripttools -nomake tools -nomake examples -nomake demos -nomake docs -nomake translations -platform win32-g++

強烈推薦使用tdm版本的mingw gcc,相比官方mingw的慢速,晦澀,tdm的安裝過程簡單,清晰,更新也快,而且官方的mingw開發人員也在使用tdm(為啥不合並了算了呢)。

【關於mingw10.dll,libgcc_s_dw2-1.dll,libstdc++-6.dll】

mingwm10.dll是線程安全的異常處理時用到的清理函數,否則將會有內存泄漏。

libgcc_s_dw2-1.dll是gcc 的核心運行庫。

libstdc++-6.dll 是gcc支持的特定語言c++的運行庫。

用mingwrt3.18之前編譯出來的qt庫,默認依賴mingwm10.dll。使用mingwrt3.18編譯qt庫不再依賴mingwm10.dll。編譯出來的qt庫不能用upx進行壓縮,這個確認是upx的bug,因為使用aspack是沒有問題的。如果想在3.18以前去掉依賴,由於qt本身不使用異常處理,所以可以在configure的時候,選項 -no-exceptions 禁止異常處理從而去掉對mingwm10.dll的依賴,並且這樣編譯出來的qt庫體積還縮小不少。

用官方gcc4.4.0編譯出來的qt庫,默認依賴libgcc_s_dw2-1.dll,gcc-4.5.0默認還多一個依賴libstdc++-6.dll。官方的mingw默認都是動態鏈接gcc的庫而TDM是靜態鏈接gcc庫。使用官方mingw要想去掉對gcc核心庫libgcc_s_dw2-1.dll依賴的話,可以在編譯qt庫之前修改QTDIR/mkspec/win32-g++/qmake.conf,QMAKE_LFLAGS = -static-libgcc。或者configure之後修改QTDIR/.qmake.cache,QMAKE_LFLAGS += -static-libgcc。取消對c++運行庫libstdc++-6.dll的依賴,使用選項-static-libstdc++。修改QTDIR/.qmake.cache順便還可以選擇不編譯examples,demos等等部件,只保留libs。或者configure的時候指定 -nomake tools -nomake examples -nomake demos -nomake docs -nomake translations

相對官方mingw的繁雜,使用tdm版的mingw的好處很多,首先,安裝過程簡單清楚,其次產生的qt庫不依賴libgcc_s_dw2-1.dll,libstdc++-6.dll,並且如果用tdm-gcc-4.5.0(mingw-runtim-3.18)的話,連mingwm10.dll也不需要了。tdm有兩個版本,sjlj和dw2,這是兩種不同的異常處理方式,sjlj是老的方式,速度慢,可能更穩定些;dw2是新的方式,速度更快。tdm4.5.0默認是用sjlj的,當然也提供了dw2的版本。除了下載官網上給出的dw2版本的文件,可能需要再下個libexpat-2.0.1-1-mingw32-dll-1.tar.gz,(不知道缺了會怎樣),因為我試了用on-demand安裝的時候,選dw2,他是會安裝libexpat.dll的。然後把所有帶-dw2的重命名為不帶dw2的,比如g++-dw2重新命名為g++,tdm的說明裏說這兩個版本可以和平共處,後面有如何做到。

【使用gcc 4.4.0編譯出現亂碼】

gcc4.4會自動檢測當前的locale,並產生相應的輸出。如要使用純英文環境,設置一下環境變量 LANG=C 或者 LANG=en_US。

【有時候編譯QT會出錯誤:qtvariantproperty.cpp:1927: internal compiler error】

具體原因未知,有人說是gcc的bug,我懷疑跟內存使用情況有關。所以最好是編譯過程中不要搞別的動作,這樣會大大減少出現這種情況的幾率。不過既然有時候還是會出現這樣的問題也得有個解決辦法,經過研究可以這樣:先去QTDIR/tools/designer/src/lib下,刪除tmp目錄以及所有qmake生成的makefile,手動qmake,生成makefile,此時先別make,雖然這時可以成功,但後面的編譯無法繼續,所以要先回到QTDIR目錄,再make。

【使用gcc4.5.0編譯qt4.6.2,報錯0xc00000005】

按照gcc4.5.0的說明也不能解決,其實qt的conf文件裏面已經添加有這樣選項。

使用tdm-gcc-4.5.0(sjlj或者dw2均可)。

【默認編譯QT時不編譯phonon模塊】

mingw需要打上相應的補丁 補丁中所有文件放到mingw/include下,為了使用補丁還需要下載MSYS 和patch,patch用法:patch < dshow.patch,這樣就打好補丁了。這樣在configure qt時,就會自動檢測到系統支持phonon,於是phono庫將被編譯。單獨安裝的MSYS(core)使用某些命令時會出現warning:terminal is not fully functional (press RETURN),這是由於沒有設置/etc/termcap,使用MSYS完整安裝版把它下面的termcap考過來就可以了,或者幹脆就用完整安裝的MSYS算了,就是版本稍老一點而已,那裏面基本上什麽都有了。

【編譯dbus】

dbus跟phonon一樣,也是需要額外支持才能編譯,首先下載windbus,地址 src/dbus make

【安裝qt之後,改變qt的位置】

qt編譯完了目錄不能隨便改名,否則會出現某文件找不到的情形,qt編譯時把當前qt的路徑硬編碼到qt庫中以及qmake中,等等,所以不能隨便改名。如果要改名可以:

1.使用qpatch,這個是qtcreator帶的小工具,當安裝qt sdk的時候,安裝程序就是通過運行qpatch來更改qt安裝目錄的。使用方法:qpatch files-to-patch-windows oldQtDir newQtDir。假設原來的安裝目錄是C:Qt2010.04,改名後的目錄為C:Qt2000.00。運行命令行,進入C:Qt2000.00bin目錄,qpatch files-to-patch-windows C:/Qt/2010.04/qt c:/qt/2000.00/qt,files-to-patch-windows指定的替換文件列表都是位於qt目錄下的,也就是prefix=C:/Qt/2010.04/qt,qpatch 會根據c:/qt/2000.00/qt+files-to-patch-windows找出所有需要替換的文件。這裏需要註意大小寫,奶奶的,看來Qt的工程師也有不少缺心眼的,windows下比較目錄字符串居然是大小寫敏感的,害的我琢磨了半天,明明看著有這個路徑居然替換不了,好在老夫靈光一閃,嗯。。我真聰明。使用qpatch有個限制就是改名後的目錄長度不能大於原來的長度,這也就是為什麽安裝包裏未解壓出來的默認目錄是一大長串的原因。

2.還有一種方法可以使用qt.conf:,在qt/bin下創建文件qt.conf,其內容如下:

[Paths]
Prefix = C:/xxx/yyy

老外說prefix指向的目錄必須包含.LICENSE-EVALUATION這個文件,當然一般都是這樣。

這樣可以從一個地方build出多個qt的版本放到不同的位置,編譯好後,不需要的目錄可以刪除,保留bin,lib,plugins,tools,include,src,mkspecs.這樣qtcreator就能正確識別qt不同版本.

【qtcreator中按F1獲取上下文幫助,顯示No documentation available】

尤其裝了多個版本的qt,很容易造成這種混亂,

xp系統下,刪除C:Documents and SettingsAdministratorApplication DataNokia。

win7系統下,刪除C:UsersdarkAppDataRoamingNokia

再重新啟動qtcreator即可。

【qtcreator1.3.1->Tools->Options->Qt versions->Debugging Helper顯示紅叉叉】

先rebuild,一切正常的話,將在QTDIR/qtc-debugging-helper目錄下生成gdbmacros.dll,這樣就變綠勾勾了。不過雖然可以找到helper庫,但是在調試程序的時候還是不能正確顯示Qt類以及stl,提示debugging helpers not found,金山打字通2010免費下載。後經反復驗證,發現原因是gdb版本不匹配,我自己安裝的mingw用的是gdb7.1而debugging helper只能支持到gdb6.8。解決方法為使用qtcreator自帶的mingw中的gdb或者自己下個gdb6.8。還有一種情況,好像必須得在qt程序(至少qtcore)裏才行,純c++的程序也會提示debugging helpers not found。

【qt 4.6.3靜態編譯後使用出錯】

編譯的過程沒有問題,但是使用libQtGui.a的時候報錯:

undefined reference to ‘_imp___Z21qt_call_post_routinesv‘
undefined reference to ‘_imp___Z21qDeleteInEventHandlerP7QObject‘

這個是qt的bug,使用4.6.2沒有問題

【編譯選項雜項】

修改$QTDIRmkspecsCOMPILERqmake.conf,其中COMPILER=win32-g++或者msvc-2008

win32-g++: QMAKE_CFLAGS_RELEASE = -Os -momit-leaf-frame-pointer
msvc-2008: QMAKE_CFLAGS_RELEASE = -O1 -Og -GL -MD

For anyone who is interested in a compiling fully static libraries for msvc (no msvcrtXX.dll dependence), you need change the QMAKE_CFLAGS_RELEASE from -MD to -MT, and add /NODEFAULTLIB:”MSVCRT” to the QMAKE_LFLAGS_RELEASE.

tdm 的dw2版,不改名,編譯即使用:gcc-dw2,g++-dw2,cpp-dw2,mingw32-gcc-dw2等等

首先修改QTDIR/qmake/Makefile.win32-g++:

CXX = g++-dw2

LINKQMAKE = g++-dw2 $(LFLAGS) -o qmake.exe $(OBJS) $(QTOBJS) $(LIBS)

這樣,qmake就可以正常生成了,接下來是qt庫,

再修改QTDIR/mkspecs/win32-g++/qmake.conf

QMAKE_CC = gcc-dw2

QMAKE_CXX = g++-dw2

QMAKE_LINK = g++-dw2
QMAKE_LINK_C = gcc-dw2

QMAKE_RC = windres --preprocessor=cpp-dw2

註意最後一個windres 調用gcc,gcc又調用cpp所以,直接cpp-dw2,不然還是找不到。

【qwt以及一般的designer插件】

qwt是一個繪制統計圖的庫,也作為designer的插件集成到qtcreator裏,這裏需要註意的問題是

IDE與編譯器的配合:如果使用的是qtsdk自帶的qtcreator,由於它本身是用msvc編譯的,為了使qwt的插件能被qtcreator識別,必須使用msvc編譯qwt,產生兩個dll,一個是qwt designer的插件qwt_designer_plugin5.dll這個放在qtcreator的designer目錄下,不過此時運行qtcreator還是不能顯示qwt的插件,因為它還依賴qwt.dll。再將qwt5.dll放到qtcreator的bin目錄下,這樣再運行qtcreator就可以看見qwt的插件了。然而事情還沒有完,當應用程序使用qwt類庫的時候,由於qt sdk的編譯器是mingw,所以必須使用mingw重新編譯qwt的類庫,生成的designer插件就不需要了,生成的libqwt5.a放在qt/lib下或者隨便什麽地方,這個導入接口庫只是為了編譯能成功,生成的qwt5.dll放在qt/bin下,或者直接放在可執行文件的目錄下,這是運行時真正要調用的。

明白了以上,那麽當然更好的辦法就是不用qt sdk,而是統一使用msvc編譯,於是這樣組合:下載單獨的qtcreator(默認為msvc編譯)+qt library msvc,這樣只需編譯一次qwt即可。

下載msvc 2008 express,安裝
下載單獨的qt creator(默認使用msvc編譯),安裝
下載qt libraries (msvc版),安裝
打開qtcreator 將編譯環境指定為使用剛剛下載安裝的qt (msvc版)
下載qwt-5.2.1源代碼,解壓
使用qtcreator打開qwt工程,編譯release版本
將qwt-build-desktopdesignerpluginsdesignerqwt_designer_plugin5.dll放到qtcreatorbindesigner目錄下
將qwt-build-desktoplibqwt5.dll放到qtcreatorbin目錄下
重新運行qtcreator你將會看到designer裏已經有qwt的控件出現,但還不能應用於程序中
為了讓程序中能使用qwt控件,還需再做幾件事
將qwt-build-desktoplibqwt5.lib放到qtlib目錄下
將qwt-build-desktoplibqwt5.dll放到qtbin目錄下
重新運行qtcreator,新建一個工程,隨便拽個qwt控件到form上
.pro中添加:
LIBS += -lqwt5
INCLUDEPATH += qwt-5.2.1src 這裏使用你自己的路徑
現在可以試試效果了

【LIBS vs LIBS_PRIVATE】

首先記住LIBS或者LIBS_PRIVTE,-Lpath -lname 後面都不能有空格。path中有空格的話

$$quote(-Lpath),path中可以使用""或者"/"都可以,不需要轉義""。

有時候很詭異,LIBS -L"path" -l"name"不起作用,而放到默認的qt/lib下就行。

這時可考慮使用LIBS_PRIVATE,還不行就直接完整路徑。

【多核編譯】

mingw32-make 參數設置 --jobs 或者 -j x ,x 是處理器的個數+1,貌似不起作用,設置了MAKEFLAGS=-j3也不行,或許根據環境自動就-jx了?

qtcreator自動使用jom代替nmake,我的雙核,jom -j 2,果然cpu占用達到了100%.

【meta object system】

meta object system除了實現了signal/slot,還實現了C++的擴展RTTI,類似java中的反射,運行時獲取類的所有信息。

由於qmake?不??理 .cpp中的Q_OBJECT(通常也很少有人?把Q_OBJECT?在.cpp,而是?在.h中),所以,如果.cpp中有Q_OBJECT的?,?? ?生出 undefined reference to ‘vtable for xxx ????.添加#include "xxx.moc" 放到 xxx.cpp 最尾端(一定要放最後一行)

【mingw dll 與 msvc dll】

不同的編譯器實現dll導出名字(name mangling)是不同的,對函數導出,我們可以使用統一的,經過extern "C" 處理過的不帶修飾的名字從而實現互聯互通;而對類的導出則復雜得多,涉及ABI(Application Binary Interface)的問題,需另外討論。

app 調用 dll 可分為4種情況:

1.mingw app調用 mingw dll

當然自家人認識自家人,pro裏直接LIBS += mingw.dll就可以,甚至不需要.a或者.lib

2.msvc app 調用 mingw dll

msvc app架子大,不認別人,直接使用mingw.a導入庫是不行的,至少release app不行,debug app倒還湊合能跑,原因未知。正確的方法為使用msvc的工具 生成msvc app需要的lib接口. 為了生成lib接口,我們需要有個def文件,這個可以在編譯mingw dll時自動生成,加入鏈接選項:QMAKE_LFLAGS += -Wl,--output-def,xxx.def.有了def 接下來的事情就簡單得很了。執行:lib /machine:i386 /def:xxx.def.這樣就生成了msvc app所需的xxx.lib和一個沒用的xxx.exp.

然後再pro裏LIBS += xxx.lib就行了

3.mingw app 調用 msvc dll

同 1. 直接LIBS += msvc.dll

Usually (read: for all DLLs created with MinGW and also a few others) MinGW links fine against a DLL. No import library is necessary .

4. msvc app 調用 msvc dll

沒啥說的

【使用QtTest】

QT += testlib 或者 CONFIG += qtestlib

http://blog.sina.com.cn/s/blog_930982070101edqf.html

mingw qt(可以去掉mingwm10.dll、libgcc_s_dw2-1.dll、libstdc++-6.dll的依賴,官方的mingw默認都是動態鏈接gcc的庫而TDM是靜態鏈接gcc庫,tdm版本更好用)