如何为 Android NDK 更新 GNU 链接器?

How do you update the GNU linker for an Android NDK?

我正在使用 NDK r12b 开发原生 Android 项目。这个 NDK(从那以后它看起来像所有其他的一样)附带了一个预构建的 GNU 链接器版本 2.25。我们最近试图提取我们项目的许多子模块,这些子模块引入了一个看起来是由 this bug in ld.

引起的构建错误

构建错误输出:

/opt/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: internal error in do_relocate_sections, at /usr/local/google/buildbot/src/android/gcc/toolchain/build/../binutils/binutils-2.25/gold/reloc.cc:953
collect2: error: ld returned 1 exit status

我想我会尝试更新链接器,但没有找到预构建的二进制文件。所以我陷入了试图自己编译 ld/binutils 的困境。要么我的 Google 技能让我失望,要么执行此操作的文档真的很少见,要么假定用户有很多我没有的介绍性知识。

当使用 target=arm-linux 构建 binutils 2.29.1 时,我的应用程序构建错误,结果如下:

/opt/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: unrecognised emulation mode: armelf_linux_eabi
Supported emulations: armelf_linux armelf armelfb armelfb_linux
collect2: error: ld returned 1 exit status

作为参考,我们当前版本的 ld 的 -V 输出是:

me@linux-vm:/opt/android-ndk-r12b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/arm-linux-androideabi/bin$ ./ld-2.25 -V
GNU gold (binutils-2.25-0666073 2.25.51.20141117) 1.11
Supported targets:
   elf64-littleaarch64
   elf64-bigaarch64
   elf32-littleaarch64
   elf32-bigaarch64
   elf64-tradlittlemips
   elf32-tradlittlemips-nacl
   elf64-tradbigmips
   elf32-tradlittlemips-nacl
   elf32-tradlittlemips
   elf32-tradlittlemips-nacl
   elf32-tradbigmips
   elf32-tradlittlemips-nacl
   elf32-tilegx-be
   elf64-tilegx-be
   elf32-tilegx-le
   elf64-tilegx-le
   elf32-bigarm
   elf32-bigarm-nacl
   elf32-littlearm
   elf32-littlearm-nacl
   elf64-powerpcle
   elf64-powerpc
   elf32-powerpcle
   elf32-powerpc
   elf64-sparc
   elf32-sparc
   elf32-x86-64
   elf32-x86-64-freebsd
   elf32-x86-64-nacl
   elf64-x86-64
   elf64-x86-64-freebsd
   elf64-x86-64-nacl
   elf32-i386
   elf32-i386-freebsd
   elf32-i386-nacl
  Supported emulations:
   aarch64_elf64_le_vec
   aarch64_elf64_be_vec
   aarch64_elf32_le_vec
   aarch64_elf32_be_vec
   elf64-tradlittlemips
   elf32-tradlittlemips-nacl
   elf64-tradbigmips
   elf32-tradlittlemips-nacl
   elf32-tradlittlemips
   elf32-tradlittlemips-nacl
   elf32-tradbigmips
   elf32-tradlittlemips-nacl
   elf32tilegx_be
   elf64tilegx_be
   elf32tilegx
   elf64tilegx
   armelfb
   armelfb_nacl
   armelf
   armelf_nacl
   elf64lppc
   elf64ppc
   elf32lppc
   elf32ppc
   elf64_sparc
   elf32_sparc
   elf32_x86_64
   elf32_x86_64_nacl
   elf_x86_64
   elf_x86_64_nacl
   elf_i386
   elf_i386_nacl

显然我遗漏了一些重要的配置参数。我还尝试使用较旧的 (r8e) Android NDK 的 build/tools/build-gcc.sh 脚本来构建整个编译器工具链,但使用较新的 binutils 版本。这导致了未知的构建错误:

me@linux-vm:/opt/android-ndk-r8e/build/tools$ ./build-gcc.sh --gmp-version=5.0.5 --mpfr-version=3.1.1 --mpc-version=1.0.1 --binutils-version=2.26 
$(pwd)/src $(pwd) arm-linux-androideabi-4.7
To follow build in another terminal, please use: tail -F /tmp/ndk-me/build/toolchain/config.log
Using C compiler: gcc -m32
Using C++ compiler: g++ -m32
Sysroot  : Copying: /opt/android-ndk-r8e/platforms/android-9/arch-arm --> /tmp/ndk-me/build/toolchain/prefix/sysroot
Configure: arm-linux-androideabi-4.7 toolchain build
Building : arm-linux-androideabi-4.7 toolchain [this can take a long time].
Error while building toolchain. See /tmp/ndk-me/build/toolchain/config.log

config.log 的最后条目:

ar cru libintl.a bindtextdom.o dcgettext.o dgettext.o gettext.o finddomain.o loadmsgcat.o localealias.o textdomain.o l10nflist.o explodename.o dcigettext.o dcngettext.o dngettext.o ngettext.o plural.o plural-exp.o localcharset.o relocatable.o localename.o log.o osdep.o intl-compat.o
ranlib libintl.a
make[1]: Leaving directory `/tmp/ndk-me/build/toolchain/libbfd-binutils-2.26/intl'

在这一点上,我只是在转动我的轮胎,并试图通过配置参数和源包版本的不同组合来暴力破解成功。它看起来就像为 armelf_linux_eabi 添加仿真支持一样简单,但正如我所说,我没有找到任何说明如何执行此操作的文档或指南。肯定有某个 GNU 向导可以为我指明一条更好的道路吗?感谢您的帮助!

我会先尝试 --enable-targets=all。这是一个有点大的锤子,但也许它可以帮助您避免弄清楚您需要的确切目标三胞胎(我的猜测是 arm-unknown-linux-eabi)。