解讀Android.mk檔案
一、介紹
本文章會介紹構建 Android.mk檔案的構建過程;Android.mk檔案會將我們的 C 和 C++ 檔案描述為 Android NDK
二、概述
Android.mk檔案是描述原始檔在構建系統的作用,更具體來說:
- 這個Android.mk是一個微小版的在構建過程中解析一次或多次的Makefile,最好儘量減少在這個檔案中宣告變數的數量,不要使用沒有定義的變數
- 它可以將你的原始檔編譯成一個模組,這個模組可以是如下之一:
- .a 靜態庫
- .so 動態庫
- 一個獨立的可執行檔案
構建系統只會將動態庫安裝或者複製到應用程式包,也就是說這個動態庫的大小不會改變;此外,靜態庫可以作為原始檔編譯生成動態庫
你可以在每個 Android.mk檔案中定義一個或多個模組,並且可以在多個模組中使用相同的原始檔
三、例子解釋
一般來說,我們編寫的 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_PATH := $(call my-dir)
一個 Android.mk檔案的開頭必須從定義這個變數開始,這個變數用於在開發過程中定位 Android.mk檔案在專案中的路徑;my-dir是一個巨集函式,由系統提供,呼叫這個函式會返回當前檔案所在目錄的路徑
include $(CLEAR_VARS)
這個 CLEAR_VARS變數是系統提供的,它指向一個特殊的 GNU Makefile檔案,它會清除很多 LOCAL_XXX的變數(如:LOCAL_MODULE、LOCAL_SRC_FILES、LOCAL_STATIC_LIBRARIES等);為什麼要清除?因為很多的控制檔案都是在單個 GUN make中生成的,這些變數都是GUN make中的全域性變數,如果不清除,上一次構建的資料資訊會影響下一次的構建
LOCAL_MODULE := hello-jni
該命令用於為每一個模組定義其名稱,這個名稱必須是唯一且不包含空格;在構建過程中,系統會自動為模組加上字首,如:hello-jni 生成的模組為 libhello-jni.so
PS
LOCAL_SRC_FILES := hello-jni.c
該命令用於列舉編譯模組需要的 C/C++原始檔,同時不要列舉標頭檔案和包含檔案,因為系統在構建的過程中自動計算這些檔案的依賴,我們只需要列舉出正確的C/C++原始檔就行
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY是系統的提供的一個變數,它指向 GUN Makefile的一個指令碼,這個指令碼會收集你定義的所有 LOCAL_XXX形式的變數,然後根據這些變數構建 .so動態庫。其他的變數還有:BUILD_STATIC_LIBRARY(構建靜態庫)
$(call import-add-path,f:/transcode-1.1.7/)
$(call import-module,avilib)
import-add-path 表示在將後面的路徑(也就是說磁碟 f:/transcode-1.1.7/路徑)下的資源新增到NDK構建的路徑中;
import-module 表示從NDK的構建路徑中引入模組
這個兩個引數一般都是配套使用的,用於引入指定的模組,引入成功後,如果要使用模組裡面的功能,那麼還要在你的so庫構建模組中新增 (LOCAL_STATIC_LIBRARIES += libName),libName就是引入模組中的Android.mk檔案中構建的模組名稱
四、Android.mk的變數
我們可以在 Android.mk檔案中使用自己的用法定義其他變數,但是 NDK的構建系統保留以下變數名,這些變數在會在 Android.mk檔案執行之前被系統定義:
- 以 LOCAL_XXX開頭的變數名,這些變數名是系統定義的
- 以 PRIVATE_、NDK_、APP_ 開頭的變數
- 小寫字母的變數名,如:my-dir;
因為系統的一些變數是小寫字母,我們在定義變數名的時候最好不能用小寫,而全部使用大寫
現在我們來看看 NDK提供的變數
BUILD_SHARED_LIBRARY
這個變數指定編譯生成 .so靜態庫,但是在使用這個變數時一定要先定義 LOCAL_MODULE 和 LOCAL_SRC_FILES兩個變數
BUILD_STATIC_LIBRARY
這個變數指定編譯生成 .a靜態庫,使用這個變數前也需要先定義 LOCAL_MODULE 和 LOCAL_SRC_FILES兩個變數
PREBUILT_SHARED_LIBRARY
用於指定預編譯的so庫,也就是在編譯目的so庫的時候需要用到源so庫的東西時,那麼就要在構建源so庫的時候,使用這個變數指定它編譯生成的庫型別