『BATcoder』 做了多年安卓還沒編譯過原始碼?一個視訊帶你玩轉!

劉望舒發表於2021-03-08

本文首發於微信公眾號「劉望舒」

這是BATcoder的第五篇,BATcoder是Android進階三部曲的番外篇,會對Android進階三部曲的內容進行擴充和升級,會以視訊的形式分享給大家。至於為啥叫BATcoder,這是因為我希望大家看了我的技術視訊能進入自己中意的大廠。

視訊版本

更多細節和內容見視訊:

B站地址: www.bilibili.com/video/BV1VU…

獨立部落格地址: liuwangshu.cn/batcoder/ao…

前言

我們順利的將AOSP下載了下來後,很多時候我們不僅僅需要去檢視原始碼,還有以下的幾個需求:

  • 1.定製Android系統
  • 2.將最新版本的Android系統刷入到自己的Android裝置中
  • 3.將整個系統原始碼匯入到Android Studio中
  • 4.動態除錯Android系統原始碼

為了實現這些需求,就需要我們去編譯系統原始碼。其中第三條和第四條也可以不用編譯原始碼來實現,第三條只要有對應Android原始碼版本的android.iml 和 android.ipr 兩個檔案就可以將原始碼匯入到Android Studio中,第四條動態除錯系統原始碼不一定非要匯入整個系統原始碼進行除錯。關於第三條和第四條的具體內容,我會在以後的內容中進行講解。

1.編譯系統概述

瞭解以下一些概念,會對Android編譯系統有大概的瞭解。

Makefile

Android平臺的編譯系統,其實就是用Makefile寫出來的一個獨立專案。它定義了編譯的規則,實現了“自動化編譯”,不僅把分散在數百個Git庫中的程式碼整合起來、統一編譯, 而且還把產物分門別類地輸出到一個目錄,打包成手機ROM,還可以生成應用開發時所使用的SDK、NDK等。 因此,採用Makefile編寫的編譯系統,也可以稱為Makefile編譯系統。

Android.mk Makefile編譯系統的一部分,Android.mk是android編譯環境下的一種特殊的“makefile”檔案, 它是經過了android編譯系統處理的。Android.mk中定義了一個模組的必要引數,使模組隨著平臺編譯。通俗來講就是告訴編譯系統,以什麼樣的規則編譯你的原始碼,並生成對應的目標檔案。

Ninja

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的概念之間的聯絡為:

VZRxYQ.png

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中直接進行系統原始碼編譯。

3.準備編譯環境

1.設定處理器數量

在沒有執行Ubuntu的時候,在VirtualBox裡選擇設定-->系統-->處理器選項,設定處理器數量,建議設定比較大一些,這裡設定的是6。 如果不能夠設定,請檢查是否開啟虛擬化技術。不同的電腦開啟的方式也不同,比如我此前惠普暗影精靈4的桌上型電腦,在開機時連續按F10就會進入BIOS,在安全->系統安全性->虛擬化技術選項設定啟用即可。 現在的暗影精靈6桌上型電腦,則是在BIOS的配置選項裡開啟虛擬化技術選項。

2.安裝 jdk8

sudo apt-get update
sudo apt-get install openjdk-8-jdk
複製程式碼

3.使用 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
複製程式碼

4.原始碼整編

整編就是編譯整個Android 原始碼,整編主要有三個步驟,下面分別就行介紹。

1.初始化環境

在AOSP的根目錄,輸入如下的命令:

source build/envsetup.sh
make clobber
複製程式碼

使用 build目錄中的envsetup.sh 指令碼初始化環境,這個指令碼會引入其他的執行指令碼。make clobber用於清除快取。

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 /ˈneksəs/ 裝置,只想編譯完後執行在模擬器檢視,那麼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 aosp_x86-eng
emulator
複製程式碼

如果是在編譯完後執行虛擬機器,由於之前已經執行過source和lunch命令了,可以直接執行:

emulator
複製程式碼

如果不出意外就會啟動模擬器,如果出現報錯,網上也有很多的解決方案。

5.原始碼單編

比如我們要編譯系統的Settings應用模組, 在AOSP根目錄執行:

source build/envsetup.sh
lunch aosp_x86-eng
複製程式碼

進入Settings的目錄:

cd packages/apps/Settings
複製程式碼

mm編譯當前目錄下的模組,不編譯依賴模組。

mm
複製程式碼

編譯成功後會有提示生成檔案的存放路徑。

除了Settings.odex檔案,還會在out/target/product/generic_x86/system/priv-app/Settings目錄下生成Settings.apk。

此外還有以下命令可以進行單編:

  • mmm:編譯指定目錄下的模組,不編譯它所依賴的其它模組。
  • mma:編譯當前目錄下的模組及其依賴項。
  • mmma:編譯指定路徑下所有模組,並且包含依賴。

如果你修改了原始碼,想檢視生成的APK檔案,有兩種方式:

  1. 通過adb push或者adb install 來安裝APK。
  2. 使用make snod命令,重新生成 system.img,執行模擬器檢視。

更多細節和內容見視訊:

B站地址: www.bilibili.com/video/BV1VU…

獨立部落格地址: liuwangshu.cn/batcoder/ao…

作者簡介:劉望舒,騰訊雲最具價值專家,著有暢銷書《Android進階之光》《Android進階解密》《Android進階指北》,蟬聯四屆電子工業出版社年度優秀作者,前華為面試官,現大廠技術負責人,谷歌開發者社群特邀講師。

也歡迎大家關注我的公號「劉望舒」,會分享大前端、Java相關的技術。

6K75Eq.jpg

相關文章