將 native libraries 加入 AOSP 的編譯
上篇介紹用 Android SDK 和 NDK 來編譯含 JNI 的 Android 應用程式。但若是已有 Android (或 Android-x86)的 source tree,可能就不會再想安裝 SDK 和 NDK。因為 AOSP tree 本身就包含完整的 SDK 和 NDK。那麼是不是可以將含有 native libraries 的應用程式,加入到 AOSP 的 build system 中編譯? 這麼做還有一個更重要的理由,就是把你的應用程式和 AOSP 的源碼結合在一起,用單一步驟就可以完成所有的編譯。這樣有助於維護單一而自我包含(self-contained)的源碼。
答案當然是肯定的。經過一番嘗試後,發現只要稍微修改一下應用程式的 Android.mk 就行。具體的做法如下:
首先,將應用程式的目錄搬到 AOSP tree 的 packages/apps/ 目錄下。例如 packages/apps/hello。
再來,建立 packages/apps/hello/Android.mk,內容如下:
$(call build-package) LOCAL_PATH:= $(LOCAL_PATH)/jni include $(CLEAR_VARS) LOCAL_MODULE := libhello LOCAL_SRC_FILES := hello.c LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) LOCAL_SHARED_LIBRARIES := include $(BUILD_SHARED_LIBRARY) |
這個 Android.mk 包含了兩部分。第一部分是編譯 java code 產生 apk,這是由 build-package macro 所完成。這個 macro 是 Android-x86 加入的。若你用的是原始的 Google AOSP 並沒有此 macro。不過用原本的 Android build system 規則,直接指定 LOCAL_PACKAGE_NAME、LOCAL_SRC_FILES 等變數也可以。
第二部分就是 native libraries 的編譯規則。其中有幾個和 NDK 裡 Android.mk 不同的地方值得注意。一是要在 LOCAL_C_INCLUDES 指定 nativehelper 目錄的位置。否則的話,就要修改源碼中的 #include <jni.h> 成為 #include <nativehelper/jni.h>,不然會找不到 jni.h。另一個不同的地方是,若原本在 LOCAL_LDLIBS 指定 link 了其它的 libraries,要改成用 LOCAL_SHARED_LIBRARIES 來指定用 AOSP 的 libraries。以 san-angeles 這個 sample 為例,它原本是
LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog |
必須改為
LOCAL_SHARED_LIBRARIES := libGLESv1_CM liblog |
還有一點不同是,LOCAL_MODULE 一定要以 lib 開頭(上例就是 libhello)。不像 NDK 的 Android.mk 裡,好像用 hello 或 libhello 都行。
這樣子照原本編譯 AOSP 的方法,就可以編出包含此應用程式的 image 了。不過和 NDK 不同的是,它的 shared libraries 是放進 /system/lib 裡,apk 裡並不包含 .so 檔(可以用 unzip 解開來看)。
參考:
如果有人有更好的做法,歡迎分享。
