Android系统编译环境变量的设置
2014-08-06 09:46
507 查看
编译之前我们一般都怎么做?
我们在编译android之前,通常会输入一些命令,比如:. ./bulid/envsetup.sh
...
lunch
...
make
...
这里的envsetup.sh就是设置android的编译环境,初始化各种变量,比如设备类型什么的,下面是我在我的板子上执行上述命令的结果:
mic@micpc:~/work/android4.0.4$ . ./build/envsetup.sh including device/moto/stingray/vendorsetup.sh including device/moto/wingray/vendorsetup.sh including device/samsung/smdk4x12/vendorsetup.sh including sdk/bash_completion/adb.bash ##这里看到,加载envsetup.sh后会加载device目录下其他的一些vendorsetup.sh过来。 ##另外adb.bash是什么?我也不清楚,看看老罗怎么说。 ##“在sdk/bash_completion目录下的adb.bash文件也会加载到当前终端来,它是用来实现adb命令的bash completion功能的。 ##也就是说,加载了该文件之后,我们在运行adb相关的命令的时候,通过按tab键就可以帮助我们自动完成命令的输入” #然后我们又执行了lunch命令,这个命令是在envsetup.sh中实现的。 mic@micpc:~/work/android4.0.4$ lunch You're building on Linux Lunch menu... pick a combo: 1. full-eng 2. full_x86-eng 3. vbox_x86-eng 4. full_stingray-userdebug 5. full_wingray-userdebug 6. full_smdk4x12-userdebug 7. full_smdk4x12-eng Which would you like? [full-eng] 6 ##可以看到,终端输出了一个菜单,并让我们选择一个选项,我选择的是6,然后就会打印出如下信息,这些变量就是我们编译前要设置好到系统变量。通过这些变量, ##我们就配置好了android的编译环境。 ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=4.0.4 TARGET_PRODUCT=full_smdk4x12 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_BUILD_TYPE=release BUILD_ID=IMM76D ============================================
envsetup.sh干啥用?
/bulid/envsetup.sh这个脚本中实现了很多功能函数,上面的lunch,还有m,mm,mmm等。加载vendorsetup.sh,添加lunch
在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
它的作用是遍历 vendor目录和device目录下的vendorsetup.sh,
1.通过echo把这个vnedorsetup.sh打印出来,就是我们前面看到的"6. full_smdk4x12-userdebug"这种东西
2.通过.(source)加载这个vendorsetup.sh
其实vendorsetup.sh的作用就是添加相应的设备型号及其编译类型支持到Lunch菜单中去。比如:
work/android4.0.4/device/samsung/smdk4x12/vendrosetup.sh内容如下
add_lunch_combo full_smdk4x12-userdebug add_lunch_combo full_smdk4x12-eng
我们看到它通过add_lunch_combo来添加设备型号等信息的,add_lunch_combo在哪呢?答案还是在envsetup.sh中。
# Clear this variable. It will be built up again when the vendorsetup.sh # files are included at the end of this file. unset LUNCH_MENU_CHOICES 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) } # add the default one here add_lunch_combo full-eng ##看这里,不就是lunch的最开始的打印信息吗,原来它在这里 add_lunch_combo full_x86-eng ##这里其实就是初始化LUNCH_MENU_CHOICES数组,里面默认有 add_lunch_combo vbox_x86-eng ##三个选项,full-eng full_x86-eng vbox_x86-eng
我们从这个函数的调用来了解它的工作过程。比如
add_lunch_combo full_smdk4x12-userdebug可见add_lunch_combo是这个函数的名字,full_smdk4x12-userdebug是这个函数的第一个参数。
在函数中,把第一个参数的值给了一个新的变量new_combo。然后通过遍历LUNCH_MENU_CHOICES这个数组,查找这个数组中是否已经有相同的选项了。
只有在没有添加过的情况下才会添加一个新的选项到LUNCH_MENU_CHOICES数组中。
${LUNCH_MENU_CHOICES[@]}表示数组LUNCH_MENU_CHOICES的所有元素。
lunch的实现解析
当我们输入lunch后,等待我们输入一个编号,比如我输入的是6,这个过程是什么样的呢?我们来看看lunch的实现。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 }
1.lunch执行的时候,可以带参数执行,也可以先不带参数,比如
我们可以先lunch,回车,这时候会让你输入一个参数,我们再输入一个6或者其他;
我们也可以直接输入lunch 6,这样也是一样的。所以,lunch开始的时候判断执行lunch时带没带参数,如果带了参数,那么把参数赋给变量answer
2.对answer进行检查,判断answer是否为空,如果为空默认selection为full-eng;如果不为空,有三种情况:
(1)数字:输入数字就像我们输入"6",要保证我们输入的数字不大于lunch菜单项的总数,根据这个数字去LUNCH_MENU_CHOICES这个数组中去获取相应的selection,即获取相应的设备型号,编译类型等信息。
mic@micpc:~/work/android4.0.4$ lunch 6
(2)非数字:就像如下这种情况,需要正确输入格式<product>-<variant>。其中<product>表示设备型号,而<variant>表示编译类型。
mic@micpc:~/work/android4.0.4$ lunch full_smdk4x12-userdebug
(3)其他情况:这种情况就是非法情况了,那样selection的值就为空,那么下面lunch就不会向下执行了。
3.解析selection,我们上面就是为了获取selection。通过sed命令分别把<product>和<variant>解析出来存到变量product和变量variant中。得到变量后就要对变量进行检查,看它是否合法,所以会调用check_product $product 和check_variant $variant ,不合发会打印出出错信息。
4.获得合法的product和variant之后,
export TARGET_PRODUCT=$product export TARGET_BUILD_VARIANT=$variant export TARGET_BUILD_TYPE=release把变量付给TARGET_PRODUCT,TARGET_BUILD_VARINAT等变量,并通过export导出供其他人使用。
5.调用set_stuff_for_environment函数来配置环境,例如设置Java SDK路径和交叉编译工具路径等。(老罗)
6.调用printconfig函数来把设置好的配置打印出来,就是我们看到的
============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=4.0.4 TARGET_PRODUCT=full_smdk4x12 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_BUILD_TYPE=release BUILD_ID=IMM76D ============================================
check_product
# check to see if the supplied product is one we can build function check_product() { 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 \ TARGET_PRODUCT=$1 \ TARGET_BUILD_VARIANT= \ TARGET_BUILD_TYPE= \ TARGET_BUILD_APPS= \ get_build_var TARGET_DEVICE > /dev/null # hide successful answers, but allow the errors to show }
gettop是用来返回android源码根目录。老罗说“函数gettop用来返回Android源代码工程的根目录。函数check_product需要在Android源代码工程根目录或者子目录下调用。否则的话,函数check_product就出错返回。”。
CALLED_FROM_SETUP ##如果这个值为true,说明接下来的make使用来初始化android编译环境 <pre name="code" class="plain">BUILD_SYSTEM ##android编译系统核心目录
TARGET_PRODUCT ##要检查的产品名称,也就是我们调用参数是传递的第一个参数$1
使用get_build_var来检查TARGET_PRODUCT指定的产品是否合法。为啥参数是TARGET_DEVICE???
# 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 }可以看到,指定目录为android源码根目录调用make,执行build/core/config.mk,目标是dumpvar-TARGET_DEVICE。
bulid/core/config.mk内容多,截取一部分。
# --------------------------------------------------------------- # Define most of the global variables. These are the ones that # are specific to the user's build configuration. include $(BUILD_SYSTEM)/envsetup.mk # 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 \ device/*/$(TARGET_DEVICE)/BoardConfig.mk \ vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \ )) ifeq ($(board_config_mk),) $(error No config file found for TARGET_DEVICE $(TARGET_DEVICE)) endif ifneq ($(words $(board_config_mk)),1) $(error Multiple board config files for TARGET_DEVICE $(TARGET_DEVICE): $(board_config_mk)) endif include $(board_config_mk) TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk))) board_config_mk := ..... ..... include $(BUILD_SYSTEM)/dumpvar.mk
主要功能是加载3个文件:
1.include $(BUILD_SYSTEM)/envsetup.mk
2.include $(board_config_mk)
3.include $(BUILD_SYSTEM)/dumpvar.mk
老罗说“
上述代码主要就是将envsetup.mk、BoardConfig,mk和dumpvar.mk三个Makefile片段文件加载进来。其中,envsetup.mk文件位于$(BUILD_SYSTEM)目录中,也就是build/core目录中,BoardConfig.mk文件的位置主要就是由环境变量TARGET_DEVICE来确定,它是用来描述目标产品的硬件模块信息的,例如CPU体系结构。环境变量TARGET_DEVICE用来描述目标设备,它的值是在envsetup.mk文件加载的过程中确定的。一旦目标设备确定后,就可以在$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)、device/*/$(TARGET_DEVICE)和vendor/*/$(TARGET_DEVICE)目录中找到对应的BoradConfig.mk文件。注意,变量SRC_TARGET_DIR的值等于build/target。最后,dumpvar.mk文件也是位于build/core目录中,它用来打印已经配置好的编译环境信息。”
中间有些过程我还没有理解,但是最终会调用到device/samsung/smdk4x12/full_smdk4x12.mk
# Discard inherited values and use our own instead. PRODUCT_NAME := full_smdk4x12 PRODUCT_DEVICE := smdk4x12 PRODUCT_MANUFACTURER := S.LSI Division, TOPEET Electronics Co., Ltd. PRODUCT_BRAND := Android PRODUCT_MODEL := iTOP-4412这里指定了PRODUCT_DEVICE :=smdk4x12,所以就会调用到device/samsung/smdk4x12/BoardConfig.mk
它描述了产品的Boot Loader、Kernel、CPU体系结构、CPU ABI和Opengl加速等信息。
VARIANT_CHOICES=(user userdebug eng) # check to see if the supplied variant is valid function check_variant() { for v in ${VARIANT_CHOICES[@]} do if [ "$v" = "$1" ] then return 0 fi done return 1 }
这个函数表示在VARIANT_CHOICES这个数组中,分别用数组中的元素user,userdebug,eng来和参数比较。
这三个值user、userdebug和eng。其中,user表示发布版本,userdebug表示带调试信息的发布版本,而eng表标工程机版本。
相关文章推荐
- 命令行对编译环境设置及系统环境变量一览
- Android 源码下载 编译 环境变量设置
- adb shell中设置android系统内部环境变量!
- Android中如何获得一些系统设置和环境变量?
- Android 源码下载 编译 环境变量设置
- Java 和 Android系统环境变量设置
- Ubuntu14.04 安装Android 编译环境之 环境变量设置1---学习笔记
- vs2005 .net 2.0 csc.exe的编译环境变量设置(配置)
- Java 中系统环境变量的设置和获取
- Ubuntu上搭建android BSP的开发编译环境 && 设置定时编译任务 && ubuntu从10.04升级到12.04后编译出错
- Ubuntu设置环境变量错误导致系统无法登录解决方法
- Linux交叉编译工具环境变量设置方法
- 查看系统环境变量(sysgen_xxx?)设置情况
- Windos下用setx.exe命令行模式下永久设置系统环境变量
- Windos下用setx.exe命令行模式下永久设置系统环境变量
- Ubuntu设置环境变量错误导致系统无法登录解决方法 [转]
- Windos下用setx.exe命令行模式下永久设置系统环境变量
- Linux进入系统时自动设置环境变量的方法
- 解析交叉编译工具环境变量的设置
- VC2005工程常用设置&系统环境变量设置(if necessary)