I'm getting an "undefined reference to 'myfunction' trying to call a function in a static (.a) library from a shared (.so) library. (This is an NDK question on OS X). The function is part of the fft library called "ffts-android" (ffts-android). I'm able to generate libraries with the project just fine. The only change I made is from BUILD_SHARED_LIBRARY to BUILD_STATIC_LIBRARY so that I can incorporate it into the shared library we use in our org's Android app.
I'm pretty sure the function I need, ffts_init_1d(size_t, int), exists as it ought in the static library because I used the nm utility (output at bottom) to list what functions are available in the symbol table.
Then I thought I'd try to modify one of NDK's simple example programs in case my Android.mk is the problem. I took the "module-exports" sample and made the simplest changes necessary and get the same error. In its original state it builds a static library and then links it into a shared library, just as I'm trying to do. I just added to Android.mk a single line, the middle one below, so that it links to the very same library I built from the ffts-android project:
LOCAL_STATIC_LIBRARIES := foo
LOCAL_STATIC_LIBRARIES += libffts-neon
include $(BUILD_SHARED_LIBRARY)
then modified bar.c so that it would call the same method, ffts_init_1d(size_t, int) that I'm trying to call:
#include "bar.h"
#include "ffts.h"
#include "foo.h"
int bar(int x)
{
/*return*/foo(x)-1;
ffts_init_1d(1, 1);
return 1;
}
and finally, I moved the ffts.h and the libffts-neon.a files to where they would be found by module-exports and then built the sample. It generates the exact same error I am getting.
samples/module-exports/jni/bar/bar.c:8: undefined reference to `ffts_init_1d'
Both the module-exports project and ffts-android project are purely c code, whereas our codebase is c++, so I'm attempting to call a static library built from c code from c++. The header file, ffts.h, however already has the needed code to adapt to this, the standard:
#ifdef __cplusplus
extern "C"
{
Below is the output from the nm utility. It seems to me to list the function I'm trying to call, so why is it unavailable?
./nm -g libffts-neon.a
ffts.o:
U _GLOBAL_OFFSET_TABLE_
U __aeabi_uidiv
U __aeabi_uidivmod
U __aeabi_unwind_cpp_pr0
U __aeabi_unwind_cpp_pr1
U __android_log_print
U __errno
U cos
U exit
00000000 T ffts_execute
00000000 T ffts_free
00000000 T ffts_free_1d
U ffts_generate_func_code
00000000 T ffts_init_1d
U ffts_init_is
U ffts_init_offsets
U firstpass_16_b
U firstpass_16_f
U firstpass_2
U firstpass_4_b
U firstpass_4_f
U firstpass_8_b
U firstpass_8_f
U free
U malloc
U mprotect
U munmap
U perror
U sin
U valloc
ffts_real.o:
U __aeabi_unwind_cpp_pr0
U __aeabi_unwind_cpp_pr1
U cos
00000000 T ffts_execute_1d_real
00000000 T ffts_execute_1d_real_inv
U ffts_free
00000000 T ffts_free_1d_real
U ffts_init_1d
00000000 T ffts_init_1d_real
U free
U malloc
U sin
U valloc
. . .
Here is what I get when I invoke ndk-build with V=1 (verbose output):
MacBook-Pro:module-exports myuser$ ndk-build V=1
rm -f ./libs/arm64-v8a/lib*.so ./libs/armeabi/lib*.so ./libs/armeabi-v7a/lib*.so ./libs/armeabi-v7a-hard/lib*.so ./libs/mips/lib*.so ./libs/mips64/lib*.so ./libs/x86/lib*.so ./libs/x86_64/lib*.so
rm -f ./libs/arm64-v8a/gdbserver ./libs/armeabi/gdbserver ./libs/armeabi-v7a/gdbserver ./libs/armeabi-v7a-hard/gdbserver ./libs/mips/gdbserver ./libs/mips64/gdbserver ./libs/x86/gdbserver ./libs/x86_64/gdbserver
rm -f ./libs/arm64-v8a/gdb.setup ./libs/armeabi/gdb.setup ./libs/armeabi-v7a/gdb.setup ./libs/armeabi-v7a-hard/gdb.setup ./libs/mips/gdb.setup ./libs/mips64/gdb.setup ./libs/x86/gdb.setup ./libs/x86_64/gdb.setup
[armeabi-v7a] SharedLibrary : libbar.so
/Users/myuser/Documents/NDKDev/android-ndk-r10e/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-g++ -Wl,-soname,libbar.so -shared --sysroot=/Users/myuser/Documents/NDKDev/android-ndk-r10e/platforms/android-3/arch-arm ./obj/local/armeabi-v7a/objs/bar/bar/bar.o ./obj/local/armeabi-v7a/libfoo.a -lgcc -no-canonical-prefixes -march=armv7-a -Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -mthumb -L/Users/myuser/Documents/NDKDev/android-ndk-r10e/platforms/android-3/arch-arm/usr/lib -llog -lc -lm -o ./obj/local/armeabi-v7a/libbar.so
jni/bar/bar.c:8: error: undefined reference to 'ffts_init_1d'
collect2: error: ld returned 1 exit status
make: *** [obj/local/armeabi-v7a/libbar.so] Error 1
Here's the Android.mk file. Modified slightly, as described:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_CFLAGS := -DFOO=2
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/foo
LOCAL_EXPORT_CFLAGS := -DFOO=1
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar/bar.c
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/bar
LOCAL_STATIC_LIBRARIES := libffts-neon
LOCAL_STATIC_LIBRARIES += foo
include $(BUILD_SHARED_LIBRARY)