V8 编译踩坑 (v8.1-lkgr)
编译版本
由于当前 Chrome
最新稳定版本是 Chrome 81
, 我们可以通过 chrome://version
查看,发现当前 Chrome
依赖的 v8
版本是 8.1.307.32
。

准备工作
安装 depot_tools
我们所需的 gn
(配置生成工具) 和 nijia
(构建工具) 都在这个仓库里。
# Clone depot_tools 仓库
$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
# 导出环境变量
$ export PATH="$PATH:/path/to/depot_tools"
下载所需依赖
$ mkdir v8_build && cd v8_build
# 配置 v8 仓库
$ gclient config https://chromium.googlesource.com/v8/v8
# 需要科学上网,然后等待很长一段时间...
$ gclient sync
结束了之后,就会看到 v8
的仓库文件夹,配置一下 v8gen.py
的别名。
$ alias v8gen=/path/to/v8/tools/v8gen.py
编译
首先切换到我们需要编译的分支 8.1-lkgr
,lkgr
是最新通过测试的稳定版本,看下日志发现就是最新 Chrome
引用的 v8
版本 8.1.307.32
。
$ git checkout 8.1-lkgr
我们目的是编译出静态库 v8_monolith
供我们的 C++
程序引用,按照官方教程走,这里需要 python 2
的环境,我用 pyenv
安装了 2.7.17
的版本,然后在 v8
目录下执行。
$ v8gen -vv x64.release.sample
'''
Traceback (most recent call last):
File "/Users/Vincent/Common/v8/build/mac/find_sdk.py", line 97, in <module>
print(main())
File "/Users/Vincent/Common/v8/build/mac/find_sdk.py", line 80, in main
raise Exception('No %s+ SDK found' % min_sdk_version)
Exception: No 10.15+ SDK found
这里报了个错误,说我们没有 10.15
的 SDK
,可是我用的是 Mojave
(滑稽),看着 min_sdk_version
这个变量是写死在分支的文件里的,于是我修改了一下。
# build/config/mac/mac_sdk_overrides.gni
_sdk_min_from_env = getenv("FORCE_MAC_SDK_MIN")
declare_args() {
# Minimum supported version of the Mac SDK.
if (_sdk_min_from_env == "") {
mac_sdk_min = "10.15" # 将这里修改成了10.14
} else {
mac_sdk_min = _sdk_min_from_env
}
}
修改后再次执行,Done.
$ v8gen -vv x64.release.sample
'''
/Users/Vincent/.pyenv/versions/2.7.17/bin/python -u tools/mb/mb.py gen -f infra/mb/mb_config.pyl -m developer_default -b x64.release.sample out.gn/x64.release.sample
Writing """\
is_component_build = false
is_debug = false
target_cpu = "x64"
use_custom_libcxx = false
v8_monolithic = true
v8_use_external_startup_data = false
""" to /Users/Vincent/Common/v8/out.gn/x64.release.sample/args.gn.
/Users/Vincent/Common/v8/buildtools/mac/gn gen out.gn/x64.release.sample --check
Done. Made 140 targets from 81 files in 753ms
下面开始构建,不出意外的话应该会报下面的错。
$ ninja -C out.gn/x64.release.sample v8_monolith
'''
FAILED: obj/v8_base_without_compiler/js-number-format.o
../../src/objects/js-number-format.cc:1227:15: error: no member named 'getAllFieldPositions' in 'icu_67::number::FormattedNumber'
formatted.getAllFieldPositions(*fp_iter, status);
~~~~~~~~~ ^
1 error generated.
ninja: build stopped: subcommand failed.
看一下这个文件 js-number-format.cc
,发现确实没有 getAllFieldPositions
这个函数的实现。我切了 8.0-lkgr
, 7.9-lkgr
, 7.8-lkgr
这几个分支,发现编译都会报这个错,查了一下官方的 issue
,发现 icu67
移除了 getAllFieldPositions
这个 API
,需要后续添加一个 icu67.1
的 patch
。

这个 bug
已在 2020/04/07
的一次 Commit
修复,这里我们直接 cherry-pick
会有冲突,但是又不想用太新的没有测试过的版本,反正也用不到国际化的模块,所以就将 i18n
从编译选项中移除了,方法如下:
# 编辑配置
$ gn args out.gn/x64.release.sample
# 增加一行:
# v8_enable_i18n_support = false
# 再次构建
$ ninja -C out.gn/x64.release.sample v8_monolith
Hello World
编译一下 samples/hello-world.cc
$ g++ samples/hello-world.cc -o hello-world \
-I. -I./include \
-L./out.gn/x64.release.sample/obj -lv8_monolith \
-std=c++11
执行一下,如果有如下输出就是编译成功了
$ ./hello-world
'''
Hello, World!
3 + 4 = 7
其他编译选项
上文已经演示了如何编译 V8 静态库并链接到你的 C++ 代码中,下面我们尝试编译可执行文件 d8
Release 版本
$ v8gen.py x64.release
$ ninja -C out.gn/x64.release
Debug 版本
$ v8gen.py x64.debug
$ ninja -C out.gn/x64.debug