这篇文章对Android的编译系统做个大概的分析,希望对大家有帮助,也希望大家一起讨论。
编译系统的框架和结构网上有很多文章描述,本文后面也附了一些链接可供大家参考。
下面我们就从Android系统(以android4.2.2为例)的编译过程来分析其编译系统。
envsetup.sh其主要作用如下:
# add the default one here add_lunch_combo aosp_arm-eng add_lunch_combo aosp_x86-eng add_lunch_combo aosp_mips-eng add_lunch_combo vbox_x86-eng
# Execute the contents of any vendorsetup.sh files we can find. for f in `test -d device && find device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null` \ `test -d vendor && find vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null` do echo "including $f" . $f done unset f
local product=$(echo -n $selection | sed -e "s/-.*$//") check_product $product
local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//") check_variant $variantcheck_product会调用config.mk设置一些平台无关的变量,下面有详细描述
该文件定义了编译过程中需要的一些 与平台无关的变量,在该方法里被调用
# Get the exact value of a build variable. function get_build_var() { T=$(gettop) if [ ! "$T" ]; then echo "Couldn't locate the top of the tree. Try setting TOP." >&2 return fi CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \ make --no-print-directory -C "$T" -f build/core/config.mk dumpvar-$1 }
现列举出几个比较重要的地方:
# --------------------------------------------------------------- # Define most of the global variables. These are the ones that # are specific to the user's build configuration. include $(BUILD_SYSTEM)/envsetup.mk1、envsetup.mk里定义了大部分的全局变量,可以从该文件的末尾发现定义的全局变量。包括android版本信息等。
2、定义了board_config_mk变量,主要是板级的配置选项,比如CPU类型,外设相关
# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE) # or under vendor/*/$(TARGET_DEVICE). Search in both places, but # make sure only one exists. # Real boards should always be associated with an OEM vendor. board_config_mk := \ $(strip $(wildcard \ $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \ $(shell test -d device && find device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \ $(shell test -d vendor && find vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \ ))
如何在Android系统中添加自己的编译系统,假设厂商名称为DCODE,该厂商有两个基于ANDROID的产品,都放到一个主线上来维护,这两个产品为:apple和orange。OK,下面我们为该厂商添加编译模块:
1、在device目录下创建子目录DCODE,并在该目录下创建文件AndroidProducts.mk,该文件的内容为:
PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/apple/apple.mk \ $(LOCAL_DIR)/orange/orange.mk
那么Android系统是怎么将产品的mk文件load进来的呢,在文件build/core/product_config.mk中有如下定义:
ifneq ($(strip $(TARGET_BUILD_APPS)),) # An unbundled app build needs only the core product makefiles. all_product_configs := $(call get-product-makefiles,\ $(SRC_TARGET_DIR)/product/AndroidProducts.mk) else # Read in all of the product definitions specified by the AndroidProducts.mk # files in the tree. all_product_configs := $(get-all-product-makefiles) endif # Find the product config makefile for the current product. # all_product_configs consists items like: # <product_name>:<path_to_the_product_makefile> # or just <path_to_the_product_makefile> in case the product name is the # same as the base filename of the product config makefile. current_product_makefile := all_product_makefiles := $(foreach f, $(all_product_configs),\ $(eval _cpm_words := $(subst :,$(space),$(f)))\ $(eval _cpm_word1 := $(word 1,$(_cpm_words)))\ $(eval _cpm_word2 := $(word 2,$(_cpm_words)))\ $(if $(_cpm_word2),\ $(eval all_product_makefiles += $(_cpm_word2))\ $(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\ $(eval current_product_makefile += $(_cpm_word2)),),\ $(eval all_product_makefiles += $(f))\ $(if $(filter $(TARGET_PRODUCT),$(basename $(notdir $(f)))),\ $(eval current_product_makefile += $(f)),)))对于这段代码,解释一下几个重要的地方:
1) get-all-product-maefiles方法,该方法定义在build//core/product.mk文件中,该方法的注释为
# # Returns the sorted concatenation of all PRODUCT_MAKEFILES # variables set in all AndroidProducts.mk files. # $(call ) isn't necessary.从注释里面可看出,该方法用来从所有的AndroidProducts.mk文件中获取PRODUCT_MAKEFILES变量。
define get-all-product-makefiles $(call get-product-makefiles,$(_find-android-products-files)) endef不难理解上面的代码,_find-andorid-products-files用来获得所有的AndroidProducts.mk文件,而get-product-maifles则是遍历这些文件,获取PRODUCT_MAKEFILES变量。
2) 在device/DCODE目录下创建两个子目录,分别为apple和orange,如上述AndroidProducts.mk中定义的,我们要在这两个目录下分别创建文件apple.mk和orange.mk。在产品的mk文件里我们要定义该产品的一些属性,比如PRODUCT_PACKAGES, PRODUCT_PACKAGE_RESOURCES等,这时候,apple和orange产品会有很多属性是完全一致的,在实际的系统里我们没必要定义两份重复的配置选项,我们可以定义一个common文件夹,然后apple和orange从这个common配置里派生出来,如下:
$(call inherit-product, device/DCODE/common/common.mk)
3、增加了上述两个mk文件,我们下面需要了解这两个文件中的内容,比如我现在有这样的需求,为apple产品添加一些自定义的功能模块,并将android系统中的一些资源进行替换。首先功能模块可以通过PRODUCT_PACKAGES属性包含进来,而替换系统资源,则可以通过PRODUCT_PACKAGE_OVERLAYS属性来指定。其他一些常用属性入PRODUCT_NAME,PRODUCT_DEVICE等,这里就不一一详述了。
4、在产品目录下添加board相关的配置。增加AndroidBoard.mk文件,该文件定义了如file copy,key layout files,key character-map files,init file,
5、在产品目录下添加verdorsetup.sh文件,增加如下内容:(这个是否需要添加?)
add_lunch_combo full_apple-userdebug
这个文件的作用是为lunch添加选项,这个文件由build/envsetup.sh脚本include进来
其他可参考的文章:
<span style="font-size:14px;">http://blog.csdn.net/yili_xie/article/details/4830541 http://www.360doc.com/content/10/0224/11/155970_16643955.shtml http://www.kandroid.org/online-pdk/guide/build_new_device.html#androidBuildSystemProductDefFiles http://blog.csdn.net/mr_raptor/article/details/7539978</span>