jok*_*oon 5 c++ protocol-buffers visual-studio visual-c++ visual-studio-2013
在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)
Cri*_*ati 10
这与你的项目和libprotobuf项目使用VStudio C(和C++)运行时库(VCRTLib - 检查[SO]:如何规避Windows Universal CRT标头依赖于vcruntime.h(@CristiFati的答案))的不匹配.让我详细说明:
假设有一些C代码.该代码的目的是运行.比可以实现:
您可以在CLR Windows窗体中检查[SO]:LNK2005错误(@CristiFati的答案),了解如何以可执行格式转换C代码的详细信息.Google还有很多关于静态库和动态库之间差异的文章,何时使用其中一个,可以在[SO]上找到一个例子:何时使用动态库和静态库.
正如您所猜测的,CRT或C运行时库(包含使C代码能够运行的底层系统- 一个例子是内存管理函数:malloc,free)也不例外 - 它相当于Ux的libc.a(静态或归档)与libc.so(动态或共享对象) - 但在VStudio中它有点复杂:
备注:
现在,VCRTLib部件不像任何其他lib一样包含在项目中(项目属性 - >链接器 - >输入 - >附加依赖项),但由于在编译时需要它们的性质(静态或动态),因此它们配置为:[ MS.Docs]:/ MD,/ MT,/ LD(使用运行时库),其中有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种组合是可能的(至少在v 3.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版本(从2015年开始),msvcr(t)部分已被vcruntime取代(或者至少这是入口点,因为它被分成较小的逻辑部分)