Android.mk
LOCAL_PATH:= $(call my-dir)
#清理緩存變量
include $(CLEAR_VARS)
#表示目標模式
LOCAL_MODULE_TAGS := samples
#表示源文件編譯路徑 這個應用里面只有java源文件
LOCAL_SRC_FILES := $(call all-java-files-under, src)
#表示項目包名也就是模塊名,在項目中唯一
LOCAL_PACKAGE_NAME := HelloWorld
#指定編譯sdk版本為當前版本
LOCAL_SDK_VERSION := current
# 使用該指令編譯目標Apk.
include $(BUILD_PACKAGE)
#搜索編譯該源碼目錄下所有的mk文件臣樱,如果沒有可以不寫
include $(call all-makefiles-under,$(LOCAL_PATH))
簡化
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)
一般看到這種帶下劃線的我們就會想到配置系統(tǒng)環(huán)境變量,何況這里還帶有明顯的路徑名稱。沒錯小伙子你很上道啊雇毫,你已經(jīng)有開發(fā)者的直覺了玄捕。
LOCAl_PATH這好像是在指明什么路徑。
:= 做開發(fā)的同學怎么看都覺得這像是賦值語句像但是又不完全像棚放。
$(call my-dir)好像是去的系統(tǒng)值并把系統(tǒng)環(huán)境變量中的什么位置枚粘,或者文件位置賦值給LOCAL_PATH。
答案
Android.mk 文件必須先定義 LOCAL_PATH 變量:
LOCAL_PATH := $(call my-dir)
此變量表示源文件在開發(fā)樹中的位置飘蚯。在這行代碼中馍迄,編譯系統(tǒng)提供的宏函數(shù) my-dir 將返回當前目錄(Android.mk 文件本身所在的目錄)的路徑。
下一行
include $(CLEAR_VARS)
這一行學C語言的小伙伴大驚引包局骤,include好像是引包的意思吧攀圈,沒好好學c希望學c的小伙伴看到我的錯我能糾正一下我。
在繼續(xù)看好像是引用了一個什么清除的包庄涡。
答案
這一行聲明 CLEAR_VARS 變量量承,其值由編譯系統(tǒng)提供。
CLEAR_VARS 變量指向一個特殊的 GNU Makefile穴店,后者會清除許多 LOCAL_XXX 變量撕捍,例如 LOCAL_MODULE、LOCAL_SRC_FILES 和 LOCAL_STATIC_LIBRARIES泣洞。請注意忧风,GNU Makefile 不會清除 LOCAL_PATH。此變量必須保留其值球凰,因為系統(tǒng)在單一 GNU Make 執(zhí)行環(huán)境(其中的所有變量都是全局變量)中解析所有編譯控制文件狮腿。在描述每個模塊之前,必須聲明(重新聲明)此變量呕诉。
LOCAL_MODULE := hello-jni
每個模塊名稱必須唯一缘厢,且不含任何空格。編譯系統(tǒng)在生成最終共享庫文件時甩挫,會對您分配給 LOCAL_MODULE 的名稱自動添加正確的前綴和后綴贴硫。例如,上述示例會生成名為 libhello-jni.so的庫伊者。
注意:如果模塊名稱的開頭已經(jīng)是 lib英遭,則編譯系統(tǒng)不會附加額外的 lib 前綴;而是按原樣采用模塊名稱亦渗,并添加 .so 擴展名挖诸。因此,比如原來名為 libfoo.c 的源文件仍會生成名為 libfoo.so 的共享對象文件法精。此行為是為了支持 Android 平臺源文件根據(jù) Android.mk 文件生成的庫多律;所有這些庫的名稱都以 lib 開頭痴突。
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SRC_FILES 變量必須包含要編譯到模塊中的 C 和/或 C++ 源文件列表。這句話的意思就是說菱涤,我這個工程的源碼路徑只有一個文件苞也,這個文件就是我這個MK文件所在目錄下的hello-jni.c
include $(BUILD_SHARED_LIBRARY)
當前模塊在靜態(tài)鏈接時需要的庫的名稱洛勉。
Android.bp
Android.bp文件是什么
Android.bp文件首先是Android系統(tǒng)的一種編譯配置文件粘秆,是用來代替原來的Android.mk文件的。在Android7.0以前收毫,Android都是使用make來組織各模塊的編譯攻走,對應的編譯配置文件就是Android.mk。在Android7.0開始此再,Google引入了ninja和kati來編譯昔搂,為啥引入ninja?因為隨著Android越來越龐大输拇,module越來越多摘符,編譯時間也越來越久,而使用ninja在編譯的并發(fā)處理上較make有很大的提升策吠。Ninja的配置文件就是Android.bp逛裤,Android系統(tǒng)使用Blueprint和Soong工具來解析Android.bp轉(zhuǎn)換生成ninja文件。為了兼容老的mk配置文件猴抹,Android當初也開發(fā)了Kati 工具來轉(zhuǎn)換mk文件生成ninja带族,目前Android Q里邊,還是支持Android.mk方式的蟀给。相信在將來的版本中蝙砌,會徹底讓mk文件廢棄,同時Kati也就淘汰了跋理,只保留bp配置方式择克,所以我們要提前學習bp。Blueprint和Soong工具的源碼在Android/build/目錄下前普,我們可以通過查閱相關代碼來學習肚邢!
上面是我引用的別人的說法.
image.png
語法初探
cc_library_shared { //編譯成動態(tài)庫,類似于Android.mk中的BUILD_SHARED_LIBRARY
name: "libbluetooth_jni", //編譯出的模塊的名稱汁政,類似于Android.mk中的LOCAL_MODULE
srcs: [ //源文件道偷,類似于Android.mk中的LOCAL_SRC_FILES
"com_android_bluetooth_btservice_AdapterService.cpp",
"com_android_bluetooth_hfp.cpp",
"com_android_bluetooth_hfpclient.cpp",
"com_android_bluetooth_a2dp.cpp",
"com_android_bluetooth_a2dp_sink.cpp",
"com_android_bluetooth_avrcp.cpp",
"com_android_bluetooth_avrcp_controller.cpp",
"com_android_bluetooth_hid.cpp",
"com_android_bluetooth_hidd.cpp",
"com_android_bluetooth_hdp.cpp",
"com_android_bluetooth_pan.cpp",
"com_android_bluetooth_gatt.cpp",
"com_android_bluetooth_sdp.cpp",
],
include_dirs: [ //用戶指定的頭文件查找路徑,類似于Android.mk中的LOCAL_C_INCLUDES
"libnativehelper/include/nativehelper",
"system/bt/types",
],
shared_libs: [ //編譯所依賴的動態(tài)庫记劈,類似于Android.mk中的LOCAL_SHARED_LIBRARIES
"libandroid_runtime",
"libchrome",
"libnativehelper",
"libcutils",
"libutils",
"liblog",
"libhardware",
],
static_libs: [ //編譯所依賴的靜態(tài)庫勺鸦,類似于Android.mk中的LOCAL_STATIC_LIBRARIES
"libbluetooth-types",
],
cflags: [ ///編譯flag,類似于Android.mk中的LOCAL_CFLAGS
"-Wall",
"-Wextra",
"-Wno-unused-parameter",
],
}
模塊與示例
Android.bp 文件中的模塊以模塊類型開頭,然后是一組格式屬性:name: value目木,在一點上Android.bp的語法結構與JSON的語法結構相似换途,都是以鍵值對的形式編寫懊渡。下面是一個簡單示例:
android_app {
name: "Provision",
srcs: ["**/*.java"],
platform_apis: true,
product_specific: true,
certificate: "platform",
}
那么接下來逐行分析這段代碼
android_app {
}
表示該模塊用于構建一個apk
name: "Provision",
如果指定了 android_app 模塊類型(在代碼塊的開頭),就需要設定該模塊的name 军拟。此設置會為模塊命名剃执,生成的 APK 將與模塊名稱相同,不過帶有 .apk 后綴懈息。例如肾档,在本例中,生成的 APK 將命名為 Provision.apk
srcs: ["**/*.java"],
srcs用于指定當前的模塊編譯的源碼位置辫继,*表示通配符
platform_apis: true,
設置該標記后會使用sdk的hide的api來編譯怒见。編譯的APK中使用了系統(tǒng)級API,必須設定該值姑宽。和Android.mk中的LOCAL_PRIVATE_PLATFORM_APIS的作用相同
certificate: "platform",
Android中共有四中簽名方式:
1.testkey:普通APK遣耍,默認使用該簽名。
2.platform:該APK完成一些系統(tǒng)的核心功能炮车。經(jīng)過對系統(tǒng)中存在的文件夾的訪問測試舵变,這種方式編譯出來的APK所在進程的UID為system。
3.shared:該APK需要和home/contacts進程共享數(shù)據(jù)瘦穆。
4.media:該APK是media/download系統(tǒng)中的一環(huán)纪隙。
常見的模塊類型
android_app
1.用于構建Android 應用程序安裝包,是Android系統(tǒng)應用開發(fā)中常用的模塊類型难审,與Android.mk中的BUILD_PACKAGE作用相同瘫拣。
java_library
2.java_library用于將源代碼構建并鏈接到設備的.jar文件中。默認情況下告喊,java_library只有一個變量麸拄,它生成一個包含根據(jù)設備引導類路徑編譯的.class文件的.jar包。生成的jar不適合直接安裝在設備上黔姜,通過會用作另一個模塊的static_libs依賴項拢切。
如果指定“installable:true”將生成一個包含“classes.dex”文件的“.jar”文件,適合在設備上安裝秆吵。指定'host_supported:true'將產(chǎn)生兩個變量淮椰,一個根據(jù)device的bootclasspath編譯,另一個根據(jù)host的bootclasspath編譯纳寂。
java_library_static
3.java_library_static作用等同于java_library主穗,但是java_library_static已經(jīng)過時,不推薦使用
android_library
4.android_library將源代碼與android資源文件一起構建并鏈接到設備的“.jar”文件中毙芜。android_library有一個單獨的變體忽媒,它生成一個包含根據(jù)device的bootclasspath編譯的.class文件的.jar文件,以及一個包含使用aapt2編譯的android資源的.package-res.apk文件腋粥。生成的apk文件不能直接安裝在設備上晦雨,但可以用作android_app模塊的static_libs依賴項架曹。
cc_library
5.cc_library為device或host創(chuàng)建靜態(tài)庫或共享庫。默認情況下闹瞧,cc_library具有針對設備的單一變體绑雄。指定'host_supported:true'還會創(chuàng)建一個以主機為目標的庫。與cc_library相關的模塊類型還有cc_library_shared奥邮、cc_library_headers万牺、cc_library_static等。
設置變量
在bp中可以通過=號來設定一個全局變量
src_path = ["**/*.java"]
android_app {
name: "Provision",
srcs: src_path,
platform_apis: true,
product_specific: true,
certificate: "platform",
}
默認模塊
soong提供了一系列xx_defaults模塊類型漠烧,例如:cc_defaults, java_defaults, doc_defaults, stubs_defaults等等杏愤。
xx_defaults的模塊提供了一組可由其它模塊繼承的屬性。其它模塊可以通過defaults:["<:default_module_name>"]來繼承xx_defaults類型模塊中定義的屬性已脓。xxx_defaults類型的模塊可以被多個模塊繼承,減少我們在bp中書寫重復的屬性通殃。
cc_defaults {
name: "gzip_defaults",
shared_libs: ["libz"],
stl: "none",
}
cc_binary {
name: "gzip",
defaults: ["gzip_defaults"],
srcs: ["src/test/minigzip.c"],
}
數(shù)據(jù)類型
Android.bp中變量和屬性是強類型度液,變量根據(jù)第一項賦值動態(tài)變化,屬性由模塊類型靜態(tài)設置画舌。支持的類型為:
1.布爾值(true或 false)
2.整數(shù) (int)
3.字符串("string")
4.字符串列表 (["string1", "string2"])
5.映射 ({key1: "value1", key2: ["value2"]})
映射可以包含任何類型的值堕担,包括嵌套映射