1. 程式人生 > >深入瞭解android平臺的jni(二)

深入瞭解android平臺的jni(二)

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

一、Android.mk檔案的用途
一個android子專案中會存在一個或多個Android.mk檔案
1、單一的Android.mk檔案
直接參考NDK的sample目錄下的hello-jni專案,在這個專案中只有一個Android.mk檔案
2、多個Android.mk檔案
如果需要編譯的模組比較多,我們可能會將對應的模組放置在相應的目錄中,
這樣,我們可以在每個目錄中定義對應的Android.mk檔案(類似於上面的寫法),
最後,在根目錄放置一個Android.mk檔案,內容如下:
include $(call all-subdir-makefiles)
只需要這一行就可以了,它的作用就是包含所有子目錄中的Android.mk檔案
3、多個模組共用一個Android.mk
這個檔案允許你將原始檔組織成模組,這個模組中含有:
  -靜態庫(.a檔案)
  -動態庫(.so檔案)
只有共享庫才能被安裝/複製到您的應用軟體(APK)包中
include $(BUILD_STATIC_LIBRARY),編譯出的是靜態庫
include $(BUILD_SHARED_LIBRARY),編譯出的是動態庫

二、自定義變數
 以下是在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)
注意:‘:=’是賦值的意思;'+='是追加的意思;‘$’表示引用某變數的值。

三、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 systemimages
      android-4 -> Official Android 1.6 systemimages
      android-5 -> Official Android 2.0 systemimages
  (6)TARGET_ARCH_ABI:  暫時只支援兩個value,armeabi 和 armeabi-v7a。。
  (7)TARGET_ABI: 目標平臺和 ABI 的組合,

                               
四、模組描述變數
 下面的變數用於向編譯系統描述你的模組。應該定義在'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 := $(callall-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/目錄下

五、NDK提供的函式巨集
GNUMake函式巨集,必須通過使用'$(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的路徑

六、 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)

#編譯動態庫
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)

#使用靜態庫
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)

#使用動態庫
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)

Android.mk給變數賦值,同時用的“:=”和“=”,他們分別代表什麼意思呢?

“:=” 的意思是,它右邊賦得值如果是變數,只能使用在這條語句之前定義好的,而不能使用本條語句之後定義的變數;

“=”,當它的右邊賦值是變數時,這個變數的定義在本條語句之前或之後都可以;


相關推薦

深入瞭解android平臺jni()

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

深入瞭解android平臺jni---使用巨集定義精簡JNI介面函式名稱

深入瞭解android平臺的jni—使用巨集定義精簡JNI介面函式名稱 (2014-07-01 18:33:01)轉載▼ 標籤: android jni 巨集定義 分類: android 精簡JNI介面函式名稱 生成java的本地方法一般是通過如下步驟完成

Android.mk檔案語法規範——深入瞭解android平臺jni

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

深入瞭解android平臺jni

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

瞭解android平臺jni(一)

android中很多Java類都具有native介面,這些介面由本地實現,然後註冊到系統中,主要的JNI程式碼放在以下的路徑中:frameworks/base/core/jni/,這個路徑中的內容被編譯成庫 libandroid_runtime.so,被放置在目標系統的/s

深入瞭解Android藍芽Bluetooth——《基礎篇》

什麼是藍芽?   也可以說是藍芽技術。所謂藍芽(Bluetooth)技術,實際上是一種短距離無線電技術,是由愛立信公司公司發明的。利用“藍芽”技術,能夠有效地簡化掌上電腦、膝上型電腦和行動電話手機等行動通訊終端裝置之間的通訊,也能夠成功地簡化以上這些裝置與因特網

Android平臺生成維碼(by google.zxing)

查了大部分的資料,發現android平臺下生成二維碼的例子都是使用谷歌的zxing類,因此仿照某一個帖子編寫了一個demo進行測試,仿照的帖子: https://blog.csdn.net/myname_kk/article/details/77649477 例子中主要用到了BitMatri

[Image_Codec]常見圖片格式的封裝及編解碼-Android平臺)PNG

PNG圖片格式 PNG(Portable Network Graphics) 是一種光柵化的,無失真壓縮的圖片檔案格式。其設計的目的是替換GIF,是目前網路中用得最廣的無失真壓縮圖片格式。我們可以用工具將前面的Bitmap轉換為PNG。 下面是從上一章

Android檢視繪製流程完全解析,帶你一步步深入瞭解View()

在上一篇文章中,我帶著大家一起剖析了一下LayoutInflater的工作原理,可以算是對View進行深入瞭解的第一步吧。那麼本篇文章中,我們將繼續對View進行深入探究,看一看它的繪製流程到底是什麼樣的。如果你還沒有看過我的上一篇文章,可以先去閱讀 Android Layo

Zabbix監控平臺深入瞭解

Zabbix監控(二)深入瞭解 一,Zabbix Web操作深入 1.1 Zabbix Web下的主機和模版以及監控項的新增方式 1.2 Zabbix Web下觸發器與表示式的編寫方法 1.3 Zabbix Web建立觸發器過程以及觸發器與監控項對應關係 1.4

Android 深入瞭解相簿內部

      通過上篇部落格我們知道了是系統對外暴露出來的ContentProvider來獲取資料庫中的圖片資訊的,使我們知道了如何去實現一個簡單的相簿了,而不是僅僅去跳轉到系統中去做處理了,這麼方便的操作極大的滿足了我們平常的開發的一些特殊的需求。但是我們在實現

Android LayoutInflater原理分析,帶你一步步深入瞭解View

有段時間沒寫部落格了,感覺都有些生疏了呢。最近繁忙的工作終於告一段落,又有時間寫文章了,接下來還會繼續堅持每一週篇的節奏。 有不少朋友跟我反應,都希望我可以寫一篇關於View的文章,講一講View的工作原理以及自定義View的方法。沒錯,承諾過的文章我是一定要兌現的,而且在View這個話題上我還

Android 四大元件之——Acitivity(三) 深入瞭解Activity的啟動流程

上圖為整個Activity的啟動流程 接下來我們大概分析  在我們的Android系統中,應用程式是由Launcher這個應用啟動起來的。當我們安裝好應用程式之後,就會在Launcher的介面上生成一個圖示,我們點選圖示時Launch就會啟動我們的應用程式。 1.點選

android睡眠喚醒 】MTK平臺喚醒框架分解

    在文章MTK 喚醒時間分析中分析了核心中的主要的亮屏重要階段,此篇文章結合上層的log一起來分析下整個系統的亮屏流程。整個流程可以分為如下幾個部分:   (1)power鍵(home鍵)產生並上報(在input子系統中已經介紹);   (2)上層接收到到鍵值,Po

、Java虛擬機器自動記憶體管理機制、執行時資料區域深入瞭解

執行時資料區域:     (1)、程式計數器         a、定義:是一塊較小的記憶體空間,可以看作是當前執行緒所執行的位元組碼的行號指示器。         b、執行緒私有:因為多執行緒是通過執行緒輪流切換並且分配處理器執行時間的方式來實現的,任何時刻,        

Zabbix監控平臺深入理解zabbix

一,Zabbix Web操作深入   1.1 Zabbix Web下的主機和模版以及監控項的新增方式   (1)建立一個模版 我們所有的功能幾乎都是在模版中定義的 我們再點進新建立的模版檢視 模版裡幾乎可以設定我們需要的所有功能

擁抱 Android Studio 之Android Studio 與 Gradle 深入

關於學習方式 曾經跟朋友討論過我們所接受過的大學工科教育,都是一上來先學基礎理論,最後再來一個金工實習。一開始不知道為什麼而學,學不進去,荒廢了基礎,等到金工實習的時候,又發現基礎不牢,後悔不已。 考慮到傳統教育方式的不足之處,筆者在組織本系列文章的時候是先講入門例項,進而

Android自定義View的實現方法,帶你一步步深入瞭解View(四)

不知不覺中,帶你一步步深入瞭解View系列的文章已經寫到第四篇了,回顧一下,我們一共學習了LayoutInflater的原理分析、檢視的繪製流程、檢視的狀態及重繪等知識,算是把View中很多重要的知識點都涉及到了。如果你還沒有看過我前面的幾篇文章,建議先去閱讀一下,多瞭解一些

Android自定義View的實現方法 帶你一步步深入瞭解View 四

                不知不覺中,帶你一步步深入瞭解View系列的文章已經寫到第四篇了,回顧一下,我們一共學習了LayoutInflater的原理分析、檢視的繪製流程、檢視的狀態及重繪等知識,算是把View中很多重要的知識點都涉及到了。如果你還沒有看過我前面的幾篇文章,建議先去閱讀一下,多瞭解一些原

Android平臺讀寫i2c裝置開發筆記

二、 使用JNI在應用程式框架層新增服務訪問介面        APP應用不能直接訪問HAL層,需要JNI層訪問HAL模組並向上提供API介面。可以直接提供介面,但建議最好使用服務的方式提供訪問。        我們先看JNI如何訪問剛才的HAL模組。        進入原