Android NDK:与CLang错误的静态编译

问题描述:

我目前正在为使用NDK和JNI的Android应用程序开发C/C++模块。Android NDK:与CLang错误的静态编译

我需要编译铛这款C模块,并使用静态链接,以消除依赖于libc中。

静态链接编译libc中正常工作与海湾合作委员会,但我不能让它铿锵工作。我得到以下错误:

D:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/../lib\crtbegin_static.o:crtbrand.c:function _start: error: undefined reference to 'main'

下面的例子是在Windows上,但问题是在Linux上一样。

以非常简单的Hello World说明问题:

HELLO-jni.c:

#include <jni.h> 
jstring Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env, jobject thiz) { 
return (*env)->NewStringUTF(env, "hello world"); 
} 

生成文件android.mk是:

LOCAL_PATH := $(call my-dir) 

ifndef NDK_PATH 
    NDK_PATH = C:/dev/android-ndk-r10d/ 
endif 

SDK_VERSION = 21 

include $(CLEAR_VARS) 
LOCAL_MODULE := LibC 
LOCAL_SRC_FILES := $(NDK_PATH)platforms/android-$(SDK_VERSION)/arch- $(TARGET_ARCH)/usr/lib/libc.a 
include $(PREBUILT_STATIC_LIBRARY) 

include $(CLEAR_VARS) 
LOCAL_MODULE := libhello 
LOCAL_SRC_FILES := hello-jni.c 

LOCAL_STATIC_LIBRARIES := LibC 
LOCAL_CFLAGS += -nostdlib 
LOCAL_LDFLAGS := -static -v 

include $(BUILD_SHARED_LIBRARY) 

和应用。 mk:

APP_ABI := armeabi-v7a 
NDK_TOOLCHAIN_VERSION := clang3.5 

如果它可以是任何的使用,设置-v标志的LDFLAGS给我:

"D:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin\ld.exe" --sysroot=D:/tools/android-ndk-r10d/platforms/android-21/arch-arm -X -m armelf_linux_eabi -Bstatic -dynamic-linker /system/bin/linker -o ./obj/local/armeabi-v7a/libhello.so "D:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/../lib\\crtbegin_static.o" -LD:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8 -LD:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib/../lib -LD:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/../lib -LD:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/arm-linux-androideabi/../../lib-LD:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib -LD:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib -soname libhello.so ./obj/local/armeabi-v7a/objs-debug/hello/hello-jni.o D:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/libc.a -lgcc --fix-cortex-a8 --no-undefined -z noexecstack -z relro -z now -lc -lm -lstdc++ -lm --start-group -lgcc -lc --end-group "D:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/../lib\\crtend_so.o" D:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/../lib\crtbegin_static.o:crtbrand.c:function _start: error: undefined reference to 'main' clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation) make.exe: *** [obj/local/armeabi-v7a/libhello.so] Error 1

如果你们能帮助我,我将不胜感激!

干杯

显然,你正在试图建立一个共享库libhello.so

要建立你必须通过选项-shared给连接器(ld)的共享库。 您的链接命令显示,tyou没有这样做。 如果你不这样做,链接器假定你正在尝试构建一个可执行程序。如果你正在尝试构建一个C可执行文件,那么它必须有一个main函数 int main(int argc, char *argv[])其中执行将开始。如果你没有, 那么你会看到你看到的链接错误。 hello-jni.c确实 不包含任何main函数,因为它应该被构建为一个库,而不是一个程序 。

因此改变你的LOCAL_LDFLAGS-shared -static。 (或者可能更符合 您的构建组织,将-shared添加到链接器标志,无论它们在设置在include $(BUILD_SHARED_LIBRARY)内)。您可能认为-shared-static是相互矛盾的选项,但它们不是。 -shared手段构建一个共享库-static意味着不与任何正在修建 链接任何共享库。

Futhermore,如果你正在建设一个共享库,那么你必须通过选项-fPIC, 生成位置独立的目标代码,当你编译的源文件。 我们看不到任何编译命令,但是您需要-fPIC在您传递给编译器的CFLAGS中出现 。至于我们可以从你的makefile 看,你只有经过-nostdlib

为什么要传递-nostlib编译器这是我不清楚。它是一个链接器 选项,对编译没有任何影响,我们在链接命令 中看不到它会对其产生影响。

顺便说一句,看起来有一个缺失的空间潜伏在你的构建看不见的解剖结构 。在这种冗长的链接命令,怪物-L 选项:

-LD:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/arm-linux-androideabi/../../lib-LD:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib 

显然是两个连接在一起的:

-LD:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/arm-linux-androideabi/../../lib 
-LD:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib 

我希望它可以使连接尝试在怪物不存在路径搜索而不是两条较短路径的 ,但可能连接只是一个印刷错误。

+0

嗨, 感谢这非常详细的回应。 我尝试添加-fPIC标志并从LOCAL_CFLAGS中删除-nostdlib。我还向链接器添加了-shared标志,但我仍然得到相同的错误。 对于... lib-LD:/ tools ...串联,这是一个复制粘贴问题,而不是实际的问题。 NDK构建工具链实际上做了什么对我来说还是很不清楚,但是只传递-static会与GCC构建一个.so,并且.so实际上与我的Java程序一起工作。 你是否认为事实上GCC的行为会因为不做而做得比CLang做得更奇怪? – Philippe 2015-03-22 22:35:57