本文基于Android 10.0源碼分析
1.概述
??在Android 7.0 之前,Android 編譯系統(tǒng)使用GNU Make描述和shell來構建編譯規(guī)則刻撒,模塊定義都使用Android.mk進行定義瞒大,Android.mk的本質就是Makefile台谊,但是隨著Android的工程越來越大,模塊越來越多,Makefile組織的項目編譯時間越來越長。這樣下去Google工程師覺得不行,得要優(yōu)化跋炕。
??因此,在Android 7.0開始律适,Google采用ninja來代取代之前使用的make辐烂,由于之前的Android.mk數(shù)據(jù)實在巨大,因此Google加入了一個kati工具捂贿,用于將Android.mk轉換成ninja的構建規(guī)則文件buildxxx.ninja纠修,再使用ninja來進行構建工作。
??ninja的網(wǎng)址:https://ninja-build.org
??編譯速度快了一些眷蜓,但是既然要干分瘾, 那就干個大的,最終目標要把make都取代吁系,于是從Android8.0開始德召,Google為了進一步淘汰Makefile,因此引入了Android.bp文件來替換之前的Android.mk汽纤。
??Android系統(tǒng)的編譯歷程:
2.Android.bp文件格式
??根據(jù)設計上岗,Android.bp文件很簡單。它們不包含任何條件語句蕴坪,也不包含控制流語句肴掷;所有復雜問題都由用Go 編寫的構建邏輯處理敬锐。Android.bp文件的語法和語義都盡可能與Bazel BUILD文件類似。
2.1 模塊
??Android.bp文件中的模塊以模塊類型開頭呆瞻,后跟一組name: "value"台夺,格式的屬性。
cc_binary {
name: "gzip",
srcs: ["src/test/minigzip.c"],
shared_libs: ["libz"],
stl: "none",
}
每個模塊都必須具有name屬性痴脾,并且相應值在所有name文件中必須是唯一的颤介,僅有兩個例外情況是命名空間和預構建模塊中的Android.bp屬性值,這兩個值可能會重復赞赖。
??srcs 屬性以字符串列表的形式指定用于構建模塊的源文件滚朵。您可以使用模塊引用語法 ":<module-name>" 來引用生成源文件的其他模塊的輸出,如 genrule 或 filegroup前域。如需有效模塊類型及其屬性的列表辕近,請參閱 Soong 模塊參考:https://www.cnblogs.com/linhaostudy/p/12361659.html
??常用模塊類型:
cc_binary
cc_library
cc_library_static
android_app
java_library
hidl_interface
aidl_interface
2.2 類型
??變量和屬性是強類型,變量根據(jù)第一項賦值動態(tài)變化匿垄,屬性由模塊類型靜態(tài)設置移宅。支持的類型為:
布爾值Bool(true 或 false)
整數(shù)Integers (int)
字符串Strings ("string")
字符串列表List of string (["string1", "string2"])
映射Maps ({key1: "value1", key2: ["value2"]})
映射可以包含任何類型的值,包括嵌套映射椿疗。列表和映射可能在最后一個值后面有終止逗號吞杭。
2.3 Glob
??接受文件列表的屬性(例如 srcs)也可以采用glob模式。glob模式可以包含普通的UNIX通配符变丧,例如.java。glob模式還可以包含單個**通配符作為路徑元素绢掰,與零個或多個路徑元素匹配痒蓬。例如,java/*/.java同時匹配 java/Main.java和java/com/android/Main.java模式滴劲。
2.4 變量
??Android.bp文件可能包含頂級變量賦值:
gzip_srcs = ["src/test/minigzip.c"]
cc_binary {
srcs: gzip_srcs,
shared_libs: ["libz"],
stl: "none",
}
變量的作用域限定在聲明它們的文件的其余部分攻晒,以及所有子Android.bp文件,可以使用 “=” 號賦值班挖, 但是不能使用 “:=” 賦值鲁捏。變量是不可變的,但有一個例外情況:可以使用 += 賦值將變量附加到別處萧芙,但只能在引用它們之前附加给梅。例:
gzip_srcs = ["src/test/minigzip.c"]
gzip_srcs += [
"src/test/test.cpp",
]
cc_binary {
srcs: gzip_srcs,
shared_libs: ["libz"],
stl: "none",
}
2.5 注釋
??Android.bp文件可以包含C樣式的多行 /* */ 注釋以及 C++ 樣式的單行//注釋。例如:
// This is a "http://" Comments test
// =========================================================
/*This is a "/**/" Comments test*/
2.6 運算符
??可以使用+運算符附加字符串双揪、字符串列表和映射动羽。可以使用+運算符對整數(shù)求和渔期。附加映射會生成兩個映射中鍵的并集运吓,并附加在兩個映射中都存在的所有鍵的值渴邦。
2.7 條件語句
??Soong不支持Android.bp文件中的條件語句。但是拘哨,編譯規(guī)則中需要條件語句的復雜問題將在Go(在這種語言中谋梭,可以使用高級語言功能,并且可以跟蹤條件語句引入的隱式依賴項)中處理倦青。大多數(shù)條件語句都會轉換為映射屬性瓮床,其中選擇了映射中的某個值并將其附加到頂級屬性。
??例如姨夹,要支持特定于架構的文件纤垂,請使用以下命令:
cc_library {
...
srcs: ["generic.cpp"],
arch: {
arm: {
srcs: ["arm.cpp"],
},
x86: {
srcs: ["x86.cpp"],
},
},
}
2.8 格式設置工具
??Soong包含一個針對Blueprint文件的規(guī)范格式設置工具,類似于gofmt磷账。如需以遞歸方式重新設置當前目錄中所有Android.bp文件的格式峭沦,請運行以下命令:
bpfmt -w .
規(guī)范格式包括縮進四個空格、多元素列表的每個元素后面有換行符逃糟,以及列表和映射末尾有英文逗號吼鱼。
2.9 默認模塊
??默認模塊可用于在多個模塊中重復使用相同的屬性。例如:
cc_defaults {
name: "gzip_defaults",
shared_libs: ["libz"],
stl: "none",
}
cc_binary {
name: "gzip",
defaults: ["gzip_defaults"],
srcs: ["src/test/minigzip.c"],
}
2.10 預編譯的模塊
??某些預構建的模塊類型允許模塊與其基于源代碼的對應模塊具有相同的名稱绰咽。例如菇肃,如果已有同名的 cc_binary,也可以將cc_prebuilt_binary命名為foo取募。這讓開發(fā)者可以靈活地選擇要納入其最終產(chǎn)品中的版本琐谤。如果編譯配置包含兩個版本,則預編譯模塊定義中的prefer標記值會指示哪個版本具有優(yōu)先級玩敏。請注意斗忌,某些預編譯模塊的名稱不能以prebuilt開頭,例如android_app_import旺聚。
2.11 命名空間模塊
??在 Android 完全從Make轉換為Soong之前织阳,Make產(chǎn)品配置必須指定PRODUCT_SOONG_NAMESPACES值。它的值應該是一個以空格分隔的列表砰粹,其中包含Soong導出到Make以使用m命令進行編譯的命名空間唧躲。在Android完成到Soong的轉換之后,啟用命名空間的詳細信息可能會發(fā)生變化碱璃。
??Soong 可以讓不同目錄中的模塊指定相同的名稱弄痹,只要每個模塊都在單獨的命名空間中聲明即可∏镀鳎可以按如下方式聲明命名空間:
soong_namespace {
imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}
請注意界酒,命名空間沒有 name 屬性;其路徑會自動指定為其名稱嘴秸。
??系統(tǒng)會根據(jù)每個Soong模塊在樹中的位置為其分配命名空間毁欣。每個Soong模塊都會被視為處于Android.bp(位于當前目錄或最近的父級目錄中的soong_namespace 文件內)定義的命名空間中庇谆。如果未找到此類 soong_namespace模塊,則認為該模塊位于隱式根命名空間中凭疮。
??下面是一個示例:Soong嘗試解析由模塊M在名稱空間N(導入命名空間 I1饭耳、I2、I3…)中聲明的依賴項D执解。
如果D是//namespace:module格式的完全限定名稱,系統(tǒng)將僅在指定的命名空間中搜索指定的模塊名稱衰腌。
否則,Soong將首先查找在命名空間N中聲明的名為D的模塊右蕊。
如果該模塊不存在,Soong會在命名空間 I1饶囚、I2帕翻、I3…中查找名為D的模塊。
最后萝风,Soong在根命名空間中查找。
2.12 Android.mk文件自動轉Android.bp方法
??Android源碼里邊提供了快捷直接Android.mk轉換成Android.bp的工具:androidmk规惰。
(1)androidmk源碼位置
build/soong/androidmk/cmd/androidmk/androidmk.go
(2)編譯出來后androidmk可執(zhí)行文件位置
aosp/out/soong/host/linux-x86/bin/androidmk
(3)轉換方法
aosp/out/soong/host/linux-x86/bin/androidmk [Android.mk PATH] > [Android.bp PATH]
該工具可以轉換變量、模塊歇万、注釋和一些條件衫仑,但任何自定義生成文件規(guī)則、復雜條件或額外的包含都必須手動轉換堕花。