一、配置 Mac OS 編譯環境
1. 建立區分大小寫的磁碟映象
Mac OS 的檔案系統,預設情況下保留大小寫但不區分大小寫。Git 不支援這樣的檔案系統。所以在 Mac OS 中編譯 Android 原始碼,需要建立一塊區分大小寫的磁碟映象。
可以通過命令直接建立區分大小寫的磁碟映象:
hdiutil create -type SPARSE -fs 'Case-sensitive Journaled HFS+' -size 100g ~/android.dmg
複製程式碼
執行上述命令將會建立一個 android.dmg 或 android.dmg.sparseimage 檔案,掛載改檔案後,可以作為一個區分大小寫的映象分割槽。
-size 用於設定分割槽的大小,完成 Android 原始碼編譯至少需要 25GB。如果之後需要調整映象分割槽的空間大小,可以使用如下命令:
hdiutil resize -size <new-size-you-want>g ~/android.dmg.sparseimage
複製程式碼
可以在 ~/.bash_profile(如果是 zsh 則在 ~/.zshrc)檔案中新增輔助函式來執行掛載和取消掛載:
# mount the android file image
function mountAndroid { hdiutil attach ~/android.dmg -mountpoint /Volumes/android; }
# unmount the android file image
function umountAndroid() { hdiutil detach /Volumes/android; }
複製程式碼
注:如果建立磁碟映象時生成的是 .dmg.sparseimage 檔案,將上述方法中的 ~/android.dmg 換成 ~/android.dmg.sparseimage。
之後我們可以使用 mountAndroid 命令來執行掛載映象,使用 umountAndroid 命令來執行取消掛載映象。
2. 安裝相關工具
2.1 安裝 JDK
不同 Android 系統版本的 JDK 要求:
-
AOSP 中 Android 的 master 分支:jdk 8u45 或更高版本
-
Android 5.x (Lollipop) - Android 6.0 (Marshmallow):jdk-7u71-macosx-x64.dmg
-
Android 2.3.x (Gingerbread) - Android 4.4.x (KitKat):Java JDK 6
根據需要選擇不同的 JDK,這裡編譯的是 Android 7.1.1,所以需要 jdk 8u45 或更高版本,安裝過程略。
2.2 安裝所需的應用程式
編譯 Android 7.1.1 原始碼需要 Mac OS v10.10 (Yosemite) 或更高版本,需要的應用程式有:
-
Xcode 4.5.2 和命令列工具
-
GNU Make 3.81 - 3.82(對於 Android 3.2.x (Honeycomb) 及更低版本,則需要將 make 3.82 還原到較低版本,以避免出現編譯錯誤)
- 安裝 Xcode 命令列工具
使用以下命令安裝 Xcode 命令列工具:
xcode-select --install
複製程式碼
- 安裝 MacPorts
在 macports.org 下載安裝 MacPorts。
然後在 ~/.bash_profile(如果是 zsh 則在 ~/.zshrc)檔案中新增:
export PATH=/opt/local/bin:$PATH
複製程式碼
- 使用 MacPorts 安裝 Make、Git 和 GPG
執行如下命令完成安裝:
POSIXLY_CORRECT=1 sudo port install gmake libsdl git gnupg
複製程式碼
3. 設定檔案描述符上限
在 Mac OS 中,可同時開啟的檔案描述符的預設數量上限太低,在高度並行的編譯流程中,可能會超出此上限。
所以要提高此上限,在 ~/.bash_profile 檔案中新增如下內容:
# set the number of open files to be 1024
ulimit -S -n 1024
複製程式碼
注:這裡建議在 ~/.bash_profile 檔案中新增,因為編譯 Android 原始碼只支援 bash,使用 zsh 或其它的 shell 可能會出現錯誤。
二、下載原始碼
1. 安裝 Repo
要處理 Android 程式碼,需要同時使用 Git 和 Repo,使用 Repo 執行基本的跨網路操作可簡化工作。
Repo 是以 Git 為基礎的程式碼庫管理工具。Repo 可以在必要時整合多個 Git 程式碼庫,將相關內容上傳到我們的修訂版本控制系統,並自動執行 Android 開發工作流程的部分環節。Repo 並非用來取代 Git,只是為了讓您在 Android 環境中更輕鬆地使用 Git。更多資訊請參閱開發部分。
- 在主目錄下建立 bin/ 目錄,並新增到 PATH 中:
mkdir ~/bin
PATH=~/bin:$PATH
複製程式碼
注:Repo 命令是一段可執行的 Python 指令碼,您可以將其放在路徑中的任何位置。
- 下載 Repo 工具
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
複製程式碼
- 確保 Repo 可執行
chmod a+x ~/bin/repo
複製程式碼
2. 初始化 Repo 客戶端
- 建立目錄
在之前建立的區分大小寫的分割槽中建立目錄,來存放 Android 原始碼,名字自定:
mkdir WORKING_DIRECTORY
cd WORKING_DIRECTORY
複製程式碼
如果是使用上面的 mountAndroid 命令來掛載分割槽的話,則可以使用 /Volumes/android/ 目錄
- 初始化
使用 repo init 獲取最新版本的 Repo 以及補丁,-u 用於指定 Android 原始碼中包含的各個程式碼庫將位於工作目錄中的什麼位置的網址,-b 用於指定相應的系統版本分支。要檢視分支列表,請參閱原始碼標記和版本。
獲取 Android 7.1.1 的版本分支:
repo init -u https://android.googlesource.com/platform/manifest -b android-7.1.1_r26
複製程式碼
初始化成功後,會產生一個 .repo 目錄,清單等檔案將儲存在該目錄下。
3. 下載 Android 原始碼
執行以下命令下載 Android 原始碼:
repo sync
複製程式碼
注:建議翻牆下載或者使用映象,如清華的映象:
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-7.1.1_r26 複製程式碼
三、編譯原始碼
切換 shell
編譯 Android 原始碼只支援 bash,如果使用的是其它的 shell 需要先切換到 bash。
切換方法有兩種:
-
臨時切換:
終端重啟後失效,切換方法為直接在終端輸入 shell 的名稱:
/bin/bash 複製程式碼
-
修改預設 shell:
終端重啟後生效,切換方法如下:
chsh -s /bin/bash 複製程式碼
可以使用以下命令檢視當前 shell:
echo $0
複製程式碼
1. 設定環境
通過原始碼 build 目錄中的 envsetup.sh 指令碼檔案初始化我們的編譯環境。
執行如下命令:
source build/envsetup.sh
複製程式碼
或
. build/envsetup.sh
複製程式碼
執行結果:
including device/asus/fugu/vendorsetup.sh
including device/generic/mini-emulator-arm64/vendorsetup.sh
including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
including device/generic/mini-emulator-mips/vendorsetup.sh
including device/generic/mini-emulator-mips64/vendorsetup.sh
including device/generic/mini-emulator-x86/vendorsetup.sh
including device/generic/mini-emulator-x86_64/vendorsetup.sh
including device/google/dragon/vendorsetup.sh
including device/google/marlin/vendorsetup.sh
including device/htc/flounder/vendorsetup.sh
including device/huawei/angler/vendorsetup.sh
including device/lge/bullhead/vendorsetup.sh
including device/linaro/hikey/vendorsetup.sh
including device/moto/shamu/vendorsetup.sh
including sdk/bash_completion/adb.bash
複製程式碼
2. 選擇目標
使用 lunch 選擇要編譯的目標。
執行 lunch 命令會顯示可選的編譯目標型別:
lunch
複製程式碼
執行結果:
You're building on Darwin
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. full_fugu-userdebug
8. aosp_fugu-userdebug
9. mini_emulator_arm64-userdebug
10. m_e_arm-userdebug
11. m_e_mips-userdebug
12. m_e_mips64-eng
13. mini_emulator_x86-userdebug
14. mini_emulator_x86_64-userdebug
15. aosp_dragon-userdebug
16. aosp_dragon-eng
17. aosp_marlin-userdebug
18. aosp_sailfish-userdebug
19. aosp_flounder-userdebug
20. aosp_angler-userdebug
21. aosp_bullhead-userdebug
22. hikey-userdebug
23. aosp_shamu-userdebug
Which would you like? [aosp_arm-eng]
複製程式碼
編譯目標都採用 BUILD-BUILDTYPE 形式,其中 BUILD 是表示特定功能組合的代號。
BUILDTYPE 是以下型別之一:
編譯型別 | 使用情況 |
---|---|
user | 許可權受限;適用於生成環境 |
userdebug | 與“user”類似,但具有 root 許可權和可除錯性;是進行除錯時的首選編譯型別 |
eng | 具有額外除錯工具的開發配置 |
開發使用的話,一般選擇 -eng。
因為這裡是準備使用模擬器執行編譯的原始碼,並且電腦的 CPU 是 x86 的,所以選擇 5. aosp_x86-eng 或 6. aosp_x86_64-eng。
執行如下命令:
lunch aosp_x86-eng
複製程式碼
執行結果:
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=7.1.1
TARGET_PRODUCT=aosp_x86
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=x86
TARGET_ARCH_VARIANT=x86
TARGET_CPU_VARIANT=
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=darwin
HOST_OS_EXTRA=Darwin-16.6.0-x86_64-i386-64bit
HOST_CROSS_OS=
HOST_CROSS_ARCH=
HOST_CROSS_2ND_ARCH=
HOST_BUILD_TYPE=release
BUILD_ID=NOF27C
OUT_DIR=out
============================================
複製程式碼
3. 編譯原始碼
在原始碼路徑下使用 make 命令編譯原始碼,可以使用 -jN 引數設定並行任務,N 為並行的任務數,一般為 CPU 執行緒數的 1-2 倍之間。
這裡是用以下命令:
make -j4
複製程式碼
成功編譯完成後會有以下顯示:
#### make completed successfully (02:51:05 (hh:mm:ss)) ####
複製程式碼
4. 執行模擬器
編譯完成後,執行 emulator 命令可以執行模擬器:
emulator
複製程式碼
第一次啟動時間會比較長。
四、編譯中遇到的問題
1. Can not find SDK 10.8 at /Developer/SDKs/MacOSX10.8.sdk
檢視 build/core/combo/mac_version.mk 檔案,可以看到裡面有如下設定:
mac_sdk_versions_supported := 10.8 10.9 10.10 10.11
複製程式碼
由此可知,支援的 Mac SDK 版本。
因為電腦的系統版本是 MacOS Sierra 10.12,在 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 目錄下只有 MacOSX10.12.sdk,所以會有報錯。
解決辦法:
網上的一些解決辦法是修改 mac_version.mk 檔案中的配置,使支援 10.12 版本:
mac_sdk_versions_supported := 10.8 10.9 10.10 10.11 10.12
複製程式碼
如果按照如上修改方法,在編譯原始碼時會出現 error: 'syscall' is deprecated 的問題,這是因為在 10.12 版本中棄用了 syscall。
所以不能修改 mac_version.mk 檔案中的配置,那麼就需要在 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 目錄下新增 MacOSX10.11.sdk。
在 github.com/phracker/Ma… 下載 MacOSX10.11.sdk。並拷貝到 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 目錄下,即可解決。
2. OOM
執行如下命令修改記憶體大小:
export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4g"
複製程式碼
然後重啟 jack 服務:
./prebuilts/sdk/tools/jack-admin kill-server
./prebuilts/sdk/tools/jack-admin start-server
複製程式碼