Errors when linking to protobuf 3 on MS Visual C
Asked Answered
C

1

5

Encountered on Visual Studio 2013, but it's reproducible with any version.

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).

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

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)

Cocainize answered 31/1, 2016 at 16:49 Comment(3)
So, you built libprotobuf static version (.lib) using CMake, and now you are trying to link it in your VStudio app?Fricassee
Yes, I built it with MSVC 2013, and am now linking it to my project, also using MSVC 2013Cocainize
here is the project fileCocainize
F
14

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:

Let's say there's some C (C++) code. The purpose of that code is to be run. Than can be achieved:

  • 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 run time the other library will need the .dll file

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.

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:

  • Static CRT resides in libcmt.lib

  • Dynamic CRT resides in msvcrt.lib which "points" to msvcr###.dll(2) (msvcr120.dll for VStudio 2013)

Notes:

  • A "d" at the end of the library name (msvcrd.lib), means that it's built with debug symbols (also bigger and slower)

  • 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

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:

  1. Multi-threaded (/MT)

  2. Multi-threaded Debug (/MTd)

  3. Multi-threaded DLL (/MD)

  4. Multi-threaded Debug DLL (/MDd)

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.

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.

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).

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).



Update #0

Adding some additional info on the above note, as some comments requested it, and it might be useful to other users.

There are 2 aspects about a library (including LibProtoBuf), that are totally unrelated:

  1. Library type (the way it is being built): dynamic / static

  2. UCRT type (the way it uses UCRT): again, dynamic / static

So, there are 4 perfectly valid combinations:

  1. Dynamic library using dynamic UCRT

  2. Dynamic library using static UCRT

  3. Static library using dynamic UCRT

  4. Static library using static UCRT

For LibProtoBuf, each of the aspects is controlled by a boolean CMake option:

  1. Library type: protobuf_BUILD_SHARED_LIBS
  2. UCRT type: protobuf_MSVC_STATIC_RUNTIME

The 2 flags can be set by either:

  • CMake-GUI

  • CMake CmdLine (passing them as arguments - e.g.: -Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF)

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.

For more details regarding build instructions (via cmake), check: [GitHub]: protocolbuffers/protobuf - (master) protobuf/cmake/README.md.



Footnotes

  • #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: 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))

Fricassee answered 31/1, 2016 at 19:31 Comment(5)
Does this, by any chance, solve the problem github.com/google/protobuf/tree/master/cmake ?Cocainize
Thank you, it now builds (with the -D_SCL_SECURE_NO_WARNINGS in command line). I already knew the difference between static and dynamic, but I had no idea about that runtime library setting. And actually, the google protobuf doc states that it's advised to use the static version, not the dynamic version: github.com/google/protobuf/tree/master/…Cocainize
Glad to hear it works. I just read the comments on the link you provided. Now regarding your previous question, if it's about the template export at the end, then I don't think it does.Fricassee
Question: Can I build a static library that uses dynamic runtime and the other way around?Denson
Yes. By default the way libprotobuf is built dictates the way VCRTLib is used. Build types are controlled by 2 flags. Here's how i built the static libprotobuf version using dynamic VCRTLib -Dprotobuf_MSVC_STATIC_RUNTIME=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF. I should add this piece of info into the answer.Fricassee

© 2022 - 2024 — McMap. All rights reserved.