热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android构建基础流程详解

参考转载:https://blog.csdn.net/xujiaofu6181/article/details/86598988https://blog.csdn.net/Thanksgining

参考转载:
https://blog.csdn.net/xujiaofu6181/article/details/86598988
https://blog.csdn.net/Thanksgining/article/details/83374493
分析 system 生成过程

编译Android系统三部曲:

source build/envsetup.sh lunch full-eng make -j24

make其实就是执行Makefile文件,在没有指定Makefile的情况下,执行当前路径下的Makefile文件。Android系统执行make命令就是source code跟目录下Makefile文件,而此Makefile文件的内容只有一句,include另外一个main.mk文件, 现在android P 上,main.mk 内容比较多,其实流程是一样的

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

根据Makefile书写规则,在main.mk开始不久,就出现了一个droid伪目标,也是默认目标(default target)。这个默认目标是一个伪目标,make工具遇到伪目标以后,会检查解析伪目标的依赖,如果伪目标存在依赖,就会检查这些依赖,如果这些依赖是伪目标,继续检查这个伪目标的依赖,如果不是伪目标,就会生成这个目标。

最终目标droid

默认目标droid依赖于droid_targets,根据build/make/core/main.mk文件可知完整编译Android系统时,droid_targets的依赖于droidcode和dist_files两大伪目标

BUILD_SYSTEM := $(TOPDIR)build/make/core # This is the default target. It must be the first declared target. .PHONY: droid DEFAULT_GOAL := droid $(DEFAULT_GOAL): droid_targets .PHONY: droid_targets droid_targets: # Set up various standard variables based on configuration # and host information. include $(BUILD_SYSTEM)/config.mk droid_targets依赖

根据上面代码可知默认目标droid依赖于droid_targets,根据build/make/core/main.mk文件可知完整编译Android系统时,droid_targets的依赖于droidcode和dist_files两大伪目标.
注意: mk 文件中定义 .PHONY 目标才可以进行,build , 在MK 可以调用shell 脚本

ifneq ($(TARGET_BUILD_APPS),) ...... .PHONY: apps_only apps_only: $(unbundled_build_modules) droid_targets: apps_only ...... else # TARGET_BUILD_APPS ...... # Building a full system-- the default is to build droidcore droid_targets: droidcore dist_files ...... endif # TARGET_BUILD_APPS

android make 基本流程一
图片.png
droid_code依赖

droidcode目标依赖files、systemimage、INSTALLED_BOOTIMAGE_TARGET等目标,dist_files没有看到依赖情况;

# $(INSTALLED_BOOTIMAGE_TARGET)取INSTALLED_BOOTIMAGE_TARGET的环境变量值 # Build files and then package it into the rom formats .PHONY: droidcore droidcore: files systemimage $(INSTALLED_BOOTIMAGE_TARGET) $(MTK_BOOTIMAGE_TARGET) $(INSTALLED_RECOVERYIMAGE_TARGET) $(INSTALLED_VBMETAIMAGE_TARGET) $(INSTALLED_USERDATAIMAGE_TARGET) $(INSTALLED_CACHEIMAGE_TARGET) $(INSTALLED_TRANFSIMAGE_TARGET) $(INSTALLED_BPTIMAGE_TARGET) $(INSTALLED_VENDORIMAGE_TARGET) $(INSTALLED_PRODUCTIMAGE_TARGET) $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) $(INSTALLED_FILES_FILE) $(INSTALLED_FILES_FILE_VENDOR) $(INSTALLED_FILES_FILE_PRODUCT) $(INSTALLED_FILES_FILE_SYSTEMOTHER) soong_docs # dist_files only for putting your library into the dist directory with a full build. .PHONY: dist_files

android make 基本流程一
图片.png
files依赖

files目标依赖modules_to_install和INSTALLED_ANDROID_INFO_TXT_TARGET目标;

# All the droid stuff, in directories .PHONY: files files: $(modules_to_install) $(INSTALLED_ANDROID_INFO_TXT_TARGET) INSTALLED_SYSTEMIMAGE依赖

build/make/core/main.mk文件包含如下.mk和Makefile文件

android make 基本流程一
图片.png

systemimage目标依赖在build/make/core/Makefile中说明,可知systemimage目标依赖INSTALLED_SYSTEMIMAGE目标;INSTALLED_SYSTEMIMAGE赋值为(PRODUCT_OUT)/system.img,即(PRODUCT_OUT)/system.img目标依赖:
-BUILT_SYSTEMIMAGE
-RECOVERY_FROM_BOOT_PATCH

NSTALLED_SYSTEMIMAGE := $(PRODUCT_OUT)/system.img SYSTEMIMAGE_SOURCE_DIR := $(TARGET_OUT) ...... # Rules that need to be present for the all targets, even # if they don't do anything. .PHONY: systemimage systemimage: # build/make/core/config.mk定义了hide := @,即$(hide)表示在命令前加“@” # 在命令前加@表示不回显命令 # call 一个可以用来创建新的参数化的函数 **$(INSTALLED_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE) $(RECOVERY_FROM_BOOT_PATCH)** @echo "Install system fs image: $@" $(copy-file-to-target) $(hide) $(call assert-max-image-size,$@ $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)) systemimage: $(INSTALLED_SYSTEMIMAGE) #QEMU表示软件化模拟器 ifeq ($(BUILD_QEMU_IMAGES),true) ...... systemimage: $(INSTALLED_QEMU_SYSTEMIMAGE) ...... endif

BUILT_SYSTEMIMAGE赋值为$(systemimage_intermediates)/system.img,其依赖:

FULL_SYSTEMIMAGE_DEPS INSTALLED_FILES_FILE BUILD_IMAGE_SRCS

systemimage_intermediates := $(call intermediates-dir-for,PACKAGING,systemimage) BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img ...... $(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE) $(BUILD_IMAGE_SRCS) $(call build-systemimage-target,$@)

目标INSTALLED_SYSTEMIMAGE执行两个动作,分别是:

copy-file-to-target,此命令在build/make/core/definitions.mk文件定义了,可知此命令就是将第一个依赖项拷贝到目标处,即$(PRODUCT_OUT)/system.img是由拷贝$(systemimage_intermediates)/system.img过来的。

# $@ --> 表示目标 # $ 表示第一个依赖项 # mkdir -p --> 可创建多级文件目录 如:mkdir -p a/b/c define copy-file-to-target @mkdir -p $(dir $@) $(hide) rm -f $@ $(hide) cp "$

assert-max-image-size,此命令在build/make/core/definitions.mk文件定义了

# build/make/core/combo/HOST_linux-x86.mk中定义了get_file-size # $(1): The file to check define get-file-size stat --format "%s" "$(1)" | tr -d 'n' endef # build/make/core/definitions.mk # $(1): The file(s) to check (often $@) # $(2): The partition size. define assert-max-image-size $(if $(2), size=$$(for i in $(1); do $(call get-file-size,$$i); echo +; done; echo 0); total=$$(( $$( echo "$$size" ) )); printname=$$(echo -n "$(1)" | tr " " +); maxsize=$$(($(2))); if [ "$$total" -gt "$$maxsize" ]; then echo "error: $$printname too large ($$total > $$maxsize)"; false; elif [ "$$total" -gt $$((maxsize - 32768)) ]; then echo "WARNING: $$printname approaching size limit ($$total now; limit $$maxsize)"; fi , true ) endef

在分析assert-max-image-size之前,先看看RECOVERY_FROM_BOOT_PATCH和BOARD_SYSTEMIMAGE_PARTITION_SIZE

,RECOVERY_FROM_BOOT_PATCH描述的是一个patch文件,这个patch文件的名称为recovery_from_boot.p,保存在设备上system分区中,描述recovery.img与boot.img之间的差异。也就是说,在设备上,可以通过boot.img和recovery_from_boot.p文件生成一个recovery.img文件,使得设备可以进入recovery模式。好比OTA通过recovery_from_boot.p方式升级recovery.img(OTA卡包里面必须要有boot.img、recovery-from-boot.p、install-recovery.sh三个文件缺一不可),在OTA升级完之后,系统重启时会去升级recovery.img(通过boot.img与recovery-from-boot.p生成的)。

RECOVERY_FROM_BOOT_PATCH依赖规则如下:

# The system partition needs room for the recovery image as well. We # now store the recovery image as a binary patch using the boot image # as the source (since they are very similar). Generate the patch so # we can see how big it's going to be, and include that in the system # image size check calculation. ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),) ifneq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true) ifneq (,$(filter true, $(BOARD_BUILD_SYSTEM_ROOT_IMAGE) $(BOARD_INCLUDE_RECOVERY_DTBO))) diff_tool := $(HOST_OUT_EXECUTABLES)/bsdiff else diff_tool := $(HOST_OUT_EXECUTABLES)/imgdiff endif intermediates := $(call intermediates-dir-for,PACKAGING,recovery_patch) RECOVERY_FROM_BOOT_PATCH := $(intermediates)/recovery_from_boot.p $(RECOVERY_FROM_BOOT_PATCH): PRIVATE_DIFF_TOOL := $(diff_tool) $(RECOVERY_FROM_BOOT_PATCH): $(INSTALLED_RECOVERYIMAGE_TARGET) $(INSTALLED_BOOTIMAGE_TARGET) $(diff_tool) @echo "Construct recovery from boot" mkdir -p $(dir $@) $(PRIVATE_DIFF_TOOL) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_RECOVERYIMAGE_TARGET) $@ else # $(BOARD_USES_FULL_RECOVERY_IMAGE) == true RECOVERY_FROM_BOOT_PATCH := $(INSTALLED_RECOVERYIMAGE_TARGET) endif endif

BOARD_SYSTEMIMAGE_PARTITION_SIZE是system分区大小,在对应产品的Makefile文件中定义了

BOARD_SYSTEMIMAGE_PARTITION_SIZE:=838860800

如下操作是将“(PRODUCT_OUT)/system.img recovery-from-boot.p”作为一组参数1,“分区size”作为一组参数$2,传入assert-max-image-size中,再根据assert-max-image-size的定义,我们可知以下操作就是在比较镜像文件总和是否大于分区大小,如果大于允许的最大分区的大小,这里就会报错。因此,assert-max-image-size函数可以理解为检查system.img size的合法性。

$(hide) $(call assert-max-image-size,$@ $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))

通过编译log也可以看到如下信息:

[100% 81510/81510] Install system fs image: out/target/product/${project}/system.img out/target/product/${project}/system.img+out/target/product/${project}/obj/PACKAGING/recovery_patch_intermediates/recovery_from_boot.p maxsize=2415114240 blocksize=4224 total=1860325777 reserve=24397824

至此,$(PRODUCT_OUT)/system.img就生成了


推荐阅读
author-avatar
远处有个蘑菇丶
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有