7

I am trying to compile Lame sound library with Android NDK for x86_64 architecture. I am getting the below link error for undefined references to bcopy and index:

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'

The code successfully compiles for x86 and arm architectures.

So I digged through NDK's libs a bit and noticed that bcopy and index are both exported in libc.so for x86 and arm platforms but not for x86_64 (see below objdump outputs).

$> 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>>

Any thoughts? Below are my Android.mk and Application.mk files.

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)
Reza
  • 109
  • 1
  • 6
  • Android x86_64 is interesting. I did not know Android offered it until your question (which caused to to find [Developers, start your 64-bit engines](https://plus.google.com/+AndroidDevelopers/posts/XG1WmNDMe8H) from the Android NDK team). – jww Jan 11 '15 at 23:43
  • I could not even get Autoconf to configure for the target Android x86_64. How did you manage to build it? This is a related question on Stack Overflow: [Autoconf triplet for Android x86_64?](http://stackoverflow.com/q/27894831/608639). Also see the question on the Autoconf mailing list: [How To Configure for Android? (Redux for x86_64)](https://lists.gnu.org/archive/html/autoconf/2015-01/index.html). – jww Jan 12 '15 at 03:22
  • I didn't do any configuration of any sorts, other than installing android-21 using the package manager. BTW, the only reason that I _seem_ to need to get a native compilation in x86_64 is to have it run in my emulator. I am using a 64-bit mac and a x86[-32] is insanely slow. In fact I couldn't even get the emulator to boot up. Is there any other way to get the emulator run with x86 arch? P.S. I am very very new to Android - exactly 2 weeks now :) – Reza Jan 12 '15 at 03:39
  • Click *Edit* to edit your question. Add your `Application.mk` and `Android.mk`. – jww Jan 12 '15 at 03:48

3 Answers3

13

You can fix this cleanly with a single line in Application.mk (docs):

APP_CFLAGS += -DSTDC_HEADERS

Why?

LAME assumes that certain symbols will be accessible without explicit inclusion via #include. However, it also provides a way to signal that explicit inclusion is necessary.

In my distribution, the conflictive files (machine.h and id3tag.c) have something like this:

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

This is the block you need to trigger, by setting the STDC_HEADERS preprocessor variable. The line above, with the -D flag, tells the C compiler to create it.

salezica
  • 74,081
  • 25
  • 105
  • 166
3

To fix bcopy issue, I added #include <strings.h> in machine.h and id3tag.h.

To fix index issue, I ended up commenting out the #define strchar index line in both machine.h and id3tag.c:

#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
Reza
  • 109
  • 1
  • 6
0

I have it in strings.h, but its a #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)))

Here's what it looks like (taken from the header 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

Earlier version of the Android runtime provided it as a library call. See, for example, How to understand this code snippet in the bcopy.c of bionic?.

It sounds like its another case of the headers changing at android-21. That is, its a function that used to present as an export in a library, but now available in a headers. See, for example, Cannot load library: reloc_library[1285]: cannot locate 'rand'.

I think the workaround is to re-compile the Lame sound library with android-21, and not an earlier version of the toolchain.

Also, there are various config.h that have the following comment:

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

You can find the config.h at, for example, android-ndk-r10d/prebuilt/darwin-x86_64/lib/perl5/5.16.2/darwin-2level/CORE/config.h.

If its not something obvious (like you already are compiling under android-21 and arch is correct), then we'll need to see how your project is setup (like what does Application.mk look like, or what --sysroot is being used).

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • I added `APP_PLATFORM := android-21` in my `Application.mk` (the only other line in the file is `APP_ABI:=x86_64` to pick the architecture. But the result is the same.Does setting `APP_PLATFORM` have the same effect as adding SYSROOT? Otherwise, how can I set SYSROOT - is it a commandline option of some sort? – Reza Jan 12 '15 at 03:31
  • 1
    Since jww found that it indeed is available in the headers, can you check whether `encoder.c` (and the other files mentioned) actually do include `strings.h` (which should redirect it to `__builtin_memmove`)? (If it isn't included, you'd get build warnings like "incompatible implicit declaration of built-in function 'bcopy'"). – mstorsjo Jan 12 '15 at 06:54
  • @mstorsjo - I was able to build from the command line using a cross-compile script. The project had some issues, but they were related to Autoconf and `libtool`. Once I got through the Autoconf issues, I got a `libmp3lame.so` out of it. – jww Jan 12 '15 at 07:40
  • @mstorsjo - You might be onto something. `$CC $CFLAGS -I./include -M libmp3lame/encoder.c | grep strings.h` (when set for the Android x86_64 cross-compile environment) did not produce any hits. Maybe he should include `` in `lame.h` and guard it on `__ANDROID__`. Placing it in `lame.h` with the `__ANDROID__` guard does produce `grep` hits. – jww Jan 12 '15 at 07:54
  • Possibly. Do note that lame's configure script checks for the `strings.h` header (and sets `HAVE_STRINGS_H` in `config.h` accordingly), but nothing in the actual library seems to include `strings.h` and nothing uses `HAVE_STRINGS_H` for anything either (at least not in the version of the source that I'm checking here). So something like `#ifdef HAVE_STRINGS_H #include #endif` in the right place would probably be even better. (I'm not sure if `lame.h` is the right place for that, though, since the public header shouldn't use `config.h`.) – mstorsjo Jan 12 '15 at 07:58
  • I included `` which solved the missing references for `bcopy`. But the same issue for `index` still stands. – Reza Jan 13 '15 at 04:22