【问题标题】:Make error when cross compiling protobuf for ARM:./.libs/libprotoc.so: error: undefined reference to 'descriptor为 ARM:./.libs/libprotoc.so 交叉编译 protobuf 时出错:error: undefined reference to 'descriptor
【发布时间】:2020-12-25 23:49:09
【问题描述】:

为 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

configure没有错误,make有错误:

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

有意思的是,虽然报错了,但是在protobuf/src/.libs下得到了.so等库文件。

【问题讨论】:

    标签: android protocol-buffers cross-compiling


    【解决方案1】:

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

    正如你所说,这“没问题”,因为库是在 src/.libs 中创建的,而且它们似乎工作正常(至少 libprotobuf.so

    使用旧版本的 ndk-r21 (Pkg.Revision = 21.0.6113669) 没有问题 我最近更新到最新的 ndk-r21e (21.4.7075529),我发现这是问题所在...

    PS:aarch64-linux-android 不会发生这种情况 这是一个链接on Qt forum on the topic

    如果有兴趣,请here is my compile script 构建 x86_64 版本以及 Android 32 和 64 位。

    【讨论】:

      【解决方案2】:

      简答

      这可能有点涉及,但它可能很简单:

      • -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 -p1 < path/to/ltmain.sh.patch
      

      长答案

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

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

      • ld
      • ld.bfd
      • ld.gold

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

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

      aarch64-linux-android29 呢?

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

      【讨论】:

        猜你喜欢
        • 2019-10-07
        • 2014-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-13
        • 2012-02-11
        • 1970-01-01
        • 2019-05-21
        相关资源
        最近更新 更多