其实单独对 V8 引擎的编译目前在 Building V8 from source 官方文档已经写得很清楚了,其主要的步骤分为以下几步:

  • 安装 depot_tools (包含源码、依赖同步工具,编译工具等)
  • gclient sync (depot_tools 中的工具)同步依赖后进行编译

但是在国内,这个环境搭建的主要问题是 depot_tools 依赖与 V8 的源代码都在 google 自己的 git 服务器上,所以我们先需要在终端配置代理。

以下内容均在 64 位 MacOS 平台下进行,其余平台可以参考执行。

I. MacOs 终端使用代理

执行如下命令安装 privoxy:

  1. brew install privoxy

编写配置文件:

  1. vim /usr/local/etc/privoxy/config

在最前面添加:

  1. listen-address 0.0.0.0:8118
  2. forward-socks5 / localhost:1080 .

启动 privoxy:

  1. sudo /usr/local/sbin/privoxy /usr/local/etc/privoxy/config

查看是否启动成功:

  1. netstat -na | grep 8118

出现:

  1. tcp4 0 0 *.8118 *.* LISTEN

则表示 privoxy 启动成功,接着编辑 .bashrc 文件 (其余终端根据类型选择不同的 profile 文件) 添加以下内容:

  1. function proxy_off(){
  2. unset http_proxy
  3. unset https_proxy
  4. echo -e "已关闭代理"
  5. }
  6. function proxy_on() {
  7. export no_proxy="localhost,127.0.0.1,localaddress,.localdomain.com"
  8. export http_proxy="http://127.0.0.1:8118"
  9. export https_proxy=$http_proxy
  10. echo -e "已开启代理"
  11. }

最后在当前窗口执行如下命令让配置生效:

  1. source ~/.bashrc

以后只需要执行 proxy_on 即可开启终端代理,执行 proxy_off 即可关闭终端代理。

II. 安装 depot_tools

执行 proxy_on 开启终端代理后,新建一个 v8_ops 目录:

  1. mkdir v8_ops && cd v8_ops

然后克隆 depot_tools:

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

depot_tools 目录加入环境变量 (为了后面可以全局使用里面的命令),编辑 .bashrc 文件 (其余终端根据类型选择不同的 profile 文件) 添加以下内容:

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

最后在当前窗口执行如下命令让配置生效:

  1. source ~/.bashrc

这里可以测试下是否可以全局使用 gclient 命令:

  1. which gclient

如果正常显示命令全路径,则可以执行如下命令进行其自身的更新:

  1. gclient

耐心等待其更新完毕后可以开始进入下一步骤。

III. 编译 V8

depot_tools 成功安装后就可以使用里面命令来获取 v8 的源代码了:

  1. mkdir ~/v8 && cd ~/v8 && fetch v8 && cd v8

耐心等待一段时间克隆完毕后,就可以 checkout 到一个特定的版本,例如我这里采用了 7.7.299.13 这个 Node.js 12.x 嵌入的版本:

  1. git checkout 7.7.299.13 && git checkout -b local-7.7.299.13

执行如下命令同步 build dependencies:

  1. gclient sync

设置一个编译工具 gm.py 的别名:

  1. alias gm=/path/to/v8/tools/dev/gm.py

编译 V8 并且运行测试:

  1. gm x64.release.check

至此 V8 已经编译完毕。

IV. 使用 d8 测试 JS

编写任意 js 文件 hello.js:

  1. 'use strict';
  2. async function hello() {
  3. const text = await Promise.resolve('Hello hyj1991.');
  4. console.log(text);
  5. }
  6. hello();

执行如下命令观察输出结果:

  1. out/x64.release/d8 hello.js

输出:

  1. Hello hyj1991.

即表示 V8 已经正确编译。

V. 测试 V8 嵌入 C++ 项目

V8 官方已经提供了一个将引擎嵌入 C++ 项目的例子: samples/hello-world.cc,下面将其编译为可执行文件进行查看。

设置一个编译工具 v8gen.py 的别名:

  1. alias v8gen=/path/to/v8/tools/dev/v8gen.py

使用 v8gen 生成编译配置:

  1. v8gen x64.release.sample

执行如下命令编译 V8 的静态库:

  1. ninja -C out.gn/x64.release.sample v8_monolith

最后执行如下命令对 samples/hello-world.cc 编译生成可执行文件:

  1. g++ -I. -Iinclude samples/hello-world.cc -o hello_world -lv8_monolith -Lout.gn/x64.release.sample/obj/ -pthread -std=c++0x

执行 ./hello_world 可以看到输出:

  1. Hello, World!
  2. 3 + 4 = 7