《Android核心剖析》讀書筆記 第18章 Android編譯系統

來源:互聯網
上載者:User
  1. Android編譯系統的核心仍然是第1章末尾介紹的Make,基於此建立了一個適合於Android自身的編譯架構,該編譯架構由各種.mk檔案、shell指令碼、python指令碼共同組成;通過該架構各個系統模組可以單獨編譯或打包、也可以根據一定的規則進行整合打包輸出;
    架構的核心設計理論有如下幾點:
    1. 建立在Make之上,定義好各類target;並適當引入python、shell指令碼;
    2. 基於COC(規則勝於配置)思想強制每個子項目使用Android.mk檔案描述,為了降低該檔案的編寫難度,編譯系統預設定義好了相關變數以及各種通用函數庫;
    3. 利用python指令碼自動掃描所有包括Android.mk檔案的子目錄,並將檔案中的設定內容轉換為Make命令;
  2. 整個編譯系統的源碼在./build/目錄下,絕大部分都是.mk檔案,理解該編譯系統的本質實際上就是分析這些指令檔之間的關係;
    整個編譯系統由編譯中樞、子項目、輸出路徑三部分組成,參見:
    1. 編譯中樞:包括各種.mk檔案,這些檔案將遍曆系統所有的子項目,並產生相對應的target,從而當執行make時能夠知道應該執行什麼具體的編譯或打包命令;
    2. 子項目:就是整個Android源碼系統中的各個功能模組,每個功能模組的目錄中必須包含一個Android.mk檔案,這是基於COC的設計,不允許自訂檔案名稱。該檔案中描述的就是包括哪些源檔案,該項目的輸出目標是什麼類型,比如是Jar包、apk包、so包等等;在實際編寫該檔案的過程中,編譯中樞已經定義好很多常用的變數,對這些變數進行賦值即可;
    3. 輸出路徑:編譯過程中產生的各種臨時檔案、以及最終目標檔案;系統預設定義為out目錄,下面又分2個子目錄host/target;
      1. out/host/:對應的是在PC上進行編譯過程中所需要的各種工具和中間產出,利用這些產出才能編譯出最終所需的目標程式;
      2. out/target/:對應的是可用於手機上部署的最終輸出檔案,比如各類img檔案;
  3. 各編譯指令碼之間的關係
    1. 編譯時間執行make命令會尋找android源碼頂級目錄中的MakeFile檔案,該檔案直接跳轉至./build/core/main.mk;
    2. main.mk就是整個編譯中樞的開始,使用.PHONY定義了預設的target名稱為droid,這樣當執行make命令時是可以不用任何參數的;
    3. config.mk:核心是定義各類常用的變數、以及編譯命令宏;裡面具體會依賴於pathmap.mk/executable.mk/buildspec.mk/envsetup.mk/product_config.mk等;
    4. definitions.mk:定義編譯過程中需要用到的各種指令碼函數,比如all-java-files-under就是返回指定目錄下所有的java檔案;
    5. ./build/tools/findleaves.py:用來掃描指定目錄下所有的Android.mk檔案,可以用參數排除掉某些不必要的目錄;
      掃描出來的結果其實就是上面提到的子項目列表;
  4. product/variant/tag這三者之間的關係
    1. product:產品的名稱,可簡單理解為我們的編譯目標代號,體現在源碼編譯目標值-分割後的第一個參數,比如lunch full-eng中的full;
      他的值可以是任意的,但必須在編譯打包指令碼中定義,本質上他就是一組資訊組合,不同的產品可以包括不同的子項目,比如我們可以自己建立一個product,只包括我們自己需要的幾個子項目;但也可以不強制指定,而完全通過variant子類型來自動判斷;
      一個product中具體包括哪些子項目可以查看對應mk檔案設定的PRODUCT_PACKAGES/PRODUCT_COPY_FILES兩個變數值;
      相關的指令碼可參見./build/target/product/目錄下的mk檔案;比如常見的full.mk中未指定PRODUCT_PACKAGES變數值,而sdk.mk中就指定了該變數值,明確指出包括哪些子項目;
    2. variant:產品子類型,與product搭配使用,是一組系統定義好的預設值,包括eng/user/userdebug/tests,體現在源碼編譯目標值-分割後的第二個參數,比如lunch full-eng中的eng,eng代表的意思是engineer;
      設定variant參數有何作用呢,他與接下來要介紹的tag有著密切的mapping關係;
    3. tag:每個子項目為自己設定的標籤,可以在子項目下的Android.mk檔案中的LOCAL_MODULE_TAGS變數設定,包括debug/eng/tests/optional/samples/shell_ash/shell_mksh,不能設定為其他值,系統編譯時間會在base_rules.mk中進行校正,校正不通過的話會出現警告,並不會將該子項目添加到任何product中;
      從上可以看出variant和tag在很多可選值上面都是相同的,的確他們之間是有mapping關係的,也就是說當編譯命令中指定variant後,具體執行過程中指令碼會根據variant的值與每個子項目中設定的tag值進行比對,若匹配則編譯該子項目並加入到product的輸出路徑中,否則不進行編譯;
      注意:tag和variant不是完全一一對應的,比如:
      1. optional代表的是可選,即他不是android系統運行所必須的,但只要在product中PRODUCT_PACKAGES變數包括了該子項目,那該子項目就會被編譯並添加到product中;
      2. samples代表的是執行個體性項目,多為獨立子項目,一般無需添加到product中;
        ./development/samples/目錄下所有的子項目都是該類型的;
      3. shell_ash只有在system/core/sh/子項目中用到;
      4. shell_mksh只有在external/mksh/子項目中用到;
  5. Android標準應用程式apk包編譯全過程,參見,理解這些原理對自己寫批量打包指令碼時非常重要:
  6. Framework/android.jar的編譯(書中這段的描述個人覺得條理不太清晰,部分描述也不準確)
    1. 首先我們直接看sdk中的android.jar包中核心包括如下幾個頂級package:
      1. java/javax:主要是Java語言的基礎類庫,比如lang/io/sql/util/xml/net等等;
      2. dalvik:裡面類不多,主要包括dalvik虛擬機器特有的DexClassLoader以及相關ByteCode類;
      3. android:大家都超級熟悉了吧,View/Activity/Handler/...都在這裡了;
      4. asset/res:一些系統功能中會用到的各種資源檔;
      5. org/com:主要是一些通用性很強的第三方包,比如httpclient、json等;
    2. 以上的內容可以分成3類,分別來源於不同的jar包,包括:
      1. core.jar:Dalvik虛擬機器運行所需要的基礎類包,其功能主要是完成dex檔案到標準class檔案的轉換與載入,在其之上可以正常運行標準java應用;對應於android.jar中java/javax/dalvik/這3個頂級package;
        源碼位於./libcore/;編譯目標在./libcore/Android.mk中定義;編譯完成後的輸出位於./out/target/common/obj/JAVA_LIBRARIES/core_intermediates
      2. framework.jar:基於Dalvik虛擬機器之上用於開發真正android手機應用的架構套件,比如視圖的繪製、管理,頁面的跳轉與管理等;對應於android.jar中android/assets/res/這3個頂級package;
        源碼位於./frameworks/base;編譯目標在./frameworks/base/Android.mk中定義;編譯完成後的輸出位於./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates
      3. ext.jar:擴充類庫,整合一些通用性較高、已經被業界廣泛接受並使用的工具包;對應於android.jar中org/com/這2個頂級package;
        源碼位於./external/;編譯目標在./frameworks/base/Android.mk中定義;編譯完成後的輸出位於./out/target/common/obj/JAVA_LIBRARIES/ext_intermediates
    3. 但是否core.jar/framework.jar/ext.jar中的所有內容都放在android.jar中呢?答案是否定的;原因是為了保持應用開發api的穩定性和向後相容,google把源檔案分為了“公有”和“私人”兩類,明顯私人的一些源檔案代表穩定性不夠未來很可能會變更,所以這部分不穩定源碼是不會放進android.jar中的,經常看源碼的同學會經常看到@hide這個標籤,這也是一種私人表現;
      android.jar編譯完成後的輸出位於./out/target/common/obj/JAVA_LIBRARIES/sdk_v${version}_intermediates
      其中${version}代表的是SDK的具體版本號碼;

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.