一、Makefile的主要流程
以下主要流程都在build/core/main.mk里安排。
l初始化相关的参数设置(buildspec.mk、envsetup.mk、config.mk)
l检测编译环境和目标环境
l决定目标product
l读取product的配置信息及目标平台信息
l清除输出目录
l检查版本号
l读取Board的配置
l读取所有Module的配置
l根据配置产生必要的规则(build/core/Makefile)
l生成image

主要配置文件:
build/core/config.mk summary of config
build/core/envsetup.mk generate dir config and so on
build/target/product product config
build/target/board board config
build/core/combo build flags config
这里解释下这里的board和product。borad主要是设计到硬件芯片的配置,比如是否提供硬件的某些功能,比如说GPU等等,或者芯片支持浮点 运算等等。product是指针对当前的芯片配置定义你将要生产产品的个性配置,主要是指APK方面的配置,哪些APK会包含在哪个product中,哪 些APK在当前product中是不提供的。
config.mk是一个总括性的东西,它里面定义了各种module编译所需要使用的HOST工具以及如何来编译各种模块,比如说 BUILT_PREBUILT就定义了如何来编译预编译模块。envsetup.mk主要会读取由envsetup.sh写入环境变量中的一些变量来配置 编译过程中的输出目录,combo里面主要定义了各种Host和Target结合的编译器和编译选项。
配置部分主要完成以下几个工作:
a) 基于 android 产品的配置(product config):选择构建安装的运行 程序 (user package)
b) 设置 target 等相关变量TARGET_ARCH, TARGET_OS,TARGET_BUILD_TYPE, TARGET_PREBUILT_TAG
c) 根据编译环境设置 host等相关变量HOST_OS, HOST_ARCH,HOST_BUILD_TYPE, HOST_PREBUILT_TAG
d) 编译 target上运行程序所需的工具链及编译参数设置,如linux-arm-cc,cflag,include目录等。
e) 编译 host上运行程序所需的工具链及编译参数设置。
下图简要介绍了Android build system的配置部分的主要构成及相互关系。
二、初始化参数设置
在main.mk里,简单设置几个主要编译路径的变量后,来到config.mk:
——————————————config.mk——————————————
其中设置了源文件的一系列路径,包括头文件、库文件、服务、API已经编译工具的路径。(前36行)
从40行开始,定义一些编译模块的生成规则:
除了CLEAR_VARS是清楚本地变量之外,其他所有的都对应了一种模块的生成规则,每一个本地模块最后都会include其中的一种来生成目标模块。
回到config.mk,接着会尝试读取buildspec.mk的设置:
如同注释所说,会尝试查找buildspec.mk,如果文件不存在会自动使用环境变量的设置,如果仍然未定义,会按arm默认的设置去build。
这里的buildspec.mk可以自己创建,也可以将原先build/下的buildspec.mk.default直接命名为buildspec.mk并移到根目录。
实际上,buildspec.mk配置都被屏蔽了,我们可以根据需要直接打开和修改一些变量。在这里我们可以加入自己的目标产品信息:
ifndef TARGET_PRODUCT
TARGET_PRODUCT:=generic_x86
endif
以及输出目录设置:
OUT_DIR:=$(TOPDIR)generic_x86

三、读取Product的设定
回到config.mk,接着进行全局变量设置,进入envsetup.mk:
——————————————envsetup.mk——————————————
里面的大部分函数都在build/envsetup.sh中定义 盛世游戏:http://www.shengshiyouxi.com
首先,设置版本信息,(11行)在build/core/version_defaults.mk中具体定义平台版本、SDK版本、Product版本,我们可以将BUILD_NUMBER作为我们产品generic_x86的version信息,当然,也可以自定义一个版本变量。
回到envsetup.mk,接着设置默认目标产品(generic),这里由于我们在buildspec.mk里设置过TARGET_PRODUCT,事实上这个变量值为generic_x86。
然后读取product的设置(41行),具体实现在build/core/product_config.mk中,进而进入product.mk,从build/target/product/AndroidProducts.mk中读出PRODUCT_MAKEFILES,这些makefile各自独立定义product,而我们的产品generic_x86也应添加一个makefile文件generic_x86.mk。在generic_x86.mk中我们可以加入所需编译的PRODUCT_PACKAGES。
下面为generic_x86.mk:
四、读取BoardConfig
接着回到config.mk,(114行)这里会搜索所有的BoardConfig.mk,主要有以下几个地方:
这里的TARGET_DEVICE就是generic_x86,就是说为了定义我们自己的产品generic_x86,我们要在build/target/board下添加一个自己的目录generic_x86用来加载自己的board配置。
在BoardConfig.mk中会决定是否编译bootloader、kernel等信息。

五、读取所有Module
结束全局变量配置后,回到main.mk,马上对编译工具及版本进行检查,错误便中断编译。
142行,包含文件definitions.mk,这里面定义了许多变量和函数供main.mk使用。main.mk第446行,这里会去读取所有的Android.mk文件:
其中include $(ONE_SHOT_MAKEFILE)
这个ONE_SHOT_MAKEFILE是在前面提到的mm(envsetup.mk)函数中赋值的:
ONE_SHOT_MAKEFILE=$M make -C $T files $@
回到main.mk,最终将遍历查找到的所有子目录下的Android.mk的路径保存到subdir_makefiles变量里(main.mk里的470行):
我们在package/apps下每个模块根目录都能看到Android.mk,里面会去定义当前本地模块的Tag:LOCAL_MODULE_TAGS,Android会通过这个Tag来决定哪些本地模块会编译进系统,通过PRODUCT和LOCAL_MODULE_TAGS来决定哪些应用包会编译进系统。(前面说过,你也能通过buildspec.mk来制定你要编译进系统的模块)
这个过程在mian.mk的445行开始,最后需要编译的模块路径打包到ALL_DEFAULT_INSTALLED_MODULES(602行):

六、产生相应的Rules,生成image
所有需要配置的准备工作都已完成,下面该决定如何生成image输出文件了,这一过程实际上在build/core/Makefile中处理的。
这里定义各种img的生成方式,包括ramdisk.img、userdata.img、system.img、update.zip、recover.img等。具体对应的rules可以参考下图:
http://img154.ph.126.net/5ekAHoRqfPf17ALmDJGDYA==/2269251262242871911.png
当Make include所有的文件,完成对所有make文件的解析以后就会寻找生成对应目标的规则,依次生成它的依赖,直到所有满足的模块被编译好,然后使用相应的工具打包成相应的img。

具体make操作:完整编译
我们在根目录下输入make命令即可开始完全编译。这个命令实际编译生成的默认目标是droid。
也就是说,大家敲入make实际上执行的make droid。而接下来大家看看main.mk文件里最后面的部分,会有很多伪目标,如sdk、clean、clobber等,这些在默认的make droid的命令下是不会执行的。我们可以在make后加上这些标签来单独实现一些操作。如:输入make sdk 将会生成该版本对应的SDK,输入make clean会清除上次编译的输出。模块编译
有时候我们只修改了某一个模块,希望能单独编译这个模块而不是重新完整编译一次,这时候我们要用到build/envsetup.sh中提供的几个bash的帮助函数。
在源代码根目录下执行:
. build/envsetup.sh(.后面有空格)
这样大家相当于多了几个可用的命令。
这时可以用help命令查看帮助信息:
其中对模块编译有帮助的是tapas、m、mm、mmm这几个命令。
1、tapas——以交互方式设置build环境变量。
输入:tapas
第一步,选择目标设备:
第二步,选择代码格式:
第三步,选择产品平台:

注意:这里,Google源代码里默认是generic,而我们针对自己的产品应修改成generic_x86
具体在build/envsetup.sh里的函数chooseproduct()中对相应代码进行修改。
2、m、mm、mmm使用独立模块的make命令。
几个命令的功能使用help命令查看。
举个例子,我们修改了Camera模块的代码,现在需要重新单独编译这一块,这时可以使用mmm命令,后面跟指定模块的路径(注意是模块的根目录)。
具体如下:
mmm packages/apps/Camera/
为了可以直接测试改动,编译好后需要重新生成system.img
可以执行:make snod单独编译image文件
一般我们完整编译后,会生成三个重要的image文件:ramdisk.img、system.img和userdata.img。当然我们可以分开单独去编译这三个目标:
make ramdisk —— ramdisk.img
make userdataimage —— userdata.img
make systemimage—— system.img

更多相关文章

  1. Android优雅的控制用户点击按钮的频率
  2. Android(安卓)添加系统服务
  3. android viewflipper 左右滑动切换显示图片效果
  4. android Criteria
  5. Android(安卓)自定义ScrollView可监控滑动方向、滑动到底部
  6. webrtc的音频处理模块apm( audio processing)下载与编译出libweb
  7. Android(安卓)三种方式实现自定义圆形页面加载中效果的进度条
  8. android输入法01:SoftKeyboard源码解析03
  9. Android(安卓)源码环境搭建及编译

随机推荐

  1. Android圆形进度显示控件的SectorProgres
  2. 关于android生命周期那点事
  3. MTK Android Driver :sound
  4. 新添的Activity 要在 manifest 中注册 否
  5. android 设置 源码 修改默认主题为白底黑
  6. [置顶] android 心跳包的分析
  7. Android Permission中英对照
  8. MyEclipse10 配置 Android SDK 时遇到的
  9. [AndroidTips]Declaring a custom androi
  10. 最新eclipse中android插件安装下载地址