VStudio C(和 C++)运行时库(VCRTLib 或 UCRT strong> - 检查 [SO]: How to circumvent Windows Universal CRT headers dependency on vcruntime.h (@CristiFati's answer)) 是否被您的项目和 libprotobuf 项目使用。让我详细说明:
假设有一些 C (C++) 代码。该代码的目的是运行。比可以实现的:
- 直接:将该代码包含在 VC 应用程序 类型的项目中 - 这将生成一个 .exe
- 间接:在 VC 库 类型的项目中包含代码 - 这将生成一个 库,该库只有在从另一个 .exe 调用时才能运行 (调用该库)。该库可以是:
-
静态:所有C (C++) 代码都将被编译并存储在一个.lib 文件中。在另一个项目(无论是应用程序还是库)中使用该库时,您将需要该文件 - 在 link 时。请注意,您的 .lib 中所有需要的代码都将“复制”到其他项目中
-
dynamic:您现在将拥有 2 个文件:一个 .dll 文件将包含已编译(和链接)的代码,以及一个 .lib 文件(1) 将包含指向 .dll 文件中代码的“指针”(如果您愿意的话) .在另一个项目中使用该库时,您还需要 .lib 文件在 link 时,但现在它不包含代码,因此不会被复制在另一个库中(另一个库会更小),但在运行时另一个库需要 .dll 文件
您可以查看[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 中它有点复杂:
- 静态 CRT 驻留在 libcmt.lib
- 动态 CRT 驻留在 msvcrt.lib 中,它“指向”msvcr###.dll(2)(msvcr120.dll 用于 VStudio 2013)
注意事项:
现在,UCRT 部分不像任何其他库(Project Properties -> Linker -> Input -> Additional Dependencies)一样包含在项目中,而是因为它们编译时需要自然(静态或动态),它们的配置来自:[MS.Docs]: /MD, /MT, /LD (Use Run-Time Library),其中有 4 种可用选择:
- 多线程 (/MT)
- 多线程调试 (/MTd)
- 多线程 DLL (/MD)
- 多线程调试 DLL (/MDd)
显然,包含“Debug”的那些是在构建时用于Debug配置,而其他的用于Release;关键是有DLL的使用dynamic运行时版本,而其他的使用static版本。
回到你的错误:链接器抱怨 main.obj(你项目的一部分)有 MDd_DynamicDebug(链接到 dynamic debug 版本),而 common.obj(libprotobuf 项目的一部分)有 MTd_StaticDebug(链接到 static debug 版本),因此您链接到同一个可执行文件(或 .dll)中的 2 个运行时 - 这是不可能的.
为了修复它,您应该确保 libprotobuf 和您的主项目具有相同的 UCRT 值。
当然更改更简单您的主要项目设置与 libprotobuf 的设置相匹配,但建议使用动态运行时版本(在涉及 .dll 的较大项目中,事情可能会变得混乱)甚至如果这需要重新编译 libprotobuf(好吧,如果更改该选项会产生错误,使 libprotobuf 很难构建,并且您的项目将保持如此简单,您可以使用静态UCRT)。
注意:不要将 UCRT 类型(静态/动态)与构建 libprotobuf 的方式(此时为静态,但我确信它也可以构建为动态的)。
更新#0
根据一些 cmets 的要求,在上面的注释中添加一些附加信息,它可能对其他用户有用。
关于一个库(包括 libprotobuf)有 2 个方面完全不相关:
-
库类型(构建方式):动态 / 静态
-
UCRT 类型(它使用 UCRT 的方式):再次,动态 / 静态
所以,有 4 种完全有效的组合:
- 使用动态 UCRT 的动态库
- 使用静态 UCRT 的动态库
- 使用动态 UCRT 的静态库
- 使用静态UCRT的静态库
对于libprotobuf,每个方面都由一个布尔cmake选项控制:
- 库类型:protobuf_BUILD_SHARED_LIBS
-
UCRT 类型:protobuf_MSVC_STATIC_RUNTIME
这 2 个标志可以通过以下任一方式设置:
- cmake-gui
-
cmake cmdline(将它们作为参数传递 - 例如:
-Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF)
上述4种组合因此可能(至少在v3.5中),但#2。 默认禁用(指定-Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_MSVC_STATIC_RUNTIME=ON 将构建一个.dll,它将链接到动态 UCRT),以避免可能的运行时问题,并且启用它需要手动干预。
有关构建说明的更多详细信息(通过 cmake),请查看:[GitHub]: protocolbuffers/protobuf - (master) protobuf/cmake/README.md。
脚注