[Android 編譯(一)] Ubuntu 16.04 LTS 成功編譯 Android 6.0 原始碼教程
1 前言
經過3天奮戰,終於在Ubuntu 16.04上把Android 6.0的原始碼編譯出來了,各種配置,各種error,各種爬坑,特寫此部落格記錄爬坑經歷。先上圖,Ubuntu上編譯完後成功執行模擬器,如圖:
2 編譯環境
- UbuntuKylin 16.04 LTS
- Android 6.0_r1
- Open JDK 7
3 準備工作
(1) 下載Android 6.0原始碼.
感謝下面這位博主上傳原始碼,我也是從他的部落格下載的原始碼:
下載原始碼請在Windows下面下載,迅雷不解釋。
注意:原始碼的存放路徑不能有中文,否則編譯到系統內建的apk的時候會報錯無法解析class.dex檔案
(2) 解壓原始碼,合併檔案。
下載完畢後,使用下面命令合併:
cat Android6_r1_*>Android6_r1.tgz
合併完後,使用下面命令校驗hash:
md5sum Android6_r1.tgz
此時會生成一個hash串,如圖:
對比你下載的檔案裡面的hash.txt,如果一致那麼繼續,不一致則檔案損壞,重新下載。
(3) 解壓原始碼。
tar -zxvf Android6_r1.tgz
解壓原始碼是個漫長的過程,解壓後會在當前目錄下生成一個mydroid的資料夾。如果你發現原始碼的路徑有中文,需要移動原始碼,請複製壓縮包,然後再使用命令解壓,而不要直接複製解壓後的資料夾
(4) 安裝Ubuntu 16.04
編譯Android原始碼最好直接安裝Linux,不要使用虛擬機器,編譯原始碼是個漫長的過程,虛擬機器要十幾個小時,博主直接在電腦上裝Ubuntu,編譯只需要3個小時。實體機可避免虛擬機器的很多問題,例如:磁碟空間不足,記憶體不夠等等。更重要的是,編譯原始碼是個不斷爬坑的過程,實體機可以很快的遇到錯誤,然後解決問題,繼續編譯,再次遇到錯誤,而虛擬機器這個週期會很漫長,因而浪費大量時間。實體機解壓速度也比虛擬機器快得多。Ubuntu與windows相容做的很好,可以直接把Ubuntu當作一個windows程式安裝,也可以單獨安裝,如果單獨安裝請務必給/home分割槽分配至少120G空間,因為編譯後的Android系統真的很大。
強烈建議下載Ubuntu映象,然後使用軟碟通刻錄到U盤,通過U盤把Ubuntu安裝到物理機器上。
(5) Ubuntu安裝教程參考下面連結,Ubuntu 16.04安裝方法也是一樣的 :
4 更換軟體源為阿里雲
為了更快的安裝軟體,我們需要更換軟體源為國內的軟體源,這裡推薦使用Ubuntu官方指定的國內軟體源阿里雲,博主之前使用的是網易的軟體源,結果發現OpenJDK7裝不上去,於是換成了阿里的,具體方法是:
sudo gedit /etc/apt/sources.list
在檔案最前面加入下面程式碼:
deb http://mirrors.aliyun.com/ubuntu/ quantal main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ quantal-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ quantal-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ quantal-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ quantal-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ quantal main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ quantal-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ quantal-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ quantal-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ quantal-backports main restricted universe multiverse
5 安裝依賴
sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386
sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib
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 lib32z-dev ccache
sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
Ubuntu 16.04請務必使用上面的依賴,Ubuntu 16.04需要的依賴和Ubuntu 14.04所需要的依賴是不同的,博主照著Ubuntu 14.04的依賴結果掉進大坑,詳見後面的編譯過程記錄.
6 安裝open JDK7
從Android 6.0開始Android原始碼的編譯需要安裝OpenJDK,不能使用Oracle JDK,而且Android 6.0只能使用OpenJDK7,如下圖:
由於Ubuntu 16.04沒有OpenJDK7的源,因此在16.04上安裝OpenJDK7需要執行下面的命令:
sudo add-apt-repository ppa:openjdk-r/ppa
sudo apt-get update
sudo apt-get install openjdk-7-jdk
配置OpenJDK.開啟/etc/profile檔案:
sudo gedit /etc/profile
在末尾追加下面程式碼:
export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
修改了/etc/profile檔案需要重啟才能生效,但使用下面命令可以在不重啟的情況下在當前bash環境生效:
source /etc/profile
檢查OpenJDK配置是否正確:
java -version
配置正確則如下圖:
7 修改原始碼
修改 mydroid/art/build/Android.common_build.mk
檔案,定位到75行,將下面的程式碼:
ifneq ($(WITHOUT_HOST_CLANG),true)
改為:
ifeq ($(WITHOUT_HOST_CLANG),false)
如果不修改這裡,會遇到一個比較棘手的編譯錯誤,修改的目的是把CLANG這個編譯選項關掉,詳見後面的編譯記錄,百度搜狗都無解,這個錯誤只會在Ubuntu16.04上遇到,Ubuntu14.04則不存在這個問題,解決這個編譯錯誤花費一天時間,還好咱英語好,在歪果人的論壇上看了幾篇帖子,終於搞定了。這裡順便說一下小技巧:
遇到編譯錯誤,請把error後面的錯誤資訊全部複製,然後用搜狗搜英文網頁,不要用百度那個渣渣
8 開始編譯
(1) 在 .bashrc檔案末尾新增:export USE_CCACHE = 1
echo export USE_CCACHE=1 >> ~/.bashrc
(2) 為了提高編譯效率,設定編譯器快取記憶體:
prebuilts/misc/linux-x86/ccache/ccache -M 50G
(3) 接著匯入編譯Android原始碼所需的環境變數和其它引數:
source build/envsetup.sh
(4) 執行lunch命令選擇編譯目標:
lunch
選擇1:
(5) 開始編譯,執行make -j8, 8為同時編譯的執行緒數,一般google推薦這個數字為2倍的cpu個數再加上2,比如4核,就是10。博主使用的是8:
make -j8
關於cpu個數,可以用下面命令檢視:
cat /proc/cpuinfo
好了,開始編譯了,接下來就是不斷error,不斷修復,繼續編譯的過程,下面記錄我的爬坑經歷
9 編譯記錄
我是參照下面這篇文章開始編譯的:
如果一帆風順,我也就用不著寫這篇部落格了,然而他用的是Ubuntu14.04,我用的最新的Ubuntu16.04,按照上面這篇博文,遇到很多坑,這裡記錄以下爬坑經歷:
(1) 依賴不同。Ubuntu 14和16的依賴選項是不同的:
於是將libsdl1.2-dev
改為libsdl-dev
,將mingw32
去掉
(2) JDK配置錯誤。
先用Oracle JDK8報下面錯:
改為Oracle JDK7報下面錯:
後改為OpenJDK7解決問題。
(3) 大坑。接著遇到下面錯誤:
仔細看錯誤:
clang: error: linker command failed with exit code
其實這個是系統使用clang編輯器報的錯,百度了一下,解決方法一般是將art/build/Android.common_build.mk
檔案ifneq ($(WITHOUT_HOST_CLANG),true)
改為ifeq ($(WITHOUT_HOST_CLANG),false)
然而紙上得來終覺淺,絕知此事要躬行,因為,這並沒有什麼卵用,至少現在沒有卵用。不信,請看下面的帖子:
我試了一下,也沒用,還是沒解決問題,好像這個是新系統的相容問題,百度搜狗一天,沒有進展,後來發現了下面這篇帖子,也是14.04編譯Android6.0的:
抱著反正無聊試一試的想法,把上面這篇帖子中的依賴一通複製(所以最終用的依賴是兩篇帖子加起來的依賴):
sudo apt-get install git-core gnupg flex bison gperf build-essential \
zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache \
libgl1-mesa-dev libxml2-utils xsltproc unzip m4
然後make clean
,重新再來,接著就睡覺去了。
一覺醒來,然後……..你以為我就編粗來了?呵呵,這個錯誤是終於編過去了,可是又遇到下面的錯誤:
解決這個錯誤,又花費一番力氣,在歪果人的論壇上看到下面這篇帖子:
注意看這個帖子的15樓,哈哈,這個時候找到解決方法了,再修改art / build/Android.common_build.mk
檔案
ifneq ($(WITHOUT_HOST_CLANG),true)
改為:
ifeq ($(WITHOUT_HOST_CLANG),false)
重新編譯,解決問題。
(4) 中文路徑,坑。
遇到這個問題也是很難百度到,哎,最後把原始碼換到了全英文的路徑下面,解決這個問題。注意移動原始碼的時候不要直接複製mydroid資料夾,一個小時都複製不完,所以正確的方法是複製壓縮包,然後再解壓一遍。
接下來就編譯成功了。
10 編譯成功
編譯成功後如下圖:
進入mydroid/out/target/product/generic目錄,可以看到編譯好的檔案:
啟動模擬器:
emulator
稍等一會,就可以出現開頭的模擬器畫面了,哈哈,打完收工。
11 附錄:Ubuntu 16.04編譯ROM英文教程
最後,附上在看帖子的時候發現的,在Ubuntu16.04上編譯AOSP、CyanogenMod的教程,當然是英文的啦:
12 總結
Android系統原始碼的編譯就是不斷和各種error做鬥爭的過程,考驗程式設計師獲取資訊的能力,遇到error的時候只能各種百度搜狗,但這也是非常鍛鍊能力的過程,博主在編譯過程中最大的體會就是:英語一定要好,哈哈。如果你成功編譯出來了,或者編譯遇到問題,歡迎給我留言。
Tips
如果覺得這篇部落格對你有幫助或者喜歡博主的寫作風格,就給博主留個言或者頂一下唄,鼓勵博主創作出更多優質部落格,Thank you.