Android源碼、內核編譯


Android源碼和內核的編譯就是一場馬拉松,每一個節點都耗時漫長,下載源碼、編譯源碼、下載內核、編譯內核,下載中途會斷掉,編譯中間會失敗,求解再重來,又是一輪馬拉松,於是每一步都要做好備份和記錄,可是30G的源碼(編譯后已經達到70G)備份一次都需要好久。好在春節伊始我放棄了其他的學習,全力搞這個過程,終於算是拿下了。不過,漫漫長路,這只是一個開頭。

我編譯的是Android最新穩定版本android-6.0.1_r11,內核是android-goldfish-3.4,平台是Mac OS 10.11。

  • 一、Android源碼下載和編譯

source.android.com官網對Mac OSX下的編譯說的挺詳細的了,不過因為你懂的原因,去到官網很不方便,我還是把自己的心路歷程記錄下來,以便以后再做的時候查找方便。

  • 1、前期准備

這是為后面下載和編譯做好環境設置和工具的准備。

  • (1)創建大小寫敏感的磁盤鏡像文件

Launchpad - 其它 - 磁盤工具,點擊菜單 文件 - 新建映像 - 空白映像

如下,在格式中必須選擇“OS X 擴展(區分大小寫,日志式)”,我在映像格式中選擇了“稀疏磁盤映像”,以便未來比較容易地擴展:

不過我發現mac的磁盤工具貌似有bug:點擊存儲之后,實際生成的磁盤映像文件還是“OS X 擴展(日志式)”的,而不是大小寫區分,需要點擊該分區文件 - 分區,此時你會發現在“格式”中選擇的是“OS X 擴展(日志式)”,把它改為“OS X 擴展(區分大小寫,日志式)”,再點應用。

  • (2)確認JDK、XCode版本、make版本

在命令行下輸入java -version,確認已經是最新的Java 8了:

輸入make -v,確認是3.8.1,據說最新的3.8.2有bug,如果裝的是3.8.2,需要退到3.8.1:

我的XCode版本是7.2.1

  • (3)安裝所需要的packages

到http://www.macports.org/install.php下載和安裝macports,再利用macports下載幾個packages:

$ POSIXLY_CORRECT=1 sudo port install gmake libsdl git gnupg
  • (4)調高文件描述符的限制

編輯~/.bash_profile文件,加入如下內容,把單個進程可打開的文件描述符上限改為1024:

# set the number of open files to be 1024
ulimit -S -n 1024

然后執行source ~/.bash_profile

  • 2、優化編譯環境

編輯~/.bashrc文件,添加如下內容,有助於加速編譯過程:

export USE_CCACHE=1

然后執行source ~/.bashrc

  • 3、安裝repo

編輯 ~/.bash_profile文件,添加:

export PATH=~/bin:$PATH

然后執行source ~/.bash_profile。

下載repo工具,並設為可執行:

$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
  • 4、初始化repo

掛載1-(1)中創建的大小寫敏感磁盤映像文件,並在里面創建目錄android-6.0.1_r11,假設它的全目錄名為WORKING_DIRECTORY,

執行如下命令初始化repo客戶端:

cd WORKING_DIRECTORY
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-6.0.1_r11

我把源指向的清華的鏡像服務器,它將下載分支android-6.0.1_r11,點擊此處查看Android分支的名稱列表

如果要下載最新主干代碼,則執行:

repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest
  • 5、下載Android代碼樹

注意,接下來我們將進入長夜漫漫的下載過程,執行:

repo sync

我下過幾次,每次都要花上四五個小時,而且常常中途會斷掉,建議晚上睡覺前走起,運氣好的話,第二天早上搞定。如果失敗了,還是執行這個命令,會接着上文繼續下載。

  • 6、編譯Android源碼

Android源碼的編譯步驟僅如下三步:

  • (1)設置環境變量

$ source build/envsetup.sh
  • (2)選擇編譯目標

$ lunch aosp_arm-eng

官網說這個參數將為模擬器打開所有的調試開關。不帶參數直接調用lunch會列出所有的目標選項,但是我沒找到每個選項的具體描述。

  • (3)編譯

$ make -j4

又是一個漫漫長夜的過程,我的編譯大概花了三四個小時,但我沒有使用-j4參數,打開這個參數將開啟多線程編譯。后來綴上這個參數再重新編譯,果然效果明顯,只用了2個小時12分鍾,建議打開。

  • (4)編譯問題

build/core/combo/mac_version.mk:38: *****************************************************
build/core/combo/mac_version.mk:39: * Can not find SDK 10.9 at /Developer/SDKs/MacOSX10.9.sdk
build/core/combo/mac_version.mk:40: *****************************************************
build/core/combo/mac_version.mk:41: *** Stop..  Stop.

原因是本機的XCode SDK已經升級到10.11,打開目錄:

/Applications/XCode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs,

檢查其下的MacOSXxx.xx.sdk即可確認本機的SDK版本,然后修改WORKING_DIRECTORY/build/core/combo/mac_version.mk,將

mac_sdk_versions_supported :=  10.6 10.7 10.8

改為

mac_sdk_versions_supported :=  10.9 10.10 10.11

然后重新啟動lunch aosp_arm-eng即可。

 

fatal error: linux/netfilter/xt_DSCP.h: No such file or directory

我在WORKING_DIRECTORY/external/iptables/extensions/../include/linux/netfilter下面能找到該文件,只不過是xt_dscp.h,我把它改名為xt_DSCP.h即可。我不知道為什么會出這樣的問題,我的文件系統已經是大小寫敏感的了,而且我是直接repo到該文件系統的,如果真的有錯誤,應該是可重現的。

  • 7、運行emulator

經過兩個多小時的編譯,終於看到如下結果:

 

在命令行下直接運行

$emulator

即可啟動模擬器。啟動過程很慢,需要耐心等待:

編譯過程做好了各種環境變量的設置:

內核使用的是WORKING_DIRECTORY/prebuilts/qemu-kernel/arm64/kernel-qemu

sysdir默認是WORKING_DIRECTORY/out/target/product/generic/

系統鏡像文件分別是sysdir下的system.img、ramdisk.img和userdata.img

 

趕緊把磁盤卸載掉,備份磁盤映像文件!未來就可以在它的基礎上做更多嘗試,萬一踩到屎了,還可以拿這個備份直接來用,不需要再編譯一次了。

以后再掛載該磁盤映像文件以后,需要先執行

$cd WORKING_DIERCTORY
$source build/envsetup.sh

再執行$emulator即可。

  • 二、編譯內核

Android源碼默認不包含他所使用的Linux內核源碼,因此需要額外下載和獨立編譯。

1、確認自己的內核版本號

在剛剛的模擬器中查看手機信息,如下:

確認內核版本是3.4

  • 2、下載內核源碼

在WORKDING_DIRECTORY目錄下

$cd WORKING_DIRECTORY 
$mkdir kernel
$cd kernel
$git clone https://android.googlesource.com/kernel/goldfish.git

這個倉庫有970M,我下了三四個小時,悲催的是我沒有找到它在國內的鏡像服務器,而且這東西不能續傳,我中途VPN斷掉了,連上之后,git就不認之前下載了一半的文件了,需要從頭再來,T T

下完之后,可以看一下該內核倉庫包含的分支:

$ git branch -a
* (頭指針分離於 origin/android-goldfish-3.4)
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/android-3.10
  remotes/origin/android-3.18
  remotes/origin/android-3.4
  remotes/origin/android-goldfish-2.6.29
  remotes/origin/android-goldfish-3.10
  remotes/origin/android-goldfish-3.10-l-mr1-dev
  remotes/origin/android-goldfish-3.10-m-dev
  remotes/origin/android-goldfish-3.18-dev
  remotes/origin/android-goldfish-3.4
  remotes/origin/android-goldfish-3.4-l-mr1-dev
  remotes/origin/linux-goldfish-3.0-wip
  remotes/origin/master

checkout3.4的分支代碼:

$git checkout remotes/origin/android-goldfish-3.4

在kernel下創建子目錄goldfish,並把剛剛檢出的代碼都放到goldfish下面。

  • 3、編譯內核源碼

依次執行如下命令:

$ export ARCH=arm
$ export SUBARCH=arm
$ export CROSS_COMPILE=arm-eabi-
$ export PATH=WORKING_DIRECTORY/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.8/bin:$PATH
$ make goldfish_armv7_defconfig
$ make -j4
  • 4、編譯問題

'elf.h' file not found

我把http://www.rockbox.org/tracker/9006?getfile=16683另存為elf.h拷貝到WORKDING_DIRECTORY/kernel/goldfish/scripts/mod下。

注意盡管在WORKING_DIRECTORY/kernel/goldfish/include/linux/elf.h下也有一個elf.h,但不能使用這個文件。

然后將WORKING_DIRECTORY/kernel/goldfish/scripts/mod下的mk_elfconfig.c和modpost.h兩個文件里的

#include <elf.h>

改為

#include "elf.h"

 

file2alias.c中的ADD宏發生語法錯誤

把發生錯誤的那行做如下修改:

sprintf(str+strlen(str), \
    sizeof(field) == 1 ? "%2X" : \
    sizeof(field) == 2 ? "%4X" : \
    sizeof(field) == 4 ? "%8X" : ""  // 最后的""改為"%8X"
    ……
  • 5、運行新編內核

內核的編譯很快,幾分鍾就會看到如下結果:

產生的Linux內核文件放在了arch/arm/boot/zImage

運行

$ emulator -kernel WORKING_DIRECTORY/kernel/goldfish/arch/arm/boot/zImage

啟動模擬器,找到關於手機的內核版本,可以看到編譯機器的信息:

幾天的探索終於開花結果,萬里探索路終於可以邁出第一步了,內心小激動~~

  • 三、編譯內核驅動模塊

激動之后是艱難的擼碼行軍。

編譯內核驅動模塊需要在kernel/goldfish下面首先敲make menuconfig命令,來配置編譯方式。今天發現在Mac OSX下面該命令是有問題的:

palancedeMacBook-Pro:goldfish palance$ make menuconfig
  HOSTLD  scripts/kconfig/mconf
Undefined symbols for architecture x86_64:
  "_COLS", referenced from:
      _dialog_checklist in checklist.o
      _dialog_clear in util.o
      _dialog_inputbox in inputbox.o
      _dialog_textbox in textbox.o
      _dialog_yesno in yesno.o
      _dialog_menu in menubox.o

      ……………………
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [scripts/kconfig/mconf] Error 1
make: *** [menuconfig] Error 2

\e[0;31m#### make failed to build some targets (1 seconds) ####\e[00m

解決方案是找到WORKING_DIRECTORY/kernel/goldfish/scripts/kconfig/lxdialog/check-lxdialog.sh文件,如下加入粗體的部分:

ldflags()         
{                 
    for extin so a dylib;do
        for libi n ncursesw ncurses curses ;do
            $cc-print-file-name=lib${lib}.${ext} | grep-q /
            if [$?-eq0];then
                echo"-l${lib}"
                exit
            fi  
        done       

        for lib in ncursesw ncurses curses ; do
            if [ -f /usr/lib/lib${lib}.${ext} ];then
                echo "-l${lib}" exit fi  
        done                          
    done           
    exit1         

}

再執行make menuconfig,搞定:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM