qcom android bootimage编译脚本分析

android编译系统解析,执行make bootimage后mk文件的调用顺序详解
构成android编译系统的有make文件(makefile,xxxxx.mk),shell脚本,python脚本等
make文件针对三个层次
1,整个编译系统的核心 android/build/core/下,如其中的main.mk文件
2,针对不同厂商不同产品的make文件位于android/device/公司名/产品名/下,如
device\qcom\msm8937_32\Android.mk
device\qcom\msm8937_32\AndroidBoard.mk
device\qcom\msm8937_32\BoardConfig.mk
device\qcom\msm8937_32\msm8937_32.mk
3,每一个模块的make文件。每个模块都有一个总的make文件,名字统一为Android.mk。编译系统会在源码树中扫描执行所哟的Android.mk。
编译整个系统时make文件的调用顺序
1,键入make命令后,编译系统会读取源码树根目录下的Makefile文件,内容如下:
### DO NOT EDIT THIS FILE ###
include build/core/main.mk
### DO NOT EDIT THIS FILE ###
2,Makefile中包含的build/core/main.mk文件才是代码结构的核心。
.PHONY: bootimage
bootimage: $(INSTALLED_BOOTIMAGE_TARGET)
.PHONY: vbmetaimage
vbmetaimage: $(INSTALLED_VBMETAIMAGE_TARGET)
.PHONY: auxiliary
auxiliary: $(INSTALLED_AUX_TARGETS)
# Build files and then package it into the rom formats
.PHONY: droidcore
droidcore: files \
    systemimage \
    $(INSTALLED_BOOTIMAGE_TARGET) \
    $(INSTALLED_RECOVERYIMAGE_TARGET) \
    $(INSTALLED_VBMETAIMAGE_TARGET) \
    $(INSTALLED_USERDATAIMAGE_TARGET) \
    $(INSTALLED_CACHEIMAGE_TARGET) \
    $(INSTALLED_BPTIMAGE_TARGET) \
    $(INSTALLED_VENDORIMAGE_TARGET) \
    $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \
    $(INSTALLED_FILES_FILE) \
    $(INSTALLED_FILES_FILE_VENDOR) \
    $(INSTALLED_FILES_FILE_SYSTEMOTHER)
其中可以看到各种target的编译规则。我们分析一下make bootimage的make文件规则定义过程
执行make bootimage后makefile、xxx.mk文件的调用顺序
1, make bootimage是用来编译内核的命令,其target定义就在build/core/main.mk中
.PHONY: bootimage
bootimage: $(INSTALLED_BOOTIMAGE_TARGET)
build/coremain.mk中包含了build/core中的Makefile文件
BUILD_SYSTEM := $(TOPDIR)build/core
include $(BUILD_SYSTEM)/Makefile
INSTALLED_BOOTIMAGE_TARGET变量的赋值在Makefile文件中
在build/core/Makefile中我们可以看到
INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
2,build/core/Makefile中我们还看到INSTALLED_BOOTIMAGE_TARGET的依赖项
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(BOOT_SIGNER)
    $(call pretty,"Target1 boot image: $@")
    $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
    $(BOOT_SIGNER) /boot $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $@
    $(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE))
其中$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@是关键的编译语句
需要使用$(MKBOOTIMG)工具,针对INTERNAL_BOOTIMAGE_ARGS来生成 bootimage。
3,其中INTERNAL_BOOTIMAGE_ARGS是编译的参数,其赋值也在build/core/Makefile中,如下:
# -----------------------------------------------------------------
# the boot image, which is a collection of other images.
INTERNAL_BOOTIMAGE_ARGS := \
    $(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
    --kernel $(INSTALLED_KERNEL_TARGET)
ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
endif
INTERNAL_BOOTIMAGE_FILES := $(filter-out --%,$(INTERNAL_BOOTIMAGE_ARGS))
ifdef BOARD_KERNEL_BASE
  INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
endif
ifdef BOARD_KERNEL_PAGESIZE
  INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
endif
ifeq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),true)
ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
VERITY_KEYID := veritykeyid=id:`openssl x509 -in $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem -text \
                | grep keyid | sed 's/://g' | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]' | sed 's/keyid//g'`
endif
endif
INTERNAL_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE) buildvariant=$(TARGET_BUILD_VARIANT) $(VERITY_KEYID))
ifdef INTERNAL_KERNEL_CMDLINE
INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(INTERNAL_KERNEL_CMDLINE)"
endif
可以看到我们编译的bootimage包含了几个image:kernel、ramdisk、cmdline、pagesize。我们看其中的kernel的target为INSTALLED_KERNEL_TARGET
INSTALLED_KERNEL_TARGET的定义在本文件中
INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)/kernel
4,要编译INSTALLED_KERNEL_TARGET目标就要有依赖关系,此处寻找依赖关系有些复杂,首先找到相关文件
main.mk文件会搜索并include所有子目录下的Android.mk文件,因此 build/target/board/Android.mk也已经被main.mk所引用
build\target\board\Android.mk
-include $(TARGET_DEVICE_DIR)/AndroidBoard.mk
这里 -include的含义是在include AndroidBoard.mk文件时,遇到错误也不会中断
其中TARGET_DEVICE_DIR定义在build\core\envsetup.mk
TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
board_config_mk变量的定义在本文件中
# Boards may be defined under $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)
# or under vendor/*/$(TARGET_DEVICE).  Search in both places, but
# make sure only one exists.
# Real boards should always be associated with an OEM vendor.
board_config_mk := \
    $(strip $(sort $(wildcard \
        $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
        $(shell test -d device && find -L device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
        $(shell test -d vendor && find -L vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
    )))
上面的脚本会在device,vendor文件夹下寻找在当前项目名文件夹下包含的BoardConfig.mk。我们实例中找到的路径为device\qcom\msm8937_32\AndroidBoard.mk
5,INSTALLED_KERNEL_TARGET这个依赖关系就在这个AndroidBoard.mk文件中
device/qcom/msm8937_32/AndroidBoard.mk
$(INSTALLED_KERNEL_TARGET): $(TARGET_PREBUILT_KERNEL) | $(ACP)
    $(transform-prebuilt-to-target)
6,TARGET_PREBUILT_KERNEL的依赖关系终于在kernel中了
device\qcom\msm8937_32\AndroidBoard.mk会包含kernel下的AndroidKernel.mk
ifeq ($(TARGET_KERNEL_SOURCE),)
     TARGET_KERNEL_SOURCE := kernel
endif
include $(TARGET_KERNEL_SOURCE)/AndroidKernel.mk
kernel\AndroidKernel.mk中如下:
TARGET_PREBUILT_KERNEL := $(TARGET_PREBUILT_INT_KERNEL)
ifeq ($(TARGET_USES_UNCOMPRESSED_KERNEL),true)
$(info Using uncompressed kernel)
TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/Image
else
ifeq ($(KERNEL_ARCH),arm64)
TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/Image.gz
else
TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/zImage
endif
7,AndroidKernel.mk中执行make编译命令就会调用到kernel目录下的Makefile文件
$(KERNEL_OUT):
    mkdir -p $(KERNEL_OUT)
$(KERNEL_CONFIG): $(KERNEL_OUT)
    $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(KERNEL_DEFCONFIG)
    $(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \
            echo "Overriding kernel config with '$(KERNEL_CONFIG_OVERRIDE)'"; \
            echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \
            $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) oldconfig; fi
至此终于走完了make bootimage命令的全过程
————————————————
版权声明:本文为CSDN博主「二进制橙子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/RadianceBlau/article/details/78362426

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值