交叉编译RISC-V的V8

最近, 我研究了一下交叉编译RISC-V上的V8 JavaScript引擎。目前, V8的主线已有较好的RISC-V支持, 因此仅需编写配置文件即可编译。假设GNU编译器套件(GCC)已经按这篇文章所述构建好, 并安装在了/opt/riscv中。需要注意的是, 由于V8依赖于浮点指令, 其JIT也会生成浮点指令, 因此建议构建GCC时开启浮点支持(否则会比较灵车: V8本身按照软件浮点的方式编译, 而JIT生成的代码使用硬件浮点指令)。具体编译流程记录如下:

〇、设置代理

如果所在的网络需要使用代理才能访问Google相关服务, 则建议执行以下操作来使得后续操作一直处于代理的环境。

首先, 创建一个名为boto.cfg的Boto工具的配置文件, 内容为:

[Boto]
proxy=127.0.0.1
proxy_port=8080
proxy_type=http

然后, 执行以下命令来设置代理的环境变量及Boto工具的配置文件路径:

export ALL_PROXY="http://127.0.0.1:8080"
export HTTPS_PROXY="http://127.0.0.1:8080"
export NO_AUTH_BOTO_CONFIG=/path/to/boto.cfg

其中, 值得注意的是, 部分工具(gclient的某个组件)似乎会忽略ALL_PROXY环境变量, 因此需要同时设置HTTPS_PROXY环境变量。此外, 部分工具(V8的build/linux/sysroot_scripts/install-sysroot.py脚本)的Python脚本使用的urllib似乎不能自动根据环境变量使用SOCKS5代理, 因此推荐全程使用HTTP代理。

另外, 如果后续操作卡在了某些步骤上, 可以尝试使用iftop工具查看网络到底有没有经过代理并进行调试。

一、参考官方文档安装depot_tools

首先, 克隆depot_tools代码仓库:

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

然后, 将depot_tools加入PATH环境变量中:

export PATH=/path/to/depot_tools:$PATH

最后, 运行一下这个工具, 它会自动更新:

gclient

二、参考官方文档下载V8源代码并安装依赖

首先, 可以创建一个工作目录, 并进入:

mkdir work
cd work

然后, 下载V8源代码, 并进入相应目录:

fetch v8
cd v8

这一步会下载大量数据, 可能需要一段时间。

接着, 更新一下依赖:

gclient sync

需要注意的是, 每次git pull之后, 都建议执行一次上述命令。

最后, 安装编译环境的依赖:

./build/install-build-deps.sh

这一步需要sudo权限。

三、验证编译x64的V8

运行以下命令即可一键编译:

tools/dev/gm.py x64.release

编译好后, 可以运行out/x64.release/d8来测试编译产物, 如下图所示。

四、修改V8源代码

首先, 修改build/linux/sysroot_scripts/install-sysroot.py脚本:

diff --git a/linux/sysroot_scripts/install-sysroot.py b/linux/sysroot_scripts/install-sysroot.py
index 67d52b47a..9dfed4356 100755
--- a/linux/sysroot_scripts/install-sysroot.py
+++ b/linux/sysroot_scripts/install-sysroot.py
@@ -79,6 +79,8 @@ def main(args):
 
   if options.print_key:
     arch = options.print_key
+    if arch == 'riscv64':
+      return 0
     print(
         GetSysrootDict(DEFAULT_TARGET_PLATFORM,
                        ARCH_TRANSLATIONS.get(arch, arch))['Key'])

根据我的分析, 这个脚本会获取指定架构的sysroot的版本号(key), 然而, 它不支持riscv64架构, 所以直接执行会报错。因此, 需要对其加入对riscv64的特判, 并直接退出。

然后, 如果安装的GCC的名字与build/toolchain/linux/BUILD.gn脚本中的不一致, 则需要相应修改, 例如:

diff --git a/toolchain/linux/BUILD.gn b/toolchain/linux/BUILD.gn
index 2eefac5fa..8a4d60c98 100644
--- a/toolchain/linux/BUILD.gn
+++ b/toolchain/linux/BUILD.gn
@@ -308,7 +308,7 @@ clang_toolchain("clang_riscv64") {
 }
 
 gcc_toolchain("riscv64") {
-  toolprefix = "riscv64-linux-gnu"
+  toolprefix = "riscv64-unknown-linux-gnu"
 
   cc = "${toolprefix}-gcc"
   cxx = "${toolprefix}-g++"

五、编译V8

首先, 创建一个存放编译产物的目录, 并进入:

mkdir -p out/rv64.release
cd out/rv64.release

然后, 在该目录中创建一个名为args.gn的配置文件, 内容为:

is_component_build = false
is_debug = false
target_cpu = "riscv64"
v8_target_cpu = "riscv64"
target_sysroot = "/opt/riscv/sysroot"
use_custom_libcxx = false
use_glib = false
use_goma = false
v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
v8_enable_verify_heap = true
dcheck_always_on = false
treat_warnings_as_errors = false

其中, target_cpuv8_target_cpu设置了目标架构, target_sysroot设置了GCC提供的sysroot。此外, use_custom_libcxx设置了不要使用自带的libcxx, 因为它似乎会导致GCC编译时报错; use_glib设置了不要使用glib, 因为我的RISC-V编译环境没有安装这个库。

最后, 生成编译脚本并开始愉快编译:

gn gen .
ninja -j`nproc`

六、运行RISC-V的V8

上述编译产物主要为d8文件, 可以通过如下命令手动调用ldso来基于qemu-user运行它, 如下图所示。

LD_LIBRARY_PATH=/opt/riscv/sysroot/lib /opt/riscv/sysroot/lib/ld-linux-riscv64-lp64d.so.1 ./d8

当然, 也可以直接在RISC-V系统上运行它, 如下图所示。

参考资料:

  1. https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up
  2. https://v8.dev/docs/source-code
  3. https://v8.dev/docs/build
  4. https://github.com/isrc-cas/v8-riscv/blob/plct-riscv64/README.md
  5. https://stackoverflow.com/questions/65682118/cross-compile-v8-using-buildroot-toolchain

发表评论

注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

:wink: :twisted: :roll: :oops: :mrgreen: :lol: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-D :-? :) :( :!: 8-O 8)

本文链接:https://twd2.me/archives/17990QrCode