詳談Android編譯命令
工欲善其事,必先利其器,對于想要深入學(xué)習(xí)Android源碼,必須先掌握Android編譯命令.
一、引言
關(guān)于Android Build系統(tǒng),這個話題很早就打算整理下,遲遲沒有下筆,決定跟大家分享下。先看下面幾條指令,相信編譯過Android源碼的人都再熟悉不過的。
source /opt/android1204_17.conf source setenv.sh lunch make -j12
記得最初剛接觸Android時,同事告訴我用上面的指令就可以編譯Android源碼,指令雖短但過幾天就記不全或者忘記順序,每次編譯時還需要看看自己的云筆記,冰冷的指令總是難以讓我記憶。后來我決定認真研究下這個指令的含義。知其然還需知其所以然,這樣能更深層次的理解并記憶,才能與自身的知識體系建立強連接,或許還能有意外收獲,果然如此,接下來跟大家分享一下在研究上述幾條指令含義的過程中,深入了解到的Android Build(編譯)系統(tǒng)。
二、編譯命令
準備好編譯環(huán)境后,編譯Android源碼的第一步是 source build/envsetup.sh,其中source命令就是用于運行shell腳本命令,功能等價于".",因此該命令也等價于. build/envsetup.sh。在文件envsetup.sh聲明了當前會話終端可用的命令,這里需要注意的是當前會話終端,也就意味著每次新打開一個終端都必須再一次執(zhí)行這些指令。起初并不理解為什么新開的終端不能直接執(zhí)行make指令,到這里總算明白了。
接下來,解釋一下本文開頭的引用的命令:
source /opt/android1204_17.conf //初始化jdk環(huán)境變量(這個不是必需的,因廠商而異)
source setenv.sh //初始化編譯環(huán)境,包括后面的lunch和make指令
lunch //指定此次編譯的目標設(shè)備以及編譯類型
make -j12 //開始編譯,默認為編譯整個系統(tǒng),其中-j12代表的是編譯的job數(shù)量為12。
所有的編譯命令都在envsetup.sh文件能找到相對應(yīng)的function,比如上述的命令lunch,make,在文件一定能找到
function lunch(){ ... } function make(){ ... }
具體實現(xiàn)這里就不展開說明,下面精煉地總結(jié)了一下各個指令用法和功效。
2.1 代碼編譯
編譯指令 解釋
m 在源碼樹的根目錄執(zhí)行編譯
mm 編譯當前路徑下所有模塊,但不包含依賴
mmm [module_path] 編譯指定路徑下所有模塊,但不包含依賴
mma 編譯當前路徑下所有模塊,且包含依賴
mmma [module_path] 編譯指定路徑下所有模塊,且包含依賴
make [module_name] 無參數(shù),則表示編譯整個Android代碼
下面列舉部分模塊的編譯指令:
模塊 make命令 mmm命令
init make init mmm system/core/init
zygote make app_process mmm frameworks/base/cmds/app_process
system_server make services mmm frameworks/base/services
java framework make framework mmm frameworks/base
framework資源 make framework-res mmm frameworks/base/core/res
jni framework make libandroid_runtime mmm frameworks/base/core/jni
binder make libbinder mmm frameworks/native/libs/binder
上述mmm命令同樣適用于mm/mma/mmma,編譯系統(tǒng)采用的是增量編譯,只會編譯發(fā)生變化的目標文件。當需要重新編譯所有的相關(guān)模塊,則需要編譯命令后增加參數(shù)-B,比如make -B [module_name],或者 mm -B [module_path]。
Tips:
對于m、mm、mmm、mma、mmma這些命令的實現(xiàn)都是通過make方式來完成的。
mmm/mm編譯的效率很高,而make/mma/mmma編譯較緩慢;
make/mma/mmma編譯時會把所有的依賴模塊一同編譯,但mmm/mm不會;
建議:首次編譯時采用make/mma/mmma編譯;當依賴模塊已經(jīng)編譯過的情況,則使用mmm/mm編譯。
2.2 代碼搜索
搜索指令 解釋
cgrep 所有C/C++文件執(zhí)行搜索操作
jgrep 所有Java文件執(zhí)行搜索操作
ggrep 所有Gradle文件執(zhí)行搜索操作
mangrep [keyword] 所有AndroidManifest.xml文件執(zhí)行搜索操作
sepgrep [keyword] 所有sepolicy文件執(zhí)行搜索操作
resgrep [keyword] 所有本地res/*.xml文件執(zhí)行搜索操作
sgrep [keyword] 所有資源文件執(zhí)行搜索操作
上述指令用法最終實現(xiàn)方式都是基于grep指令,各個指令用法格式:
xgrep [keyword] //x代表的是上表的搜索指令
例如,搜索所有AndroidManifest.xml文件中的launcher關(guān)鍵字所在文件的具體位置,指令
mangrep launcher
再如,搜索所有system_app的selinux權(quán)限信息
sepgrep system_app
Tips: Android源碼非常龐大,直接采用grep來搜索代碼,不僅方法笨拙、浪費時間,而且搜索出很多無意義的混淆結(jié)果。根據(jù)具體需求,來選擇合適的代碼搜索指令,能節(jié)省代碼搜索時間,提高搜索結(jié)果的精準度,方便定位目標代碼。
2.3 導(dǎo)航指令
導(dǎo)航指令 解釋
croot 切換至Android根目錄
cproj 切換至工程的根目錄
godir [filename] 跳轉(zhuǎn)到包含某個文件的目錄
Tips: 當每次修改完某個文件后需要編譯時,執(zhí)行cproj后會跳轉(zhuǎn)到當前模塊的根目錄,也就是Android.mk文件所在目錄,然后再執(zhí)行mm指令,即可編譯目標模塊;當進入源碼層級很深后,需要返回到根目錄,使用croot一條指令完成;另外cd - 指令可用于快速切換至上次目錄。
2.4信息查詢
查詢指令 解釋
hmm 查詢所有的指令help信息
findmakefile 查詢當前目錄所在工程的Android.mk文件路徑
print_lunch_menu 查詢lunch可選的product
printconfig 查詢各項編譯變量值
gettop 查詢Android源碼的根目錄
gettargetarch 獲取TARGET_ARCH值
Tips: 當忘了前面的所有指令時,可以執(zhí)行一個hmm便可輸出這些指令的幫助信息。
其他指令:
make clean:執(zhí)行清理操作,等價于 rm -rf out/
make update-api:更新API,在framework API改動后需執(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分類
整個Build系統(tǒng)的Make文件分為三大類:
系統(tǒng)核心的Make文件:定義了Build系統(tǒng)的框架,文件全部位于路徑/build/core,其他Make文件都是基于該框架編寫的;
針對產(chǎn)品的Make文件:定義了具體某個型號手機的Make文件,文件路徑位于/device,該目錄下往往又以公司名和產(chǎn)品名劃分兩個子級目錄,比如/device/qcom/msm8916;
針對模塊的Make文件:整個系統(tǒng)分為各個獨立的模塊,每個模塊都一個專門的Make文件,名稱統(tǒng)一為"Android.mk",該文件定義了當前模塊的編譯方式。Build系統(tǒng)會掃描整個源碼樹中名為"Android.mk"的問題,并執(zhí)行相應(yīng)模塊的編譯工作。
3.2 編譯產(chǎn)物
經(jīng)過make編譯后的產(chǎn)物,都位于/out目錄,該目錄下主要關(guān)注下面幾個目錄:
/out/host:Android開發(fā)工具的產(chǎn)物,包含SDK各種工具,比如adb,dex2oat,aapt等。
/out/target/common:通用的一些編譯產(chǎn)物,包含Java應(yīng)用代碼和Java庫;
/out/target/product/[product_name]:針對特定設(shè)備的編譯產(chǎn)物以及平臺相關(guān)C/C++代碼和二進制文件;
在/out/target/product/[product_name]目錄下,有幾個重量級的鏡像文件:
system.img:掛載為根分區(qū),主要包含Android OS的系統(tǒng)文件;
ramdisk.img:主要包含init.rc文件和配置文件等;
userdata.img:被掛載在/data,主要包含用戶以及應(yīng)用程序相關(guān)的數(shù)據(jù);
當然還有boot.img,reocovery.img等鏡像文件,這里就不介紹了。
3.3 Android.mk解析
在源碼樹中每一個模塊的所有文件通常都相應(yīng)有一個自己的文件夾,在該模塊的根目錄下有一個名稱為“Android.mk”
的文件。編譯系統(tǒng)正是以模塊為單位進行編譯,每個模塊都有唯一的模塊名,一個模塊可以有依賴多個其他模塊,模塊間的依賴關(guān)系就是通過模塊名來引用的。也就是說當模塊需要依賴一個jar包或者apk時,必須先將jar包或apk定義為一個模塊,然后再依賴相應(yīng)的模塊。
對于Android.mk文件,通常都是以下面兩行
LOCAL_PATH := $(call my-dir) //設(shè)置當編譯路徑為當前文件夾所在路徑 include $(CLEAR_VARS) //清空編譯環(huán)境的變量(由其他模塊設(shè)置過的變量)
為方便模塊編譯,編譯系統(tǒng)設(shè)置了很多的編譯環(huán)境變量,如下:
LOCAL_SRC_FILES:當前模塊包含的所有源碼文件;
LOCAL_MODULE:當前模塊的名稱(具有唯一性);
LOCAL_PACKAGE_NAME:當前APK應(yīng)用的名稱(具有唯一性);
LOCAL_C_INCLUDES:C/C++所需的頭文件路徑;
LOCAL_STATIC_LIBRARIES:當前模塊在靜態(tài)鏈接時需要的庫名;
LOCAL_SHARED_LIBRARIES:當前模塊在運行時依賴的動態(tài)庫名;
LOCAL_STATIC_JAVA_LIBRARIES:當前模塊依賴的Java靜態(tài)庫;
LOCAL_JAVA_LIBRARIES:當前模塊依賴的Java共享庫;
LOCAL_CERTIFICATE:簽署當前應(yīng)用的證書名稱,比如flatform。
LOCAL_MODULE_TAGS:當前模塊所包含的標簽,可以包含多標簽,可能值為debgu,eng,user,development或optional(默認值)
針對這些環(huán)境變量,編譯系統(tǒng)還定義了一些便捷函數(shù),如下:
$(call my-dir):獲取當前文件夾路徑;
$(call all-java-files-under, <src>):獲取指定目錄下的所有Java文件;
$(call all-c-files-under, <src>):獲取指定目錄下的所有C文件;
$(call all-Iaidl-files-under, <src>) :獲取指定目錄下的所有AIDL文件;
$(call all-makefiles-under, <folder>):獲取指定目錄下的所有Make文件;
示例:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) # 獲取所有子目錄中的Java文件 LOCAL_SRC_FILES := $(call all-subdir-java-files) # 當前模塊依賴的動態(tài)Java庫名稱 LOCAL_JAVA_LIBRARIES := com.gityuan.lib # 當前模塊的名稱 LOCAL_MODULE := demo # 將當前模塊編譯成一個靜態(tài)的Java庫 include $(BUILD_STATIC_JAVA_LIBRARY)
- 單獨編譯Android 源代碼中的模塊實現(xiàn)方法
- Android內(nèi)核源碼 在Ubuntu上下載,編譯,安裝
- Android源碼 在Ubuntu上下載,編譯和安裝
- 為Android的apk應(yīng)用程序文件加殼以防止反編譯的教程
- Android APK反編譯圖文教程
- Android開發(fā)apk反編譯和二次打包教程
- Android應(yīng)用程序的編譯流程及使用Ant編譯項目的攻略
- 從源碼編譯Android系統(tǒng)的Java類庫和JNI動態(tài)庫的方法
- 利用源碼編譯Android系統(tǒng)的APK和可執(zhí)行命令的方法
- 使用Android studio創(chuàng)建的AIDL編譯時找不到自定義類的解決辦法
- Android 源碼如何編譯調(diào)試
相關(guān)文章
Android動畫之3D翻轉(zhuǎn)效果實現(xiàn)函數(shù)分析
Android中的翻轉(zhuǎn)動畫效果的實現(xiàn),Android中并沒有提供直接做3D翻轉(zhuǎn)的動畫,所以關(guān)于3D翻轉(zhuǎn)的動畫效果需要我們自己實現(xiàn),那么我們首先來分析一下Animation 和 Transformation,感興趣的朋友可以了解下啊2013-01-01Android之解析JSON數(shù)據(jù)示例(android原生態(tài),F(xiàn)astJson,Gson)
本篇文章主要介紹了Android之解析JSON數(shù)據(jù)示例,主要使用android原生態(tài)代碼解析,F(xiàn)astJson,Gson三種方法,有興趣的可以了解一下。2017-02-02開源電商app常用標簽"hot"之第三方開源LabelView
這篇文章主要介紹了開源電商app常用標簽"hot"之第三方開源LabelView,對開源電商app相關(guān)資料感興趣的朋友一起學(xué)習(xí)吧2015-12-12Android利用二階貝塞爾曲線實現(xiàn)添加購物車動畫詳解
這篇文章主要給大家介紹了關(guān)于Android利用二階貝塞爾曲線實現(xiàn)添加購物車動畫的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對各位Android開發(fā)者具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08Android通過RemoteViews實現(xiàn)跨進程更新UI示例
本篇文章主要介紹了Android通過RemoteViews實現(xiàn)跨進程更新UI示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02