如何在Yocto构建中使用构建版protoc而非主机版protoc?
在Yocto 2.2(Morty)环境移植gRPC C++示例时,已成功集成protobuf 3.3.0和gRPC 1.4.3,但构建过程中Makefile始终调用主机系统的protoc 3.21.12版本,生成的代码依赖高版本protobuf头文件,出现以下编译错误:
| In file included from helloworld.pb.cc:4:0:
| helloworld.pb.h:10:10: fatal error: google/protobuf/port_def.inc: No such file or directory
| #include <google/protobuf/port_def.inc>
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| compilation terminated.
| : recipe for target 'helloworld.pb.o' failed
| make: *** [helloworld.pb.o] Error 1
| WARNING: exit code 2 from a shell command.
以下是解决方法:
步骤1:修改hello.bb配方,传递Yocto构建工具路径
在配方中添加原生依赖,并通过环境变量传递Yocto构建的protoc和插件路径,确保构建时使用正确版本的工具:
DESCRIPTION = "Working example for grpc" AUTHOR = "" LICENSE = "Apache-2.0" HOMEPAGE = "" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" # 添加原生依赖,获取主机端可用的protoc和grpc插件 DEPENDS = "grpc-native protobuf3-native grpc protobuf3 c-ares zlib openssl" RDEPENDS_${PN} += "libstdc++" SRCREV = "29a2a533c98aa21f05c8f598ef2b47321508d5da" BRANCH = "v1.4.x" SRC_URI = "gitsm://github.com/grpc/grpc.git;protocol=https;name=grpc;branch=${BRANCH}" PR = "r0" S = "${WORKDIR}/git" EXTRA_OECMAKE = "-DRUN_HAVE_STD_REGEX=1 \ -DRUN_HAVE_POSIX_REGEX=0 \ -DRUN_HAVE_STEADY_CLOCK=0 \ -DTHREADS_PTHREAD_ARG=2 \ -DBUILD_DEPS=ON \ -DHAVE_STD_REGEX=ON \ -DRUN_HAVE_STD_REGEX=1 \ " do_compile() { # 导出环境变量,指定Yocto构建的工具路径 export PROTOC="${STAGING_BINDIR_NATIVE}/protoc" export GRPC_CPP_PLUGIN="${STAGING_BINDIR_NATIVE}/grpc_cpp_plugin" export PKG_CONFIG_PATH="${STAGING_LIBDIR}/pkgconfig:${STAGING_DATADIR}/pkgconfig" cd ${S}/examples/cpp/helloworld/ make all } FILES_${PN} += "${bindir}/*" do_install() { install -d ${D}${bindir} install -m 0755 ${S}/examples/cpp/helloworld/greeter_client ${D}${bindir} install -m 0755 ${S}/examples/cpp/helloworld/greeter_server ${D}${bindir} }
步骤2:修改Makefile,使用环境变量指定工具路径
移除硬编码的主机路径和工具检查逻辑,直接使用Yocto传递的环境变量:
HOST_SYSTEM = $(shell uname | cut -f 1 -d_) SYSTEM ?= $(HOST_SYSTEM) CXX = ${CXX} # 使用Yocto提供的标准头文件路径,无需硬编码 CXXFLAGS += -I${STAGING_INCDIR} -pthread -std=c++11 LDFLAGS += -L${STAGING_LIBDIR} `pkg-config --libs grpc++ grpc` \ -Wl,--no-as-needed -lgrpc++_reflection -Wl,--as-needed \ -lprotobuf -lpthread -ldl # 从环境变量获取工具路径,优先使用Yocto传递的值 PROTOC ?= protoc GRPC_CPP_PLUGIN ?= grpc_cpp_plugin PROTOS_PATH = ../../protos vpath %.proto $(PROTOS_PATH) all: greeter_client greeter_server greeter_client: helloworld.pb.o helloworld.grpc.pb.o greeter_client.o $(CXX) $^ $(LDFLAGS) -o $@ greeter_server: helloworld.pb.o helloworld.grpc.pb.o greeter_server.o $(CXX) $^ $(LDFLAGS) -o $@ .PRECIOUS: %.grpc.pb.cc %.grpc.pb.cc: %.proto $(PROTOC) -I $(PROTOS_PATH) --grpc_out=. --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN) $< .PRECIOUS: %.pb.cc %.pb.cc: %.proto $(PROTOC) -I $(PROTOS_PATH) --cpp_out=. $< clean: rm -f *.o *.pb.cc *.pb.h greeter_client greeter_server
关键说明
Yocto构建环境中,STAGING_BINDIR_NATIVE目录存放的是适配构建主机的工具(包括对应版本的protoc和grpc_cpp_plugin),通过将其路径导出为环境变量传递给Makefile,就能强制使用Yocto构建的工具版本,彻底避免与主机系统高版本工具的冲突。
内容的提问来源于stack exchange,提问作者demzys

