上篇咱們編寫了NDK代碼了。也調用到了C/C++的方法,這篇咱們來編譯成動態庫so文件, 在編譯生成SO文件須要配下Android.mk文件 爲何須要這個文件Android.mk。當你須要使用JNI的時候,你須要建立一個native工程。Android.mk就是一個makefile配置文件,幫你把C/C++的代碼編譯成動態庫so的。 咱們來看下Android.mk文件內容android
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hellojni LOCAL_SRC_FILES := hajskdh.c include $(BUILD_SHARED_LIBRARY)
解釋下這幾行代碼:bash
LOCAL_PATH := $(call my-dir) 它用於在開發樹中查找源文件。 在這個例子中,宏函數‘my-dir’, 由編譯系統提供,用於返回當前路徑(即包含Android.mk file文件的目錄)。app
include $(CLEAR_VARS) CLEAR_VARS 由編譯系統提供(能夠在 android 安裝目錄下的/build/core/config.mk 文件看到其定義,爲 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk),指定讓 GNU MAKEFILE爲你清除許多 LOCAL_XXX 變量 ( 例如 LOCAL_MODULE , LOCAL_SRC_FILES ,LOCAL_STATIC_LIBRARIES,等等…),除 LOCAL_PATH。這是必要的,由於全部的編譯控制文件都在同一個 GNU MAKE 執行環境中,全部的變量都是全局的。函數
LOCAL_MODULE := hellojni LOCAL_MODULE變量必須定義,以表示你在Android.mk文件中描述的每一個模塊名稱必須是惟一的,通俗的說這個就是你最後生成so的名稱,好比你填寫的hellojni最後生成的就是libhellojni.so文件。注意:若是把庫命名爲‘libhellojni’,編譯系統將不會添加任何的 lib 前綴,也會生成libhelloworld.so,這是爲了支持來源於 Android平臺的源代碼的 Android.mk 文件。gradle
LOCAL_SRC_FILES := hajskdh.c LOCAL_SRC_FILES變量必須包含將要編譯的打包進模塊中的C/C++文件源碼。這裏不須要引用頭文件。ui
include $(BUILD_SHARED_LIBRARY) BUILD_SHARED_LIBRARY 是編譯系統提供的變量,指向一個 GNU Makefile 腳本(應該就是在 build/core 目錄下的 shared_library.mk) ,負責收集自從上次調用 'include $(CLEAR_VARS)'以來,定義在 LOCAL_XXX 變量中的全部信息,而且決定編譯什麼,如何正 確地去作。並根據其規則生成靜態庫。同理對於靜態庫。命令行
Android.mk是必要文件,那麼application.mk就是否是必要文件了。這個文件目的是描述在你的應用程序中所須要的模塊(即靜態庫或動態庫)。code
APP_MODULES := hellojni APP_ABI := all
這兩行就相對簡單, APP_MODULES這個變量是可選的,若是沒有定義,NDK將由在Android.mk中聲明的默認的模塊編譯,而且包含全部的子文件(makefile文件)若是APP_MODULES定義了,它不準是一個空格分隔的模塊列表,這個模塊名字被定義在Android.mk文件中的LOCAL_MODULE中。 APP_ABI默認狀況下,NDK的編譯系統"armeabi"ABI生成機器代碼。 all就表示全部類型都生成, 若是不須要所有隻須要部分就能夠設置APP_ABI := armeabi armeabi-v7a x86 這樣就ok。 以上介紹是的編譯SO須要的兩個配置文件。那麼接下來就正式編譯so文件,找到以前hellojni項目的jni目錄,在目錄上右鍵選擇ndk-build(在前篇有介紹的,不知道的同窗能夠過去看下)。點擊完成就能夠看到控制檯輸出的結果以下,orm
這裏就會看到項目目錄裏面多生成了兩個目錄一個是libs,另外一個是obj。libs下面就是編譯生成的so對應的機器碼,而後obj目錄就沒有什麼用能夠刪除了。這裏須要注意下obj這個目錄在第二次編譯以前請刪除掉。否則二次編譯就會收到影響。 刪除的編譯生成的文件可使用ndk-build clear這個命令配置。這個命令就會清楚以前因編譯生成的so相關文件,圖片
咱們在介紹另外一種編譯SO文件的辦法,這種辦法相對上面一種辦法對依賴AS相對較少。 這裏可使用.sh腳本去執行編譯SO文件操做。咱們先介紹下.sh模板
#!/usr/bin/env bash NDK_PROJECT_PATH=../ function build_so(){ ANDROID_MK=Android.mk APPLICATION_MK=Application.mk XXX/xxx/xxx/android-ndk-r12b/ndk-build -j8 NDK_TOOLCHAIN_VERSION=clang NDK_DEBUG=$1 #-platforms } #set_env DEBUG=1 RELEASE=0; build_so $RELEASE
以上就是build.sh的模板了。 直接將這段代碼複製到文本後綴名改成.sh 而後將xxx/xxx/xxx/Android-ndk/ndk-build更改成你當前ndk的存放目錄便可。 運行的話打開命令行進入到項目目錄的jni目錄下,而後執行sh build.sh文件便可獲得同上面同樣效果的文件目錄結構。
以上還須要注意點內容就是: 經過AS編譯出來的so文件配置是能夠不須要依賴Aapplication.mk文件的。它對應的配置文件是build.gradle 中這個配置,因此在調整本身須要的so文件的時候注意下,
//定義使用ndk ndk{ moduleName "hellojni" //生成的so名字 abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種abi體系結構下的so庫。目前無關緊要。 }
而經過腳本編譯出來以來的文件就是Aapplication.mk因此最後在使用的時候記得分清楚。以避免搞混亂了。