关闭

Android 编译系统(二):envsetup.sh学习

2595人阅读 评论(0) 收藏 举报
一、编译指令
     cd $(Android_dir)     // 进入android源码的根目录
     . build/envsetup.sh  // 特别注意,点号后面跟着一个空格,然后才是 build
     chooseproduct dkb
     choosevariant eng
     export ANDROID_PREBUILT_MODULES=/home/alex/share/Marvell/m4sp3/kernel/out/modules       // 特别注意,这个目录各人机器上可能不同;另外,个别项目如果没有内核模块的话,请输入:export ANDROID_PREBUILT_MODULES=no_kernel_modules
     make -j4
     cd kernel
     make telephony
二、解释如上几句的真实含义
     这里先解释如上几句的含义,后续第三节会详细讨论 envsetup.sh 文件。
     . build/envsetup.sh  // 该文件定义了 chooseproduct 等函数,并使其驻留在环境变量中
     chooseproduct dkb     // 指明配置文件从如下两个地方之一读取:
build/target/board/*/BoardConfig.mk 或
 vendor/*/*/
BoardConfig.mk。在Marvell TD平台中则是从 vendor\marvell\dkb\
BoardConfig.mk 
读取
     choosevariant eng
三、解析 envsetup.sh
(一)目的
     在编译Android源代码之前必须在Android源代码的顶层目录执行 . /build/envsetup.sh 目的是为了使用脚本 envsetup.sh 里面定义了一些函数:
function help()
function get_abs_build_var()
function get_build_var()
function check_product()
function check_variant()
function setpaths()
function printconfig()
function set_stuff_for_environment()
function set_sequence_number()
function settitle()
function choosetype()
function chooseproduct()
function choosevariant()
function tapas()
function choosecombo()
function print_lunch_menu()
function lunch()
function gettop
function m()
function findmakefile()
function mm()
function mmm()
function croot()
function pid()
function gdbclient()
function jgrep()
function cgrep()
function resgrep()
function getprebuilt
function tracedmdump()
function runhat()
function getbugreports()
function startviewserver()
function stopviewserver()
function isviewserverstarted()
function smoketest()
function runtest()
function runtest_py()
function godir ()
(二)命令详解
help()
          显示帮助,列出提供的函数
choosecombo()
function choosecombo()
{
choosesim $1     // choosesim以及后续的choosetype都是本文件定义的一个函数
echo
echo
choosetype $2
echo
echo
chooseproduct $3
echo
echo
choosevariant $4
echo
set_stuff_for_environment
printconfig
}
执行该函数后会依次进行如下选择:
Build for the simulator or the device?
1. Device
2. Simulator
Which would you like? [1]
Build type c
Build type choices are:
1. release
2. debug
Which would you like? [1]
Product choices are:
1. emulator
2. generic
3. sim
4. littleton
You can also type the name of a product if you know it.
Which would you like? [littleton]
Variant choices are:
1. user
2. userdebug
3. eng
Which would you like? [eng] user
默认选择以后会出现:
TARGET_PRODUCT=littleton
TARGET_BUILD_VARIANT=user
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=
chooseproduct()
配置环境变量TARGET_PRODUCT。会提示用户选择release或debug。然后调用set_stuff_for_environment设置。
choices=(`/bin/ls build/target/board/*/BoardConfig.mk vendor/*/*/BoardConfig.mk 2> /dev/null`)
读取 build/target/board/* 目录下的板配置文件:BoardConfig.mk
读取 vendor/*/*/目录下的板配置文件:BoardConfig.mk
choices 的值为:
build/target/board/emulator/BoardConfig.mk
build/target/board/generic/BoardConfig.mk
build/target/board/sim/BoardConfig.mk
vendor/marvell/littleton/BoardConfig.mk
经过:
for choice in ${choices[@]}
do
# The product name is the name of the directory containing
# the makefile we found, above.
prodlist=(${prodlist[@]} `dirname ${choice} | xargs basename`)
done
的处理,prodlist的值为:
emulator generic sim littleton
所以选择菜单为:
Product choices are:
1. emulator
2. generic
3. sim
4. littleton
如果选择 4,那么 TARGET_PRODUCT 被赋值为: littleton。
board_config_mk := \
$(strip $(wildcard \
$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \
))

choosevariant

          配置环境变量TARGET_BUILD_VARIANT。会提示用户选择release或debug。

lunch()

lunch函数提供了一个菜单,让开发人员选择需要编译的目标产品(target product)和变体(variant),并做一些检查,设置环境变量,并打印出主要的环境变量。
直接运行lunch(必须先运行 build/envsetup.sh,让lunch函数驻留到环境变量中)
alex@alex-Vostra3400:~/share/Marvell/m4sp3$ lunch
You're building on Linux
Lunch menu... pick a combo:
     1. generic-eng
     2. simulator
Which would you like? [generic-eng] dkb-eng
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3.7
TARGET_PRODUCT=dkb
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=GWK74
============================================

用户也可以直接输入参数,不使用菜单
alex@alex-Vostra3400:~/share/Marvell/m4sp3$  lunch dkb-eng

下面是lunch函数源代码,用蓝色添加了一下注释,便于阅读:
function lunch()
{
    local answer
    if [ "$1" ] ; then       # lunch
        answer=$1
    else       # lunch后面不带参数,则打印出所有的target product和variant菜单提供用户选择
     print_lunch_menu  
        echo -n "Which would you like? [generic-eng] "

       read answer
    fi
    local selection=
    if [ -z "$answer" ]     # 如果用户在菜单中没有选择,直接回车,则为系统缺省的generic-eng
    then
          selection=generic-eng
    elif [ "$answer" = "simulator" ]     # 如果是模拟器
    then
        selection=simulator
    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")     # 如果answer是选择菜单的数字,则获取该数字对应的字符串
    then
        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
        then
            selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}
        fi
    elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")     # 如果answer字符串匹配*-*模式(*的开头不能为-)
    then
        selection=$answer
    fi
    if [ -z "$selection" ]
    then
        echo
        echo "Invalid lunch combo: $answer"
        return 1
    fi
    # special case the simulator
    if [ "$selection" = "simulator" ]
    then
        #
模拟器模式
        export TARGET_PRODUCT=sim
        export TARGET_BUILD_VARIANT=eng
        export TARGET_SIMULATOR=true
        export TARGET_BUILD_TYPE=debug
    else
        #
将 product-variant模式种的product分离出来
        local product=$(echo -n $selection | sed -e "s/-.*$//")
        #
检查之,调用关系 check_product()->get_build_var()->build/core/config.mk比较罗嗦,不展开了
        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
        #
将 product-variant模式种的variant分离出来
        local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
        #
检查之,看看是否在 (user userdebug eng) 范围内
        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_SIMULATOR=false
        export TARGET_BUILD_TYPE=release
    fi # !simulator
    echo
    #
设置到环境变量,比较多,不再一一列出,最 简单的方法 set >env.txt 可获得
    set_stuff_for_environment
    #
打印一些主要的变量, 调用关系 printconfig()->get_build_var()->build/core/config.mk->build/core/envsetup.mk 比较罗嗦,不展开了
    printconfig
}

get_abs_build_var  

列出make脚本中某变量的值,前缀是当前路径。ref dumpvar.mk
使用方法:
       get_abs_build_var VAR_NAME
VAR_NAME是需要显示的make脚本中的变量。
例如:
     alex@alex-Vostra3400:~/share/Marvell/m4sp3$ get_abs_build_var TARGET_PRODUCT
返回
     /home/alex/share/Marvell/m4sp3/dkb

get_build_var    


列出make脚本中某变量的值。ref dumpvar.mk
与上一个命令的区别是没有前缀。
Usage:
       get_build_var VAR_NAME
VAR_NAME是需要显示的make脚本中的变量。
Return:
       <VAR_NAME Value>
例如:
     alex@alex-Vostra3400:~/share/Marvell/m4sp3$ get_build_var TARGET_PRODUCT
返回
     dkb
check_product
检查指定的TARGET_PRODUCT是否允许,默认的有sim和generic。如果不允许,则输出错误信息,允许则无回显。
Usage:
       check_product <YourTargetProduct>
Example:
       check_product generic
check_variant

检查variant是否支持,支持则返回0,不支持则返回1。允许的variant列表定义在envsetup.sh中的 VARIANT_CHOICES中,默认是user,userdebug,eng。定制android时,可以在VARIANT_CHOICES中添加 vairant。
Usage:
       check_variant <YourVariant>
Example:
       check_variant eng
setpaths

奇次执行时,将ANDROID_BUILD_PATHS路径加到PATH中。偶次执行时,将ANDROID_BUILD_PATHS路径从 PATH中去除。ANDROID_BUILD_PATHS包括android编译中要使用到的路径,例如 ANDROID_EABI_TOOLCHAIN,ANDROID_TOOLCHAIN,ANDROID_QTOOLS,ANDROID_JAVA_TOOLCHAIN,ANDROID_PRODUCT_OUT 等等。
 
Usage:
       setpaths
printconfig

输出类似如下形势的配置信息。
============================================
PLATFORM_VERSION_CODENAME=AOSP
PLATFORM_VERSION=AOSP
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=OPENMASTER
============================================
set_stuff_for_environment

依次调用settitle, set_java_home,setpaths,set_sequence_number。设置android编译需要的环境变量。
set_sequence_number

输出环境变量BUILD_ENV_SEQUENCE_NUMBER。
settitle

设置shell的prompt提示,PROMPT_COMMAND中加入TARGET_PRODUCT,TARGET_BUILD_VARIANT,和TARGET_BUILD_APPS等信息提示。
choosesim

配置环境变量TARGET_SIMULATOR。linux下会提示用户选择device或simulator。然后调用set_stuff_for_environment设置。
choosetype

配置环境变量TARGET_BUILD_TYPE_SIMULATOR。会提示用户选择release或debug。然后调用set_stuff_for_environment设置。
add_lunch_combo
向环境变量LUNCH_MENU_CHOICES标识的列表中添加项。envsetup.sh中默认添加了full-eng,full_x86-eng,和simulator。
print_lunch_menu

列出LUNCH_MENU_CHOICES中的所有选项。
tapas
用户给定variant和一个或多个app name,就是LOCAL_PACKAGE_NAME的名字。tapas设定
export TARGET_PRODUCT=generic
    export TARGET_BUILD_VARIANT=$variant
    export TARGET_SIMULATOR=false
    export TARGET_BUILD_TYPE=release
    export TARGET_BUILD_APPS=$apps
Usage:
       tapas <YourVariant>?  <YourAppName>*
?代表可选,*代表0个,1个或多个。YourVariant 和YourAppName的次序可颠倒。
 
Example:
       tapas user Calculator Calender
gettop

返回当前android代码树的顶层路径。前提是当前路径位于android代码树中。
m

等价于在当前android代码树的顶层路径下执行make命令。
findmakefile

查找当前或最接近自己的祖辈路径上的Android.mk,返回Android.mk的路径,假设当前路径处于android代码树中。
mm

如果当前路径是代码树顶层,则mm相当于make。如果是深层,测mm相当于

ONE_SHOT_MAKEFILE=$M make -C $T files $@


$M是findmakefile发现的Android.mk,$T是代码树顶层路径,files是main.mk中定义的phony goal,就是完成$M对应目录范围内,所有android需编译的modules以及辅助说明txt文件。
mmm

给定package的路径,则mm会make相应的package。
例如,

mmm package/apps/Calculator


croot

改变当前路径到代码树顶层。
cproj

改变当前路径到最近的还有Android.mk文件的祖父辈路径。
pid

使用adb shell ps命令列出手机上指定名字的进程的pid。
Usage:
       pid <YourName>
systemstack

使用kill -3system_server将系统进程中的线程信息写入/data/anr/traces.txt。
gdbclient

建立gdb调试环境,包括两步,手机上运行gdbserver,本机上运行arm-eabi-gdb。
Usage:
       gdbclient <EXE> <PORT> <AppName>

EXE: AppName的执行名。


PORT:gdbserver的端口,例如, 192.168.2.102:5039
AppName:手机中ps列出的app名字,据此查pid。
sgrep

查找当前目录及子目录中所有.c,.h,.cpp,.S,.java,.mk,.xml,.sh文件,即源码文件中包含特定单词的行,并颜色显示输出。
Usage:
       sgrep <YourWord>
Example:
       sgrep Calendar
jgrep

同sgrep,但只查.java文件。
cgrep

同sgrep,但只查c相关的文件,即.c,.cc,.cpp,.h文件。
resgrep

同sgrep,但只查res相关的.xml文件。
mgrep

同sgrep,但只查make相关的脚本文件,包括Makefile文件,Makefile目录下的所有文件,.make文件,.mak文件和.mk文件。
treegrep

查找当前目录及子目录中所有.c,.h,.cpp,.S,.java,.xml文件,即源码文件中包含特定单词的行,并颜色显示输出。
getprebuilt

输出prebuilt的路径。
tracedmdump

生成dexlist文件qtrace.dexlit,dmtrace数据文件dmtrace,和调用dmtracedump工具生成的dmtrace解析文件dmtrace.html,将生成文件放到指定路径。
Usage:
       tracedmdump <YourDirName>
如果YourDirName中不含’\’,则将放置的路径是$ANDROID_PRODUCT_OUT/traces/YourDirName。
runhat

貌似使用kill -10的方法得到heap dump并取到本地。使用hat以http方式展现出来。hat可能是个lightweight http server,不曾用过。
getbug reports

将手机/sdcard/bugreports目录下的文件下载到本地并压缩打包。
startviewserver

用指定端口启动viewserver。
Usage:
       startviewserver <Port>
不指定端口,则默认4939。
stopviewserver

关闭viewserver。
isviewserverstarted

检查viewserver是否可用。
smoketest

编译smoketest并安装手机运行。
runtest

运行development/testrunner/runtest.py $@


godir

给出一个词,godir会输出一个路径列表供用户选择要进入的路径。路径列表包含的路径满足,路径名中包含这个词,或这路径下的文件有文件名含这个词。out/路径下不考虑。
Usage:
       godir <YourKey>
Usage:
       godir Calculator
set_java_home

设置JAVA_HOME环境变量为/usr/lib/jvm/java-6-sun。
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:150300次
    • 积分:2211
    • 等级:
    • 排名:第17704名
    • 原创:75篇
    • 转载:41篇
    • 译文:2篇
    • 评论:63条
    最新评论