1. 程式人生 > >如何在windows上用ndk交叉編譯其他平臺程式

如何在windows上用ndk交叉編譯其他平臺程式

目標       :編譯arm64的.so庫

編譯方法:理論上應該有兩種交叉編譯方法,法一,在Linux伺服器上安裝交叉工具鏈,直接用交叉工具鏈進行編譯連結;法二,使用ndk完成交叉編譯,因為

ndk已經安裝好交叉編譯工具鏈,以及相關的系統庫和系統標頭檔案了。這兩種方法的區別在於,linux伺服器上的編譯使用的makefile和ndk使用的.mk
檔案顯然不同。原因是ndk作為一個整合編譯環境,制定了一套特定的規則用於生成最終的編譯指令碼。

這裡簡單總結下,如何在windows用ndk進行交叉編譯arm64目標平臺的.so庫:

step1:找到ndk開發工具包,官網之類的都可以下載,android-ndk64-r10-windows-x86_64.rar檔案

step2:解壓上述ndk工具包,將包含程式原始檔和標頭檔案的資料夾testProject都放入android-ndk-r10下的samples目錄下。

放在其他地方當然也可以,但是後續相對路徑之類的不太好加,既然其他例子都放這,把程式碼放這編譯是最保險的了。

step3:在testProject中增加一個jni的資料夾,必須要新增!!!!!!

step4:在jni資料夾中,新增一個Android.mk的檔案,必須要新增!!!!!

step5:在jni資料夾中,新增一個Application.mk的檔案與Android.mk並列,必須要新增!!!!!

step6:Android.mk和Application.mk合起來就類似於linux環境下的makefile編譯檔案。

         如何寫Android.mk,可以參考例子helllo-jni中jni資料夾下的Android.mk。

LOCAL_PATH:=$(call my-dir) #必須要寫的

include $(CLEAR_VARS) #必須要寫的

LOCAL_MODULE:=hello-jni #編譯出來的模組名稱

LOCAL_SRC_FILES:=hello-jni.c #制定編譯的原始檔名稱

include $(BUILD_SHARED_LIBRARY)#放在最後

除了上述變數之外,還有其他的指定的變數,

LOCAL_CFLAGS,用於指定編譯選項,這個和makefile中是完全一樣的,可以指定編譯選項-g,也可以指定編譯巨集及巨集值

LOCAL_LDLIBS,用於指定連結的依賴庫,這個可以makefile也是完全一樣的,可以指定連結庫用-l庫名,以及指定庫搜尋路徑用_L路徑名

LOCAL_STATIC_LIBRARIES,指定連結的靜態庫名,makefile中沒有

LOCAL_C_INCLUDES,用於指定編譯標頭檔案的路徑,和makefile中不同,路徑前不需要加-I,直接寫路徑即可,可以是相對路徑或絕對路徑,

多個路徑之間用空格隔開。

編寫上述Android.mk碰到的問題有,

(1)使用預設的系統自動載入stl庫標頭檔案總是出錯,只好手動在LOCAL_STATIC_LIBRARIES指定sources/cxx-stl/stlport/stlport來完成對#include<string>這種c++形式的標頭檔案載入

(2)使用$(SYSROOT)/usr/include來完成對系統庫標頭檔案的載入,結果找不到sem_t符號,只好指定platforms/android-L/arch-arm64/usr/include

step7:Application.mk編寫

APP_STL指定使用的stl移植庫,動態或者靜態都行

APP_CPPFLAGS,指定app編譯的編譯選項

APP_ABI指定abi規範型別,例如arm64-v8a,也可以寫成ALL就是把所有的型別全部編一編

APP_PLATFORM指定編譯的platform名稱,這裡可以寫成android-L或者不指定全編。

step8:編譯完成後,執行。

啟動cmd,使用cd /D進行到testProject的jni目錄下

step9:將android-ndk-r10下的ndk-build.cmd直接拖拽到cmd中,此時直接敲回車,就可以編譯了。當然也可以加一個 clean,清除編譯中間檔案。

step10:檢查下編譯結果,編譯成功後在testProject中多了兩個資料夾與jni並列的,libs和obj。

編譯連結後的結果就在libs中!