Reputation: 73
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
Upvotes: 1
Views: 4726
Reputation: 61590
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.
Upvotes: 3