最近, 我研究了一下交叉编译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_cpu
和v8_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系统上运行它, 如下图所示。
参考资料:
- https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up
- https://v8.dev/docs/source-code
- https://v8.dev/docs/build
- https://github.com/isrc-cas/v8-riscv/blob/plct-riscv64/README.md
- https://stackoverflow.com/questions/65682118/cross-compile-v8-using-buildroot-toolchain
发表评论