Android 源码构建维度
为什么Android源码要引入这样一套构建系统呢?里面涉及几个维度思考:
-
编译核心:编译系统的核心,决定了整个项目的最核心编译规则,定义了编译流程的框架,源码在build/core/目录下
-
模块维度:模块是编译系统的最小的目标单元。Android早期采用Android.mk,其中定义了一个模块的必要参数,使模块跟随平台编译。编译核心要让所有的模块全部include进来。
-
产品维度:出现在build/target/、device/或vendor/目录中。 这部分的主要入口是AndroidProducts.mk文件,功能是指定一些产品独特的内容。 这些额外的组件,会随着编译前lunch PRODUCT的PRODUCT参数而改变。
-
映像维度: Android 源码构建的最终目标是要生成各类映像文件,以便最后刷机使用
Android的编译核心目标
Android默认目标就是droid,droid目标的依赖如下:
Android 编译核心逻辑
这些规则定义在build/core/main.mk里面,主要逻辑包括:
- 定义编译目标product
- 加载config.mk来初始化相关变量,检测编译环境和目标环境
- 清除规则,清除out目录中的dex文件
- 加载build/croe/definitions.mk,定义了很多通用函数,供编译过程调
- 加载平台开发工具包 build/make/core/pdk_config.mk
- 加载系统中所有的Android.mk,最终会被存放到out/.module_paths/Android.mk.list
- Link 类型检查,校验Link
- 要为此产品生成的模块的基本列表由相应的产品定义文件指定,这些定义在"product_config.mk"中
- 运行时APEX库,并进行检查校验
- 将所有要安装的模块都保存在变量ALL_DEFAULT_INSTALLED_MODULES中,并且将build/core/Makefie文件加载进来。build/core/Makefie文件会根据要安装的模块生成system.img、super.img、boot.img和recovery.img等镜像文件的生成规则
- 定义编译的image目标
- 构建文件,然后将其打包成rom格式
Android编译核心文件
Android打包流程
System打包流程
BUILT_SYSTEMIMAGE 最终会把system.img编译到 out/target/product/generic/obj/PACKAGING/systemimage_intermediates/system.img中。
BUILT_SYSTEMIMAGE 依赖于FULL_SYSTEMIMAGE_DEPS、INSTALLED_FILES_FILE和BUILD_IMAGE_SRCS,通过调用 函数build-systemimage-target 来编译systemimage,相关依赖如下所示:
-
BUILD_IMAGE_SRCS 在[/build/make/core/config.mk] 中定义,配置了build/make/tools/releasetools中的python脚本参与编译
BUILD_IMAGE_SRCS := $(wildcard build/make/tools/releasetools/*.py) -
INSTALLED_FILES_FILE 依赖的是文件$(PRODUCT_OUT)/installed-files.txt,这是已安装的文件列表,这些文件要打包到system.img中,他也依赖于FULL_SYSTEMIMAGE_DEPS
-
FULL_SYSTEMIMAGE_DEPS依赖于INTERNAL_SYSTEMIMAGE_FILES 和INTERNAL_USERIMAGES_DEPS,列出了制作system.img所需要的工具和制作system.img所需要的文件。
Android设置编译工具链
加载config.mk来初始化相关变量,检测编译环境和目标环境,加载clang/config.mk,配置一些编译的环境。
include build/make/core/config.mk
…
#加载out/soong/make_vars-aosp_arm.mk
include $(SOONG_MAKEVARS_MK)
#加载clang编译的一些配置
include $(BUILD_SYSTEM)/clang/config.mk
Soong overview
使用方法和以前一样。先引入build/envsetup,sh,然后执行m/mm/mmm等命令。只不过现在的m/mm/mmm命令将调用Soong中的对应工具。
Soong将把.bp文件交给blueprint工具集来处理。blueprint工具集是用go语言写的。官方文档对它的描述是:a meta-build system。输入为.bp文件。输出为.ninja文件
Soong把.mk/Makefile文件交给kati/ckati工具来处理。kati是go语言写的,而ckati是c++写的。kati官方文档对它的描述是:kati is an experimental GNU make clone。也就是说,kati是对等make命令的。只不过kati并不执行具体的编译工作,而是生成ninja文件。
ninja是一个神奇的东西,它是忍者桃太郎的意思。ninja本身不是编译器,它是去调用具体编译器的工具。真正的编译工作还是由编译器来完成,比如gcc,clang,java等。ninja读取的是.ninja结尾的编译配置文件,然后调起对应的编译器。
Make入口 soong_ui.bash
envsetup.sh主要是用于初始化shell环境,使其支持android build系统的特有命令:croot、mgrep、cgrep、m、mm等,和build系统相关的主要是m、mm、mmm、mma、ma、make,尤其是make
当我们执行make,在envsetup.sh初始化后的shell环境中,执行的是function make函数
function make()
{
_wrap_build
(
g
e
t
m
a
k
e
c
o
m
m
a
n
d
"
(get_make_command "
(getmakecommand"@") “[email protected]”
}
这里判断当前make是在build系统根目录下,则执行build/soong/soong_ui.bash --make-mode
注意:这里是echo,使用echo作为get_make_command返回值,我们调用的是make -j8,
此时@就是-j8,经过shell展开处理后_wrap_build(get_make_command "@") "@"展开成了build/soong/soong_ui.bash --make-mode -j8
Android10.0上是通过soong执行编译构建,这里执行make命令时,main.mk文件把一些环境变量和目标都配置好后,会执行envsetup.sh中的make()进行编译。
如果找到“build/soong/soong_ui.bash”,就使用soong_ui.bash 来进行编译,否则使用原始的make命令进行编译。
Soong的编译流程
执行runKatiBuild时,有个重要的步骤,就是加载build/make/core/main.mk,main.mk文件是Android Build系统的主控文件。从main.mk开始,将通过include命令将其所有需要的.mk文件包含进来,最终在内存中形成一个包括所有编译脚本的集合,这个相当于一个巨大Makefile文件。Makefile文件看上去很庞大,其实主要由三种内容构成: 变量定义、函数定义和目标依赖规则,此外mk文件之间的包含也很重要。
编译步骤如下:
-
runMakeProductConfig 主要配置编译参数
-
runSoong 对工具进行编译,编译出blueprint等编译工具, 把*.bp 编译成 out/soong/build.ninja
/.minibootstrap/build.ninja
- Run minibp to generate .bootstrap/build.ninja (Primary stage) - Run minibp to generate .minibootstrap/build.ninja.in
/.bootstrap/build.ninja - Build any bootstrap_go_binary rules and dependencies – usually the primary builder and any build or runtime dependencies. - Run the primary builder to generate build.ninja
-
runKatiBuild, 加载 build/make/core/main.mk, 搜集所有的Android.mk文件生成ninja文件:out/build-aosp_arm.ninja
-
runKatiPackage, 加载build/make/packaging/main.mk, 编译生成out/build-aosp_arm-package.ninja
-
createCombinedBuildNinjaFile,将out/soong/build.ninja 、out/build-aosp_arm.ninja和out/build-aosp_arm-package.ninja, 合成为out/combined-aosp_arm.ninja
-
runNinja,运行Ninja命令, 解析combined-aosp_arm.ninja,执行编译过程
参考:
https://mp.weixin.qq.com/s/pMg0TxGlqAWmZZ5TW-CzWA
https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MjM5NDk5ODQwNA==&action=getalbum&album_id=1552818877435265027&scene=173&from_msgid=2652469359&from_itemidx=1&count=3#wechat_redirect
https://blog.csdn.net/Innost/article/details/103286516
https://blog.csdn.net/Innost/article/details/103519211