【问题标题】:Android NDK for x86_64 has no reference for bcopy and index适用于 x86_64 的 Android NDK 没有 bcopy 和 index 的参考
【发布时间】:2015-01-11 23:06:24
【问题描述】:

我正在尝试使用 Android NDK 为 x86_64 架构编译 Lame 声音库。对于对bcopyindex 的未定义引用,我收到以下链接错误:

jni/libmp3lame/encoder.c:471: error: undefined reference to 'bcopy'
jni/libmp3lame/encoder.c:476: error: undefined reference to 'bcopy'
jni/libmp3lame/id3tag.c:1125: error: undefined reference to 'index'
jni/libmp3lame/newmdct.c:1036: error: undefined reference to 'bcopy'
jni/libmp3lame/util.c:685: error: undefined reference to 'bcopy'

代码成功编译为 x86 和 arm 架构。

所以我稍微挖掘了一下 NDK 的库,并注意到 bcopyindex 都在 x86 和 arm 平台的 libc.so 中导出,但不适用于 x86_64(见下文 objdump 输出)。

$> objdump -d android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/libc.so | grep bcopy -A 6
0000b000 <bcopy>:
    b000:   e52db004 push   {fp}    ; (str fp, [sp, #-4]!)
    b004:   e28db000 add    fp, sp, #0
    b008:   e28bd000 add    sp, fp, #0
    b00c:   e8bd0800 ldmfd  sp!, {fp}
    b010:   e12fff1e bx lr


$> objdump -d android-ndk-r10d/platforms/android-21/arch-x86/usr/lib/libc.so | grep -A 6 bcopy
00009fb0 <bcopy>:
    9fb0:   55                   push   %ebp
    9fb1:   89 e5                   mov    %esp,%ebp
    9fb3:   5d                   pop    %ebp
    9fb4:   c3                   ret


$>  objdump -d android-ndk-r10d/platforms/android-21/arch-x86_64/usr/lib/libc.so | grep -A 6 bcopy
<<NOTHING FOUND>>

有什么想法吗?下面是我的 Android.mk 和 Application.mk 文件。

Application.mk:

APP_ABI:=x86_64
APP_PLATFORM := android-21

Android.mk:

LOCAL_PATH := $(call my-dir)

APP_PLATFORM := android-21

include $(CLEAR_VARS)

LOCAL_MODULE        := libmp3lame

LOCAL_SRC_FILES     := \
...<list-of-.c-files>...

LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

【问题讨论】:

  • Android x86_64 很有趣。直到您提出问题(导致从 Android NDK 团队找到Developers, start your 64-bit engines),我才知道 Android 提供了它。
  • 我什至无法为目标 Android x86_64 配置 Autoconf。你是如何设法建造它的?这是 Stack Overflow 上的一个相关问题:Autoconf triplet for Android x86_64?。另请参阅 Autoconf 邮件列表中的问题:How To Configure for Android? (Redux for x86_64)
  • 我没有做任何配置,除了使用包管理器安装 android-21。顺便说一句,我似乎需要在 x86_64 中进行本机编译的唯一原因是让它在我的模拟器中运行。我使用的是 64 位 mac,而 x86[-32] 速度非常慢。事实上,我什至无法启动模拟器。有没有其他方法可以让模拟器在 x86 arch 上运行?附言我对 Android 非常陌生 - 现在正好 2 周 :)
  • 点击编辑来编辑你的问题。添加您的Application.mkAndroid.mk

标签: android android-ndk


【解决方案1】:

您可以在Application.mk (docs) 中使用一行代码彻底解决此问题:

APP_CFLAGS += -DSTDC_HEADERS

为什么?

LAME 假设某些符号无需通过#include 显式包含即可访问。然而,它也提供了一种方式来表明明确包含是必要的。

在我的发行版中,有冲突的文件(machine.hid3tag.c)是这样的:

#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#endif

这是您需要通过设置STDC_HEADERS 预处理器变量来触发的块。上面带有-D 标志的行告诉C 编译器创建它。

【讨论】:

  • 非常感谢您提供快速简便的解决方案!同样效果我在 Android.mk 中使用了 LOCAL_CFLAGS += -DSTDC_HEADERS
  • 感谢您拯救我的周末!
【解决方案2】:

为了解决bcopy 问题,我在machine.hid3tag.h 中添加了#include &lt;strings.h&gt;

为了修复index 问题,我最终在machine.hid3tag.c 中注释掉了#define strchar index 行:

#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#else
# ifndef HAVE_STRCHR
//#  define strchr index
#  define strrchr rindex
# endif
char   *strchr(), *strrchr();
# ifndef HAVE_MEMCPY
#  define memcpy(d, s, n) bcopy ((s), (d), (n))
#  define memmove(d, s, n) bcopy ((s), (d), (n))
# endif
#endif

【讨论】:

  • 您可能真正想要的是将-DSTDC_HEADERS 添加到您的 cflags 中。
【解决方案3】:

我在strings.h 有它,但它是#define

$ cd /opt/android-ndk-r10d
$ grep -R bcopy * | grep x86_64
platforms/android-21/arch-x86_64/usr/include/linux/mroute6.h:#define IF_COPY(f, t) bcopy(f, t, sizeof(*(f)))
platforms/android-21/arch-x86_64/usr/include/strings.h:#define bcopy(b1, b2, len) \
platforms/android-21/arch-x86_64/usr/include/strings.h:#define bcopy(b1, b2, len) (void)(__builtin_memmove((b2), (b1), (len)))

这是它的样子(取自标题strings.h):

#if defined(__BIONIC_FORTIFY)
#  define bcopy(b1, b2, len) \
    (void)(__builtin___memmove_chk((b2), (b1), (len), __bos0(b2)))
#  define bzero(b, len) \
    (void)(__builtin___memset_chk((b), '\0', (len), __bos0(b)))
#else
# define bcopy(b1, b2, len) (void)(__builtin_memmove((b2), (b1), (len)))
# define bzero(b, len) (void)(__builtin_memset((b), '\0', (len)))
#endif

早期版本的 Android 运行时将其作为库调用提供。例如,请参阅How to understand this code snippet in the bcopy.c of bionic?

这听起来像是另一种标题在android-21 发生变化的情况。也就是说,它是一个过去在库中作为导出呈现的函数,但现在在标题中可用。例如,请参阅Cannot load library: reloc_library[1285]: cannot locate 'rand'

我认为解决方法是使用 android-21 重新编译 Lame 声音库,而不是工具链的早期版本。

此外,还有各种config.h 有以下评论:

/* HAS_BCOPY:
 *  This symbol is defined if the bcopy() routine is available to
 *  copy blocks of memory.
 */
#define HAS_BCOPY   /**/

您可以在例如android-ndk-r10d/prebuilt/darwin-x86_64/lib/perl5/5.16.2/darwin-2level/CORE/config.h 找到config.h

如果不是很明显(比如你已经在android-21arch 下编译是正确的),那么我们需要看看你的项目是如何设置的(比如Application.mk 看起来像什么,或者是什么--sysroot 正在使用中)。

【讨论】:

  • 我在Application.mk中添加了APP_PLATFORM := android-21(文件中唯一的另一行是APP_ABI:=x86_64来选择架构。但结果是一样的。设置APP_PLATFORM是否有相同的添加 SYSROOT 的效果?否则,我该如何设置 SYSROOT - 它是某种命令行选项吗?
  • 既然 jww 发现它确实在标题中可用,你能检查一下encoder.c(和提到的其他文件)是否确实包含strings.h(应该重定向到__builtin_memmove) ? (如果不包括在内,您会收到诸如“内置函数'bcopy'的不兼容隐式声明”之类的构建警告)。
  • @mstorsjo - 我能够使用交叉编译脚本从命令行构建。该项目有一些问题,但它们与 Autoconf 和 libtool 有关。解决 Autoconf 问题后,我得到了 libmp3lame.so
  • @mstorsjo - 你可能正在做某事。 $CC $CFLAGS -I./include -M libmp3lame/encoder.c | grep strings.h(当为 Android x86_64 交叉编译环境设置时)没有产生任何命中。也许他应该在lame.h 中包含&lt;strings.h&gt; 并在__ANDROID__ 上保护它。将它放在 lame.h__ANDROID__ 保护确实会产生 grep 命中。
  • 可能。请注意,lame 的配置脚本会检查 strings.h 标头(并相应地在 config.h 中设置 HAVE_STRINGS_H),但实际库中似乎没有任何内容包含 strings.h 并且没有任何内容使用 HAVE_STRINGS_H 任何东西(至少不在我在这里检查的源版本中)。所以像#ifdef HAVE_STRINGS_H #include &lt;strings.h&gt; #endif 这样的东西在正确的地方可能会更好。 (不过,我不确定lame.h 是否合适,因为公共标头不应该使用config.h。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-07
  • 2014-03-30
  • 2013-01-16
  • 1970-01-01
  • 2011-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多