热门标签 | 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就生成了


推荐阅读
  • 通常情况下,修改my.cnf配置文件后需要重启MySQL服务才能使新参数生效。然而,通过特定命令可以在不重启服务的情况下实现配置的即时更新。本文将详细介绍如何在线调整MySQL配置,并验证其有效性。 ... [详细]
  • 对于许多初学者而言,遇到总线错误(bus error)或段错误(segmentation fault/core dump)是极其令人困扰的。本文详细探讨了这两种错误的成因、表现形式及解决方法,并提供了实用的调试技巧。 ... [详细]
  • 主调|大侠_重温C++ ... [详细]
  • 本文探讨了C++编程中理解代码执行期间复杂度的挑战,特别是编译器在程序运行时生成额外指令以确保对象构造、内存管理、类型转换及临时对象创建的安全性。 ... [详细]
  • 本文详细介绍了Java中实现异步调用的多种方式,包括线程创建、Future接口、CompletableFuture类以及Spring框架的@Async注解。通过代码示例和深入解析,帮助读者理解并掌握这些技术。 ... [详细]
  • 本文详细介绍了get和set方法的作用及其在编程中的实现方式,同时探讨了点语法的使用场景。通过具体示例,解释了属性声明与合成存取方法的概念,并补充了相关操作的最佳实践。 ... [详细]
  • Linux中的yum安装软件
    yum俗称大黄狗作用:解决安装软件包的依赖关系当安装依赖关系的软件包时,会将依赖的软件包一起安装。本地yum:需要yum源,光驱挂载。yum源:(刚开始查看yum源中的内容就是上图 ... [详细]
  • 使用Powershell Studio快速构建GUI应用程序
    本文介绍了如何利用Powershell Studio创建功能强大的可视化界面。相较于传统的开发工具,Powershell Studio提供了更为简便和高效的开发体验,尤其适合需要快速构建图形用户界面(GUI)的场景。 ... [详细]
  • 本文详细介绍了一种通过MySQL弱口令漏洞在Windows操作系统上获取SYSTEM权限的方法。该方法涉及使用自定义UDF DLL文件来执行任意命令,从而实现对远程服务器的完全控制。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 本文详细介绍了如何检查和配置电脑上的PHP环境,包括位数、运行支持以及文件格式的打开方式。适合初学者了解PHP的基础知识和操作方法。 ... [详细]
  • 在编译BSP包过程中,遇到了一个与 'gets' 函数相关的编译错误。该问题通常发生在较新的编译环境中,由于 'gets' 函数已被弃用并视为安全漏洞。本文将详细介绍如何通过修改源代码和配置文件来解决这一问题。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • Python自动化测试入门:Selenium环境搭建
    本文详细介绍如何在Python环境中安装和配置Selenium,包括开发工具PyCharm的安装、Python环境的设置以及Selenium包的安装方法。此外,还提供了编写和运行第一个自动化测试脚本的步骤。 ... [详细]
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
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社区 版权所有