Android 系统编译
一、流程
根目录下的Makefile--->build/core/main.mk---->build/core/Makefile
1.1 根目录下的Makefile
### DO NOT EDIT THIS FILE ### include build/core/main.mk ### DO NOT EDIT THIS FILE ###
1.2 main.mk
.PHONY: droidcore
droidcore:  kernelimage     \
            kernelmodules    \
            bootloader        \
            files            \
            systemimage        \
            $(INSTALLED_BOOTIMAGE_TARGET)    \
            $(INSTALLED_RECOVERY_TARGET)    \
            $(INSTALLED_USRTDATAIAGE_TARGET) \
            $(INSTALLED_CACHEIMAGE_TARGET)    \
            $(INSTALLED_VERDORIMAGE_TARGET)    \
            $(INSTALLED_FILES_FILE)            \
            ubiimagesgenerate
include $(BUILD_SYSTEM)/Makefile
BUILD_SYSTEM := $(TOPDIR)build/core
可以看出,该编译目标为 android的核心编译目标。kernelimage即编译出的目标zImage,systemimage即编译出的system.img。
$(TOPDIR)即为Android源码的根目录。所以就把build/core/Makefile包含进去了。
1.3 build/core/Makefile
这个文件里定义了上文所有的目标
1.3.1 接下来分析目标 kernelimage ⇒ {kernel, dtb}
定义如下:
.PHONY: kernelimage
ifneq    ($(strip $(TARGET_NO_KERNEL)), true)
KERNEL_CROSS_TOOLCHAIN  := `pwd`/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-
KERNEL_CFLAGS             := KCFLAGS=-mno-android
KERNEL_ENV                 := ARCH=arm CROSS_COMPILE=$(KERNEL_CROSS_TOOLCHAIN) LOADADDR=$(LOAD_KERNEL_ENTRY) $(KERNEL_CFLAGS)
HOST_PROCESSOR             := $(shell cat /proc/cpuinfo | grep processor | wc -l)
INSTALLED_KERNEL_TARGET := $(PRODUCT_OUT)kernel
TARGET_PREBUILT_KERNEL  := $(PRODUCT_OUT)kernel
KERNEL_CONFIGURE           := kernel_imx/.config
TARGET_KERNEL_CONFIGURE := $(PRODUCT_OUT)/.config
KERNEL_ZMAGE             := kernel_imx/arch/arm/boot/zImage
KERNEL_OUT                :=$(TARGET_OUT_INTERMEDIATES/KERNEL_OBJ
.PHONY: $(TARGET_PREBUILT_KERNEL)    
kernel.image:    $(TARGET_PREBUILT_KERNEL)
# 默认的内核配置文件
$(KERNEL_CONFIGURE): kernel_imx/arch/arm/configs/$(TARGET_KERNEL_DEFCONF)
# 配置内核
$(TARGET_KERNEL_CONFIGURE): kernel_imx/arch/arm/configs/$(TARGET_KERNEL_DEFCONF) $(KERNEL_CONFIGURE)
        $(MAKE)    -C kernel_imx $(TARGET_KERNEL_DEFCONF) $(KERNEL_ENV)
        install -D $(KERNEL_CONFIGURE) $(TARGET_KERNEL_CONFIGURE)
# 编译uImage 和 dtb,并安装到指定的目录
$(TARGET_PREBUILT_KERNEL): $(TARGET_KERNEL_CONFIGURE)
        $(MAKE) -C kernel_imx -j$(HOST_PROCESSOR) uImage $(KERNEL_ENV)
        $(MAKE) -C kernel_imx    dtbs $(KERNEL_ENV)
        install -D $(KERNEL_ZIMAGE)     $(PRODUCT_OUT)/kernel
        for dtsplat in $(TARGET_BOARD_DTS_CONFIG); do           \
                DTS_PLATFORM=`echo $$dtsplat | cut -d':' -f1`; \
                DTS_BOARD=`echo $$dtsplat | cut -d':' -f2`;        \
                install -D kernel_imx/arch/arm/boot/dts/$$DTS_BOARD $(PRODUCT_OUT)/$$DTS_BOARD; \
        done
else
kernelimage:
endif
整体过程就是配置交叉编译链,默认的配置文件,内核和设备树的输出目录和其他参数。这里用到了make 的 -C 参数,指定编译的源码路径编译。
1.3.2 kernelmodules
.PHONY:    kernelmodules
kernel_modules_src_list :=
kernel_modules_dist_list :=
$(foreach cf, $(TARGET_KERNEL_MODULES),        \
$(eval _src := $(call word-colon,1,$(cf)))    \
$(eval _dest := $(call word-colon,2,$(cf)))    \
$(eval kernel_modules_src_list    += $(_src)) \
$(eval kernel_modules_dest_list    += $(call append-path, $(PRODUCT_OUT), $(_dest))))
ifneq ($(strip $(kernel_modules_src_list)),)
# 编译模块,并拷贝到指定的目录
kernelmodules:    $(TARGET_PREBUILT_KERNEL) | $(ACP)
        $(MAKE) -C kernel_imx modules $(KERNEL_ENV)
        $(hide) $(foreach cf, $(TARGET_KERNEL_MODULES),        \
        $(eval _src := $(call word-colon,1,$(cf)))            \
        $(eval _dest := $(call word-colon,2,$(cf)))            \
        $(eval _full_dest := $(call append-path, $(PRODUCT_OUT), $(_dest))) \
        $(eval _dest_dir  := $(call dir, $(_full_dest)))
        mkdir -p $(_dest_dir)                                \
        $(ACP) $(_src) $(_full_dest);                        \
        )
        @echo "install kernel modules: $(kernel_modules_src_list)"
else
kernelmodules:
endif
1.3.3 目标 $(INSTALLED_BOOTIMAGE_TARGET) ==> boot.img
==> {kernel, dtb, ramdisk}
ifneq ($(strip $(TARGET_NO_KERNEL)), true)
# 编译boot.img的参数
INTERNAL_BOOTIMAGE_ARGS :=    \
        $(addprefix --second , $(INSTALLED_2NDBOOTLOADER_TARGET))    \
        --kernel $(INSTALLED_KERNEL_TARGET)
# ramdisk 参数
ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE), true)
INTERNAL_BOOTIMAGE_ARGS += --ramdisk $(INSTALLED_RAMDISK_TARGET)
endif
INTERNAL_BOOTIMAGE_FILLES := $(filter-out --%, $(INTERNAL_BOOTIMAGE_ARGS))
# cmdline 参数
BOARD_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
ifdef BOARD_KERNEL_CMDLINE
    INTERNAL_BOOTIMAGE_ARGS += --cmdline "$(BOARD_KERNEL_CMDLINE)"
endif
# base ?
BOARD_KERNEL_BASE := $(strip $(BOARD_KERNEL_BASE))
ifdef BOARD_KERNEL_BASE
    INTERNAL_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
endif 
# 页大小的参数
BOARD_KERNEL_PAGESIZE := $(strip $(BOARD_KERNEL_PAGESIZE))
ifdef BOARD_KERNEL_PAGESIZE
    INTERNAL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
endif
# 生成目标的完整路径文件名
INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
ifeq ($(TARGET_BOOTIMAGE_USE_EXT2),true)
$(error TARGET_BOOTIMAGE_USE_EXT2 is not supports anymore)
else ifeq (true, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER))
# 此处省略部分源码 本平台没用到
.....
else ifeq (true, $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT))
# 此处省略部分源码 本平台没用到
.....
else 
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES)
        $(call pretty, "Target boot image: $@")
        for dtsplat in $(TARGET_BOARD_DTS_CONFIG); do     \
            DTS_PLATFORM=`echo $$dtsplat | cut =d':' -f1`; \
            DTS_BOARD=`echo $$dtsplat | cut =d':' -f2`; \
            BOOT_IMAGE_BOATD=$(patsubst %.img,%-$$DTS_PLATFORM.img,$@);    \
            $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) --second $(PRODUCT_OUT)/$$DTS_BOARD $(BOARD_MKBOOTIMG_ARGS) --output $@;    \
            cp  -f $@ $$BOOT_IMGAE_BOARD;    \
        done
.PHONY:    bootimage-nodeps
bootimage-nodeps: $(MKBOOTIMG)
        @echo "make $@: ignoring dependencies"
        $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET)
        $(hide) $(call assert-max-image-size, $(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
endif
1.3.4 ramdisk 是如何生成的?
跟踪 $(INSTALLED_BOOTIMAGE_TARGET)的依赖 $(INTERNAL_BOOTIMAGE_FILES)
$(INTERNAL_BOOTIMAGE_FILES) := $(filter-out --%, $(INTERNAL_BOOTIMAGE_ARGS))
然后有一句:
$(INTERNAL_BOOTIMAGE_ARGS) += --ramdisk $(INSTALLED_RAMDISK_TARGET)
所以 $(INSTALLED_RAMDISK_TARGET)会生成ramdisk。
INTERNAL_RAMDISK_FILES := $(filter $(TARGET_ROOT_OUT)/%, \
        $(ALL_PREBUILT)        \
        $(ALL_COPIED_HEADERS)    \
        $(ALL_GENERATED_SOURCES)    \
        $(ALL_DEFAULT_INSTALLED_MODULES))
            
BUILT_RAMDISK_TARGET := $(PRODUCT_OUT)/ramdisk.img
INSTALLED_RAMDISK_TARGET := $(BUILT_RAMDISK_TARGET)
$(INSTALLED_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_RAMDISK_FILES) | $(MINIGZIP)
        $(call pretty, "Target ram disk: $@")
        $(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_ROOT_OUT) | $(MINIGZIP) > $(INSTALLED_RAMDISK_TARGET)
1.3.5 目标 bootloader
即uboot的生成规则。
bootloader的生成规则相对比较简单,配置好交叉编译器,通过make **defconfig 配置源码,然后 make 就可以,接下来看Makefile:
build/core/main.mk的默认目标droidcore中包含了 bootloader目标,bootloader目标在build/core/Makefile中有定义:
.PHONY: bootloader
ifneq ($(strip $(TARGET_BOOTLOADER_CONFIG)),)
BOOTLOADER_CROSS_TOOLCHAIN := `pwd`/prebuilts/gcc/linux-x86/arm/arm-linux-androideaib-4.9/bin/arm-linux
BOOTLOADER_ENV    := ARCH=arm CROSS_COMPILE=$(BOOTLOADER_CROSS_TOOLCHAIN)
HOST_PROCESSOR  := $(shell cat /proc/cpuinfo | grep processor | wc -l)
TARGET_BOOTLODAER_IMAGE := $(PRODUCT_OUT)/u-boot.imx
BOOTLOADER_PATH := bootable/bootloader/uboot/
bootloader: $(TARGET_BOOTLOADER_IMAGE)
.PHONY    $(TARGET_BOOTLOADER_IMAGE)
$(TARGET_BOOTLOADER_IMAGE):
        for ubootplat in $(TARGET_BOOTLOADER_CONFIG); do    \
            UBOOT_PLATFORM=`echo $$ubootplat | cut -d':' -f1`;    \
            UBOOT_CONFIG=`echo $$ubootplat | cut -d':' -f2`;    \
            $(MAKE) -C    $(BOOTLOADER_PATH) distclean $(BOOTLOADER_ENV);    \
            $(MAKE) -C    $(BOOTLOADER_PATH) $$UBOOT_CONFIG $(BOOTLOADER_ENV);    \
            $(MAKE) -C    $(BOOTLOADER_PATH) $(BOOTLOADER_ENV);    \
            install -D    $(BOOTLOADER_PATH)/u-boot.imx $(PRODUCT_OUT)/u-boot-$$UBOOT_PLATFORM.imx;     \
            install -D    $(BOOTLOADER_PATH)/u-boot.imx $@;     \
        done
else
bootloader:
endif
二、编译运用
2.1 单独编译
我们要单独编译的时候,就可以在build 目录下搜索:grep -r "PHONY:" -n
这样就可以列出所有目标的定义。比如:.PHONY: recoveryimage
我就可以通过 make recoveryimage 来编译recovery.img,同时也可以查看recovery.img 在生成时要依赖哪些?编译过程是什么等?
2.2 lk的编译
我们通过上面的方式,找不到lk的定义,但是我们又可以通过make lk 来进行编译lk.bin呢?
因为,lk 这种不属于AOSP 的范畴了,所有它的定义是在:vendor/mediatek/proprietary/bootable/bootloader/lk/Android.mk
44 .PHONY: lk check-lk-config check-mtk-config include $(LOCAL_PATH)/build_lk.mk
需要在不同的平台下去找,Android 编译的时候会扫描mk文件,从而将lk 的目标添加到系统,这样我们就可以通过make lk的方式来编译lk 了。
参考连接:https://blog.csdn.net/qq_29897125/article/details/108880883
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号