如果android的source在android21檔案夾(即Makefile檔案的目錄)下,先執行cd android21,
然後可以執行下面的命令;
1、make Settings
產生Settings.apk的檔案
2、 make snod
等同於make droid
該命令產生一個新的系統映像system.img,速度比make快很多,但不穩定(有的時候不好用)
將這個系統映像拷貝至sdk下
cp out/target/product/generic/system.img /
out/host/linux-x86/sdk/android-sdk_eng.justin_linux-x86/tools/lib/images/
刪除程式遺留的資料:
out/host/linux-x86/sdk/android-sdk_eng.justin_linux-x86/tools/emulator -wipe-data
3、make
映像編譯成功後會在目錄 ~/android/src/out/target/product/generic
下產生一些image檔案
ramdisk.img system.img userdata.img
4、make sdk
注意:如果需要build SDK,需要安裝sun-java5-jdk, 而不是sun-java6-jdk
sdk編譯成功後會在~/android/src /o ut/host/linux-x86/sdk/ 產生sdk的檔案目錄和壓縮包:
android-sdk_eng.justin_linux-x86
android-sdk_eng.justin_linux-x86.zip
並在~/android/src /out/target/product/generic(generic是預設的產品名)下打包所有的映像檔案:
generic-img-eng.justin.zip
最近編譯了一下android 1.6,同時也分析了一下android的build system。build system對我來說實在太大,要想瞭解這個系統的細節不是一兩天可以完成的,於是我就退而求其次,去瞭解編譯android源碼的命令make。還是那句話,一切都是從編譯開始的。
1. make命令執行後,編譯的入口在哪裡?
雖然我的最終目的是研究android源碼之間的關係,但是,當我編完android源碼後,這是我想到的第一個問題。根據makefile的規則,make若不加參數會預設執行目錄下的makefile檔案,而這裡的makefile檔案include了main.mk檔案。同時,makefile會執行main.mk中的第一條規則。根據這個原則,你會發現main.mk中的第一條規則在main.mk的第45行,但是它什麼也不做,目的只是佔個位置。
# This is the default target. It must be the first declared target.DEFAULT_GOAL := droid$(DEFAULT_GOAL):
真正的定義在第681行,這裡的定義覆蓋了上面的定義。往下走一步是droidcore規則,它的定義為:
.PHONY: droidcoredroidcore: files / systemimage / $(INSTALLED_BOOTIMAGE_TARGET) / $(INSTALLED_RECOVERYIMAGE_TARGET) / $(INSTALLED_USERDATAIMAGE_TARGET) / $(INTERNAL_DEFAULT_DOCS_TARGETS) / $(INSTALLED_FILES_FILE)
這個規則顯然是我們想要的,但問題是其中的變數值是多少呢?要解決這個問題也很容易。make在解析makefile檔案時,大致流程如下:首先會解析makefile檔案,這一步主要是進行規則的展開工作,根據make後面的參數來解析出規則實際要執行的動作(action)。解析完整個檔案後,就開始執行指定的規則後面的動作了,此時,就只剩下一個動作列表,挨個執行就可以了。根據這個原則,加上droidcore規則位於檔案的末尾,所以我們可以在檔案的最後輸出這些參數。這裡我們要用到makefile的函數info和error,info的作用是在第一遍解析時,輸出資訊,然後繼續解析,error則是輸出資訊後退出,具體可以參考make的文檔。比如,這裡我們要查看上面幾個變數的值,可以在main.mk的最後添加如下語句。最後一句用來標識main.mk已經解析完。
1: $(info INSTALLED_BOOTIMAGE_TARGET = $(INSTALLED_BOOTIMAGE_TARGET))
2: $(info INSTALLED_RECOVERYIMAGE_TARGET = $(INSTALLED_RECOVERYIMAGE_TARGET))
3: $(info INSTALLED_USERDATAIMAGE_TARGET = $(INSTALLED_USERDATAIMAGE_TARGET))
4: $(info INTERNAL_DEFAULT_DOCS_TARGETS = $(INTERNAL_DEFAULT_DOCS_TARGETS))
5: $(info INSTALLED_FILES_FILE = $(INSTALLED_FILES_FILE))
6: $(error >>>>>>> end of the main.mk)
上面幾個變數的值實際上是相對於android源碼的相對目標檔案路徑,比如INSTALLED_BOOTIMAGE_TARGET為out/target/product/generic/ramdisk.img。這裡我們很容易猜到systemimage的值(out/target/product/generic/system.img)是什麼了。
到這裡,我們可以認為,像out/target/product/generic/ramdisk.img的值,實際上就是一條makefile確定的規則,無論這條規則是怎麼來的,使用make out/target/product/generic/ramdisk.img是可以編譯ramdisk.img檔案的,在後面我們可以看到,知道這一點很重要,android的build system就是靠這一點工作的,我認為是核心。
2. droidcore規則完全展開後是什麼樣子的?
有了上面的工作,這個問題就變的容易許多。我本來的目的是想要研究android原始碼之間的依賴關係,而這個依賴關係通過makefile中擷取,是最直觀和可靠的。要想獲得droidcore的所有動作列表也不難,make命令有個參數-n,它的目的是“只輸出規則下的動作(編譯命令)語句,而不執行規則”。比如,要想獲得droidcore的所有動作序列,可以使用如下命令:(輸出結果太長了,可以將它輸出到檔案)
make -n
我將這個命令的結果輸出到檔案,由於等的時間太長,就放棄了,估計起碼有幾十兆,幾萬行命令。
也可以用如下命令來擷取編譯ramdisk.img所需要的命令序列:
make -n out/target/product/generic/ramdisk.img
編譯ramdisk.img命令大概有5600行。還是有點大,那該如何?這個輸出的最後一行你會發現,ramdisk.img是通過將目錄out/target/product/generic/root打包而成的。所以,你可以去研究這個包裡的每個檔案是怎麼編出來的。有了上面的例子,應該不難。