Linker errors when consuming gRPC C++ on release configuration

Viewed 2058

I've compiled the grpc library from source code using the official instructions on github. I've used cmake to invoke MSVC v142 build tools(Visual Studio 2019), and generated two build configurations one for Release, and one for Debug. From the build artifacts, and from the include files of the gRPC library, I've created a C++ NuGet package. That NuGet package uses both the Release as well as the Debug build artifacts(and of course places them in a designated folder for each configuration type). I've created some "Hello World" app that consumes the gRPC library on Windows, via the NuGet package that I've built. (This is just a standard example the can be found on gRPC official examples, nothing new was added). On Debug build of the "Hello World" app, everything works just fine - compilation, linking, execution and debugging, but when I switch to compile the project on Release, I have 7 linker errors related to missing functions definitions.

The instruction of how to build gRPC from source code was taken from here: "https://github.com/grpc/grpc/blob/master/BUILDING.md". I've searched where were those functions implemented back on the gRPC source code, and found that it's in the 'grpc++' project, which being compiled to be 'grpc++.lib'. I've checked that this file does get included in my nuget package, in the correct configuration(Release) and architecture(x64). I've checked that I did took the correct configuration and architecture as an input for the NuGet package, and even tried to link against those binaries directly without using the NuGet package that I've created.

This is the linker output when building with Release, x64:

1>------ Build started: Project: HelloGrpc++NuGet, Configuration: Release x64 ------
1>HelloWorldServer.cc
1>HelloWorldServer.obj : error LNK2001: unresolved external symbol "class std::shared_ptr<class grpc::ServerCredentials> __cdecl grpc::InsecureServerCredentials(void)" (?InsecureServerCredentials@grpc@@YA?AV?$shared_ptr@VServerCredentials@grpc@@@std@@XZ)
1>HelloWorldServer.obj : error LNK2001: unresolved external symbol "public: __cdecl grpc::ServerBuilder::ServerBuilder(void)" (??0ServerBuilder@grpc@@QEAA@XZ)
1>HelloWorldServer.obj : error LNK2001: unresolved external symbol "public: virtual __cdecl grpc::ServerBuilder::~ServerBuilder(void)" (??1ServerBuilder@grpc@@UEAA@XZ)
1>HelloWorldServer.obj : error LNK2001: unresolved external symbol "public: virtual class std::unique_ptr<class grpc::Server,struct std::default_delete<class grpc::Server> > __cdecl grpc::ServerBuilder::BuildAndStart(void)" (?BuildAndStart@ServerBuilder@grpc@@UEAA?AV?$unique_ptr@VServer@grpc@@U?$default_delete@VServer@grpc@@@std@@@std@@XZ)
1>HelloWorldServer.obj : error LNK2001: unresolved external symbol "public: class grpc::ServerBuilder & __cdecl grpc::ServerBuilder::RegisterService(class grpc::Service *)" (?RegisterService@ServerBuilder@grpc@@QEAAAEAV12@PEAVService@2@@Z)
1>HelloWorldServer.obj : error LNK2001: unresolved external symbol "public: class grpc::ServerBuilder & __cdecl grpc::ServerBuilder::AddListeningPort(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::shared_ptr<class grpc::ServerCredentials>,int *)" (?AddListeningPort@ServerBuilder@grpc@@QEAAAEAV12@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$shared_ptr@VServerCredentials@grpc@@@4@PEAH@Z)
1>D:\Users\abiton\Desktop\grpcsandbox\HelloGrpc++NuGet\bin\x64\Release\HelloGrpc++NuGet.exe : fatal error LNK1120: 6 unresolved externals
1>Done building project "HelloGrpc++NuGet.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

This is the executable code that uses the gRPC C++ library(Standard example, nothing was added by me):

#include <iostream>
#include <memory>
#include <string>
#include <grpc++/grpc++.h>
#include "src/server/helloworld.grpc.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;

class GreeterServiceImpl final : public helloworld::Greeter::Service
{
    Status SayHello(ServerContext* context, const HelloRequest* request, HelloReply* response) override
    {
        response->set_message("Hello from GRPC Server !");
        return Status::OK;
    }
};

int main(int argc, char** argv)
{
    std::string server_address("0.0.0.0:50051");
    GreeterServiceImpl service;

    ServerBuilder builder;
    // Listen on the given address without any authentication mechanism.
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
    // Register "service" as the instance through which we'll communicate with
    // clients. In this case it corresponds to an *synchronous* service.
    builder.RegisterService(&service);
    // Finally assemble the server.
    std::unique_ptr<Server> server(builder.BuildAndStart());
    std::cout << "Server listening on " << server_address << std::endl;

    // Wait for the server to shutdown. Note that some other thread must be
    // responsible for shutting down the server for this call to ever return.
    server->Wait();
    return 0;
}

These are relative paths for additional include directories added to my sample project:

grpc\include
grpc\third_party\protobuf\src

These are relative paths for the build artifacts:

grpc\.build\Release
grpc\.build\third_party\cares\cares\lib\Release
grpc\.build\third_party\protobuf\Release
grpc\.build\third_party\zlib\Release

And these are the linker inputs:

address_sorting.lib
cares.lib
gpr.lib
grpc.lib
grpc++.lib
grpc++_unsecure.lib
libprotobuf.lib
zlib.lib

Any help will be appreciated !

0 Answers
Related