摘要:Blueprint決議Android.bp到ninja的代碼流程時如何走的?
閱讀本文大約需要花費18分鐘,
文章首發微信公眾號:IngresGe
專注于Android系統級原始碼分析,Android的平臺設計,歡迎關注我,謝謝!
歡迎關注我的公眾號!

[Android取經之路] 的原始碼都基于Android-Q(10.0) 進行分析
[Android取經之路] 系列文章:
《系統啟動篇》
- Android系統架構
- Android是怎么啟動的
- Android 10.0系統啟動之init行程
- Android10.0系統啟動之Zygote行程
- Android 10.0 系統啟動之SystemServer行程
- Android 10.0 系統服務之ActivityMnagerService
- Android10.0系統啟動之Launcher(桌面)啟動流程
- Android10.0應用行程創建程序以及Zygote的fork流程
- Android 10.0 PackageManagerService(一)作業原理及啟動流程
- Android 10.0 PackageManagerService(二)權限掃描
- Android 10.0 PackageManagerService(三)APK掃描
- Android 10.0 PackageManagerService(四)APK安裝流程
《日志系統篇》
- Android10.0 日志系統分析(一)-logd、logcat 指令說明、分類和屬性
- Android10.0 日志系統分析(二)-logd、logcat架構分析及日志系統初始化
- Android10.0 日志系統分析(三)-logd、logcat讀寫日志原始碼分析
- Android10.0 日志系統分析(四)-selinux、kernel日志在logd中的實作?
《Binder通信原理》:
- Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
- Android10.0 Binder通信原理(二)-Binder入門篇
- Android10.0 Binder通信原理(三)-ServiceManager篇
- Android10.0 Binder通信原理(四)-Native-C\C++實體分析
- Android10.0 Binder通信原理(五)-Binder驅動分析
- Android10.0 Binder通信原理(六)-Binder資料如何完成定向打擊
- Android10.0 Binder通信原理(七)-Framework binder示例
- Android10.0 Binder通信原理(八)-Framework層分析
- Android10.0 Binder通信原理(九)-AIDL Binder示例
- Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub設計模式
- Android10.0 Binder通信原理(十一)-Binder總結
《HwBinder通信原理》
- HwBinder入門篇-Android10.0 HwBinder通信原理(一)
- HIDL詳解-Android10.0 HwBinder通信原理(二)
- HIDL示例-C++服務創建Client驗證-Android10.0 HwBinder通信原理(三)
- HIDL示例-JAVA服務創建-Client驗證-Android10.0 HwBinder通信原理(四)
- HwServiceManager篇-Android10.0 HwBinder通信原理(五)
- Native層HIDL服務的注冊原理-Android10.0 HwBinder通信原理(六)
- Native層HIDL服務的獲取原理-Android10.0 HwBinder通信原理(七)
- JAVA層HIDL服務的注冊原理-Android10.0 HwBinder通信原理(八)
- JAVA層HIDL服務的獲取原理-Android10.0 HwBinder通信原理(九)
- HwBinder驅動篇-Android10.0 HwBinder通信原理(十)
- HwBinder原理總結-Android10.0 HwBinder通信原理(十一)
《編譯原理》
- 編譯系統入門篇-Android10.0編譯系統(一)
- 編譯環境初始化-Android10.0編譯系統(二)
- make編譯程序-Android10.0編譯系統(三)
- Image打包流程-Android10.0編譯系統(四)
- Kati詳解-Android10.0編譯系統(五)
- Blueprint簡介-Android10.0編譯系統(六)
- Blueprint代碼詳細分析-Android10.0編譯系統(七)
1 概述
在 Android 7.0 之前,Android 編譯系統使用 GNU Make 描述和shell來構建編譯規則,模塊定義都使用Android.mk進行定義,Android.mk的本質就是Makefile,但是隨著Android的工程越來越大,模塊越來越多,Makefile組織的專案編譯時間越來越長,這樣下去Google工程師覺得不行,得要優化,
因此,在Android7.0開始,Google采用ninja來代取代之前使用的make,由于之前的Android.mk資料實在巨大,因此Google加入了一個kati工具,用于將Android.mk轉換成ninja的構建規則檔案buildxxx.ninja,再使用ninja來進行構建作業,
ninja的網址:https://ninja-build.org
編譯速度快了一些,但是既然要干, 那就干個大的,最終目標要把make都取代,于是從Android8.0開始,Google為了進一步淘汰Makefile,因此引入了Android.bp檔案來替換之前的Android.mk,
Android系統的編譯歷程:

2 Android.bp 檔案格式
根據設計,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 型別
變數和屬性是強型別,變數根據第一項賦值動態變化,屬性由模塊型別靜態設定,支持的型別為:
-
布林值Bool(true 或 false)
-
整數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 "//" Comments test
// =========================================================
/*This is a "/**/" Comments test*/
2.6 運算子
可以使用 + 運算子附加字串、字串串列和映射,可以使用 + 運算子對整數求和,附加映射會生成兩個映射中鍵的并集,并附加在兩個映射中都存在的所有鍵的值,
2.7 條件陳述句
Soong 不支持 Android.bp 檔案中的條件陳述句,但是,編譯規則中需要條件陳述句的復雜問題將在 Go(在這種語言中,您可以使用高級語言功能,并且可以跟蹤條件陳述句引入的隱式依賴項)中處理,大多數條件陳述句都會轉換為映射屬性,其中選擇了映射中的某個值并將其附加到頂級屬性,
例如,要支持特定于架構的檔案,請使用以下命令:
cc_library {
...
srcs: ["generic.cpp"],
arch: {
arm: {
srcs: ["arm.cpp"],
},
x86: {
srcs: ["x86.cpp"],
},
},
}
2.8 格式設定工具
Soong 包含一個針對 Blueprint 檔案的規范格式設定工具,類似于 gofmt,如需以遞回方式重新設定當前目錄中所有 Android.bp 檔案的格式,請運行以下命令:
bpfmt -w .
規范格式包括縮進四個空格、多元素串列的每個元素后面有換行符,以及串列和映射末尾有英文逗號,
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,這讓開發者可以靈活地選擇要納入其最終產品中的版本,如果編譯配置包含兩個版本,則預編譯模塊定義中的 prefer 標記值會指示哪個版本具有優先級,請注意,某些預編譯模塊的名稱不能以 prebuilt開頭,例如 android_app_import,
2.11 命名空間模塊
在 Android 完全從 Make 轉換為 Soong 之前,Make 產品配置必須指定 PRODUCT_SOONG_NAMESPACES 值,它的值應該是一個以空格分隔的串列,其中包含 Soong 匯出到 Make 以使用 m 命令進行編譯的命名空間,在 Android 完成到 Soong 的轉換之后,啟用命名空間的詳細資訊可能會發生變化,
Soong 可以讓不同目錄中的模塊指定相同的名稱,只要每個模塊都在單獨的命名空間中宣告即可,可以按如下方式宣告命名空間:
soong_namespace {
imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}
請注意,命名空間沒有 name 屬性;其路徑會自動指定為其名稱,
系統會根據每個 Soong 模塊在樹中的位置為其分配命名空間,每個 Soong 模塊都會被視為處于 Android.bp(位于當前目錄或最近的父級目錄中的 soong_namespace 檔案內)定義的命名空間中,如果未找到此類 soong_namespace 模塊,則認為該模塊位于隱式根命名空間中,
下面是一個示例:Soong 嘗試決議由模塊 M 在名稱空間 N(匯入命名空間 I1、I2、I3…)中宣告的依賴項 D,
1.如果 D 是 //namespace:module 格式的完全限定名稱,系統將僅在指定的命名空間中搜索指定的模塊名稱,
2.否則,Soong 將首先查找在命名空間 N 中宣告的名為 D 的模塊,
3.如果該模塊不存在,Soong 會在命名空間 I1、I2、I3…中查找名為 D 的模塊,
4.最后,Soong 在根命名空間中查找,
2.12 Android.mk檔案 自動轉Android.bp方法
Android原始碼里邊提供了快捷直接Android.mk轉換成Android.bp的工具:androidmk,
androidmk原始碼位置:
build/soong/androidmk/cmd/androidmk/androidmk.go
編譯出來后androidmk可執行檔案位置:
aosp/out/soong/host/linux-x86/bin/androidmk
轉換方法:
aosp/out/soong/host/linux-x86/bin/androidmk [Android.mk PATH] > [Android.bp PATH]
該工具可以轉換變數、模塊、注釋和一些條件,但任何自定義生成檔案規則、復雜條件或額外的包含都必須手動轉換,
參考:
《SOONG構建系統》
《Soong Modules Reference》
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/210054.html
標籤:java
下一篇:關于融云的單聊通訊那點事
