Soong 編譯系統(tǒng)
在 Android 7.0 發(fā)布之前偷霉,Android 僅使用 GNU Make 描述和執(zhí)行其構(gòu)建規(guī)則沸移。Make 構(gòu)建系統(tǒng)得到了廣泛的支持和使用婉烟,但在 Android 層面變得緩慢、容易出錯沪伙、無法擴展且難以測試户辞。Soong 構(gòu)建系統(tǒng)正好提供了 Android build 所需的靈活性翔横。
Soong 構(gòu)建系統(tǒng)是在 Android 7.0 (Nougat) 中引入的,旨在取代 Make啊掏。它利用 Kati GNU Make 克隆工具和 Ninja 構(gòu)建系統(tǒng)組件來加速 Android 的構(gòu)建蠢络。
Android.bp文件格式
Android.bp的語法在設(shè)計上要比Android.mk簡單一些,主要是因為Android.bp沒有條件或控制流語句迟蜜。
注意:Android.bp不支持條件語句刹孔!在實際項目中,如果構(gòu)建的腳本必須包含條件語句娜睛,建議使用Android.mk或使用Go語言
模塊與示例
Android.bp 文件中的模塊以模塊類型
開頭髓霞,然后是一組格式屬性:name: value
卦睹,在一點上Android.bp的語法結(jié)構(gòu)與JSON的語法結(jié)構(gòu)相似,都是以鍵值對的形式編寫方库。下面是一個簡單示例:
android_app {
name: "Provision",
srcs: ["**/*.java"],
platform_apis: true,
product_specific: true,
certificate: "platform",
}
每個模塊都必須具有 name
屬性结序,并且相應(yīng)值在所有 name
文件中必須是唯一的,僅有兩個例外情況是命名空間和預(yù)構(gòu)建模塊中的 Android.bp
屬性值纵潦,這兩個值可能會重復(fù)徐鹤。
srcs
屬性以字符串列表的形式指定用于構(gòu)建模塊的源文件±掖可以使用模塊引用語法 ":<module-name>"
來引用生成源文件的其他模塊的輸出凳干,如 genrule
或 filegroup
。
android_app{}
表示該模塊用于構(gòu)建一個apk
name: "Provision",
如果指定了 android_app
模塊類型(在代碼塊的開頭)被济,就需要設(shè)定該模塊的name
救赐。此設(shè)置會為模塊命名,生成的 APK 將與模塊名稱相同只磷,不過帶有 .apk
后綴经磅。例如,在本例中钮追,生成的 APK 將命名為 Provision.apk
srcs: ["**/*.java"],
srcs
用于指定當(dāng)前的模塊編譯的源碼位置预厌,*表示通配符
platform_apis: true,
設(shè)置該標(biāo)記后會使用sdk的hide的api來編譯。編譯的APK中使用了系統(tǒng)級API元媚,必須設(shè)定該值轧叽。和Android.mk中的LOCAL_PRIVATE_PLATFORM_APIS
的作用相同
product_specific: true,
設(shè)置該標(biāo)記后,生成的apk會被安裝在Android系統(tǒng)的product分區(qū)刊棕,和Android.mk中LOCAL_PRODUCT_MODULE
作用相同
certificate: "platform",
certificate
用于指定APK的簽名方式炭晒。如果不指定,默認(rèn)使用testkey簽名甥角。與LOCAL_CERTIFICATE
作用相同网严。
Android中共有四中簽名方式:
- testkey:普通APK,默認(rèn)使用該簽名嗤无。
- platform:該APK完成一些系統(tǒng)的核心功能震束。經(jīng)過對系統(tǒng)中存在的文件夾的訪問測試,這種方式編譯出來的APK所在進程的UID為system当犯。
- shared:該APK需要和home/contacts進程共享數(shù)據(jù)垢村。
- media:該APK是media/download系統(tǒng)中的一環(huán)。
常見模塊類型
在Android.bp中我們會基于模塊類型來構(gòu)建我們所需要的東西嚎卫,常用的有以下幾種類型
android_app
用于構(gòu)建Android 應(yīng)用程序安裝包肝断,是Android系統(tǒng)應(yīng)用開發(fā)中常用的模塊類型,與Android.mk中的BUILD_PACKAGE
作用相同。
android_app_certificate
android_app_certificate
模塊可由android_app
模塊的證書屬性certificate
引用以選擇簽名密鑰胸懈。
java_library
java_library
用于將源代碼構(gòu)建并鏈接到設(shè)備的.jar
文件中担扑。默認(rèn)情況下,java_library
只有一個變量趣钱,它生成一個包含根據(jù)設(shè)備引導(dǎo)類路徑編譯的.class
文件的.jar
包涌献。生成的jar不適合直接安裝在設(shè)備上,通過會用作另一個模塊的static_libs
依賴項首有。
如果指定“installable:true”將生成一個包含“classes.dex”文件的“.jar”文件燕垃,適合在設(shè)備上安裝。指定'host_supported:true'將產(chǎn)生兩個變量井联,一個根據(jù)device的bootclasspath編譯卜壕,另一個根據(jù)host的bootclasspath編譯。
java_library_static
java_library_static
作用等同于java_library
烙常,但是java_library_static
已經(jīng)過時轴捎,不推薦使用
android_library
android_library
將源代碼與android資源文件一起構(gòu)建并鏈接到設(shè)備的“.jar”文件中。android_library有一個單獨的變體蚕脏,它生成一個包含根據(jù)device的bootclasspath編譯的.class
文件的.jar
文件侦副,以及一個包含使用aapt2編譯的android資源的.package-res.apk
文件。生成的apk文件不能直接安裝在設(shè)備上驼鞭,但可以用作android_app
模塊的static_libs
依賴項秦驯。
cc_library
cc_library
為device或host創(chuàng)建靜態(tài)庫或共享庫。默認(rèn)情況下挣棕,cc_library
具有針對設(shè)備的單一變體译隘。指定'host_supported:true'還會創(chuàng)建一個以主機為目標(biāo)的庫。與cc_library相關(guān)的模塊類型還有cc_library_shared
洛心、cc_library_headers
固耘、cc_library_static
等。
Android.bp中涉及到的模塊類型非常的多皂甘,我們可以在Soong模塊和屬性列表中查看其它的模塊類型以及用法。
設(shè)置變量
在bp中可以通過=
號來設(shè)定一個全局變量
src_path = ["**/*.java"]
android_app {
name: "Provision",
srcs: src_path,
platform_apis: true,
product_specific: true,
certificate: "platform",
}
默認(rèn)模塊
soong提供了一系列xx_defaults模塊類型悼凑,例如:cc_defaults
, java_defaults
, doc_defaults
, stubs_defaults
等等偿枕。
xx_defaults
的模塊提供了一組可由其它模塊繼承的屬性。其它模塊可以通過defaults:["<:default_module_name>"]來繼承xx_defaults類型模塊中定義的屬性户辫。xxx_defaults類型的模塊可以被多個模塊繼承渐夸,減少我們在bp中書寫重復(fù)的屬性。
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)設(shè)置。支持的類型為:
布爾值(
true
或false
)整數(shù) (
int
)字符串(
"string"
)字符串列表 (
["string1", "string2"]
)映射 (
{key1: "value1", key2: ["value2"]}
)
映射可以包含任何類型的值,包括嵌套映射苫幢。
條件語句
Soong 不支持 Android.bp
文件中的條件語句访诱。編譯規(guī)則中需要條件語句的復(fù)雜問題將在 Go(在這種語言中,您可以使用高級語言功能韩肝,并且可以跟蹤條件語句引入的隱式依賴項)中處理触菜。大多數(shù)條件語句都會轉(zhuǎn)換為映射屬性,其中選擇了映射中的某個值并將其附加到頂級屬性哀峻。
例如涡相,要支持特定于架構(gòu)的文件,可以使用以下命令:
cc_library {
...
srcs: ["generic.cpp"],
arch: {
arm: {
srcs: ["arm.cpp"],
},
x86: {
srcs: ["x86.cpp"],
},
},
}
注意:Android.bp不支持條件語句剩蟀!在實際項目中催蝗,如果構(gòu)建的腳本必須包含條件語句,建議使用Android.mk
運算符
可以使用 + 運算符附加字符串育特、字符串列表和映射丙号。可以使用 +
運算符對整數(shù)求和且预。附加映射會生成兩個映射中鍵的并集槽袄,并附加在兩個映射中都存在的所有鍵的值。
注釋
Android.bp文件可以和C/C++的注釋類似锋谐,可以包含多行注釋和單行注釋遍尺。
- 多行注釋:/ * 注釋 * /
- 單行注釋://注釋。
關(guān)于Android.bp還有一些其它的基礎(chǔ)知識涮拗,請繼續(xù)參閱Soong 編譯系統(tǒng)
使用示例
關(guān)于Android.bp如何使用乾戏,我們可以參考系統(tǒng)中已有模塊的是如何編寫的。
該Android.bp位于Android 10 : packages/apps/Car/Notification 下
// 構(gòu)建可執(zhí)行程序
android_app {
// 設(shè)定可執(zhí)行的程序的名稱三热,編譯后會生成一個 CarNotification.apk
name: "CarNotification",
// 指定java源碼的位置
srcs: ["src/**/*.java"],
// 指定資源文件的位置
resource_dirs: ["res"],
// 允許使用系統(tǒng)hide api
platform_apis: true,
// 設(shè)定apk簽名為 platform
certificate: "platform",
// 設(shè)定apk安裝路徑為priv-app
privileged: true,
// 是否啟用代碼優(yōu)化鼓择,android_app中默認(rèn)為true,java_library中默認(rèn)為false
optimize: {
enabled: false,
},
// 是否預(yù)先生成dex文件就漾,默認(rèn)為true呐能。該屬性會影響應(yīng)用的首次啟動速度以及Android系統(tǒng)的啟動速度
dex_preopt: {
enabled: false,
},
// 引入java靜態(tài)庫
static_libs: [
"androidx.cardview_cardview",
"androidx.recyclerview_recyclerview",
"androidx.palette_palette",
"car-assist-client-lib",
"android.car.userlib",
"androidx-constraintlayout_constraintlayout"
],
// 引入java庫
libs: ["android.car"],
product_variables: {
pdk: {
enabled: false,
},
},
// 設(shè)定依賴模塊。如果安裝了此模塊抑堡,則要還需要安裝的其他模塊的名稱
required: ["privapp_whitelist_com.android.car.notification"]
}
// As Lib
android_library {
name: "CarNotificationLib",
srcs: ["src/**/*.java"],
resource_dirs: ["res"],
manifest: "AndroidManifest-withoutActivity.xml",
platform_apis: true,
optimize: {
enabled: false,
},
dex_preopt: {
enabled: false,
},
static_libs: [
"androidx.cardview_cardview",
"androidx.recyclerview_recyclerview",
"androidx.palette_palette",
"car-assist-client-lib",
"android.car.userlib",
"androidx-constraintlayout_constraintlayout"
],
libs: ["android.car"],
product_variables: {
pdk: {
enabled: false,
},
},
}
常見疑問
Android.bp引用Android.mk編譯的模塊
Android.bp編譯的模塊無法訪問到Android.mk編譯的模塊摆出!相反,Android.mk可以引用Android.bp編譯的模塊首妖。
引入第三方j(luò)ar
在實際開發(fā)中偎漫,我們經(jīng)常需要在app中引入第三方的jar,在Android.bp中有缆,可以按照下面的方式引入象踊。在項目的根目錄新建 libs文件夾温亲,放入要導(dǎo)入的jar包,比如 CarServicelib.jar杯矩,然后在Android.bp中引入該jar
java_import {
name: "CarServicelib.jar",
jars: ["libs/CarServicelib.jar"],
}
android_app {
// 省去其它屬性
// 引入AndroidX庫下的lib
static_libs: [
"CarServicelib.jar"
],
}
引入AndroidX庫
開發(fā)過程如果想要引入AndroidX的類庫可以參考下面的方式編寫栈虚。
android_app {
// 省去其它屬性
// 引入AndroidX庫下的lib
static_libs: [
"androidx.cardview_cardview",
"androidx.recyclerview_recyclerview",
"androidx-constraintlayout_constraintlayout"
],
}
參考資料
Soong 編譯系統(tǒng) | Android 開源項目 | Android Open Source Project (google.cn)