點擊上方“劉望舒”,選擇“星標”
多點在看,就是真愛!
作者 :? 劉望舒? |??來源 :劉望舒的博客地址:http://liuwangshu.cn/framework/aosp/3-compiling-aosp.html前言
在上一篇文章是時候下載Android 9.0系統源碼了
中,我們順利的將AOSP下載了下來,很多時候我們不僅僅需要去查看源碼,還有以下的幾個需求:
動態調試Android系統源碼
定制Android系統
將最新版本的Android系統刷入到自己的Android設備中
為了實現這些需求,就需要我們去編譯系統源碼。
1.編譯系統概述
了解以下一些概念,會對Android編譯系統有大概的了解。Makefile
Android平臺的編譯系統,其實就是用Makefile寫出來的一個獨立項目。它定義了編譯的規則,實現了“自動化編譯”,不僅把分散在數百個Git庫中的代碼整合起來、統一編譯, 而且還把產物分門別類地輸出到一個目錄,打包成手機ROM,還可以生成應用開發時所使用的SDK、NDK等。
因此,采用Makefile編寫的編譯系統,也可以稱為Makefile編譯系統。Android.mk
Makefile編譯系統的一部分,定義了一個模塊的必要參數,使模塊隨著平臺編譯。通俗來講就是告訴編譯系統,以什么樣的規則編譯你的源代碼,并生成對應的目標文件。
Ninja
Ninja是一個致力于速度的小型編譯系統,如果把其他的編譯系統看作高級語言,那么Ninja 目標就是匯編。
Soong
Soong是谷歌用來替代此前的Makefile編譯系統的替代品,負責解析Android.bp文件,并將之轉換為Ninja文件
Blueprint
Blueprint用來解析Android.bp文件翻譯成Ninja語法文件。
kati
kati是谷歌專門為了Android而開發的一個小項目,基于Golang和C++。 目的是把Android中的Makefile,轉換成Ninja文件。
Android.bp
Android.bp,是用來替換Android.mk的配置文件。
Android.mk、Ninja、Soong、Blueprint、kati、Android.bp的概念之間的聯系為:

Blueprint負責解析Android.bp文件內容,Blueprint類似一個處理相關語法的庫文件,Soong則是定義具體如何處理相應的語法以及命令實現。通俗來講就是Soong借助于Blueprint定義的Android.bp語法,完成Android.bp的解析,最終轉換成Ninja文件。
Makefile文件會通過kati轉換為Ninja文件。
隨著Android工程越來越大,采用Makefile的編譯系統花費的時間也越來越長,因此谷歌在Android 7.0開始引入了Ninja來編譯系統,相對于Makefile來說Ninja在大的項目管理中速度和并行方面有突出的優勢。
Makefile默認文件名為Makefile或makefile,也常用.make或.mk作為文件后綴。 Ninja的默認文件名是build.ninja,其它文件以.ninja為后綴。Makefile與Ninja的區別在于, Makefile是設計來給開發編寫的,而Ninja設計出來是給其它程序生成的。如果Makefile是Java語言,那么Ninja就是匯編語言。
2.編譯源碼的方式
Androd系統源碼編譯有很多種方式,主要有以下幾種:
在Linux中直接進行系統源碼編譯(Android官方支持)
在Mac OS中直接進行系統源碼編譯(Android官方支持)
使用Docker編譯,支持Mac OS和Windows
其中需要注意的是,Docker的最低支持版本為Windows7,建議用Windows10環境下使用Docker,因為在Windows7種還需要借助Docker Toolbox和VirtualBox中的容器進行通信,效率相對低些。
考慮到大多數人的設備和上手難易程度,本為講解在Linux中直接進行系統源碼編譯,如果你的系統不是Ubuntu,可以查看趁周末,用VirtualBox安裝 Ubuntu吧!這篇文章。
3.準備編譯環境
1.安裝 jdk8
sudo?apt-get?update
sudo?apt-get?install?openjdk-8-jdk
2.使用 ubuntu 14+,需要安裝以下依賴包:
sudo?apt-get?install?git-core?gnupg?flex?bison?gperf?build-essential?zip?curl?zlib1g-dev?gcc-multilib?g++-multilib?libc6-dev-i386?lib32ncurses5-dev?x11proto-core-dev?libx11-dev?lib32z-dev?ccache?libgl1-mesa-dev?libxml2-utils?xsltproc?unzip
3.設置處理器數量
在設置-->系統-->處理器選項,設置處理器數量,建議選擇能設置的最大值,這里設置的是6。
4.源碼整編
整編就是編譯整個Android 源碼,整編主要有三個步驟,下面分別就行介紹。
1.初始化環境
在AOSP的根目錄,輸入如下的命令:
source?build/envsetup.sh
//?編譯前刪除build文件夾A
make?clobber
使用 build目錄中的envsetup.sh 腳本初始化環境,這個腳本會引入其他的執行腳本。
2. 選擇編譯目標
輸入命令:
lunch
lunch命令是envsetup.sh里定義的一個命令,用來讓用戶選擇編譯目標。
會有以下信息輸出:
You're?building?on?Linux
Lunch?menu...?pick?a?combo:
?????1.?aosp_arm-eng
?????2.?aosp_arm64-eng
?????3.?aosp_mips-eng
?????4.?aosp_mips64-eng
?????5.?aosp_x86-eng
?????6.?aosp_x86_64-eng
?????7.?aosp_car_arm-userdebug
?????8.?aosp_car_arm64-userdebug
?????9.?aosp_car_x86-userdebug
?????10.?aosp_car_x86_64-userdebug
?????11.?mini_emulator_arm64-userdebug
?????12.?m_e_arm-userdebug
?????13.?m_e_mips64-eng
?????14.?m_e_mips-userdebug
?????15.?mini_emulator_x86_64-userdebug
?????16.?mini_emulator_x86-userdebug
?????17.?uml-userdebug
?????18.?aosp_cf_x86_auto-userdebug
?????19.?aosp_cf_x86_phone-userdebug
?????20.?aosp_cf_x86_tablet-userdebug
?????21.?aosp_cf_x86_tablet_3g-userdebug
?????22.?aosp_cf_x86_tv-userdebug
?????23.?aosp_cf_x86_wear-userdebug
?????24.?aosp_cf_x86_64_auto-userdebug
?????25.?aosp_cf_x86_64_phone-userdebug
?????26.?aosp_cf_x86_64_tablet-userdebug
?????27.?aosp_cf_x86_64_tablet_3g-userdebug
?????28.?aosp_cf_x86_64_tv-userdebug
?????29.?aosp_cf_x86_64_wear-userdebug
?????30.?cf_x86_auto-userdebug
?????31.?cf_x86_phone-userdebug
?????32.?cf_x86_tablet-userdebug
?????33.?cf_x86_tablet_3g-userdebug
?????34.?cf_x86_tv-userdebug
?????35.?cf_x86_wear-userdebug
?????36.?cf_x86_64_auto-userdebug
?????37.?cf_x86_64_phone-userdebug
?????38.?cf_x86_64_tablet-userdebug
?????39.?cf_x86_64_tablet_3g-userdebug
?????40.?cf_x86_64_tv-userdebug
?????41.?cf_x86_64_wear-userdebug
?????42.?aosp_marlin-userdebug
?????43.?aosp_marlin_svelte-userdebug
?????44.?aosp_sailfish-userdebug
?????45.?aosp_walleye-userdebug
?????46.?aosp_walleye_test-userdebug
?????47.?aosp_taimen-userdebug
?????48.?hikey-userdebug
?????49.?hikey64_only-userdebug
?????50.?hikey960-userdebug
Which?would?you?like??[aosp_arm-eng]
意思就是要你選擇編譯目標的格式,編譯目標的格式組成為BUILD-BUILDTYPE,比如aosp_arm-eng
的BUILD為aosp_arm,BUILDTYPE為eng。
其中BUILD表示編譯出的鏡像可以運行在什么環境,aosp代表Android開源項目,arm表示系統是運行在arm架構的處理器上。
更多參考官方文檔。
BUILDTYPE 指的是編譯類型,有以下三種:
user:用來正式發布到市場的版本,權限受限,如沒有 root 權限,不能 dedug,adb默認處于停用狀態。
userdebug:在user版本的基礎上開放了 root 權限和 debug 權限,adb默認處于啟用狀態。一般用于調試真機。
eng:開發工程師的版本,擁有最大的權限(root等),具有額外調試工具的開發配置。一般用于模擬器。
如果你沒有Nexus設備,只想編譯完后運行在模擬器查看,那么BUILD可以選擇aosp_x86
,BUILDTYPE選擇eng,Which would you like? [aosp_arm-eng]
后面直接輸入對應序號5就可以。
也可以直接指定編譯的目標:
lunch?aosp_x86-eng
或者(不同的系統版本,序號的對應會有差別,建議不要直接用序號)
lunch?5
3. 開始編譯
通過-jN參數來設置編譯的并行任務數,以提高編譯速度,在此前我的CPU核心數為6,這里N值最好選在6到12之間,這里我們設置6個并行任務進行編譯:
make?-j6
整編成功后會打印類似如下內容:

由于采用的是虛擬機整編,編譯速度會慢一些,這里花費了2小時46分鐘.
最終會在 out/target/product/generic_x86/目錄生成了三個重要的鏡像文件: system.img、userdata.img、ramdisk.img。大概介紹著三個鏡像文件:
system.img:系統鏡像,里面包含了Android系統主要的目錄和文件,通過init.c進行解析并mount掛載到/system目錄下。
userdata.img:用戶鏡像,是Android系統中存放用戶數據的,通過init.c進行解析并mount掛載到/data目錄下。
ramdisk.img:根文件系統鏡像,包含一些啟動Android系統的重要文件,比如init.rc。
運行模擬器
在編譯完成之后,就可以通過以下命令運行Android虛擬機了,命令如下:
source?build/envsetup.sh
lunch?5
emulator
如果是在編譯完后運行虛擬機,由于之前已經執行過source和lunch命令了,可以直接運行:
emulator
如果不出意外就會啟動模擬器,如果出現報錯,網上也有很多的解決方案。
5.源碼單編
比如我們要編譯系統的Settings應用模塊,
在AOSP根目錄執行:
source?build/envsetup.sh
lunch?5
進入Settings的目錄:
cd?packages/apps/Settings
mm編譯當前目錄下的模塊,不編譯依賴模塊。
mm
編譯成功后會有提示生成文件的存放路徑。

除了Settings.odex文件,還會在out/target/product/generic_x86/system/priv-app/Settings目錄下生成Settings.apk。
如果你修改了源碼,想查看生成的APK文件,有兩種方式:
通過adb push或者adb install 來安裝APK。
使用make snod命令,重新生成 system.img,運行模擬器查看。
熱門文章
Java中的鎖到底有幾種,你知道嗎?
Flutter 美團的實踐及原理
一次違反常規的大廠OPPO面試經歷(文末大量面試文章)
----------? END? ----------
分享大前端、Java、跨平臺等技術,
關注職業發展和行業動態。