我在国内外Qt论坛上看到的最多的问题之一就是如何编译静态Qt库,可见在动态链接库(Windows: .dll, Linux:
.so)大势所趋的今天,静态链接库还是具有其存在的合理性和广泛需求。首先看看动态库给我们带来了什么:
1. 开发时的复用性:成千上万的各种实用库,包含它们的头文件,你就可以开始使用它们提供的功能;
2. 编译时的快捷化:进行过静态链接编译的人都知道,其编译过程的时间消耗是动态链接的数倍倍甚至更多;
3.
部署时的轻量化:如果你的程序使用操作系统自带的动态库,或者是一些非常流行的库。那么部署你的软件时,这些库便可以不用包含在你的packge里面,大
大减小了其体积;
4. 使用时的可维护性:某个库如果发布了更新的版本,那么你只需替换这个动态库文件,而不需要重新编译你的整个程序。
在如今这个时不时都需要给软件打补丁的时代,这是相当方便的。
那么,她又会给我们带来什么烦恼呢?软件的易用性至上。所谓易用性,不单单指这个进入了这个软件后使用起来多么多么方便,使用之前的那些过程同样也是易用
性的一部分。
用过Linux的可能都会有同感,装个软件真难啊,一会儿提示缺这个so库,一会儿这个so和那个so又不兼容了,还有甚者,你还需要在你的帐户的配置文
件里设置一大堆参数……还没安装完,就已经放弃了使用这个软件的念头。我想,易用性的问题也是Linux如此强大可是普及率远远不及Windows的根源
吧,毕竟绝大多数的用户需要的是一个傻瓜相机般的操作系统。
不过在Windows下,常常你也会遇到”某个dll无法找到,程序无法启动”、”需要.net
framework”之类的提示之。懂点软件知识的,还知道去下载这个缺失的dll库或者是下载.net的再发行库来安装。但是这已经大大违背了软件易用
性的原则,要知道软件的受众绝大多数都是与IT行业无关的人员,它们遇到这些问题时候便是束手就擒。
Visual Studio 2005后的版本更是不可理喻,它们编译出来的C/C++程序,如果在没有Visual
Studio再发行库的系统上运行,直接提示”应用程序没有正确配置,重新安装可能解决该问题”,简直不知所云……
静态链接的存在的合理性就在这里,一个可执行文件部署给用户,用户什么都不用做,双击一下就可享用。至于编译、维护,那是开发者的事情,哪怕一次编译要耗
费一天的时间,也不能浪费用户的时间去做一些对他来说不知所云而本可以在开发者的环节中完成的事情。
基于以上的信念,我研究了Windows下真正意义上的Qt静态库编译方法。至于什么叫”真正意义上”,看了下文便知。
Visual Studio相关编译选项
自己动手编译过Qt的人可能会觉得奇怪,拿这个问题来写这么一大段,真是小题大作。Qt的配置选项中不是写得清楚明白-static便是编译静态库吗。可
是你有真正试过吗,用这个静态库编译的程序拿到一个”干净”的机器上运行,则提示”应用程序没有正确配置……”或是”msvcrpxx.dll”没有找
到。看来Qt是静态了,可是Qt是用C++写的,其中链接的C++运行库还是动态的。解决这个问题,要从Visual
Studio的4个编译选项说起,它们决定了程序在链接阶段C/C++库的链接方式。
1.链接C/C++多线程动态库,使用这些编译选项,软件部署时需要VC的再发行库,否则就会出现上述错误提示。
/MD:动态链接多线程库(msvcrt.lib)。使用该选项时,需要用/NODEFAULTLIB选项来忽略掉libc.lib、
libcmt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib库,否则会有链接错误;
/MDd:动态链接多线程调试库(msvcrtd.lib)。使用该选项时,需要用/NODEFAULTLIB选项来忽略掉libc.lib、
libcmt.lib、msvcrt.lib、libcd.lib、libcmtd.lib库,否则会有链接错误;
2.链接C/C++多线程静态库,使用这些编译选项,软件部署时不需要VC的再发行库。
/MT:静态链接多线程库(libcmt.lib)。使用该选项时,需要用/NODEFAULTLIB选项来忽略掉libc.lib、
msvcrt.lib、libcd.lib、libcmtd.lib、msvcrtd.lib库,否则会有链接错误;
/MTd:静态链接多线程调试库(libcmtd.lib)。使用该选项时,需要用/NODEFAULTLIB选项来忽略掉libc.lib、
libcmt.lib、msvcrt.lib、libcd.lib、msvcrtd.lib库,否则会有链接错误。
OK,准备工作就绪,下面开始编译真正意义上的静态Qt库:-)
编译静态Qt库
既然找到了解决方法,这个编译就应该没问题了吧。可是configure时明明用-static配置了Qt,编译结果确仍然事与愿违。仔细查看所生成的
makefile,才发现编译选项都是/MD、/MDd。问题就出在这里啦,不过这成千上百个makefile,难道要手动一个个修改……一定有什么东西
决定了makefile的生成参数。不错!就在Qt根目录中的mkspecs目录里,一看名字就知道是make
specification的缩写。该目录下,各种平台下的各个编译器都有一个子目录。嘿嘿,编译器的编译选项就都在这里了,打开win32-
msvc2008中的qmake.conf看看,找到了下面两行吗:
QMAKE_CFLAGS_RELEASE = -O2 -MD -GL
QMAKE_CFLAGS_DEBUG = -Zi -MDd
相信你已经知道了问题答案,将它们改成:
QMAKE_CFLAGS_RELEASE = -O2 -MT -GL
QMAKE_CFLAGS_DEBUG = -Zi -MTd
同时别忘了加入前面提到的忽略库选项,修改QMAKE_LFLAGS_RELEASE和QMAKE_LFLAGS_DEBUG参数为:
QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO /LTCG /NODEFAULTLIB:libc.lib
/NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libcd.lib
/NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib
QMAKE_LFLAGS_DEBUG = /DEBUG /NODEFAULTLIB:libc.lib
/NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:msvcrt.lib
/NODEFAULTLIB:libcd.lib /NODEFAULTLIB:msvcrtd.lib
大功告成,这个时候再在Qt的根目录下configure -static
…(其它选项自行选择),然后nmake,两三个小时之后,真正意义上的静态Qt库就产生了。本人有个小建议,其实编译demos和examples会消
耗非常多时间,你只用cd src然后nmake来编译Qt库,如有需要cd
tools来编译诸如QtDesigner之类的工具。另外webkit库的编译是最耗时的,如果你不准备使用这个库,那么configure加入
-no-webkit,这样,整个编译过程大概值耗时40-60分钟。
这时候你可以尝试建立第一个纯静态的Qt程序,不过当你链接的时候,仍然会出现一大堆链接错误,提示 unresolved external
symbol。这个时候你只需要在你的Qt工程文件.pro里面加入:
win32:LIBS += Imm32.lib Winmm.lib ws2_32.lib
即可。至此,你的”纯”静态Qt应用程序就可以发布给用户啦。
阅读(924) | 评论(0) | 转发(0) |