官术网_书友最值得收藏!

2.3 Android編譯的板級支持

Android的開源代碼默認(rèn)是支持仿真器的。如果需要使用Android的開源代碼支持一個(gè)特定的設(shè)備,除了具體的代碼實(shí)現(xiàn)之外,還需要對Android的編譯系統(tǒng)做出一些更改。這種編譯的板級支持可以作為附加的方式被添加到Android系統(tǒng)之中。

2.3.1 支持一個(gè)板的工作

從Android開源代碼到一個(gè)板(特定設(shè)備)的支持,變化的部分就是更改部分代碼和增加板級支持目錄。更改完成后,Android編譯系統(tǒng)按照一定的順序進(jìn)行處理。

Android對特定板的支持的處理流程如圖2-1所示。

圖2-1 Android編譯的板級支持的處理流程

Android對特定板的編譯支持主要分成以下幾個(gè)步驟。

● Make的時(shí)候傳入TARGET_PRODUCT宏。

● Android的編譯系統(tǒng)根據(jù)TARGET_PRODUCT宏找到目標(biāo)板的配置目錄。

● 在目標(biāo)板配置目錄中的板級配置文件得到若干配置宏。

● (系統(tǒng)編譯流程)各個(gè)模塊根據(jù)配置宏進(jìn)行編譯。

● 處理目標(biāo)板中的其他特定配置文件。

Android編譯流程主要涉及以下的一些文件。

● buildspec.mk:根目錄中的文件,指定板名稱。

● vendersetup.sh:專用設(shè)置文件。

● BoardConfig.mk:板級全局配置。

● AndroidBoard.mk:當(dāng)前板的特殊配置。

● AndroidProducts.mk:產(chǎn)品的配置。

buildspec.mk和vendersetup.sh兩個(gè)文件執(zhí)行的是同一種功能,也就是目標(biāo)產(chǎn)品名稱的定義,二者可以取其一(實(shí)際上也可以有其他定義方式)。

在make配置后,系統(tǒng)可以開始進(jìn)行構(gòu)建。構(gòu)建的前面就是找到目標(biāo)產(chǎn)品的配置目錄,并使用其中的幾個(gè)文件:BoardConfig.mk中定義的內(nèi)容可以被系統(tǒng)的每一個(gè)部分使用(傳遞到每一個(gè)Android.mk);AndroidBoard.mk和AndroidProducts.mk是配置文件,可以引用默認(rèn)的內(nèi)容。板級的編譯支持目錄中也可以具有自己的Android.mk文件,與普通的用法類似。

2.3.2 buildspec.mk文件的作用

將buildspec.mk增加到源代碼TOP目錄,可以完成配置工作。Android在執(zhí)行make的時(shí)候,將找到TOP目錄中的buildspec.mk,取出其中定義的內(nèi)容進(jìn)行配置。buildspec.mk的作用實(shí)際上就是為了定義幾個(gè)宏,作為Make第一步使用的環(huán)境變量。

一個(gè)buildspec.mk的寫法如下所示:

ifndef TARGET_PRODUCT
#TARGET_PRODUCT:=generic
Endif
ifndef TARGET_BUILD_VARIANT
#TARGET_BUILD_VARIANT:=user
#TARGET_BUILD_VARIANT:=userdebug
#TARGET_BUILD_VARIANT:=eng
endif

其中,最重要的一個(gè)宏是TARGET_PRODUCT,表示目標(biāo)產(chǎn)品的名稱;TARGET_BUILD_VARIANT則表示編譯的類型,分成user(用戶模式)、userdebug(用戶調(diào)試模式)、eng(工程模式),這個(gè)宏將主要影響系統(tǒng)是否具有root權(quán)限等方面。

當(dāng)編譯不進(jìn)行定義時(shí),或者TARGET_PRODUCT的數(shù)值本身就是“generic”,將使用“generic”板(也就是仿真器)的配置,其路徑為:build/target/product。

提示:Android的仿真器默認(rèn)情況下也是ARM體系結(jié)構(gòu)的目標(biāo),仿真器QEMU仿真執(zhí)行了ARM代碼,因此generic目標(biāo)和實(shí)際的產(chǎn)品差別并不大。

當(dāng)TARGET_PRODUCT宏被正式定義時(shí),將在自定義板的路徑找到名稱為其值的目錄,作為板級編譯支持目錄。可以使用的板級編譯支持目錄有以下兩個(gè)。

● device/*/<TARGET_PRODUCT>

● vendor/*/<TARGET_PRODUCT>

其含義為TOP目錄中的device或者vendor目錄中的某個(gè)子目錄中的下一級目錄作為板級編譯支持目錄。也就是說板級編譯支持目錄必須是Android三級子目錄,且必須在device或者vendor目錄中,二級子目錄沒有要求,一般是公司的名稱。

兩個(gè)產(chǎn)品的板級編譯支持目錄如下所示。

● device/htc/passion/:Nexus One手機(jī)(Google和HTC合作出品)。

● device/samsung/crespo/:Nexus S手機(jī)(Google和三星合作出品)。

2.3.3 vendersetup.sh和lunch命令

vendersetup.sh文件可以提供另外一種編譯配置方法,這也是較新版本的Android系統(tǒng)推薦的方法。其職能實(shí)際上也是配置幾個(gè)宏,作為Make時(shí)的環(huán)境變量。

在編譯之前,可以使用envsetup.sh腳本進(jìn)行編譯的配置,配置的過程中,將會(huì)調(diào)用每一個(gè)板的vendersetup.sh文件,內(nèi)容如下所示:

$ . build/envsetup.sh
including device/htc/passion/vendorsetup.sh
including device/samsung/crespo/vendorsetup.sh

此時(shí)的配置,實(shí)際是一個(gè)“遍歷”的過程,將會(huì)調(diào)用device/*/和vendor/*/目錄中每一個(gè)板的vendersetup.sh文件。只要板級支持目錄中有vendersetup.sh文件,就會(huì)被調(diào)用。調(diào)用后實(shí)際上將為增加系統(tǒng)可以選擇的目標(biāo)產(chǎn)品,這個(gè)影響將在使用lunch命令進(jìn)行選擇產(chǎn)品時(shí)有所體現(xiàn),內(nèi)容如下所示:

$ lunch
You're building on Linux
Lunch menu... pick a combo:
    1. generic-eng
    2. simulator
    3. full_passion-userdebug
    4. full_crespo-userdebug
Which would you like? [generic-eng] 1
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3.4
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=GRJ22
============================================

在lunch時(shí)出現(xiàn)的菜單項(xiàng)目(combo)中,出現(xiàn)了4個(gè)選項(xiàng),可以使用數(shù)字進(jìn)行選擇。從中可見,除了默認(rèn)的generic-eng和simulator兩個(gè)選擇之外,full_passion-userdebug和full_crespo-userdebug就是來自于自定義板級支持的文件。

device/htc/passion/中的vendersetup.sh文件如下所示:

add_lunch_combo full_passion-userdebug

device/samsung/crespo/中的vendersetup.sh文件如下所示:

add_lunch_combo full_crespo-userdebug

其中full_passion和full_crespo也就是所定義的TARGET_PRODUCT宏的名稱。在lunch時(shí)選擇了數(shù)字后,實(shí)際上得到的結(jié)果也是設(shè)置TARGET_PRODUCT等宏。

2.3.4 BoardConfig.mk文件的作用

BoardConfig.mk文件是一個(gè)平臺(tái)全局配置的文件,這些配置的內(nèi)容可以在各個(gè)工程的Android.mk文件中得到。BoardConfig.mk只是進(jìn)行配置的定義,其中不能包含實(shí)際執(zhí)行的命令。

例如,BoardConfig.mk文件可以進(jìn)行定義:

BOARD_USES_GENERIC_AUDIO := false

BOARD_USES_GENERIC_AUDIO等宏的數(shù)值就可以在每一個(gè)編譯文件(Android.mk)中被讀出。

BoardConfig.mk文件中也可以使用-include包含其他的板級配置宏。

例如,device/samsung/crespo/中的BoardConfig.mk文件包含了如下的片斷:

-include vendor/samsung/crespo/BoardConfigVendor.mk
TARGET_CPU_ABI := armeabi-v7a               # CPU體系結(jié)構(gòu)的二進(jìn)制格式
BOARD_HAVE_BLUETOOTH := true                # 是否具有藍(lán)牙
TARGET_NO_BOOTLOADER := true                # 是否具有BootLoader
TARGET_NO_KERNEL := false                   # 是否具有Linux內(nèi)核

BoardConfig.mk文件中既可以使用TARGET_CPU_ABI等編譯系統(tǒng)使用的宏,也可以定義自己使用的宏。

2.3.5 AndroidProducts.mk文件

AndroidProducts.mk為當(dāng)前板的配置文件,其中可以使用一些宏定制最終在目標(biāo)系統(tǒng)中需要的安裝內(nèi)容。在實(shí)際的板級支持過程中,通常需要在AndroidProducts.mk中包含同類文件,進(jìn)行大部分默認(rèn)的定義,然后再對不同配置進(jìn)行覆蓋(Override)定義。

AndroidProducts.mk需要定義幾個(gè)宏,用于表示當(dāng)前產(chǎn)品的信息: PRODUCT_NAME(產(chǎn)品名稱),PRODUCT_DEVICE(產(chǎn)品設(shè)備)。

其中build/target/product/目錄中的AndroidProducts.mk是默認(rèn)的產(chǎn)品配置文件,內(nèi)容如下所示。

ifneq ($(TARGET_BUILD_APPS),)
PRODUCT_MAKEFILES := \
  $(LOCAL_DIR)/core.mk \
  $(LOCAL_DIR)/generic.mk
else
PRODUCT_MAKEFILES := \
  $(LOCAL_DIR)/core.mk \
  $(LOCAL_DIR)/generic.mk \
  $(LOCAL_DIR)/generic_x86.mk \
  $(LOCAL_DIR)/full.mk \
  $(LOCAL_DIR)/sdk.mk \
  $(LOCAL_DIR)/sim.mk
endif

其中指定的PRODUCT_MAKEFILES實(shí)際上就是被其包含的文件。full.mk也在build/target/product/目錄中,其中具有如下內(nèi)容。

PRODUCT_NAME := full
PRODUCT_BRAND := generic
PRODUCT_DEVICE := generic
PRODUCT_MODEL := Full Android

這里的PRODUCT_NAME等宏的定義也就是產(chǎn)品名稱等信息,這里進(jìn)行了定義后,在系統(tǒng)中通過部分的函數(shù)可以讀取這些信息,并可以提供給程序和用戶。

其中另一個(gè)功能是定義系統(tǒng)預(yù)安裝的包。例子如下所示:

PRODUCT_PACKAGES := \
  OpenWnn \
  PinyinIME \
  VoiceDialer \
  libWnnEngDic \
  libWnnJpnDic \
  libwnndict

在包被增加到PRODUCT_PACKAGES宏之后,這個(gè)包將會(huì)被預(yù)裝到系統(tǒng)中,作為系統(tǒng)映像的一部分。

系統(tǒng)預(yù)裝文件使用PRODUCT_COPY_FILES宏來定義。例子如下所示:

PRODUCT_COPY_FILES := \
  development/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
  development/data/etc/vold.conf:system/etc/vold.conf

在PRODUCT_COPY_FILES的各項(xiàng)內(nèi)容中,“:”前面的為源文件,“:”后面的為目標(biāo)機(jī)的文件(為out/target/product/<產(chǎn)品名稱>目錄加上后面的路徑),編譯時(shí)將源文件復(fù)制為目標(biāo)文件。如果目標(biāo)文件的目錄沒有,也會(huì)進(jìn)行自動(dòng)創(chuàng)建。因此,這是另外一種像目標(biāo)系統(tǒng)中預(yù)裝文件的方法。

另外一個(gè)可以定義的內(nèi)容是系統(tǒng)語言區(qū)域的定義,在build/target/product/目錄中的languages_<XXX>.mk文件中進(jìn)行定義,類似具有如下的內(nèi)容:

PRODUCT_LOCALES := en_US en_GB fr_FR it_IT de_DE es_ES

這里使用的是ISO 639-1定義的語言碼和ISO 3166-1-alpha-2定義的區(qū)域碼。

例如,device/samsung/crespo/中的AndroidProducts.mk文件包含了同目錄的full_crespo.mk文件,full_crespo.mk的主要內(nèi)容如下所示:

$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_full.mk)
$(call inherit-product, device/samsung/crespo/device.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/full.mk)
PRODUCT_NAME := full_crespo
PRODUCT_DEVICE := crespo
PRODUCT_MODEL := Full Android on Crespo

此時(shí)除了PRODUCT_NAME等宏的定義之外,也可以包含其他的同類文件,包含的languages_full.mk和full.mk就是系統(tǒng)默認(rèn)的文件,在這里被復(fù)用,而device.mk是當(dāng)前目錄中的另外一個(gè)文件。

2.3.6 AndroidBoard.mk文件

AndroidBoard.mk用于板級一些編譯內(nèi)容的定義,這個(gè)文件通常是可選的。AndroidBoard.mk的功能和語法類似一般的Android.mk文件。

例如,build/target/board/generic/中的AndroidBoard.mk文件如下所示:

LOCAL_PATH := $(call my-dir)
file := $(TARGET_OUT_KEYLAYOUT)/tuttle2.kl
ALL_PREBUILT += $(file)
$(file) : $(LOCAL_PATH)/tuttle2.kl | $(ACP)
    $(transform-prebuilt-to-target)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := tuttle2.kcm
include $(BUILD_KEY_CHAR_MAP)

這里進(jìn)行了兩個(gè)工作:一個(gè)是將按鍵布局的文件tuttle2.kl復(fù)制到目標(biāo)系統(tǒng)中,一個(gè)是調(diào)用BUILD_KEY_CHAR_MAP模板對按鍵字符映像的tuttle2.kcm文件進(jìn)行編譯處理。由于每一個(gè)Android板的輸入設(shè)備通常都不同,因此在一個(gè)特定設(shè)備的構(gòu)建過程中,按鍵相關(guān)的定制處理也是經(jīng)常需要進(jìn)行的工作。

AndroidBoard.mk不是必需的,例如,在crespo的配置目錄device/samsung/crespo/中,就沒有AndroidBoard.mk文件,而具有Android.mk文件。

2.3.7 編譯中的層疊加

在一個(gè)Android的板級構(gòu)建過程中,有一種不更改源代碼文件,而實(shí)現(xiàn)構(gòu)建出不同內(nèi)容的方法,這就是通過編譯中層疊加(overlay)的機(jī)制來實(shí)現(xiàn)的。使用這種方式可以基于同樣的源代碼,為了不同的硬件或不同產(chǎn)品構(gòu)建出不同的系統(tǒng)。

在板級配置目錄中,可以有一個(gè)名稱為overlay的子目錄,這個(gè)目錄表示的就是一個(gè)代碼疊加層。這個(gè)overlay目錄對應(yīng)于Android源代碼的TOP目錄,在編譯的過程中將使用overlay目錄中的內(nèi)容替換TOP目錄中的內(nèi)容。

例如,在Nexus S(crespo)的板級配置的目錄device/samsung/crespo/overlay/下面的一個(gè)目錄結(jié)構(gòu)如下所示:

device/samsung/crespo/overlay/frameworks/base/core/
`-- res
  `-- res
        |-- drawable-hdpi
        |   `-- default_wallpaper.jpg
        |-- values
        |   `-- config.xml
        `-- xml
            `-- power_profile.xml

此時(shí),將把TOP目錄中的frameworks/base/core/res/res/drawable-hdpi中的default_wallpaper.jpg替換成overlay對應(yīng)目錄的同名文件。這個(gè)文件實(shí)際上是系統(tǒng)默認(rèn)的墻紙,由此,進(jìn)行完如此的定義后,相當(dāng)于crespo編譯的系統(tǒng)將替換默認(rèn)的墻紙。

Android系統(tǒng)中很多模塊比較適合使用這種替換方式,例如應(yīng)用程序包中的資源文件等。尤其值得注意的是,一旦使用overlay進(jìn)行層替換,原有的源文件將不再起作用。

主站蜘蛛池模板: 华亭县| 阆中市| 齐河县| 天峻县| 金昌市| 固原市| 桑日县| 靖西县| 尤溪县| 永顺县| 鄂托克前旗| 门源| 凭祥市| 张家界市| 阆中市| 旬阳县| 抚宁县| 五莲县| 会理县| 定南县| 扎囊县| 镇宁| 阜城县| 广南县| 蒙阴县| 荣成市| 旌德县| 樟树市| 临颍县| 武山县| 平泉县| 石首市| 庆阳市| 甘德县| 交城县| 丰城市| 林口县| 正安县| 泸定县| 右玉县| 潜山县|