目錄
Android 8.0- —— Android.mk實現條件編譯
Android 9.0+ —— Android.bp實現條件編譯
擴展:Android 9.0+ —— Android.bp實現自定義條件編譯
本人正在學習中。此篇文章如有不正之處,歡迎指正討論!
前言 —— 需求提出
最近在協助完成模塊優化的時候,有個需求如下:
依賴結構:A B C……等多個平臺共用一個自定義系統模塊
隨後優化此模塊中內容,改動需要跟隨A平臺進行系統迭代測試,但希望BC等其他平臺不受此優化內容影響
基於上面的需求,整理了一下條件:
1.平臺系統版本包括Android 8.0、9.0。
2.自定義系統模塊功能已經在源碼打點完畢,儘可能少地改動系統源碼(否則要多個平臺都修改)。
3.不同平臺可快速進行優化方案和非優化方案的切換,便於在不同階段的各個平臺能不受影響快速切換方案。
因此想出了以下做法:
1.保證優化後的類名和包名一致,可以放到包名以上的其他目錄中。 —— 確保系統源碼中的打點無需改動。
如自定義系統模塊中優化前的類和包名爲:(module_path)/hotkey/service/core/java/com/android/server/policy/HotKey.java
自定義系統模塊中優化後的類和包名爲:(module_path)/audio/service/core/java/com/android/server/policy/HotKey.java
如此一來,HotKey的類名和包名與原來一致,系統中引用到HotKey的地方依舊只需要import com.android.server.policy.HotKey; 無需變動。
2.在Android.mk和Android.bp中完成條件編譯。 —— 兼容不同版本系統平臺,根據條件快速切換優化方案。
下面就想方法解決這個問題吧!
Android 8.0- —— Android.mk實現條件編譯
先給出一份8.0系統framework下的mk文件(framework/base/service/core):
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := services.core
……
LOCAL_SRC_FILES += \
$(call all-java-files-under,java) \
java/com/android/server/EventLogTags.logtags \
java/com/android/server/am/EventLogTags.logtags \
../../../../system/netd/server/binder/android/net/INetd.aidl \
../../../../system/netd/server/binder/android/net/metrics/INetdEventListener.aidl \
../../../native/cmds/installd/binder/android/os/IInstalld.aidl \
# patch start
$(custom_module_files) \
# patch end
……
include $(BUILD_STATIC_JAVA_LIBRARY)
在源碼中mk中加入 $(module_files),在自定義系統模塊的mk中完成 module_files 的定義,將改動儘量放到系統自定義模塊下。
Android.mk不必多說,通過在mk裏設立變量,即可使用ifeq、ifdef等判斷值,進行條件編譯。如定義:
OPTIMIZE := true
隨後修改mk參與編譯的文件,如下:
custom_module_files := \
……
# patch start
ifeq ($(OPTIMIZE),true)
custom_module_files += \
(custom_module_path)/audio/services/core/java/com/android/server/policy/HotKey.java
else
custom_module_files += \
(custom_module_path)/hotkey/services/core/java/com/android/server/policy/HotKey.java
endif
# patch end
其中audio目錄下的HotKey.java是優化後待測試的代碼,而policy目錄下的HotKey則是未優化的穩定代碼。通過定義mk中的變量,就可以完成mk文件的條件編譯了。
Android 9.0+ —— Android.bp實現條件編譯
Android在7.0引入 ninja 編譯系統,8.0引入Android.bp替代Android.mk,9.0強制使用Android.bp作爲編譯配置。
解決完8.0的編譯問題,準備着手9.0的編譯問題了。出於一樣的想法,在bp裏完成條件編譯,然後和mk處理方式一樣,通過開關決定參與編譯的文件,即可解決此問題。但是Android.bp實際上是一個純粹的json配置文件,沒有條件、分支等流程結構,因此即便使用自帶的androidmk工具想要將Android.mk快速轉成Android.bp,也會發現流程語句並不起效果。爲了解決此問題,google將條件編譯進行分家,Android.bp負責純粹配置,引入Go文件負責進行流程結構判斷。
這樣一來思路就清楚了:
下面用代碼實現:
1.自定義模塊custommodule下Android.bp定義兩個方案(優化和未優化),如:
# patch start
filegroup {
name: "custom_optimize",
srcs: [
"audio/services/core/java/com/android/server/policy/HotKey.java",
],
}
filegroup {
name: "custom_origin",
srcs: [
"hotkey/services/core/java/com/android/server/policy/HotKey.java",
],
}
# patch end
2.添加用於自定義系統模塊條件編譯的Go文件。如在自定義模塊名字爲customsystem,則在customsystem目錄下創建customsystem.go,內容如下:
package customsystem
import (
"android/soong/android"
"android/soong/java"
"fmt"
)
//註冊module模板,存放默認屬性
func init() {
android.RegisterModuleType("custom_optimize_default", custom_optimize_go)
}
func custom_optimize_go() android.Module {
module := java.DefaultsFactory()
android.AddLoadHook(module, custom_optimize_append_properties)
return module
}
func custom_optimize_append_properties(ctx android.LoadHookContext) {
type props struct {
Srcs []string
}
p := &props{}
sdkVersion := ctx.AConfig().PlatformSdkVersionInt()
fmt.Println("sdkVersion:", sdkVersion)
if sdkVersion >=28 { //after P
p.Srcs = append(p.Srcs, ":custom_optimize")
} else {
p.Srcs = append(p.Srcs, ":custom_origin")
}
ctx.AppendProperties(p)
}
3.framework下Android.bp加入自定義模塊聲明(framework/base/service/core/Android.bp):
# patch start
custom_optimize_default{
name: "custom_optimize_default",
}
# patch end
java_library_static {
name: "services.core.unboosted",
# patch start
defaults: [
"custom_optimize_default",
],
# patch end
aidl: {
……
},
srcs: [
……
],
……
}
這樣子就完成了一次條件編譯,此處使用的條件是Android版本。如果需要其他變量作爲判斷條件,可以查看out/soong/soong.variables文件,裏面是系統中提供的所有環境變量,如當前系統Android版本、是否調試版本、架構、路徑等等:
{
"Platform_version_name": "9",
"Platform_sdk_version": 28,
"Platform_sdk_codename": "REL",
"Platform_sdk_final": true,
"Allow_missing_dependencies": false,
"Debuggable": false,
"Eng": false,
"DeviceArch": "arm",
"DeviceArchVariant": "armv7-a-neon",
"DeviceCpuVariant": "cortex-a9",
"DeviceAbi": ["armeabi-v7a","armeabi"],
"DeviceSecondaryArchVariant": "",
"DeviceSecondaryCpuVariant": "",
"HostArch": "x86_64",
"HostSecondaryArch": "x86",
"HostStaticBinaries": false,
"CrossHost": "windows",
"CrossHostArch": "x86",
"CrossHostSecondaryArch": "x86_64",
……
}
擴展:Android 9.0+ —— Android.bp實現自定義條件編譯
上一部分做了一個用系統內環境變量條件編譯的實例,不過等等,好像和一開頭的需求不是很符合?
想一想,僅用sdkVersion進行判斷,那麼對於所有Android9.0的平臺來說只能做統一處理,連區分平臺都做不到,更何況區分同code的不同平臺了。
那麼擴展場景來了:如何打入一個系統環境變量,並通過mk文件賦值,讓我們的條件編譯真正按照平臺生效呢?
翻了資料,全程耗時一週,打通了一條路,原理剖析後續補上,直接上code。(具體可以戳傳送門瞅瞅這位大大寫出來的通路圖 --> https://blog.csdn.net/u012188065/article/details/89352166)
1.在平臺mk中,定義mk變量。(此處平臺mk選擇的是BoardConfig.mk, 路勁device/(廠商)/(平臺)/BoardConfig.mk
# patch start
OPTIMIZE := true
# patch end
2.新增bool類型go變量。路徑build/soong/android/variable.go
type productVariables struct {
……
// patch start
Optimize *bool `json:",omitempty"`
// patch end
}
3.建立go變量和mk變量的json映射關係,讓go變量可以獲取到mk中定義的變量值。路徑build/make/core/soong_config.mk
……
# patch start
$(call add_json_bool, Optimize, $(filter true, $(OPTIMIZE)))
# patch end
# 這句等同於:
# bool Optimize = (OPTIMIZE == true)
……
4.定義go方法,返回go變量的值。路徑:build/soong/android/config.go
……
# patch start
func (c *deviceConfig) Optimize() bool {
return Bool(c.config.productVariables.Optimize)
}
# patch end
……
完成了以上四步後,mk變量就成功映射到go文件中,並生成系統環境變量。
在編譯之後可以查看out/soong/soong.variables文件,確認是否生成環境變量,賦值是否正確。
基於上一部分的成果,我們來修改一下實現,完成我們的需求:
修改customsystem.go,如下:
……
func custom_optimize_append_properties(ctx android.LoadHookContext) {
type props struct {
Srcs []string
}
p := &props{}
// 修改成自定義條件
optimize := ctx.DeviceConfig().Optimize()
fmt.Println("mk OPTIMIZE:", optimize)
if optimize {
p.Srcs = append(p.Srcs, ":custom_optimize")
} else {
p.Srcs = append(p.Srcs, ":custom_origin")
}
ctx.AppendProperties(p)
}
……
修改到這裏,就完全結束了。現在只需要編譯看看,驗證效果。
相關原理剖析會另起一篇,未完待續……
——————————————————————————————————————
參考資料:
① 少俠的崛起 - 產品.mk控制android.bp選擇性編譯 - https://blog.csdn.net/u012188065/article/details/89352166
② 秋少 - Android系統開發進階-Android編譯系統介紹 - https://qiushao.net/2020/02/06/Android%E7%B3%BB%E7%BB%9F%E5%BC%80%E5%8F%91%E8%BF%9B%E9%98%B6/Android%E7%BC%96%E8%AF%91%E7%B3%BB%E7%BB%9F%E4%BB%8B%E7%BB%8D/
(③ 感謝海思的小抄!