Android源碼編譯命令詳解

一、引言

先看下面幾條指令爽哎,相信編譯過Android源碼的人都再熟悉不過的姐帚。

source setenv.sh
lunch
make -j8

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

二锣杂、編譯命令

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

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

source setenv.sh  //初始化編譯環(huán)境稼虎,包括后面的lunch和make指令
lunch  //指定此次編譯的目標(biāo)設(shè)備以及編譯類型
make  -j8 //開始編譯衅檀,默認(rèn)為編譯整個系統(tǒng),其中-j8代表的是編譯的job數(shù)量為8霎俩。

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

function lunch(){
    ...
}

function make(){
    ...
}

source envsetup.sh杉适,需要cd到setenv.sh文件所在路徑執(zhí)行谎倔,路徑可能在build/envsetup.sh,或者integrate/envsetup.sh猿推,再或者不排除有些廠商會封裝自己的.sh腳本片习,但核心思路是一致的。

具體實現(xiàn)這里就不展開說明蹬叭,下面精煉地總結(jié)了一下各個指令用法和功效藕咏。

2.1 代碼編譯

編譯指令 解釋
m 在源碼樹的根目錄執(zhí)行編譯
mm 編譯當(dāng)前路徑下所有模塊,但不包含依賴
mmm [module_path] 編譯指定路徑下所有模塊秽五,但不包含依賴
mma 編譯當(dāng)前路徑下所有模塊孽查,且包含依賴
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ā)生變化的目標(biāo)文件起宽。當(dāng)需要重新編譯所有的相關(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編譯;當(dāng)依賴模塊已經(jīng)編譯過的情況柠衍,則使用mmm/mm編譯洋满。

2.2 代碼搜索

搜索指令 解釋
cgrep 所有 C/C++ 文件執(zhí)行搜索操作
jgrep 所有Java文件執(zhí)行搜索操作
ggrep 所有Gradle文件執(zhí)行搜索操作
mangrep [keyword] 所有AndroidManifest.xml文件執(zhí)行搜索操作
mgrep [keyword] 所有Android.mk文件執(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

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

jgrep zygote

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

sepgrep system_app

Tips: Android源碼非常龐大驻民,直接采用grep來搜索代碼翻具,不僅方法笨拙、浪費時間回还,而且搜索出很多無意義的混淆結(jié)果裆泳。根據(jù)具體需求,來選擇合適的代碼搜索指令懦趋,能節(jié)省代碼搜索時間晾虑,提高搜索結(jié)果的精準(zhǔn)度,方便定位目標(biāo)代碼仅叫。

2.3 導(dǎo)航指令

導(dǎo)航指令 解釋
croot 切換至Android根目錄
cproj 切換至工程的根目錄
godir [filename] 跳轉(zhuǎn)到包含某個文件的目錄

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

2.4 信息查詢

查詢指令 解釋
hmm 查詢所有的指令help信息
findmakefile 查詢當(dāng)前目錄所在工程的Android.mk文件路徑
print_lunch_menu 查詢lunch可選的product
printconfig 查詢各項編譯變量值
gettop 查詢Android源碼的根目錄
gettargetarch 獲取TARGET_ARCH值

2.5 其他指令

上述只是列舉比較常用的指令坏快,還有其他指令,而且不同的build編譯系統(tǒng)憎夷,支持的指令可能會存在一些差異莽鸿,當(dāng)忘記這些編譯指令,可以通過執(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文件。

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”,該文件定義了當(dāng)前模塊的編譯方式索抓。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ù)鸦列;

當(dāng)然還有boot.img,reocovery.img等鏡像文件鹏倘,這里就不介紹了薯嗤。

3.3 Android.mk解析

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

對于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)鏈接時需要的庫名;
  • LOCAL_SHARED_LIBRARIES:當(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)值)

針對這些環(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)前模塊依賴的動態(tài)Java庫名稱
LOCAL_JAVA_LIBRARIES := com.gityuan.lib

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

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

四咏雌、附錄:常用make命令

  1. make -jX
    X表示數(shù)字凡怎,這個命令將編譯Android系統(tǒng)并生成鏡像,XX表示可以使用到的CPU核數(shù)赊抖,這在配置好的電腦上特別有用统倒,公司的16核ubuntu服務(wù)器執(zhí)行make -j16只要不到20分鐘,而雙核PC上需要4個小時氛雪!
  2. make snod
    這條命令將重新生成鏡像房匆,消耗的時間很少,類似WinCE的makeimg過程报亩,如果你修改了一些數(shù)據(jù)文件(如音樂浴鸿、視頻)等文件時比較有用。
  3. make cts
    這條命令將編譯CTS套機弦追,編譯出的結(jié)果放在out目錄對應(yīng)版的data/app目錄下面岳链。CTS測試時有用
  4. make installclean
    這條命令清除out目錄下對應(yīng)板文件夾中的內(nèi)容,也就是相當(dāng)于make clean劲件,通常如果改變了一些數(shù)據(jù)文件(如去掉)掸哑、最好執(zhí)行以下make installclean,否則殘留在out目錄下的還會被打包進去零远。
  5. mm/mm -B
    開發(fā)調(diào)試中最喜歡這條命令了苗分,在修改了的目錄下執(zhí)行這條命令,就能智能地進行編譯牵辣,輸出的文件在通過adb推送到目標(biāo)機摔癣,可以很方便地調(diào)試。
    1 .make sdk
    這條命令可以生成可發(fā)布的SDK,目前還沒試過供填,據(jù)說需要JDK1.5
  6. make Setting
    可以單獨編譯setting這個模塊拐云,目前還沒試,猜想是不是可以單獨編譯Email近她、Music這些模塊
  7. make bootimage
    用這條命令可以生成boot.img,這個鏡像文件中包含Linux Kernel叉瘩,Ram disk,生成的boot.img只能通過fastboot進行燒寫粘捎,這在只修改了Linux內(nèi)核的時候有用
  8. make systemimage
    同上薇缅,不過是生成system.img用的。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末攒磨,一起剝皮案震驚了整個濱河市泳桦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌娩缰,老刑警劉巖灸撰,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拼坎,居然都是意外死亡浮毯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門泰鸡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來债蓝,“玉大人,你說我怎么就攤上這事盛龄∈渭#” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵余舶,是天一觀的道長啊鸭。 經(jīng)常有香客問我,道長匿值,這世上最難降的妖魔是什么赠制? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮千扔,結(jié)果婚禮上憎妙,老公的妹妹穿的比我還像新娘库正。我一直安慰自己曲楚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布褥符。 她就那樣靜靜地躺著龙誊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪喷楣。 梳的紋絲不亂的頭發(fā)上趟大,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天鹤树,我揣著相機與錄音,去河邊找鬼逊朽。 笑死罕伯,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的叽讳。 我是一名探鬼主播追他,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼岛蚤!你這毒婦竟也來了邑狸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤谤逼,失蹤者是張志新(化名)和其女友劉穎瑰剃,沒想到半個月后羡棵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡硅堆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了犁苏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硬萍。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖围详,靈堂內(nèi)的尸體忽然破棺而出朴乖,到底是詐尸還是另有隱情,我是刑警寧澤助赞,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布买羞,位于F島的核電站,受9級特大地震影響雹食,放射性物質(zhì)發(fā)生泄漏畜普。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一群叶、第九天 我趴在偏房一處隱蔽的房頂上張望吃挑。 院中可真熱鬧,春花似錦街立、人聲如沸舶衬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逛犹。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間虽画,已是汗流浹背舞蔽。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留码撰,地道東北人渗柿。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像脖岛,于是被迫代替她去往敵國和親做祝。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容