VS2005、VS2008中如何屏蔽讨厌的MSVCR*.dll的引用

Posted on 2012-03-20 20:21  无忧consume  阅读(351)  评论(0编辑  收藏  举报

  在用VS2005或VS2008的VC++开发产品时,经常遇到的一个问题就是最终编译出的可执行文件Exe、Dll、Ocx之类会需要MSVCR90.dll、MSVCR80.dll等C库函数运行时Dll的支持,在一些较老的系统,如XP 中,经常不具备这些新版本的运行库,导致产品发布推广成为一个严重的问题。在2008年我还在开发一款网游时,也遇到了同样的问题,虽然想尽了办法,也无法屏蔽对这个动态库的引用,不得已,客户端就又返回老的VS2003环境中进行编译开发,最终发布。

  可以使用VS2008自带的安装程序制作工具,生成一个最简的VC++ Redistributable 包,体积也很小,但是一样需要一个额外的安装包来支持你的最终产品,很多产品经理是不太喜欢这种形式的,所以此问题还是很纠结。

 解决这个问题,方法就是修改一下编译选项,将/MD选项改为/MT选项,最终的可执行文件就不会包含对那些VC运行时DLL的引用了,可以很方便的发布和部署。首先让我们来看下这个云遮雾罩的编译开关究竟是干什么的?MSDN中的描述如下:

  /MD

   使应用程序使用运行时库的多线程并特定于 DLL 的版本。定义 _MT 和 _DLL,并使编译器将库名 MSVCRT.lib 放入 .obj 文件中。

  用此选项编译的应用程序静态链接到 MSVCRT.lib。该库提供允许链接器解析外部引用的代码层。实际工作代码包含在 MSVCR90.DLL, 中,该库必须在运行时对于与 MSVCRT.lib 链接的应用程序可用。

  当 /MD 与 _STATIC_CPPLIB 预处理器定义 (/D_STATIC_CPPLIB) 一起使用时,您的应用程序将与静态多线程标准 C++ 库 (libcpmt.lib) 而非动态版本 (msvcprt.lib) 链接,但仍通过 msvcrt.lib 动态链接到主 CRT。

  请注意,不支持 _STATIC_CPPLIB 预处理器定义和 /clr 或 /clr:pure 编译器选项的组合。有关 /clr 选项的限制的更多信息,请参见 /clr 限制。

  /MDd

  定义 _DEBUG、_MT 和 _DLL,并使应用程序使用运行时库的调试多线程并特定于 DLL 的版本。它还使编译器将库名 MSVCRTD.lib 放入 .obj 文件中。

  /MT

使应用程序使用运行时库的多线程静态版本。定义 _MT 并使编译器将库名 LIBCMT.lib 放入 .obj 文件中,以便链接器使用 LIBCMT.lib 解析外部符号。

  /MTd

  定义 _DEBUG 和 _MT。此选项还使编译器将库名 LIBCMTD.lib 放入 .obj 文件中,以便链接器使用 LIBCMTD.lib 解析外部符号。

  /LD

   创建 DLL。

  将 /DLL 选项传递到链接器。链接器查找 DllMain 函数,但并不需要该函数。如果没有编写 DllMain 函数,链接器将插入返回 TRUE 的 DllMain 函数。

  链接 DLL 启动代码。

  如果命令行上未指定导出 (.exp) 文件,则创建导入库 (.lib);将导入库链接到调用您的 DLL 的应用程序。

  将 /Fe(命名 EXE 文件) 解释为命名 DLL 而不是 .exe 文件;默认程序名成为基名称.dll 而不是基名称.exe。

  除非显式指定 /MD,否则将暗指 /MT。

  /LDd

  创建调试 DLL。定义 _MT 和 _DEBUG。

  这个开关就是控制这个C运行时库的引用方式的。

  当然到这里先别忙着去修改你的项目属性中关于这个开关的选项,因为当你的项目也是一个LIB 时,如果使用了/MT或/MTd选项时,最终的静态LIB中就会出现LIBCMT.lib中的大量符号,导致在别的项目引用你的这个静态LIB时出现重复定义符号而无法链接的错误,怎么解决呢?其实继续看MSDN中的帮助就可以得到答案:

  传递给链接器的给定调用的所有模块都必须使用相同的运行时库编译器选项(/MD、/MT、/LD)进行编译。

  所有的模块保持一致就完了,但是静态的LIB貌似还是无法引用,问题依旧怎么办呢?

  那就是在引用了你自己的使用/MT或/MTd选项编译生成的静态LIB的项目中,不但指定对应的/MT或/MTd选项,而且需要忽略LIBCMT.lib库即可。

  总算是有一个非常完满的解决方法了,《VC++语言参考手册》描述过这个问题了。

  “项目”->“属性”->“配置属性”->“C / C++”->“代码生成”->“运行库”->改成“多线程(/MT)”。默认是 “多线程DLL(/MD)”。或者cmd里面cl.exe /MT ...效果也是一样的。

Copyright © 2024 无忧consume
Powered by .NET 8.0 on Kubernetes