1. 程式人生 > >解讀Android.mk檔案

解讀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

:如果模組名為libhello-jni,那麼生成的模組還是 libhello-jni.so
 

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檔案執行之前被系統定義:

  1. 以 LOCAL_XXX開頭的變數名,這些變數名是系統定義的
  2. 以 PRIVATE_、NDK_、APP_ 開頭的變數
  3. 小寫字母的變數名,如: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庫的時候,使用這個變數指定它編譯生成的庫型別