在Visual Studio 2013上遇到,但它可以与任何版本重现。
我从github克隆了协议缓冲库,在它上面运行了CMake-gui(我将所有内容都保留为默认值,因此它是静态版本),只构建libprotobuf(其他项目由于某种原因失败,cmd.exe错误,可能有事情要做有测试,但libprotobuf构建良好)。
我的项目使用在mapbox矢量tile规范的github上找到的.proto文件生成的标题。
当我链接时,我首先有这个错误
Error 1 error C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators' s:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility
我尝试在其他命令行参数中使用-D_SCL_SECURE_NO_WARNINGS
禁用它,但后来我有其他错误:
Error 1 error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in main.obj S:\eiogit3\misc-projs\mapload\mapload\libprotobufd.lib(common.obj)
这与您的项目和libprotobuf项目如何使用VStudio C(和C ++)运行时库(VCRTLib - check [SO]: How to circumvent Windows Universal CRT headers dependency on vcruntime.h (@CristiFati's answer))不匹配。让我详细说明:
假设有一些C(C ++)代码。该代码的目的是运行。比可以实现:
您可以查看[SO]: LNK2005 Error in CLR Windows Form (@CristiFati's answer)以获取有关如何以可执行格式转换C(C ++)代码的详细信息。 Google还有很多关于静态库和动态库之间差异的文章,何时使用其中一个,可以在[SO]: When to use dynamic vs. static libraries上找到一个例子。
正如您所猜测的那样,CRT或C运行时库(包含使C代码能够运行的底层系统 - 一个例子是内存管理函数:malloc,free)也不例外 - 它相当于Nix的libc.a(静态或存档)与libc.so(动态或共享对象) - 但在VStudio中它有点复杂:
笔记:
现在,VCRTLib部件不像任何其他lib一样包含在项目中(项目属性 - >链接器 - >输入 - >附加依赖项),但由于在编译时需要它们的性质(静态或动态),因此它们的配置来自:[MS.Docs]: /MD, /MT, /LD (Use Run-Time Library) ,有4种可供选择:
显然,包含“Debug”的是在构建Debug配置时,而其他包含Release;关键点是拥有DLL的是使用动态运行时版本,而其他版本是静态版本。
回到你的错误:链接器抱怨main.obj(项目的一部分)有MDd_DynamicDebug(链接动态调试版本),而common.obj(libprotobuf项目的一部分)有MTd_StaticDebug(链接静态调试版本),所以你在同一个可执行文件(或.dll)中链接2个运行时 - 这是不可能的。
为了解决这个问题,你应该确保libprotobuf和你的主项目都具有相同的VCRTLib值。 当然,更改主项目设置以匹配libprotobuf更简单,但建议使用动态运行时版本(在涉及.dll的大型项目中,事情会变得混乱),即使这需要重新编译libprotobuf(好吧,如果更改)该选项会生成错误,使libprotobuf很难构建,并且您的项目将保持这么简单,您可以使用静态VCRTLib)。
注意:不要误解VCRTLib类型(静态/动态)与构建libprotobuf的方式(此时是静态的,但我确信它也可以构建为动态的)。
@ EDIT0:
在上面的注释中添加一些额外的信息,就像一些注释所要求的那样,它可能对其他用户有用。
关于库(包括libprotobuf)有两个方面,它们完全不相关:
所以,有4个完全有效的组合:
对于libprotobuf,每个方面都由布尔cmake选项控制:
可以通过以下任一方式设置2个标志:
-Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF
)因此,上述4种组合是可能的(至少在v3.5中),但是#2。默认情况下禁用(指定-Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_MSVC_STATIC_RUNTIME=ON
将构建将链接到动态VCRTLib的.dll),以避免可能的运行时问题,并启用它需要手动干预。
有关构建说明(通过cmake)的更多详细信息,请检查:[GitHub]: protocolbuffers/protobuf - (master) protobuf/cmake/README.md。
1:只有在库导出符号时才会创建.lib文件,因为它没有意义(链接时不需要,并且会创建.dll,但几乎无法使用)
2:对于较新的VStudio版本(从v2015开始),msvcr(t)部分已被vcruntime替换(或者至少这是入口点,因为它被分成较小的逻辑部分(在开头检查URL))