Android開(kāi)源已經(jīng)有一段時(shí)間了,一直沒(méi)有去研究它,一是沒(méi)有時(shí)間,二是沒(méi)有Linux環(huán)境去測(cè)試,三是塊頭太大了(源碼2G,加編譯要5G左右)。
最近項(xiàng)目差不多近尾聲了,終于可以喘口氣,有時(shí)來(lái)好好研究一下Android的源碼了,就在WinXP中從網(wǎng)上下載了Android的源碼,一開(kāi)始只是想看看自已感興趣的部分(GUI、OpenGL ES、Audio等),后來(lái)在網(wǎng)上找到了一些在Cygwin下搭建原生開(kāi)發(fā)環(huán)境的文章,于是就自已試了下,發(fā)現(xiàn)不要Linux、不下全部源碼進(jìn)行原生開(kāi)發(fā)完全是可行的!
首先,要裝Cygwin這個(gè)“活寶”,網(wǎng)上有很多相關(guān)的文章,下載包時(shí)請(qǐng)選擇中國(guó)的鏡像:http://www.cygwin.cn,比較快,如下包一定要安裝:gcc、make、Flex、bison、gettext、gettext-devel、textinfo,另外一定要裝 git 包,下源碼就靠它了;
其次,Cygwin及git安裝好了,進(jìn)入Cygwin,輸入git --version,如果能正確顯示就表示git安裝沒(méi)有問(wèn)題,就可以開(kāi)始有選擇地下載Android的源碼了。Android的源碼太多了,如果只為原生開(kāi)發(fā),只要下載bionic及build兩個(gè)包,先為Android源碼建一個(gè)目錄,進(jìn)入此目錄,再按如下步驟取源碼:
1. bionic,Android沒(méi)有用 glibc,用的是google自已寫(xiě)的 bionic Libc,小是小,快是快,但有一個(gè)最大問(wèn)題,對(duì)C++的兼容不好(這是后話)。命令如下:
git clone git://android.git.kernel.org/platform/bionic.git
2. build,其實(shí)我們只是要參考Android的一些編譯鏈接選項(xiàng),命令如下:
git clone git://android.git.kernel.org/platform/build.git
3. system/core,其實(shí)我們只是要一個(gè)頭文件:AndroidConfig.h,也可直接從android git web上下載:http://android.git.kernel.org/?p=platform/system/core.git;a=blob_plain;f=include/arch/linux-arm/AndroidConfig.h;hb=HEAD,如果要下整個(gè)目錄,命令如下:
git clone git://android.git.kernel.org/platform/system/core.git
4. frameworks/base,如果要進(jìn)行 opengl es 的3D開(kāi)發(fā),一定要下載這個(gè)包,因?yàn)閛pengl es的頭文件在這個(gè)包中,命令如下:
git clone git://android.git.kernel.org/platform/frameworks/base.git
更多Android項(xiàng)目信息請(qǐng)?jiān)L問(wèn):http://android.git.kernel.org/,大家可根據(jù)自已的興趣選擇下載。
再次,下載Android訂制的toolchain的源碼(
http://android.git.kernel.org/pub/android-toolchain-20081019.tar.bz2),編譯步驟如下:
1.解壓文件,并進(jìn)入目錄,執(zhí)行如下命令配置要編譯的target及安裝的目錄:
./configure --target=arm-eabi --prefix=/cygdrive/d/Android/cupcake/toolchain
雖然安裝目錄可稍后安裝配,但推薦在配置時(shí)設(shè)置好,目錄一定要是絕對(duì)路徑,如要裝在 D:\Android\cupcake\toolchain,則為:/cygdrive/d/Android/cupcake/toolchain。
2.執(zhí)行:make build 命令,如果有錯(cuò)誤按提示再編譯,一般沒(méi)有什么大問(wèn)題;
3.安裝:make install。
Toolchain編譯安裝完成后,就要開(kāi)始進(jìn)行一些環(huán)境配置的動(dòng)作了,網(wǎng)上說(shuō)直接將bionic的一些頭文件復(fù)制到 $toolchain/arm-eabi/include,一般情況是,但先執(zhí)行如下看一下:
$arm-eabi-cpp -v
一般gcc會(huì)從如下3個(gè)目錄去搜索頭文件:
$toolchain/lib/gcc/arm-eabi/4.2.1/include
$toolchain/arm-eabi/sys-include
$toolchain/arm-eabi/include
如下頭文件需從android源碼目錄復(fù)制到toolchain目錄$toolchain/lib/gcc/arm-eabi/4.2.1/include:
bionic/libc/arch-arm/include
bionic/libc/include
bionic/libstdc++/include
bionic/libc/common
bionic/libc/arch-arm
bionic/libm/include
bionic/libm/include/arch/arm (好象找不到此目錄,ignore it!)
bionic/libthread_db/include
frameworks/base/opengl/include (3D開(kāi)發(fā),一定要加此目錄!)其中,一些頭文件有重復(fù):limits.h一定要用bionic/libc/include目錄的,endian.h 用 bionic/libc/arch-arm/include,再將system/core/include/arch/linux-arm目錄下的AndroidConfig.h文件復(fù)制到$toolchain/lib/gcc/arm-eabi/4.2.1/include。
頭文件復(fù)制完成了,接下來(lái)復(fù)制庫(kù)文件,庫(kù)文件因沒(méi)有所有源碼不能通過(guò)編譯得到,只好從模擬器中pull下來(lái),這次要用到一個(gè)工具:
busybox。
從網(wǎng)上下載
busybox的可執(zhí)行程序,啟動(dòng)模擬器,將busybox push上去,執(zhí)行:
$adb push busybox /dev/sample/busybox
$adb shell chmod 777 /dev/sample/busybox
$adb shell ./dev/sample/busybox tar -cf /dev/sample/libs.tar /system/lib
$adb pull /dev/sample/libs.tar libs.tar
這樣就將模擬器下的 /system/lib 目錄的所有庫(kù)(so)文件打包并下載下來(lái)了,解壓libs.tar就得到了我們所需要的所有庫(kù)文件,執(zhí)行如下命令:
arm-eabi-ld --verbose 或 arm-eabi-ld --verbose | grep SEARCH_DIR
復(fù)制所有庫(kù)文件到 SEARCH_DIR(一般是$toolchain/arm-eabi/lib)目錄下,同時(shí)將 toolchain 的編譯腳本 armelf.x armelf.xsc 從下載的Android的源碼目錄的 build/core 復(fù)制到同目錄。
至此,環(huán)境基本上搭建完成,可以試著編譯一個(gè) hello world C 源碼了。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int i;
printf("argc\t = %d\n", argc);
for (i = 0; i < argc; i++) {
printf("argv[%d]\t = %s\n", i, argv[i]);
}
printf("Hello world!\n");;
return 0;
}
編譯命令如下:
$ arm-eabi-gcc -nostdlib -Bdynamic -Wl,-T,armelf.x -Wl,-dynamic-linker,/system/bin/linker -include AndroidConfig.h -lc -o hello hello.c
得到警告:
warning: cannot find entry symbol _start; defaulting to 000082c8
沒(méi)有入口函數(shù) _start,加上再編譯,成功了,push至模擬器執(zhí)行看一下:
$ adb shell ./dev/sample/hello
argv[0] = (null)
argv[1] = (null)
argv[2] = (null)
argv[3] = (null)
argv[4] = (null)
argv[5] = (null)
argv[6] = (null)
argv[7] = (null)
argv[8] = (null)
argv[9] = (null)
argv[10] = (null)
argv[11] = ./dev/sample/hello
argv[12] = (null)
argv[13] =
argv[14] = (null)
[1] Segmentation fault ./dev/sample/hello
很不幸,Segmentation fault!好象加_start也不是那么有用,看樣子非得要象build的makefile中說(shuō)的,要crtbegin_dynamic.o和crtend.o,但沒(méi)有編整個(gè)源碼,怎么得到這兩個(gè)文件呢?
答案就在下載的Android的源碼bionic的目錄中,進(jìn)入$android_src/bionic/libc/arch-arm/bionic,你會(huì)發(fā)現(xiàn)在很多匯編文件,其中我們想要的 crtbegin_dynamic.S,crtend.S就在其中,編譯它們:
arm-eabi-gcc -mthumb-interwork -o crtbegin_dynamic.o -c crtbegin_dynamic.S
arm-eabi-gcc -mthumb-interwork -o crtend.o -c crtend.S
不出意外,將得到 crtbegin_dynamic.o & crtend.o,再來(lái)編譯我們的hello.c
$arm-eabi-gcc -nostdlib -Bdynamic -Wl,-T,armelf.x -Wl,-dynamic-linker,/system/bin/linker -include AndroidConfig.h -lc -o hello hello.c crtbegin_dynamic.o crtend.o
將生成的hello push到模擬器,再執(zhí)行,如下:
$adb push hello /dev/sample/hello
$adb shell chmod 777 /dev/sample/hello
$adb shell ./dev/sample/hello A B C
輸出如下:
argc = 4
argv[0] = ./dev/sample/hello
argv[1] = A
argv[2] = B
argv[3] = C
Hello world!
這正是我們想要看到的。
參考網(wǎng)站: