<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          理解 Android 編譯命令

          共 4530字,需瀏覽 10分鐘

           ·

          2017-08-09 18:51

          工欲善其事,必先利其器,對(duì)于想要深入學(xué)習(xí)Android源碼,必須先掌握Android編譯命令.

          一、引言

            
          關(guān)于Android Build系統(tǒng),這個(gè)話題很早就打算整理下,遲遲沒有下筆,決定跟大家分享下。先看下面幾條指令,相信編譯過Android源碼的人都再熟悉不過的。

          source?/opt/android1204_17.conf?
          source?setenv.sh
          lunch
          make?-j12

            

          記得最初剛接觸Android時(shí),同事告訴我用上面的指令就可以編譯Android源碼,指令雖短但過幾天就記不全或者忘記順序,每次編譯時(shí)還需要看看自己的云筆記,冰冷的指令總是難以讓我記憶。后來我決定認(rèn)真研究下這個(gè)指令的含義。知其然還需知其所以然,這樣能更深層次的理解并記憶,才能與自身的知識(shí)體系建立強(qiáng)連接,或許還有意外收獲,果然如此,接下來跟大家分享一下在研究上述幾條指令含義的過程中,深入了解到的Android Build(編譯)系統(tǒng)。

          二、編譯命令

            
          準(zhǔn)備好編譯環(huán)境后,編譯Android源碼的第一步是 source build/envsetup.sh,其中source命令就是用于運(yùn)行shell腳本命令,功能等價(jià)于”.”,因此該命令也等價(jià)于. build/envsetup.sh。在文件envsetup.sh聲明了當(dāng)前會(huì)話終端可用的命令,這里需要注意的是當(dāng)前會(huì)話終端,也就意味著每次新打開一個(gè)終端都必須再一次執(zhí)行這些指令。起初并不理解為什么新開的終端不能直接執(zhí)行make指令,到這里總算明白了。
            

          接下來,解釋一下本文開頭的引用的命令:  

          source?/opt/android1204_17.conf??//初始化jdk環(huán)境變量(這個(gè)不是必需的,因廠商而異)
          source?setenv.sh??//初始化編譯環(huán)境,包括后面的lunch和make指令
          lunch??//指定此次編譯的目標(biāo)設(shè)備以及編譯類型
          make??-j12?//開始編譯,默認(rèn)為編譯整個(gè)系統(tǒng),其中-j12代表的是編譯的job數(shù)量為12。

            

          所有的編譯命令都在envsetup.sh文件能找到相對(duì)應(yīng)的function,比如上述的命令lunch,make,在文件一定能找到

          function?lunch(){
          ...

          }

          function?make(){**
          ...

          }
            

          source envsetup.sh,需要cd到setenv.sh文件所在路徑執(zhí)行,路徑可能在build/envsetup.sh,或者integrate/envsetup.sh,再或者不排除有些廠商會(huì)封裝自己的.sh腳本,但核心思路是一致的。
            
          具體實(shí)現(xiàn)這里就不展開說明,下面精煉地總結(jié)了一下各個(gè)指令用法和功效。

          2.1 代碼編譯

          image
            
          下面列舉部分模塊的編譯指令:

          image
            
          上述mmm命令同樣適用于mm/mma/mmma,編譯系統(tǒng)采用的是增量編譯,只會(huì)編譯發(fā)生變化的目標(biāo)文件。當(dāng)需要重新編譯所有的相關(guān)模塊,則需要編譯命令后增加參數(shù)-B,比如make -B [module_name],或者 mm -B [module_path]。
            
          Tips:

          1. 對(duì)于m、mm、mmm、mma、mmma這些命令的實(shí)現(xiàn)都是通過make方式來完成的。
            • mmm/mm編譯的效率很高,而make/mma/mmma編譯較緩慢;
            • make/mma/mmma編譯時(shí)會(huì)把所有的依賴模塊一同編譯,但mmm/mm不會(huì);
            • 建議:首次編譯時(shí)采用make/mma/mmma編譯;當(dāng)依賴模塊已經(jīng)編譯過的情況,則使用mmm/mm編譯。

          2.2 代碼搜索

          image
            
          上述指令用法最終實(shí)現(xiàn)方式都是基于grep指令,各個(gè)指令用法格式:

          xgrep?[keyword]??//x代表的是上表的搜索指令
            
          例如,搜索所有AndroidManifest.xml文件中的launcher關(guān)鍵字所在文件的具體位置,指令  

          mangrep?launcher
            
          再如,搜索所有Java代碼中包含zygote所在文件  

          jgrep?zygote

          又如,搜索所有system_app的selinux權(quán)限信息

          sepgrep?system_app
            
          Tips: Android源碼非常龐大,直接采用grep來搜索代碼,不僅方法笨拙、浪費(fèi)時(shí)間,而且搜索出很多無意義的混淆結(jié)果。根據(jù)具體需求,來選擇合適的代碼搜索指令,能節(jié)省代碼搜索時(shí)間,提高搜索結(jié)果的精準(zhǔn)度,方便定位目標(biāo)代碼。

          2.3 導(dǎo)航指令

          Tips: 當(dāng)每次修改完某個(gè)文件后需要編譯時(shí),執(zhí)行cproj后會(huì)跳轉(zhuǎn)到當(dāng)前模塊的根目錄,也就是Android.mk文件所在目錄,然后再執(zhí)行mm指令,即可編譯目標(biāo)模塊;當(dāng)進(jìn)入源碼層級(jí)很深后,需要返回到根目錄,使用croot一條指令完成;另外cd - 指令可用于快速切換至上次目錄。

          2.4 信息查詢

          2.5 其他指令

            
          上述只是列舉比較常用的指令,還有其他指令,而且不同的build編譯系統(tǒng),支持的指令可能會(huì)存在一些差異,當(dāng)忘記這些編譯指令,可以通過執(zhí)行hmm,查詢指令的幫助信息。
            
          最后再列舉兩個(gè)比較常用的指令:

          • make clean:執(zhí)行清理操作,等價(jià)于 rm -rf out/
          • make update-api:更新API,在framework API改動(dòng)后需執(zhí)行該指令,Api記錄在目錄frameworks/base/api;

          三、編譯系統(tǒng)

            
          Android 編譯系統(tǒng)是Android源碼的一部分,用于編譯Android系統(tǒng),Android SDK以及相關(guān)文檔。該編譯系統(tǒng)是由Make文件、Shell以及Python腳本共同組成,其中最為重要的便是Make文件。關(guān)于編譯系統(tǒng)可參考 理解 Android Build 系統(tǒng)。

          3.1 Makefile分類

           
          整個(gè)Build系統(tǒng)的Make文件分為三大類:

          • 系統(tǒng)核心的Make文件:定義了Build系統(tǒng)的框架,文件全部位于路徑/build/core,其他Make文件都是基于該框架編寫的;
          • 針對(duì)產(chǎn)品的Make文件:定義了具體某個(gè)型號(hào)手機(jī)的Make文件,文件路徑位于/device,該目錄下往往又以公司名和產(chǎn)品名劃分兩個(gè)子級(jí)目錄,比如/device/qcom/msm8916;
          • 針對(duì)模塊的Make文件:整個(gè)系統(tǒng)分為各個(gè)獨(dú)立的模塊,每個(gè)模塊都一個(gè)專門的Make文件,名稱統(tǒng)一為”Android.mk”,該文件定義了當(dāng)前模塊的編譯方式。Build系統(tǒng)會(huì)掃描整個(gè)源碼樹中名為”Android.mk”的問題,并執(zhí)行相應(yīng)模塊的編譯工作。

          3.2 編譯產(chǎn)物

           
          經(jīng)過make編譯后的產(chǎn)物,都位于/out目錄,該目錄下主要關(guān)注下面幾個(gè)目錄:

          • /out/host:Android開發(fā)工具的產(chǎn)物,包含SDK各種工具,比如adb,dex2oat,aapt等。
          • /out/target/common:通用的一些編譯產(chǎn)物,包含Java應(yīng)用代碼和Java庫;
          • /out/target/product/[product_name]:針對(duì)特定設(shè)備的編譯產(chǎn)物以及平臺(tái)相關(guān)C/C++代碼和二進(jìn)制文件;
              
            在/out/target/product/[product_name]目錄下,有幾個(gè)重量級(jí)的鏡像文件:
          • system.img:掛載為根分區(qū),主要包含Android OS的系統(tǒng)文件;
          • ramdisk.img:主要包含init.rc文件和配置文件等;
          • userdata.img:被掛載在/data,主要包含用戶以及應(yīng)用程序相關(guān)的數(shù)據(jù);
              
            當(dāng)然還有boot.img,reocovery.img等鏡像文件,這里就不介紹了。

          3.3 Android.mk解析

            
          在源碼樹中每一個(gè)模塊的所有文件通常都相應(yīng)有一個(gè)自己的文件夾,在該模塊的根目錄下有一個(gè)名稱為“Android.mk” 的文件。編譯系統(tǒng)正是以模塊為單位進(jìn)行編譯,每個(gè)模塊都有唯一的模塊名,一個(gè)模塊可以有依賴多個(gè)其他模塊,模塊間的依賴關(guān)系就是通過模塊名來引用的。也就是說當(dāng)模塊需要依賴一個(gè)jar包或者apk時(shí),必須先將jar包或apk定義為一個(gè)模塊,然后再依賴相應(yīng)的模塊。
            
          對(duì)于Android.mk文件,通常都是以下面兩行

          LOCAL_PATH?:=?$(call?my-dir)??//設(shè)置當(dāng)編譯路徑為當(dāng)前文件夾所在路徑
          include?$(CLEAR_VARS)??//清空編譯環(huán)境的變量(由其他模塊設(shè)置過的變量)

           
          為方便模塊編譯,編譯系統(tǒng)設(shè)置了很多的編譯環(huán)境變量,如下:

          • LOCAL_SRC_FILES:當(dāng)前模塊包含的所有源碼文件;
          • LOCAL_MODULE:當(dāng)前模塊的名稱(具有唯一性);
          • LOCAL_PACKAGE_NAME:當(dāng)前APK應(yīng)用的名稱(具有唯一性);
          • LOCAL_C_INCLUDES:C/C++所需的頭文件路徑;
          • LOCAL_STATIC_LIBRARIES:當(dāng)前模塊在靜態(tài)鏈接時(shí)需要的庫名;
          • LOCAL_SHARED_LIBRARIES:當(dāng)前模塊在運(yùn)行時(shí)依賴的動(dòng)態(tài)庫名;
          • LOCAL_STATIC_JAVA_LIBRARIES:當(dāng)前模塊依賴的Java靜態(tài)庫;
          • LOCAL_JAVA_LIBRARIES:當(dāng)前模塊依賴的Java共享庫;
          • LOCAL_CERTIFICATE:簽署當(dāng)前應(yīng)用的證書名稱,比如platform。
          • LOCAL_MODULE_TAGS:當(dāng)前模塊所包含的標(biāo)簽,可以包含多標(biāo)簽,可能值為debgu,eng,user,development或optional(默認(rèn)值)  
             
            針對(duì)這些環(huán)境變量,編譯系統(tǒng)還定義了一些便捷函數(shù),如下:
          • $(call my-dir):獲取當(dāng)前文件夾路徑;
          • $(call all-java-files-under, ):獲取指定目錄下的所有Java文件;
          • $(call all-c-files-under, ):獲取指定目錄下的所有C文件;
          • $(call all-Iaidl-files-under, ) :獲取指定目錄下的所有AIDL文件;
          • $(call all-makefiles-under, ):獲取指定目錄下的所有Make文件;
             示例:
            ??LOCAL_PATH?:=?$(call?my-dir)?
            ??include?$(CLEAR_VARS)?

          ?? #?獲取所有子目錄中的Java文件
          ? LOCAL_SRC_FILES?:=?$(call?all-subdir-java-files)
          ?

          ?當(dāng)前模塊依賴的動(dòng)態(tài)Java庫名稱

          ? ?LOCAL_JAVA_LIBRARIES?:=?com.gityuan.lib?

          ? ?#?當(dāng)前模塊的名稱
          ? ?LOCAL_MODULE?:=?demo?

          ? ?#?將當(dāng)前模塊編譯成一個(gè)靜態(tài)的Java庫
          ? ?include?$(BUILD_STATIC_JAVA_LIBRARY)

          版權(quán)聲明:此文章轉(zhuǎn)載自碼農(nóng)網(wǎng)

          瀏覽 90
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  抠逼操逼| 超碰在线碰 | 男女操逼视频在线播放 | 国产1234操逼 | 玖玖精品影视 |