2015-03-13 96 views
1

我目前正在爲使用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

如果你們能幫助我,我將不勝感激!

乾杯

回答

2

顯然,你正在試圖建立一個共享庫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