简单一点理解就是多线程/MT是将程序依赖的部分系统库静态链接进你的dll或者exe,而多线程DLL /MD则是依赖于dll(例如:vcruntime140.dll,msvcp140.dll),所以经常可以看到MD程序发布时需要拷贝一大堆的系统库。具体介绍参考下面两份文章:
VS项目属性中C/C++运行库 、MT /MTd /MD /MDd_ymxwz的专栏-CSDN博客
C Runtime Library 的来历_nodeathphoenix的专栏-CSDN博客
对于MT于MD的了解源于我们的dll库需要给别人调用,但我们的dll又依赖log4cpp-1.1.3,因此有两种选择:
1、将自己的dll,log4cpp.dll,以及log4cpp依赖的所有系统库统一打包拷贝。
那么调用者也可能会依赖相同的系统库,那么可能由于版本不同会导致冲突
2、将我们所依赖的所有开源库编译为MT。
首先编译MD版的log4cpp会报两个错误,向预处理器定义中添加HAVE_SNPRINTF即可成功编译。
将MD改为MT后编译,则会出现许多已导入本地符号的警告和无法解析的外部符号错误:
例如:错误 LNK2001 无法解析的外部符号 __imp___unlink log4cpp
警告 LNK4049 已导入本地定义的符号 ___std_exception_destroy log4cpp
看上去像是依赖库加载的不对,首先忽略特定库OLDNAMES.lib,由于系统库是默认加载,猜测可能是编译器加载问题。
首先通过Dependency Walker导入编译好的MD版log4cpp.dll,查看依赖的系统库:
全局搜索了一下,只要MSVCP140.lib和VCRUNTIME140.lib没有。搜索一番后,发现VCRUNTIME140的静态库名叫libvcruntime.lib,参考:
vc编译去掉vcruntime140.dll依赖_weixin_33785108的博客-CSDN博客
而其余系统库可以通过下面链接搜索到对应lib库:
C 运行时 (CRT) 和 C++ 标准库 .lib 文件 | Microsoft Docs
于是准备手动向链接器-输入-附加依赖项添加libucrt.lib libcmt.lib libvcruntime.lib libcpmt.lib,编译后发现错误:
错误 LNK2038 检测到“RuntimeLibrary”的不匹配项: 值“MT_StaticRelease”不匹配值“MD_DynamicRelease”(AbortAppender.obj 中) log4cpp
看来手动加载所需lib库是失败了。
毫无头绪时看到预处理器定义中有这么几个包含敏感词dll的宏,预感应该是有点问题
将以上四个删除后居然编译通过!
LOG4CPP开头的两个宏是用于dllexport dllimport的,删除后会删除log4cpp的符号,无法外部调用它的接口。需要加上
_USRDLL是表示做一个用户DLL,默认加上
那么问题就出在_DLL,搜索后得知_DLL是用于表示MD的。参考:
那么问题就解决了,不清楚是否是log4cpp最新是使用vs2010,该编译器可能不支持ui设置MD、MT,需要手动设置宏。