<一>配置过程分析:
jackie@jackie-host:~/svn/vimicro$ . ./build/envsetup.sh
including device/vimicro/vortex/vendorsetup.sh
------------------------------------------------------------------
build/envsetup.sh末尾有:
# Execute the contents of any vendorsetup.sh files we can find.
for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh device/*/*/vendorsetup.sh 2> /dev/null`
do
echo "including $f"
. $f
done
unset f
------------------------------------------------------------------
device/vimicro/vortex/vendorsetup.sh:
add_lunch_combo generic_vortex-userdebug
add_lunch_combo full_vortex-userdebug //添加lunch项目
------------------------------------------------------------------
jackie@jackie-host:~/svn/vimicro$ lunch //配置lunch
You're building on Linux
Lunch menu... pick a combo:
1. generic-eng
2. simulator
3. generic_vortex-userdebug
4. full_vortex-userdebug
Which would you like? [generic-eng] 3
-------------------------------------------------------------------
function lunch()
{
local answer
if [ "$1" ] ; then
answer=$1
else
print_lunch_menu
//打印lunch列表
echo -n "Which would you like? [generic-eng] "
read answer
………………
# 将 product-variant模式种的product分离出来
# 将 product-variant模式种的variant分离出来
# 检查之,看看是否在 (user userdebug eng) 范围内
export TARGET_PRODUCT=$product
export TARGET_BUILD_VARIANT=$variant
export TARGET_SIMULATOR=false
export TARGET_BUILD_TYPE=release
printconfig
//打印一些主要的变量, 调用关系 printconfig()->get_build_var()->build/core/config.mk->build/core/envsetup.mk
}
function print_lunch_menu()
{
local uname=$(uname)
echo
echo "You're building on" $uname
echo
echo "Lunch menu... pick a combo:"
local i=1
local choice
for choice in ${LUNCH_MENU_CHOICES[@]}
do
echo " $i. $choice"
i=$(($i+1))
done
echo
}
-------------------------------------------------------------------
在build/core/envsetup.mk最末尾回显:
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3 //envsetup.mk->version_defaults.mk 定义了平台版本
TARGET_PRODUCT=generic_vortex
TARGET_BUILD_VARIANT=userdebug
TARGET_SIMULATOR=false //envsetup.mk:默认当为false时,TARGET_PRODUCT=generic
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS= //lunch->export TARGET_BUILD_APPS=
TARGET_ARCH=arm .
HOST_ARCH=x86 .
HOST_OS=linux .
HOST_BUILD_TYPE=release .
BUILD_ID=GRH55 //lunch->...->envsetup.mk有定义
============================================
以上在build/buildspec.mk.default 有默认宏定义
<二>Android编译系统分析:
执行:make -j2
顶层目录下的Makefile:
就只有一行:include build/core/main.mk
固实际是从main.mk开始编译的。
《1》初始化参数设置:
在 main.mk 里,简单设置几个主要编译路径的变量后,来到config.mk :
build/core/main.mk->config.mk
->(0)首先设置了源文件的一系列路径,包括头文件、库文件、服务、API 已经编译工具的路径。
例如:SRC_HEADERS := \ …… SRC_TARGET_DIR := $(TOPDIR)build/target 等。
->(1)读取 buildspec.mk 的设置,在这里我们可以加入自己的目标产品信息:
直接编辑build/buildspec.mk.default并移到根目录下; device/vimicro/vortex/buildspec.mk是 一样的。
ifndef TARGET_PRODUCT
TARGET_PRODUCT:=generic_vortex
endif
《2》读取Product设定:
->(2)接着进入envsetup.mk:
->version_defaults.mk 中具体定义平台版本
->product_config.mk:include $(BUILD_SYSTEM)/product.mk
get-all-product-makefiles
product.mk:define get-all-product-makefiles来遍历整个vendor或device 的子目录, 找到vendor或device目录下所有的 AndroidProducts.mk, 不同子目录下的“产品.mk” 中定义了不同的 PRODUCT_NAME, PRODUCT_DEVICE 等信息
---------------------------------------------------------------------
device/vimicro/vortex/AndroidProducts.mk 包含所有具体“产品.mk”文件
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/generic_vortex.mk \
$(LOCAL_DIR)/full_vortex.mk
device/vimicro/vortex/generic_vortex.mk
$(call inherit-product, device/vimicro/vortex/device_vortex.mk)//device_vortex.mk:PRODUCT_COPY_FILES 批量拷贝!
$(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
PRODUCT_NAME := generic_vortex
PRODUCT_DEVICE := vortex //赋值为TARGET_DEVICE
PRODUCT_LOCALES += hdpi
---------------------------------------------------------------------
接着build/core/product_config.mk 会调用resolve-short-product-name 将TARGET_PRODUCT匹配的“产品.mk” 中定义的 PRODUCT_DEVICE 赋值给TARGET_DEVICE。
《3》读取BoardConfig:
BoardConfig.mk是和目标平台主板相关的设定,例如使用了什么装置、driver 等,或是是否需要编译bootloader 、kernel等,都是在 BoardConfig.mk 里设定。同样,每张主板可以有不同设定,存在不同目录下的。
->(3)读取BoardConfig:129 board_config_mk := \……$(SRC_TARGET_DIR)/board/ $(TARGET_DEVICE)/BoardConfig.mk \
device/*/$(TARGET_DEVICE)/BoardConfig.mk \
这里的TARGET_DEVICE 就是 votex ,就是说为了定义我们自己的产品 votex. TARGET_DEVICE 宏也决定了TARGET_DEVICE_DIR, 因为TARGET_DEVICE_DIR 取的是上面提到的 BoardConfig.mk 的路径。即device/vimicro/vortex/BoardConfig.mk
TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
当然Android 的Ob目标输出也是由TARGET_DEVICE决定,见build/core/envsetup.mk。
PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)
《4》读取所有Module:
->(4)读取所以Moudule (definitions.mk )
结束全局变量配置后,回到main.mk ,马上对编译工具及版本进行检查,错误便中断编译。
main.mk 160:include $(BUILD_SYSTEM)/definitions.mk包含文件 definitions.mk 这里面定义了许多变量和函数供main.mk 使用。
编译系统接着做的一个件事情是,遍历所有子目录,找到所有Android.mk文件,并将这些Android.mk文件include 进来
#
# Include all of the makefiles in the system
#
subdir_makefiles := \
$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)
include $(subdir_makefiles)
我们再来看其中的
./build/target/board/Android.mk
对了它引用了
include $(TARGET_DEVICE_DIR)/AndroidBoard.mk
由上面TARGET_DEVICE_DIR的定义,这下又进入了device目录下TARGET_DEVICE指向的目录了(device/vimicro/vortex/目录),这个mk文件中定义了特定Product需要编译和安装app 和 script.
我们在package/apps 下每个模块根目录都能看到 Android.mk ,里面会去定义当前本地模块的 Tag : LOCAL_MODULE_TAGS ,Android 会通过这个 Tag 来决定哪些本地模块会编译进系统,通过 PRODUCT 和 LOCAL_MODULE_TAGS 来决定哪些应用包会编译进系统。 ( 前面说过,你也能通过buildspec.mk 来制定你要编译进系统的模块 )
最后需要编译的模块路径打包到 ALL_DEFAULT_INSTALLED_MODULES:
《5》生成镜像文件images:
->(5)产生相应的rules,生存images:
所有需要配置的准备工作都已完成,下面该决定如何生成image 输出文件了,这一过程实际上在 build/core/Makefile 中处理的。这里定义各种img 的生成方式,包括 ramdisk.img 、 userdata.img 、 system.img 、 update.zip 、 recover.img 等。 当Make include 所有的文件,完成对所有 make 文件的解析以后就会寻找生成 对应目标 的规则,依次生成它的依赖,直到所有满足的模块被编译好,然后使用相应的工具打包成相应的img 。
kernel/Android.mk
kernel/arch/arm/configs/vc0882_vortex_nand_defconfig ->kernel/.config
Makefile的主要流程:
以下主要流程都在build/core/main.mk 里安排。
初始化相关的参数设置(buildspec.mk 、 envsetup.mk 、 config.mk)
检测编译环境和目标环境
决定目标product
读取product 的配置信息及目标平台信息
读取BoardConfig 的配置
读取所有Module 的配置
根据配置产生必要的规则(build/core/Makefile)
生成image