Android源码编译命令详解(一)

Android的优势就在于其开源,手机和平板生产商可以根据自己的硬件进行个性定制自己的手机产品,如小米,LePhone,M9等,因此,在我们在对Android的源码进行定制的时候,很有必要了解下,Android的编译过程。

如果你从来没有做过Android代码的编译,那么最官方的编译过程就是查看Android的官方网站:http://source.android.com/source/building.html

但是,这儿只是告诉你了如何去编译一个通用的系统,并没有详细告诉你细节,我们跟着编译过程来了解下。

+--------------------------------------------------------------------------------------------------------------------+

 本文使用Android版本为2.1,采用开发板为华清远见研发的FS_S5PC100 A8开发板。

+--------------------------------------------------------------------------------------------------------------------+


1. source build/envsetup.sh

这个命令是用来将envsetup.sh里的所有用到的命令加载到环境变量里去,我们来分析下它。

envsetup.sh里的主要命令如下:


[plain] function help()                  # 显示帮助信息 
function get_abs_build_var()           # 获取绝对变量 
function get_build_var()             # 获取绝对变量 
function check_product()             # 检查product 
function check_variant()             # 检查变量 
function setpaths()                # 设置文件路径 
function printconfig()              # 打印配置 
function set_stuff_for_environment()        # 设置环境变量 
function set_sequence_number()            # 设置序号 
function settitle()                # 设置标题 
function choosetype()               # 设置type 
function chooseproduct()              # 设置product 
function choosevariant()              # 设置variant 
function tapas()                  # 功能同choosecombo 
function choosecombo()               # 设置编译参数 
function add_lunch_combo()             # 添加lunch项目 
function print_lunch_menu()            # 打印lunch列表 
function lunch()                 # 配置lunch 
function m()                   # make from top 
function findmakefile()              # 查找makefile 
function mm()                   # make from current directory 
function mmm()                   # make the supplied directories 
function croot()                 # 回到根目录 
function cproj() 
function pid() 
function systemstack() 
function gdbclient() 
function jgrep()                 # 查找java文件 
function cgrep()                  # 查找c/cpp文件 
function resgrep() 
function tracedmdump() 
function runhat() 
function getbugreports() 
function startviewserver() 
function stopviewserver() 
function isviewserverstarted() 
function smoketest() 
function runtest() 
function godir ()                 # 跳到指定目录 
 
  
# 这是系统自动增加了一个默认的编译项 generic-eng 
# add the default one here 
<strong><span style="color:#ff0000;">add_lunch_combo generic-eng</span></strong> 
 
  
# 下面的代码很重要,它要从vendor目录下查找vendorsetup.sh文件,如果查到了,就加载它 
# Execute the contents of any vendorsetup.sh files we can find. 
<strong><span style="color:#ff0000;">for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh 2> /dev/null` 
do 
    echo "including $f" 
    . $f 
done</span></strong> 
function help()                  # 显示帮助信息
function get_abs_build_var()           # 获取绝对变量
function get_build_var()             # 获取绝对变量
function check_product()             # 检查product
function check_variant()             # 检查变量
function setpaths()                # 设置文件路径
function printconfig()              # 打印配置
function set_stuff_for_environment()        # 设置环境变量
function set_sequence_number()            # 设置序号
function settitle()                # 设置标题
function choosetype()               # 设置type
function chooseproduct()              # 设置product
function choosevariant()              # 设置variant
function tapas()                  # 功能同choosecombo
function choosecombo()               # 设置编译参数
function add_lunch_combo()             # 添加lunch项目
function print_lunch_menu()            # 打印lunch列表
function lunch()                 # 配置lunch
function m()                   # make from top
function findmakefile()              # 查找makefile
function mm()                   # make from current directory
function mmm()                   # make the supplied directories
function croot()                 # 回到根目录
function cproj()
function pid()
function systemstack()
function gdbclient()
function jgrep()                 # 查找java文件
function cgrep()                  # 查找c/cpp文件
function resgrep()
function tracedmdump()
function runhat()
function getbugreports()
function startviewserver()
function stopviewserver()
function isviewserverstarted()
function smoketest()
function runtest()
function godir ()                 # 跳到指定目录

 
# 这是系统自动增加了一个默认的编译项 generic-eng
# add the default one here
<strong><span style="color:#ff0000;">add_lunch_combo generic-eng</span></strong>

 
# 下面的代码很重要,它要从vendor目录下查找vendorsetup.sh文件,如果查到了,就加载它
# Execute the contents of any vendorsetup.sh files we can find.
<strong><span style="color:#ff0000;">for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh 2> /dev/null`
do
    echo "including $f"
    . $f
done</span></strong>根据上面的内容,可以推测出,如果要想定义自己的产品编译项,简单的办法是直接在envsetup.sh最后,添加上add_lunch_combo myProduct-eng,当然这么做,不太符合上面代码最后的本意,我们还是老实的在vendor目录下创建自己公司名字,然后在公司目录下创建一个新的vendorsetup.sh,在里面添加上自己的产品编译项


[plain] #mkdir vendor/farsight/ 
#touch vendor/farsight/vendorsetup.sh 
#echo "add_lunch_combo fs100-eng" > vendor/farsight/vendorsetup.sh 
#mkdir vendor/farsight/
#touch vendor/farsight/vendorsetup.sh
#echo "add_lunch_combo fs100-eng" > vendor/farsight/vendorsetup.sh这样,当我们在执行source build/envsetup.sh命令的时候,可以在shell上看到下面的信息:


[plain] including vendor/farsight/vendorsetup.sh 
including vendor/farsight/vendorsetup.sh
2. 按照android官网的步骤,开始执行lunch full-eng

当然如果你按上述命令执行,它编译的还是通用的eng版本系统,不是我们个性系统,我们可以执行lunch命令,它会打印出一个选择菜单,列出可用的编译选项

如果你按照第一步中添加了vendorsetup.sh那么,你的选项中会出现:


[plain] You're building on Linux 
 
generic-eng simulator fs100-eng 
Lunch menu... pick a combo: 
     1. generic-eng 
     2. simulator 
     3. fs100-eng 
You're building on Linux

generic-eng simulator fs100-eng
Lunch menu... pick a combo:
     1. generic-eng
     2. simulator
     3. fs100-eng其中第3项是我们自己添加的编译项。

lunch命令是envsetup.sh里定义的一个命令,用来让用户选择编译项,来定义Product和编译过程中用到的全局变量。

我们一直没有说明前面的fs100-eng是什么意思,现在来说明下,fs100是我定义的产品的名字,eng是产品的编译类型,除了eng外,还有user, userdebug,分别表示:

eng: 工程机,

user:最终用户机

userdebug:调试测试机

由此可见,除了eng和user外,另外两个一般不能交给最终用户的,记得m8出来的时候,先放出了一部分eng工程机,然后出来了user机之后,可以用工程机换。

好了,我们来分析下lunch命令干了什么?


[plain] 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" ] 
    then 
           # 如果用户在菜单中没有选择,直接回车,则为系统缺省的generic-eng 
        selection=generic-eng 
    elif [ "$answer" = "simulator" ] 
    then 
        # 如果是模拟器 
        selection=simulator 
    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$") 
    then 
        # 如果answer是选择菜单的数字,则获取该数字对应的字符串 
        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ] 
        then 
            selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]} 
        fi 
        # 如果 answer字符串匹配 *-*模式(*的开头不能为-) 
    elif (echo -n $answer | grep -q -e "^[^-][^-]*-[^-][^-]*$") 
    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 
        # 模拟器模式 www.2cto.com
        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 
<span style="white-space:pre">    </span>#  导出环境变量,这儿很重要,因为后面的编译系统都是依赖于这里定义的几个变量的 
        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 

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" ]
    then
           # 如果用户在菜单中没有选择,直接回车,则为系统缺省的generic-eng
        selection=generic-eng
    elif [ "$answer" = "simulator" ]
    then
        # 如果是模拟器
        selection=simulator
    elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
    then
        # 如果answer是选择菜单的数字,则获取该数字对应的字符串
        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
        then
            selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}
        fi
        # 如果 answer字符串匹配 *-*模式(*的开头不能为-)
    elif (echo -n $answer | grep -q -e "^[^-][^-]*-[^-][^-]*$")
    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
<span style="white-space:pre"> </span>#  导出环境变量,这儿很重要,因为后面的编译系统都是依赖于这里定义的几个变量的
        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
}由上面分析可知,lunch命令可以带参数和不带参数,最终导出一些重要的环境变量,从而影响编译系统的编译结果。导出的变量如下(以实际运行情况为例)


[plain] TARGET_PRODUCT=fs100 
TARGET_BUILD_VARIANT=eng 
TARGET_SIMULATOR=false 
TARGET_BUILD_TYPE=release 
        TARGET_PRODUCT=fs100
        TARGET_BUILD_VARIANT=eng
        TARGET_SIMULATOR=false
        TARGET_BUILD_TYPE=release
执行完上述两个步骤,就该执行:make命令了,下篇来分析。

原文地址:https://www.cnblogs.com/cane/p/3956120.html