標籤:

Android 8.1 build 編譯系統介紹

Android 8.1 build 編譯系統介紹

一 概述

1.1 編譯系統變化

從Android 7.0開始,android的編譯系統發生了變化,之前依賴Makefile組織編譯系統,從7.0開始逐步引入了kati soong(optional未正式使用,需要USE_SOONG=true開啟),將Android.mk文件轉化成ninja文件,使用ninja文件對編譯系統進行管理。

從8.0開始,android 引入了Android.bp文件來替代之前的Android.mk文件,不同於Android.mk,Android.bp只是純粹的配置文件,不包括分支、循環等流程式控制制。在android項目上如何進行選擇編譯、解析配置、轉換成ninja等,Soong就被創造出來,將Android.bp轉換為ninja文件進行管理。

同時,Soong還會編譯長生一個androidmk命令可以手動將Android.mk轉換成Android.bp文件。

1.2 代碼位置

Kati的位置是在build/kati/中,平台也自帶編譯好的ckati

Soong的位置在build/soong,它和build/blueprint同時期作用,他們之間的系統關係如下:

Blueprint更像是一個庫,專門來翻譯blueprint文件,關於Blueprint文件格式可以參考build/blueprint/Blueprints文件,soong是在blueprint上面的擴展,基於blueprint的語法定製產生Android.bp語法,解析Android.bp文件生成ninja文件。

Blueprint和Soong都是有Go語言寫的項目,從7.0開始在prebuilts/go/目錄下新增了go語言的運行環境,在編譯是使用。

1.3 Android ninja組織

在編譯過程中,將所有的android.bp文件搜集成outsoonguild.ninja.d , 並以此為基礎生成outsoonguild.ninja規則。

由所有的Android.mk生成build-aosp_arm.ninja文件。通過combined-aosp_arm.ninja將兩個文件組織起來。

builddir = out

include out/build-aosp_arm.ninja

include out/soong/build.ninja

build out/combined-aosp_arm.ninja: phony out/soong/build.ninja

通過編譯的LOG,首先搜集所有的bp文件生成build.ninja,然後搜集所有的mk文件生成build-aosp-arm.ninja文件。

out/soong/.bootstrap/bin/soong_build out/soong/build.ninja

out/build-aosp_arm-cleanspec.ninja is missing, regenerating...

out/build-aosp_arm.ninja is missing, regenerating...

[1/894] including out/soong/Android-aosp_arm.mk ...

經過試驗表明,soong處理後的bp文件生成build.ninja的同時還包含out/soong/Android-aosp_arm.mk,這個文件是編譯完成後模塊的安裝腳本,負責將模塊安裝到對應位置。比如我們現在處理的vndk相關vendor處理就是在這個目錄下進行的。

在out/soong目錄下有兩個文件.minibootstrap/build.ninja 和.bootstrap/build.ninja兩個目錄。.minibootstrap/build.ninja 主要是用來編譯blueprint和生成.bootstrap/build.ninja。而.bootstrap/build.ninja主要是生成 soong相關工具和out/soong/build.ninja文件。

二 編譯流程

2.1 make 流程

當我們在android 總目錄下make時,默認尋找當前Makefile並找到all目標進行編譯操作,這個是默認的make機制。當android更換為ninja是,在總目錄下進行make時進行如何的流程呢。

同老的make機制一樣,make找到總目錄下的Makefile

$ cat Makefile

include build/make/core/main.mk

Makefile內容沒有改變,同樣是進入到main.mk中,剛開始幾行有了明顯的變化

ifndef KATI

host_prebuilts := linux-x86

ifeq ($(shell uname),Darwin)

host_prebuilts := darwin-x86

endif

.PHONY: run_soong_ui

run_soong_ui:

+@prebuilts/build-tools/$(host_prebuilts)/bin/makeparallel --ninja build/soong/soong_ui.bash --make-mode $(MAKECMDGOALS)

.PHONY: $(MAKECMDGOALS)

$(sort $(MAKECMDGOALS)) : run_soong_ui

@#empty

else # KATI

其中MAKECMDGOALS這個命名是make執行時後面的參數賦值,也就是我們執行任何make的時候都是執行run_soong_ui這個目標,這樣android從Makefile切換為soong進行了編譯流程,後面跟make就沒有關係了。

2.2 mm流程

當我們單獨編譯某個模塊時,在這個模塊目錄下輸入mm命令進行編譯,在build/envsetup.sh看一下具體實現過程:

function mm()

{

local T=$(gettop)

local DRV=$(getdriver $T)

# If were sitting in the root of the build tree, just do a

# normal build.

if [ -f build/soong/soong_ui.bash ]; then

_wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $@

else

ONE_SHOT_MAKEFILE=$M _wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $MODULES $ARGS

流程上同make差不多隻不過目標,是單獨模塊組成。

同時在mm一個單獨模塊是,生成獨立的ninja文件

combined--aosp_arm-frameworks_native_libs_gui_Android.mk.ninja 和

build- aosp_arm-frameworks_native_libs_gui_Android.mk.ninja

2.3 Soong流程

在介紹soong編譯流程之前,先介紹幾個命令以便我們後續編譯流程的理解,在out/soong/host/linux-x86/bin目錄下,有幾個命令是soong用到的,

soong_ui: soong編譯的入口

androidmk: 後面的Android.bp用到,Android.mk一鍵轉換為android.bp

在out/soong/.bootstrap/bin目錄下有幾個

out/soong/.bootstrap/bin$ ls

bpglob gotestmain gotestrunner loadplugins minibp soong_build soong_env

minibp: 在bootstrap是用到

soong_build :這個很重要,主要是將bp文件轉換為ninja文件

通過上文的分析,當我們make命令敲下去的時候,主要是執行

prebuilts/build-tools/$(host_prebuilts)/bin/makeparallel --ninja build/soong/soong_ui.bash --make-mode $(MAKECMDGOALS)

soong_ui.bash腳本主要是執行如下:

build_go soong_ui android/soong/cmd/soong_ui //生成soong_ui命令

cd ${TOP}

exec "$(getoutdir)/soong_ui" "$@" //soong_ui入口,執行soong流程

比如我們執行make systemimage,到這邊就變成了soong_ui –make-mode systemimage

soong_ui代碼在build/soong/cmd/soong_ui/main.go 下,主要流程如下:

func main() {

log := logger.New(os.Stderr)

defer log.Cleanup()

if len(os.Args) < 2 || !inList("--make-mode", os.Args) {

log.Fatalln("The `soong` native UI is not yet available.")

}

build.Build(buildCtx, config, build.BuildAll)

主要執行soong/ui/build/build.go,從build.go就可以看到執行soong的大體流程

看一下各個流程

Step 1: runMakeProductConfig 主要配置編譯參數

Step 2: runSoongBootstrap 這個主要是為後面編譯工具的使用 ckati soong做環境搭建

runSoong 對工具進行編譯

<builddir>/.minibootstrap/build.ninja

- Run minibp to generate .bootstrap/build.ninja (Primary stage) - Run minibp to generate .minibootstrap/build.ninja.in

<builddir>/.bootstrap/build.ninja

- Build any bootstrap_go_binary rules and dependencies -- usually the primary builder and any build or runtime dependencies. - Run the primary builder to generate build.ninja

同時還會生成out/soong/build.ninja

Step 3: 運行step2生成的ckati,搜集所有的Android.mk文件生成ninja文件,也就是前面提到的 out/build-aosp_arm.ninja

Step4: 將out/soong/build.ninja 和out/build-aosp_arm.ninja 合成為combined-aosp_arm.ninja

Step5: 運行runNinja 解釋combined-aosp_arm.ninja 運行編譯過程


推薦閱讀:

TAG:Android開發 |