Android FrameWork 之原始碼編譯

zly394發表於2018-03-28

一、配置 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 要求:

根據需要選擇不同的 JDK,這裡編譯的是 Android 7.1.1,所以需要 jdk 8u45 或更高版本,安裝過程略。

2.2 安裝所需的應用程式

編譯 Android 7.1.1 原始碼需要 Mac OS v10.10 (Yosemite) 或更高版本,需要的應用程式有:

  1. 安裝 Xcode 命令列工具

使用以下命令安裝 Xcode 命令列工具:

xcode-select --install
複製程式碼
  1. 安裝 MacPorts

macports.org 下載安裝 MacPorts。

然後在 ~/.bash_profile(如果是 zsh 則在 ~/.zshrc)檔案中新增:

export PATH=/opt/local/bin:$PATH
複製程式碼
  1. 使用 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。更多資訊請參閱開發部分。

  1. 在主目錄下建立 bin/ 目錄,並新增到 PATH 中:
mkdir ~/bin
PATH=~/bin:$PATH
複製程式碼

注:Repo 命令是一段可執行的 Python 指令碼,您可以將其放在路徑中的任何位置。

  1. 下載 Repo 工具
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
複製程式碼
  1. 確保 Repo 可執行
chmod a+x ~/bin/repo
複製程式碼

2. 初始化 Repo 客戶端

  1. 建立目錄

在之前建立的區分大小寫的分割槽中建立目錄,來存放 Android 原始碼,名字自定:

mkdir WORKING_DIRECTORY
cd WORKING_DIRECTORY
複製程式碼

如果是使用上面的 mountAndroid 命令來掛載分割槽的話,則可以使用 /Volumes/android/ 目錄

  1. 初始化

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

第一次啟動時間會比較長。

Android FrameWork 之原始碼編譯

四、編譯中遇到的問題

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
複製程式碼

3. 其他警告資訊如果沒有終止編譯可以忽略

相關文章