交叉编译 ARM:./.libs/libprotoc.so 的 protobuf 时出错:错误:未定义对"描述符"的引用



为ARM 交叉编译protobuf时出错

已编译脚本:

1 #!/bin/sh
2 
3 export PREFIX=$HOME/soft/protobuf_arm/
4 CLANG_TOOLCHAIN=$HOME/soft/arm-29-toolchain-clang
5 export PATH=$CLANG_TOOLCHAIN/bin:$PATH
6 export SYSROOT=$CLANG_TOOLCHAIN/sysroot
7 export CC="armv7a-linux-androideabi29-clang --sysroot $SYSROOT"
8 export CXX="armv7a-linux-androideabi29-clang++ --sysroot $SYSROOT"
9 
10 cd $HOME/github/c++/protobuf
11 make clean
12 ./autogen.sh
13 ./configure --prefix=$PREFIX 
14 --host=armv7a-linux-androideabi29 
15 --with-sysroot="${SYSROOT}" 
16 --enable-shared 
17 --enable-cross-compile 
18 --with-protoc=$HOME/soft/protobuf_linux/protoc 
19 CFLAGS="-march=armv7-a -D__ANDROID_API__=29" 
20 CXXFLAGS="-frtti -fexceptions -march=armv7-a -D__ANDROID_API__=29" 
21 LIBS="-llog -lz -lc++_static"
22 make -j 12
23 make install

配置中没有错误,生成中有错误:

In file included from google/protobuf/compiler/csharp/csharp_source_generator_base.cc:39:
./google/protobuf/compiler/csharp/csharp_source_generator_base.h:62:25: warning: private field 'descriptor_' is not used [-Wunused-private-field]
const FileDescriptor* descriptor_;
^
1 warning generated.
CXXLD    libprotoc.la
clang90++: warning: argument unused during compilation: '-pthread' [-Wunused-command-line-argument]
clang90++: warning: argument unused during compilation: '-pthread' [-Wunused-command-line-argument]
CXXLD    protoc
./.libs/libprotoc.so: error: undefined reference to 'descriptor_table_google_2fprotobuf_2fdescriptor_2eproto'
./.libs/libprotoc.so: error: undefined reference to 'scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto'
clang90++: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [Makefile:3883: protoc] Error 1
make[2]: Leaving directory '/home/sen/github/c++/protobuf/src'
make[1]: *** [Makefile:1866: all-recursive] Error 1
make[1]: Leaving directory '/home/sen/github/c++/protobuf'
make: *** [Makefile:1773: all] Error 2

环境

Linux x 5.6.15-arch1-1
GNU Make 4.3
NDK (Side by side) 21.1.6352462
protobuf v3.13.0

有趣的是,尽管报告了一个错误,但像.so这样的库文件是在protobuf/src/.libs.下获得的

简短回答

这可能有点复杂,但也可以简单到:

  • -fuse-ld=bfd添加到CFLAGS
  • -fuse-ld=bfd添加到CXXFLAGS

如果这样做不能解决问题,那么您可能还需要:

  • ./autogen.sh之后但在./configure之前修补ltmain.sh以允许使用-fuse-ld=bfd(下面的修补程序文件(

修补程序文件(ltmain.sh.patch(:

--- a/ltmain.sh 2015-02-16 04:15:37.000000000 +1100
+++ b/ltmain.sh 2021-05-23 18:18:46.000000000 +1000
@@ -7273,9 +7273,11 @@
# --sysroot=*          for sysroot support
# -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
# -stdlib=*            select c++ std lib with clang
+      # -fuse-ld=*           Linker select flags for GCC
-64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| 
-t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| 
-      -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*)
+      -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| 
+      -fuse-ld=*)
func_quote_for_eval "$arg"
arg=$func_quote_for_eval_result
func_append compile_command " $arg"

Patch命令:

patch -p1 < path/to/ltmain.sh.patch

答案很长

该问题是由于src/.libs/libprotobuf.so中的符号导出较弱,这与src/libprotobuf.map中提供的映射配置相悖。此配置指定所有与模式*google*匹配的符号都应被强导出(因此可用于链接到protoc(,而所有其他符号都应隐藏。

但是,在运行armv7a-linux-androideabi29-clang++时使用的默认链接器(GOLD(中存在一个错误,它忽略了extern "C++"块内的任何映射指令。在NDK中,提供了三个链接器:

  • ld
  • ld.bfd
  • ld.gold

BFD链接器没有相同的问题,因此前进的路径是将armv7a-linux-androideabi29-clang++配置为使用BFD链接程序,这就是-fuse-ld=bfd选项的作用。

不幸的是,这可能并不那么简单,因为protobuf源代码是使用libtool构建的,而最新发布的版本无法识别-fuse-ld参数。因此,如果您的libtool发行版没有将补丁应用到其打包版本,我们需要进行更改以允许它这样做(部分来自开发提交(。要做到这一点,侵入性最小的方法是等待必要的文件(ltmain.sh(作为./autogen.sh命令的一部分复制到源中,然后对其进行修补,以便在处理该文件(作为./configure命令的一个部分(时,更改传播到创建的libtool文件中。

aarch64-linux-android29

当使用aarch64-linux-android29-clang++构建时,默认的链接器已更改为BFD链接器,因此对于像protobuf这样的代码库,这个问题不会发生。使用上面的相同修补程序,您可以使用-fuse-ld=gold复制该问题。

在Linux(debian 4.19.0-16-amd64(上为armv7a-linux-androideabi编译时,我也遇到了这个错误

正如你所说;ok";因为库是在src/.libs中创建的,并且它们似乎工作正常(至少是libprotobuf.so(

我使用旧版本的ndk-r21没有问题(Pkg.Revision=21.0.6113669(我最近更新到了最新的ndk-r21e(21.4.7075529(,在那里我发现了问题。。。

PS:aarch64-linux-android不会发生这种情况这是Qt论坛上关于这个话题的链接。

对于那些感兴趣的人,这里是我的编译脚本,用于构建x86_64版本以及Android 32和64位。

最新更新