深刻了解android平臺的jni(二)

Android.mk是Android提供的一種makefile文件,用來指定諸如編譯生成so庫名、引用的頭文件目錄、須要編譯的.c/.cpp文件和.a靜態庫文件等。要掌握jni,就必須熟練掌握Android.mk的語法規範。java

1、Android.mk文件的用途
一個android子項目中會存在一個或多個Android.mk文件
一、單一的Android.mk文件
直接參考NDK的sample目錄下的hello-jni項目,在這個項目中只有一個Android.mk文件
二、多個Android.mk文件
若是須要編譯的模塊比較多,咱們可能會將對應的模塊放置在相應的目錄中,
這樣,咱們能夠在每一個目錄中定義對應的Android.mk文件(相似於上面的寫法),
最後,在根目錄放置一個Android.mk文件,內容以下:
include $(call all-subdir-makefiles)
只須要這一行就能夠了,它的做用就是包含全部子目錄中的Android.mk文件
三、多個模塊共用一個Android.mk
這個文件容許你將源文件組織成模塊,這個模塊中含有:
  -靜態庫(.a文件)
  -動態庫(.so文件)
只有共享庫才能被安裝/複製到您的應用軟件(APK)包中
include $(BUILD_STATIC_LIBRARY),編譯出的是靜態庫
include $(BUILD_SHARED_LIBRARY),編譯出的是動態庫android

 

2、自定義變量
 如下是在 Android.mk中依賴或定義的變量列表,能夠定義其餘變量爲本身使用,可是NDK編譯系統保留下列變量名:
 -以 LOCAL_開頭的名字(例如 LOCAL_MODULE)
 -以 PRIVATE_, NDK_ 或 APP_開頭的名字(內部使用)
 -小寫名字(內部使用,例如‘my-dir’)
  若是爲了方便在 Android.mk 中定義本身的變量,建議使用 MY_前綴,一個小例子:
MY_SOURCES := foo.c
ifneq ($(MY_CONFIG_BAR),)
 MY_SOURCES += bar.c
endif
LOCAL_SRC_FILES += $(MY_SOURCES)
注意:‘:=’是賦值的意思;'+='是追加的意思;‘$’表示引用某變量的值。api

 

3、GNU Make系統變量
  這些 GNU Make變量在你的 Android.mk 文件解析以前,就由編譯系統定義好了。注意在某些狀況下,NDK可能分析 Android.mk 幾回,每一次某些變量的定義會有不一樣。
  (1)CLEAR_VARS:  指向一個編譯腳本,幾乎全部未定義的 LOCAL_XXX 變量都在"Module-description"節中列出。必須在開始一個新模塊以前包含這個腳本:include$(CLEAR_VARS),用於重置除LOCAL_PATH變量外的,全部LOCAL_XXX系列變量。
  (2)BUILD_SHARED_LIBRARY:  指向編譯腳本,根據全部的在 LOCAL_XXX 變量把列出的源代碼文件編譯成一個共享庫。
       注意,必須至少在包含這個文件以前定義 LOCAL_MODULE 和 LOCAL_SRC_FILES。
  (3)BUILD_STATIC_LIBRARY:  一個 BUILD_SHARED_LIBRARY 變量用於編譯一個靜態庫。靜態庫不會複製到的APK包中,可是可以用於編譯共享庫。
       示例:include $(BUILD_STATIC_LIBRARY)
       注意,這將會生成一個名爲 lib$(LOCAL_MODULE).a 的文件
  (4)TARGET_ARCH: 目標 CPU平臺的名字
  (5)TARGET_PLATFORM: Android.mk 解析的時候,目標 Android 平臺的名字.詳情可考/development/ndk/docs/stable- apis.txt.
       android-3 -> Official Android 1.5 system images
       android-4 -> Official Android 1.6 system images
       android-5 -> Official Android 2.0 system images
  (6)TARGET_ARCH_ABI:  暫時只支持兩個 value,armeabi 和 armeabi-v7a。。
  (7)TARGET_ABI: 目標平臺和 ABI 的組合,函數

                               
4、模塊描述變量
  下面的變量用於向編譯系統描述你的模塊。應該定義在'include  $(CLEAR_VARS)'和'include $(BUILD_XXXXX)'之間。$(CLEAR_VARS)是一個腳本,清除全部這些變量。
  (1)LOCAL_PATH:  這個變量用於給出當前文件的路徑。
       必須在 Android.mk 的開頭定義,能夠這樣使用:LOCAL_PATH := $(call my-dir)
       如當前目錄下有個文件夾名稱 src,則能夠這樣寫 $(call src),那麼就會獲得 src 目錄的完整路徑
       這個變量不會被$(CLEAR_VARS)清除,所以每一個 Android.mk 只須要定義一次(即便在一個文件中定義了幾個模塊的狀況下)。
  (2)LOCAL_MODULE: 這是模塊的名字,它必須是惟一的,並且不能包含空格。
       必須在包含任一的$(BUILD_XXXX)腳本以前定義它。模塊的名字決定了生成文件的名字。
  (3)LOCAL_SRC_FILES:  這是要編譯的源代碼文件列表。
       只要列出要傳遞給編譯器的文件,由於編譯系統自動計算依賴。注意源代碼文件名稱都是相對於 LOCAL_PATH的,你可使用路徑部分,例如:
        LOCAL_SRC_FILES := foo.c toto/bar.c\
        Hello.c
       文件之間能夠用空格或Tab鍵進行分割,換行請用"\"
       若是是追加源代碼文件的話,請用LOCAL_SRC_FILES +=
       注意:能夠LOCAL_SRC_FILES := $(call all-subdir-java-files)這種形式來包含local_path目錄下的全部java文件。
  (4)LOCAL_C_INCLUDES:  可選變量,表示頭文件的搜索路徑。
        默認的頭文件的搜索路徑是LOCAL_PATH目錄。
  (5)LOCAL_STATIC_LIBRARIES: 表示該模塊須要使用哪些靜態庫,以便在編譯時進行連接。
  (6)LOCAL_SHARED_LIBRARIES:  表示模塊在運行時要依賴的共享庫(動態庫),在連接時就須要,以便在生成文件時嵌入其相應的信息。
       注意:它不會附加列出的模塊到編譯圖,也就是仍然須要在Application.mk 中把它們添加到程序要求的模塊中。
  (7)LOCAL_LDLIBS:  編譯模塊時要使用的附加的連接器選項。這對於使用‘-l’前綴傳遞指定庫的名字是有用的。
       例如,LOCAL_LDLIBS := -lz表示告訴連接器生成的模塊要在加載時刻連接到/system/lib/libz.so
       可查看 docs/STABLE-APIS.TXT 獲取使用 NDK發行版能連接到的開放的系統庫列表。
   (8)LOCAL_MODULE_PATH 和 LOCAL_UNSTRIPPED_PATH
       在 Android.mk 文件中, 還能夠用LOCAL_MODULE_PATH 和LOCAL_UNSTRIPPED_PATH指定最後的目標安裝路徑.
       不一樣的文件系統路徑用如下的宏進行選擇:
       TARGET_ROOT_OUT:表示根文件系統。
       TARGET_OUT:表示 system文件系統。
       TARGET_OUT_DATA:表示 data文件系統。
       用法如:LOCAL_MODULE_PATH :=$(TARGET_ROOT_OUT)
       至於LOCAL_MODULE_PATH 和LOCAL_UNSTRIPPED_PATH的區別,暫時還不清楚。
   (9)LOCAL_JNI_SHARED_LIBRARIES:定義了要包含的so庫文件的名字,若是程序沒有采用jni,不須要
        LOCAL_JNI_SHARED_LIBRARIES := libxxx 這樣在編譯的時候,NDK自動會把這個libxxx打包進apk; 放在youapk/lib/目錄下this

 

5、NDK提供的函數宏
GNU Make函數宏,必須經過使用'$(call  )'來調用,返回值是文本化的信息。
   (1)my-dir:返回當前 Android.mk 所在的目錄的路徑,相對於 NDK 編譯系統的頂層。這是有用的,在 Android.mk 文件的開頭如此定義:
        LOCAL_PATH := $(call my-dir)
   (2)all-subdir-makefiles: 返回一個位於當前'my-dir'路徑的子目錄中的全部Android.mk的列表。
       例如,某一子項目的目錄層次以下:
            src/foo/Android.mk
            src/foo/lib1/Android.mk
            src/foo/lib2/Android.mk
      若是 src/foo/Android.mk 包含一行:
           include $(call all-subdir-makefiles)
      那麼它就會自動包含 src/foo/lib1/Android.mk 和 src/foo/lib2/Android.mk。
      這項功能用於向編譯系統提供深層次嵌套的代碼目錄層次。
      注意,在默認狀況下,NDK 將會只搜索在 src/*/Android.mk 中的文件。
   (3)this-makefile:  返回當前Makefile 的路徑(即這個函數調用的地方)
   (4)parent-makefile:  返回調用樹中父 Makefile 路徑。即包含當前Makefile的Makefile 路徑。
   (5)grand-parent-makefile:返回調用樹中父Makefile的父Makefile的路徑debug

 

6、 Android.mk示例
#編譯靜態庫
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE = libhellos
LOCAL_CFLAGS = $(L_CFLAGS)
LOCAL_SRC_FILES = hellos.c
LOCAL_C_INCLUDES = $(INCLUDES)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_COPY_HEADERS_TO := libhellos
LOCAL_COPY_HEADERS := hellos.h
include $(BUILD_STATIC_LIBRARY)blog

#編譯動態庫
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE = libhellod
LOCAL_CFLAGS = $(L_CFLAGS)
LOCAL_SRC_FILES = hellod.c
LOCAL_C_INCLUDES = $(INCLUDES)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_COPY_HEADERS_TO := libhellod
LOCAL_COPY_HEADERS := hellod.h
include $(BUILD_SHARED_LIBRARY)ip

#使用靜態庫
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hellos
LOCAL_STATIC_LIBRARIES := libhellos
LOCAL_SHARED_LIBRARIES :=
LOCAL_LDLIBS += -ldl
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := mains.c
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)ci

#使用動態庫
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hellod
LOCAL_MODULE_TAGS := debug
LOCAL_SHARED_LIBRARIES := libc libcutils libhellod
LOCAL_LDLIBS += -ldl
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := maind.c
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)get

Android.mk給變量賦值,同時用的「:=」和「=」,他們分別表明什麼意思呢?

「:=」 的意思是,它右邊賦得值若是是變量,只能使用在這條語句以前定義好的,而不能使用本條語句以後定義的變量;

「=」,當它的右邊賦值是變量時,這個變量的定義在本條語句以前或以後均可以;

本文歡迎轉載,轉載請註明做者與出處

做者:流星

出處:http://blog.sina.com.cn/staratsky

相關文章
相關標籤/搜索