If you’re building a micro-service architecture you’ll most likely end up using some sort of networking lib to manage the communication between services.
This is where gRPC fits in. I’m not gonna go through why it’s a good choice, most of the time, but let’s just say that interoperability between different programming languages becomes a lot better.
There’s also a decent amount of documentation and a relatively large community where you can find help.
But when it comes to cross-compiling binaries that use gRPC for a different platform/architecture than your host (ARM in this case), it’s not exactly straightforward to do.
Though, to be fair, there’s a cross-compile section in the building gRPC doc that leads to an example which is definitely very helpful. In fact, this post is just an adaptation of that example with a few improvements:
We’ll use the arm-linux-gnueabihf cross-compiler toolchain instead of the one used in the example
We’ll use Docker to build our binaries so that we can run this from any environment
Prerequisites
Make sure you have the following tools installed on your machine:
// src/hello_server.cc
#include<iostream>#include<memory>#include<string>#include<grpcpp/grpcpp.h>#include<grpcpp/health_check_service_interface.h>#include<grpcpp/ext/proto_server_reflection_plugin.h>#include"hello.grpc.pb.h"classGreeterServicefinal:publichello::Greeter::Service{grpc::StatusSayHello(grpc::ServerContext*ctx,consthello::Req*req,hello::Rep*rep)override{std::stringprefix("Hello, ");std::stringsuffix("!");rep->set_message(prefix+req->name()+suffix);returngrpc::Status::OK;}};voidRunServer(){std::stringaddr("0.0.0.0:50051");GreeterServiceservice;grpc::EnableDefaultHealthCheckService(true);grpc::reflection::InitProtoReflectionServerBuilderPlugin();grpc::ServerBuilderbuilder;// No auth
builder.AddListeningPort(addr,grpc::InsecureServerCredentials());// Register the service
builder.RegisterService(&service);// Start server
std::unique_ptr<grpc::Server>server(builder.BuildAndStart());std::cout<<"Server running at "<<addr<<std::endl;// Wait for shutdown
server->Wait();}intmain(intargc,char**argv){RunServer();return0;}
There’s not much going on above, just a simple server that will respond with Hello, <name>! to client requests and gRPC facilitating the communication between the two.
We’ll also need a cmake config that can find the necessary dependencies and generate the sources from our proto file:
This may take some time as we’re compiling gRPC 2 times (once to build the protoc and gRPC programs for the host and once more to cross-compile gRPC for our target architecture). But subsequent runs will be fast if there’s no changes to the dockerfile.
After the build command is done, you should have two binaries in the ./bin folder. Copy both to your ARM host and run them. You should see something similar to:
That’s it. I hope you found this helpful. You can also find all the source code and some tests at rolandjitsu/grpc-cross-arm.
If you find this post helpful, please consider sponsoring.