編譯android源碼的make命令解析


摘要:
   本文描述了編譯android源碼時,make命令后面隱藏的玄機,通過一步步的分析,你會發現,實際上不是想象的那么復雜(肯定比編hello world復雜,哈)。
正文:
   最近編譯了一下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打包而成的。所以,你可以去研究這個包里的每個文件是怎么編出來的。有了上面的例子,應該不難。
后面該怎么樣進行下去,我還沒想好,先研究ramdisk.img下每個文件是怎么來的再說。




免責聲明!

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



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