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

6 篇文章 0 订阅

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

前言

Android Kernel源码不随AOSP一同释放,后者通常内置的是kernel及其相关模块的ko二进制文件,若想修改相关部分,并完成编译,则需要按照如下步骤实现:

  • 下载Android Kernel源码;
  • 编译一次,确认环境与代码下载正确;
  • 修改相关部分;
  • 再次编译;
  • 将产物合入回AOSP源码树,再次编译AOSP(打包)
  • 刷入手机;

这一套步骤非常冗长,且需要来回切换目录,拷贝文件,因此如果可以像SoC厂商释放的基线一样,将内核源码内置到AOSP源码树中,一次编译即可生成正确产物,那么调试效率可以大幅提升;

要将Android Kernel源码并入AOSP源码,使后者的编译框架可以直接从源码编译boot.img,大致需要如下几步:

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

本部分较为冗长,故而分为三部分进行阐述,这一部分介绍上面的步骤1、2、3;

环境

台式机

Ubuntu16.04

AOSP版本

9.0(android-9.0.0_r46)

内核版本

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

Pixel型号

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-qpr2Android 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)不同步导致。

解决方案也很简单(三选一):

  1. build仓库切换到aosp/android-msm-bluecross-4.9-pie-qpr1分支;
  2. 不切换build仓库的分支,但是注释掉其中_setup_env.sh文件中unset LD_LIBRARY_PATH这一句代码;
  3. 修改build.config,使其依赖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" />

有多种不同改法,这里提供其中一种:

  1. 由于manifest中仅允许一个<default/>标签,因此需要将拷贝过来的<default/>标签;
  2. <remote/>标签内容如果与AOSP的不同,则需要重命名,避免命名重复,此处举例修改为"aosp-kernel",同时需要指定fetch标签,避免由于与<default/>标签定义的不同,从而导致的无法下载;
  3. 由于<default/>标签的消失,每个<projects/>标签内的仓库均需要手动指定remoterevision属性(已经覆写了的其中一条或两条属性的仓库则不需要再修改了);
  4. 由于目录需要集中到kernel目录下,因此所有仓库的path属性需要在前面添加kernel/的路径;
  5. 如果自己本地做了二级镜像,<remote/>标签按需修改即可;

如果对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/下重复的工具链:

<!-- 
  <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" />
-->

然后再同步一次代码:

# -l:仅从本地checkout
# --force-sync:会删除上面那几个仓库对应的目录
$ repo sync -l --force-sync -j16

后记

截至目前,我们已经成功将Android Kernel代码整合进了AOSP中,但这仅仅是代码目录层面上的整合,编译仍然需要分段进行,并且期间伴随着拷贝操作,比改造之前略微方便一点,但仍然没有达到我的预期;

因此下一篇,会介绍如何编写编译规则,实现AOSP下一个make指令完成Android Kernel代码的编译,以及最后打包成boot.img;

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值