如何解决&#34;对<myfunction>&#34;的未定义引用在NDK构建的静态库中建立NDK构建的静态库?

时间:2015-11-13 22:58:59

标签: macos android-ndk static-libraries linker-errors undefined-reference

我得到了一个&#34;未定义的引用“myfunction&#39;尝试从共享(.so)库中调用静态(.a)库中的函数。 (这是OS X上的NDK问题)。该函数是fft库的一部分,名为&#34; ffts-android&#34; (ffts-android)。我能够用项目生成库就好了。我做的唯一更改是从BUILD_SHARED_LIBRARY到BUILD_STATIC_LIBRARY,以便我可以将它合并到我们在我们的组织Android应用程序中使用的共享库中。

我非常确定我需要的函数ffts_init_1d(size_t,int)存在于静态库中,因为我使用nm实用程序(底部输出)列出了符号中可用的函数表

然后我想我会尝试修改一个NDK的简单示例程序,以防我的Android.mk出现问题。我拿了&#34; module-exports&#34;示例并进行必要的最简单更改并获得相同的错误。在其原始状态下,它构建一个静态库,然后将其链接到一个共享库,就像我试图做的那样。我刚刚在Android.mk中添加了一行,中间的一行,所以它链接到我从ffts-android项目构建的同一个库:

LOCAL_STATIC_LIBRARIES := foo
LOCAL_STATIC_LIBRARIES += libffts-neon
include $(BUILD_SHARED_LIBRARY)

然后修改bar.c,以便它调用我试图调用的相同方法ffts_init_1d(size_t,int):

#include "bar.h"
#include "ffts.h"
#include "foo.h"

int  bar(int  x)
{
    /*return*/foo(x)-1;
    ffts_init_1d(1, 1);
    return 1;
}

最后,我将ffts.h和libffts-neon.a文件移动到module-exports找到的位置,然后构建样本。它产生了我得到的完全相同的错误。

samples/module-exports/jni/bar/bar.c:8: undefined reference to `ffts_init_1d'

module-exports项目和ffts-android项目都是纯粹的c代码,而我们的代码库是c ++,所以我试图调用从c ++的c代码构建的静态库。然而,头文件ffts.h已经有了所需的代码来适应这个标准:

#ifdef __cplusplus
extern "C"
{

以下是nm实用程序的输出。在我看来,列出我试图打电话的功能,为什么它不可用?

./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
. . .

这是我用V = 1(详细输出)调用ndk-build时得到的结果:

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

这是Android.mk文件。稍微修改,如下所述:

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)

1 个答案:

答案 0 :(得分:2)

您必须为要使用的模块定义预构建的静态库 libffts-neon.a 。我们的想法是每个库(静态或共享,预构建或编译)都应该有单独的部分,并分配其单独的 LOCAL_MODULE 名称。所以,你错过了以下结界:

include $(CLEAR_VARS)
LOCAL_MODULE := libffts-neon
LOCAL_SRC_FILES := obj/local/armeabi-v7a/libffts-neon.a
include $(PREBUILT_STATIC_LIBRARY)

可将其放置在 Android.mk 的任意位置,或使用 include 指令并将其保存为单独的文件。

请注意 LOCAL_STATIC_LIBRARIES 是指模块名称,而不是实际文件的名称。所以,以下也可以:

include $(CLEAR_VARS)
LOCAL_MODULE := qqq
LOCAL_SRC_FILES := obj/local/armeabi-v7a/libffts-neon.a
include $(PREBUILT_STATIC_LIBRARY)
…
LOCAL_STATIC_LIBRARIES += qqq
include $(BUILD_SHARED_LIBRARY)

另外请注意,您可以将预建库放在任何位置, ndk-build 会根据需要将其复制到相应的目录中。

官方documentation非常详细,解决了多ABI支持和预建库的其他黑暗角落的问题。