【转】Android编译系统详解(三)——编译流程详解
原文网址:http://www.cloudchou.com/android/post-276.html
1.概述
编译Android的第三步是使用mka命令进行编译,当然我们也可以使用make –j4,但是推荐使用mka命令。因为mka将自动计算-j选项的数字,让我们不用纠结这个数字到底是多少(这个数字其实就是所有cpu的核心数)。在编译时我们可以带上我们需要编译的目标,假设你想生成recovery,那么使用mka recoveryimage,如果想生成ota包,那么需要使用mka otapackage,后续会介绍所有可以使用的目标。另外注意有一些目标只是起到修饰的作用,也就是说需要和其它目标一起使用,共有4个用于修饰的伪目标:
- 1) showcommands 显示编译过程中使用的命令
- 2) incrementaljavac用于增量编译java代码
- 3) checkbuild用于检验那些需要检验的模块
- 4) all如果使用all修饰编译目标,会编译所有模块
研究Android编译系统时最头疼的可能是变量,成百个变量我们无法记住其含义,也不知道这些变量会是什么值,为此我专门做了一个编译变量的参考网站android.cloudchou.com,你可以在该网站查找变量,它能告诉你变量的含义,也会给出你该变量的示例值,另外也详细解释了编译系统里每个Makefile的作用,这样你在看编译系统的代码时不至于一头雾水。
编译的核心文件是build/core/main.mk和build/core/makefile,main.mk主要作用是检查编译环境是否符合要求,确定产品配置,决定产品需要使用的模块,并定义了许多目标供开发者使用,比如droid,sdk等目标,但是生成这些目标的规则主要在Makefile里定义,而内核的编译规则放在build/core/task/kernel.mk
我们将先整体介绍main.mk的执行流程,然后再针对在Linux上编译默认目标时使用的关键代码进行分析。Makefile主要定义了各个目标的生成规则,因此不再详细介绍它的执行流程,若有兴趣看每个目标的生成规则,可查看http://android.cloudchou.com/build/core/Makefile.php
2. main.mk执行流程
2.1 检验编译环境并建立产品配置
- 1) 设置Shell变量为bash,不能使用其它shell
- 2) 关闭make的suffix规则,rcs/sccs规则,并设置一个规则: 当某个规则失败了,就删除所有目标
- 3) 检验make的版本,cygwin可使用任意版本make,但是linux或者mac只能使用3.81版本或者3.82版本
- 4) 设置PWD,TOP,TOPDIR,BUILD_SYSTEM等变量,定义了默认目标变量,但是暂时并未定义默认目标的生成规则
- 5) 包含build/core/help.mk,该makefile定义了两个目标help和out, help用于显示帮助,out用于检验编译系统是否正确
- 6) 包含build/core/config.mk,config.mk作了很多配置,包括产品配置,包含该makefile后,会建立输出目录系列的变量,还会建立PRODUCT系列变量,后续介绍产品配置时,对此会有更多详细介绍
- 7) 包含build/core/cleanbuild.mk,该makefile会包含所有工程的CleanSpec.mk,写了CleanSpec.mk的工程会定义每次编译前的特殊清理步骤,cleanbuild.mk会执行这些清除步骤
- 8) 检验编译环境,先检测上次编译结果,如果上次检验的版本和此次检验的版本一致,则不再检测,然后进行检测并将此次编译结果写入
2.2 包含其它makefile及编译目标检测
- 1) 如果目标里含有incrementaljavac, 那么编译目标时将用incremental javac进行增量编译
- 2) 设置EMMA_INSTRUMENT变量的值,emma是用于测试代码覆盖率的库
- 3) 包含build/core/definistions.mk,该makefile定义了许多辅助函数
- 4) 包含build/core/qcom_utils.mk,该makefile定义了高通板子的一些辅助函数及宏
- 5) 包含build/core/dex_preopt.mk,该makefile定义了优化dex代码的一些宏
- 6) 检测编译目标里是否有user,userdebug,eng,如果有则告诉用户放置在buildspec.mk或者使用lunch设置,检测TARGET_BUILD_VARIANT变量,看是否有效
- 7) 包含build/core/pdk_config.mk, PDK主要是能提高现有设备升级能力,帮助设备制造商能更快的适配新版本的android
2.3 根据TARGET_BUILD_VARIANT建立配置
- 1) 如果编译目标里有sdk,win_sdk或者sdk_addon,那么设置is_sdk_build为true
- 2) 如果定义了HAVE_SELINUX,那么编译时为build prop添加属性ro.build.selinux=1
- 3) 如果TARGET_BUILD_VARIANT是user或者userdebug,那么tags_to_install += debug 如果用户未定义DISABLE_DEXPREOPT为true,并且是user模式,那么将设置WITH_DEXPREOPT := true,该选项将开启apk的预优化,即将apk分成odex代码文件和apk资源文件
- 4) 判断enable_target_debugging变量,默认是true,当build_variant是user时,则它是false。如果该变量值为true,则设置Rom的编译属性ro.debuggable为1,否则设置ro.debuggable为0
- 5) 如果TARGET_BUILD_VARIANT是eng,那么tags_to_install为debug,eng, 并设置Rom的编译属性ro.setupwizard.mode为OPTIONAL,因为eng模式并不要安装向导
- 6) 如果TARGET_BUILD_VARIANT是tests,那么tags_to_install := debug eng tests
- 7) 设置sdk相关变量
- 8) 添加一些额外的编译属性
- 9) 定义should-install-to-system宏函数
- 10) 若除了修饰目标,没定义任何目标,那么将使用默认目标编译
2.4 包含所有要编译的模块的Makefile
如果编译目标是clean clobber installclean dataclean,那么设置dont_bother为true,若dont_bother为false,则将所有要编译的模块包含进来
1) 如果主机操作系统及体系结构为darwin-ppc(Mac电脑),那么提示不支持编译Sdk,并将SDK_ONLY设置为true
2) 如果主机操作系统是windows,那么设置SDK_ONLY为true
3) 根据SDK_ONLY是否为true,编译主机操作系统类型,BUILD_TINY_ANDROID的值,设置sudbidrs变量
4) 将所有PRODUCT_*相关变量存储至stash_product_vars变量,稍后将验证它是否被修改
5) 根据ONE_SHOT_MAKEFILE的值是否为空,包含不同的makefile
6) 执行post_clean步骤,并确保产品相关变量没有变化
7) 检测是否有文件加入ALL_PREBUILT
8) 包含其它必须在所有Android.mk包含之后需要包含的makefile
9) 将known_custom_modules转化成安装路径得到变量CUSTOM_MODULES
10) 定义模块之间的依赖关系,$(ALL_MODULES.$(m).REQUIRED))变量指明了模块之间的依赖关系
11) 计算下述变量的值:product_MODULES,debug_MODULES,eng_MODULES,tests_MODULES,modules_to_install,overridden_packages,target_gnu_MODULES,ALL_DEFAULT_INSTALLED_MODULES
12) 包含build/core/Makefile
13) 定义变量modules_to_check
2.5 定义多个目标
这一节定义了众多目标,prebuilt,all_copied_headers,files,checkbuild,ramdisk,factory_ramdisk,factory_bundle,systemtarball,boottarball,userdataimage,userdatatarball,cacheimage,bootimage,droidcore,dist_files,apps_only,all_modules,docs,sdk,lintall,samplecode,findbugs,clean,modules,showcommands,nothing。
后续文章将列出所有可用的目标
3 编译默认目标时的执行流程
在介绍编译默认目标时的执行流程之前,先介绍一下ALL_系列的变量,否则看代码时很难搞懂这些变量的出处,这些变量在包含所有模块后被建立,每个模块都有对应的用于编译的makefile,这些makefile会包含一个编译类型对应的makefile,比如package.mk,而这些makefile最终都会包含base_rules.mk,在base_rules.mk里会为ALL系列变量添加值。所有这些变量及其来源均可在android.cloudchou.com查看详细解释:
- 1) ALL_DOCS所有文档的全路径,ALL_DOCS的赋值在droiddoc.mk里, ALL_DOCS += $(full_target)
- 2) ALL_MODULES系统的所有模块的简单名字集合,编译系统还为每一个模块还定义了其它两个变量,ALL_MODULES.$(LOCAL_MODULE).BUILT 所有模块的生成路径ALL_MODULES.$(LOCAL_MODULE).INSTALLED 所有模块的各自安装路径,详情请见http://android.cloudchou.com/build/core/definitions.php#ALL_MODULES
- 3) ALL_DEFAULT_INSTALLED_MODULES 所有默认要安装的模块,在build/core/main.mk和build/core/makfile里设置
- 4) ALL_MODULE_TAGS 使用LOCAL_MODULE_TAGS定义的所有tag集合,每一个tag对应一个ALL_MODULE_TAGS.变量,详情请见http://android.cloudchou.com/build/core/definitions.php#ALL_MODULE_TAGS
- 5) ALL_MODULE_NAME_TAGS类似于ALL_MODULE_TAGS,但是它的值是 某个tag的所有模块的名称 详情请见http://android.cloudchou.com/build/core/definitions.php#ALL_MODULE_NAME_TAGS
- 6) ALL_HOST_INSTALLED_FILES 安装在pc上的程序集合
- 7) ALL_PREBUILT 将会被拷贝的预编译文件的安装全路径的集合
- 8) ALL_GENERATED_SOURCES 某些工具生成的源代码文件的集合,比如aidl会生成java源代码文件
- 9) ALL_C_CPP_ETC_OBJECTS 所有asm,c,c++,以及lex和yacc生成的c代码文件的全路径
- 10) ALL_ORIGINAL_DYNAMIC_BINARIES 没有被优化,也没有被压缩的动态链接库
- 11) ALL_SDK_FILES 将会放在sdk的文件
- 12) ALL_FINDBUGS_FILES 所有findbugs程序用的xml文件
- 13) ALL_GPL_MODULE_LICENSE_FILES GPL 模块的 许可文件
- 14) ANDROID_RESOURCE_GENERATED_CLASSES Android 资源文件生成的java代码编译后的类的类型
3.1 关键代码
定义默认目标的代码位于main.mk:
1 |
.PHONY: droid |
droid目标依赖的目标有:
1 |
ifneq ($(TARGET_BUILD_APPS),) |
dist_files目标依赖的目标主要是一些用于打包的工具,它们都是用dist-for-goals宏添加依赖关系的:
1 |
$(call dist-for-goals, dist_files, $(EMMA_META_ZIP)) |
我们再看droidcore目标依赖的目标有:
1 |
droidcore: files \ |
system.img, boot.img, recovery.img, data.img,cache.img,installed_files.txt的生成规则在Makefile里定义, 在http://android.cloudchou.com/build/core/Makefile.php里可以看到详细的生成规则 再看一下files目标所依赖的目标:
1 |
files: prebuilt \ |
prebuilt目标依赖$(ALL_PREBUILT),android-info.txt的生成规则在target/board/board.mk里定义,而$(modules_to_install)目标是所有要安装的模块的集合,计算比较复杂,现在以在linux下编译默认目标为例,将涉及到的代码组织如下:
1 |
…… |
【转】Android编译系统详解(三)——编译流程详解的更多相关文章
- unity3d-配置Android环境,打包发布Apk流程详解
31:unity3d-配置Android环境,打包发布Apk流程详解 作者 阿西纳尼 关注 2016.08.28 22:52 字数 498 阅读 1806评论 0喜欢 5 Unity配置Android ...
- linux驱动由浅入深系列:高通sensor架构实例分析之三(adsp上报数据详解、校准流程详解)【转】
本文转载自:https://blog.csdn.net/radianceblau/article/details/76180915 本系列导航: linux驱动由浅入深系列:高通sensor架构实例分 ...
- tp6源码解析-第二天,ThinkPHP6编译模板流程详解,ThinkPHP6模板源码详解
TP6源码解析,ThinkPHP6模板编译流程详解 前言:刚开始写博客.如果觉得本篇文章对您有所帮助.点个赞再走也不迟 模板编译流程,大概是: 先获取到View类实例(依赖注入也好,通过助手函数也好) ...
- Android APK反编译easy 详解
在学习Android开发的过程你,你往往会去借鉴别人的应用是怎么开发的,那些漂亮的动画和精致的布局可能会让你爱不释手,作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用 ...
- Android编译系统详解(一)
++++++++++++++++++++++++++++++++++++++++++ 本文系本站原创,欢迎转载! 转载请注明出处: http://blog.csdn.net/mr_raptor/art ...
- Android 反编译apk 详解
测试环境: win 7 使用工具: CSDN上下载地址: apktool (资源文件获取) 下载 dex2jar(源码文件获取) 下载 jd-gui (源码查看) ...
- Android编译过程详解(一)
Android编译过程详解(一) 注:本文转载自Android编译过程详解(一):http://www.cnblogs.com/mr-raptor/archive/2012/06/07/2540359 ...
- Android 6.0 RK3288 ROM编译详解+命令详解【转】
本文转载自:http://blog.csdn.net/MLQ8087/article/details/58607692 Android 6.0 RK3288 ROM编译详解+命令详解 原创 2017年 ...
- Android 之窗口小部件详解(三) 部分转载
原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...
随机推荐
- 爆牙齿的 Web 标准面试题 【转藏】
<!DOCTYPE html> <html lang="zh-CN"><head> <meta http-equiv="cont ...
- 如何写robots.txt?
robin 发表在 八月 2, 2006 在国内,网站管理者似乎对robots.txt并没有引起多大重视,应一些朋友之请求,今天想通过这篇文章来简单谈一下robots.txt的写作. robots.t ...
- Android 读取txt文件并以utf-8格式转换成字符串
博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 博客园: 追风917 # 使用EncodingUtils 今天用到了城市选择三级联动的库,用的这个:https://gi ...
- Delphi Register
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Form ...
- Codeforces 553C Love Triangles(图论)
Solution: 比较好的图论的题. 要做这一题,首先要分析love关系和hate关系中,love关系具有传递性.更关键的一点,hate关系是不能成奇环的. 看到没有奇环很自然想到二分图的特性. 那 ...
- 引入的iframe是跨域的, 如何控制其高度
前提是你有编辑这个跨域的iframe的权限!! 1. main-domain.html (main display HTML) <!DOCTYPE html> <html> & ...
- php基础知识【函数】(1)数组array
一.排序 1.sort -- 从最低到最高排序,删除原有的键名,赋予新的键名[字母比数字高] 2.rsort -- 逆向排序(最高到最低),删除原有的键名,赋予新的键名[字母比数字高] 3.asort ...
- iOS: performSelectorOnMainThread(译)
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)waitperfor ...
- github基础命令
github被zf断断续续的墙掉,只能多试几次;习惯用svn了,作为git新手,把svn跟git命令对比了一下,瞬间发现好方便记忆了: (1)获取代码仓库克隆:https://github.com/c ...
- ARM的STRB和LDRB指令分析
一.SDRAM 1.存储结构 SDRAM的内部是一个存储阵列.阵列就如同表格一样,将数据“填”进去.在数据读写时和表格的检索原理一样,先指定一个行(Row),再指定一个列 (Column),我们就可以 ...