Android编译系统
Android编译系统遵循多个设计原则和策略
1、同一套代码支持编译出不同的构建目标。
2、Non-Recursive Make:其核心思想是我们在大型项目中应该采用唯一的Makefile来组织所有文件的自动化编译。
3、可以对项目中的任意模块进行单独的编译验证。
4、编译所产生的中间过程文件,以及最终编译结果和源代码需要在存储目录上分离。
date: 2020年9月14日
author: LRAA
参考资料:《深入理解Android内核设计思想》
Android 编译系统抽象模型
树根节点droid
从Android源码工程的根目录分析起,其下的Makefile文件是其编译系统的起点,它只是一个简单的文件转向,直接引用了另一个Makefile文件(build/core/main.mk)
### DO NOT EDIT THIS FILE ###
CURRENTDIRNAME:=$(shell basename ${PWD})
$(shell unlink ./${CURRENTDIRNAME})
include build/core/main.mk
### DO NOT EDIT THIS FILE ###
- 需要强调的是,编译系统中有不止一棵依赖树存在。比如我们在Android系统下使用“make”和“make sdk”的编译结果会不同,这是因为他们分别执行了两棵不同的依赖树。
- 在没有显示指定编译目标的情况下(直接make 不带参数),第一个符合要求的目标会被Make作为默认依赖的树根节点。所以编写Makefile时注意顺序,不要把clean这些目标放在最前面。
- 原则上Make程序会对makefile中的内容按照顺序进行逐条解析。一个典型的解析过程分为三大步骤:
- 变量赋值、环境监测等初始化操作
- 按照规则生成所有依赖树
- 更具用户选择的依赖树,从叶到根逐步生成目标文件
所以对照main.mk可以很快找出“make”命令对应的依赖树的根节点时droid。
# This is the default target. It must be the first declared target.
.PHONY: droid
DEFAULT_GOAL := droid
$(DEFAULT_GOAL):
main.mk
main.mk有一大半内容是为了完成一下几点
1、对编译坏境的检测,比如java版本、make环境必须高于特定版本等
2、进行一些必要的前期处理,比如清理工作,部分工具安装等
3、引用其他Makefile文件
4、设置全局变量
5、各种函数实现(Android编译系统中定义了不少函数,他们提供了各种问题的通过一解决方案。比如print-vars函数用于打印一串变量列表,my-dir可以知道当前所处的路径等)
主要Makefile文件释义
Name | Description |
---|---|
main.mk | 整个编译系统的主导文件 |
config.mk | 产品配置的主导文件 |
base_rules.mk | 编译系统需要遵循的基础规则定义。 |
build_id.mk | 版本id号的定义 |
cleanbuild.mk | clean操作的定义 |
clear_vars.mk | 清空以LOCAL开头的相关系统变量 |
definitions.mk | 提供了大量使用函数的定义 |
envsetup.mk | 配置编译时的环境变量,注意要与envsetup.sh区分开来 |
executable.mk | 负责BUILD_EXECUTABLE的具体实现 |
java.mk | 负责与java语言相关的编译实现,是java_library.mk的基础 |
host_executable.mk | 负责BUILD_HOST_EXECUTABLE的具体实现 |
host_static_library.mk | 负责BUILD_HOST_STATIC_LIBRARY的具体实现 另外,其他类型的BUILD_XX变量也有对应的Makefile文件实现,不在赘述 |
product_config.mk | 产品级别的配置,属于config的一部分 |
version_defaults.mk | 负责生成版本星系,默认格式为: BUILD_NUMBER:= eng. ( U S E R ) . (USER). (USER).(shell date+%Y%m%d.%H%M%S) |
base_rules.mk:其中最重要的变量之一是ALL_MODULED,它负责将各Android.mk中的LOCAL_MODULE添加到全局依赖树中,从而保证所有的模块都参与到整个系统的编译中。
另外两个起到关键作用的变量是LOCAL_BUILT_MODULE和LOCAL_INSTALLED_MODULE(添加到ALL_MODULES的是my_register_name,而后者则依赖这两个变量),典型的赋值如下:
LOCAL_BUILT_MODULE=out/target/product/generic/obj/JAVA_LIBRARIES/framework_intermediates/javalib.jar
LOCAL_INSTALLED_MODULE=out/target/product/generic/system/framwork/framework.jar