簡介 - 這東西是從哪里來的呢?
Android.bp 是 Android 編譯系統(tǒng)從 make 系統(tǒng)切換到 ninja 系統(tǒng)過程中的產(chǎn)物,Android 7.0 和 8.0 是該編譯系統(tǒng)切換的過渡期,所以在 Android 7.0 和 8.0 時既可以看到 Android.mk,也可以看到 Android.bp,但是從 Android 9.0 開始,在Android 源碼里面 Android.mk 已經(jīng)看不到了,只有少數(shù) Vendor 廠家的代碼里面還可以看到。
這次切換的背后原因是,Android 要提升編譯效率,顯著提升的是第一次編譯后增量編譯的速度,但是由于 Android 工程越來越龐大,這個效率很難被大家感受到。
內(nèi)容 - 這東西內(nèi)容長啥樣呢?
以 hardware/libhardware/Android.bp 為例,其內(nèi)容與 json 文件非常類似,實際上也是一種更加簡潔的編譯配置文件,相比 Android.mk,可閱讀性更強,但是前提是有很好的 Android.bp 語法基礎(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 長下面這樣:
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)
語法 - 怎么閱讀呢?
語法是這樣的(多數(shù)內(nèi)容來自 Android 官網(wǎng)介紹):
模塊
Android.bp 文件中的模塊以模塊類型開頭,后跟一組 name: "value", 格式的屬性:
cc_binary {
name: "gzip",
srcs: ["src/test/minigzip.c"],
shared_libs: ["libz"],
stl: "none",
}
每個模塊都必須具有 name 屬性,并且相應(yīng)值在所有 name 文件中必須是唯一的,僅有兩個例外情況是命名空間和預(yù)構(gòu)建模塊中的 Android.bp 屬性值,這兩個值可能會重復(fù)。
srcs 屬性以字符串列表的形式指定用于構(gòu)建模塊的源文件。您可以使用模塊引用語法 ":<module-name>" 來引用生成源文件的其他模塊的輸出,如 genrule 或 filegroup。
如需有效模塊類型及其屬性的列表,請參閱 Soong 模塊參考。
類型
變量和屬性是強類型,變量根據(jù)第一項賦值動態(tài)變化,屬性由模塊類型靜態(tài)設(shè)置。支持的類型為:
布爾值(true 或 false)
整數(shù) (int)
字符串 ("string")
字符串列表 (["string1", "string2"])
映射 ({key1: "value1", key2: ["value2"]})
映射可以包含任何類型的值,包括嵌套映射。列表和映射可能在最后一個值后面有終止逗號。
Glob
接受文件列表的屬性(例如 srcs)也可以采用 glob 模式。glob 模式可以包含普通的 UNIX 通配符 ,例如 .java。glob 模式還可以包含單個 ** 通配符作為路徑元素,與零個或多個路徑元素匹配。例如,java//*.java 同時匹配 java/Main.java 和 java/com/android/Main.java 模式。
變量
Android.bp 文件可能包含頂級變量賦值:
gzip_srcs = ["src/test/minigzip.c"],
cc_binary {
name: "gzip",
srcs: gzip_srcs,
shared_libs: ["libz"],
stl: "none",
}
變量的作用域限定在聲明它們的文件的其余部分,以及所有子 Blueprint 文件。變量是不可變的,但有一個例外情況:可以使用 += 賦值將變量附加到別處,但只能在引用它們之前附加。
注釋
Android.bp 文件可以包含 C 樣式的多行 /* */ 注釋以及 C++ 樣式的單行 // 注釋。
運算符
可以使用 + 運算符附加字符串、字符串列表和映射??梢允褂?+ 運算符對整數(shù)求和。附加映射會生成兩個映射中鍵的并集,并附加在兩個映射中都存在的所有鍵的值。
條件語句
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"],
},
},
}
格式設(shè)置工具
Soong 包含一個針對 Blueprint 文件的規(guī)范格式設(shè)置工具,類似于 gofmt。如需以遞歸方式重新設(shè)置當(dāng)前目錄中所有 Android.bp 文件的格式,請運行以下命令:
bpfmt -w .
規(guī)范格式包括縮進四個空格、多元素列表的每個元素后面有換行符,以及列表和映射末尾有英文逗號。
特殊模塊
一些特殊模塊組具有獨特的特征。
默認模塊
默認模塊可用于在多個模塊中重復(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)建的模塊類型允許模塊與其基于源代碼的對應(yīng)模塊具有相同的名稱。例如,如果已有同名的 cc_binary,也可以將 cc_prebuilt_binary 命名為 foo。這讓開發(fā)者可以靈活地選擇要納入其最終產(chǎn)品中的版本。如果 build 配置包含兩個版本,那么預(yù)編譯模塊定義中的 prefer 標志值會指示哪個版本具有優(yōu)先級。請注意,某些預(yù)編譯模塊的名稱不能以 prebuilt 開頭,例如 android_app_import。
命名空間模塊
在 Android 完全從 Make 轉(zhuǎn)換為 Soong 之前,Make 產(chǎn)品配置必須指定 PRODUCT_SOONG_NAMESPACES 值。它的值應(yīng)該是一個以空格分隔的列表,其中包含 Soong 導(dǎo)出到 Make 以使用 m 命令進行編譯的命名空間。在 Android 完成到 Soong 的轉(zhuǎn)換之后,啟用命名空間的詳細信息可能會發(fā)生變化。
Soong 可以讓不同目錄中的模塊指定相同的名稱,只要每個模塊都在單獨的命名空間中聲明即可??梢园慈缦路绞铰暶髅臻g:
soong_namespace {
imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}
請注意,命名空間沒有 name 屬性;其路徑會自動指定為其名稱。
系統(tǒng)會根據(jù)每個 Soong 模塊在樹中的位置為其分配命名空間。每個 Soong 模塊都會被視為處于 Android.bp(位于當(dāng)前目錄或最近的父級目錄中的 soong_namespace 文件內(nèi))定義的命名空間中。如果未找到此類 soong_namespace 模塊,則認為該模塊位于隱式根命名空間中。
下面是一個示例:Soong 嘗試解析由模塊 M 在名稱空間 N(導(dǎo)入命名空間 I1、I2、I3…)中聲明的依賴項 D。
- 如果 D 是 //namespace:module 格式的完全限定名稱,系統(tǒng)將僅在指定的命名空間中搜索指定的模塊名稱。
- 否則,Soong 將首先查找在命名空間 N 中聲明的名為 D 的模塊。
- 如果該模塊不存在,Soong 會在命名空間 I1、I2、I3…中查找名為 D 的模塊。
- 最后,Soong 在根命名空間中查找。
舉個栗子,實際解析一下
以 frameworks/native/services/surfaceflinger/Android.bp 的前 1/3 內(nèi)容為例。
cc_defaults { // 到這個鏈接里面查一下,
// 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", // 這個 module 的名字是 surfaceflinger_defaults,字符串類型。
cflags: [ // 這是 gcc 的編譯選項,不懂的話,可以參考下面鏈接:
// https://blog.csdn.net/shenhuxi_yu/article/details/79788760。
"-DLOG_TAG=\"SurfaceFlinger\"",
"-Wall",
"-Werror",
"-Wthread-safety",
"-Wunused",
"-Wunreachable-code",
],
cppflags: ["-std=c++1z"], // 這是 g++ 的編譯選項。
}
cc_defaults { // 類型是 cc_defaults。
name: "libsurfaceflinger_defaults", // 名字是 libsurfaceflinger_defaults
defaults: ["surfaceflinger_defaults"], // 從 surfaceflinger_defaults 繼承。
cflags: [ // gcc 編譯選項。
"-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",
],
}