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

 Android編譯系統集中於build/core下,幾個很重要的*.mk文件以下:java

         main.mk(主控 Makefile)
         base_rules.mk(對一些 Makefile的變量規則化)
         config.mk(關於編譯參數、編譯命令的一些配置)
         definations.mk(定義了不少編譯系統中用到的宏,至關於函數庫)
         Makefile(這個 Makefile特指build/core下的Makefile,此文件主要控制生成system.img,ramdisk.img,userdata.img,以及recorvery p_w_picpath,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 控制整個編譯流程
      下面對上面幾點進行必要解釋:
       Main.mk的第一句就根據 ANDROID_BUILD_SHELL 來包裹編譯系統用到的Shell,若是咱們不想使用bash,而想使用sh,那麼就能夠在它前面寫上ANDROID_BUILD_SHELL := /bin/sh,或者在build/envsetup.sh中添加相關定義。(內容以下圖)  
          定義完 SHELL以後,就是對MAKE_VERSION的檢查,而後定義了默認的編譯目標droid!若是咱們敲入 make以後,不加任何參數,默認的目標就是droid。注意雖而後面的include $(BUILD_SYSTEM)/config.mk寫在默認目標droid依賴以後,但其和以後的語句都是要執行的,這是Makefile的語法決定的。(內容以下圖)  

          後面會include config.mk cleanbuild.mk對編譯系統進行必要的配置。後面就是對編譯環境的檢查,包括是否大小寫敏感、路徑檢查、java版本檢查、javac版本檢查。Android對編譯環境的檢查若是符合條件,在下次編譯的時候,不會再次進行檢查。(內容以下圖) linux

 

         檢查完版本以後,會包含進definitions.mk,如前所述,definitions.mk中定義了不少編譯系統中用到的宏,這些宏在編譯時須要常常調用,所以在編譯的很靠前的階段,就將之包含了進來。(內容以下圖)Definitions.mk中的內容本身有時間在回顧一下,裏面定義了不少宏. android

     而後就是針對make時傳入的編譯類型(eng user userdebug showcommands等)進行編譯配置,這些配置會影響到最終編譯目標所包括的模塊。對於eng user userdebug sdk win_sdk tests等編譯目標的區別,能夠經過查看main.mk的代碼找出其中到底有什麼不一樣。(內容以下圖)shell

 

在編譯完整個系統以後,再運行make sdk,就能夠進行sdk 的編譯了。make sdk 將各類工具和p_w_picpath 打包,供開發和調試使用。 注: 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、userdatap_w_picpath、userdatatarball、bootimg、droidcore等。最重要的一點,是會發現droid依賴於droidcore,而droidcore依賴於
droidcore: files \
         systemp_w_picpath \
         $(INSTALLED_BOOTIMAGE_TARGET) \
         $(INSTALLED_RECOVERYIMAGE_TARGET) \
         $(INSTALLED_USERDATAIMAGE_TARGET) \
         $(INSTALLED_FILES_FILE)
正是這幾個依賴項,控制着整個 android的編譯。
         當咱們敲 Make實際上就等同於咱們執行make droid。當Make include全部的文件,完成對全部make我文件的解析之後就會尋找生成droid的規則,依次生成它的依賴,直到全部知足的模塊被編譯好,而後使用相應的工具打包成相應的img。
config.mk分析
          build/core/config.mk該文件被 main.mk包含。config.mk 文件的主要內容以下:頭文件的定義;(各類 include 文件夾的設定)在定義頭文件的部分,還include 了pathmap.mk,以下:include $(BUILD_SYSTEM)/pathmap.mk
該文件設置 include 目錄和frameworks/base 下子目錄等的信息。編譯系統內部 mk 文件的定義; <Build system internal files>。(內容以下圖)
 
設定通用的名稱; <Set common values>
 Include 必要的子配置文件; <Include sub-configuration files>
 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
warning as well.。(內容以下圖)
       設置經常使用工具的常量; < Generic tools.>
       設置目標選項; < Set up final options.>
       遍歷並設置 SDK 版本;

envsetup.mk分析bash

       125行又包含了另一個重要的 mk文件envsetup.mk,咱們來看一下。

        上面的代碼是指定了目標輸出代碼的位置和主機輸出代碼的位置,重要的幾個以下:PRODUCT_OUT = 這個的結果要根據 product_config.mk文件內容來決定。envsetup.mk文件主要包含了 product_config.mk文件,而後指定了編譯時要輸出的全部文件的OUT目錄。

        envsetup.mk又包含了product_config.mk文件 app

 

build/core/product_config.mk又包含了product.mk文件。
          所以 android編譯系統經過各類依賴關係、確保某個模塊的修改引發相依賴的文件的從新編譯連接,甚至還包括目標文件系統的生成,配置文件的生成等。
相關文章
相關標籤/搜索