修复gRPC HelloWorld的BitBake编译错误:缺失grpc_cpp_plugin
问题描述
尝试通过BitBake Recipe编译gRPC helloworld示例(目标在嵌入式设备运行greeter-client/server),执行bitbake grpc-helloworld时触发CMake错误:
导入目标gRPC::grpc_cpp_plugin引用的文件
/home/buildbot/oe-core/build/tmp/work/aarch64-tdx-linux/grpc-helloworld/1.0.0-r0/recipe-sysroot/usr/bin/grpc_cpp_plugin不存在
当前Recipe文件结构:
recipes-customer/ grpc-helloworld_1.0.0.bb grpc-helloworld/ CMakeLists.txt common.cmake greeter_client.cc greeter_server.cc helloworld.proto
CMakeLists.txt与gRPC官方示例基本一致,仅调整了proto文件和common.cmake路径;此前已将common.cmake中查找Protobuf的语句从find_package(Protobuf CONFIG REQUIRED)改为find_package(Protobuf REQUIRED),否则会出现无法找到Protobuf配置文件的错误。
当前BitBake Recipe内容:
SUMMARY = "gRPC Hello World" LICENSE = "CLOSED" DEPENDS += "protobuf grpc" SRC_URI += "file://CMakeLists.txt file://*.cc file://*.h" S = "${WORKDIR}" inherit pkgconfig cmake
原因分析
- grpc_cpp_plugin是主机端工具,而非目标端文件:OpenEmbedded构建体系中,用于编译proto的
grpc_cpp_plugin和protoc属于主机端编译工具,会安装在${STAGING_BINDIR_NATIVE}目录下;但当前CMake默认在目标端的sysroot(recipe-sysroot)中查找该工具,自然找不到。 - Protobuf查找逻辑混淆了主机/目标端:官方示例用
find_package(Protobuf CONFIG REQUIRED)是针对主机端带配置文件的Protobuf,而目标端的Protobuf可能没有提供CMake配置文件;直接改为find_package(Protobuf REQUIRED)会让CMake优先查找目标端的Protobuf,导致编译proto时无法调用主机端的protoc工具。
修复方案
1. 调整BitBake Recipe的依赖与CMake参数
修改grpc-helloworld_1.0.0.bb,添加主机端依赖,并传递CMake参数明确区分主机/目标端工具与库:
SUMMARY = "gRPC Hello World" LICENSE = "CLOSED" # 同时添加目标端运行依赖和主机端编译依赖 DEPENDS += "protobuf grpc protobuf-native grpc-native" # 明确列出所有需要的源文件,避免匹配不到common.cmake和proto SRC_URI += " \ file://CMakeLists.txt \ file://common.cmake \ file://greeter_client.cc \ file://greeter_server.cc \ file://helloworld.proto \ " S = "${WORKDIR}" inherit pkgconfig cmake # 告诉CMake优先找主机端的编译工具,仅从目标sysroot找库和头文件 EXTRA_OECMAKE += " \ -DPROTOBUF_PROTOC_EXECUTABLE=${STAGING_BINDIR_NATIVE}/protoc \ -DgRPC_CPP_PLUGIN_EXECUTABLE=${STAGING_BINDIR_NATIVE}/grpc_cpp_plugin \ -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER \ -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY \ -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY \ "
2. 修正common.cmake的查找逻辑
将common.cmake中Protobuf和gRPC的查找改为主机/目标端分离:
# 查找主机端的Protobuf和gRPC(用于编译proto文件) find_package(Protobuf CONFIG REQUIRED PATHS "${STAGING_DIR_NATIVE}/usr/lib/cmake/Protobuf") find_package(gRPC CONFIG REQUIRED PATHS "${STAGING_DIR_NATIVE}/usr/lib/cmake/gRPC") # 查找目标端的Protobuf和gRPC库(用于链接最终可执行文件) find_package(Protobuf REQUIRED PATHS "${STAGING_DIR_TARGET}/usr/lib/cmake/Protobuf" NO_DEFAULT_PATH) find_package(gRPC REQUIRED PATHS "${STAGING_DIR_TARGET}/usr/lib/cmake/gRPC" NO_DEFAULT_PATH) # 强制指定主机端的工具路径,避免CMake误判 set(PROTOBUF_PROTOC_EXECUTABLE "${STAGING_BINDIR_NATIVE}/protoc") set(gRPC_CPP_PLUGIN_EXECUTABLE "${STAGING_BINDIR_NATIVE}/grpc_cpp_plugin")
3. 验证CMakeLists.txt的proto编译逻辑
确保CMakeLists.txt中生成proto代码的部分调用正确的主机工具,官方示例中的这段逻辑可保留(配合上面的参数即可正常工作):
get_filename_component(hw_proto "helloworld.proto" ABSOLUTE) get_filename_component(hw_proto_path "${hw_proto}" PATH) # Generate the code protobuf_generate_cpp(hw_proto_srcs hw_proto_hdrs "${hw_proto}") grpc_generate_cpp(hw_grpc_srcs hw_grpc_hdrs "${hw_proto}") # Link the executables add_executable(greeter_server greeter_server.cc ${hw_proto_srcs} ${hw_grpc_srcs}) target_link_libraries(greeter_server gRPC::grpc++ gRPC::grpc++_reflection protobuf::libprotobuf) add_executable(greeter_client greeter_client.cc ${hw_proto_srcs} ${hw_grpc_srcs}) target_link_libraries(greeter_client gRPC::grpc++ gRPC::grpc++_reflection protobuf::libprotobuf)
内容的提问来源于stack exchange,提问作者mmnano50
相关产品推荐
相关产品推荐

