在Yocto 2.2上为armv5e编译gRPC 1.6.8遇格式错误求助
问题背景
正尝试在Yocto 2.2环境下为armv5e架构编译gRPC 1.6.8,编译static_c和shared_c目标时构建成功,但编译static_cxx和shared_cxx目标时触发链接错误。
使用的gRPC配方
inherit autotools-brokensep pkgconfig DEPENDS = "\ protobuf3 \ protobuf3-native \ zlib \ openssl \ c-ares \ " SRC_URI = "gitsm://github.com/grpc/grpc.git;branch=v1.6.x" SRCREV = "4735689cc5af6c56eeae5c9ab10fa538552dc08e" DEPENDS_append_class-target = " gtest grpc-native " DEPENDS_append_class-nativesdk = " grpc-native" SRC_URI_append_class-target = " file://0001-CMakeLists.txt-Fix-grpc_cpp_plugin-path-during-cross.patch" PR = "r0" S = "${WORKDIR}/git" # Fix static library generation AR += "rcs" OUTDIR = "${S}/libs/opt/" CXXFLAGS_append_class-native = " --with-protoc=protoc,--host=x86_64-linux,CC="${CC}",CXX="${CC}",HOST_CC="gcc-6",HOST_CXX="gcc-6",RANLIB="${CC}",LD="${CC}",LDXX="${CC}"" do_configure () { } do_compile () { make clean export LD="${CC}" export GRPC_CROSS_COMPILE=true export HAS_PKG_CONFIG=false make prefix=${exec_prefix} static_cxx shared_cxx # make shared_cxx static_cxx } do_install () { oe_runmake prefix=${D}${exec_prefix} install-headers_c oe_libinstall -C ${OUTDIR} -so libgpr ${D}${libdir} oe_libinstall -C ${OUTDIR} -so libgrpc ${D}${libdir} oe_libinstall -C ${OUTDIR} -so libgrpc_cronet ${D}${libdir} oe_libinstall -C ${OUTDIR} -so libgrpc_unsecure ${D}${libdir} oe_libinstall -C ${OUTDIR} -so libgrpc++ ${D}${libdir} oe_libinstall -C ${OUTDIR} -so libgrpc++_cronet ${D}${libdir} oe_libinstall -C ${OUTDIR} -so libgrpc++_unsecure ${D}${libdir} install -d ${D}${libdir}/pkgconfig install -m 0644 ${OUTDIR}/pkgconfig/*.pc ${D}${libdir}/pkgconfig/ } INSANE_SKIP_${PN} = "already-stripped rpaths"
错误信息
/usr/bin/ld: /home/src/build/tmp/work/armv5e-linux-gnueabi/grpc/1.6.8-r0/git/objs/opt/src/compiler/cpp_plugin.o: Relocations in generic ELF (EM: 40)
/home//src/build/tmp/work/armv5e-linux-gnueabi/grpc/1.6.8-r0/git/objs/opt/src/compiler/cpp_plugin.o: error adding symbols: File in wrong format
collect2: error: ld returned 1 exit status
Makefile:15002: recipe for target '/home/src/build/tmp/work/armv5e-linux-gnueabi/grpc/1.6.8-r0/git/bins/opt/grpc_cpp_plugin' failed
make: *** [/home/src/build/tmp/work/armv5e-polatis-gnueabi/grpc/1.6.8-r0/git/bins/opt/grpc_cpp_plugin] Error 1
问题原因
报错核心是交叉编译时混淆了宿主工具与目标架构库的编译逻辑:grpc_cpp_plugin是需要在开发机(x86)上运行的工具,但static_cxx/shared_cxx目标会连带编译该插件,导致用ARM编译器生成的插件目标文件,被主机的ld尝试链接,出现架构格式不兼容。
解决步骤
拆分编译目标,跳过宿主工具编译
修改do_compile函数,只编译目标架构的C++库,不触发宿主插件的构建:do_compile () { make clean export GRPC_CROSS_COMPILE=true export HAS_PKG_CONFIG=false # 直接指定目标架构的库编译目标,避免触发宿主工具构建 make prefix=${exec_prefix} grpc++_static grpc++_shared grpc_static grpc_shared }移除错误的环境变量设置
删除export LD="${CC}",这个设置会强制用ARM的链接器处理宿主工具,加剧架构不兼容问题。明确区分宿主与目标编译变量(可选)
如果仍有构建问题,在make时明确指定宿主工具链的编译变量,确保宿主工具用主机编译器:do_compile () { make clean export GRPC_CROSS_COMPILE=true export HAS_PKG_CONFIG=false make prefix=${exec_prefix} \ CC="${CC}" CXX="${CXX}" LD="${LD}" \ HOST_CC="gcc" HOST_CXX="g++" HOST_LD="ld" \ grpc++_static grpc++_shared grpc_static grpc_shared }依赖native版本的插件
配方中已引入grpc-native依赖,宿主端需要的grpc_cpp_plugin直接由该依赖提供,无需在目标架构编译流程中生成。
内容的提问来源于stack exchange,提问作者demzys

