近日接手了后续android新平台项目搭建的任务。

本文内容基于sprd公司提供的android5.1源码。

一、一般的编译工作流程

我们代码一般情况下是从芯片商SPRD/MTK获得的。

源码的编译上,一般还是和google官网(http://source.android.com/source/building.html)上要求的一致。分为三步:

1.source build/envsetup.sh

2.lunch xxx

3.make -j8 2>&1 |tee build.log (make就可以,这样写两个目的:1.多核编译 2.输出编译的log)

4.mmm "模块"可以编译单独的模块(要全编译后才可以编译模块)

二、原理

android的编译是基于的linux的make命令的。Make命令在执行的时候,默认会在当前目录找到一个Makefile文件,然后根据Makefile文件中的指令来对代码进行编译。

Makefile文件最基础的功能就是描述文件之间的依赖关系,以及怎么处理这些依赖关系。

整个android源码的编译就是由根目录的Makefile文件来执行的。

现在我们就了解下我们编译过程中的命令做了哪些事情。

1.source build/envsetup.sh

执行build/envsetup.sh脚本(ps: source xx.sh命令就是 执行一个脚本的意思。那为什么不直接./xxx.sh呢? 见这篇文章http://blog.csdn.net/coofive/article/details/671835)

build/envsetup.sh脚本里做了哪些事情呢?

(1)遍历出device/xxx/xxx/里 所有的 envsetup.sh文件,并将他们都source进来,

这些 envsetup.sh里面有哪些代码呢

举一个例子 device/sprd/zsl1805/lava/envsetup.sh

add_lunch_combo zsl1805_lava-userdebug
add_lunch_combo zsl1805_lava-user

add_lunch_combo是什么东西?我们先不管,往下看。

(2)定义各种函数。

如:lunch mmm add_lunch_combo等。

lunch:用来初始化编译环境,例如设置环境变量和指定目标产品型号。后面再说

m:相当于是在执行make命令。对整个Android源码进行编译。

mm:如果是在Android源码根目录下执行,那么就相当于是执行make命令对整个源码进行编译。如果是在Android源码根目录下的某一个子目录执行,那么就在会在从该子目录开始,一直往上一个目录直至到根目录,寻找是否存在一个Android.mk文件。如果存在的话,那么就通过make命令对该Android.mk文件描述的模块进行编译。

mmm:后面可以跟一个或者若干个目录。就是编译模块了。如mmm "packages/apps/Launcher3"

add_lunch_combo:

 unset LUNCH_MENU_CHOICES
function add_lunch_combo()
{
local new_combo=$
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_lunch_combo把"zsl1805_lava_userdebug"和"zsl1805_lava_user"add到"LUNCH_MENU_CHOICES"里了。

到这里,source build/envsetup.sh的工作就做完了。

此时可以在shell命令行里看到

including device/sprd/zsl1805/lava/vendorsetup.sh的字样,这个文件确实被加载进来了

2.lunch操作

我们先看下build/envsetup.sh中lunch函数的代码

 #打印"LUNCH_MENU_CHOICES"中所有值
function print_lunch_menu()
{
local uname=$(uname)
echo
echo "You're building on" $uname
echo
echo "Lunch menu... pick a combo:" local i=
local choice
for choice in ${LUNCH_MENU_CHOICES[@]}
do
echo " $i. $choice"
i=$(($i+))
done echo
} function lunch()
{
local answer
#如果只输入了lunch命令,会打印"LUNCH_MENU_CHOICES"中所有值
if [ "$1" ] ; then
answer=$
else
print_lunch_menu
echo -n "Which would you like? [aosp_arm-eng] "
read answer
fi #判断lunch后面的值是不是LUNCH_MENU_CHOICES中的值,如果是,则把这个值赋给selection
local selection= if [ -z "$answer" ]
then
selection=aosp_arm-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-))]}
fi
elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
then
selection=$answer
fi if [ -z "$selection" ]
then
echo
echo "Invalid lunch combo: $answer"
return
fi export TARGET_BUILD_APPS=
export CONFIG_TARGET_BUILD_TYPE= #对selection值进行分割操作,得到product和variant

local product=$(echo -n $selection | sed -e "s/-.*$//")
check_product $product
if [ $? -ne ]
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 ]
then
echo
echo "** Invalid variant: '$variant'"
echo "** Must be one of ${VARIANT_CHOICES[@]}"
echo "** Vinton.Wang -----------> variant:'$variant'"
export CONFIG_TARGET_BUILD_TYPE=$(echo $variant | tr '[a-z]' '[A-Z]')
echo "** Vinton.Wang -----------> type:'$CONFIG_TARGET_BUILD_TYPE'"
variant="userdebug"
fi if [ -z "$product" -o -z "$variant" ]
then
echo
return
fi
91 #得到TARGET_PRODUCT TARGET_BUILD_VARIANT TARGET_BUILD_TYPE三个值
export TARGET_PRODUCT=$product
export TARGET_BUILD_VARIANT=$variant
export TARGET_BUILD_TYPE=release
export ARCH=$(gettargetarch)
echo "############# ${ARCH} ##############" echo
echo
check_hq_version
set_stuff_for_environment #设置环境变量
printconfig
}

另外,在check_product()和printconfig()两个方法中,调用了get_build_var()函数。

# 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." >&
return
fi
(\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
command make --no-print-directory -f build/core/config.mk dumpvar-$)
}

也就是说,在lunch的过程中,编译了build/core/config.mk

总结一下Lunch流程:

1.判断是不是没有参数

2.判断参数是否合法

3.将参数进行分割操作,得到TARGET_PRODUCT    TARGET_BUILD_VARIANT 。针对我们的例子TARGET_PRODUCT = zsl1805_lava  TARGET_BUILD_VARIANT = user或者userdebug

4.设置环境变量

如果我们直接输入lunch,会有下面的界面出现

You're building on Linux

 
generic-eng simulator fs100-eng
Lunch menu... pick a combo:
     1. generic-eng
     2. simulator
     3. fs100-eng
         .....................

40. zsl1805_lava-userdebug
        41. zsl1805_lava-user

然后,我们需要lunch zsl1805_lava-userdebug即可。

到此时,android编译环境的初始化就完成了。

贴一张初始化完成之后,我们获得的东西

3.make

下面就是执行编译了。根目录里的Makefile文件中是这样的

### DO NOT EDIT THIS FILE ###
include build/core/main.mk
### DO NOT EDIT THIS FILE ###

Make其实就是按照main.mk的编译规则来编译的。

整个编译过程还是比较复杂的,这里有一张main.mk的编译示意图,基本涵盖了所有编译内容。这里,如果对某些细节感兴趣,可以看下面的参考资料再去深入学习。

如果我们要对编译过程中的流程修改,就按照这个图找到相应的.mk文件进行修改。

参考资料:

Android编译系统环境初始化过程分析

Android编译过程详解(一):http://www.cnblogs.com/mr-raptor/archive/2012/06/07/2540359.html

Android编译过程详解(二):http://www.cnblogs.com/mr-raptor/archive/2012/06/08/2541571.html

android编译系统学习的更多相关文章

  1. Android编译系统入门(二)

    Android.mk的使用方法 在上一篇Android编译系统入门(一)中我们只要介绍了Android系统使用make命令默认编译的依赖树是droid,而droid是一个伪目标,它有两个先决条件dro ...

  2. Android编译系统入门(一)

    做过Android平台开发的朋友对make,mm或make clean命令应该很熟悉,但也许大家只是熟知这些命令的作用却不知道这些命令底下有些什么原理?那么今天我就带着大家推开Android编译系统的 ...

  3. Android编译系统简要介绍【转】

    本文转载自:http://blog.csdn.net/luoshengyang/article/details/18466779 在Android源码环境中,我们开发好一个模块后,再写一个Androi ...

  4. Android开发学习之路-RecyclerView滑动删除和拖动排序

    Android开发学习之路-RecyclerView使用初探 Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析 Android开 ...

  5. Android开发学习路线图

    Android开发学习方法: Android是一个比较庞大的体系,从底层的Linux内核到上层的应用层,各部分的内容跨度也比较大.因此,一个好的学习方法对我们学习Android开发很重要. 在此建议, ...

  6. Android动画学习(二)——Tween Animation

    前两天写过一篇Android动画学习的概述,大致的划分了下Android Animation的主要分类,没有看过的同学请移步:Android动画学习(一)——Android动画系统框架简介.今天接着来 ...

  7. Android自动化学习笔记:编写MonkeyRunner脚本的几种方式

    ---------------------------------------------------------------------------------------------------- ...

  8. Android自动化学习笔记之MonkeyRunner:官方介绍和简单实例

    ---------------------------------------------------------------------------------------------------- ...

  9. android开发学习笔记000

    使用书籍:<疯狂android讲义>——李刚著,2011年7月出版 虽然现在已2014,可我挑来跳去,还是以这本书开始我的android之旅吧. “疯狂源自梦想,技术成就辉煌.” 让我这个 ...

随机推荐

  1. Unity3d Material(材质) 无缝拼接

    Unity3d Material(材质) Edit by @灰太龙 在做一个项目的过程中,遇到动态切换壁纸的功能,问题点在无缝拼接! 那我们先查查Unity3d 中的材质球,里面有个参数 Tiling ...

  2. 【木德木作杯楼市达人秀NO.28】南湖买房故事

    应得意版主的邀请,我也来写写我的买房故事,虽然过程没有别人那么惊心动魄,但是毕竟是自己人生中非常重要的一件事情,就像恋爱一样,情话永远没有情书好,我也借此纪念一下这段短暂的时光.其中会涉及到本人对一些 ...

  3. Python4Delphi也是与VCL密切相关,所以才能相互调用,绝对有研究价值!

    Python4Delphi也是与VCL密切相关,所以才能相互调用,绝对有研究价值! http://www.cnblogs.com/GarfieldTom/archive/2013/01/17/2864 ...

  4. android 读取SD卡文件

    SD卡作为手机的扩展存储设备,在手机中充当硬盘角色,可以让我们手机存放更多的数据以及多媒体等大体积文件.因此查看SD卡的内存就跟我们查看硬盘的剩余空间一样,是我们经常操作的一件事,那么在Android ...

  5. AES加密跨平台出现的问题

    javax.crypto.BadPaddingException: Given final block not properly padded at com.sun.crypto.provider.S ...

  6. 【Linux】鸟哥的Linux私房菜基础学习篇整理(二)

    1. dumpe2fs [-bh] devicename:查询superblock信息.参数:-b:列出保留为坏道的部分:-h:列出superblock的数据,不会列出其他的区段内容. 2. df [ ...

  7. Unity NGUI中动态添加和删除sprite

    (以后,参考链接和作者将在文章首部给出,转载请保留此部分内容) 参考链接:http://www.narkii.com/club/thread-299977-1.html,作者:纳金网 比巴卜: 参考链 ...

  8. Pots(bfs)

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8266   Accepted: 3507   Special Judge D ...

  9. 【转】android开发中如何结束所有的activity

    原文网址:http://java--hhf.iteye.com/blog/1826880 每一个activity都有自己的生命周期,被打开了最终就要被关闭. 四种结束当前的activity方法 //关 ...

  10. 数据结构(线段树):BZOJ 1568 [JSOI2008]Blue Mary开公司

    1568: [JSOI2008]Blue Mary开公司 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 602  Solved: 214[Submit ...