Android编译系统)——命令执行流程
来源:互联网 发布:网络机柜cad图纸 编辑:程序博客网 时间:2024/05/19 17:51
编译Rom的第一步是source build/envsetup.sh,该步骤将envsetup.sh里的函数声明为当前终端可用的命令,并将所有产品添加至变量LUNCH_MENU_CHOICES里。
编译Rom的第二步是让用户选择他想编译的产品,用户可以使用在source build/envsetup.sh后设置的breakfast或者lunch命令进行选择,接下来我们将详细分析这些命令的执行流程以及执行完breakfast命令或者lunch命令后在会话终端设置的变量
1. 命令执行流程
1.1 breakfast执行流程
流程:
- 1) 从github上下载cm支持的产品,并添加至产品列表
- 2) 如果命令参数为空,那么调用lunch函数,让用户选择产品
- 3) 如果命令参数为1个且$target格式为$product-$build_variant,那么调用lunch $target,这样不需要用户选择产品
- 4) 如果命令参数为1个且$target格式为$product,那么将其扩展为带build_variant格式的产品,然后调用lunch cm_$target-userdebug,这样不需要用户选择产品
1234567891011121314151617181920212223242526272829303132
target=$1CM_DEVICES_ONLY="true" #只编译CM支持的设备unset LUNCH_MENU_CHOICESadd_lunch_combo full-eng#vendor/cm/vendorsetup.sh 该脚本会从github上下载cm支持的产品,#并添加至LUNCH_MENU_CHOICES变量 ,该变量表示产品列表for f in `/bin/ls vendor/cm/vendorsetup.sh 2> /dev/null` do echo "including $f" . $f doneunset f #如果没有带任何参数,那么调用lunch函数,让用户选择产品if [ $# -eq 0 ]; then lunchelse#target格式:$product-$build_variant 或者 $product # 示例 cm_i9100-userdebug 或 i9100 echo "z$target" | grep -q "-" #如果用户输入的产品格式是$product-$build_variant 那么直接调用lunch if [ $? -eq 0 ]; then # A buildtype was specified, assume a full device name lunch $target else #如果用户输入的产品格式是$product, #那么扩展该变量为cm_$target-userdebug格式 # This is probably just the CM model name lunch cm_$target-userdebug fifireturn $?
1.2 lunch执行流程
流程:
- 1) 获取用户指定的产品或者让用户选择产品,并提取$product和$variant
- 2) 检查是否支持产品
- 3) 若不支持该产品,从网上下载该产品的相关配置到本地device目录,并再次检查是否支持该产品
- 4) 若支持该产品,下载产品的最新配置到本地device目录
- 5) 若还是不支持,告诉用户不支持并退出
- 6) 设置环境变量export TARGET_PRODUCT,TARGET_BUILD_VARIANT,TARGET_BUILD_TYPE
- 7) 建立$(OUT_DIR)/target/common目录
- 8) 设置PROMPT_COMMAND变量,java_home,PATH目录,set_sequence_number
- 9) 打印选择产品后对应的一些编译配置变量
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
local answerif [ "$1" ] ; then answer=$1else #若调用者没有指定产品,那么打印产品列表,让用户选择 print_lunch_menu echo -n "Which would you like? [full-eng] " read answerfilocal selection=if [ -z "$answer" ] #默认产品为full-engthen selection=full-engelif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")#用户如输入的是数字then if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ] then selection=${LUNCH_MENU_CHOICES[$(($answer-1))]} fi#选择的产品为$product-$build_variant格式 elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")then selection=$answerfi if [ -z "$selection" ]#selection格式为$product-$build_variantthen echo echo "Invalid lunch combo: $answer" return 1fi export TARGET_BUILD_APPS= #提取product变量 product示例cm_i9100local product=$(echo -n $selection | sed -e "s/-.*$//")check_product $product #检查产品是否支持if [ $? -ne 0 ]#若产品不支持then #if we can't find a product, try to grab it off the CM github T=$(gettop) pushd $T > /dev/null #下载prouct的配置 放在device/$vendor/$product目录 build/tools/roomservice.py $product popd > /dev/null check_product $product #再次检查产品是否支持else #获取最新配置 更新device/$vendor/$product build/tools/roomservice.py $product truefiif [ $? -ne 0 ]then echo echo "** Don't have a product spec for: '$product'" echo "** Do you have the right repo manifest?" product=fi#从$product-$build_variant里提取$variantlocal variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")check_variant $variantif [ $? -ne 0 ]then echo echo "** Invalid variant: '$variant'" echo "** Must be one of ${VARIANT_CHOICES[@]}" variant=fi if [ -z "$product" -o -z "$variant" ]then echo return 1fi export TARGET_PRODUCT=$productexport TARGET_BUILD_VARIANT=$variantexport TARGET_BUILD_TYPE=release fixup_common_out_dir #建立$(OUT_DIR)/target/common目录 #设置PROMPT_COMMAND变量,java_home,PATH目录,set_sequence_numberset_stuff_for_environment# 打印选择产品后的重要环境变量printconfig
1.3 check_product执行流程
流程:
- 1) export CM_BUILD CM_BUILD示例:若$1是cm_i9100,则CM_BUILD是i9100
- 2) 调用get_build_var TARGET_DEVICE
123456789101112131415161718
T=$(gettop)if [ ! "$T" ]; then echo "Couldn't locate the top of the tree. Try setting TOP." >&2 returnfi if (echo -n $1 | grep -q -e "^cm_") ; then CM_BUILD=$(echo -n $1 | sed -e 's/^cm_//g')else CM_BUILD=fiexport CM_BUILDCALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \ TARGET_PRODUCT=$1 \ TARGET_BUILD_VARIANT= \ TARGET_BUILD_TYPE= \ TARGET_BUILD_APPS= \ get_build_var TARGET_DEVICE > /dev/null
1.4 get_build_var执行流程
调用流程:lunch->check_product->get_build_var TARGET_DEVICE
此时的环境变量有
1)TARGET_PRODUCT:cm_i9100
2)CALLED_FROM_SETUP:true
3)BUILD_SYSTEM:build/core
4)export CM_BUILD=i9100
最终调用build/core/config.mk来完成检测是否支持产品$TARGET_PRODUCT
12345678
T=$(gettop)if [ ! "$T" ]; then echo "Couldn't locate the top of the tree. Try setting TOP." >&2 returnfiCALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \ #$1的值可能为TARGET_DEVICE make --no-print-directory -C "$T" -f build/core/config.mk dumpvar-$1
选择好产品后,可用get_build_var查看产品对应的编译变量,它依赖于以下环境变量
export TARGET_PRODUCT=cm_i9100
export TARGET_BUILD_VARIANT=userdebug
export TARGET_BUILD_TYPE=release
export CM_BUILD=i9100
因此makefile里定义的变量并未添加至环境变量,每次调用get_build_var时,其实是调用config.mk依赖的dumpvar.mk实时计算出编译变量的值
比如说LEX变量 HOST_ARCH变量
1.5 printconfig执行流程
123456
T=$(gettop)if [ ! "$T" ]; then echo "Couldn't locate the top of the tree. Try setting TOP." >&2 returnfiget_build_var report_config
最终调用build/core/dumpvar.mk来完成变量的打印
示例:
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.2.2
CM_VERSION=10.1-20130822-UNOFFICIAL-i9100
TARGET_PRODUCT=cm_i9100
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
HOST_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-2.6.32-33-generic-x86_64-with-Ubuntu-10.04-lucid
HOST_BUILD_TYPE=release
BUILD_ID=JDQ39E
OUT_DIR=/home/android/tmp/android_out/CyanogenMod
1.5 mm执行流程
1234567891011121314151617181920212223242526
local MM_MAKE=makelocal ARG=for ARG in $@ ; do #如果参数中有mka,那么利用mka进行编译 if [ "$ARG" = mka ]; then MM_MAKE=mka fidone#如果处在根目录 利用Android根目录的makefile编译选中目标if [ -f build/core/envsetup.mk -a -f Makefile ]; then $MM_MAKE $@ else T=$(gettop) #找到最近的makfile,即当前目录所在工程的makefile local M=$(findmakefile) # Remove the path to top as the makefilepath needs to be relative local M=`echo $M|sed 's:'$T'/::'` if [ ! "$T" ]; then echo "Couldn't locate the top of the tree. Try setting TOP." elif [ ! "$M" ]; then echo "Couldn't locate a makefile from the current directory." else #使用ONE_SHOT_MAKEFILE关键字确定工程所用的makefile, #并利用Android根目录的makefile进行编译 ONE_SHOT_MAKEFILE=$M $MM_MAKE -C $T all_modules $@ fifi
1.5 mmm执行流程
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
local MMM_MAKE=makeT=$(gettop)if [ "$T" ]; then local MAKEFILE= local MODULES= local ARGS= local DIR TO_CHOP #提取编译选项(用-指定编译参数) local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/') #提取编译目录 local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/') for DIR in $DIRS ; do MODULES=`echo $DIR | sed -n -e 's/.*:\(.*$\)/\1/p' | sed 's/,/ /'` #提取模块 dir格式:dirname:modulename if [ "$MODULES" = "" ]; then MODULES=all_modules fi DIR=`echo $DIR | sed -e 's/:.*//' -e 's:/$::'` #如果指定目录有Android.mk,计算出MAKEFILE变量的值 if [ -f $DIR/Android.mk ]; then TO_CHOP=`(cd -P -- $T && pwd -P) | wc -c | tr -d ' '` TO_CHOP=`expr $TO_CHOP + 1` START=`PWD= /bin/pwd` MFILE=`echo $START | cut -c${TO_CHOP}-` if [ "$MFILE" = "" ] ; then MFILE=$DIR/Android.mk else MFILE=$MFILE/$DIR/Android.mk fi MAKEFILE="$MAKEFILE $MFILE" else #特殊目标 其实是做编译参数 if [ "$DIR" = snod ]; then ARGS="$ARGS snod" elif [ "$DIR" = showcommands ]; then ARGS="$ARGS showcommands" elif [ "$DIR" = dist ]; then ARGS="$ARGS dist" elif [ "$DIR" = incrementaljavac ]; then ARGS="$ARGS incrementaljavac" elif [ "$DIR" = mka ]; then MMM_MAKE=mka else echo "No Android.mk in $DIR." return 1 fi fi done #使用ONE_SHOT_MAKEFILE关键字确定工程所用的makefile, #并利用Android根目录的makefile进行编译 ONE_SHOT_MAKEFILE="$MAKEFILE" $MMM_MAKE -C $T $DASH_ARGS $MODULES $ARGSelse echo "Couldn't locate the top of the tree. Try setting TOP."fi
2. breakfast或者lunch命令执行后在会话终端定义的变量
在执行完breakfast或者lunch命令后,会在当前终端设置许多变量,这些变量有些只能在当前shell里使用,有些能继续在子shell里使用(用sh执行某个shell脚本即在子shell里)。根据变量定义位置,将变量分为3类:
- 1) 函数:是在函数定义的变量,但并未用export显示指出,在子shell里不可用,当前shell可用
- 2) export:导出的环境变量,子Shell也可用
- 3) 文件:文件里定义的变量
函数
根目录
TARGET_BUILD_TYPE
export
release或者debug
TARGET_PRODUCT
export
示例:cm_find5
TARGET_BUILD_VARIANT
export
可能的值为user,userdebug,eng
TARGET_BUILD_APPS
export
需要编译的App集合
CM_BUILD
export
示例find5
VARIANT_CHOICES
文件
(user userdebug eng)
LUNCH_MENU_CHOICES
函数
产品列表
prebuiltdir
函数
$(getprebuilt)
gccprebuiltdir
函数
$(get_abs_build_var ANDROID_GCC_PREBUILTS)
ANDROID_EABI_TOOLCHAIN
export
工具链所在目录:以下选项之一
$ gccprebuiltdir /x86/i686-linux-android-4.6/bin
$ gccprebuiltdir /arm/arm-linux-androideabi-4.6/bin
$ gccprebuiltdir /mips/mipsel-linux-android-4.6/bin
ANDROID_TOOLCHAIN
export
$ANDROID_EABI_TOOLCHAIN
ANDROID_QTOOLS
export
$T/development/emulator/qtools
ANDROID_DEV_SCRIPTS
export
$T/development/scripts
ANDROID_BUILD_PATHS
export
$(get_build_var ANDROID_BUILD_PATHS):
$ANDROID_QTOOLS:
$ANDROID_TOOLCHAIN:
$ARM_EABI_TOOLCHAIN_PATH:
$CODE_REVIEWS:$ANDROID_DEV_SCRIPTS:
ARM_EABI_TOOLCHAIN
export
$gccprebuiltdir/ arm/arm-eabi-4.6/bin
ARM_EABI_TOOLCHAIN_PATH
函数
$gccprebuiltdir/ arm/arm-eabi-4.6/bin
toolchaindir
函数
以下三个选项之一
x86/i686-linux-android-4.6/bin
arm/arm-linux-androideabi-4.6/bin
mips/mipsel-linux-android-4.6/bin
ANDROID_JAVA_TOOLCHAIN
export
$JAVA_HOME/bin
ANDROID_PRE_BUILD_PATHS
export
$ANDROID_JAVA_TOOLCHAIN
ANDROID_PRODUCT_OUT
export
$(get_abs_build_var PRODUCT_OUT)
OUT
export
$ANDROID_PRODUCT_OUT
ANDROID_HOST_OUT
export
$(get_abs_build_var HOST_OUT)
OPROFILE_EVENTS_DIR
export
$T/external/oprofile/events
BUILD_ENV_SEQUENCE_NUMBER
export
export BUILD_ENV_SEQUENCE_NUMBER=10
PROMPT_COMMAND
export
命令提示符
CM_DEVICES_ONLY
函数
true 表示只支持CM的设备,如果使用breakfast命令会将改变量设置为true
MODVERSION
函数
$(get_build_var CM_VERSION)
ZIPFILE
函数
cm-$MODVERSION.zip
ZIPPATH
函数
$OUT/$ZIPFILE
TOPFILE
函数
build/core/envsetup.mk
用户下一步将使用mka进行编译,会利用这前两步设置的变量和函数命令,虽然breakfast命令和lunch命令有利用到一些makefile检查选择的产品是否符合要求,但是makefile里的变量都引入到当前shell,仅仅用于检查产品是否符合要求而已。
我们现在了解到breakfast命令会从网上下载产品列表,而lunch命令会下载产品的最新配置,所以我们在使用breakfast命令或者lunch命令时,会觉得时间比较长,如果是本地产品,你可以注释那些检查的代码,这样会很快
转自:http://www.cloudchou.com/android/post-261.html
- Android编译系统详解(二)——命令执行流程
- Android编译系统)——命令执行流程
- Android编译系统详解(二)——命令执行流程
- Android编译系统详解(二)——命令执行流程
- Android编译系统详解(三)——编译流程详解
- Android编译系统——编译流程详解
- Android编译系统详解(三)——编译流程详解
- Android编译系统详解(三)——编译流程详解
- Android编译系统详解(三)——编译流程详解
- android系统编译流程
- Android编译系统流程
- Android 系统编译流程
- Android编译系统的流程
- android 编译系统流程简介
- Android系统的编译命令
- 命令行进入android系统里执行linux命令的方法——busybox
- Android学习笔记之编译系统(五)apk编译流程
- Android学习札记之编译系统(五)apk编译流程
- js 直接触发事件
- 远远相望也是一种美 ?
- Traits 编程技法+模板偏特化+template参数推导+内嵌型别编程技巧
- 产品经理学习笔记(3)-腾讯亿级用户的团队经验:产品经理如何协同工作
- Linux内核移植和根文件系统制作(详细步骤精讲)
- Android编译系统)——命令执行流程
- boost.smart_ptr-智能指针scoped_ptr
- 开始懂了
- [黑马程序员][C语言]static和extern关键字
- 面向对象的三大特征
- Mapped Statements collection does not contain value for Addressbook.pageSelect
- Python内建序列之字符串
- eclipse python插件地址选择以及安装
- DE0 Nano ADC 使用