2013年9月6日 星期五

編譯 Android AOSP

先前曾經寫過一篇怎麼下載 Android AOSP 原始碼的文章。不過還沒說怎麼編譯 Android Open Source Project。雖然官方網頁有很詳細的說明,但我自己有遇到一些無法執行的步驟,而且有很多可選的步驟不太好讀。所以我就花一點時間把我自己的步驟寫下來。希望可以拋磚引玉。

準備編譯環境


安裝套件


根據官方的說明文件,最適合編譯 Android 的開發環境為 Ubuntu 12.04 (x86_64)。以下文章我們假設大家的環境都是 Ubuntu 12.04。首先在開始之前,我們必須要安裝一些必要的套件:

$ sudo apt-get install git gnupg flex bison gperf build-essential \
    zip curl libc6-dev libncurses5-dev:i386 x11proto-core-dev \
    libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-glx:i386 \
    libgl1-mesa-dev g++-multilib gcc-multilib mingw32 tofrodos \
    python-markdown libxml2-utils xsltproc zlib1g-dev:i386


另外為了可以讓 Build System 找得到  Mesa3d 函式庫,我們必須為他建立一個 Soft Link:

$ sudo ln -s /usr/lib/i386-linux-gnu/mesa/libGL.so.1 /usr/lib/i386-linux-gnu/libGL.so

如果你在 apt-get install 時,遇到類似下面的錯誤(沒有遇到可以直接跳到 Java 的段落):

E: Unable to locate package mingw32
E: Package 'python-markdown' has no installation candidate

這是因為你的 APT 沒有開啟 Universe 來源(也就是第三方維護的自由軟體)。我們要先把他加進 Ubuntu 軟體來源,然後再更新套件資訊。

$ sudo vim /etc/apt/sources.list
# 找到 "deb http://archive.ubuntu.com/ubuntu precise main" 在後面加上 universe

$ sudo apt-get update

等到 apt-get update 執行完,再從頭開始執行應該就不會有問題了。

安裝 OpenJDK 7 JDK


如果要編譯最新的 Android,你會需要 Java 7。你可以用以下指令安裝 OpenJDK 7:

$ sudo apt-get install openjdk-7-jdk

之後如果我們要編譯 Android 之前,我們必須記得:

$ export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
$ export PATH=$JAVA_HOME/bin:$PATH


安裝 Java SE 6 JDK


如果你是要編譯較舊的 Android,你會需要 Java SE 6 JDK,如果你是要編譯最新的 Android,可以跳過這一節。我們必需到 Oracle 網站取得 Java SE Development Kit 6u45 (Java SE 6 JDK)。因為我們的環境是 Ubuntu,所以我們要下載的是  jdk-6u45-linux-x64.bin。下載之後,就依下述指令安裝:

$ chmod +x ./jdk-6u45-linux-x64.bin
$ ./jdk-6u45-linux-x64.bin
$ mv jdk1.6.0_45 /opt

之後如果我們要編譯 Android 之前,我們必須記得:

$ export JAVA_HOME=/opt/jdk1.6.0_45
$ export PATH=$JAVA_HOME/bin:$PATH


取得 repo 管理工具


因為 Android 是一個很大的專案,由數百個 Git 版本庫所構成。為了管理這些版本庫,Google 開發了 repo 這個 Git 管理工具。透過 repo 我們可以一次下載整個 Android 原始碼樹。我們必須先取得 repo:

$ mkdir ~/bin
$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod +x ~/bin/repo
$ export PATH=~/bin:$PATH

取得原始碼與 Prebuilt Binaries


下載 Android 原始碼


和先前那篇一樣,我們現在可以下載 AOSP 的原始碼了!我們先建立一個資料夾,再使用 repo init 取得 Android Source Tree 的設定檔。最後使用 repo sync 把所有 Git 版本庫抓到本地端。

$ mkdir ~/android-src
$ cd ~/android-src
$ repo init -u https://android.googlesource.com/platform/manifest
$ repo sync -j2

下載 Prebuilt Binaries


如果要刷手機,我們還需要一些來自廠商的驅動程式或 Prebuilt Binaries。我們可以到 Binaries for Nexus Devices 找到 Nexus 系列所需的驅動程式。下載之後(以 broadcom-maguro-jdq39-8edbeae8.tgz 為例),我們先把壓縮檔放在 ~/android-src,然後:

$ cd ~/android-src
$ tar zxvf broadcom-maguro-jdq39-8edbeae8.tgz
$ ./extract-broadcom-maguro.sh
# 按下 Enter,再按下 q,輸入 "I ACCEPT" 之後按下 Enter 即可。

編譯 Android 原始碼


取得所有程式碼之後我們就可以開始編譯整個 Android。首先我們必需先設定好環境變數:

$ cd ~/android-src
$ export JAVA_HOME=/opt/jdk1.6.0_45
$ export PATH=$JAVA_HOME/bin:$PATH
$ source build/envsetup.sh

選取你想要編譯的目標。一般來說 full-eng 就可以滿足所需。如果你要刷手機,可能要從 Building for Devices 頁面找到合適的目標。

$ lunch full-eng

接下來我們就可以開始編譯了!

$ make -j16
(...中略...)
Install system fs image: out/target/product/generic/system.img
out/target/product/generic/system.img+ maxsize=588791808 blocksize=2112 total=576716800 reserve=5947392

經過漫長的等待,如果你可以在最後看到類似上面的訊息,那整個 Android 就成功完成編譯工作,我們可以打開模擬器或刷手機了。

開啟模擬器


開啟模擬器的方法非常容易,只要輸入以下指令:

$ ./out/host/linux-x86/bin/emulator

  • 根據我的測試,有些目標例如 full_maguro-eng 沒辦法使用模擬器。如果要使用模擬器要改用 lunch full-eng。
  • 如果你之後要使用模擬器,但是看到:

    emulator: ERROR: You did not specify a virtual device name, and the system directory could not be found.

    那是因為你忘記 lunch full-eng 了。我們必需 lunch full-eng 模擬器才能找到對應的 System Image。

刷手機


在刷手機之前,最好先上網尋找有沒有成功的案例。因為刷機一定會違反保固條款失去保固。其次,如果指令錯誤更有可能讓你的手機變成磚塊。一般來說,Google 推出的 Nexus 系列都沒有什麼大問題。但是因為不同的手機有不同的狀況,本文僅供參考,不為後果負責

首先我們先看 adb 能不能抓到你的手機:

$ adb devices

  • 如果看不到你的裝置,有可能是 udev 設定檔沒有設好。可以參考 Configuring USB Access,建立 /etc/udev/rules.d/51-android.rules。
  • 如果你有看到裝置,但是在 offline 的狀態。這有可能是因為你沒有開啟手機的開發者選項。你可以拿起手機,進入「Setting/About Phone/Build Number」,連續點 7 下。之後在「Developer Options」頁面勾選「USB Debugging」。

接下來我們要開機進入刷機模式:

$ adb reboot bootloader

這時我們可以看到手機進入 Bootloader,我們可以用 fastboot devices 尋找手機:

$ fastboot devices

如果你還沒有 Unlock 手機,這時我們就可以 Unlock 他。注意:這一步會讓保固失效!

$ fastboot oem unlock

最後,我們來刷手機。刷手機的過程絕對不能拔手機線。

$ fastboot flashall

除了把新的映象檔刷進手機,我們還要清空所有 User Data 與 Cache。否則 Android 有一定的機會一直停留在開機畫面。

$ fastboot erase userdata
$ fastboot erase cache

最後我們就可以重新開機!

$ fastboot reboot

我們可以用 adb logcat 觀察開機過程。有時候會遇到一直開不了機的情況。這時可以先試著清空 User Data 與 Cache。如果還是有問題,有時候是 AOSP 有問題,可以先刷回官方的映象檔。

結語


本文簡單的介紹怎麼編譯 Android Open Source Project 與刷機的基本流程。 希望大家看完之後有能力自己 Hack Android。Happy hacking!