NDK cross bulid gRPC (android-ndk-r27c)

ChatGPT,DeepSeek,etc    all of them  give us fake code. 

1, Cross build on Ubuntu. Prerequeist.

High version cmake is required.

cmake --version
cmake version 3.30.3
wget -q -O cmake-linux.sh https://github.com/Kitware/CMake/releases/download/v3.30.3/cmake-3.30.3-linux-x86_64.sh
sh cmake-linux.sh -- --skip-license --prefix=$MY_INSTALL_DIR
rm cmake-linux.sh

Install ubuntu depedencies.

sudo apt install -y build-essential autoconf libtool pkg-config

2, Recusive clone gRPC code.(version: 1.60.0)

git clone --recurse-submodules -b v1.60.0 --depth 1 --shallow-submodules https://github.com/grpc/grpc

3, setup NDK toolchain.

Download android-ndk-r27c-xxx.zip and unzip to /opt/ndk/android-ndk-r27c/  folder.

4, Update CMakeLists.txt according to clang compiler.

Append:

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--undefined-version")

in CMakeLists.txt.

find anddrod and log:

if(_gRPC_PLATFORM_ANDROID)
  target_link_libraries(gpr
    android
    #log
    /opt/ndk/android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/29/liblog.so
  )
endif()

5,cross compile

cd grpc
mkdir -p cmake/build
pushd cmake/build
ThinkPad-X280:~/ndk_demos/grpc/cmake/build_android$ cat ../build.sh 
cmake -DCMAKE_TOOLCHAIN_FILE=/opt/ndk/android-ndk-r27c/build/cmake/android.toolchain.cmake \
      -DANDROID_ABI=arm64-v8a \
      -DANDROID_PLATFORM=android-29 \
      -DCMAKE_INSTALL_PREFIX=../android_install \
      -DgRPC_BUILD_TESTS=OFF \
      -DBUILD_SHARED_LIBS=ON \
      -DANDROID_STL=c++_shared \
      -DgRPC_ZLIB_PROVIDER=package \
      -DCMAKE_BUILD_TYPE=Release \
      -DCMAKE_SYSTEM_NAME=Android \
      -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON \
      -DCMAKE_ANDROID_NDK=/opt/ndk/android-ndk-r27c/ \
      -DgRPC_INSTALL=ON \
      -DCMAKE_LDFLAGS=-Wl,--undefined-version \
      -B . \
      -S ../..

$bash ../build.sh
$make -j `nproc`

6, Install

make install

To find all output in uplayer folder:android_install

7, Helloworld android native test example.

proto file:

syntax = "proto3";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

CMakeLists.txt

~/ndk_demos/grpc_ndk_demo/build$ cat ../CMakeLists.txt 
cmake_minimum_required(VERSION 3.10)
project(gRPCDemo)

set(CMAKE_CXX_STANDARD 17)

set(PROTOBUF_INCLUDE_DIR /opt/android_install/include)
set(PROTOBUF_LIBRARYIES /opt/android_install/lib)

include_directories(${PROTOBUF_INCLUDE_DIR})
include_directories(src/broker_feeder)
include_directories(src/)

list(APPEND CMAKE_PREFIX_PATH "/opt/anroid_install/lib/cmake/grpc/")
list(APPEND CMAKE_PREFIX_PATH "./")
list(APPEND CMAKE_FIND_ROOT_PATH "/opt/android_install/")

set(GRPC_DIR  "/opt/anroid_install/")
set(Protobuf_DIR "/opt/android_install/")
include_directories(${GRPC_DIR}/include)
include_directories(${Protobuf_DIR}/include)

link_directories(${GRPC_DIR}/lib)
link_directories(${Protobuf_DIR}/lib)

message("############${CMAKE_MODULE_PATH}##############")

set(Protobuf_PREFIX_PATH
    "/opt/android_install/include"
    "/opt/android_install/lib"
    "/opt/android_install/bin" )
list(APPEND CMAKE_PREFIX_PATH "${Protobuf_PREFIX_PATH}")

find_package(absl CONFIG REQUIRED)
find_package(Protobuf CONFIG REQUIRED)
find_package(gRPC CONFIG  REQUIRED)


add_executable(greeter_server greeter_server.cc helloworld.pb.cc helloworld.grpc.pb.cc)
add_executable(greeter_client greeter_client.cc helloworld.pb.cc helloworld.grpc.pb.cc)

target_link_libraries(greeter_server gRPC::grpc++ ${Protobuf_LIBRARIES} )
target_link_libraries(greeter_client gRPC::grpc++ ${Protobuf_LIBRARIES})

example server and client code:

aric@aric-ThinkPad-X280:~/ndk_demos/grpc_ndk_demo/build$ cat ../greeter_server.cc 
#include <iostream>
#include <memory>
#include <string>

#include <grpcpp/grpcpp.h>
#include "helloworld.grpc.pb.h"

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

class GreeterServiceImpl final : public Greeter::Service {
  Status SayHello(ServerContext* context, const HelloRequest* request,
                  HelloReply* reply) override {
    std::string prefix("Hello ");
    reply->set_message(prefix + request->name());
    return Status::OK;
  }
};

void RunServer() {
  std::string server_address("0.0.0.0:50051");
  GreeterServiceImpl service;

  ServerBuilder builder;
  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
  builder.RegisterService(&service);
  std::unique_ptr<Server> server(builder.BuildAndStart());
  std::cout << "Server listening on " << server_address << std::endl;

  server->Wait();
}

int main(int argc, char** argv) {
  RunServer();
  return 0;
}

aric@aric-ThinkPad-X280:~/ndk_demos/grpc_ndk_demo/build$ cat ../greeter_client.cc 
#include <iostream>
#include <memory>
#include <string>

#include <grpcpp/grpcpp.h>
#include "helloworld.grpc.pb.h"

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloRequest;
using helloworld::HelloReply;

class GreeterClient {
 public:
  GreeterClient(std::shared_ptr<Channel> channel)
      : stub_(Greeter::NewStub(channel)) {}

  std::string SayHello(const std::string& user) {
    HelloRequest request;
    request.set_name(user);

    HelloReply reply;
    ClientContext context;

    Status status = stub_->SayHello(&context, request, &reply);

    if (status.ok()) {
      return reply.message();
    } else {
      std::cerr << "RPC failed: " << status.error_message() << std::endl;
      return "RPC failed";
    }
  }

 private:
  std::unique_ptr<Greeter::Stub> stub_;
};

int main(int argc, char** argv) {
  GreeterClient greeter(grpc::CreateChannel(
      "localhost:50051", grpc::InsecureChannelCredentials()));
  std::string user("World");
  std::string reply = greeter.SayHello(user);
  std::cout << "Greeter received: " << reply << std::endl;

  return 0;
}

Protoc to generate code: (Build same version protobuf on x86 and install, genereate code with x86 protoc version, then cross compile with NDK arm64.)

 protoc -I . --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto
 protoc -I . --cpp_out=. helloworld.proto

Build:

~/ndk_demos/grpc_ndk_demo/build$ cat ../build.sh 
cmake -DCMAKE_TOOLCHAIN_FILE=/opt/ndk/android-ndk-r27c/build/cmake/android.toolchain.cmake       
-DANDROID_ABI=arm64-v8a       
-DANDROID_PLATFORM=android-29       
-DCMAKE_INSTALL_PREFIX=../android_install     
-DANDROID_STL=c++_static       
-DgRPC_ZLIB_PROVIDER=package      
 -DCMAKE_BUILD_TYPE=Release       
-DCMAKE_SYSTEM_NAME=Android         
-DCMAKE_ANDROID_NDK=/opt/ndk/android-ndk-r27c/        
-B .  -S ../ 

make -j `nproc`

ric@aric-ThinkPad-X280:~/ndk_demos/grpc_ndk_demo/build$ bash ../build.sh 
##########################
-- Configuring done
-- Generating done
-- Build files have been written to: /home/aric/ndk_demos/grpc_ndk_demo/build
aric@aric-ThinkPad-X280:~/ndk_demos/grpc_ndk_demo/build$ make -j 8
Consolidate compiler generated dependencies of target greeter_server
Consolidate compiler generated dependencies of target greeter_client
[ 50%] Built target greeter_server
[100%] Built target greeter_client

#### build completed successfully  ####

aric@aric-ThinkPad-X280:~/ndk_demos/grpc_ndk_demo/build$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  greeter_client  greeter_server  Makefile
aric@aric-ThinkPad-X280:~/ndk_demos/grpc_ndk_demo/build$ file greeter_server 
greeter_server: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /system/bin/linker64, BuildID[sha1]=9954d9cd6250028e8697ef41837d036da3a2fd2d, with debug_info, not stripped

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值