关于 kernel 的构建

include kernel

增量编译,这个 device/qcom/kernelscripts/buildkernel.sh 好像每次都会执行,如果去掉这个编译会节省不少时间。大概节省30分钟。

在 device/zzzz/sa8295_xxxx/AndroidBoard.mk 中 include 这个 msmnile_gvmq 下面的 AndroidBoard.mk

在 device/qcom/msmnile_gvmq/AndroidBoard.mk 中 include 这个 kernel_definitions.mk 文件

调用 build-kernel

在 device/qcom/kernelscripts/kernel_definitions.mk 中有调用 build-kernel

1
2
3
$(TARGET_PREBUILT_KERNEL): $(KERNEL_OUT) $(DTC) $(KERNEL_USR)
echo "Building the requested kernel.."; \
$(call build-kernel,$(KERNEL_DEFCONFIG),$(KERNEL_OUT),$(KERNEL_MODULES_OUT),$(KERNEL_HEADERS_INSTALL),0,$(TARGET_PREBUILT_INT_KERNEL))

TARGET_PREBUILT_KERNEL 目标 就是编译 内核的。里面调用了那个 buildkernel.sh

定义 build-kernel

脚本在 build-kernel 中 调用 这个 device/qcom/kernelscripts/buildkernel.sh 脚本

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

# Build the kernel
# $(1): KERNEL_DEFCONFIG to build for
# $(2): KERNEL_OUT directory
# $(3): KERNEL_MODULES_OUT directory
# $(4): KERNEL_HEADERS_INSTALL directory
# $(5): HEADERS_INSTALL; If 1, the call would just generate the headers and quit
# $(6): TARGET_PREBUILT_INT_KERNEL: The location to the kernel's binary format (Image, zImage, and so on)
define build-kernel
KERNEL_DIR=$(TARGET_KERNEL_SOURCE) \
DEFCONFIG=$(1) \
OUT_DIR=$(2) \
MAKE_PATH=$(MAKE_PATH)\
ARCH=$(KERNEL_ARCH) \
CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) \
KERNEL_MODULES_OUT=$(3) \
KERNEL_HEADERS_INSTALL=$(4) \
HEADERS_INSTALL=$(5) \
TARGET_PREBUILT_INT_KERNEL=$(6) \
TARGET_INCLUDES=$(TARGET_KERNEL_MAKE_CFLAGS) \
TARGET_LINCLUDES=$(TARGET_KERNEL_MAKE_LDFLAGS) \
VENDOR_KERNEL_MODULES_ARCHIVE=$(VENDOR_KERNEL_MODULES_ARCHIVE) \
VENDOR_RAMDISK_KERNEL_MODULES_ARCHIVE=$(VENDOR_RAMDISK_KERNEL_MODULES_ARCHIVE) \
VENDOR_RAMDISK_KERNEL_MODULES="$(VENDOR_RAMDISK_KERNEL_MODULES)" \
TARGET_PRODUCT=$(TARGET_BOARD_PLATFORM) \
device/qcom/kernelscripts/buildkernel.sh \
$(real_cc) \
$(TARGET_KERNEL_MAKE_ENV)
endef
```

## 调用日志
相关的编译进程信息如下

```bash
bash,2256375 -c
echo "Building the requested kernel..";
\011\011 # 这2个字符不知道哪里打印出来的????? 这2个字符是 tab 键, 一个在 define build-kernel 中引入的,一个在 $(call build-kernel) 引入的。
KERNEL_DIR=kernel/msm-5.4
DEFCONFIG=vendor/autogvm-qgki-debug_defconfig
OUT_DIR=out/target/product/sa8295_xxxx/obj/kernel/msm-5.4
MAKE_PATH=./prebuilts/build-tools/linux-x86/bin/
ARCH=arm64
CROSS_COMPILE=./prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-
KERNEL_MODULES_OUT=out/target/product/msmnile_gvmq/dlkm/lib/modules
KERNEL_HEADERS_INSTALL=out/target/product/sa8295_xxxx/obj/kernel/msm-5.4/usr
HEADERS_INSTALL=0
TARGET_PREBUILT_INT_KERNEL=out/target/product/sa8295_xxxx/obj/kernel/msm-5.4/arch/arm64/boot/Image
TARGET_INCLUDES="-I.kernel/msm-5.4/include/uapi -I/usr/include -I/usr/include/x86_64-linux-gnu -I.kernel/msm-5.4/include -L/usr/lib -L/usr/lib/x86_64-linux-gnu -fuse-ld=lld" TARGET_LINCLUDES="-L/usr/lib -L/usr/lib/x86_64-linux-gnu -fuse-ld=lld"
VENDOR_KERNEL_MODULES_ARCHIVE=vendor_modules.zip
VENDOR_RAMDISK_KERNEL_MODULES_ARCHIVE=
VENDOR_RAMDISK_KERNEL_MODULES=""
TARGET_PRODUCT=msmnile
device/qcom/kernelscripts/buildkernel.sh # 执行这个脚本,前面的是定义的变量
REAL_CC=./prebuilts/clang/host/linux-x86/clang-r416183b/bin/clang
CLANG_TRIPLE=aarch64-linux-gnu-
AR=./prebuilts/clang/host/linux-x86/clang-r416183b/bin/llvm-ar
LLVM_NM=./prebuilts/clang/host/linux-x86/clang-r416183b/bin/llvm-nm
LD=./prebuilts/clang/host/linux-x86/clang-r416183b/bin/ld.lld
NM=./prebuilts/clang/host/linux-x86/clang-r416183b/bin/llvm-nm
DTC_EXT=./out/host/linux-x86/bin/dtc
DTC_OVERLAY_TEST_EXT=./out/host/linux-x86/bin/ufdt_apply_overlay
CONFIG_BUILD_ARM64_DT_OVERLAY=y
HOSTCC=./prebuilts/clang/host/linux-x86/clang-r416183b1/bin/clang
HOSTAR=./prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/bin/x86_64-linux-ar
HOSTLD=./prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/bin/x86_64-linux-ld
M4=./prebuilts/build-tools/linux-x86/bin/m4
LEX=./prebuilts/build-tools/linux-x86/bin/flex
YACC=./prebuilts/build-tools/linux-x86/bin/bison

关于 \011\011 这2个诡异的符号

1
2
3
$(TARGET_PREBUILT_KERNEL): $(KERNEL_OUT) $(DTC) $(KERNEL_USR)↵
→ echo "Building the requested kernel.."; \↵
→ $(call build-kernel,$(KERNEL_DEFCONFIG),$(KERNEL_OUT),$(KERNEL_MODULES_OUT),$(KERNEL_HEADERS_INSTALL),0,$(TARGET_PREBUILT_INT_KERNEL))↵

把 echo 那一行的 结尾的 \ 去掉就能 消除 \011 这个符号的引入。

1
2
3
$(TARGET_PREBUILT_KERNEL): $(KERNEL_OUT) $(DTC) $(KERNEL_USR)↵
→ echo "Building the requested kernel.."↵
→ $(call build-kernel,$(KERNEL_DEFCONFIG),$(KERNEL_OUT),$(KERNEL_MODULES_OUT),$(KERNEL_HEADERS_INSTALL),0,$(TARGET_PREBUILT_INT_KERNEL))↵

去掉后会变成如下的 调用方式:

1
2
3
4
5
6
bash,809616 -c 
(echo "Building the requested kernel.." ) &&
(KERNEL_DIR=kernel/msm-5.4

....省略后续的

去掉前是如下的 调用方式:

1
2
3
4
5
6
7
bash,2256375 -c 
echo "Building the requested kernel..";
\011\011
KERNEL_DIR=kernel/msm-5.4

....省略后续的

问题1,到底哪个依赖让TARGET_PREBUILT_KERNEL这个目标执行了呢?

思路 1

到底 哪个 依赖 让 TARGET_PREBUILT_KERNEL 这个目标执行了呢???

我们最开始执行的是make命令,默认目标是 droid ???

先分析 device/qcom/kernelscripts/kernel_definitions.mk 文件里面 对 TARGET_PREBUILT_KERNEL 的依赖目标

1
2
3
4
5
6
7
8
9
10
11
ifeq ($(TARGET_PREBUILT_KERNEL),)                                                        这里说明没定义这个,才会进入到这个文件里面,这里就会重新定义。

TARGET_PREBUILT_KERNEL := $(TARGET_PREBUILT_INT_KERNEL) 这里是给这边目标变量赋值,是一个路径 out/target/product/sa8295_xxxx/obj/kernel/msm-5.4/arch/arm64/boot/Image

$(BOARD_VENDOR_KERNEL_MODULES_ARCHIVE): $(TARGET_PREBUILT_KERNEL) 定义依赖编译内核目标的, 这个目标没找到被其他所依赖!!!
$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_ARCHIVE): $(TARGET_PREBUILT_KERNEL) 定义依赖编译内核目标的, 这个目标没找到被其他所依赖!!!
$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_ARCHIVE): $(TARGET_PREBUILT_KERNEL) 定义依赖编译内核目标的, 这个目标没找到被其他所依赖!!!
$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES): $(TARGET_PREBUILT_KERNEL) 定义依赖编译内核目标的
$(INSTALLED_KERNEL_TARGET): $(TARGET_PREBUILT_KERNEL) $(GKI_TARGET_PREBUILT_KERNEL) 定义依赖编译内核目标的, 最终发现 还是 从这里进入的!!!!!!!!!!!

$(TARGET_PREBUILT_KERNEL): $(KERNEL_OUT) $(DTC) $(KERNEL_USR) 定义这个目标依赖

后来偶然发现:

怎么发现的,也是偶然发现的, TARGET_PREBUILT_KERNEL 这一个文件,是一个变量,值是 out/target/product/sa8295_xxxx/obj/kernel/msm-5.4/arch/arm64/boot/Image,然后就随便改名了一下。
改名后就报错了,然后尝试解决报错。需要把 myimage 文件从原来的位置复制一个,不能随便新建个空文件,不然后续的 check_vintf、build/make/tools/extract_kernel.py 什么的检查会报错的。

发现里面的 cp 动作 和 $(INSTALLED_KERNEL_TARGET) 下面定义的 一致!!!

尝试改名的一个报错信息如下:

1
2
3
4
5
6
7
8
9
10
11
12

[sa8295_xxxx-userdebug][ 86% 447/518]FAILED: out/target/product/sa8295_xxxx/kernel
[sa8295_xxxx-userdebug][ 86% 447/518]/bin/bash -c "(
cp out/target/product/sa8295_xxxx/obj/kernel/msm-5.4/arch/arm64/boot/myimage out/target/product/sa8295_xxxx/kernel ) && (
if [ ! -z \"\" ]; then
cp out/target/product/sa8295_xxxx/kernel-gki;
fi ) && (
touch out/target/product/sa8295_xxxx/obj/KERNEL_OBJ/usr -r out/target/product/sa8295_xxxx/obj/kernelusr.time
)"
[sa8295_xxxx-userdebug][ 86% 447/518]cp: bad 'out/target/product/sa8295_xxxx/obj/kernel/msm-5.4/arch/arm64/boot/myimage': No such file or directory
[sa8295_xxxx-userdebug][ 86% 447/518]

$(INSTALLED_KERNEL_TARGET) 依赖这个 TARGET_PREBUILT_KERNEL 在 kernel_definitions.mk 文件中

1
2
3
4
5
6
$(INSTALLED_KERNEL_TARGET): $(TARGET_PREBUILT_KERNEL) $(GKI_TARGET_PREBUILT_KERNEL)
cp $(TARGET_PREBUILT_KERNEL) $(PRODUCT_OUT)/kernel
if [ ! -z "$(GKI_TARGET_PREBUILT_KERNEL)" ]; then \
cp $(GKI_TARGET_PREBUILT_KERNEL) $(PRODUCT_OUT)/kernel-gki; \
fi
touch $(KERNEL_USR) -r $(KERNEL_USR_TS)

INSTALLED_KERNEL_TARGET 这个也是个变量,一个文件路径 值是 out/target/product/sa8295_xxxx/kernel 。

$(INSTALLED_KERNEL_TARGET) 依赖这个 TARGET_PREBUILT_KERNEL 在 msmnile_gvmq/AndroidBoard.mk 文件中 。

1
2
$(INSTALLED_KERNEL_TARGET): $(TARGET_PREBUILT_KERNEL) | $(ACP)
$(transform-prebuilt-to-target)

重要重要: makefile中同名目标会被后面的覆盖,只是下面的命令部分被覆盖掉,目标后面的依赖会合并到一起。

尝试 把  INSTALLED_KERNEL_TARGET 目标名称改掉,发现 也会调用编译内核的脚本。。。
到底 哪个 依赖 让 TARGET_PREBUILT_KERNEL 这个目标执行了呢??? 我们最开始执行的是make命令,默认目标是 droid ???
还需要继续查找 谁 依赖 TARGET_PREBUILT_KERNEL 这个,让这个目标进行编译构建了!!!!!!!!!!!

重要重要: TARGET_PREBUILT_KERNEL 目标的更新 会导致 INSTALLED_KERNEL_TARGET 目标执行。

思路 2

现在切换思路,不去看冒号前面的,要看 冒号好后面的 依赖部分了,依赖部分更新的话也会导致 内核被编译。

1
2
3
$(TARGET_PREBUILT_KERNEL): $(KERNEL_OUT) $(DTC) $(KERNEL_USR)
echo "Building the requested kernel.."; \
$(call build-kernel,$(KERNEL_DEFCONFIG),$(KERNEL_OUT),$(KERNEL_MODULES_OUT),$(KERNEL_HEADERS_INSTALL),0,$(TARGET_PREBUILT_INT_KERNEL))
1
2
3
4
5
1️⃣KERNEL_OUT=out/target/product/sa8295_xxxx/obj/kernel/msm-5.4  		这是一个目录   

2️⃣DTC=out/host/linux-x86/bin/dtc 这是一个 可执行命令

3️⃣KERNEL_USR=out/target/product/sa8295_xxxx/obj/KERNEL_OBJ/usr=" 这是一个目录

去掉后面 这几个 $(KERNEL_OUT) $(DTC) $(KERNEL_USR) 依赖 发现 内核不会被编译了!!!!

Building the kernel as part of the platform build?

https://groups.google.com/g/android-building/c/7xTXJ480MO8