Android 系统编译

一、流程

根目录下的Makefile--->build/core/main.mk---->build/core/Makefile

1.1 根目录下的Makefile

1
2
3
### DO NOT EDIT THIS FILE ###
include build/core/main.mk
### DO NOT EDIT THIS FILE ###

1.2 main.mk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.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}

定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
.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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.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}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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。

1
2
3
4
5
6
7
8
9
10
11
12
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中有定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.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 

1
2
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

posted @   皓然123  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
历史上的今天:
2023-04-28 Python模块之struct
2023-04-28 为程序添加日志
点击右上角即可分享
微信分享提示