Windows, VisualStudio, C++, and building libraries

1,082 views
Skip to first unread message

Stéphane Charette

unread,
Nov 25, 2019, 6:38:27 PM11/25/19
to Protocol Buffers
(Windows10, Visual Studio Community 2019, protobufs v3.10.1, gRPC v1.20.0.)

I need to use protocol buffers and gRPC to get some data, and then combine that with other things to write a plugin for an existing Windows application.  So my plugin will be a .dll that is dynamically loaded by the application which I didn't write and cannot control.

For that reason, I wanted gRPC and protocol buffers to be statically linked into my .dll.  This way users will only have a single .dll file they need to manage.  But I'm having a very difficult time figuring out how to properly build protobufs and grpc for Windows so I can link a .lib file into the rest of my code.

I first tried to use vcpkg, like this:

vcpkg.exe install zlib:x64-windows-static
vcpkg.exe install c-ares:x64-windows-static
vcpkg.exe install openssl:x64-windows-static
vcpkg.exe install protobuf[zlib]:x64-windows-static
vcpkg.exe install grpc:x64-windows-static

If I remember correctly, this led to some link-time problems because the libs use /MT, while the application uses/expects /MD.  So then I switched to this:

vcpkg.exe install zlib:x64-windows
vcpkg.exe install c-ares:x64-windows
vcpkg.exe install openssl:x64-windows
vcpkg.exe install protobuf[zlib]:x64-windows
vcpkg.exe install grpc:x64-windows

But I believe this gave me .dll files instead of .lib files.  I even tried this from a post I saw somewhere:

SET ( VCPKG_CRT_LINKAGE dynamic )
SET ( VCPKG_LIBRARY_LINKAGE static )

So now I'm trying to build protobufs and grpc from scratch.  E.g.,

cd protobuf
git submodule update --init --recursive
cd cmake
mkdir build64
cd build64
cmake -DCMAKE_BUILD_TYPE=Debug -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_WITH_ZLIB=OFF ..

I then copied the resulting .lib files into my plugin project, but I'm still seeing several unresolved external symbols, such as this:

1>app.pb.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: void __cdecl google::protobuf::internal::ArenaStringPtr::ClearToEmpty(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const *,class google::protobuf::Arena *)" (__imp_?ClearToEmpty@ArenaStringPtr@internal@protobuf@google@@QEAAXPEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@PEAVArena@34@@Z) referenced in function "public: static void __cdecl google::protobuf::internal::MapTypeHandler<9,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::Clear(struct google::protobuf::internal::ArenaStringPtr *,class google::protobuf::Arena *)" (?Clear@?$MapTypeHandler@$08V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@internal@protobuf@google@@SAXPEAUArenaStringPtr@234@PEAVArena@34@@Z)

So I'm still barking up the wrong tree.

The files I'm attempting to linking against are:

${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/gpr.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/grpc.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/grpc_cronet.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/grpc_unsecure.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/grpc++_cronet.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/grpc++_unsecure.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/grpc++.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/address_sorting.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/cares.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/zlibd.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/libprotobuf-lited.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/libprotobufd.lib
${CMAKE_HOME_DIRECTORY}/3rd-party/Debug/libprotocd.lib

This was my attempt to manually fixing up the .lib against which to link.  Originally, I had tried it like this:

FIND_PACKAGE ( Threads REQUIRED)
FIND_PACKAGE ( ZLIB REQUIRED)
FIND_PACKAGE ( c-ares CONFIG REQUIRED)
FIND_PACKAGE ( OpenSSL REQUIRED)
FIND_PACKAGE ( protobuf CONFIG REQUIRED)
FIND_PACKAGE ( gRPC CONFIG REQUIRED)

SET ( SPLICE_EXTERNAL_DEPS
Threads::Threads
protobuf::libprotoc protobuf::libprotobuf protobuf::libprotobuf-lite
gRPC::gpr gRPC::grpc gRPC::grpc++ gRPC::grpc_cronet
# c-ares::cares_static
c-ares::cares # c-ares::cares_static ? should I be using static?
OpenSSL::SSL OpenSSL::Crypto
ZLIB::ZLIB
)

Another possibly-related question:  gRPC seems to include protocol buffers.  Am I reading that correct?  By building gRPC, am I already building protobufs, and thus shouldn't bother with protobufs directly?

Thanks for any pointers,

Stéphane

Martin Scholz

unread,
Nov 26, 2019, 2:19:44 AM11/26/19
to Protocol Buffers
I assume you included your Debug folder as an additional library folder and added all the libs as dependencies in your Linker options.
Reply all
Reply to author
Forward
0 new messages