天天看點

Android源碼分析(二):mk檔案具體的具體的執行流程

 Android編譯系統集中于build/core下,幾個很重要的*.mk檔案如下:

         main.mk(主要Makefile)

         base_rules.mk(對一些Makefile的變量規則化)

         config.mk(關于編譯參數、編譯指令的一些配置)

         definations.mk(定義了很多編譯系統中用到的宏,相當于函數庫)

         Makefile(這個Makefile特指build/core下的Makefile,此檔案主要控制生成system.img,ramdisk.img,userdata.img,以及recorvery image,sdk等)

         Binary.mk(控制如何生成目标檔案)

         Clear_vars.mk(清除編譯系統中用到的臨時變量)

         Combo/linux-arm.mk(控制如何生成linux-arm二進制檔案,包括ARM相關的編譯器,編譯參數等的設定)

         Copy_headers.mk(将頭檔案拷貝到指定目錄)

         分散于各個目錄下的Android.mk(控制生成局部子產品的源碼,名稱所需頭檔案路徑,依賴庫等特殊選項)

         Build/envsetup.mk(編譯環境初始化,定義一些實用的shell函數,友善編譯使用)

         以上幾個主要的檔案,可以按照社會分工打一個比方:

         Main.mk是總統,是老大,承擔了很多工作。

         Makefile是副總統,輔佐老大Main.mk

         Base_rules.mk是交警,讓不規則的東西,變得規則。

         Config.mk是省長,規定了各個人民群衆該如何行事

         Definations.mk是圖書館管理者

         Binary.mk應該屬于村長了,規定每個人該如何行事

         Clear_vars.mk應該屬于保潔公司的勞工吧

         Combo/linux-arm.mk應該屬于社會公民了,他決定自己該如何去做

Main.mk分析

   Main.mk主要包含如下幾個部分的内容

      1.   SHELL設定

      2.   編譯環境配置

      3.   編譯環境檢查

      4.   包含必要的宏

      5.   根據make參數設定編譯時的變量

      6.   包含需要編譯的Android.mk

      7.   設定編譯系統Target:prerequisites 控制整個編譯流程

      下面對上面幾點進行必要解釋:

     然後就是針對make時傳入的編譯類型(eng user userdebug showcommands等)進行編譯配置,這些配置會影響到最終編譯目标所包括的子產品。對于eng user userdebug sdk win_sdk tests等編譯目标的差別,可以通過檢視main.mk的代碼找出其中到底有什麼不同。(内容如下圖)

(在編譯完整個系統之後,再運作make sdk,就可以進行sdk 的編譯了。make sdk 将各種工具和image 打包,供開發和調試使用。注: Make 指令

      make droid:等同于make 指令。droid 是預設的目标名稱。

      make all: make all 将make 所有make droid 會編譯的項目。同時,将編譯LOCAL_MODULE_TAGS 定義的不包括android tag 的子產品。這将確定所有的在代碼樹裡面同時有Android.mk 檔案的子產品。

     clean-$(LOCAL_MODULE)和clean-$(LOCAL_PACKAGE_NAME):删除某個子產品的目标檔案。例如:clean-libutils 将删除所有的libutils.so 以及和它相關的中間檔案;

      clean-Home 将删除Home 應用。

      make clean:删除本次配置所編譯輸出的結果檔案。類似于:rm –rf ./out/ <configuration>

      make clobber:删除所有配置所編譯輸出的結果檔案。類似于:rm –rf ./out/

      make dataclean:make dataclean deletes contents of the data directory inside the

     current combo directory. This is especially useful on the simulator and emulator, where

     the persistent data remains present between builds.

     make showcommands在編譯的時候顯示腳本的指令而不是顯示編譯的簡報。用于調試腳本。

     make LOCAL_MODULE:編譯一個單獨得子產品(需要有Android.mk 檔案存在)。

     make targets:将輸出所有拟可以編譯的子產品名稱清單。還有一些指令,從make 檔案裡面應該可以找到。)

       Ifeq($(SDK_ONLY),true)處,大概400行上下,這個判斷語句一直到這個語句塊結束,都是對subdirs變量的設定,subdirs變量決定了哪些子檔案夾最終被編譯。在後面的subdir_makefiles變量的設定,決定了哪些Android.mk被編譯。緊接着include $(subdir_makefiles)就會添加所有這些Android.mk檔案的依賴。這其中包含了droid的依賴,後面我們會發現。(内容如下圖)

  本地子產品的Makefile檔案就是我們在Android 裡面幾乎上随處可見的Android.mk。Android 進行編譯的時候會通過下面的函數來周遊所有子目錄中的Android.mk,一旦找到就不會再往層子目錄繼續尋找(所有你的子產品定義的頂層Android.mk 必須包含自己定義的子目錄中的Android.mk)。subdir_makefiles += \$(shellbuild/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk)不同類型的本地子產品具有不同的文法,但基本上是相通的,隻有個别變量的不同,如何添加子產品在前面,如上圖就是公司自己添加的子產品。

         然後就會根據這些Makefile,找出所有需要編譯的子產品(module),以及進行必要的分類(eng_MODULES/debug_MODULES/tests_MODULES等、modules_to_check/modules_to_install等),用以差別對待。緊接着是定義了一系列的隐含目标:prebuilt、all_copied_headers、files、checkbuild、ramdisk、systemtallball、userdataimage、userdatatarball、bootimg、droidcore等。最重要的一點,是會發現droid依賴于droidcore,而droidcore依賴于

droidcore: files \

         systemimage \

         $(INSTALLED_BOOTIMAGE_TARGET) \

         $(INSTALLED_RECOVERYIMAGE_TARGET) \

         $(INSTALLED_USERDATAIMAGE_TARGET) \

         $(INSTALLED_FILES_FILE)

正是這幾個依賴項,控制着整個android的編譯。

         當我們敲Make實際上就等同于我們執行make droid。當Make include所有的檔案,完成對所有make我檔案的解析以後就會尋找生成droid的規則,依次生成它的依賴,直到所有滿足的子產品被編譯好,然後使用相應的工具打包成相應的img。

config.mk分析

該檔案設定include 目錄和frameworks/base 下子目錄等的資訊。編譯系統内部mk 檔案的定義; <Build system internal files>。(内容如下圖)

<a href="http://blog.51cto.com/attachment/201212/235859102.jpg" target="_blank"></a>

設定通用的名稱;&lt;Set common values&gt;

 Include 必要的子配置檔案;&lt;Include sub-configuration files&gt;

 buildspec.mk

 envsetup.mk

 BoardConfig.mk

 /combo/select.mk

 /combo/javac.mk

檢查BUILD_ENV_SEQUENCE_NUMBER 版本号;

In order to make easier for people when the build system changes, when it is necessary

to make changes to buildspec.mk or to rerun the environment setup scripts, they contain

a version number in the variable BUILD_ENV_SEQUENCE_NUMBER. If this variable does

not match what the build system expects, it fails printing an error message explaining

what happened. If you make a change that requires an update, you need to update two

places so this message will be printed.

· In config/envsetup.make, increment the

CORRECT_BUILD_ENV_SEQUENCE_NUMBER definition.

· In buildspec.mk.default, update the BUILD_ENV_SEQUENCE_DUMBER definition

to match the one in config/envsetup.make

The scripts automatically get the value from the build system, so they will trigger the

       設定常用工具的常量;&lt; Generic tools.&gt;

       設定目标選項;&lt; Set up final options.&gt;

       周遊并設定SDK 版本;

envsetup.mk分析

       125行又包含了另外一個重要的mk檔案envsetup.mk,我們來看一下。

<a href="http://blog.51cto.com/attachment/201212/000733869.jpg" target="_blank"></a>

        上面的代碼是指定了目标輸出代碼的位置和主機輸出代碼的位置,重要的幾個如下:PRODUCT_OUT = 這個的結果要根據product_config.mk檔案内容來決定。envsetup.mk檔案主要包含了product_config.mk檔案,然後指定了編譯時要輸出的所有檔案的OUT目錄。

        envsetup.mk又包含了product_config.mk檔案

在build/core/product_config.mk又包含了product.mk檔案。

          是以android編譯系統通過各種依賴關系、確定某個子產品的修改引起相依賴的檔案的重新編譯連結,甚至還包括目标檔案系統的生成,配置檔案的生成等。

本文轉自 646676684 51CTO部落格,原文連結:http://blog.51cto.com/2402766/1077778,如需轉載請自行聯系原作者

繼續閱讀