链接到MS Visual C上的protobuf 3时出错 [英] Errors when linking to protobuf 3 on MS Visual C
问题描述
在Visual Studio 2013 上遇到过,但是任何版本都可以复制.
Encountered on Visual Studio 2013, but it's reproducible with any version.
我从github克隆了协议缓冲区库,在其上运行CMake-gui(我将所有内容保留为默认值,因此它是静态版本),仅构建了libprotobuf(其他项目由于某种原因而失败,cmd.exe错误,可能有与测试有关,但libprotobuf构建良好).
I cloned the protocol buffer library from github, ran CMake-gui on it (I left everything to default, so it's the static version), only built libprotobuf (other project failed for some reason, cmd.exe error, might have something to do with tests, but libprotobuf builds fine).
我的项目使用在mapbox矢量图块规范的github上找到的.proto文件生成的标头.
My project uses headers generated with the .proto file found on the mapbox vector tiles spec's github.
链接时,我首先遇到此错误
When I link, I first have this error
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
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
禁用它,但是随后出现其他错误:
I tried disabling it with -D_SCL_SECURE_NO_WARNINGS
in additional command line arguments, but then I have other errors:
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)
推荐答案
这与 VStudio C(和C ++)运行时库( VCRTLib 或 UCRT -检查
It's a mismatch of how the VStudio C (and C++) RunTime Library (VCRTLib or UCRT - check [SO]: How to circumvent Windows Universal CRT headers dependency on vcruntime.h (@CristiFati's answer)) is used by your project and by libprotobuf project. Let me detail:
假设有一些 C ( C ++ )代码.该代码的目的是要运行.比可以实现的:
Let's say there's some C (C++) code. The purpose of that code is to be run. Than can be achieved:
- 直接:将代码包含在 VC Application 类型的项目中-这将生成 .exe
- 间接地:将代码包含在 VC Library 类型的项目中-这将生成一个 library ,该库仅在从另一个 .exe调用时才能运行(调用该库).该库可以是:
- 静态:所有 C ( C ++ )代码将被编译并存储在 .lib 文件中.在 link 时在另一个项目(无论是应用程序还是库)中使用库时,将需要该文件.请注意,您 .lib 中所有所需的代码都将被复制".进入另一个项目
- 动态:您现在将有2个文件:一个 .dll 文件,其中将包含编译(和链接)的代码,以及一个 .lib 文件 (1) ,其中将包含指针" (如果愿意)到 .dll 文件中的代码.在其他项目中使用该库时,您还需要在 link 时使用 .lib 文件,但是现在它不再包含代码,因此不会被复制.在另一个库中(另一个库将较小),但是在运行时,另一个库将需要 .dll 文件
- Directly: including that code in an VC Application type project - which will generate an .exe
- Indirectly: including the code in an VC Library type project - which will generate a library which will only be able to run when called from another .exe (that calls that library). The library can be:
- static: all the C (C++) code will be compiled and stored in a .lib file. You will need that file when using the library in another project (whether it's an application or a library) - at link time. Note that all the needed code from your .lib will be "copied" into the other project
- dynamic: you will have 2 files now: a .dll file which will contain the compiled (and linked) code, and a .lib file(1) which will contain "pointers" (if you will) to the code in the .dll file. When using the library in another project, you will also need the .lib file at link time, but now it won't contain the code so it won't be copied in the other library (the other library will be smaller), but at runtime the other library will need the .dll file
您可以检查 [SO]:CLR Windows窗体中的LNK2005错误(@CristiFati的答案),详细了解如何将 C ( C ++ )代码转换为可执行格式.另外, Google 充斥着有关静态库和动态库之间差异的文章,何时使用一个或另一个库,可以在
You can check [SO]: LNK2005 Error in CLR Windows Form (@CristiFati's answer) for details of how C (C++) code gets to be transformed in executable format. Also Google is full of articles about differences between static and dynamic libraries, when to use one or the other, an example can be found on [SO]: When to use dynamic vs. static libraries.
您猜到了 CRT 或 C RunTime库(其中包含构成 C 的基础系统能够运行的代码-一个示例是内存管理功能: malloc , free )也不例外-它等效于 Nix 的 libc.a (静态或存档)与 libc.so (动态或共享对象)-但是在 VStudio 中,它有点复杂:
As you guessed, the CRT or C RunTime library (that contains the underlying system that makes C code able to run - one example are memory management functions: malloc, free) makes no exception - it's the equivalent of Nix's libc.a (static or archive) vs. libc.so (dynamic or shared object) - but in VStudio it's a little bit more complicated:
- 静态 CRT 驻留在 libcmt.lib 中
- 动态 CRT 位于 msvcrt.lib 中,该文件指向"目录.到 msvcr ###.dll (2) ( msvcr120.dll VStudio 2013 )
- Static CRT resides in libcmt.lib
- Dynamic CRT resides in msvcrt.lib which "points" to msvcr###.dll(2) (msvcr120.dll for VStudio 2013)
注释:
- " d "库名称( msvcr d .lib )的末尾,表示它是使用调试符号编译的.
- C ++ 运行时库处于确切的情况;名称中有一个额外的 p : libc p mt.lib , msvc p rt.lib , msvc p 120.dll
- 有关更多详细信息,请检查
- A "d" at the end of the library name (msvcrd.lib), means that it's compiled with debug symbols
- C++ runtime library is under the exact situation; the names have an extra p: libcpmt.lib, msvcprt.lib, msvcp120.dll
- For more details, check [MS.Docs]: CRT Library Features
UCRT 部分没有像其他任何lib(项目属性->链接器->输入->其他依赖项)一样包含在项目中,但是由于在编译时需要它们的性质(静态或动态),因此可以通过以下方式对其进行配置:
Now, UCRT parts, are not included in the project like any other lib (Project Properties -> Linker -> Input -> Additional Dependencies), but because their nature (static or dynamic) is required at compile time they are configured from: [MS.Docs]: /MD, /MT, /LD (Use Run-Time Library), where there are 4 available choices:
- 多线程(/MT )
- 多线程调试(/MTd )
- 多线程DLL(/MD )
- 多线程调试DLL(/MDd )
很显然,包含"Debug"的代码会是针对 Debug 配置进行构建,而其他针对 Release 进行构建;关键是具有 DLL 的版本正在使用 dynamic 运行时版本,而其他具有 static 版本.
Obviously, the ones that contain "Debug" are when building for Debug configuration while the other ones for Release; the key point is that the ones that have DLL are using the dynamic runtime version, while the other ones the static version.
返回您的错误:链接器抱怨 main.obj (项目的一部分)具有 MDd_DynamicDebug (链接到动态调试版本),而 common.obj (属于 libprotobuf 项目的一部分)具有 MTd_StaticDebug (针对静态调试版本的链接),因此您针对同一可执行文件(或 .dll )中的2个运行时进行链接-这是不可能的
Back to your error: the linker complains that main.obj (part of your project) has MDd_DynamicDebug (linking against the dynamic debug version), while common.obj (part of libprotobuf project) has MTd_StaticDebug (linking against the static debug version), so you link against 2 runtimes in the same executable (or .dll) - which is not possible.
为了修复它,您应该确保 libprotobuf 和您的主项目对 UCRT 具有相同的值.
当然,更改起来更简单您的主要项目设置要与 libprotobuf 的设置相匹配,但建议使用动态运行时版本(在涉及到 .dll 的大型项目中,事情可能会变得混乱)如果这需要重新编译 libprotobuf (好吧,如果更改该选项会产生使 libprotobuf 很难构建的错误,并且您的项目将保持如此简单,则可以使用静态 UCRT ).In order to fix it, you should make sure that both libprotobuf and your main project have the same value for UCRT.
Of course it's simpler to change your main project setting to match libprotobuf's one, but it's recommended to use the dynamic runtime version (things can get messy in larger projects that have .dlls involved) even if this requires to recompile libprotobuf (well, if changing that option generates errors that make libprotobuf very hard to build, and your project is going to stay this simple, you can use the static UCRT).注意:不要将 UCRT 类型(静态/动态)与构建 libprotobuf 的方式(目前是静态的,但我确信它也可以构建为动态的.
Note: Not to mistake UCRT type (static / dynamic) with the way libprotobuf is being built (static at this point, but I'm sure that it can be built as dynamic too).
根据一些评论的要求,在上述注释中添加一些其他信息,这可能对其他用户有用.
Adding some additional info on the above note, as some comments requested it, and it might be useful to other users.
关于库(包括 libprotobuf )有两个方面,它们完全不相关:
There are 2 aspects about a library (including libprotobuf), that are totally unrelated:
- 库类型(构建方式):动态/静态
- UCRT 类型(它使用 UCRT 的方式):再次,动态/静态
- Library type (the way it is being built): dynamic / static
- UCRT type (the way it uses UCRT): again, dynamic / static
因此,有4种完全有效的组合:
So, there are 4 perfectly valid combinations:
- 使用动态 UCRT 的动态库
- 使用静态 UCRT 的动态库 使用动态 UCRT
的 - 静态库 使用静态 UCRT 的
- 静态库
- Dynamic library using dynamic UCRT
- Dynamic library using static UCRT
- Static library using dynamic UCRT
- Static library using static UCRT
对于 libprotobuf ,每个方面均由布尔型 cmake 选项控制:
For libprotobuf, each of the aspects is controlled by a boolean cmake option:
- 库类型: protobuf_BUILD_SHARED_LIBS
- UCRT 类型: protobuf_MSVC_STATIC_RUNTIME
可以通过以下任一方式设置2个标记:
The 2 flags can be set by either:
- cmake-gui
- cmake cmdline (将它们作为参数传递-例如:
-Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF
)
- cmake-gui
- cmake cmdline (passing them as arguments - e.g.:
-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
将生成一个 .dll ,该链接到 dynamic UCRT ),以便避免可能的运行时问题,并启用它需要人工干预.The above 4 combinations are thus possible (at least in v3.5), but #2. is disabled by default (specifying
-Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_MSVC_STATIC_RUNTIME=ON
will build a .dll which will link to the dynamic UCRT), in order to avoid possible runtime problems, and enabling it requires manual intervention.有关构建说明的更多详细信息(通过 cmake ),请检查: [GitHub]:protocolbuffers/protobuf-(主)protobuf/cmake/README.md .
For more details regarding build instructions (via cmake), check: [GitHub]: protocolbuffers/protobuf - (master) protobuf/cmake/README.md.
-
#1 :仅当库导出符号时,才会创建 .lib 文件. ,否则就没有任何意义(在链接时不需要任何操作,并且将创建 .dll ,但几乎无法使用)
#1: The .lib file will only be created if the library exports symbols, as it wouldn't make sense otherwise (nothing needed at link time, and the .dll will be created, but pretty much unusable)
#2 :对于较新的 VStudio 版本(从 v2015 开始), msvcr(t) 部分已由 vcruntime 代替(或者至少是入口点,因为它被分割成较小的逻辑部分(请检查 URL 开头))
#2: For newer VStudio versions (starting with v2015), the msvcr(t) part has been replaced by vcruntime (or at least this is the entrypoint, as it was split in smaller logical pieces (check the URL at the beginning))
这篇关于链接到MS Visual C上的protobuf 3时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!