本文是我在MAC下編譯ANDROID源碼和模擬器內核GoldFish時的過程與所遇到的問題解決方案,到目前已經編譯完成並在模擬器中成功加載自己的內核,同時在系統中加載了一個內核模塊進行測試,下面是編譯和問題解決過程:
約定:
1. $代表在Mac終端進行命令操作,#代表在Android終端進行操作
Section 1: 環境準備
首先,在MAC中編譯源碼需要的文件系統格式是case-sensitive的,對所要存儲代碼的盤查看其信息,可知其是否case-sensitive
我的操作系統是MAC OS X 10.8.3,原本是非Case-sensitive的,這裏是遇到的問題一,要下載源碼Android官方已說明需要Case-sensitive,若不是,有兩種解決方案
1. 創建一個Case-sensitive的鏡相
方法如android官網:http://source.android.com/source/initializing.html 所示
2. 使用ipartition將整個盤轉換爲case-sensitive
本人採用的是此方法,畢竟不知道最後會用多少硬盤空間來做Android開發,ipartition網址:http://www.coriolis-systems.com/iPartition.php
因爲需要從Recovery模式啓動,需要用一個U盤作啓動盤然後然後此工具進行case-sensitive的轉換。
然後是相關軟件的一些準備:
1> Xcode4
因爲之前做過iOS開發,所以一直就有。XCode是需要在https://developer.apple.com/註冊後下載的開發工具。
2>安裝MacPorts
因爲在Mac上不可能如Linux中用apt-get install等命令解析依賴獲得庫,需要在http://www.macports.org/install.php 中安裝Macports來獲取庫
並將/opt/local/bin加入環境變量中,寫入.bash_profile即可:
-
export PATH=$PATH:/opt/local/bin
然後用如下命令獲取相關庫:
-
$ POSIXLY_CORRECT=1 sudo port install gmake libsdl git-core gnupg
這裏有可能出現如下的問題:
Warning:
The Command Line Tools for Xcode don't appear to be installed;most ports will likely fail to build.
解決辦法
在Terminal中執行sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
打開XCODE安裝組件 Command line tools :
xcode> preferences >downloads>components然後選擇Command line tools下載並安裝。
3> JDK6/7
要編譯Android還需要有JDK的支持,JDK6可在java.sun.com.下載,下載後將其加入到環境變量中,在此我用的JDK7, 並不是官網上推薦的JDK6
4> Python 2.6--2.7
直接下載即可 python.org. , 不過好像MAC中是自帶的
Section 2: Android源碼下載與編譯
這部分在http://source.android.com/source/downloading.html中有詳細說明每步作用
1. 準備源碼下載工具repo
建立一個文件夾用於放工具repo,並將其路徑寫入.bash_profile環境變量
-
$ mkdir ~/bin $ PATH=~/bin:$PATH
$ curl http://commondatastorage.googleapis.com/git-repo-downloads/repo > ~/bin/repo $ chmod a+x ~/bin/repo
3. 建立源碼文件夾並下載源碼目錄manifest
建立工作目錄
$ mkdir Source $ cd Source
建立工作目錄在工作目錄中下載源碼目錄文件manifest
$ repo init -u https://android.googlesource.com/platform/manifest
開始同步代碼:$ repo sync
在這個同步代碼過程中,可能會有很多次斷線或停滯,關閉終端重新repo sync即可, 在所有同步完成前,此目錄都會爲空,看不到任何文件,只有用ls -a可以看到一個.git文件夾4.建立好環境變量並開始編譯
用源碼中的文件設置好編譯的環境變量$ source build/envsetup.sh
選擇好要編譯的版本爲模擬器版本,具體各版本選項可用lunch命令進行選擇$ lunch full-eng
然後使用make命令開始編譯,j4爲代碼編譯時所採用的線程數, armv7_defconfig代表將arm V7的.config文件作爲kernel的配置文件$ make goldfish_armv7_defconfig -j4
Section 3:下載模擬器源碼GoldFish編譯並用emulator加載
這個部分主要是參考 http://blog.csdn.net/flydream0/article/details/7070392
1. 下載GoldFish源碼於特定文件夾
$mkdir GoldFish_Source
$cd GoldFish_Source
下載過程中同樣是可能多次斷線,重新使用以上第三條命令繼續下即可,在完成前文件夾用ls -a都只能看到一個.git文件夾$git clone http://android.googlesource.com/kernel/goldfish.git
2.切換分支並編譯內核
下載完成後,會看到有一個goldfish的文件夾,進入文件夾ls看到文件夾內容仍爲空,用git branch -a查看當前的分支
然後使用如下命令切換到goldfish-3.4分支
此時使用ls命令使可看到本文件夾下的goldfish內核,接下來我們需要將交叉編譯工具目錄加入到$PATH中去,將下面這行寫入.bash_profile中$git checkout remotes/origin/android-goldfish-3.4
export PATH=/Users/keenite/Android/Source/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.6/bin:$PATH
然後修改Kernel的Makefile文件:# ARCH ?= (SUBARCH)
# CROSS_COMPILE?=$(CONFIG_CROSS_COMPILE:"%"=%)
修改爲:
ARCH ?= armCROSS_COMPILE ?= arm-eabi-爲了保證環境變量等的正確,用以下命令再配置下環境變量
$ source build/envsetup.sh $ lunch full-eng
這裏在編譯前要注意一個問題,如果想在Android Emulator裏面用insmod安裝Linux的內核模塊時會出現錯誤,因爲Android SDK的自帶kernel中沒有把LKM功能打開,所以如果要開發內核模塊需要打開內核LKM功能並重新編譯,否則會出現以下錯誤(如果不想用LKM可以跳過此步)
error: variable '__this_module' has initializer but incomplete type
要解決這個問題需要配置內核選項,首先執行
$ make ARCH=arm CROSS_COMPILE=arm-eabi- menuconfig
進入內核配置界面,勾選下列選項
[*] Enable loadable module support ---> (選中這一項,按空格即可)
[*] Forced module loading (選中上述一項,按回車即可看到此項)
[*] Module unloading
[*] Forced module unloading保存內核配置後就可以用如下命令開始編譯
$ make -j4
如果編譯成功,最後編譯出來的內核會存在內核源下的/arch/arm/boot/中,名爲zImage。
這時候就需要先配置一下環境變量來指定源碼,否則會出現如下錯誤:emulator: ERROR: You did not specify a virtual device name, and the system
directory could not be found.
爲了解決這個問題,我們需要配置兩個環境變量加入.bash_profile中:
export ANDROID_BUILD_TOP=/Users/keenite/Android/Source
export ANDROID_PRODUCT_OUT=/Users/keenite/Android/Source/out/target/product/generic然後使用$source ~/.bash_profile來更新環境變量,完成後我們就可以用如下命令來啓動模擬器並加載指定內核:
$ emulator -kernel /Users/keenite/Android/GoldFish_Source/goldfish/arch/arm/boot/zImage
啓動後可以從About Phone中看到內核信息:
Section4: 加載內核模塊
本部分主要參考:http://www.linuxidc.com/Linux/2011-05/35740.htm
注意,爲了要加載內核模塊,必須要對我們的內核進行Section3中2部分的內核配置,打開LKM
1. 編譯內核模塊
先建立一個文件夾用於放代碼:
$mkdir TestCode
$cd TestCode
然後Makefile與hello.c文件內容分別如下所示:
Makefile
KERNELDIR:=/Users/keenite/Android/GoldFish_Source/goldfish PWD:=$(shell pwd) ARCH=arm CROSS_COMPILE=/Users/keenite/Android/Source/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.6/bin/arm-eabi- CC=$(CROSS_COMPILE)gcc LD=$(CROSS_COMPILE)ld obj-m:=hello.o modules: $(MAKE) -C $(KERNELDIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules clean: rm *.o *.ko *.mod.c *.markers *.order *.symvers
hello.c
然後在此文件夾中就可以使用make 命令來編譯模塊,不過這時要注意在Mac OS X中編譯會遇到以下錯誤:#include<linux/init.h> #include<linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_ALERT "Hello World----------->\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Good bye World.-------<\n"); } module_init(hello_init); module_exit(hello_exit);
HOSTCC scripts/mod/mk_elfconfig
scripts/mod/mk_elfconfig.c:4:17: error: elf.h: No such file or directory
因爲Mac的include文件少了一個elf.h
從 http://download.csdn.net/detail/keenite/5830705中下載,放在scripts/mod目錄中, 然後再進行編譯即可。編譯完成後的hello.ko文件便是我們的內核模塊文件
2. 將hello.ko放入手機中並加載
使用命令:
$adb push hello.ko /data/
將模塊放入手機中的/data/文件夾下,若此時adb警告failed to copy 'hello.ko' to '/data/hello.ko': Read-only file system
則使用adb remount後再push一次文件即可
這時候使用:
$adb shell
命令進入模擬器控制檯,然後使用如下命令加載模塊
#cd data
#insmod hello.ko
這時候我們可以用dmesg命令來查看當前手機中的內核打印信息,這時候能夠看到我們代碼中的打印信息
用lsmod命令可以查看當前加載的模塊狀態,rmmod命令移除模塊當我們用
#rmmod hello
移除模塊後,用dmesg命令查看內核信息,可以看到模塊的移除信息
In the case of Ubuntu12.04LTS the packages need to be installed are:
$ sudo apt-get install git gnupg flex bison gperf build-essential \ zip curl libc6-dev libncurses5-dev x11proto-core-dev \ libx11-dev:i386 libreadline6-dev:i386 \ libgl1-mesa-dev g++-multilib mingw32 tofrodos \ python-markdown libxml2-utils xsltproc zlib1g-dev:i386
Using libgl1-mesa-glx-lts-quantal:i386 in place of
libgl1-mesa-glx:i386 -