刨根問(wèn)底 - 安卓編譯 Android.bp 使用方法

簡(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)引用生成源文件的其他模塊的輸出蓄诽,如 genrulefilegroup薛训。

如需有效模塊類型及其屬性的列表,請(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。

  1. 如果 D 是 //namespace:module 格式的完全限定名稱辞居,系統(tǒng)將僅在指定的命名空間中搜索指定的模塊名稱楷怒。
  2. 否則寨腔,Soong 將首先查找在命名空間 N 中聲明的名為 D 的模塊。
  3. 如果該模塊不存在率寡,Soong 會(huì)在命名空間 I1迫卢、I2、I3…中查找名為 D 的模塊冶共。
  4. 最后乾蛤,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",
    ],
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市卧秘,隨后出現(xiàn)的幾起案子呢袱,更是在濱河造成了極大的恐慌,老刑警劉巖翅敌,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羞福,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡哼御,警方通過(guò)查閱死者的電腦和手機(jī)坯临,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)恋昼,“玉大人看靠,你說(shuō)我怎么就攤上這事∫杭。” “怎么了挟炬?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我谤祖,道長(zhǎng)婿滓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任粥喜,我火速辦了婚禮凸主,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘额湘。我一直安慰自己卿吐,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布锋华。 她就那樣靜靜地躺著嗡官,像睡著了一般。 火紅的嫁衣襯著肌膚如雪毯焕。 梳的紋絲不亂的頭發(fā)上衍腥,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音纳猫,去河邊找鬼婆咸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛续担,可吹牛的內(nèi)容都是我干的擅耽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼物遇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了憾儒?” 一聲冷哼從身側(cè)響起询兴,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎起趾,沒(méi)想到半個(gè)月后诗舰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡训裆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年眶根,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片边琉。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡属百,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出变姨,到底是詐尸還是另有隱情族扰,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站渔呵,受9級(jí)特大地震影響怒竿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扩氢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一耕驰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧录豺,春花似錦朦肘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至兢哭,卻和暖如春领舰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背迟螺。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工冲秽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人矩父。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓锉桑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親窍株。 傳聞我的和親對(duì)象是個(gè)殘疾皇子民轴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容