Ubantu18.04環境下編譯android源碼

最近在看金泰延老師寫的《Android 框架揭祕》一書,第一章就是下載並編譯android源碼,書中內容較爲陳舊,所以不得不到網上收羅各種資料,最後總算是大功告成,現在總結如下。

1、安裝git和repo並配置

安裝git通過下面命令實現

sudo apt-get install git

另外還需要配置好git的user.email和user.name,這個自己隨便寫就行了

git config --global user.name "your name"
git config --global user.email "[email protected]"

然後由於我們是通過repo來拉取android源碼的,git配置好後,還得安裝配置repo

git clone https://aosp.tuna.tsinghua.edu.cn/git-repo/
chmod a+x git-repo/repo

然後添加repo(路徑目錄如:~/git-repo/repo)到PATH環境變量

export PATH=~/git-repo:$PATH

然後到打開~/git-repo/repo文件,將REPO_URL替換爲清華鏡像地址,以避免下載android源碼時可能出現的無法連接到 gerrit.googlesource.com問題。

REPO_URL = 'https://mirrors.tuna.tsinghua.edu.cn/git/git-repo'

2、下載andriod源碼

首先創建一個自己存放源碼的目錄,我是放在~/Android/source路徑下的,然後cd到對應的路徑下執行下面命令

repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest

然後執行如下命令可以查看可以下載的android源碼分支,目前我看到的已經可以獲取android-9.x的分支了。

cd .repo/manifests.git/
git branch -a

這裏同步android-8.1.0_r41分支並拉取對應分支源碼

repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-8.1.0_r41
repo sync

這個過程時間較長,可能需要幾個小時,期間該幹嘛幹嘛。

3、Ubuntu 18.04編譯環境配置

首先得配置java8

sudo apt-get install openjdk-8-jdk
sudo apt-get install openjdk-8-jre

注意這裏是配置openjdk,不要弄錯了,我之前是按照一篇教程配置了android studio環境,結果配置的jdk不是openjdk,執行java -version時有如下提示
這裏寫圖片描述
實際上在執行java -version有如下的openjdk提示時(版本號不一定相同),纔算是jdk配置成功
這裏寫圖片描述
然後配置在ubantu 18.04中編譯android源碼需要的一些依賴,這些依賴包在ubantu 16.04中編譯android源碼時也是需要的

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

到這裏編譯環境配置就算是完成了。

4、編譯Android源碼

這裏到了最關鍵也是最容易出問題的一步了,首先cd到應的源碼目路,初始化編譯環境

. build/envsetup.sh

初始化編譯環境後,引入了一些執行腳本,其中就包括馬上要使用的lunch指令。通過lunch指令可以設置編譯目標,所謂的編譯目標就是生成的鏡像要運行在什麼樣的設備上。這裏我們設置的編譯目標是aosp_arm64-eng,因此執行指令

lunch aosp_arm64-eng

簡單的說明下,aosp表示Android Open Source Project,arm64表示是使用arm64 cpu的設備,eng表示engineer版本,其直接開放了一些root等權限。當然直接使用lunch命令會列出所有可選的編譯目標。

最後,我們便可通過如下命令來開始編譯andriod源碼

make -j8

這裏的j8表示可以開啓8個線程來參與編譯源碼,這裏指定的線程數一般應該遵從cpu內核數的2倍這個規律,可以通過cat /proc/cpuinfo查看相關cpu信息。

5、編譯錯誤集錦

如果以爲第四小節的三步走戰略就可以直接編譯出可用的Android image來那就too young啦,實際上在編譯過程中,我遇到很多故障,同時由於編譯過程需要話費很多時間,所以整個編譯花費了我大把時間,這個童鞋們一定要作好心理準備。下面是我在編譯過程遇到的問題以及解決辦法總結

故障1:You are attemping to build with the incorrect version
這裏寫圖片描述
這個就是在編譯高版本android源碼時,可能出現的jdk版本問題,我之前是使用上面命令介紹的方式配置了openjdk卻在java -version發現還是不是open jdk版本,究其原因竟是我在更之前配置android studio時在/etc/profile 中配置了另一個jdk版本導致該問題發生,後面在/etc/profile中刪除對應配置就好了。

故障2:Out of memory error
這裏寫圖片描述
這個問題是因爲編譯過程中JVM heap size太小而導致的,解決辦法比較簡單

export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096m"
~/Android/source/prebuilts/sdk/tools/jack-admin kill-server
~/Android/source/prebuilts/sdk/tools/jack-admin start-server

通過這個配置可以講JVM heap size調整爲4g,這個應該是夠用的,這裏我們看到了jack-admin工具,後面可能還會使用這個工具,所以這裏直接建議配置jack-admin的環境變量

export PATH=$PATH:~/Android/source/prebuilts/sdk/tools

之後就可以直接使用如下命令來啓動jack-admin了

jack-admin start-server

故障3:sizeof (_nl_value_type_LC_TIME[0]))’ ???
這裏寫圖片描述
這裏圖片我是從其它博客哪裏拷過來的,但是的確碰到這個故障,通過下面配置去除本地化配置解決

export LC_ALL=C

故障4:No Jack server running. Try ‘jack-admin start-server’
這裏寫圖片描述
這個錯誤碰到的還不止一次,看到這個提示我們都知道是jack-admin沒有啓動的原因,重啓便可

jack-admin kill-server
jack-admin start-server

比較奇怪的是,有時自己明明開啓了jack-admin,但是在編譯的過程中,jack-admin卻掛掉了,這個得多注意。

我在編譯過程中主要是遇到了以上幾個故障,實際上其它博客上還有一些其它故障可以參考的,也只能在遇到具體故障的時候再百度google了,總之是編譯android源碼需要一定的耐心。

6、運行模擬器

在完成編譯後,我們可以直接通過emulator命令來運行模擬器

emulator

運行模擬器實際上需要四個組件

1、Linux Kernel
2、system.img
3、userdata.img
4、ramdisk.img

如果你在使用lunch命令時選擇的是aosp_arm-eng,那麼在執行不帶參數的emualtor命令時,Linux Kernel默認使用的是/source/prebuilds/qemu-kernel/arm/kernel-qemu目錄下的kernel-qemu文件。而android鏡像文件則是默認使用source/out/target/product/generic目錄下的system.img、userdata.img和ramdisk.img,也就是我們剛剛編譯出來的鏡像文件。

上面我在使用lunch命令時選擇的是aosp_arm64-eng,因此linux默認使用的/source/prebuilds/qemu-kernel/arm64/kernel-qemu下的kernel-qemu,而其他文件則是使用的source/out/target/product/generic64目錄下的system.img、userdata.img和ramdisk.img。
這裏寫圖片描述
在使用emulator命令後,正常的話,我們可以啓動模擬器,我這裏啓動的模擬器信息如下
這裏寫圖片描述
這裏可以看出啓動的是我們編譯時指定的aosp_arm64-eng模擬器,實際上emulator還有很多其它指令可以選擇,這個可以通過它的help命令來查看

emulator -help

7、單獨編譯模塊及SDK

除了通過make命令編譯可以整個android源碼外,Google也爲我們提供了相應的命令來支持單獨模塊的編譯。

編譯環境初始化(即執行. build/envsetup.sh)之後,我們可以得到一些有用的指令,除了上邊用到的lunch,在envsetup.sh文件中我們還可以找到如下的指令
這裏寫圖片描述
其中的mmm指令就可以用來編譯指定模塊,

mmm packages/apps/StorageManager/

稍等一會之後,如果提示編譯完成,此時便可在out/target/product/gereric_arm64/system/priv-app就可以找到編譯的StorageManager.apk文件了。

這裏寫圖片描述
編譯好指定模塊後,如果我們想要將該模塊對應的apk集成到系統鏡像中,需要藉助make snod指令重新打包系統鏡像,這樣我們新生成的system.img中就包含了剛纔編譯的Launcher2模塊了,重啓模擬器之後生效。

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

直接執行make是不包括make sdk的,如果要編譯自己的sdk則十分簡單,只需要執行如下命令便可

. build/envsetup.sh
lunch sdk-eng
make sdk

如果編譯成功,不出意外,在out/host/linux-x86/sdk就可以看到了。
補充
我們簡單的來介紹out/target/product/generic_arm64/system目錄下的常用目錄:
Android系統自帶的apk文件都在out/target/product/generic_arm64/system/priv-app目錄下
一些可執行文件(比如C編譯的執行),放在out/target/product/generic_arm64/system/bin目錄下
動態鏈接庫放在out/target/product/generic_arm64/system/lib目錄下
硬件抽象層文件都放在out/targer/product/generic_arm64/system/lib/hw目錄下

這裏需要注意的就是由於我們這裏編譯的是aosp_arm64-eng編譯目標,所以這裏的路徑中是generic_arm64,如果是編譯的其它目標路徑可能不一樣,比如當編譯的是aosp_arm-eng時,則路徑中就是generic。

到這裏Ubantu18.04環境下編譯android源碼基本介紹就算完成了。

參考文獻

1、自己動手編譯Android 8.0源碼
2、Ubuntu 18.04編譯Android8.1 automotive
3、自己動手編譯最新Android源碼及SDK(Ubuntu)
4、Linux Out of memory error
5、 Android 編譯命令
6、通過清華大學鏡像下載Android源碼並編譯源碼
7、Ubuntu環境中的Android源代碼下載
8、ERROR: No Jack server running

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章