Android Kernel源码不随AOSP一同释放,后者通常内置的是kernel及其相关模块的ko二进制文件,若想修改相关部分,并完成编译,则需要按照如下步骤实现:
这一套步骤非常冗长,且需要来回切换目录,拷贝文件,因此如果可以像SoC厂商释放的基线一样,将内核源码内置到AOSP源码树中,一次编译即可生成正确产物,那么调试效率可以大幅提升;
要将Android Kernel源码并入AOSP源码,使后者的编译框架可以直接从源码编译boot.img,大致需要如下几步:
本部分较为冗长,故而分为三部分进行阐述,这一部分介绍上面的步骤1、2、3;
Ubuntu16.04
9.0(android-9.0.0_r46)
4.9(android-msm-crosshatch-4.9-pie-qpr2)
Pixel3 (4GB + 64GB)
与AOSP源码树不同,Android Kernel部分代码下载参考地址是这里;
其中针对的Pixel3的分支为android-msm-crosshatch-4.9-android12
但是由于我们AOSP版本仍然停留在9.0(android-9.0.0_r46),因此使用Android 12的内核源码必然是不合适的;
那么我们需要来确认下,repo manifest提供了哪些分支:
# 首先我们将manifest下载下来
$ mkdir android-kernel
$ cd android-kernel/
# 暂不指定分支名,init会失败,但不影响我们获取分支列表
$ repo init -u https://android.googlesource.com/kernel/manifest
# 进入manifest的仓库
$ cd .repo/manifests.git/
# fetch下完整分支信息
$ git fetch origin
# 查看所有分支
$ git branch -a
结果很多,这里我们根据分支明明规则,使用如下关键字过滤:
$ git branch -a | grep android-msm-crosshatch-4.9
remotes/origin/android-msm-crosshatch-4.9-android10
remotes/origin/android-msm-crosshatch-4.9-android10-qpr1
remotes/origin/android-msm-crosshatch-4.9-android10-qpr3
remotes/origin/android-msm-crosshatch-4.9-android11
remotes/origin/android-msm-crosshatch-4.9-android11-qpr2
remotes/origin/android-msm-crosshatch-4.9-android11-qpr3
remotes/origin/android-msm-crosshatch-4.9-android12
remotes/origin/android-msm-crosshatch-4.9-pie-qpr1
remotes/origin/android-msm-crosshatch-4.9-pie-qpr2
可见android-msm-crosshatch-4.9-pie-qpr2
是Android 9.0
下,Pixel3设备所支持的最新的一个分支;
于是我们退回repo根目录,再次init(不需要删除.repo):
¥ cd ../../
# 建议添加--depth=1,减少下载量,缩短下载时间
$ repo init -u https://android.googlesource.com/kernel/manifest -b android-msm-crosshatch-4.9-pie-qpr2 --depth=1
# 看到如下信息即表示init成功
Your identity is: xxx <yyy>
If you want to change this, please re-run 'repo init' with --config-name
repo has been initialized in /zzz/android-kernel/
If this is not the directory in which you want to initialize repo, please run:
rm -r /zzz/android-kernel//.repo
and try again.
# 同步代码
$ repo sync -c --no-tags -j8
为了确保整合之前的代码是没有问题的,这里需要先对下载下来的代码进行一次编译;
在编译之前,强烈建议在AOSP的代码环境中进行一次lunch
操作:
$ source build/envsetup.sh
$ lunch aosp_blueline-userdebug
这么做的目的是使用AOSP的工具链,避免由于Ubuntu环境中缺少编译需要的工具链导致编译失败;
然后,按照官网建议,执行:
$ ./build/build.sh
开始编译。
然后喜闻乐见的失败了:
Makefile:152: recipe for target 'sub-make' failed
make[1]: *** [sub-make] Error 2
Makefile:24: recipe for target '__sub-make' failed
make: *** [__sub-make] Error 2
向上搜索Error
(Error
末尾有一个空格)字样,可以看到类似如下的报错:
aarch64-linux-android-ld.gold: error: LLVMgold.so: could not load plugin library: LLVMgold.so: cannot open shared object file: No such file or directory
/xxx/android-kernel/private/msm-google/scripts/Makefile.build:591: recipe for target 'lib/lib-ksyms.o' failed
make[3]: *** [lib/lib-ksyms.o] Error 1
/xxx/android-kernel/private/msm-google/Makefile:1118: recipe for target 'lib' failed
网上搜一下,可以发现很多解释,但是不一定能找到解决该问题的方案;
为了节约时间,这里直接放结论——build仓库代码进度与源码仓库(private/msm-google)不同步导致。
解决方案也很简单(三选一):
build
仓库切换到aosp/android-msm-bluecross-4.9-pie-qpr1
分支;build
仓库的分支,但是注释掉其中_setup_env.sh
文件中unset LD_LIBRARY_PATH
这一句代码;build.config.no-cfi
,而不是build.config.common.clang
,且不覆写POST_DEFCONFIG_CMDS
变量:KERNEL_DIR=private/msm-google
UNSTRIPPED_MODULES="
wlan.ko
"
# Modified @{
. ${ROOT_DIR}/${KERNEL_DIR}/build.config.no-cfi
# Original Code:
# . ${ROOT_DIR}/${KERNEL_DIR}/build.config.common.clang
# POST_DEFCONFIG_CMDS="check_defconfig"
# @}
为了确认我们上述三种方案修改后编译的产物依旧是可用的,我们可以将编译产物拷贝回AOSP打包刷机验证以下:
这里我就以方案3为例,如果使用其他方案出现问题,可留言再讨论;
$ cp out/android-msm-bluecross-4.9/dist/*.ko ~/aosp/device/google/crosshatch-kernel/
$ cp out/android-msm-bluecross-4.9/dist/dtbo.img ~/aosp/device/google/crosshatch-kernel/dtbo.img
$ cp out/android-msm-bluecross-4.9/dist/Image.lz4-dtb ~/aosp/device/google/crosshatch-kernel/Image.lz4-dtb
$ cp out/android-msm-bluecross-4.9/dist/unstripped/wlan.ko ~/aosp/device/google/crosshatch-kernel/unstripped/wlan.ko
然后回到AOSP侧,运行:
$ cd ~/aosp/
# 由于编译Android Kernel之前已经lunch过,所以这里可以直接make
# 否则需要依次执行source build/envsetup.sh && lunch aosp_blueline-userdebug
$ make bootimage
编译完成后刷机验证,功能正常;
于是我们可以开始着手将这套代码迁移到AOSP中了;
这一步很简单,将Android Kernel中.repo/manifests/default.xml
中的内容拷贝到AOSP中即可:
<remote name="aosp-kernel" fetch="https://android.googlesource.com/" review="https://android-review.googlesource.com/" />
<project path="kernel/build" name="kernel/build" remote="aosp-kernel" revision="master"/>
<project path="kernel/private/msm-google" name="kernel/msm" remote="aosp-kernel" revision="android-msm-crosshatch-4.9-pie-qpr2">
<linkfile src="build.config" dest="build.config" />
project>
<project path="kernel/private/msm-google/techpack/audio" remote="aosp-kernel" name="kernel/msm-extra" revision="android-msm-crosshatch-4.9-pie-qpr2"/>
<project path="kernel/private/msm-google-modules/wlan/qca-wifi-host-cmn" remote="aosp-kernel" name="kernel/msm-modules/qca-wfi-host-cmn" revision="android-msm-crosshatch-4.9-pie-qpr2"/>
<project path="kernel/private/msm-google-modules/wlan/qcacld-3.0" remote="aosp-kernel" name="kernel/msm-modules/qcacld" revision="android-msm-crosshatch-4.9-pie-qpr2"/>
<project path="kernel/private/msm-google-modules/wlan/fw-api" remote="aosp-kernel" name="kernel/msm-modules/wlan-fw-api" revision="android-msm-crosshatch-4.9-pie-qpr2"/>
<project path="kernel/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9" remote="aosp-kernel" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9" revision="pie-release" clone-depth="1" />
<project path="kernel/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" remote="aosp-kernel" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" revision="pie-release" clone-depth="1" />
<project path="kernel/prebuilts-master/clang/host/linux-x86" remote="aosp-kernel" name="platform/prebuilts/clang/host/linux-x86" revision="pie-release" clone-depth="1" groups="partner" />
<project path="kernel/prebuilts-master/misc" remote="aosp-kernel" name="platform/prebuilts/misc" revision="pie-release" clone-depth="1" />
有多种不同改法,这里提供其中一种:
标签,因此需要将拷贝过来的
标签;
标签内容如果与AOSP的不同,则需要重命名,避免命名重复,此处举例修改为"aosp-kernel"
,同时需要指定fetch
标签,避免由于与
标签定义的不同,从而导致的无法下载;
标签的消失,每个
标签内的仓库均需要手动指定remote
与revision
属性(已经覆写了的其中一条或两条属性的仓库则不需要再修改了);kernel
目录下,因此所有仓库的path
属性需要在前面添加kernel/
的路径;
标签按需修改即可;如果对manifest的各个定义非常熟悉,则可以根据自己实际情况进行合并、拆分、提取;
完成后同步一次:
$ repo sync -c --no-tags -j16 --force-sync
如果是重新下载的代码,那么需要将刚才提到的三种方案,任选其一合入以下,避免编译报错;
然后编译一下试试:
$ source build/envsetup.sh
$ lunch aosp_blueline-userdebug
$ cd kernel/
$ ./build/build.sh
如果编译没有报错,就可以继续了;
在上面迁移时,执行repo sync
时,会出现如下输出:
kernel/prebuilts-master/misc: Shared project platform/prebuilts/misc found, disabling pruning.
prebuilts/misc: Shared project platform/prebuilts/misc found, disabling pruning.
kernel/prebuilts-master/clang/host/linux-x86: Shared project platform/prebuilts/clang/host/linux-x86 found, disabling pruning.
prebuilts/clang/host/linux-x86: Shared project platform/prebuilts/clang/host/linux-x86 found, disabling pruning.
kernel/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9: Shared project platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9 found, disabling pruning.
prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9: Shared project platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9 found, disabling pruning.
kernel/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9: Shared project platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9 found, disabling pruning.
prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9: Shared project platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9 found, disabling pruning.
这表示,这部分仓库是重复的,因此repo没有重复拉取,直接复用了;
那么,我们是不是可以直接移除这些重复的仓库,修改编译命令,使其指向AOSP中的工具链?
答案必然是肯定的,我们只需要修改build.conifg.common即可:
修改后的内容如下:
ARCH=arm64
BRANCH=android-msm-bluecross-4.9
CROSS_COMPILE=aarch64-linux-android-
CROSS_COMPILE_ARM32=arm-linux-androideabi-
DEFCONFIG=b1c1_defconfig
EXTRA_CMDS=''
CLANG_PREBUILT_BIN=../prebuilts/clang/host/linux-x86/clang-4393122/bin/
LD_LIBRARY_PATH=${ROOT_DIR}/../prebuilts/clang/host/linux-x86/clang-4393122/lib64:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=../prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin
LINUX_GCC_CROSS_COMPILE_ARM32_PREBUILTS_BIN=../prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin
LZ4_PREBUILTS_BIN=../prebuilts/misc/linux-x86/lz4
DTC_PREBUILTS_BIN=../prebuilts/misc/linux-x86/dtc
LIBUFDT_PREBUILTS_BIN=../prebuilts/misc/linux-x86/libufdt
FILES="
arch/arm64/boot/dtbo.img
arch/arm64/boot/Image.lz4-dtb
vmlinux
System.map
.config
"
EXT_MODULES="
private/msm-google-modules/wlan/qcacld-3.0
"
IN_KERNEL_MODULES=1
STOP_SHIP_TRACEPRINTK=1
成功编译Android Kernel后,即可修改manifest,删除kernel/
下重复的工具链:
然后再同步一次代码:
# -l:仅从本地checkout
# --force-sync:会删除上面那几个仓库对应的目录
$ repo sync -l --force-sync -j16
截至目前,我们已经成功将Android Kernel代码整合进了AOSP中,但这仅仅是代码目录层面上的整合,编译仍然需要分段进行,并且期间伴随着拷贝操作,比改造之前略微方便一点,但仍然没有达到我的预期;
因此下一篇,会介绍如何编写编译规则,实现AOSP下一个make
指令完成Android Kernel代码的编译,以及最后打包成boot.img;