Android的优势就在于其开源,软件开发商可以根据自己的需求来基于Android定制自己的OS,如小米(MIUI),魅族(Flyme),锤子(Smartisan)等,因此,在对Android的源码进行定制的时候,有必要了解Android的编译过程。

Android的官方网站:http://source.android.com/source/building.html,给出了一个通用系统的编译过程

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

本文使用Android版本为2.1

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

首先来看一下google给出的编译步骤:

1> source build/envsetup.sh:加载命令

2> lunch:选择平台编译选项

3> make:执行编译

我们按照编译步骤来分析编译过程的细节,最终添加自己的平台编译选项。

1. source build/envsetup.sh

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

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

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 ()                  # 跳到指定目录 405

# add_lunch_combo函数被多次调用,就是它来添加Android编译选项

 # Clear this variable.  It will be built up again when the vendorsetup.sh

 406 # files are included at the end of this file.

 # 清空LUNCH_MENU_CHOICES变量,用来存在编译选项

 407 unset LUNCH_MENU_CHOICES

 408 function add_lunch_combo()   

 409 {

 410     local new_combo=$1         # 获得add_lunch_combo被调用时的参数

 411     local c

     # 依次遍历LUNCH_MENU_CHOICES里的值,其实该函数第一次调用时,该值为空

 412     for c in ${LUNCH_MENU_CHOICES[@]} ; do 

 413         if [ "$new_combo" = "$c" ] ; then    # 如果参数里的值已经存在于LUNCH_MENU_CHOICES变量里,则返回

 414             return

 415         fi

 416     done

     # 如果参数的值不存在,则添加到LUNCH_MENU_CHOICES变量里

 417     LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)

 418 }

# 这是系统自动增加了一个默认的编译项 generic-eng

 420 # add the default one here

 421 add_lunch_combo generic-eng    # 调用上面的add_lunch_combo函数,将generic-eng作为参数传递过去

 422 

 423 # if we're on linux, add the simulator.  There is a special case

 424 # in lunch to deal with the simulator

 425 if [ "$(uname)" = "Linux" ] ; then

 426     add_lunch_combo simulator

 427 fi

# 下面的代码很重要,它要从vendor目录下查找vendorsetup.sh文件,如果查到了,就加载它

1037 # Execute the contents of any vendorsetup.sh files we can find.

1038 for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/build/vendorsetup.sh 2> /dev/null`

1039 do

1040     echo "including $f"

1041    . $f       # 执行找到的脚本,其实里面就是厂商自己定义的编译选项

1042 done

1043 unset f

envsetup.sh其主要作用如下:

  1. 加载了编译时使用到的函数命令,如:help,lunch,m,mm,mmm等

  2. 添加了两个编译选项:generic-eng和simulator,这两个选项是系统默认选项

  3. 查找vendor/<-厂商目录>/和vendor/<厂商目录>/build/目录下的vendorsetup.sh,如果存在的话,加载执行它,添加厂商自己定义产品的编译选项

 其实,上述第3条是向编译系统添加了厂商自己定义产品的编译选项,里面的代码就是:add_lunch_combo xxx-xxx。

根据上面的内容,可以推测出,如果要想定义自己的产品编译项,简单的办法是直接在envsetup.sh最后,添加上add_lunch_combo myProduct-eng,当然这么做,不太符合上面代码最后的本意,我们还是老实的在vendor目录下创建自己公司名字,然后在公司目录下创建一个新的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上看到下面的信息:

including
vendor/farsight/vendorsetup.sh

2. 按照android官网的步骤,开始执行lunch full-eng

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

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

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:调试测试机

tests:测试机

由此可见,除了eng和user外,另外两个一般不能交给最终用户的。

那么这四个类型是干什么用的呢?其实,在main.mk里有说明,在Android的源码里,每一个目标(也可以看成工程)目录都有一个Android.mk的makefile,每个目标的Android.mk中有一个类型声明:LOCAL_MODULE_TAGS,这个TAGS就是用来指定,当前的目标编译完了属于哪个分类里。

PS:Android.mk和Linux里的makefile不太一样,它是Android编译系统自己定义的一个makefile来方便编译成:c,c++的动态、静态库或可执行程序,或java库或android的程序,

好了,我们来分析下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" ]

    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

 #  导出环境变量,这里很重要,因为后面的编译系统都是依赖于这里定义的几个变量的

        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命令可以带参数和不带参数,最终导出一些重要的环境变量,从而影响编译系统的编译结果。导出的变量如下(以实际运行情况为例)

TARGET_PRODUCT=fs100
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release

执行完上述两个步骤,就该执行:make命令了,下篇来分析。

Android编译过程详解(一)的更多相关文章

  1. Android编译过程详解(三)

    前面两节讲解了自定义Android编译项和创建Product产品配置文件,除了编译和定义产品相关环境变量外,还需要定义Board相关环境变量. 1. build/core/config.mk 109 ...

  2. Android编译过程详解(二)

    通过上篇文章,我们分析了编译android时source build/envsetup.sh和lunch命令,在执行完上述两个命令后, 我们就可以进行编译android了. 1. make  执行ma ...

  3. Android 核心分析 之八Android 启动过程详解

    Android 启动过程详解 Android从Linux系统启动有4个步骤: (1) init进程启动 (2) Native服务启动 (3) System Server,Android服务启动 (4) ...

  4. cegui-0.8.2编译过程详解

    cegui 编译过程详解(cegui-0.8.2) cegui配置整了好长时间了,在一位大牛帮助下终于搞定了,网上的教程大多是老版本的,cegui-0.8.2版的配置寥寥无几,现在总结一下,献给正在纠 ...

  5. GCC 概述:C 语言编译过程详解

    Tags: C Description: 关于 GCC 的个人笔记 GCC 概述 对于 GCC 6.1 以及之后的版本,默认使用的 C++ 标准是 C++ 14:使用 -std=c++11 来指定使用 ...

  6. uboot主Makefile分析(t配置和编译过程详解)

    1.编译uboot前需要三次make make distcleanmake x210_sd_configmake -j4 make distclean为清楚dist文件. make x210_sd_c ...

  7. uboot配置和编译过程详解【转】

    本文转载自:http://blog.csdn.net/czg13548930186/article/details/53434566 uboot主Makefile分析1 1.uboot version ...

  8. uboot配置和编译过程详解

    根据朱有鹏老师讲解整理 一.uboot主Makefile分析 1.uboot version确定(Makefile的24-29行) include/version_autogenerated.h文件是 ...

  9. Cocos2dx-3.0版本 从开发环境搭建(Win32)到项目移植Android平台过程详解

    作为重量级的跨平台开发的游戏引擎,Cocos2d-x在现今的手游开发领域占有重要地位.那么问题来了,作为Cocos2dx的学习者,它的可移植特性我们就需要掌握,要不然总觉得少一门技能.然而这个时候各种 ...

随机推荐

  1. js动态生成选项之考试系统(一)

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"% ...

  2. maven打包忽略测试用例

    忽略单元测试失败: $ mvn test -Dmaven.test.failure.ignore=true 跳过单元测试: mvn install -Dmaven.test.skip=true 跳过测 ...

  3. poj2109

    刚开始看着道题时,感觉不用高精度好像就没法做,想了半天然后果断去看依然博客(这样确实不好),发现又用到了double(这个可以放“+” “-” 300多位的家伙!!!) #include <io ...

  4. 奥迪--A4L

    -型号:A4L -价格:30-41W -动力:2T -变速箱:7挡双离合 -长宽高:4.81,1.84,1.43 -油箱:54L -发动机:EA888 -大灯:氙气(选装LED)

  5. virt-XXX

    尽管 virt-manager 是 libvirt 虚拟化 API 的一个首要用户,但有一个越来越庞大的工具生态系统在使用此接口进行虚拟化管理.virt-manager 包提供了一个便捷的 GUI,用 ...

  6. JAVA 综合布局应用

    //布局综合应用 import java.awt.*; import javax.swing.*; public class Jiemian4 extends JFrame{ JPanel mb1,m ...

  7. APP测试时不可忽视搭建代理服务器抓包测试的必要性

    这几天测的一个app,后台从已有服务器搬迁到了阿里云,接口api之类的都没有变化,但测试时发现客户端始终无法使用,每次点击都无法获得服务器反馈 用python编写脚本调接口,没问题,返回数据一切正常, ...

  8. this.IsMounted() is not a function

    I'm trying to build a simple React App. It retrieves data from an ajax call and renders it to the pa ...

  9. Winform 中 DesignMode 返回值不正确的问题。

    本文转载:http://blog.csdn.net/sabty/article/details/5325260 以前也曾遇到这样的问题,不过影响不大也没有去详细了解.今天又重新遇到此问题,实在太不便. ...

  10. Hadoop,master和slave简单的分布式搭建

    搭建过程中配置免密钥登录为了以后方便使用 [提醒]安装Hadoop中会遇到新建文件夹,配置路径等问题,这个不能生搬硬套,要使用自己配置的路径,灵活使用. Hadoop的部署配置文件在http://bl ...