Android编译系统环境初始化过程分析 1
来源:互联网 发布:网络女主播说唱歌曲 编辑:程序博客网 时间:2024/05/28 15:04
Android源代码在编译之前,要先对编译环境进行初始化,其中最主要就是指定编译的类型和目标设备的型号。Android的编译类型主要有eng、userdebug和user三种,而支持的目标设备型号则是不确定的,它们由当前的源码配置情况所决定。为了确定源码支持的所有目标设备型号,Android编译系统在初始化的过程中,需要在特定的目录中加载特定的配置文件。接下来本文就对上述的初始化过程进行详细分析。
对Android编译环境进行初始化很简单,分为两步。第一步是打开一个终端,并且将build/envsetup.sh加载到该终端中:
- $ . ./build/envsetup.sh
- including device/asus/grouper/vendorsetup.sh
- including device/asus/tilapia/vendorsetup.sh
- including device/generic/armv7-a-neon/vendorsetup.sh
- including device/generic/armv7-a/vendorsetup.sh
- including device/generic/mips/vendorsetup.sh
- including device/generic/x86/vendorsetup.sh
- including device/lge/mako/vendorsetup.sh
- including device/samsung/maguro/vendorsetup.sh
- including device/samsung/manta/vendorsetup.sh
- including device/samsung/toroplus/vendorsetup.sh
- including device/samsung/toro/vendorsetup.sh
- including device/ti/panda/vendorsetup.sh
- including sdk/bash_completion/adb.bash
第二步是执行命令lunch,如下所示:
- $ lunch
- You're building on Linux
- Lunch menu... pick a combo:
- 1. full-eng
- 2. full_x86-eng
- 3. vbox_x86-eng
- 4. full_mips-eng
- 5. full_grouper-userdebug
- 6. full_tilapia-userdebug
- 7. mini_armv7a_neon-userdebug
- 8. mini_armv7a-userdebug
- 9. mini_mips-userdebug
- 10. mini_x86-userdebug
- 11. full_mako-userdebug
- 12. full_maguro-userdebug
- 13. full_manta-userdebug
- 14. full_toroplus-userdebug
- 15. full_toro-userdebug
- 16. full_panda-userdebug
- Which would you like? [full-eng]
当我们选定了一个Lunch菜单项序号(1-16)之后,按回车键,就可以完成Android编译环境的初始化过程。例如,我们选择1,可以看到以下输出:
- Which would you like? [full-eng] 1
- ============================================
- PLATFORM_VERSION_CODENAME=REL
- PLATFORM_VERSION=4.2
- TARGET_PRODUCT=full
- TARGET_BUILD_VARIANT=eng
- TARGET_BUILD_TYPE=release
- TARGET_BUILD_APPS=
- TARGET_ARCH=arm
- TARGET_ARCH_VARIANT=armv7-a
- HOST_ARCH=x86
- HOST_OS=linux
- HOST_OS_EXTRA=Linux-3.8.0-31-generic-x86_64-with-Ubuntu-13.04-raring
- HOST_BUILD_TYPE=release
- BUILD_ID=JOP40C
- OUT_DIR=out
- ============================================
通过图1我们就可以直观地看到Android编译环境初始化完成后,我们所获得的东西:
图1 Android编译环境初始化完成之后
图2 自己的系统分析
总体来说,Android编译环境初始化完成之后,获得了以下三样东西:
1. 将vendor和device目录下的vendorsetup.sh文件加载到了当前终端;
2. 新增了lunch、m、mm和mmm等命令;
3. 通过执行lunch命令设置好了TARGET_PRODUCT、TARGET_BUILD_VARIANT、TARGET_BUILD_TYPE和TARGET_BUILD_APPS等环境变量。
接下来我们就主要分析build/envsetup.sh文件的加载过程以及lunch命令的执行过程。
一. 文件build/envsetup.sh的加载过程
文件build/envsetup.sh是一个bash shell脚本,从它里面定义的函数hmm可以知道,它提供了lunch、m、mm和mmm等命令供我们初始化编译环境或者编译Android源码。
函数hmm的实现如下所示:
- function hmm() {
- cat <<EOF
- Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
- - lunch: lunch <product_name>-<build_variant>
- - tapas: tapas [<App1> <App2> ...] [arm|x86|mips] [eng|userdebug|user]
- - croot: Changes directory to the top of the tree.
- - m: Makes from the top of the tree.
- - mm: Builds all of the modules in the current directory.
- - mmm: Builds all of the modules in the supplied directories.
- - cgrep: Greps on all local C/C++ files.
- - jgrep: Greps on all local Java files.
- - resgrep: Greps on all local res/*.xml files.
- - godir: Go to the directory containing a file.
- Look at the source to view more functions. The complete list is:
- EOF
- T=$(gettop)
- local A
- A=""
- for i in `cat $T/build/envsetup.sh | sed -n "/^function /s/function \([a-z_]*\).*/\1/p" | sort`; do
- A="$A $i"
- done
- echo $A
- }
函数hmm主要完成三个工作:
1. 调用另外一个函数gettop获得Android源码的根目录T。
2. 通过cat命令显示一个Here Document,说明$T/build/envsetup.sh文件加载到当前终端后所提供的主要命令。
3. 通过sed命令解析$T/build/envsetup.sh文件,并且获得在里面定义的所有函数的名称,这些函数名称就是$T/build/envsetup.sh文件加载到当前终端后提供的所有命令。
注意,sed命令是一个强大的文本分析工具,它以行为单位为执行文本替换、删除、新增和选取等操作。函数hmm通过执行以下的sed命令来获得在$T/build/envsetup.sh文件定义的函数的名称:
- sed -n "/^function /s/function \([a-z_]*\).*/\1/p"
文件build/envsetup.sh除了定义一堆函数之外,还有一个重要的代码段,如下所示:
- # Execute the contents of any vendorsetup.sh files we can find.
- for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/*/vendorsetup.sh device/*/*/vendorsetup.sh 2> /dev/null`
- do
- echo "including $f"
- . $f
- done
- unset f
这个for循环遍历vendor目录下的一级子目录和二级子目录以及device目录下的二级子目录中的vendorsetup.sh文件,并且通过source命令(.)将它们加载当前终端来。vendor和device相应子目录下的vendorsetup.sh文件的实现很简单,它们主要就是添加相应的设备型号及其编译类型支持到Lunch菜单中去。
例如,device/samsung/maguro目录下的vendorsetup.sh文件的实现如下所示:
- add_lunch_combo full_maguro-userdebug
函数add_lunch_combo定义在build/envsetup.sh文件中,它的实现如下所示:
- function add_lunch_combo()
- {
- local new_combo=$1
- local c
- for c in ${LUNCH_MENU_CHOICES[@]} ; do
- if [ "$new_combo" = "$c" ] ; then
- return
- fi
- done
- LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
- }
数组LUNCH_MENU_CHOICES是定义在文件build/envsetup.sh的一个全局变量,当文件build/envsetup.sh被加载的时候,这个数组会被初始化为化full-eng、full_x86-eng、vbox_x86-eng和full_mips-eng,如下所示:
- # add the default one here
- add_lunch_combo full-eng
- add_lunch_combo full_x86-eng
- add_lunch_combo vbox_x86-eng
- add_lunch_combo full_mips-eng
二. lunch命令的执行过程
lunch命令实际上是定义在文件build/envsetup.sh的一个函数,它的实现如下所示:
- function lunch()
- {
- local answer
- if [ "$1" ] ; then
- answer=$1
- else
- print_lunch_menu
- echo -n "Which would you like? [full-eng] "
- read answer
- fi
- local selection=
- if [ -z "$answer" ]
- then
- selection=full-eng
- elif (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
- elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
- then
- selection=$answer
- fi
- if [ -z "$selection" ]
- then
- echo
- echo "Invalid lunch combo: $answer"
- return 1
- fi
- export TARGET_BUILD_APPS=
- local product=$(echo -n $selection | sed -e "s/-.*$//")
- check_product $product
- if [ $? -ne 0 ]
- then
- echo
- echo "** Don't have a product spec for: '$product'"
- echo "** Do you have the right repo manifest?"
- product=
- fi
- local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
- check_variant $variant
- if [ $? -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 1
- fi
- export TARGET_PRODUCT=$product
- export TARGET_BUILD_VARIANT=$variant
- export TARGET_BUILD_TYPE=release
- echo
- set_stuff_for_environment
- printconfig
- }
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析
- Android编译系统环境初始化过程分析 1
- Android编译系统环境初始化过程分析2
- Android编译系统环境初始化过程分析3
- java学习记录笔记--继承,super,Object类
- java 字节流和字符流的区别 转载
- Android编译系统环境初始化过程分析3
- C++中的智能指针
- Eclipse打开-报错:发现了以元素 ‘d:skin’ 开头的无效内容。此处不应含有子元素(解决方法)
- Android编译系统环境初始化过程分析 1
- 快学Scala习题解答—第三章 数组相关操作
- 这就是web app跟原生app的差别 (太经典了,说到骨子了去)
- 【LeetCode】169_Majority Element
- 求所有最大公共子序列的算法实现(转)
- Java中正则表达式和常用的Math、Random、System、BigInteger、BigDecimal、Date/DateFormat、Calendar类的使用
- UVA 694-The Collatz Sequence
- JAVA运行环境JDK的安装配置
- malloc/free函数