Date: 2014-03-14
Title: Compile Android Native Binary And Library Published: true
Type: post
Tags: Andoird, Develope
在Android平台上,通過NDK可以編譯NativeC程序,生成原生的NativeCode。從生成的代碼的使用方式來看,主要有三種形式:Native Executable Binary, Shared Dynamic Library, 以及Static Link Library。接下來將分別介紹這三種類型的二進制文件的用途和生成時的MakeFile的設置。
1. Static Link Library
1.1 用途
顧名思義,就是靜態鏈接庫的意思。靜態庫編譯生成后是以*.a的文件形式存在;主要用於生成其他鏈接庫或可執行程序;在生成時靜態鏈接庫的代碼會被鏈接到目標程序中去,因此,目標程序在使用工程中無需在使用靜態鏈接庫。同時由於靜態鏈接庫的部分或全部代碼被連接到目標程序中,從而使得目標程序體積變大;使用了同一靜態鏈接庫的不同程序均已經連接了各自所需的目標代碼,程序間不會共享代碼。
在使用時,會用到聲明了靜態鏈接庫中函數的頭文件。
1.2 生成方式
使用NDK再帶的ndk-build生成時,要求代碼需放在./jni/目錄下;同時在jni下創建Android.mk文件;根據需要創建Application.mk。
一個典型的用於生成靜態鏈接庫的Android.mk內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mystaticLibrary
LOCAL_SRC_FILES := mystaticLibrary.cpp
LOCAL_INCLUDES := $(LOCAL_PATH)/jni
include $(BUILD_STATIC_LIBRARY)
由於生產的是靜態庫,所以還需要一個Application.mk的文件:
APP_MODULES := mystaticLibrary
#APP_PLATFORM := android-8
其中聲明應用平台的這一行是可選項。
之后在當前目錄使用$(NDK_PATH)/ndk-build命令,正常情況即可生成相應的模塊,一般位於./libs/armeabi/目錄下.
2. Shared Dynamic Library
2.1 用途
動態鏈接庫,通常不會在編譯時將庫中代碼直接連接到目標程序中。在目標程序載入內存或使用dlopen動態加載時才會映射到進程內存;由於文件是單獨存在的,故需要隨其它程序或模塊一起分發;當然,文件獨立存在性,也使得其具備不同模塊或目標程序可以共享一個共同的庫文件,就是有了共享庫的含義。
如前所說,存在兩種使用方式:
- 編譯目標程序時聲明了所使用的動態鏈接庫,那么在目標程序啟動時,動態鏈接庫將會被載入內存;
- 目標程序在使用時通過
dlopen主動裝載鏈接庫,那么這種情況,鏈接庫的裝載時機取決於開發者。
下面簡單介紹第2種情況的使用流程:
typedef bool (void * _MY_FUNC)(int)
...
//*使用`dlopen`*將庫載入內存,獲得句柄
void * libHandle = dlopen("mySharedLibrary.so",RTLD_LAZY);
...
//獲取導出函數
_MY_FUNC myFunc = (_MY_FUNC)dlsym(libHandle, "MyTestFunc");
...
//調用導出函數
bool bRet = myFunc(2);
...
//關閉鏈接庫
dlclose(libHandle);
2.2 生成動態鏈接共享庫
2.2.1 通常情況的so生成
與生成靜態鏈接庫的要求一樣,需要將源代碼和庫放在當前目錄下的jni目錄下,並在jni目錄創建Android.mk文件。一般情況其內容如下:
include $(CLEAR_VARS)
LOCAL_MODULE := myLibrary
LOCAL_C_INCLUDES := $(LOCAL_PATH)/jni
LOCAL_SRC_FILES := myLibrary.cpp
include $(BUILD_SHARED_LIBRARY)
之后ndk-build即可。
2.2.2 適用於jni接口的so的生成
生成適用於jni調用的so,則需要用先用javah生成包含函數聲明的頭文件:javah <包名>.<類名>。例如:
javah com.my.package.myActivity
其它過程和2.2.1 通常情況下的so生成中的方法一致。
2.2.3 生成過程中靜態連接其他靜態庫
生成so時,可能會需要鏈接其他一些靜態庫,這是Android.mk如下所示:
LOCAL_PATH := $(call my-dir)
###include myStaticLibrary lib as a prebuilt lib###
include $(CLEAR_VARS)
LOCAL_MODULE := mystaticLibrary
LOCAL_SRC_FILES := ./../../mystaticLibrary/obj/local/armeabi/libmystaticLibrary.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../mystaticLibrary/jni
include $(PREBUILT_STATIC_LIBRARY)
### build ndk lib###
include $(CLEAR_VARS)
LOCAL_MODULE := myLib
LOCAL_C_INCLUDES := $(LOCAL_PATH)/jni \
$(LOCAL_PATH)/../../mystaticLibrary/jni
LOCAL_SRC_FILES := myLib.cpp
LOCAL_LDLIBS := -llog
LOCAL_STATIC_LIBRARIES := mystaticLibrary
include $(BUILD_SHARED_LIBRARY)
其中LOCAL_SRC_FILES指定的靜態庫需要提前已經編譯好。這里也需要Application.mk
3. Native Executable Binary
這里說的就是原生的可執行文件。Android平台本身就有不少原生的可執行程序,如ps、cd等命令對應的bin。
其生產方法和so生成類似,鏈接靜態庫也類似。
### compile NDK Executable ###
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := native_run
LOCAL_SRC_FILES := native_run.cpp
LOCAL_INCLUDE := $(LOCAL_PATH)/jni
include $(BUILD_EXECUTABLE)
