草莓熊和QQ猪
Chrome浏览器想必大家都不陌生,Chrome是由Google基于Chromium开发的商业化产品,目前Chrome基本算是统一浏览器市场份额了,连Windows的Edge浏览器也是使用了Chromium内核,还有谁能和其竞争。作为老司机,在Chromium项目刚开始就关注过,刚开始也是觉得它是WebKit加个壳,后面经历了几年的发展,我是没有深入了解,现在Chromium排版引擎已经将WebKit改名为blink,其发展更是已经超越了所以对手,成为最用户量最多的浏览器。
再来搞Chromium我就是一个小白,还好现在有互联网,有各路高手都会给自己的答案,也是给你一条指引,最后能不能成功就看你人品了,只要方法对下载和编译也只是在不那么自信和不那么确定中最终完成。当然踩到别人踩过的坑也不一定是坏事,不经历风雨何来的彩虹不是!
前期准备
- CPU核数越多越好。
- 内存越大越好,至少16G。
- 100G+硬盘空间。
环境准备
编译win或者mac的都要各自系统,其他的在Linux完成,当然在Linux完成应该是最少问题的吧,话说Chromium也是开Ubuntu里开发的,大家使用Ubuntu可以避免不必要的麻烦。当然大家用的都是Windows系统,编win的主要问题可能就是字符编码和git的设置了。我是编译linux的所以使用win11+wsl2(ubuntu2004),当然我除了需要编译Chromium最新版本外还要编译Chromium旧的版本,旧版本在新的系统环境下载和编译会可能有错误提示,我是使用wsl2+docker+ubuntu1604这个可以解决。
软件准备
- Ubuntu
- python3(Chromium新版)和python2(Chromium旧版)
- git
- 梯子
下载depot_tools
depot_tools是Google的一个工具集,完成代码拉取和构建的,想要完成下载和编译它是必须的,当然不是唯一,只是如果你是靠看别人经验来下载和编译的,那么你还是老老实实使用depot_tools吧
首先通过git下载depot_tools到你想要的目录里,因为wsl在/mnt下挂载的硬盘IO都会很慢,这里源码一定不要放在/mnt挂载的硬盘里,所以我都在用户目录下操作
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
然后将depot_tools添加到PATH环境变量中,可以写入到~/.bashrc,后面就自动导入了
export PATH=$PATH:${HOME}/depot_tools
下载完整代码
mkdir chromium && cd chromium
gclient config –unmanaged https://chromium.googlesource.com/chromium/src.git
solutions = [
{ "name" : 'src',
"url" : 'https://chromium.googlesource.com/chromium/src.git',
"deps_file" : 'DEPS',
"managed" : False,
"custom_deps" : {
},
"custom_vars": {},
},
]
会在chromium目录下生成.gclient配置文件,当然可以换成下面的,当然”name”就是url-path最后的一个文件名称了(去掉.git),这个也是gclient命令管理的源码的目录名称。
https://github.com/chromium/chromium.git (国外github源)
https://gitee.com/mirrors/chromium.git (国内gitee源)
然后执行下载代码命令:gclient sync
下载代码会放chromium目录中.gclient配置”name”指定名字的目录下,因为代码太大,可能会失败,所以推荐sync和hook分开执行,默认情况下,gclient sync是包含gclient sync –nohooks和gclient runhooks先后两步操作,分开更直观在那阶段出现的失败。
同步除了DEPS指定的依赖外,src目录就是chromium的git仓库,gclient sync下载的依赖或者runhooks生成的文件都不在git status里,所以只要src目录下的.git目录已经指定好了仓库源,也可以先git pull下载仓库代码,也可以通过命令
git clone --depth 1 https://gitee.com/mirrors/chromium.git src
先浅克隆到src目录,然后在src目录下执行git pull下载完整仓库,再运行gclient sync –nohooks,最后执行gclient runhooks,只要跟着.gclient配置约定,不要损坏src下的.git目录,可以随意搞,无需担心各种错误问题,错了用git目录还原回来就好。如果你把git clone、git tag、git log都下载好源码了,后面想编译那个分支,直接在src目录下用git切换分支就好,如:
git checkout -b 116.0.5845.180 tags/116.0.5845.180
或者直接整个chromium目录拷贝一份,然后切换分支,这样再运行:gclient sync –nohooks –with_branch_heads,如果这个仓库以前sync其他版本的代码,可以加上-D和–force参数保存sync下来的代码和切换分支一致。完了再运行gclient runhooks就可以啦。gclient有好几个命令可以独立完成以上事情,但和相对于gclient命令不那么熟悉,我更愿意使用git与其相互配合的用,这样拉取代码更加可控。
Chromium源码已经下载下来后,是shell环境的先执行./build/install-build-deps.sh,如果脚本提示这个要在指定版本系统运行的,那么还是按照它要求换系统,执行完install-build-deps.sh,然后再执行sync和hook命令。
拉取chromium主仓库一般都因为梯子影响网络问题或者源码太大git命令配置问题导致的,除了这两种错误拉取主仓库基本没有见过其他问题,sync或者hook一般错误都是在拉取src/DEPS配置文件指定的子仓库时多有失败,或者子仓库目录下DEPS依赖下载失败,分支对应的子仓库链接已经无效或者地址变了都可以通过先注释DEPS子仓库,有些依赖不一定的必须的,可以直接注释不需拉取。
当然有些子仓库可以手动下载的,如果链接失效或者对应版本找不到了,那么这个就先看能不能忽律此子仓库,如果不行就只能修改depot_tools的脚本使用其他本地替代了!走到这步如果是强依赖的库那么可能会导致编译失败,不过目前我试过的版本,拉不下来的可以注释忽律,不影响编译。
如果是强依赖的,像ffmpeg这个子仓库,但DEPS描述的版本已经找不到,这个也不要急,找与它时间相近的就好,当然策略是要新不要旧,有些库是可以用最新版的,直接修改DEPS里的版本(一般都是git的commit-id),换好再跑一下sync和hook命令就可以,还报错,一直换到不报错为止,这个就看人品了。
如果依赖库很多错了,可以先将错误的库先全部在DEPS里注释,一个一个的修正回来,保证每加一个都能sync和hook正确完成就可以,不要担心DEPS改坏,git diff DEPS就可以看到修改的项目了。
假如sync拉去DEPS中src/third_party/android_toolchain失败,那么可以手动去下载,配置如下:
'src/third_party/android_toolchain': {
'packages': [
{
'package': 'chromium/third_party/android_toolchain/android_toolchain',
'version': 'version:2@r25c.cr1',
},
],
'condition': 'checkout_android_native_support',
'dep_type': 'cipd',
}
打开https://chrome-infra-packages.appspot.com/p/${package}对应链接,拉取version对应的版本。gclient runhooks失败,多见https://storage.googleapis.com/${bucket}/${sha1}拉取失败,其他的见招拆招了。
https://storage.googleapis.com/
chromium-browser-clang/rc/7d3a485bb5bae0cf3c6b8af95d21f36aa7d02832
https://storage.googleapis.com/
chromium-clang-format/2e569921b9884daf157021d6ae9e21991cd6cf8
https://storage.googleapis.com/
chromium-fonts/336e775eec536b2d785cc80eff6ac39051931286
https://storage.googleapis.com/
chromium-webrtc-resources/009a3ee778767c2402b1d2c920bc2449265f5a2c
gclient sync是可以多次执行的,已经做完的不会重复,没有完成的会继续完成,等gclient sync都完成了,那么下载代码已经大功告成。
安装其他依赖和工具链
代码拉下来后,在就可以在src目录下运行:./build/install-build-deps.sh,这个目录是给系统环境安装依赖库,其实和下载的代码没有关系,要不会修改src目录下文件,是给系统安装编译和链接需要的依赖库。
不过能运行install-build-deps.sh的时候先运行一次,再执行gclient runhooks,其实runhooks只是sync里的一个步骤,所以如果拉取代码都没有问题了,其实install-build-deps.sh执行后就可以配置编译了,无需再执行一次hook命令,当然因为已经hook完了,再执行一次也是很快的,无需担心这步会影响心情。原则上是只有主仓库下载完了就可以执行install-build-deps.sh,再运行gclient sync,但因为sync也是可以下载代码的这个就是鸡和蛋谁先有的问题了,有些情况如果没有先执行install-build-deps.sh,运行gclient sync就会有错误了。
配置编译选项
gn args out/Default
ninja和gn都在depot_tools里了,先cd src到仓库根目录,上面命令是gn args弹出要输入的配置,并在out/Default目录下生成一个args.gn的配置文件,是告诉编译器接下要怎么编译和编译那些内容的。
target_os
:顾名思义,要为哪个系统编译Chromium。我只是要linux编译,所以没写这个。target_cpu
:设置编译对应的CPU架构。如arm64,arm,x86,x64等,如果没有目标可以不写。is_debug
:是否编译Debug版本。如果不设置此项,默认是true
。设置此项还会影响许多其它选项的值。treat_warnings_as_errors
:是否把编译中遇到的warning视为error并停止编译。默认是true
,建议把此项设置为false
,因为编译中会产生不少warning。is_java_debug
:是否给Java代码开启debug,默认值与is_debug
同步,设置为false
可以关闭代码混淆以提升编译速度。is_component_build
:是否把浏览器的每个部分拆分为单独的.so
库还是动态链接为一个完整的libchrome.so
。默认值是true
。如果要调试C++代码,必须设置为true
。- enable_nacl:这个选项值可以为true或者false。控制是否启用Native Client,通常我们并不需要。所以把其值设置成enable_nacl = false。
- enable_rust:新版Chromium代码里的配置,旧版没有这个选项,如果你不是rust用户,这个就设置成enable_rust = false吧,但最新的版本已经和rust紧密结合了,怎么使用你多试试。
is_official_build
:默认是false
。开启后会移除调试符号并进行编译优化,同时增加编译耗时。编译生产版本时直接开启此项即可,因为关闭此项后浏览器执行速度会明显变慢。注意开启此项后is_debug
和is_component_build
都会自动设为false
。symbol_level
:它的值为整数。设置为0
会移除所有调试符号,并减小.so
库大小。设置为2
开启所有调试符号。默认是2
。- blink_symbol_level:关闭 blink 的源代码级调试以减少构建时间,如果您不打算调试 blink,可以这么干。
- v8_symbol_level:关闭 v8 的源代码级调试以减少构建时间,如果您不打算调试 v8,可以这么干。
gn gen out/Default
gn gen就完成.ninja的配置了,如果想修改args.gn可以先执行gn clean,或者再执行gn args命令
gn clean out/Default
确定好配置后就开搞编译了:
autoninja -C out/Default chrome
到这步就等编译完成了!
v8独立编译
mkdir chromium-v8 && cd chromium-v8
gclient config https://github.com/v8/v8.git
gclient sync
cd v8
gn args out/v8Default && gn gen out/v8Default
target_cpu = "x64"
#target_arch = "x64"
#v8_target_cpu = "x64"
v8_use_external_startup_data = true
v8_enable_i18n_support = false
v8_use_snapshot = true
is_component_build = true
#is_debug = false
autoninja -C out/v8Default
Chromium和v8的关系
v8是Chromium默认的js引擎,可以从Chromium代码版本找到对应的v8版本,但反之查不了,因为v8是独立模块,它的接口比较稳定,原则上是可以给任意Chromium版本使用。
Chromium根目录找到DEPS文件,打开找到如:
'v8_revision': '0d3057fd367eeae5f101c08fc834f4b196b90eee'
然后拼接代码链接:
https://chromium.googlesource.com/v8/v8.git/+/0d3057fd367eeae5f101c08fc834f4b196b90eee
就能看到仓库里显示的v8版本是:Version 7.5.288.31
docker编译
docker pull ubuntu:18.04
docker run -it ubuntu:18.04 bash
docker容器初始化
1 adduser test
2 su test
3 exit
4 apt-get update
5 apt-get install gcc g++ gdb make cmake clang llvm lldb bison flex
6 apt-get install curl wget vim git subversion lbzip2 unzip zip
7 apt-get install sudo lsb-release locales ninja-build gobjc gobjc++
8 lsb_release -a
9 chmod u+w /etc/sudoers
10 vim /etc/sudoers # 找到root用户一行,复制粘贴,然后将root改成test,保存退出
11 chmod u-w /etc/sudoers
12 su test
13 cd ~
14 exit
将上面的容器 docker commit ${容器id} ubuntu1804:chromium,打包镜像,方便下次操作。
docker编译
代码是wsl下载好的,映射到docker里了,如果你想在docker下载一份那么请让我叫一声大哥!depot_tools代码直接在docker里git clone一份就好,因为可能要修改里面代码的。
1 docker run -it -d
-v /home/test/chromium-refs_tags_75.0.3770.156:/home/test/chromium
ubuntu1804:chromium bash
2 su test
3 cd ~
4 git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
5 vim .bashrc [[ export PATH="$PATH:${HOME}/depot_tools" ]]
6 source .bashrc
7 cd chromium/src
8 ./build/install-build-deps.sh
9 cd ..
10 gclient sync ...
11 gclient sync --nohooks --with_branch_heads && gclient runhooks
12 cd src
13 vim /home/test/depot_tools/gclient_paths.py
@functools.lru_cache(maxsize=128, typed=False)
14 gn args out/Default
treat_warnings_as_errors = false
is_component_build = false
is_debug = false
enable_nacl = false
#enable_rust = false
#target_os = "win"
#target_cpu = "x86"
#blink_symbol_level = 0
#v8_symbol_level = 0
#symbol_level = 0
15 gn gen out/Default
16 autoninja -C out/Default chrome
如果gn args见到错误是
找到@functools.lru_cache,替换成@functools.lru_cache(maxsize=128, typed=False),再继续就好。
如果编译环境更老,可能还有修改depot_tools里的脚本:
download_from_google_storage.py # print和queue问题
upload_to_google_storage.py # print和queue问题
from __future__ import print_function # 首行插入解决print函数python3兼容问题
import sys
if sys.version > '3': # 判断python版本导入queue库
import queue
else:
import Queue as queue
subprocess2.py # STDOUT问题
DEVNULL = subprocess.STDOUT # subprocess.DEVNULL # 直接STDOUT输出就好了
推荐开发环境
win11+vs+vscode+wsl2
如果是只是想编译windows版本当然是用visual studio,如果是开发linux或android,那么用vscode,mac就算了,不是不想用,是用不起。win11+wsl2下编译linux界面程序也是可以直接在windows上跑的,这个非常方便开发和验证。
参考文档:
Chromium Docs – Chromium docs (googlesource.com)
Chromium Docs – Checking out and building Chromium on Linux (googlesource.com)
Chromium Docs – Checking out and Building Chromium for Windows (googlesource.com)
Chromium Docs – Cross-compiling Chrome/win (googlesource.com)
Chromium Docs – The Chrome Component Build (googlesource.com)
GN Quick Start guide (googlesource.com)
GN Reference (googlesource.com)