簡(jiǎn)介 - 這東西是從哪里來(lái)的呢验游?
Android.bp 是 Android 編譯系統(tǒng)從 make 系統(tǒng)切換到 ninja 系統(tǒng)過(guò)程中的產(chǎn)物,Android 7.0 和 8.0 是該編譯系統(tǒng)切換的過(guò)渡期保檐,所以在 Android 7.0 和 8.0 時(shí)既可以看到 Android.mk耕蝉,也可以看到 Android.bp,但是從 Android 9.0 開始夜只,在Android 源碼里面 Android.mk 已經(jīng)看不到了垒在,只有少數(shù) Vendor 廠家的代碼里面還可以看到。
這次切換的背后原因是扔亥,Android 要提升編譯效率场躯,顯著提升的是第一次編譯后增量編譯的速度,但是由于 Android 工程越來(lái)越龐大旅挤,這個(gè)效率很難被大家感受到踢关。
內(nèi)容 - 這東西內(nèi)容長(zhǎng)啥樣呢?
以 hardware/libhardware/Android.bp 為例粘茄,其內(nèi)容與 json 文件非常類似签舞,實(shí)際上也是一種更加簡(jiǎn)潔的編譯配置文件,相比 Android.mk柒瓣,可閱讀性更強(qiáng)儒搭,但是前提是有很好的 Android.bp 語(yǔ)法基礎(chǔ)。
cc_library_shared {
name: “l(fā)ibxmlrpc++”,
rtti: true,
cppflags: [
“-Wall”,
“-Werror”,
“-fexceptions”,
],
export_include_dirs: [“src”],
srcs: [“src/**/*.cpp”],
target: {
darwin: {
enabled: false,
},
},
}
相同的 Android.mk 長(zhǎng)下面這樣:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libxmlrpc++
LOCAL_MODULE_HOST_OS := linux
LOCAL_RTTI_FLAG := -frtti
LOCAL_CPPFLAGS := -Wall -Werror -fexceptions
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/src
LOCAL_SRC_FILES := $(call \
all-cpp-files-under,src)
include $(BUILD_SHARED_LIBRARY)
語(yǔ)法 - 怎么閱讀呢嘹朗?
語(yǔ)法是這樣的(多數(shù)內(nèi)容來(lái)自 Android 官網(wǎng)介紹):
模塊
Android.bp
文件中的模塊以模塊類型開頭师妙,后跟一組 name: "value",
格式的屬性:
cc_binary {
name: "gzip",
srcs: ["src/test/minigzip.c"],
shared_libs: ["libz"],
stl: "none",
}
每個(gè)模塊都必須具有 name
屬性,并且相應(yīng)值在所有 name
文件中必須是唯一的屹培,僅有兩個(gè)例外情況是命名空間和預(yù)構(gòu)建模塊中的 Android.bp
屬性值默穴,這兩個(gè)值可能會(huì)重復(fù)怔檩。
srcs
屬性以字符串列表的形式指定用于構(gòu)建模塊的源文件。您可以使用模塊引用語(yǔ)法 ":<module-name>"
來(lái)引用生成源文件的其他模塊的輸出蓄诽,如 genrule
或 filegroup
薛训。
如需有效模塊類型及其屬性的列表,請(qǐng)參閱 Soong 模塊參考仑氛。
類型
變量和屬性是強(qiáng)類型乙埃,變量根據(jù)第一項(xiàng)賦值動(dòng)態(tài)變化,屬性由模塊類型靜態(tài)設(shè)置锯岖。支持的類型為:
布爾值(true 或 false)
整數(shù) (int)
字符串 ("string")
字符串列表 (["string1", "string2"])
映射 ({key1: "value1", key2: ["value2"]})
映射可以包含任何類型的值介袜,包括嵌套映射。列表和映射可能在最后一個(gè)值后面有終止逗號(hào)出吹。
Glob
接受文件列表的屬性(例如 srcs)也可以采用 glob 模式遇伞。glob 模式可以包含普通的 UNIX 通配符 ,例如 .java捶牢。glob 模式還可以包含單個(gè) ** 通配符作為路徑元素鸠珠,與零個(gè)或多個(gè)路徑元素匹配。例如秋麸,java//*.java 同時(shí)匹配 java/Main.java 和 java/com/android/Main.java 模式渐排。
變量
Android.bp 文件可能包含頂級(jí)變量賦值:
gzip_srcs = ["src/test/minigzip.c"],
cc_binary {
name: "gzip",
srcs: gzip_srcs,
shared_libs: ["libz"],
stl: "none",
}
變量的作用域限定在聲明它們的文件的其余部分,以及所有子 Blueprint 文件灸蟆。變量是不可變的驯耻,但有一個(gè)例外情況:可以使用 += 賦值將變量附加到別處,但只能在引用它們之前附加次乓。
注釋
Android.bp 文件可以包含 C 樣式的多行 /* */ 注釋以及 C++ 樣式的單行 // 注釋吓歇。
運(yùn)算符
可以使用 + 運(yùn)算符附加字符串、字符串列表和映射票腰〕强矗可以使用 + 運(yùn)算符對(duì)整數(shù)求和。附加映射會(huì)生成兩個(gè)映射中鍵的并集杏慰,并附加在兩個(gè)映射中都存在的所有鍵的值测柠。
條件語(yǔ)句
Soong 不支持 Android.bp 文件中的條件語(yǔ)句。但是缘滥,編譯規(guī)則中需要條件語(yǔ)句的復(fù)雜問(wèn)題將在 Go(在這種語(yǔ)言中轰胁,您可以使用高級(jí)語(yǔ)言功能,并且可以跟蹤條件語(yǔ)句引入的隱式依賴項(xiàng))中處理朝扼。大多數(shù)條件語(yǔ)句都會(huì)轉(zhuǎn)換為映射屬性赃阀,其中選擇了映射中的某個(gè)值并將其附加到頂級(jí)屬性。
例如擎颖,要支持特定于架構(gòu)的文件榛斯,請(qǐng)使用以下命令:
cc_library {
...
srcs: ["generic.cpp"],
arch: {
arm: {
srcs: ["arm.cpp"],
},
x86: {
srcs: ["x86.cpp"],
},
},
}
格式設(shè)置工具
Soong 包含一個(gè)針對(duì) Blueprint 文件的規(guī)范格式設(shè)置工具观游,類似于 gofmt。如需以遞歸方式重新設(shè)置當(dāng)前目錄中所有 Android.bp
文件的格式驮俗,請(qǐng)運(yùn)行以下命令:
bpfmt -w .
規(guī)范格式包括縮進(jìn)四個(gè)空格懂缕、多元素列表的每個(gè)元素后面有換行符,以及列表和映射末尾有英文逗號(hào)王凑。
特殊模塊
一些特殊模塊組具有獨(dú)特的特征搪柑。
默認(rèn)模塊
默認(rèn)模塊可用于在多個(gè)模塊中重復(fù)使用相同的屬性。例如:
cc_defaults {
name: "gzip_defaults",
shared_libs: ["libz"],
stl: "none",
}
cc_binary {
name: "gzip",
defaults: ["gzip_defaults"],
srcs: ["src/test/minigzip.c"],
}
預(yù)編譯的模塊
某些預(yù)構(gòu)建的模塊類型允許模塊與其基于源代碼的對(duì)應(yīng)模塊具有相同的名稱索烹。例如工碾,如果已有同名的 cc_binary,也可以將 cc_prebuilt_binary 命名為 foo术荤。這讓開發(fā)者可以靈活地選擇要納入其最終產(chǎn)品中的版本倚喂。如果 build 配置包含兩個(gè)版本,那么預(yù)編譯模塊定義中的 prefer 標(biāo)志值會(huì)指示哪個(gè)版本具有優(yōu)先級(jí)瓣戚。請(qǐng)注意,某些預(yù)編譯模塊的名稱不能以 prebuilt 開頭焦读,例如 android_app_import子库。
命名空間模塊
在 Android 完全從 Make 轉(zhuǎn)換為 Soong 之前,Make 產(chǎn)品配置必須指定 PRODUCT_SOONG_NAMESPACES 值矗晃。它的值應(yīng)該是一個(gè)以空格分隔的列表仑嗅,其中包含 Soong 導(dǎo)出到 Make 以使用 m 命令進(jìn)行編譯的命名空間。在 Android 完成到 Soong 的轉(zhuǎn)換之后张症,啟用命名空間的詳細(xì)信息可能會(huì)發(fā)生變化仓技。
Soong 可以讓不同目錄中的模塊指定相同的名稱,只要每個(gè)模塊都在單獨(dú)的命名空間中聲明即可俗他〔蹦恚可以按如下方式聲明命名空間:
soong_namespace {
imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}
請(qǐng)注意,命名空間沒(méi)有 name 屬性兆衅;其路徑會(huì)自動(dòng)指定為其名稱地沮。
系統(tǒng)會(huì)根據(jù)每個(gè) Soong 模塊在樹中的位置為其分配命名空間。每個(gè) Soong 模塊都會(huì)被視為處于 Android.bp(位于當(dāng)前目錄或最近的父級(jí)目錄中的 soong_namespace 文件內(nèi))定義的命名空間中羡亩。如果未找到此類 soong_namespace 模塊摩疑,則認(rèn)為該模塊位于隱式根命名空間中。
下面是一個(gè)示例:Soong 嘗試解析由模塊 M 在名稱空間 N(導(dǎo)入命名空間 I1畏铆、I2雷袋、I3…)中聲明的依賴項(xiàng) D。
- 如果 D 是 //namespace:module 格式的完全限定名稱辞居,系統(tǒng)將僅在指定的命名空間中搜索指定的模塊名稱楷怒。
- 否則寨腔,Soong 將首先查找在命名空間 N 中聲明的名為 D 的模塊。
- 如果該模塊不存在率寡,Soong 會(huì)在命名空間 I1迫卢、I2、I3…中查找名為 D 的模塊冶共。
- 最后乾蛤,Soong 在根命名空間中查找。
舉個(gè)栗子捅僵,實(shí)際解析一下
以 frameworks/native/services/surfaceflinger/Android.bp 的前 1/3 內(nèi)容為例家卖。
cc_defaults { // 到這個(gè)鏈接里面查一下,
// https://ci.android.com/builds/submitted/9670465/linux/latest/view/soong_build.html庙楚,
// cc_defaults provides a set of properties that can be inherited by other cc modules. A module
// can use the properties from a cc_defaults using `defaults: ["<:default_module_name>"]`.
// Properties of both modules are merged (when possible) by prepending the default module's values to
// the depending module's values.
// cc_defaults 一般是被繼承的類常用的類型上荡。
name: "surfaceflinger_defaults", // 這個(gè) module 的名字是 surfaceflinger_defaults,字符串類型馒闷。
cflags: [ // 這是 gcc 的編譯選項(xiàng)酪捡,不懂的話,可以參考下面鏈接:
// https://blog.csdn.net/shenhuxi_yu/article/details/79788760纳账。
"-DLOG_TAG=\"SurfaceFlinger\"",
"-Wall",
"-Werror",
"-Wthread-safety",
"-Wunused",
"-Wunreachable-code",
],
cppflags: ["-std=c++1z"], // 這是 g++ 的編譯選項(xiàng)逛薇。
}
cc_defaults { // 類型是 cc_defaults。
name: "libsurfaceflinger_defaults", // 名字是 libsurfaceflinger_defaults
defaults: ["surfaceflinger_defaults"], // 從 surfaceflinger_defaults 繼承疏虫。
cflags: [ // gcc 編譯選項(xiàng)永罚。
"-DGL_GLEXT_PROTOTYPES",
"-DEGL_EGLEXT_PROTOTYPES",
],
shared_libs: [ // list of string, list of shared libraries that provide headers for this binding.
"android.frameworks.vr.composer@1.0",
"android.hardware.configstore-utils",
"android.hardware.configstore@1.0",
"android.hardware.configstore@1.1",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
"android.hardware.power@1.0",
"libbase",
"libbinder",
"libbufferhubqueue",
"libcutils",
"libdl",
"libEGL",
"libfmq",
"libGLESv1_CM",
"libGLESv2",
"libgui",
"libhardware",
"libhidlbase",
"libhidltransport",
"libhwbinder",
"liblayers_proto",
"liblog",
"libpdx_default_transport",
"libprotobuf-cpp-lite",
"libsync",
"libtimestats_proto",
"libui",
"libutils",
"libvulkan",
],
static_libs: [ // list of string, list of static libraries that provide headers for this binding.
"libserviceutils",
"libtrace_proto",
"libvkjson",
"libvr_manager",
"libvrflinger",
],
header_libs: [ // list of string, List of libraries which export include paths required for this module.
"android.hardware.graphics.composer@2.1-command-buffer",
"android.hardware.graphics.composer@2.2-command-buffer",
],
export_static_lib_headers: [ // list of string, list of static libraries to re-export include directories from. Entries must be present in static_libs.
"libserviceutils",
],
export_shared_lib_headers: [ // list of string, list of shared libraries to re-export include directories from. Entries must be present in shared_libs.
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
"libhidlbase",
"libhidltransport",
"libhwbinder",
],
}