在 WSL2 下编译适用于 Android 的 Chromium 踩坑日志

前天睡不着,脑子里在想在 Android 上 Chrome 是怎么获取网站的 favicon 的。于是,直接爬起来下载了一份适用于 Android 的 Chromium 源码,准备扒开看看。

下完后,按照个人习惯,先跑一遍编译,可是在编译的过程中遇到了些小坑,遂有了这篇水文。

为了这篇文章,我不得不拾起我将近一年没有维护的博客,重建博客也花了不少时间。

安装 WSL2 的部分略过,这不属于本文的范畴,只需简简单单按照微软给出的官方文档就可以很轻松的完成安装。

以下开始进入正文,我用的是 Ubuntu 20.04 作为编译环境。

需要的依赖

下载以及编译 Chromium 需要自行安装 Git 和 Python 2。

1
sudo apt install git python

下载源码

根据 Chromium 给出的官方文档依次运行以下命令。

下载用于下载源码的工具

1
2
git clone https://chromium.googlesource.com/
chromium/tools/depot_tools.git

添加环境变量

1
export PATH="$PATH:$HOME/depot_tools"

把工具路径加入环境变量中,方便调用。实际上为了下次不再输入这个命令,我手动加入到 .zshrc 里了。.zshrc 是 zsh 的配置文件,zsh 的安装不在本文范围内。你可以根据自身需求将以下命令加入到 .bashrc 或 /etc/profile 里。

创建源码目录,以及下载源码

1
2
mkdir ~/chromium && cd ~/chromium
fetch --nohooks android

文档中提到:

If you don’t want the full repo history, you can save a lot of time by adding the –no-history flag to fetch.

我并不需要源码的历史记录因此我真正运行的命令是:

1
2
mkdir ~/chromium && cd ~/chromium
fetch --nohooks --no-history android

下载编译 Chromium 的依赖

根据文档所说我们需要进入 src 目录,写入文件声明目标系统是 Android,并开始同步 Android 所需的依赖库。

1
2
3
cd src
echo "target_os = [ 'android' ]" >> ../.gclient
gclient sync

文档中还提到,在编译适用于 Android 的 Chromium 之前,需要下载安装额外的依赖。

1
2
# 在 src 目录下运行
build/install-build-deps-android.sh

注意在 WSL2 下安装 Snapcraft 会报错,通过 Google 到的解决方法依次运行以下两条命令得以正常安装。

1
2
sudo daemonize /usr/bin/unshare --fork --pid --mount-proc /lib/systemd/systemd --system-unit=basic.target
exec sudo nsenter -t $(pidof systemd) -a su - $LOGNAME

然后接着看文档,文档中说我们还需要运行钩子以安装额外依赖。

好!很有精神!

好!很有精神!

装就完事了~

Once you’ve run install-build-deps at least once, you can now run the Chromium-specific hooks, which will download additional binaries and other things you might need:

1
gclient runhooks

另外文档中提到可以申请 API keys 用以调用谷歌服务,这里用不到略过了~

Optional: You can also install API keys if you want your build to talk to some Google services, but this is not necessary for most development and testing purposes.

编译

终于可以开始编译,根据文档所说我们需要运行以下命令:

1
gn args out/Default

并将以下内容写入到 out/Default/args.gn

1
2
target_os = "android"
target_cpu = "arm64" # See "Figuring out target_cpu" below

这里我一切照搬,因为现在的 Android 手机都是 64 位系统了,所以 target_cpuarm64

我不喜欢使用 vim 输入因此直接 :qa 退出,并通过 VS Code 修改。

最后运行以下命令就可以开始编译了:

1
autoninja -C out/Default chrome_public_apk

经过一段漫长的等待我们可以在 out/Default/apks 下看到我们的成品 ChromePublic.apk

结语

安装打开使用一切都很顺利。

顺带查看了下版本号,发现了点有意思的事情。

Variants Version
Chrome 86.0.4240.75
Chrome Canary 88.0.4291.0
自己编译的 Chromium 88.0.4292.0

由此可以看出,谷歌对 Chrome 的测试还是非常严格的。通过查看文档也可以进一步说明此问题。

最后也在漫长的编译等待过程中找到了调用 favicon 的部分代码,全是通过 JNI 操作 C 来调用的。好吧我就知道,这种大型的跨平台应用为了节约各种成本,一定会共用大量代码,而不可能老老实实用 Java 在 Android 上全部写一遍的~