posts - 189,comments - 115,trackbacks - 0
          Android Building System
          http://blog.csdn.net/liushaogeng/article/details/5834186


          最近研究了下Android的編譯系統(tǒng),下面結(jié)合編譯我們自己的產(chǎn)品mobot來(lái)對(duì)整個(gè)編譯系統(tǒng)進(jìn)行必要的介紹,方便大家今 后對(duì)默認(rèn)編譯的修改。

           

          先列出幾個(gè)覺(jué)得重要的Make文件:

          build/buildspec.mk

          build/envsetup.sh

          build/core/main.mk

          build/core/envsetup.mk

          build/config.mk

           

          總的來(lái)說(shuō),Android以模塊(module/package)的形式來(lái)組織各個(gè)系統(tǒng)的部件,每個(gè)模塊(module/package)的目錄下都會(huì)有一個(gè)Android.mk。所謂module就是指系統(tǒng)的Native Code,而相對(duì)于Java寫(xiě)的Android application稱(chēng)為package。

           

           

           

          Makefile的主要流 程 1

          初始化參數(shù)設(shè)置 2

          讀取Product的設(shè)定 3

          讀取BoardConfig 4

          讀取所有Module 4

          產(chǎn)生相應(yīng)的Rules,生成image 5

          具體make操作: 6

          完整編譯 6

          模塊編譯 6

          單獨(dú)編譯image文件 7

          一些疑問(wèn)和解答: 7

           

           

           

          Makefile的主要流程

          以下主要流程都 在build/core/main.mk里 安排。

           初始化相關(guān)的參數(shù)設(shè)置(buildspec.mk、envsetup.mk、config.mk)

           檢測(cè)編譯環(huán)境和目標(biāo)環(huán)境

           決定目標(biāo)product

           讀取product的配置信息及目標(biāo)平臺(tái)信息

           清除輸出目錄

           檢查版本號(hào)

           讀取Board的配置

           讀取所有Module的配置

           根據(jù)配置產(chǎn)生必要的規(guī)則(build/core/Makefile)

           生成image

          初始化參數(shù)設(shè)置

           main.mk 里,簡(jiǎn)單設(shè)置 幾個(gè)主要編譯路徑的變量后,來(lái)到config.mk:

          ——————————————config.mk——————————————

          其中設(shè)置了源文件的一系列路徑,包括頭文件、庫(kù)文件、服務(wù)、API已經(jīng)編譯工具的路徑。(前36行)

          從40行開(kāi)始,定義一些編譯模塊的生成規(guī)則:

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

          這里面除了第一個(gè)CLEAR_VARS外,其他都對(duì)應(yīng)的一種模塊的生成規(guī)則,每一個(gè)module都會(huì)來(lái)include其中某個(gè)來(lái)生成目標(biāo)模塊。

          例如:

          Camera模塊的makefile里( Android.mk )就包含了其中的一種生成規(guī)則BUILD_PACKAGE:

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

          也就是Camera會(huì)按照package.mk里的生成規(guī)則去生成目標(biāo)模塊。

          回到config.mk,接著會(huì)嘗試讀取buildspec.mk的設(shè)置:

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

          如同注釋所說(shuō),會(huì)嘗試查找 buildspec.mk ,如果文件不 存在會(huì)自動(dòng)使用環(huán)境變量的設(shè)置,如果仍然未定義,會(huì)按arm默認(rèn)的設(shè)置去build。

          這里的buildspec.mk可以自己創(chuàng)建,也可以將原先build/下的buildspec.mk.default直接命名為buildspec.mk并移到根目錄。

           

           

          實(shí)際上,buildspec.mk配置都被屏蔽了,我們可以根據(jù)需要直接打開(kāi)和修改一些變量。在這里我們可以加入自己的目標(biāo)產(chǎn)品信息:

          ifndef TARGET_PRODUCT

          TARGET_PRODUCT:=mobot

          endif

          以及輸出目錄設(shè)置:

          OUT_DIR:=$(TOPDIR)mobot

          讀取Product的設(shè)定

          回到config.mk,接著進(jìn)行全局變量設(shè)置,進(jìn)入envsetup.mk:

          ——————————————envsetup.mk——————————————

          里面的大部分函數(shù)都在build/envsetup.sh中定義。

          首先,設(shè)置版本信息,(11行)在build/core/version_defaults.mk中具體定義平臺(tái)版本、SDK版本、Product版本,我們可以將BUILD_NUMBER作為我們產(chǎn)品mobot的version信息,當(dāng)然,也可以自定義一個(gè)版本變量。

          Android Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

          回到envsetup.mk,接著設(shè)置默認(rèn)目標(biāo)產(chǎn)品(generic),這里由于我們?cè)赽uildspec.mk里設(shè)置過(guò)TARGET_PRODUCT ,事實(shí)上這個(gè) 變量值為mobot。

          然后讀取product的設(shè)置(41行), 具體實(shí)現(xiàn)在build/core/ product_config.mk 中,進(jìn)而進(jìn)入product.mk,從build/target/product/ AndroidProducts.mk 中讀出PRODUCT_MAKEFILES,這些makefile各自獨(dú)立定義product,而我們的產(chǎn)品mobot也應(yīng)添加一個(gè)makefile文件mobot.mk。在mobot.mk中我們可以加入所需編譯的PRODUCT_PACKAGES。

          下面為HOST配置信息及輸出目錄,最后打印相關(guān)信息:

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

          讀取BoardConfig

          接著回到config.mk,(114行)這 里會(huì)搜索所有的BoardConfig.mk,主要有以下兩個(gè)地方:

          $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk 

          vendor/*/$(TARGET_DEVICE)/BoardConfig.mk 

          這里的TARGET_DEVICE就是mobot,就是說(shuō)為了定義我們自己的產(chǎn)品mobot,我們要在build/target/board下添加一個(gè)自己的 目錄mobot用來(lái)加載自己 的board配置。

          在BoardConfig.mk中會(huì)決定是否編譯bootloader、kernel等信息。

          讀取所有Module

          結(jié)束全局變量配置后,回到main.mk,馬上對(duì)編譯工具及版本進(jìn)行檢查,錯(cuò)誤便中斷編譯。

          142行,包含文件 definitions.mk ,這里面定義了許多變量和函數(shù)供main.mk使用。main.mk第446行,這里會(huì)去讀取所有的Android.mk文件:

          include $(ONE_SHOT_MAKEFILE)

          這個(gè) ONE_SHOT_MAKEFILE 是在前面提到 的mm(envsetup.mk)函數(shù)中賦 值的:

          ONE_SHOT_MAKEFILE=$M make -C $T files $@

          而M=$(findmakefile),最終實(shí)現(xiàn)在:

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

          回到main.mk,最終將遍歷查找到的所有子目錄下的Android.mk的路徑保存到subdir_makefiles變量里(main.mk里的470行):

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

          我們?cè)趐ackage/apps下每個(gè)模塊根目錄都能看到Android.mk,里面會(huì)去定義當(dāng)前本地模塊的Tag: LOCAL_MODULE_TAGS ,Android會(huì)通過(guò)這個(gè)Tag來(lái)決定哪些本地模塊會(huì)編譯進(jìn)系統(tǒng),通過(guò)PRODUCT和LOCAL_MODULE_TAGS來(lái)決定哪些應(yīng)用包會(huì)編譯進(jìn)系統(tǒng)。( 前面說(shuō) 過(guò),你也能通過(guò)buildspec.mk來(lái) 制定你要編譯進(jìn)系統(tǒng)的模塊 )

          這個(gè)過(guò) 程在mian.mk的445行開(kāi)始,最后需要編譯的模塊路徑打包到ALL_DEFAULT_INSTALLED_MODULES (602行):

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

           

          產(chǎn)生相應(yīng)的Rules,生成image

          所有需要配置的準(zhǔn)備工作都已完成,下面該決定如何生成image輸出文件了,這一過(guò)程實(shí)際上在build/core/Makefile中處理的。

          這里定義各種img的生成方式,包括ramdisk.img、userdata.img、system.img、update.zip、recover.img等。具體對(duì)應(yīng)的rules可以參考下圖:

          http://p.blog.csdn.net/images/p_blog_csdn_net/yili_xie/EntryImages/20091214/make%20goals.png

          當(dāng)Make include所有的文件,完成對(duì)所有make文件的解析以后就會(huì)尋找生成 對(duì)應(yīng)目標(biāo) 的規(guī)則,依次生成它的依賴(lài),直到 所有滿足的模塊被編譯好,然后使用相應(yīng)的工具打包成相應(yīng)的img。

           

          具體make操作:

          完整編譯

          我們?cè)诟夸浵螺斎雖ake命令即可開(kāi)始完全編譯。這個(gè)命令實(shí)際編譯生成的默認(rèn)目標(biāo)是droid:

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

          也就是說(shuō),大家敲入make實(shí)際上執(zhí)行的make droid。而接下來(lái)大家看看main.mk文件里最后面的部分,會(huì)有很多偽目標(biāo),如sdk、clean、clobber等,這些在默認(rèn)的make droid的命令下是不會(huì)執(zhí)行的。我們可以在make后加上這些標(biāo)簽來(lái)單獨(dú)實(shí)現(xiàn)一些操作。如:輸入make sdk 將會(huì)生成該版本對(duì)應(yīng)的SDK,輸入make clean會(huì)清除上次編譯的輸出。

          模塊編譯

          有時(shí)候我們只修改了某一個(gè)模塊,希望能單獨(dú)編譯這個(gè)模塊而不是重新完整編譯一次,這時(shí)候我們要用到 build/envsetup.sh中提供的幾個(gè)bash的幫助函數(shù)。

          在 源代碼根目錄下執(zhí)行:

          .  build/envsetup.sh(.后面有空格)

          這 樣大家相當(dāng)于多了幾個(gè)可用的命令。

          這 時(shí)可以用help命令查看幫助信息:

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

          其中對(duì)模塊編譯有幫助的是tapas、m、mm、mmm這幾個(gè)命令。

          1、 tapas——以交互方式設(shè)置build環(huán)境變量。

             輸入:tapas

              第一步,選擇目標(biāo)設(shè)備:

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

               例如 我們選擇1

              第二步,選擇代碼格式:

          Android Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

          我們選擇1

          第三步,選擇產(chǎn)品平臺(tái):

          Android 
Building System - bimoshi - 血域天使的個(gè)人主頁(yè)

               注意:這里,Google源代碼里默認(rèn)是generic,而我們針對(duì)自己的產(chǎn)品應(yīng)修改成mobot

                     具體在build/envsetup.sh里的函數(shù)chooseproduct()中對(duì)相應(yīng)代碼進(jìn)行修 改。

           

          2、 m、mm、mmm使用獨(dú)立模塊的make命令。

          幾個(gè)命 令的功能使用help命令查看。

          舉個(gè)例 子,我們修改了Camera模塊的代碼,現(xiàn) 在需要重新單獨(dú)編譯這一塊,這時(shí)可以使用mmm命令,后面跟指定模塊的路徑(注意是模塊的根目錄)。

          具體如 下:

          mmm packages/apps/Camera/

          為了可 以直接測(cè)試改動(dòng),編譯好后需要重新生成system.img

          可以執(zhí) 行:make snod

          單獨(dú)編譯image文件

          一般我 們完整編譯后,會(huì)生成三個(gè)重要的image文 件:ramdisk.img、system.img和userdata.img。當(dāng)然我們可以分開(kāi)單獨(dú)去編譯 這三個(gè)目標(biāo):

          make ramdisk —— ramdisk.img

          make userdataimage —— userdata.img

          make systemimage  —— system.img

          一些疑問(wèn)和解答:

          1)  什么是recovery.img?

          顧名思義,recovery.img是為了恢復(fù)系統(tǒng)的,相對(duì)于普通的boot.img,recovery.img多了一些圖片文件(恢復(fù)時(shí)界面的背景)、/sbin/recovery/目錄(跟 恢復(fù)有關(guān)的二進(jìn)制文件),一 些初始化文件也不相同(init.rc、init.goldfish.rc、default.prop)

          這就是為什么啟 動(dòng)恢復(fù)模式時(shí)會(huì)進(jìn)入類(lèi)似文本界面而不是圖形界面。

          將recovery.img文件復(fù)制到SD卡中,進(jìn)入shell下輸入:

          mount -a

          flash_image recovery /sdcard/recovery.img

          若提示“no space on device”,可用fastboot模式刷

          fastboot erase recovery

          fastboot flash recovery recovery.img

          在關(guān)機(jī)狀態(tài)下按home+power鍵進(jìn)入recovery模式,根據(jù)選項(xiàng)選擇需要的操作。

           

          2)  make sdk和make droid編譯有什么不同?

          make sdk:

          其實(shí),執(zhí)行make sdk,編譯后會(huì)在目錄out/host/linux-x86里生成sdk目錄,這個(gè)sdk和官方下載的sdk包是一樣的,可以直接使用。

          make droid:

          實(shí)際上droid就是默認(rèn)的生成目標(biāo),和直接敲make是一樣的,都會(huì)完整編譯出目標(biāo)image文件,但不會(huì)編譯出sdk。

           

          3)  我們將默認(rèn)產(chǎn) 品改為mobot,那我怎么編譯原先的generic?

          其實(shí),無(wú)論編譯哪個(gè)目標(biāo)產(chǎn)品版本,只要產(chǎn)品相關(guān)設(shè)置存在,都可以直接在編譯時(shí)加上目標(biāo)產(chǎn)品名來(lái)編譯。會(huì)在out/target/product/下生成對(duì)應(yīng)的 產(chǎn)品輸出目錄,如:要編譯generic版本:

          make TARGET_PRODUCT := generic


          原帖:http://bimoshi.blog.163.com/blog/static/14613297201022233711527/


          posted on 2011-10-19 16:53 MEYE 閱讀(677) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 明溪县| 甘谷县| 张家川| 喀喇| 阳江市| 藁城市| 新沂市| 金塔县| 张家口市| 葫芦岛市| 中牟县| 封丘县| 蒙阴县| 建瓯市| 方城县| 庄浪县| 资溪县| 农安县| 日土县| 镇平县| 伊通| 封开县| 海淀区| 恩施市| 伊金霍洛旗| 襄垣县| 溧阳市| 岐山县| 晋江市| 高要市| 娱乐| 昌江| 格尔木市| 马边| 介休市| 乌兰察布市| 海宁市| 上思县| 宣恩县| 沭阳县| 禹城市|