使用VC2005编译真正的静态Qt程序

首先,你应该该知道什么叫静态引用编译、什么叫动态引用编译。我这里只是简单的提提,具体的可以google一下。

动态引用编译,是指相关的库,以dll的形式引用库。动态编译的Exe程序尺寸比较小,因为相关的库都没有包含进来。当然,程序发布的时候,还要把相关的库也一并发布出去。

静态引用编译,是指把相关的库也一并引入Exe文件。这是程序的尺寸就会很大,不过,程序发布就会变得简单很多。

其次,你可能会注意到我标题上写了“真正”这两个字。为什么我要强调真正这两个字呢?因为使用VC编译的C或者C++程序,都需要相关的C runtime库才能运行。如果你是VC6,相应的库就叫MSVCR,如果是vc2005,那就是MSVCR08,vc2008就是MSVCR09。我这里假设你安装的是VC2005,请进入如下目录:${VS Install Dir}\VC\redist\x86 和 ${System Driver}:\windows\WinSxS,你就会发现下面有很多很多的库。没错,这里相当一部分就是C runtime库。

好了,言归正传,首先,我们用VC2005写了一个不使用MFC的存C或者C++的程序,怎么发布给最终用户呢?有两个方法:
(1)静态引用C runtime库:打开“项目”->“XXX属性”->“配置属性”->“C/C++”->“代码生成”->“运行时库”。看到了吧?这里一共有四个选项,其中MT开头的是静态引用,MD开头的是动态引用,d结尾的是Debug调试版本,没有d的是Release发布版本,所以就一共有四个选项。我们选择/MT,然后编译程序(生成的程序应该不小),把这个程序发给用户,然后用户就可以直接运行了。
(2)动态引用C runtime库:跟上面差不多,不过是用/MD选项编译(程序应该只是几十K),然后发给用户。这时,用户是不能运行这个程序的,会报个什么程序引导失败,重装系统可能会修复问题之类的提示。这是我们还要把C runtime库一并发过去。把${VS Install Dir}\VC\redist\x86\Microsoft.VC80.CRT下的所有文件(注意,是所有,包括那个.manifest文件)发给用户,用户把这些文件放在我们的程序的同一个目录,然后再次运行,这时,程序就起来了(VC2005之后,C runtime库的引用改变了很多,建议google一下)。

说完C runtime库,就来说说Qt库了,这里我假设你用的是最新的Qt4.4.3。我们编译Qt的时候,configure.exe有很多参数,大家可以configure.exe --help来看看,其中,默认生成的Qt库(这里默认的意思,是指没有加-share或者-static参数)是动态引用的,也就是说,编译完后,在QtDir的lib目录下除了一大堆lib文件外,还有一大堆的dll文件。我们发布我们的Exe程序的时候,需要把相应的Qt库的Dll也一并发给用户。

按照Qt的安装手册和网上一大堆大牛的说法,加上-static参数后,Qt就可以静态编译了,也就是说,lib目录下之后一大堆lib文件,没有dll文件。是否?我们做个试验:

首先是设置变量:
set QTDIR=%CD%
set PATH=%PATH%;%QTDIR%\bin
set QMAKESPEC=win32-msvc2005
"C:\Program Files\Microsoft Visual Studio 8\VC\vcvarsall.bat"" x86
配置makefile:
configure -release -static -fast -qt-sql-odbc -qt-sql-sqlite -no-webkit
(这里的参数就不一一说明了,建议读者打入--help认真查查,特别注明一下,之所以-no-webkit,是因为新版的qt加上了Webkit,而这个东东编译的时候非常耗时间,编译后也很大,有100多M,并且我基本不会用到这个东东,所以忽略它)
然后
cd src  (我之所以直接进入src目录nmake,是因为不想make其它不相干的模块,节省时间)
nmake

漫长的等待之后,我们发现lib下果然只有一大堆lib文件了,而且每个lib文件的尺寸都在M以上,似乎已经成功了。然后我们在安装了qt-vsintegration的VC2005新建一个Qt工程,然后编译一个release版本。编译的时候,问题来了。我们选择/MD选项,这时链接就可以通过,但如果我们想要用/MT选项来使用静态C runtime库,就会报一大堆某某函数链接重复之类的错误。经验告诉我们,之所以不能使用/MT来编译,是因为另外一个库——Qt库使用了另外一种引用方式/MD(原则上来说,一个程序里面的所有模块,都应该使用同一种引用方式,具体可以google一下)。很显然,我们编译的所谓静态Qt程序,一样要背着微软的C Runtime库到处跑,还不够“真正”的静态。

怎么才能做成完全的静态呢?记得之前编译wxWidgets的时候,它除了有SHARED=0或者1的选项之外,还有一个RUNTIME_LIBS = static or dynamic的选项,很显然,这个RUNTIME_LIBS的选项就是我们想要的选项。不过我翻遍了Qt的安装手册以及网上大牛的文章,都没有提及这个问题,我当时心里就觉得奇怪,难道没人遇到过这个问题?我又认真翻查了configure.exe的help,也没有类似的选项,问题一下就僵住了。

回忆一下刚才我们编译的时候,屏幕上调用cl.exe编译的时候,有这样一个参数:cl.exe .... -MD .... xxx.cpp,眼利的朋友一下就会发现,这个-MD就是c runtime动态引用的选项。然而,怎么把这个-MD改成-MT呢?我们翻开刚才我们编译的qt的src目录下,随便找个目录进去,打开Makefile.Release,我们就会看到CFLAGS=-MD ........,没错,就是这里。我们只要在这里把-MD改成-MT,就会使用静态c runtime库编译Qt了。我们当然不可能一个一个地替换这些makefile,关键是找出生成这些参数的模板文件。很显然,它肯定在qt的mkspecs目录,我们直奔win32-msvc2005目录,果然找到一个qmake.conf文件,果然找到一个QMAKE_CFLAGS_RELEASE = -O2 -MD,把这里的-MD换成-MT,然后清理一下刚才的生成的配置信息(网上又说用nmake confclean来清空,不过我没有成功,貌似是使用了-fast参数的缘故,不过没关系,把这个目录删掉,重新解压一份源代码就可以了,然后把win32-msvc2005目录下的qmake.conf的-MD换成-MT),重新
configure -release -static -fast -qt-sql-odbc -qt-sql-sqlite -no-webkit
然后nmake
又是漫长的等待。不过我们不要干等,看看出来的编译命令,cl.exe .... -MT .... xxx.cpp,果然变成静态c运行库了。
编译完之后,像刚才那样,在VC2005建一个Qt的工程,然后用/MT这个选项编译,OK,编译成功,出来的Exe文件大小是4.95M,貌似已经把C runtime库嵌进来了。然后把这个程序放到用户那里运行,OK单个Exe文件运行成功了。

至此,编译真正静态的Qt程序试验完成。总结一下整个过程,首先是要有耐性,因为编译一次Qt都至少两个小时(当然,用一些技巧,例如-fast,-no-qmake,只编译src等等的技巧可以缩短很多时间),我来回就编译了五次Qt;其次熟悉一些常见的编译、链接的错误,例如一见到XXX库已经引用之类的错误,马上就联想到应该是引用不同的库导致的;最后,要善于发现问题,查找问题。

http://www.cnblogs.com/bingcaihuang/archive/2010/12/01/1892765.html

时间: 2024-08-04 16:05:59

使用VC2005编译真正的静态Qt程序的相关文章

使用VC2005编译真正的静态Qt程序 good

首先,你应该该知道什么叫静态引用编译.什么叫动态引用编译.我这里只是简单的提提,具体的可以google一下. 动态引用编译,是指相关的库,以dll的形式引用库.动态编译的Exe程序尺寸比较小,因为相关的库都没有包含进来.当然,程序发布的时候,还要把相关的库也一并发布出去. 静态引用编译,是指把相关的库也一并引入Exe文件.这是程序的尺寸就会很大,不过,程序发布就会变得简单很多. 其次,你可能会注意到我标题上写了“真正”这两个字.为什么我要强调真正这两个字呢?因为使用VC编译的C或者C++程序,都

编译OpenWrt平台上Qt程序的环境配置

很久没有整Qt了,现在基本的功能实现了,需要移植到目标平台,配置环境如下: 从linux移植qt移植到openwrt上. 配置QMAKESPEC (这个指定来qmake.conf目标文件位置,toolchain提供相对目录mips-linux-g++, qmake.conf需要修改编译工具名称) 配置STAGING_DIR (这个是openwrt平台的需要,相对应OpenWrt SDK中的目标平台) /{目标平台}toolchain/qmake {目标}.pro 生成Makefile 修改mak

亲测VS2010纯静态编译QT4.8.0,实现VS2010编译调试Qt程序,QtCreator静态发布程序(图文并茂,非常详细)

下载源代码,注意一定是源码压缩包如qt-everywhere-opensource-src-4.8.0.zip,不是Qt发布的已编译的不同版本的标准库如qt-win-opensource-4.8.0-vs2010.exe,这些版本都只是动态编译的,不是我们所需要的.只有用源码包才能做真正的纯静态编译,如果用Qt官网已编译的标准库.exe文件进行编译,有可能出现各种错误,而且编译后的文件巨大,我当时就在这里绕了很大的弯子,请童鞋们注意啦!!可能有些老鸟会笑话,但我本着最严肃的态度告诉菜鸟们,上网查

Linux下编译静态MinGW环境,编译windows平台Qt程序(使用MXE)

参考链接: MXE.>大多数程序都是在windows平台下开发的程序.windows 在现实中也是绕不过的一个系统平台,做为受过几年VC,MFC”虐待”的程序员,在做为一个程序员之前是一位Linux重度使用者,受够了MFC之后一直想要找一个框架替换,使用过GTK,wxWidgets,Qt,最后还是Qt用得多一些.我认为程序跨平台应该是一个基本标准,同一份代码不需改动,或者改动极少,放在不同的平台下编译就能使用.不同平台,同样的界面,同样的操作,同样的体验.这里要讲的是我如何在Linux 下开发跨

Linux下静态编译Qt程序

一般情况下,我们用Qt编译出来的程序是要依赖于系统Qt库的,也就是这个程序移到别的没有安装Qt库的系统上是不能使用的.会提示缺少……库文件之类的错误.这就是动态编译的结果. 但是如果我们想编译一个程序,这个程序在发给别人后,他们可以直接打开,而不需要特别地去先安装Qt库,那就需要采用静态编译了. 在Linux下如何静态编译Qt程序呢? 首先需要先安装静态编译的Qt,也就是静态编译Qt程序首先是需要一个静态编译安装的Qt   1.下载源安装程序,如 qt-x11-opensource-src-4.

VS2010 win7 QT4.8.0,实现VS2010编译调试Qt程序,QtCreator静态发布程序

https://www.cnblogs.com/rainbowzc/p/4689009.html 下载源代码,注意一定是源码压缩包如qt-everywhere-opensource-src-4.8.0.zip, 不是Qt发布的已编译的不同版本的标准库如qt-win-opensource-4.8.0-vs2010.exe,这些版本都只是动态编译的,不是我们 所需要的.只有用源码包才能做真正的纯静态编译,如果用Qt官网已编译的标准库.exe文件进行编译,有可能出现各种错误,而且编译后的文件巨大,我当

Mac平台下的Qt程序在Windows下执行编译运行出现的中文乱码问题

Mac平台下的Qt程序在Windows下执行编译运行时,QString::asprintf()部分会出现的中文乱码问题,之前已经使用QStringLiteral宏解决了一个中文乱码问题: 但是此种情形单凭QStringLiteral宏解决不了. 原因: mac下采用MinGW编译,在Windows下可能是MinGW,也可能是MSV2017等VS编译器编译.如果win平台下是MinGW编译,在mac下写好的程序在win平台下运行不会出现乱码: 如果win下是MSV2017编译就会出现中文乱码,需要

QT程序在windows下部署发布

转载:http://www.cnblogs.com/Fan_Fan/archive/2010/05/29/1746860.html QT程序在windows下部署发布 以下包括了部分网上收集的,以及qt帮助里的内容(Deploying an Application on Qt/Windows) 首先,打开windows控制台,然后,找到vs安装目录下的bin里,执行 vcvars32.bat 这个脚本.执行完之后,vs需要的所有环境变量就已经设置好了. 我的环境是QT 4.3.3 + mingw

Linux下同时运行不同版本的qt程序

因项目需要,可能有不同版本的qt程序要运行到同一台机器上,本次实验是qt4.8.5和qt5.3.1开发的程序同时运行在同一台机器上,此机器可以不按照qt的任何版本,当然,两个版本开发的qt与机器的位数必须一样,例如都是32位或者64位. 两个版本的qt的程序我都采用动态编译(静态编译方法请度娘),所以需要把运行程序所需的动态库放到程序可以链接的地方,程序可以链接的动态库路径参见:linux动态库搜索路径.此处直接贴出结论:动态库的搜索路径搜索的先后顺序是: 1.编译目标代码时指定的动态库搜索路径