第一章 源碼下載、編譯與調試

第一章 源碼下載、編譯與調試

**注意:**做爲Android開發人員,心裏多少有對源碼的嚮往,研究源碼能夠說是開發人員的榮耀,彰顯了對系統的認知度,本文適用於Ubuntu 16.04上編譯Android 6.0.*及以上版本,其餘狀況請酌情處理,自行參考官網,源碼針對系統8.0分析。python

@(源碼系列)linux

##摘要 android源碼編譯的四個流程:android

  • 源碼下載
  • 構建編譯環境
  • 編譯源碼
  • 運行

下文也將按照該流程講述.git

##1.源碼下載 因爲牆的緣由,不少人採用國內的鏡像源進行下載。不過筆者經過設置hosts能夠在官方地址上下載源碼,配置項以下:shell

110.4.24.178    www.googlesource.com
110.4.24.178    android.googlesource.com
110.4.24.178    dl-ssl.google.com
110.4.24.178    gerrit.googlesource.com
110.4.24.178    www.google.com
110.4.24.178    google.com
110.4.24.178    google.com.hk
110.4.24.178    www.google.com.hk
110.4.24.178    chromium.googlesource.com

地址查詢來源,參考google代理hosts查詢,按期更新,用起來很是方便。 在ubuntu下,下載代碼仍是比較簡單的,步驟分爲4步:ubuntu

1.下載repo toolapi

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

2.初始化repo下載代碼,須要註冊谷歌帳號,與本身git配置相對應,注意姓名的排序,lastName在前。bash

mkdir WORKING_DIRECTORY
cd WORKING_DIRECTORY
git config --global user.name "Your Name"
git config --global user.email "you@example.com"

3.repo初始化,選擇須要下載的分支markdown

repo init -u https://android.googlesource.com/platform/manifest
# 若是不填寫分支默認下載master或經過-b切換至對應的分支
repo init -u https://android.googlesource.com/platform/manifest -b android-6.0.1_r1

4.同步android源碼網絡

repo sync

**提示:**這裏,來簡單的介紹下repo工具,咱們知道AOSP項目由不一樣的子項目組成,爲了方便進行管理,Google採用Git對AOSP項目進行多倉庫管理。AOSP項目當前全部的分支列表參看分支列表

之後若是須要同步最新的遠程代碼到本地,也只須要執行該命令便可。在同步過程當中,若是由於網絡緣由中斷,使用該命令繼續同步便可。不出意外,5個小時即可以將所有源碼同步到本地。

**提示:**必定要肯定代碼徹底同步了,否則在下面編譯過程出現的錯誤會讓你痛不欲生,不肯定的童鞋能夠多用repo sync同步幾回。

因爲網絡緣由,在使用repo sync同步代碼的過程當中會屢次出錯,總不能時時刻刻刻盯着,能不能在同步失敗的狀況下,自動重試呢?固然能夠,咱們能夠寫一個簡單的shell腳本:

#!/bin/bash
#FileName source_asyn.sh
PATH=~/bin:$PATH
# 注意修改爲你要編譯的版本,固然也能夠不填
repo init -u https://android.googlesource.com/platform/manifest
repo sync
while [$? = 1]: do
echo "=========download failed,again============"
sleep 5
repo sync
done

將該文件保存在源碼目錄下,也就是咱們的source目錄,而後執行該腳本便可,如今能夠安心的等待源碼下載完成了。

注意:因爲.repo目錄是隱藏目錄,所以在下載完成以前你是不看到啥東西的。

##2.源碼編譯 ###2.1編譯環境 源碼下載完成後,就能夠構建編譯環境了。在開始以前,咱們先來看看一些編譯要求:

硬件

磁盤空間越多越好,至少在100GB以上

軟件

|Android版本| 編譯要求的Ubuntu最低版本| 編譯要求的JDK版本| |--| |Android 6.0至AOSP master| Ubuntu 14.04|OpenJDK 8| |Android 5.x至AOSP 6.0| Ubuntu 12.04|OpenJDK 7| |Android 2.3.x至Android 5.0| Ubuntu 12.04|Oracle JDK 6| |Android 1.5至Android 2.2.x| Ubuntu 10.04|Oracle JDK 5|

更具體的能夠參看:Google源碼編譯要求

我如今在Ubuntu 16.04下編譯AOSP主線代碼,所以須要安裝OpenJDK 8,執行命令以下:

sudo apt-get install openjdk-8-jdk

其它需求

sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib 
sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386 
sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386 
sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev
sudo apt-get install git-core gnupg flex bison gperf build-essential  
sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib 
sudo apt-get install libc6-dev-i386 
sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev 
sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
sudo apt-get install lib32z-dev ccache

###2.2初始化編譯 首先初始化編譯環境,確保上述過程完整完成,接下來咱們須要初始化編譯環境,命令以下:

source build/envsetup.sh

不難發現該命令只是引入了其餘執行腳本,至於這些腳本作什麼,目前不在本文中細說.。該命令執行成功後,咱們會獲得了一些有用的命令,好比最下面要用到的lunch命令。

###2.3編譯源碼 初始化編譯環境以後,就進入源碼編譯階段。這個階段又包括兩個階段:選擇編譯目標和執行編譯。 ####2.3.1選擇編譯目標 經過lunch指令設置編譯目標,所謂的編譯目標就是生成的鏡像要運行在什麼樣的設備上。這裏咱們設置的編譯目標是aosp_arm64-eng,所以執行指令:

lunch aosp_arm64-eng

編譯目標格式說明 編譯目標的格式:BUILD-BUILDTYPE,好比上面的aosp_arm-eng的BUILD是aosp_arm,BUILDTYPE是eng

什麼是BUILD

BUILD指的是特定功能的組合的特定名稱,即表示編譯出的鏡像能夠運行在什麼環境。其中aosp(Android Open Source Project)表明Android開源項目;arm表示系統是運行在arm架構的處理器上;arm64則是指64位arm架構;處理器x86則表示x86架構的處理器;此外,還有一些單詞表明瞭特定的Nexus設備,下面是經常使用的設備代碼和編譯目標,更多參考官方文檔

|受型號| 設備代碼| 編譯目標| |:--| |Nexus 6P| angler| aosp_angler-userdebug| |Nexus 5X| bullhead| aosp_bullhead-userdebug| |Nexus 6| shamu| aosp_shamu-userdebug| |Nexus 5| hammerhead| aosp_hammerhead-userdebug|

提示:若是你沒有Nexus設備,那麼一般選擇arm或者x86便可

什麼是BUILDTYPE

BUILD TYPE則指的是編譯類型,一般有三種:

  • user:表明這是編譯出的系統鏡像是能夠用來正式發佈到市場的版本,其權限是被限制的(如沒有root權限,不包含dedug等)
  • userdebug:在user版本的基礎上開放了root權限和debug權限。
  • eng:表明engineer,也就是所謂的開發工程師的版本,擁有最大的權限(root等),此外還附帶了許多debug工具

瞭解編譯目標的組成以後,咱們就能夠根據本身目前的狀況選擇了。那不知道編譯目標怎麼辦?咱們只須要執行不帶參數的lunch指令,稍後控制檯會列出全部的編譯目標,以下:

接着咱們只須要輸入相應的數字便可。 來舉個例子:你沒有Nexus設備,只想編譯完後運行看看,那麼就能夠選擇aosp_arm-eng。(我在ubuntu 16.04(64位)中編譯完成後啓動虛擬機時,卡在黑屏,嘗試編譯aosp_arm64-eng解決。所以這裏我使用了aosp_arm64-eng)

####2.3.2開始編譯 經過make指令進行代碼編譯,該指令經過-j參數來設置參與編譯的線程數量,以提升編譯速度。好比這裏咱們設置8個線程同時編譯:

make -j8

須要注意的是,參與編譯的線程並非越多越好,一般是根據你機器cup的核心來肯定:core*2,即當前cpu的核心的2倍。好比我如今的筆記本是雙核四線程的,所以根據公式,最快速的編譯能夠make -j8

經過cat /proc/cpuinfo查看相關cpu信息

若是一切順利的化,在幾個小時以後,即可以編譯完成。看到

### make completed successfully (04:16:38(hh:mm:ss)) ###

表示你編譯成功了。

###2.4運行模擬器 在編譯完成以後,就能夠經過如下命令運行Android虛擬機了,命令以下:

source build/envsetup.sh
lunch(選擇剛纔你設置的目標版本,好比這裏了我選擇的是2)
emulator

若是你是在編譯完後馬上運行虛擬機,因爲咱們以前已經執行過source及lunch命令了,所以如今你只須要執行命令就能夠運行虛擬機:

emulator

不出意外,在等待一會以後,你會看到運行界面: 運行界面

**補充:**既然談到了模擬器運行,這裏咱們順便介紹模擬器運行所須要四個文件: Linux Kernelsystem.imguserdate.imgramdisk.img 若是你在使用 lunch命令時選擇的是aosp_arm-eng,那麼在執行不帶參數的emualtor命令時,Linux Kernel默認使用的是/source/prebuilds/qemu-kernel/arm/kernel-qemu目錄下的kernel-qemu文件;而android鏡像文件則是默認使用source/out/target/product/generic目錄下的system.imguserdata.imgramdisk.img,也就是咱們剛剛編譯出來的鏡像文件。

上面我在使用lunch命令時選擇的是aosp_arm64-eng,所以linux默認使用的/source/prebuilds/qemu-kernel/arm64/kernel-qemu下的kernel-qemu,而其餘文件則是使用的source/out/target/product/generic64目錄下的system.imguserdata.imgramdisk.img

固然emulator指令容許你經過參數制定使用不一樣的文件,具體用法能夠經過emulator --help查看。

###2.5模塊編譯 除了經過make命令編譯能夠整個android源碼外,Google也爲咱們提供了相應的命令來支持單獨模塊的編譯。編譯環境初始化(即執行source build/envsetup.sh)以後,咱們能夠獲得一些有用的指令,除了上邊用到的lunch,還有如下:

- croot: Changes directory to the top of the tree.
 - m: Makes from the top of the tree.
 - mm: Builds all of the modules in the current directory.
 - mmm: Builds all of the modules in the supplied directories.
 - cgrep: Greps on all local C/C++ files.
 - jgrep: Greps on all local Java files.
 - resgrep: Greps on all local res/*.xml files.
 - godir: Go to the directory containing a file.

其中mmm指令就是用來編譯指定目錄。一般來講,每一個目錄只包含一個模塊。好比這裏咱們要編譯Launcher2模塊,執行指令:

mmm packages/apps/Launcher2/

稍等一會以後,若是提示:

### make completed success fully ###

即表示編譯完成,此時在out/target/product/gereric/system/app就能夠看到編譯的Launcher2.apk文件了。

從新打包系統鏡像

編譯好指定模塊後,若是咱們想要將該模塊對應的apk集成到系統鏡像中,須要藉助make snod指令從新打包系統鏡像,這樣咱們新生成的system.img中就包含了剛纔編譯的Launcher2模塊了,重啓模擬器以後生效。

單獨安裝模塊

咱們在不斷的修改某些模塊,總不能每次編譯完成後都要從新打包system.img,而後重啓手機吧?有沒有什麼簡單的方法呢? 在編譯完後,藉助adb install命令直接將生成的apk文件安裝到設備上便可,相比使用make snod,會節省不少事件。

補充:咱們來介紹out/target/product/generic/system目錄下的內容: 系統自帶apk文件:out/target/product/generic/system/apk目錄下; 系統可執行文件:out/target/product/generic/system/bin目錄下; 動態連接庫:out/target/product/generic/system/lib目錄下; 硬件抽象層文件:out/targer/product/generic/system/lib/hw目錄下。

###2.6錯誤合集 1. 提示:error processing archive /var/cache/apt/archives/lib32z1-dev_

在安裝依賴的時候有一個依賴不能順利安裝:

sudo apt-get install lib32z-dev ccache

這裏筆者也是安裝你們推薦的依賴安裝,若是出現任何不能安裝的依賴都會去解決一下,解決辦法爲:

sudo dpkg -i --force-overwrite <filename>
# 以下例
sudo dpkg -i --force-overwrite /var/cache/apt/archives/lib32z1-dev_1%3a1.2.8.dfsg-2ubtuntu4_amd64.deb
# 而後執行
sudo apt-get -f install

問題順利解決。

##3.源碼調試 咱們已經描述了Android源碼在Ubuntu 16.0.4上下載和編譯的過程,目前咱們已經順利的編譯出android的成果文件:

下載源碼初衷咱們是爲了調試代碼,查看其中的運行機制和關鍵過程,理解其精髓。好比咱們對PMS過程不是很瞭解,如何打個斷點查看一下,亦或是根據本身思想改進一下,都是很是值得嘗試的。下面咱們來講說如何調試源碼,一樣這裏的工做平臺仍是ubuntu 16.04和Android Studio。

**參考:**源碼中developent/tools/idegen/README文檔

###3.1調試準備 在源碼中,存在idegen模塊,該模塊專門用來爲idea工具生成系統源碼的project。在開始調試以前,須要確保當前已經編譯過Android源碼了,若是沒有,跳轉至第二章編譯源碼,時間大概4-5個小時。準備過程分爲以下幾個過程:

  1. 工程文件生成android.iprandroid.iml
  2. 修改android.iml文件提升as啓動速度
  3. 設置jdk和sdk,導入源碼

1.工程文件生成

檢查out/host/Linux-x86/framework/目錄下是否存在idegen.jar文件,存在則說明你已經編譯過該模塊,若是沒有編譯過則須要編譯。執行以下命令便可:

source build/envsetup.sh
mmm development/tools/idegen/

其中mmm development/tools/idegen/執行完成後會生成idegen.jar,在已經編譯過idegen模塊後,執行:

sudo ./development/tools/idegen/idegen.sh

會在源碼目錄下生成IEDA工程配置文件:android.iprandroid.iml文件,文件什麼做用呢?

  • android.ipr:一般是保存工程相關的設置,好比編譯器配置入口相關的libraries等
  • android.iml:則是主要是描述了modules,好比modules的路徑,依賴關係等

2.修改android.iml

android源碼的體量仍是很大的,若是直接使用Android Studio導入工程,須要漫長的等待時間,看代碼仍是選擇source Insight。這就要求咱們有選擇的導入模塊,選擇須要導入。在導入前修改android.iml文件,經過添加配置的方式告訴AS不導入某些模塊,好比如今我不想導入art模塊,那麼就在android.iml文件中添加:

<excludeFloder url="file://$MODULE_DIR$"/abi>

格式爲:<excludeFloder url="file://$MODULE_DIR$"/模塊名> ,這裏只保留了framworks和packages模塊,將其餘模塊所有排除了,所以在android.iml中添加了如下配置:

<excludeFolder url="file://$MODULE_DIR$/.repo" />
<excludeFolder url="file://$MODULE_DIR$/abi" />
<excludeFolder url="file://$MODULE_DIR$/art" />
<excludeFolder url="file://$MODULE_DIR$/bionic" />
<excludeFolder url="file://$MODULE_DIR$/bootable" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/cts" />
<excludeFolder url="file://$MODULE_DIR$/dalvik" />
<excludeFolder url="file://$MODULE_DIR$/developers" />
<excludeFolder url="file://$MODULE_DIR$/development" />
<excludeFolder url="file://$MODULE_DIR$/device" />
<excludeFolder url="file://$MODULE_DIR$/docs" />
<excludeFolder url="file://$MODULE_DIR$/external" />
<excludeFolder url="file://$MODULE_DIR$/hardware" />
<excludeFolder url="file://$MODULE_DIR$/libcore" />
<excludeFolder url="file://$MODULE_DIR$/libnativehelper" />
<excludeFolder url="file://$MODULE_DIR$/ndk" />
<excludeFolder url="file://$MODULE_DIR$/out" />
<excludeFolder url="file://$MODULE_DIR$/pdk" />
<excludeFolder url="file://$MODULE_DIR$/prebuilt" />
<excludeFolder url="file://$MODULE_DIR$/prebuilts" />
<excludeFolder url="file://$MODULE_DIR$/sdk" />
<excludeFolder url="file://$MODULE_DIR$/system" />
<excludeFolder url="file://$MODULE_DIR$/tools" />

3.設置jdk和sdk,導入源碼

在完成android.iml文件的修改後,將源碼工程導入至AS,以下圖所示:

源碼工程導入至AS

圖3.1 源碼工程導入至AS

導入時間會比較長,要耐心等待,若是已經將所有項目導入到AS中,而又想排除一些模塊該怎麼辦呢? 此時能夠在Project Scureture的Mobules中進行排除。 爲了排除android sdudio的Sdk中依賴的干擾,須要改進當前的jdk和sdk,讓代碼跳轉也在源碼的文件中,而不能在依賴於外部的sdk項目,點擊Project Structure進入到項目配置頁面: 設置jdk

圖3.2 設置工程的jdk

選擇新建,新建一個jdk,將其classpath標籤下的內容通通刪除,選擇Android API 25 Platform將當前新建的JDK配置給它。 jdk配置

圖3.3 jdk配置給Android API 25 Platform

###3.2調試源碼 搞定上面以後,如今咱們來看看如何用Android Studio一步一步調試代碼。首先使用emulator命令啓動咱們的虛擬機,啓動完虛擬機後,運行的是咱們源碼編譯的最新的系統。接下來打開android studio,打開源碼工程,選擇Attache debugger to Android process選項,在彈出的Choose Process框內必須選擇Show all processes,不然看不到相關的進程,能夠看到系統的不少進程。如system_process、com.android.systemui、com.android.settings等不少進程。

**注意:**在虛擬機或設備運行了咱們編譯的系統後,擁有的是root權限,能夠查看全部進程,這與咱們前面說的BUILDTYPE爲eng相關,方便開發和調試

選擇任意一個進程,這裏以com.android.settings進程爲例,並在包名爲com.android.settings的SettingsActivity的onCreate()函數上打上斷點,打開虛擬機的設置,源碼會在onCreate()函數上中止,此時能夠對源碼進行斷點調試。

##參考

本身動手編譯最新Android源碼及SDK 本身動手調試Android源碼 android源碼-下載與管理

相關文章
相關標籤/搜索