背景介紹
在Android7.0之前,Android使用GNU Make描述和執行build規則。Android7.0引入了Soong構建系統,彌補Make構建系統在Android層面變慢、容易出錯、無法擴展且難以測試等缺點。
Soong利用Kati GNU Make克隆工具和Ninja構建系統組件來加速Android的構建。
下面從兩個方面來了解Soong構建系統:
- 使用Soong構建系統構建自己模塊要熟悉的兩個內容,即.bp和.go。
- Soong構建系統和Make構建系統的差異。
1.Soong構建系統中.bp和.go的關系
在Android的Soong構建系統中,.bp (Blueprint)文件和.go(Golang)文件共同協作,關系大概如下:
1.?.bp文件,聲明式構建配置
.bp文件用于定義模塊及其屬性,采用類似JSON的聲明式語法,描述模塊的構建規則(如源文件、依賴項、編譯選項等)
.bp文件不支持條件語句或控制流,僅用于靜態配置。
Soong預定義了模塊類型,如cc_library,cc_binary,? java_library等。
?例如,Android15源碼中Camera HAL AIDL Demo中的一段:
//hardware/google/camera/common/hal/aidl_service/Android.bp
cc_binary {name: "android.hardware.camera.provider@2.7-service-google",defaults: ["hardware_camera_service_defaults","camera_service_eager_hal_defaults",],init_rc: ["android.hardware.camera.provider@2.7-service-google.rc],
}
2. .go文件,邏輯處理與擴展
.go文件用于實現復雜的構建邏輯,例如
- 解析.bp文件并生成Ninja構建規則
- 處理條件編譯、環境變量、動態依賴等無法在.bp中直接表達的邏輯
- 擴展模塊類型或自定義構建行為(如通過Go的發射機制)
使用GO語言編寫,靈活性高,可調用Android構建系統的底層API。
例如,通過LoadHook動態修改模塊屬性:
func myHook(ctx android.LoadHookContext) {if ctx.AConfig().IsEnvTrue("USE_FEATURE_X") {ctx.AppendProperties(map[string]interface{}{"cflags": ["-DFEATURE_X"]})}
}
3.協作關系
.bp負責“做什么”(聲明模塊和屬性), .go負責“怎么做”(實現復雜邏輯和生成構建規則)
轉換流程:
- Soong解析所有.bp文件,生成模塊依賴圖。
- .go代碼處理模塊間的動態邏輯(如根據產品配置選擇源碼)。
- 最終轉換為Ninja可執行的構建規則。
4.協作的典型例子1-條件編譯
在.bp中通過arch或target(.go中預定義的變量)分平臺配置,而跨模塊的全局條件(如產品型號)需要在.go中實現。
cc_library {srcs: ["generic.cpp"],arch: { arm: { srcs: ["arm.cpp] } },
}
?如果arch是arm, srcs是arm.cpp。arch是soong中預定義的變量,用于分平臺構建。
5.協作的典型例子2-模塊級別控制
例如, Android15 Camera HAL AIDL Demo構建中的一段:
gch_lazy_hal_cc_defaults {name: "camera_service_eager_hal_defaults",enabled: true,soong_config_variables: {use_lazy_hal: {enabled: false,},},
}gch_lazy_hal_cc_defaults {name: "camera_service_lazy_hal_defaults",enabled: false,soong_config_variables: {use_lazy_hal: {enabled: true,},},
}
6.總結
.bp文件 | .go文件 | |
語法 | 聲明式,類JSON | 命令式,Go語言 |
靈活性 | 有限,無邏輯控制 | 高,可編程 |
適用場景 | 模塊定義、靜態依賴 | 動態邏輯、構建規則擴展 |
維護者 | 開發者 | 構建系統工程師/高級開發者 |
2.Soong構建系統和Make構建系統的差異
這兩種構建系統在設計理念、語法結構和執行效率等方面又著顯著的差異。以下從多個維度對這兩種構建系統進行對比分析。
基本概念與發展背景
Make構建系統
- Android早期使用的構建系統,基于GNU Make實現
- 通過Android.mk文件定義構建規則
- 隨著Android項目復雜度增加,逐漸暴露出性能瓶頸和可維護性問題
Soong構建系統
- Android 7.0(Nougat)引入的新構建系統,旨在取代Make
- 使用Android.bp文件(Blueprint格式)定義構建規則
- 采用Go語言編寫,與Kati和Ninja構建系統組件配合使用
- 設計目標式解決Make系統在大型項目中的性能瓶頸
語法結構與配置方式
Make語法特點
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libexample
LOCAL_SRC_FILES := example.cpp
include $(BUILD_SHARED_LIBRARY)
- 命令式語法,包含變量定義和流程控制
- 需要手動管理依賴關系
- 基于shell命令執行構建任務
Soong語法特點
cc_library_shared {name: "libexample",srcs: ["example.cpp"],
}
- 聲明式語法,類似JSON格式
- 不支持條件語句和控制流,復雜邏輯由Go代碼處理
- 強類型變量和屬性系統
- 更簡潔直觀的模塊定義方式
系統架構與工作原理
Make系統架構
- 串行構建方式,依賴關系手動指定
- 擴展性差,配置復雜度隨項目規模增長而急劇上升
- 增量構建能力有限
Soong系統架構
- ?自動分析模塊依賴關系并生成構建圖
- 支持并行構建,充分利用多核CPU
- 高效的增量構建機制,僅重新編譯變更部分
- 模塊化設計,易于擴展
性能與效率對比
構建速度
- Make系統在大型項目上構建速度較慢,特別是全量構建時
- Soong通過并行構建和精確的依賴分析,顯著提升構建速度
資源利用率
- Make系統資源利用率低,主要受限于串行執行
- Soong能充分利用現代多核處理器,實現高效資源利用
增量構建
- Make需要開發者手動維護依賴關系,增量構建不可靠
- Soong自動跟蹤文件變更,增量構建精確高效
功能特性對比
特性 | Make構建系統 | Soong構建系統 |
語法類型 | 命令式 | 聲明式 |
依賴管理 | 手動指定 | 自動處理 |
并行構建 | 有限支持 | 原生支持 |
增量構建 | 基本支持 | 高效支持 |
擴展性 | 有限 | 高度可擴展 |
跨平臺 | 需要適配 | 原生支持 |
學習曲線 | 相對簡單 | 較陡峭 |
條件編譯 | 支持 | 通過Go代碼實現 |
模塊化 | 有限 | 高度模塊化 |
與Android集成 | 逐漸淘汰 | 深度集成 |
實際應用場景
適合使用Make的場景
- 維護舊的Android項目代碼
- 小型項目或原型開發
- 需要與現有Make系統集成的場景
適合使用Soong的場景
- 新的Android平臺開發
- 大型復雜項目
- 需要高效并行構建的環境
- 需要精確增量構建的項目
遷移于兼容性
- Soong設計時考慮了與Make系統的兼容性
- 提供androidmk工具可將Android.mk轉換為Android.bp
- 過渡期間采用混合模式:Make由Kati解析生成ninja文件,再與Soong的ninja文件合并
- 完全遷移到Soong是Android構建系統的未來方向
Make構建系統作為Android早期的構建解決方案,已經逐漸無法滿足現代大型項目的需求。Soong構建系統通過聲明式配置、自動依賴管理和并行構建等特性,顯著提升了Android項目的構建效率和可維護性。
Make和Soong構建系統的使用建議
- 新項目應直接采用Soong構建系統
- 舊項目可逐步將Android.mk轉換為Android.bp
- 復雜構建邏輯可通過Go擴展實現
- 充分利用Soong提供的工具鏈(bpfmt等)提高開發效率
隨著Android生態的發展,Soong構建系統將持續演進,可能最終向Bazel構建系統過渡,但其核心優勢仍將在Android構建領域發揮重要作用。