從 0 開始編譯 Android 系統源碼
前言
在開始學習 Android Framework 的知識前,準備好相關的源碼環境是非常有必要的。可以選擇直接在 https://cs.android.com/ 網站在線看,但是跳轉這些還是不如在 IDE 下來的方便。或者也可以下載好指定版本的源碼,並通過 IDE 來查看,但是這樣無法編譯源碼,所以也就無法修改源碼後編譯查看效果。
所以這篇文章主要是為了後續編譯 Android 源碼來做準備的,由於編譯源碼最好是在 Linux 環境下進行(因為 Android 官方就是在 Linux 環境下編譯的,為了省事),但是我的設備是 Windows,所以為了在不影響原系統的情況下,可以通過安裝虛擬機並在虛擬機中安裝 Linux 系統。或者有一種更方便的方式是安裝 Docker,在 Docker 下安裝別人已經準備好的 Linux 環境,但是後者在這篇文章中就不介紹了。
當前文章所使用的環境和版本信息:
使用設備:Windows 10 64 位 x86 系統 VirtualBox:7.0.2 版本 Ubuntu:22.04.1 LTS 版本
準備工作
- 下載並安裝 VirtualBox 虛擬機軟件:https://www.virtualbox.org/wiki/Downloads
- 下載 Linux 的 Ubuntu 發行版:https://cn.ubuntu.com/download/desktop
VirtualBox 的安裝很簡單,直接下一步、下一步就可以了。所以後面主要介紹下 Ubuntu 的安裝和配置。
安裝 Ubuntu
- 打開 VirtualBox,點擊“新建”按鈕,並填寫虛擬機的名稱:
注:此時不需要選擇 ISO Image,這樣就是手動安裝了,手動安裝可以選擇系統語言。
- 分配內存和線程數(建議分配最少 4G 內存):
- 分配磁盤大小(建議最少 200G 起):
- 點擊完成。
接下來會進入系統的安裝流程,語言可以選擇中文,輸入用户名和密碼,根據提示直接一步步安裝即可。
注意:進入系統的引導安裝頁面後,屏幕的分辨率很低,可能會導致顯示不完整的情況,例如沒有顯示出下一步的按鈕。此時可以用快捷鍵 Win + 鼠標左鍵拖動安裝頁面,將顯示不全的頁面展示出來。
配置 Ubuntu
- 修改分辨率:由於默認的分辨率太低,看起來不是很舒服,所以可以進入設置頁面調整分辨率到合適的大小。
- 安裝增強工具:從而可以使用共享目錄、共享粘貼板和拖放功能。
- 點擊“設備”-> “安裝增強工具”,此時文件系統中會出現 VBox_GAs_xxx 目錄
- 進入該目錄,並右鍵選擇在當前目錄打開終端
- 在終端中輸入:
sudo ./VBoxLinuxAdditions.run
並回車,即可安裝增強工具 - 開啟共享目錄:在“設備”-> “共享文件夾”中可以添加要共享的文件夾。注意:只需要勾選“自動掛載”和“固定分配”。當重啟系統後,就可以在文件系統中看到
sf_xxx
的目錄,該目錄就是共享的目錄。如果點擊查看該目錄出現權限問題,可以使用sudo adduser [username] vboxsf
命令將當前用户添加到vboxsf
用户組(注意替換為你設置的用户名)。 - 設置“共享粘貼板”和“拖放”為雙向。
- 配置網絡代理:即便我們在 Windows 系統上安裝好了 FQ 軟件,但是在 Ubuntu 系統中還是無法訪問外網的。所以我們需要配置好代理,從而在後續下載 Android 源碼時更方便。例如(IP 地址為 Windows 系統上的 IP,端口為 FQ 軟件上設置的端口):
注意:在完成配置後,最好重啟下系統,從而讓配置生效。
準備源碼環境
安裝 Repo
Android 項目很大,是一個超級項目。所以為了更好的管理代碼,Android 官方做了一個叫做 Repo 的工具,用來在 Android 環境中更好的使用 Git 來管理代碼。因此我們要獲取 Android 源碼,首先需要準備好該工具。
在終端中運行以下命令來安裝 Repo 工具:
bash
sudo apt-get update
sudo apt-get install repo
檢查是否安裝成功:
bash
repo version
如果出現和以下類似的輸出,則説明安裝成功:
```
[email protected]:~$ repo version
repo launcher version 2.17
(from /usr/bin/repo) ```
初始化 Repo
由於眾多周知的原因,如果不適用鏡像的話會出現網絡問題,下載速度也不理想。因此可以選擇用清華大學或其他組織提供的鏡像地址來解決問題。這裏以清華大學的鏡像為例:
-
安裝 curl 工具:
bash sudo apt-get install curl
-
下載 repo 到 bin 目錄並設置權限:
bash mkdir ~/bin curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o ~/bin/repo chmod +x ~/bin/repo
-
repo 的運行過程中會嘗試訪問官方的 Git 源更新自己,如果想使用鏡像源進行更新,可以將如下內容複製到你的
~/.bashrc
裏(使用sudo nano ~/.bashrc
命令進入nano
編輯器修改): ```bash
https://mirrors.tuna.tsinghua.edu.cn/help/git-repo/
export PATH=~/bin:$PATH export REPO_URL='https://mirrors.tuna.tsinghua.edu.cn/git/git-repo' ```
- 使用
source ~/.bashrc
讓其立即生效。
下載源碼
-
創建一個目錄用來存放源碼:
bash mkdir <dir_name> cd <dir_name>
-
使用真實用户名和郵件地址配置 Git:
bash git config --global user.name YourName git config --global user.email [email protected]
-
初始化 repo:
bash repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest
如果需要指定版本,可以使用 -b 選項指定分支(該鏈接中包含所有的分支信息:https://source.android.com/docs/setup/about/build-numbers#source-code-tags-and-builds):bash repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-10.0.0_r47
-
同步源碼:
basic repo sync
如果需要加快同步速度,可以傳遞-c
(當前分支)和-jthreadcount
標誌:bash repo sync -c -j4
以 Android 10 源碼為例,下載完大小大約為 100G 左右。
編譯源碼
安裝所需工具
在編譯的過程中需要用到一些工具,所以提前安裝好它們避免編譯失敗:
bash
sudo apt install m4 libncurses5 python-is-python3
執行 envsetup 腳本
envsetup.sh
腳本用於初始化環境,其中記錄着編譯過程中所需的各種函數實現,例如 lunch、m、mm、mmm
等等。在下載好的源碼目錄下通過一下命令執行該腳本:
bash
source ./build/envsetup.sh
或者也可以使用以下命令:
bash
. ./build/envsetup.sh
注意:每次重新打開終端後都需要再次執行該命令。另外,使用 hmm 可查看可用命令的完整列表。
選擇編譯目標
通過 lunch <product_name>-<build_variant>
命令可以選擇要構建的目標。其中 product_name
指定要構建的產品,build_variant
指定要構建的變體。
所有構建目標都採用 BUILD-BUILDTYPE
形式,其中 BUILD
是指代特定功能組合的代號。 BUILDTYPE
是以下之一:
| BUILD TYPE | 備註 | | --- | --- | | user | 編譯出的系統有權限限制,適用於生產環境 | | userdebug | 編譯出的系統有 root 權限,調試首選 | | eng | 優先考慮開發生產力,帶有附加調試工具並關閉了優化 |
如果不知道該如何選擇目標產品,可以只使用 lunch
命令列出可用的產品列表。例如:
```bash
[email protected]:~/aosp$ lunch
You're building on Linux
Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_arm64-eng
3. aosp_blueline-userdebug
4. aosp_bonito-userdebug
5. aosp_car_arm-userdebug
6. aosp_car_arm64-userdebug
7. aosp_car_x86-userdebug
8. aosp_car_x86_64-userdebug
9. aosp_cf_arm64_phone-userdebug
10. aosp_cf_x86_64_phone-userdebug
......
``
此時可以直接輸入對應的序號來選擇,後續也可以直接通過產品名來直接選擇,例如:
lunch aosp_arm-eng`。
執行編譯命令
編譯指令根據使用場景不同有好幾種,下表中列出了這些編譯指令:
| 編譯指令 | 備註 | | --- | --- | | m | 在源碼樹的根目錄執行編譯 | | mm | 編譯當前路徑下所有模塊,但不包含依賴 | | mmm [module_path] | 編譯指定路徑下所有模塊,但不包含依賴 | | mma | 編譯當前路徑下所有模塊,幷包含依賴 | | mmma [module_path] | 編譯指定路徑下所有模塊,幷包含依賴 | | make [module_name] | 當不指定參數時則表示編譯整個 Android 源碼(包含依賴) |
注:m、mm、mmm、mma、mmma 這些命令都是通過 make 方式來完成的。
一般首次的情況下會使用 make
指令來編譯,相當於進行一次全量編譯。為了加快編譯速度,可以使用 -j
參數指定線程數,例如:
bash
make -j8
編譯成功後,終端會顯示 build completed successfully
。同時,在源碼根目錄下的 /home/airsaid/aosp/out/target/product/<product_name>
目錄中會出現編譯後的產物。其中比較重要的有以下三個鏡像文件:
- system.img:系統鏡像。裏面包含了 Android 系統主要的目錄和文件,通過
init.c
進行解析並mount
掛載到/system
目錄下。 - userdata.img:用户鏡像。是 Android 系統中存放用户數據的,通過
init.c
進行解析並mount
掛載到/data
目錄下。 - ramdisk.img:根文件系統鏡像。包含一些啟動 Android 系統的重要文件,例如
init.rc
。
在編譯的過程中可能會遇到以下問題,可以按照對應的解決方法來解決:
-
找不到
/usr/bin/python
文件或目錄:bash /bin/bash: device/generic/goldfish/tools/mk_combined_img.py:/usr/bin/python:解釋器錯誤: 沒有那個文件或目錄
-
python 腳本語法錯誤(由於源碼中部分 python 腳本用到了 python2 的語法導致的): ```bash File "/home/airsaid/aosp/device/generic/goldfish/tools/mk_combined_img.py", line 48
print "'%s' cannot be converted to int" % (line[2])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(...)?
解決方法:沒有安裝 python2 則先安裝,並建立軟連接將 python 指向 python2:
bash
sudo apt install python2
sudo ln -s /usr/bin/python2 /usr/bin/python
```
- 內存溢出:
bash Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
解決方法:通過修改_JAVA_OPTIONS
環境變量配置,指定更大的內存。將下面的代碼添加到.bashrc
文件:bash export _JAVA_OPTIONS=-Xmx4096m
其他
為 VirtualBox 中的 Ubuntu 擴容
-
在關閉虛擬機的前提下,通過 cmd 進入 VirtualBox 的安裝目錄,例如:
bash cd /d D:\virtualbox\
-
查看 VirtualBox 的虛擬硬盤,並記下 UUID 信息:
bash D:\virtualbox>VBoxManage list hdds UUID: 279063de-8822-48c2-97d9-67964fb90b18 Parent UUID: base State: created Type: normal (base) Location: G:\VirtualBoxVMs\Ubuntu\Ubuntu.vdi Storage format: VDI Capacity: 225280 MBytes Encryption: disabled
-
根據指定 UUID 修改對應虛擬機的容量大小,例如下面的示例中重新分配了 51200 MB(50G):
bash VBoxManage modifyhd 279063de-8822-48c2-97d9-67964fb90b18 --resize 51200
-
打開虛擬機,安裝
gparted
分區工具:bash sudo apt-get install gparted
-
打開分區工具,並將多出來的磁盤分到對應磁盤上。
注意:如果出現
Unable to resize read-only file system
可以參照該文章進行解決:https://blog.csdn.net/ningmengzhihe/article/details/127295333