[Android]基于AOSP源码为Pixel3编译boot.img(中)

[Android]基于AOSP源码为Pixel3编译boot.img(中)

前言

上一节我们提到,本系列主要是要实现将Android Kernel源码并入AOSP源码,使后者的编译框架可以直接从源码编译boot.img这一目标,而改造工作大致需要如下几步:

  1. 下载源码——下载Android Kernel源码;
  2. 编译代码——编译一次,确认环境与代码状态正确;
  3. 代码迁移与合并——将目录结构合入AOSP,并复用AOSP的编译工具链(但此时仍然为独立编译方式,仅仅工具链复用);
  4. 编译规则修改——在AOSP侧编写编译规则,使其可以从源码编译Android Kernel;
  5. 确认产物、刷机验证;

上一节中,我们已经完成上面的步骤1、2、3;

本篇继续从4、5继续;

环境

台式机

Ubuntu16.04

AOSP版本

9.0(android-9.0.0_r46)

内核版本

4.9(android-msm-crosshatch-4.9-pie-qpr2)

Pixel型号

Pixel3 (4GB + 64GB)

正文

编译规则修改

确认当前规则

依旧以Pixel3为例,在原生AOSP的设计中,kernel是以二进制形式保存在device/google/crosshatch-kernel/Image.lz4-dtb,在编译时通过拷贝的形式,重命名,并放置到out/target/product/blueline/kernel

# device/google/crosshatch/device.mk:
...
ifeq ($(TARGET_PREBUILT_KERNEL),)
    LOCAL_KERNEL := device/google/crosshatch-kernel/Image.lz4-dtb
else
    LOCAL_KERNEL := $(TARGET_PREBUILT_KERNEL)
endif
...

PRODUCT_COPY_FILES += \
    $(LOCAL_KERNEL):kernel \
    ...

如果要实现从源码编译出kernel的目标,这部分代码需要去掉;
并且,我们要编写自己的编译规则,来生成out/target/product/blueline/kernel

选定修改方案

要实现上述目标,目前可参考的方案有如下几个:

  1. 参考CAF(CodeAuroraForum, 现更改为:CodeLinaro) 中SDM845(Pixel3 SoC) + Android 9.0的基线上的编译规则编写;
  2. 参考LineageOS 16(Android 9.0)上Pixel3(blueline)对应基线的编译规则编写;
  3. 自行实现:按照编译Android Kernel的命令行添加编译规则;

事实上,前两个方案我也充分评估,甚至尝试过,但是由于各种比较恼人的报错,最终放弃,最终采用方案3来实现;(另外两个方案的评估过程,优劣分析会在下一篇详细介绍,这里为了阅读连贯性,暂不展开)

方案具体实施

确认使用方案3后,我们先来罗列下在当前代码结构下,编译Android Kernel的步骤:

$ source build/envsetup.sh
$ lunch aosp_blueline-userdebug
$ cd kernel/
$ ./build/build.sh
$ cp out/android-msm-bluecross-4.9/dist/*.ko ../out/target/product/blueline/vendor/lib/modules/
$ cp out/android-msm-bluecross-4.9/dist/dtbo.img ../out/target/product/blueline/dtbo.img
$ cp out/android-msm-bluecross-4.9/dist/Image.lz4-dtb ../out/target/product/blueline/kernel
$ cd ../

首先,前两句是不需要的,因为在调用make之前,必然已经执行过了;
其次,由于Makefile是逐行执行的,也就是说每一行的$(PWD)都是不会变的,因此cd kernel/ ./build/build.sh合并为一句命令;
同理,后续拷贝的相对相对路径也需要做相应调整,且最后一句也不需要;

按照这个方向,我们可以编写规则如下:

# 由于打包boot.img明确依赖out/target/product/blueline/kernel,因此需要将其提取成一个目标
# 由于编译Android Kernel最后需要依赖soong_zip,因此需要在此声明依赖;
# 否则new build时可能会出现打包失败的问题(kernel在soong_zip之前编译);
$(PRODUCT_OUT)/kernel: $(SOONG_ZIP)
	@echo "Making kernel"
	# 合并为一行执行
	cd kernel && bash build/build.sh
	# 由于AOSP指定了OUT_DIR(=out),因此目录不再以分支名创建(out/android-msm-bluecross-4.9)
	# 拷贝所有生成的ko文件
	cp kernel/out/dist/*.ko $(TARGET_OUT_VENDOR)/lib/modules/
	# 拷贝dtbo.img文件
	cp kernel/out/dist/dtbo.img $(PRODUCT_OUT)/dtbo.img
	# 拷贝kernel文件
	cp kernel/out/dist/Image.lz4-dtb $(PRODUCT_OUT)/kernel

# 定义一个名为kernel的伪目标,方便通过命令make kernel来快速验证;
.PHONY: kernel
kernel: $(PRODUCT_OUT)/kernel

同时,为了反复快速验证,再创建一个kernelclean来进行重置操作:

.PHONY: kernelclean
kernelclean:
	if [ -f $(PRODUCT_OUT)/dtbo.img ]; then rm $(PRODUCT_OUT)/dtbo.img; fi
	if [ -f $(PRODUCT_OUT)/kernel ]; then rm $(PRODUCT_OUT)/kernel; fi
	if [ -d kernel/out ]; then rm -rf kernel/out; fi
	@echo "kernelclean done"

  1. 新建一个mk文件(随便取,此处以kernel.mk为例),保存上述内容;
  2. kernel.mk放置到可以自动引入的目录下;
    AOSP预定义了一些路径,在编译初期会自动引入,因此放到以下提到的任何目录下均可:
    # build/make/core/Makefile:
    ...
    ifneq ($(dont_bother),true)
    include $(sort $(wildcard $(BUILD_SYSTEM)/tasks/*.mk))
    -include $(sort $(wildcard vendor/*/build/tasks/*.mk))
    -include $(sort $(wildcard device/*/build/tasks/*.mk))
    -include $(sort $(wildcard product/*/build/tasks/*.mk))
    # Also the project-specific tasks
    -include $(sort $(wildcard vendor/*/*6. 去掉/build/tasks/*.mk))
    -include $(sort $(wildcard device/*/*/build/tasks/*.mk))
    -include $(sort $(wildcard product/*/*/build/tasks/*.mk))
    # Also add test specifc tasks
    include $(sort $(wildcard platform_testing/build/tasks/*.mk))
    include $(sort $(wildcard test/vts/tools/build/tasks/*.mk))
    endif
    ...
    
  3. 编译:make kernel

如果你严格按照上述步骤,那么使用make kernel编译成功是必然的,但是为了处理与原生AOSP编译逻辑的冲突,我们还需要修改:

  1. 去掉上面提到的device/google/crosshatch/device.mk中拷贝device/google/crosshatch-kernel/Image.lz4-dtbout/target/product/blueline/kernel的规则;
  2. 去掉device/google/crosshatch/BoardConfig-common.mkBOARD_PREBUILT_DTBOIMAGEBOARD_VENDOR_KERNEL_MODULES两个宏的所有赋值逻辑;
  3. 去掉device/google/crosshatch/AndroidBoard.mkkernel-modules:这个伪目标的定义,已经INSTALLED_KERNEL_MODULESINTERNAL_KERNEL_MODULES的宏定义;

确认产物、刷机验证

编译验证

建议删除out全编译一次,避免一些编译依赖问题在增量编译的环境下被掩盖;
编译成功后则可以进行刷机验证了;

刷机验证

由于AVB的机制,在刷入boot.img的同时,建议同时刷入:

  • vbmeta.img
  • vendor.img
  • dtbo.img

以上步骤都是我实际操作过的,经验证,手机在刷入编译出的product.img/system_other.img/system.img/boot.img/vendor.img/dtbo.img/vbmeta.img后可正常开机,相机、传感器、WLAN、音频均工作正常;

若读者在参考本文操作过程中遇到问题,欢迎留言讨论;

后记

截至目前,我们已经成功实现使用make命令,从源码编译boot.img的目标,但其实仍然存在一定的局限性和优化空间:

  1. 编译依赖kernel/build,生成产物目录与AOSP不相同:目前只是将编译命令脚本化,并没有实现编译环境的完全整合,比较明显的一个现象就是,各自的out目录并不相同;
  2. 编译过程仍然有目录建拷贝的过程:同上,这种拷贝实际上也是没有完全整合的产物;
  3. 编译目标粒度过于粗糙:make kernel只有一个目标,因此在其成功、失败之前,是没有日志输出的;

因此下一篇,会进行编译规则的优化,使其与AOSP实现真正意义上的融合;

同时,会详细讨论下上述提到的其他几家方案实现的优劣;

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值