NDK編譯native程序(二)構建原生組件

接上一篇NDK編譯native程序(一),ANT使用的build.xml指定了使用ndk-build來構建native so。

<exec executable="/opt/android-ndk-r15c/ndk-build" dir="${basedir}/main/jni" >
	<arg value="V=1" />
	<arg value="APP_BUILD_SCRIPT=Android_android-ndk-r15c.mk" />
	<arg value="NDK_APPLICATION_MK=Application_android-ndk-r15c.mk" />
</exec>

Android NDK的構建系統是基於GNU make的,由多個Makefile片段構成的。爲了簡便,開發人員只要關心這些Makefile片段中的Android.mk和Application.mk即可。
從Android ndkr4起,引入了一個新的、小巧的shell腳本ndk-build,其本質就是對GNU Make的封裝,目的是調用正確的NDK編譯腳本來簡化源碼編譯。ndk-build腳本位於NDK根目錄,進入你的工程根目錄或子目錄之後,在命令行下調用即可。當然對於ndk-build而言,Android.mk和Application.mk的文件名可以另行指定,如上所示。

Android.mk

是Android NDK的構建系統的必備組件,一般出現在jni子目錄中。Android.mk就是一個GNU Make文件,編寫Android.mk是爲了向編譯系統描述你的源碼,會被編譯系統解析一次或多次。應該儘量精簡裏面定義的變量,同時可以認爲所有的變量在這裏都已經被定義。


LOCAL_PATH := $(call my-dir)
Android.mk文件必須以變量LOCAL_PATH的定義起始。這個變量用來定位開發樹中的源文件的位置。一般使用了編譯環境中的宏my-dir,它可以返回當前目錄(包含Android.mk文件的目錄)的路徑。

include $(CLEAR_VARS)
變量CLEAR_VARS也是編譯環境提供的,指向一個特別的GNU Make文件,這個Make文件會幫你清除一些LOCAL_XXX變量(如LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES等),但不會清除LOCAL_PATH。這是因爲所有的編譯控制文件會被GNU Make環境解析爲全局變量。

LOCAL_MODULE := hello-jni
變量LOCAL_MODULE必須被定義,用以區分你在Android.mk文件中定義的每一個模塊。這個名字必須是唯一的而且不能夠含有空格。注意編譯系統會爲生成的文件自動添加正確的前綴和後綴。也就是說,一個名爲foo的模塊會生成libfoo.so。
注意:如果你命名你的模塊爲libfoo,編譯環境不會再添加一個lib前綴,而且也可會生成libfoo.so。這是爲了支持源自於AOSP的Android.mk文件,你也許會用到這些。

LOCAL_CFLAGS := -g
可選,編譯C和C++源文件時的編譯器flags。這個可以用來指定額外的宏定義和編譯選項。

LOCAL_CPPFLAGS := -std=c++11 -pthread -frtti -fexceptions -fvisibility=hidden -ffunction-sections -fdata-sections
可選,編譯C++文件時編譯器flags,在編譯器命令行中,他們出現在LOCAL_CFLAGS之後。

LOCAL_LDFLAGS :=                                                                                     \
    -L../../../modules/$(LOCAL_PLATFORM)/lib/$(LD_LIB_FOLDER)           \
    ${NULL}

傳遞給鏈接器一個一些額外的參數,比如想傳遞額外的庫和庫路徑給ld,或者傳遞給ld linker的一些鏈接參數,-On,-EL{B}(大小端字節序),那麼就要加到這個上面。

LOCAL_LDLIBS := -lc -lprotobuf-lite
編譯你的模塊時需要的額外鏈接flags列表。傳遞指定的以-l爲前綴的系統庫。

LOCAL_SRC_FILES := hello-jni.c
LOCAL_SRC_FILES變量必須包含將要編譯到模塊中的C和/或C++源文件的列表。注意,你不許要在這裏列出頭文件,編譯環境會自動幫你處理這些依賴,只需要列出被編譯器直接編譯的源文件即可。
注意,C++源文件的默認擴展名是.cpp。你也可以通過定義變量LOCAL_CPP_EXTENSION來指定一個不同的擴展名。不要忘記.(.cxx是可以的,但是cxx不行)。

$(info TARGET_ARCH_ABI:$(TARGET_ARCH_ABI))
TARGET_ARCH_ABI變量是解析Android.mk時,目標CPU+ABI的名稱。如armeabi-v7a。

include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY變量是由編譯環境提供,指向一個GNU Make腳本文件,負責收集自上一個include $(CLEAR_VARS)
在sample目錄下有更多更復雜的帶有註釋的Android.mk文件的例子供你參考。

LOCAL_PROGUARD_ENABLED := disabled
表示是否要混淆,混淆就是防止別人破解你的代碼,disabld是不需要使用代碼混淆的工具進行代碼混淆。默認爲full,如果是user或userdebug則取值full,爲full表示即將該工程代碼全部混淆。

LOCAL_ARM_MODE := arm
默認情況下,以thumb模式生成ARM目標二進制,每一個指令都是16比特寬。如果你想強制生成arm(32比特指令)模式下的模塊,你可以定義這個變量爲arm。

Application.mk

是Android NDK的構建系統的可選組件,也出現在jni目錄中。目的是描述應用程序需要哪些模塊,定義了所有模塊的通用變量。

APP_PLATFORM := android-23
必選,定義使用的ndk庫函數版本號。

APP_ABI := armeabi-v7a x86_64 arm64-v8a
必選,編譯哪些cpu架構的so

APP_STL := c++_shared
可選,如何連接c++標準庫

APP_CPPFLAGS := -std=c++11
指定CPPFLAGS屬性

NDK_TOOLCHAIN_VERSION := clang
設置toolchain的方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章