zoukankan      html  css  js  c++  java
  • 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命令了,下篇来分析。

  • 相关阅读:
    Java实现web页面内容抓取
    Java写入文件的几种方法及性能对比
    Java实现导出excel
    win10系统安装VMware虚拟机软件以及linux系统
    oracle11g安装教程
    oracle怎么建立本地连接
    工厂模式
    计算一个字符串中每个字符出现的次数
    MySql多表查询
    如何查看MySql的sql语句性能
  • 原文地址:https://www.cnblogs.com/cane/p/3956120.html
Copyright © 2011-2022 走看看