日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

Android 编译系统分析(一)

發(fā)布時(shí)間:2024/4/15 Android 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 编译系统分析(一) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、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
  • ?主要配置文件:

    ??????build/core/config.mk?????????summary of config

    ??????build/core/envsetup.mk????generate dir config and so on

    ??????build/target/product?????????product config

    ??????build/target/board????????????board config

    ??????build/core/combo??????????????build flags config

    這里解釋下這里的board和product。borad主要是設(shè)計(jì)到硬件芯片的配置,比如是否提供硬件的某些功能,比如說(shuō)GPU等等,或者芯片支持浮點(diǎn)?運(yùn)算等等。product是指針對(duì)當(dāng)前的芯片配置定義你將要生產(chǎn)產(chǎn)品的個(gè)性配置,主要是指APK方面的配置,哪些APK會(huì)包含在哪個(gè)product中,哪?些APK在當(dāng)前product中是不提供的。?
    ????? config.mk是一個(gè)總括性的東西,它里面定義了各種module編譯所需要使用的HOST工具以及如何來(lái)編譯各種模塊,比如說(shuō)?BUILT_PREBUILT就定義了如何來(lái)編譯預(yù)編譯模塊。envsetup.mk主要會(huì)讀取由envsetup.sh寫(xiě)入環(huán)境變量中的一些變量來(lái)配置?編譯過(guò)程中的輸出目錄,combo里面主要定義了各種Host和Target結(jié)合的編譯器和編譯選項(xiàng)。

    配置部分主要完成以下幾個(gè)工作:

    a)?基于Android?產(chǎn)品的配置(product config):選擇構(gòu)建安裝的運(yùn)行程序(user package)

    b)?設(shè)置?target?等相關(guān)變量TARGET_ARCH, TARGET_OS,TARGET_BUILD_TYPE, TARGET_PREBUILT_TAG

    c)?根據(jù)編譯環(huán)境設(shè)置?host等相關(guān)變量HOST_OS, HOST_ARCH,HOST_BUILD_TYPE, HOST_PREBUILT_TAG

    d)?編譯?target上運(yùn)行程序所需的工具鏈及編譯參數(shù)設(shè)置,如linux-arm-cc,cflag,include目錄等。

    e)?編譯?host上運(yùn)行程序所需的工具鏈及編譯參數(shù)設(shè)置。

    下圖簡(jiǎn)要介紹了Android build system的配置部分的主要構(gòu)成及相互關(guān)系。

    ?

    二、初始化參數(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ī)則:

    除了CLEAR_VARS是清楚本地變量之外,其他所有的都對(duì)應(yīng)了一種模塊的生成規(guī)則,每一個(gè)本地模塊最后都會(huì)include其中的一種來(lái)生成目標(biāo)模塊。

    ?
    回到
    config.mk ,接著會(huì)嘗試讀取 buildspec.mk 的設(shè)置:
    ? 如同注釋所說(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:=generic_x86

    endif

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

    OUT_DIR:=$(TOPDIR)generic_x86

    ?

    三、讀取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)品generic_x86的version信息,當(dāng)然,也可以自定義一個(gè)版本變量。

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

    然后讀取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)品generic_x86也應(yīng)添加一個(gè)makefile文件generic_x86.mk。在generic_x86.mk中我們可以加入所需編譯的PRODUCT_PACKAGES。

    下面為generic_x86.mk:

    ? 四、讀取BoardConfig

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

    ?

    這里的TARGET_DEVICE就是generic_x86,就是說(shuō)為了定義我們自己的產(chǎn)品generic_x86,我們要在build/target/board下添加一個(gè)自己的目錄generic_x86用來(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?$@

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

    我們?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行):

    ?

    六、產(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://img154.ph.126.net/5ekAHoRqfPf17ALmDJGDYA==/2269251262242871911.png

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

    ?

    具體make操作:

    完整編譯

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

    也就是說(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命令查看幫助信息:

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

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

    ???輸入:tapas

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

    第二步,選擇代碼格式:

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

    ?

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

    ?具體在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

    總結(jié)

    以上是生活随笔為你收集整理的Android 编译系统分析(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。