简体   繁体   中英

Android NDK: Static compilation with CLang error

I'm currently developing a C/C++ module for an Android application using the NDK and JNI.

I need to compile this C module with CLang and use static linking in order to remove dependencies to libc.

The compilation with static linking to libC works fine with GCC but I can't get it working with CLang. I get the following error:

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'

The example below is on Windows, but the problem is the same on linux.

To demonstrate the problem with a very simple 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");
}

The makefile android.mk is:

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)

and the application.mk:

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

If it can be of any use, setting the -v flag for the LDFLAGS gives me:

"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

If any of you could help me, I would be very grateful !

Cheers

Apparently you are trying to build a shared library libhello.so .

To build a shared library you must pass option -shared to the linker ( ld ). Your link command shows that tyou are not doing so. If you don't, the linker assumes you are trying to build an executable program. And you if are trying to build a C executable, then it must have a main function int main(int argc, char *argv[]) where execution will start. If you don't, then you will get the linkage error you are seeing. hello-jni.c does not contain any main function, because it's supposed to be built as a library, not a program.

So change your LOCAL_LDFLAGS to -shared -static . (Or probably more in line with the organisation of your build, add -shared to the linker flags wherever they are set within include $(BUILD_SHARED_LIBRARY) ). You may suppose that -shared and -static are contradictory options, but they're not. -shared means build a shared library and -static means don't link any shared libraries with whatever is being built .

Futhermore, if you are building a shared library, then you must pass option -fPIC , to generate position-independant object code, when you compile the source files. We can't see any of your compile commands, but you will need -fPIC to be present in the CFLAGS that you pass to the compiler. As far as we can see from your makefile, you are only passing -nostdlib

It is unclear to me why you are passing -nostlib to the compiler. It is a linker option, with no effect on compilation, and we do not see it in your link command, where it would have some effect.

Incidentally, there appears to be a missing space lurking somewhere in the unseen anatomy of your build. In that verbose link command, the monster -L option:

-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

is clearly two joined together:

-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

I would expect this to make the linker try to search in the monster non-existent path instead of two shorter paths, but possibly the concatenation is just a typographical error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM