Windows下Qt静态编译连接和生成程序的

electri 贡献于2012-10-16

作者 New  创建于2011-04-14 03:59:00   修改者New  修改于2011-04-14 07:17:00字数22921

文档摘要:Windows下Qt静态编译连接和生成程序的 mingwm10.dll、 libgcc_s_dw2-1.dll依赖问题解决
关键词:

Windows下Qt静态编译连接和生成程序的 mingwm10.dll、 libgcc_s_dw2-1.dll依赖问题解决 本文编写和程序配置调试:蔚蓝 (winland0704@126.com ) http://hi.baidu.com/winland0704/home 一、官方Qt 库-MinGW版本(Qt Creator)静态编译和DLL依赖解决 1、MinGW版本 (1)MinGW官方版本(gcc-4.5.2) 使用dwarf2异常处理,默认使用动态C运行时库,默认生成的程序依赖: libgcc_s_dw2-1.dll(105K) libstdc++-6.dll(860K) 使用参数 -static 可以解除对以上dll依赖。 现在新版MinGW生成的程序默认已经不依赖mingwm10.dll了。 (2) TDM-GCC版本(Codelite和CodeBlocks带的,gcc-4.4.1) 使用sjlj异常处理,默认使用静态C运行时库,默认生成的程序独立运行,无dll依赖问题。 (3) MinGW Distro - nuwen.net最新版本(gcc 4.6.0) 使用dwarf2异常处理,默认使用静态C运行时库,无DLL依赖问题。 (4) QP-GCC版本(gcc-4.4.5) 使用dwarf2异常处理,默认使用静态C运行时库,无DLL依赖问题。 (5) PCX版本,包括32bit和64bit版本的MinGW(最新有gcc 4.6测试版) 与(4)差不多,无DLL依赖问题。 (6) Qt库自带的MinGW(gcc-4.4.0) GCC配置信息: D:\Qt\2011qt>gcc -v Using built-in specs. Target: mingw32 Configured with: ../gcc-4.4.0/configure --enable-languages=c,ada,c++,fortran,java,objc,obj-c++ --disable-sjlj-exceptions --enable-shared --enable-libgcj --enable-libgomp --with-dwarf2 --disable-win32-registry --enable-libstdcxx-debug --enable-version-specific-runtime-libs --prefix=/mingw --with-gmp=/mingw/src/gmp/root --with-mpfr=/mingw/src/mpfr/root --build=mingw32 Thread model: win32 gcc version 4.4.0 (GCC) Qt带的这个MinGW比较老,gcc-4.4.0版, 使用dwarf2异常处理,默认使用动态C运行时库。编写helloworld控制台程序,main.cpp #include #include #include using namespace std; int main(int argc, char **argv) { printf("Hello World!\n"); cout<<"Hello World!\n" ; system("PAUSE"); return 0; } ①编译命令:g++ -o hello.exe main.cpp -mthreads 依赖DLL: mingwm10.dll (12KB) libgcc_s_dw2-1.dll(42KB) 生成的hello.exe有3.59MB。很大,莫名其妙。 ②编译命令:g++ -o hello.exe main.cpp 依赖DLL: libgcc_s_dw2-1.dll(42KB) 生成的hello.exe有3.58MB。 ③编译命令:g++ -o hello.exe main.cpp -static 依赖DLL:无。 生成的hello.exe有3.67MB。 ④编译命令:g++ -o hello.exe main.cpp -mthreads -static 依赖DLL: mingwm10.dll (12KB) 生成的hello.exe有3.68MB。 最后一个命令我们看到一个有意思的现象,Qt带的这个MinGW的gcc-4.4.0里压根没有mingwm10.dll对应的静态库版本,所以存在-mthreads参数时,不管怎么用-static参数,它总是需要动态库mingwm10.dll,这就是官方Qt让人纠结的地方。 只要使用它自带的MinGW,在-mthreads参数启用时,你不管怎么搞,生成的exe必定依赖mingwm10.dll,怎么搞都搞不掉,这就是官方Qt库让人抓狂的地方。 网上有人说自己编译qt库,去掉-mthreads来编译自己qt库,当然不推荐这种搞法。还有使用-no-exceptions 配置来编译qt库,这也不好,异常处理都搞没了。 mthreads是多线程异常处理安全库,图形界面一般都要用的。下面我们通过换掉Qt官方老掉牙的MinGW来解决mingwm10.dll依赖的问题。 2、通用测试的helloqt程序代码 弄个helloqt文件夹,建个 helloqt.cpp : #include #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel *label = new QLabel("

Hello Qt !

"); label->show(); return app.exec(); } 打开Qt环境命令行,执行: $ cd /d D:\QtExample\helloqt $ qmake -project $ qmake helloqt.pro 生成Debug版程序: $ mingw32-make -f Makefile.Debug 生成Release版程序 $ mingw32-make -f Makefile.Release 3、官方Qt版本(默认动态库)和Qt Creator带的MinGW版本(默认动态C运行库)测试 (1)打开开始菜单----》Qt by Nokia v4.7.2 (MinGW OpenSource)----》Qt 4.7.2 Command Prompt $ cd /d D:\QtExample\helloqt 然后按2中生成项目,编译连接程序。生成helloqt.exe, Debug版大小:455 KB Release版大小:59 KB 不能独立运行,依赖DLL顺序: 第一:mingwm10.dll (11 KB) 第二:libgcc_s_dw2-1.dll (42 KB) 第三:QtCore4.dll (2.43 MB),debug版对应是QtCored4.dll 第四:QtGui4.dll (9.45 MB),debug版对应是QtGuid4.dll 除了exe之外,还得带上4个动态链接库。 (2) 使用static参数重新创建 将helloqt.pro复制一份,改名为helloqt-s.pro,用记事本打开helloqt-s.pro, 在最后一行加上一句: QMAKE_LFLAGS += -static 然后保存。在Qt 4.7.2 Command Prompt 命令行内执行: $ qmake helloqt-s.pro $ mingw32-make -f Makefile.Debug $ mingw32-make -f Makefile.Release 生成新的helloqt-s.exe, Debug版大小:541 KB Release版大小:76 KB 依赖的DLL顺序: 第一:mingwm10.dll (11 KB) 第二:QtCore4.dll (2.43 MB),debug版对应是QtCored4.dll 第三:libgcc_s_dw2-1.dll (42 KB) 第四:QtGui4.dll (9.45 MB),debug版对应是QtGuid4.dll 这里奇怪的是,为什么还需要libgcc_s_dw2-1.dll呢?命令行测试helloworld程序在-static生效后是不需要libgcc库的。 这里的release版helloqt-s.exe也确实增加了17KB,说明exe本身是带了libgcc代码的。 原因就在这四个依赖库的顺序! 可见是QtGui的dll在依赖libgcc_s_dw2-1.dll,Qt库本身还要依赖libgcc_s_dw2-1.dll。 Qt官方发布的库是底层用动态C运行时库,并且上层也是动态生成的Qt*.dll,所以即使在生成程序时用了-static参数,也不能减少dll的依赖。 4、官方Qt版本(默认动态库)和QP-GCC版本MinGW(默认静态C运行时库)测试 我们将 Qt目录下:\bin\qtvars.bat 复制一份到D:\QtExample\helloqt 目录下面。 现在替换MinGW,用记事本打开helloqt目录下的qtvars.bat,原来的: echo Setting up a MinGW/Qt only environment... echo -- QTDIR set to D:\Qt\2011qt echo -- PATH set to D:\Qt\2011qt\bin echo -- Adding D:\Qt\2011\mingw\bin to PATH echo -- Adding %SystemRoot%\System32 to PATH echo -- QMAKESPEC set to win32-g++ set QTDIR=D:\Qt\2011qt set PATH=D:\Qt\2011qt\bin set PATH=%PATH%;D:\Qt\2011\mingw\bin set PATH=%PATH%;%SystemRoot%\System32 set QMAKESPEC=win32-g++ 改写为: echo Setting up a MinGW/Qt only environment... echo -- QTDIR set to D:\Qt\2011qt echo -- PATH set to D:\Qt\2011qt\bin echo -- Adding D:\MinGW\bin to PATH echo -- Adding %SystemRoot%\System32 to PATH echo -- QMAKESPEC set to win32-g++ set QTDIR=D:\Qt\2011qt set PATH=D:\Qt\2011qt\bin set PATH=%PATH%;D:\MinGW\bin set PATH=%PATH%;%SystemRoot%\System32 set QMAKESPEC=win32-g++ cmd /k 改好保存。改后的D:\MinGW\bin就是之前安装QP-GCC版本的MinGW\bin目录。然后双击qtvars.bat,就可以直接打开Qt编译环境命令行了。 这样就完成了MinGW替换,我们用新的QP-GCC来编译helloqt程序。 (1)生成helloqt.exe $ qmake helloqt.pro $ mingw32-make -f Makefile.Debug $ mingw32-make -f Makefile.Release 生成新的helloqt.exe: Debug版大小:384 KB Release版大小:62 KB 依赖DLL的顺序: 第一:QtCore4.dll (2.43 MB),debug版对应是QtCored4.dll 第二:mingwm10.dll (11 KB) 第三:libgcc_s_dw2-1.dll (42 KB) 第四:QtGui4.dll (9.45 MB),debug版对应是QtGuid4.dll 注意这四个依赖库的顺序又有变化! 这次将QtGui4.dll的依赖体现的清清楚楚! Helloqt.exe使用QP-MinGW生成的,自己默认带静态C运行时库代码的。 这里完全是QtGui4.dll惹的祸!QtGui4.dll是使用老版本的gcc-4.4.0动态链接生成的。是QtGui4.dll需要底层C运行时库,就是mingwm10.dll和libgcc_s_dw2-1.dll。要想解除DLL依赖,必须自己动手编译静态Qt库。 (2) 生成helloqt-s.exe $ qmake helloqt-s.pro $ mingw32-make -f Makefile.Debug $ mingw32-make -f Makefile.Release 生成新的helloqt-s.exe: Debug版大小:384 KB Release版大小:62 KB 由于QP-GCC默认就是使用静态C运行时库,(1)中版本与(2)中完全一样。依赖关系也一样。不赘述了。 5、静态编译的Qt版本(默认静态链接)和QP-GCC版本MinGW(默认静态C运行时库)测试 (1)我们使用QP-MinGW来编译新的静态Qt库。 ①打开我们在helloqt目录下的新qtvars.bat,这样Qt目录和MinGW目录、QMAKESPEC参数就都设置好了。 ②在qt库安装目录(D:\Qt\2011qt)下面,修改D:\Qt\2011qt\mkspecs\win32-g++ 目录 下面qmake.conf文件(先备份),改两处: QMAKE_LFLAGS = -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc 修改为 QMAKE_LFLAGS = -static -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc 再将 QMAKE_LFLAGS_DLL = -shared 修改为 QMAKE_LFLAGS_DLL = -static ③在打开的控制台里执行:(D:\Qt\2011qt是qt库所在目录) $ cd /d D:\Qt\2011qt $ configure -platform win32-g++ -debug-and-release -opensource -static -fast -qt-sql-sqlite -plugin-sql-sqlite -no-qt3support   -qt-zlib -qt-gif -qt-libpng -qt-libmng -qt-libtiff -qt-libjpeg -no-webkit -qt-style-windowsxp -qt-style-windowsvista -nomake examples -nomake docs -nomake demos  如果有提问是否遵守LGPL协议,选y。配置完成后,最后两句是这样的: Qt is now configured for building. Just run mingw32-make. To reconfigure, run mingw32-make confclean and configure. 我们只在在Qt子目录src里运行make: $ cd src $ mingw32-make -i -k 然后可以去看个电影等静态qt编译库编译好。 注意,不要在整个qt库的大目录下运行make。只在src目录make,这样只编译核心的Qt库和一些插件,节省时间,而且有核心Qt库就够用了。 如果在D:\Qt\2011qt\ 整个大目录下运行make,那么make还会去重新编译生成tools目录下的代码,重新做工具程序,像assistant.exe、designer.exe、linguist.exe、qmlviewer.exe等等(生成后全在bin目录)。这些工具使用静态库生成后巨大无比,像linguist.exe静态链接版是12.7MB,qmlviewer.exe达到373MB。我们装的Qt库默认已经带了生成好的动态连接版的tools,完全没必要自己重编译这些工具。这些工具程序不管是静态链接还是动态链接生成的,对我们编程压根没影响,都一样用。 重新tools生成为静态版,不但占用空间大,他们的编译连接过程特别的慢。 如果只在src目录编译库,大概一部电影时间就生成好了。 如果在大目录下,编译核心库和tools的话,得在晚上睡觉前运行make,一觉睡醒,第二天才会编译好所有库和工具等。 特别注意:Qt 4.7.2静态编译连接的库,如果自己写程序时不使用libQtOpenGLd.a和libQtOpenGL.a,那么万事大吉,如果使用静态QtOpenGL,那么会出现: undefined reference to `_imp___Z14qt_defaultDpiXv' collect2: ld returned 1 exit status 连接错误。这个错误只在静态链接库使用时出现,对官方的动态连接使用QTOpenGL库没影响,只是使用静态库版本才出问题。出这问题的qt版本有:4.7.0-RC1, 4.7.2。 这问题已经有解决了,修改8个源码文件里共18处,将opengl和openvg源码里的Q_DECL_IMPORT宏替换为Q_GUI_EXPORT宏,并且去掉伴随的extern关键字就行了。 http://bugreports.qt.nokia.com/browse/QTBUG-13649 http://qt.gitorious.org/qt/qt/commit/7ec1c27e662dfd4393491f90bfcb9c868cc0a23f 详细讨论见附录。由于我们没用OpenGL,只是一个helloqt,先不管这个,我们看看新的静态库的使用效果。 (2)使用新的静态qt库来生成helloqt程序 我们在helloqt目录双击运行之前弄的qtvars.bat,打开QP-MinGW版的Qt环境命令行: $ qmake helloqt.pro $ mingw32-make -f Makefile.Debug $ mingw32-make -f Makefile.Release 生成新的helloqt.exe: Debug版大小:144 MB Release版大小:10 MB 这里QP-GCC使用静态Qt库和静态C运行时库生成的helloqt.exe是完全独立运行的,不依赖其他DLL,所以可以很好的解决附加DLL依赖问题。 但是看到静态版Debug版的helloqt的大小,我直接晕倒了。最简单的helloqt也能上100MB,之前见过wxWidgets的wxHello静态debug版,28 MB,Qt静态Debug版更夸张。 难怪Qt官方只发布动态链接版的Qt库了。 我们使用Free UPX对Qt静态Release版helloqt程序进行压缩处理,压缩后的helloqt.exe大小是3.74MB,这个大小还可以接受,对这个独立运行的exe还可以接受。 (3)生成helloqt-s.exe,对于QP-GCC来说,它默认使用静态C运行时库,所以helloqt-s.exe和上面的helloqt.exe完全是一样的,不作多余的测试了。它们都是不依赖其他dll,可以独立运行的。 6、静态编译的Qt版本(默认静态链接)和Qt附带的MinGW版本(默认动态库)测试 我们打开开始菜单----》Qt by Nokia v4.7.2 (MinGW OpenSource)----》Qt 4.7.2 Command Prompt, 就是qt官方默认安装的qt编译环境命令行。 (1)生成helloqt.exe,执行: $ cd /d D:\QtExample\helloqt $ qmake helloqt.pro $ mingw32-make -f Makefile.Debug $ mingw32-make -f Makefile.Release 生成的应用程序大小:(Qt官方带的gcc-4.4.0,默认动态C运行时库) Debug版:145 MB Release版:10 MB 依赖DLL的顺序: 第一:mingwm10.dll (12 KB) 就这一个依赖,由于qt静态库使用QP-GCC生成的,libgcc代码等等已经集成到QtGUI的静态库*.a文件里了,所以不需要libgcc_s_dw2-1.dll了。 (2)生成helloqt-s.exe,执行: $ cd /d D:\QtExample\helloqt $ qmake helloqt-s.pro $ mingw32-make -f Makefile.Debug $ mingw32-make -f Makefile.Release 生成的应用程序大小:(Qt官方带的gcc-4.4.0,默认动态C运行时库) Debug版:145 MB Release版:10 MB 依赖DLL的顺序: 第一:mingwm10.dll (12 KB) 只有一个依赖,和上面的helloqt.exe完全一样,这是由于qt静态库使用QP-GCC生成的。不依赖C运行时库,是因为我们源码里没有直接用到标准C++库,而之前helloqt.exe需要C运行时库是间接的QtGui依赖的,而不是exe直接依赖的。 7、静态编译的Qt版本(默认静态链接)和比较新的MinGW.org的GCC-4.5.2版本测试 我们复制helloqt目录下的qtvars.bat为新的qtvars-O.bat,用记事本打开qtvars-O.bat,修改其中的MinGW路径(MinGW官方GCC-4.5.2版本路径:C:\OMinGW\bin): echo Setting up a MinGW/Qt only environment... echo -- QTDIR set to D:\Qt\2011qt echo -- PATH set to D:\Qt\2011qt\bin echo -- Adding C:\OMinGW\bin to PATH echo -- Adding %SystemRoot%\System32 to PATH echo -- QMAKESPEC set to win32-g++ set QTDIR=D:\Qt\2011qt set PATH=D:\Qt\2011qt\bin set PATH=%PATH%;C:\OMinGW\bin set PATH=%PATH%;%SystemRoot%\System32 set QMAKESPEC=win32-g++ cmd /k 然后打开qtvars-O.bat命令行,用来编译程序。 (1)生成helloqt.exe,执行: $ qmake helloqt.pro $ mingw32-make -f Makefile.Debug $ mingw32-make -f Makefile.Release 生成的应用程序大小:(MinGW.org的GCC-4.5.2版本生成的) Debug版:144 MB Release版:10.1 MB 无DLL依赖问题。 不依赖C运行时库,应该是我们代码里没有直接使用标准C++库。而之前helloqt.exe需要C运行时库是间接的QtGui依赖的,而不是exe直接依赖的。 (2)生成helloqt-s.exe,执行: $ qmake helloqt-s.pro $ mingw32-make -f Makefile.Debug $ mingw32-make -f Makefile.Release 生成的应用程序大小:(MinGW.org的GCC-4.5.2版本生成的) Debug版:144 MB Release版:10.1 MB 这里的与上面helloqt.exe一样。无DLL依赖问题。不依赖C运行时库,应该是我们代码里没有直接使用标准C++库。而之前helloqt.exe需要C运行时库是间接的QtGui依赖的,而不是exe直接依赖的。 从6和7两节的对比,我们可以发现,Qt官方的MinGW-GCC-4.4.0默认生成的exe之所以依赖mingwm10.dll,是因为这个GCC版本问题,与Qt库本身没关系,所以解除mingwm10.dll依赖,需要更新GCC版本,推荐用QP-MinGW或者MinGW.org官方最新版本,并且要用新版MinGW重新编译自己的Qt库和其他应用程序,这样才能彻底去除Qt库对mingwm10.dll的依赖。 如果是用MinGW.org官方最新版本编译Qt库,编译生成的exe程序如果出现依赖libgcc_s_dw2-1.dll(105K)和libstdc++-6.dll(860K)的情况的话,在连接参数里加上 -static, 对 *.pro 文件进行修改: 用记事本打开 *.pro ,在最后一行加上一句: QMAKE_LFLAGS += -static 然后编译连接程序就行了。 8、Qt(默认动态/静态链接) ,MinGW-GCC版本(默认动态/静态)组合测试与DLL依赖问题解决总结 Qt库和GCC版本\ 测试项目 Hellqt程序 大小 release依赖DLL顺序 发行时exe和dll总数目/大小 其他说明 3、QT官方库(默认动态链接) Debug:455 KB Release:59 KB mingwm10.dll (11 KB) 5个 12MB QT自带 MinGW-GCC-4.4.0(默认动态C运行时库) libgcc_s_dw2-1.dll (42 KB) QtCore4.dll(2.43 MB) QtGui4.dll(9.45 MB) 4、QT官方库(默认动态链接) QP-GCC-4.4.5(默认静态C运行时库) Debug:384 KB Release:62 KB QtCore4.dll(2.43 MB) mingwm10.dl(11 KB) libgcc_s_dw2-1.dll (42 KB) QtGui4.dll(9.45 MB) 5个 12MB 6、静态编译的Qt库(默认静态链接) QT自带 MinGW-GCC-4.4.0(默认动态C运行时库) Debug:145 MB Release:10 MB mingwm10.dll(12 KB) 2个 10MB 5、静态编译的Qt库(默认静态链接) QP-GCC-4.4.5(默认静态C运行时库) Debug:144 MB Release:10 MB 无 1个 10MB UPX压缩后:3.74MB 7、静态编译的Qt库(默认静态链接)MinGW.org官方新的GCC-4.5.2版本(默认动态C运行时库) Debug:144 MB Release:10.1 MB 无 (helloqt代码里没有直接使用标准C++库) 1个 10MB UPX压缩后:3.74MB 如果出现依赖libgcc_s_dw2-1.dll和libstdc++-6.dll 使用-static参数,在pro文件里加上: QMAKE_LFLAGS += -static 去除mingwm10.dll依赖,通过更换新的MinGW来实现,推荐QP-MinGW和MinGW.org官方新版本。对MinGW.org官方新版本GCC生成的程序去除libgcc_s_dw2-1.dll和libstdc++-6.dll依赖使用-static参数,在pro文件里加上:QMAKE_LFLAGS += -static 9、推荐Qt库的编译连接方式(官方动态Debug版Qt库 + 静态Release版Qt库) 从上面测试对比, 静态Debug版Qt库生成helloqt程序达到144MB,这个太夸张了。 而官方动态Debug版Qt库生成的helloqt只有几百KB,所以推荐使用官方动态Debug版Qt库来调试程序,官方的动态链接的Debug、Release版本Qt库要多依赖mingwm10.dll (11 KB)、libgcc_s_dw2-1.dll (42 KB)这两个DLL,没其他的影响。 使用静态Release版Qt库来生成可独立运行的发行版helloqt程序,再用UPX来压缩一下,exe大小就可以接受了。现在整理一下推荐的Qt编译和使用方式。 (1)下载官方Qt 库-MinGW版本,安装好,我安装的目录是:D:\Qt\2011qt ,QtCreator目录是:D:\Qt\2011,Qt带的MinGW目录:D:\Qt\2011\mingw 。 再下载安装QP-MinGW或PCXPRJ的MinGW或者MinGW.org官方新版本。 我的QP-MinGW安装目录是:D:\MinGW 我们从D:\Qt\2011qt\bin目录复制一个qtvars.bat出来到新目录helloqt里。 修改qtvars.bat内容为:(替换旧的MinGW为QP-MinGW) echo Setting up a MinGW/Qt only environment... echo -- QTDIR set to D:\Qt\2011qt echo -- PATH set to D:\Qt\2011qt\bin echo -- Adding D:\MinGW\bin to PATH echo -- Adding %SystemRoot%\System32 to PATH echo -- QMAKESPEC set to win32-g++ set QTDIR=D:\Qt\2011qt set PATH=D:\Qt\2011qt\bin set PATH=%PATH%;D:\MinGW\bin set PATH=%PATH%;%SystemRoot%\System32 set QMAKESPEC=win32-g++ cmd /k 保存后运行新的qtvars.bat,打开新的qt环境命令行。 (2)使用QP-MinGW编译生成静态链接的Release版本Qt库 在qt库安装目录(D:\Qt\2011qt)下面,修改D:\Qt\2011qt\mkspecs\win32-g++ 目录 下面qmake.conf文件(先备份),改两处: QMAKE_LFLAGS = -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc 修改为 QMAKE_LFLAGS = -static -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc 再将 QMAKE_LFLAGS_DLL = -shared 修改为 QMAKE_LFLAGS_DLL = -static 然后在新的qt环境命令行执行: $ cd /d D:\Qt\2011qt $ configure -platform win32-g++ -release -opensource -static -fast -qt-sql-sqlite -plugin-sql-sqlite -no-qt3support   -qt-zlib -qt-gif -qt-libpng -qt-libmng -qt-libtiff -qt-libjpeg -no-webkit -qt-style-windowsxp -qt-style-windowsvista -nomake examples -nomake docs -nomake demos  注意到这里只是生成静态连接的release版本Qt库。运行: $ cd src $ mingw32-make -i -k 等待库编译完毕就行了。 (3)测试helloqt程序,命令行进入helloqt目录: $ qmake helloqt.pro $ mingw32-make -f Makefile.Debug $ mingw32-make -f Makefile.Release 生成新的helloqt.exe: Debug版大小:不能生成。由于没有编译静态Debug版本Qt库。 Release版大小:10 MB,无DLL依赖。 静态编译的Release版本helloqt.exe再使用FreeUPX压缩一下,就可以用了。 (4)注意到(3)中debug版没生成,如果生成的话,144MB也太吓人了。 要生成动态链接的Debug版本helloqt程序的话,手动修改Makefile.Debug内容, 只需要更改LIBS选项内容: LIBS = -L"d:\Qt\2011qt\lib" -lmingw32 -lqtmaind -lQtGuid -lgdi32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lwinspool -lmsimg32 -lQtCored -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lws2_32 更改为: LIBS = -L"d:\Qt\2011qt\lib" -lmingw32 -lqtmaind -lQtGuid4 -lgdi32 -lcomdlg32 -loleaut32 -limm32 -lwinmm -lwinspool -lmsimg32 -lQtCored4 -lkernel32 -luser32 -lshell32 -luuid -lole32 -ladvapi32 -lws2_32 如上将链接库替换掉,然后运行: $ mingw32-make -f Makefile.Debug 就能生成动态链接的Debug版的exe,这里生成的helloqt.exe大小是385KB,依赖DLL: QtGuid4.dll、QtCored4.dll、mingwm10.dll、libgcc_s_dw2-1.dll。这是debug版,依赖其他dll无所谓。 同理,如果修改Makefile.Release内容,如上面一样修改,就可以使用qt官方动态库生成动态链接的Release版的exe。 这样只需修改LIBS 变量,就可以自由调整Qt链接库的版本。 调试好程序后,用静态链接Qt库生成release版本exe,这个发行版exe可以独立运行。最好使用UPX将发行版exe(约10MB)压缩后发布,压缩后大小约4MB。 二、官方Qt 库-VS 2008版本静态编译和DLL依赖解决 这方面帖子很多,如: http://www.qtcn.org/bbs/read.php?tid=13825 http://www.cnblogs.com/mcxiaoke/archive/2010/05/12/1733801.html http://blogold.chinaunix.net/u/8780/showart_2512710.html 过程如下 1、下载安装用于 Windows 的Qt 库 4.7.2 (VS 2008, 218 MB),当然要先装好Visual Studio。 然后用记事本打开 %QTDIR%\mkspecs\win32-msvc2010\qmake.conf 如果是VS2005,那么编辑win32-msvc2005目录下的qmake.conf,如果是VS2008,那么编辑win32-msvc2008目录下的qmake.conf,修改前注意备份。 编辑该文件: 将 QMAKE_CFLAGS_RELEASE 和 QMAKE_CFLAGS_DEBUG 中的 -MD -MDd 分别修改为 -MT 和 -MTd 即可。 另外,还可以将 CONFIG 中的 embed_manifest_dll embed_manifest_exe 去掉(也可以不去掉)。 2、打开Visual Studio 2010或2008的命令行,执行 $ set QTDIR=D:\QtVS $ set PATH=%PATH%;%QTDIR%\bin $ set QMAKESPEC=win32-msvc2010 D:\QtVS 是Visual Studio对应的Qt库安装目录。运行配置: $ cd /d D:\QtVS $ configure -platform win32-msvc2010 -debug-and-release -opensource -static -fast -qt-sql-sqlite -plugin-sql-sqlite -no-qt3support -qt-zlib -qt-gif -qt-libpng -qt-libmng -qt-libtiff -qt-libjpeg -no-webkit -qt-style-windowsxp -qt-style-windowsvista -nomake examples -nomake docs -nomake demos 如果是VS2008,将win32-msvc2010修改为win32-msvc2008,VS2005类似。 3、进入src目录,生成静态Qt库 $ cd src $ nmake /I /K 经过漫长等待,Qt库编译好就可以用了。 4、测试helloqt程序 Visual Studio命令行加上2中set命令环境,这个可以写成一个bat脚本,下次要用就可以直接运行Qt + Visual Studio命令行。D:\QtVS\bin\qtvars.bat 就是一个例子,可以复制一份出来,修改Visual Studio的脚本位置,再在最后一行加上 cmd /k ,保存,下次可以直接双击新的qtvars.bat打开Qt + Visual Studio命令行。 编译helloqt: $ cd D:\QtExample\helloqt $ qmake helloqt.pro $ nmake -f Makefile.Debug $ nmake -f Makefile.Release VS生成静态连接Qt库Release版的helloqt程序大小是5.55MB,UPX压缩后是2.29MB,这个就挺不错了。Windows平台还是Visual Studio编译图形界面程序给力。 注意:这里没有用到静态QtOpenGL连接库,如果用到了,出现undefined reference to `_imp___Z14qt_defaultDpiXv' 连接错误,解决见附录,修改源代码重新生成Qt库。 对于Qt官方给的动态链接库,是不会出现这个问题的。 附录:Qt 4.7.2静态static编译连接的libQtOpenGLd.a库的 undefined reference to `_imp___Z14qt_defaultDpiXv' 连接错误解决。 连接错误在QtOpenGL的静态库里。不使用opengl库是不会出现这个问题的。 动态链接版的Qt库也没这个问题。 错误解决见如下帖子: http://bugreports.qt.nokia.com/browse/QTBUG-13649 http://qt.gitorious.org/qt/qt/commit/7ec1c27e662dfd4393491f90bfcb9c868cc0a23f 出错的症状类似这样: d:\build-472-static-debug\lib/libQtOpenGLd.a(qpixmapdata_gl.o):d:/qt/4.7.2-vs2005-org/src/opengl/qpixmapdata_gl.cpp:760: undefined reference to `imp__Z14qt_defaultDpiXv' d:\build-472-static-debug\lib/libQtOpenGLd.a(qpixmapdata_gl.o):d:/qt/4.7.2-vs2005-org/src/opengl/qpixmapdata_gl.cpp:762: undefined reference to `imp__Z14qt_defaultDpiYv' 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 d:\build-472-static-debug\lib/libQtOpenGLd.a(qglpixelbuffer.o):d:/qt/4.7.2-vs2005-org/src/opengl/qglpixelbuffer.cpp:427: undefined reference to `imp__Z14qt_defaultDpiXv' d:\build-472-static-debug\lib/libQtOpenGLd.a(qglpixelbuffer.o):d:/qt/4.7.2-vs2005-org/src/opengl/qglpixelbuffer.cpp:428: undefined reference to `imp__Z14qt_defaultDpiYv' collect2: ld returned 1 exit status mingw32-make[3]: *** [..\..\bin\qmlviewer.exe] Error 1 mingw32-make[3]: Leaving directory `D:/build-472-static-debug/tools/qml' mingw32-make[2]: *** [debug] Error 2 mingw32-make[2]: Leaving directory `D:/build-472-static-debug/tools/qml' mingw32-make[1]: *** [sub-qml-make_default-ordered] Error 2 mingw32-make[1]: Leaving directory `D:/build-472-static-debug/tools' mingw32-make: *** [sub-tools-make_default-ordered] Error 2 解决错误的原文: Fix static build on Windows with MinGW. Q_DECL_IMPORT is still __declspec(dllimport), which is unsuitable for static code. 意思是说Q_DECL_IMPORT宏只有动态链接的入口,没有静态版本代码,所以不能用于静态库。 Now we change Q_DECL_IMPORT to Q_GUI_EXPORT when declaring QtGui functions into opengl and openvg. Also removed the redundant keyword "extern" from the function declarations. 现在我们将src目录的子目录opengl和openvg里的Q_DECL_IMPORT宏全部替换成 Q_GUI_EXPORT宏,并且去除伴随其的多余的extern关键字。 具体要修改的源码: src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp (2 / 2)     102 102 extern bool qt_applefontsmoothing_enabled; 103 103 #endif 104 104 105 Q_DECL_IMPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); 105 Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert); 106 106 107 107 ////////////////////////////////// Private Methods ////////////////////////////////////////// 108 108 … … 1154 1154 d->fill(path); 1155 1155 } 1156 1156 1157 extern Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp 1157 Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp 1158 1158 1159 1159 1160 1160 void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) src/opengl/qglframebufferobject.cpp (2 / 2)     1171 1171 } 1172 1172 #endif 1173 1173 1174 Q_DECL_IMPORT extern int qt_defaultDpiX(); 1175 Q_DECL_IMPORT extern int qt_defaultDpiY(); 1174 Q_GUI_EXPORT int qt_defaultDpiX(); 1175 Q_GUI_EXPORT int qt_defaultDpiY(); 1176 1176 1177 1177 /*! \reimp */ 1178 1178 int QGLFramebufferObject::metric(PaintDeviceMetric metric) const src/opengl/qglpixelbuffer.cpp (2 / 2)     416 416 #endif 417 417 } 418 418 419 Q_DECL_IMPORT extern int qt_defaultDpiX(); 420 Q_DECL_IMPORT extern int qt_defaultDpiY();     419 Q_GUI_EXPORT int qt_defaultDpiX(); 420 Q_GUI_EXPORT int qt_defaultDpiY(); 421 421 422 422 /*! \reimp */ 423 423 int QGLPixelBuffer::metric(PaintDeviceMetric metric) const src/opengl/qglpixmapfilter.cpp (3 / 3)     63 63 QT_BEGIN_NAMESPACE 64 64 65 65 // qpixmapfilter.cpp 66 Q_DECL_IMPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); 67 Q_DECL_IMPORT QImage qt_halfScaled(const QImage &source); 66 Q_GUI_EXPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); 67 Q_GUI_EXPORT QImage qt_halfScaled(const QImage &source); 68 68 69 69 void QGLPixmapFilterBase::bindTexture(const QPixmap &src) const 70 70 { … … 436 436 return x + multiplier - mod; 437 437 } 438 438 439 Q_DECL_IMPORT void qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride, 439 Q_GUI_EXPORT void qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride, 440 440 quint32 *dest, int dstStride); 441 441 442 442 bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &) const src/opengl/qpaintengine_opengl.cpp (1 / 1)     79 79 80 80 QT_BEGIN_NAMESPACE 81 81 82 Q_DECL_IMPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp 82 Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp 83 83 #ifdef QT_MAC_USE_COCOA 84 84 extern void *qt_current_nsopengl_context(); // qgl_mac.mm 85 85 #endif src/opengl/qpixmapdata_gl.cpp (2 / 2)     739 739 return &m_texture; 740 740 } 741 741 742 Q_DECL_IMPORT extern int qt_defaultDpiX(); 743 Q_DECL_IMPORT extern int qt_defaultDpiY(); 742 Q_GUI_EXPORT int qt_defaultDpiX(); 743 Q_GUI_EXPORT int qt_defaultDpiY(); 744 744 745 745 int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const 746 746 { src/openvg/qpaintengine_vg.cpp (4 / 4)     77 77 78 78 #if !defined(QVG_NO_DRAW_GLYPHS) 79 79 80 Q_DECL_IMPORT extern int qt_defaultDpiX(); 81 Q_DECL_IMPORT extern int qt_defaultDpiY(); 80 Q_GUI_EXPORT int qt_defaultDpiX(); 81 Q_GUI_EXPORT int qt_defaultDpiY(); 82 82 83 83 class QVGPaintEnginePrivate; 84 84 … … 526 526 vgLoadMatrix(mat); 527 527 } 528 528 529 Q_DECL_IMPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); 529 Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); 530 530 531 531 void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) 532 532 { … … 994 994 return vgpath; 995 995 } 996 996 997 Q_DECL_IMPORT extern QImage qt_imageForBrush(int style, bool invert); 997 Q_GUI_EXPORT QImage qt_imageForBrush(int style, bool invert); 998 998 999 999 static QImage colorizeBitmap(const QImage &image, const QColor &color)     1000 1000 { src/openvg/qpixmapdata_vg.cpp (2 / 2)     404 404 destroyImages(); 405 405 } 406 406 407 Q_DECL_IMPORT extern int qt_defaultDpiX(); 408 Q_DECL_IMPORT extern int qt_defaultDpiY(); 407 Q_GUI_EXPORT int qt_defaultDpiX(); 408 Q_GUI_EXPORT int qt_defaultDpiY(); 409 409 410 410 int QVGPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const 411 411 { 最后一个文件的407、408行指的应该qt 4.7.0 rc 版的代码位置。 Qt 4.7.2的那两行代码位置靠后了: 新的位置在 415、416行。其他的都一样。这样QtOpenGL静态库就没问题了。 在生成静态链接程序tools目录里的qml子目录的qmlviewer会出现这个连接错误。通过修改共18行源码,然后再在src目录下面运行 $ mingw32-make -i -k 这样就搞定了。 如果是Visual Studio静态编译Qt,运行 nmake /I /K . 参考网址 维基百科:http://zh.wikipedia.org/zh/MinGW 百度百科:http://baike.baidu.com/view/975244.htm FreeUPX:http://www.52z.com/xunlei/xunlei_22409.html MinGW:http://www.mingw.org/ TDM-GCC:http://tdm-gcc.tdragon.net/ MinGW Distro - nuwen.net:http://nuwen.net/mingw.html QP' GCC:http://code.google.com/p/qp-gcc/ PCXPRJ MinGW:http://code.google.com/p/pcxprj/downloads/list CodeLite:http://www.codelite.org/ Code::Blocks:http://www.codeblocks.org/ CSDN:http://bbs.csdn.net/ Qt官方网站(中文):http://qt.nokia.com/title-cn 下载:http://qt.nokia.com/downloads-cn 用于 Windows 的Qt 库 4.7.2 (minGW 4.4, 321 MB): http://qt.nokia.com/downloads/windows-cpp 用于 Windows 的Qt 库 4.7.2 (VS 2008, 218 MB): http://qt.nokia.com/downloads/windows-cpp-vs2008 QT源码包:http://get.qt.nokia.com/qt/source/qt-everywhere-opensource-src-4.7.2.zip windows下 Qt 静态编译 http://blogold.chinaunix.net/u/8780/showart_2512710.html http://hi.baidu.com/cyclone/blog/item/25b262d9337a172310df9b78.html (配置命令显示有问题) Qt 程序在 windows 下的发布 http://hi.baidu.com/cyclone/blog/item/d77a86182fb915b84bedbc57.html 使用VC2005编译真正的静态Qt程序 http://www.qtcn.org/bbs/read.php?tid=13825 静态编译--configure参数说明 http://huoshaoyun52.blog.163.com/blog/static/126176173201042775925731/ Qt 4.6.2在VS2005,VS2008,MinGW环境下的静态编译 http://www.cnblogs.com/mcxiaoke/archive/2010/05/12/1733801.html Qt4 with Visual Studio and static C runtime http://qtnode.net/wiki/Qt4_with_Visual_Studio_and_static_C_runtime Removing dependencies for mingwm10.dll and libgcc_s_dw2-1.dll,static linking? http://www.qtcentre.org/threads/29489-Removing-dependencies-for-mingwm10.dll-and-libgcc_s_dw2-1.dll-static-linking Static qT compilation and mingwm10.dll (MinGW) confusion. http://blog.lugru.com/2010/04/static-qt-compilation-and-mingwm10-dll-mingw-confusion/ mingw gcc 4 static build failed in toos/qml http://bugreports.qt.nokia.com/browse/QTBUG-13649?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel Commit 7ec1c27e662dfd4393491f90bfcb9c868cc0a23f http://qt.gitorious.org/qt/qt/commit/7ec1c27e662dfd4393491f90bfcb9c868cc0a23f

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档