1. 程式人生 > >Android平臺交叉編譯流程

Android平臺交叉編譯流程

一: 當我們在Android平臺上開發一些軟體的時候,有時不可避免的要用到一些用c/c++所編寫的庫。有些庫有大神們已經封裝好了在特定平臺上對應的api,我們直接呼叫就可以,但是更多的庫需要我們自己根據自己所需的特定的平臺去進行編譯。

二: 不同的目標平臺都有明確的編譯器,所以說在一個平臺上編譯另一個平臺上所執行的程式就叫做交叉編譯。常見的ARM平臺的交叉編譯工具鏈有:  arm-linux-gcc 這個主要用於編譯linux核心,  arm-linux-androideabi-gcc 則是我們android平臺的交叉編譯鏈,意思就是如果我們安卓的應用程式想要使用c語言編寫的第三方庫,就必須用這個交叉編譯工具鏈進行編譯。

三: 獲取交叉編譯鏈

         一般獲取交叉工具鏈我們可以通過android 官網中的ndk進行獲取,地址:https://developer.android.google.cn/ndk/downloads/index.html  ,下載下來以後我們可以解壓目錄的 android-ndk-r14b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin  看到我們的arm處理所對應的交叉編譯工具鏈,當然,其他處理器例如X86也有對應的處理器。

四: 交叉編譯工具鏈的使用

       一般在我們有兩種方式進行android平臺上軟體的移植,第一種方式就是直接用ndk中的ndk-build指令碼進行編譯,第二種則是利用ndk生成交叉編譯工具鏈,然後我們用這個交叉編譯工具鏈去編譯我們的目標檔案。

       a.ndk-build方式:

                 一般我們在android專案中作ndk開發是絕大多數都會用這種方式,這種方式需要我們在專案中建立 Android.mk  Application.mk檔案,這裡的Android.mk檔案類似於我們一般常用的makefile,只是格式不同罷了。下面貼出來一個寫好的makefile檔案:   

Android.mk      

LOCAL_PATH:= $(call my-dir)    # 返回當前路徑  
include $(CLEAR_VARS)          # 清除定義的變數
LOCAL_MODULE := JniDemo        # 生成模組的名字
LOCAL_SRC_FILES := test.cpp    # 需要編譯的原始檔
LOCAL_LDLIBS := -llog          # 編譯所需要的庫
LOCAL_SHARED_LIBRARIES := myadd#編譯所需要的靜態庫
include $(BUILD_SHARED_LIBRARY)  #編譯為靜態庫
Application.mk
APP_PLATFORM := android-19  #指定對於Android系統版本
APP_BUILD_SCRIPT := Android.mk #指定對應mk檔案
APP_ABI := armeabi-v7a x86  #指定對於平臺

上面列出的只是一些最基本最常用的用法, 由於本文不側重mk語法的講解,想要深入瞭解可以百度,資料很多。

                當根據自己的 情況寫好自己的mk檔案後(部分情況都是第三方庫自帶mk檔案)我們通常建立一個jni目錄,在這些檔案及原始檔放在該目錄中,然後在該目錄下執行ndk-build.sh 這個指令碼,它會自動在我們jni的同級目錄建立lib目錄,生成的庫檔案都會放在這個庫中。我們可以直接通過jni進行呼叫,關於jni呼叫第三方庫的詳細流程我會專門去講。

        b.生成交叉編譯工具鏈的方式:

                 這種方式一般適用於一些沒有提供安卓版本的第三方庫,我更多的情況也是使用的這種方式,需要我們自己去修改cmake或makefile或者configure 等一些編譯或配置檔案去實現Android版本的編譯,那麼如何生成交叉編譯工具鏈呢?

                 一般我們的做法是: 

在我們所裝的ndk的目錄下執行:

./build/tools/make-standalone-toolchain.sh --platform=android-21

其中--platform是我們所對應的Android平臺,更多的選項可以使用 --help進行檢視,生成的壓縮包會在終端提示,直接過去解壓加入環境變數就可以使用了,使用方式基本與gcc 及 arm-linux-gcc 類似,(切記不要直接使用/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin 下面的編譯鏈)

五:當我們編譯類庫的時候,我們如果是在studio下面用java開發的應用程式,需要使用jni去呼叫我們的so庫中的c/c++函式。因為我目前使用的qt下面c++開發的android程式,所以把so庫放在lib下面,直接就可以呼叫。

今天主要針對一些編譯環境的搭建及編譯的使用進行一些簡單的講解,原理其實並不難。我個人感覺在編譯一些第三方庫的過程中所出現的問題稍微麻煩一點,這方面好多錯誤在網上也查不到資料,一定要沉的住氣,多分析提示的錯誤,多思考。 有這方面的問題可以加q交流: 553096041