Windows 平台使用 VS2019 编译 V8 引擎小记

Windows 平台使用 VS2019 编译 V8 引擎小记

前言

本文记录在 Windows 平台下,使用 Visual Studio 2019 编译 Google V8 JavaScript 引擎的完整流程。由于项目需要兼容 Windows 7 系统,因此选择了较早的稳定分支 chromium-5414 (10.9-lkgr) 进行编译。

说明

  1. 除参考本文外,亦可借鉴 v8-nuget 等项目的构建流程。
  2. 编译环境为 VS2019,VS2022 在此特定 V8 版本上可能因兼容性问题导致编译失败。
  3. 本文涵盖静态库与动态库的 x86/x64、Debug/Release 全版本编译方法。

参考资料


一、编译环境准备

1.1 安装 Visual Studio 2019 必要组件

通过 Visual Studio Installer 安装或确保已包含以下工作负载和组件:

  • Desktop Development with C++
  • C++ ATL for Latest v142 Build Tools (x86 & x64)
  • C++ MFC for Latest v142 Build Tools (x86 & x64)
  • C++ CMake tools for Windows
  • Windows 10 SDK(建议安装 10.0.16299.0 或更高版本)

1.2 获取并配置 depot_tools

depot_tools 是 Google 用于管理 Chromium 系列项目源码的工具集。

  1. 下载 depot_tools
    访问下载页面:depot_tools tutorial

  2. 配置环境变量
    将 depot_tools 的解压目录(例如 D:\depot_tools)添加到系统的 PATH 环境变量中,并确保其位于任何其他可能包含 Python 或 Git 的路径之前
    环境变量配置示例

1.3 选择并拉取 V8 源码分支

  1. 确定分支版本
    访问 V8 Branch Details 查看可用的分支。本文选用 10.9-lkgr
    V8分支列表

  2. 拉取源码
    管理员身份打开命令提示符(CMD),执行以下命令:

    mkdir v8
    set DEPOT_TOOLS_WIN_TOOLCHAIN=0
    fetch v8
    cd v8
    git checkout 10.9-lkgr
    gclient sync -v
    

    此过程耗时较长,需等待全部同步完成。
    源码拉取完成

1.4 (可选)编译 Ninja

若系统中未安装 Ninja 构建工具,可参考 此文章 进行编译安装,也可使用 depot_tools 自带的版本。


二、编译 V8 引擎

2.1 启动编译命令行

  1. 进入 V8 源码根目录。
    进入V8目录
  2. 从开始菜单打开 适用于 VS 2019 的开发人员命令提示符(根据目标平台选择 x86 或 x64 版本)。
    VS2019开发者命令行
  3. 在命令行中设置必要的环境变量(每次新开命令行都需要执行):
    set DEPOT_TOOLS_WIN_TOOLCHAIN=0
    set GYP_MSVS_VERSION=2019  # 如果使用VS2022,则设为2022
    

2.2 静态库编译

以下分别介绍四种常见配置的编译方法。每次编译分为两步:gn args 配置生成,ninja -C 执行编译。

x64 Debug 静态库

gn args out.lib/x64.debug

在弹出的记事本中,在文件末尾追加以下配置:

v8_static_library=true
v8_monolithic=true 
v8_enable_sandbox=true
v8_enable_disassembler=true
v8_enable_object_print=true
v8_use_external_startup_data=false
v8_enable_slow_dchecks=false
v8_enable_backtrace=true 
v8_optimized_debug=false
v8_enable_i18n_support=true
v8_enable_webassembly=true
v8_symbol_level=0 
enable_iterator_debugging=true
use_custom_libcxx=false 
is_component_build=false 
treat_warnings_as_errors=false 
is_debug=true
is_clang=false 
target_cpu="x64"

保存并关闭记事本,命令行会自动应用配置。然后执行编译:

ninja -C out.lib/x64.debug v8_monolith

gn配置过程

x64 Release 静态库

点击查看配置详情
gn args out.lib/x64.release

配置内容:

v8_static_library=true
v8_monolithic=true
v8_enable_sandbox=true
v8_use_external_startup_data=false
v8_enable_disassembler=true
v8_enable_object_print=true
v8_enable_webassembly=true
v8_enable_i18n_support=true
v8_symbol_level=0
use_custom_libcxx=false
is_component_build=false
treat_warnings_as_errors=false
is_debug=false
is_clang=false
target_cpu="x64"

编译命令:

ninja -C out.lib/x64.release v8_monolith

x86 Debug 静态库

点击查看配置详情
gn args out.lib/x86.debug

配置内容:

v8_static_library=true
v8_monolithic=true 
v8_enable_sandbox=false  # x86 通常关闭沙箱
v8_enable_disassembler=true
v8_enable_object_print=true
v8_use_external_startup_data=false
v8_enable_slow_dchecks=false
v8_enable_backtrace=true 
v8_optimized_debug=false
v8_enable_webassembly=true
v8_enable_i18n_support=true
v8_symbol_level=0 
enable_iterator_debugging=true
use_custom_libcxx=false 
is_component_build=false 
treat_warnings_as_errors=false 
is_debug=true
is_clang=false 
target_cpu="x86"

编译命令:

ninja -C out.lib/x86.debug v8_monolith

x86 Release 静态库

点击查看配置详情
gn args out.lib/x86.release

配置内容:

v8_static_library=true
v8_monolithic=true
v8_enable_sandbox=false
v8_use_external_startup_data=false
v8_enable_disassembler=true
v8_enable_object_print=true
v8_enable_webassembly=true
v8_enable_i18n_support=true
v8_symbol_level=0
use_custom_libcxx=false
is_component_build=false
treat_warnings_as_errors=false
is_debug=false
is_clang=false
target_cpu="x86"

编译命令:

ninja -C out.lib/x86.release v8_monolith

2.3 动态库编译

x64 Debug 动态库

点击查看配置详情
gn args out.dll/x64.debug

配置内容:

v8_static_library=false
v8_monolithic=false 
v8_enable_sandbox=true
v8_enable_disassembler=true
v8_enable_object_print=true
v8_use_external_startup_data=false
v8_enable_slow_dchecks=false
v8_enable_backtrace=true 
v8_optimized_debug=false
v8_enable_i18n_support=true
v8_enable_webassembly=true
v8_enable_verify_heap=false  # 修正动态库链接错误
v8_symbol_level=0 
enable_iterator_debugging=true
use_custom_libcxx=false 
is_component_build=true 
treat_warnings_as_errors=false 
is_debug=true
is_clang=true 
target_cpu="x64"

编译命令:

ninja -C out.dll/x64.debug

x64 Release 动态库

点击查看配置详情
gn args out.dll/x64.release

配置内容:

v8_static_library=false
v8_monolithic=false
v8_enable_sandbox=true
v8_use_external_startup_data=false
v8_enable_disassembler=true
v8_enable_object_print=true
v8_enable_webassembly=true
v8_enable_i18n_support=true
v8_symbol_level=0
use_custom_libcxx=false
is_component_build=true
treat_warnings_as_errors=false
is_debug=false
is_clang=true
target_cpu="x64"

编译命令:

ninja -C out.dll/x64.release

x86 Debug 动态库

点击查看配置详情
gn args out.dll/x86.debug

配置内容:

v8_static_library=false
v8_monolithic=false
v8_enable_sandbox=false
v8_enable_disassembler=true
v8_enable_object_print=true
v8_use_external_startup_data=false
v8_enable_slow_dchecks=false
v8_enable_backtrace=true 
v8_optimized_debug=false
v8_enable_webassembly=true
v8_enable_i18n_support=true
v8_symbol_level=0 
enable_iterator_debugging=true
use_custom_libcxx=false 
is_component_build=true 
treat_warnings_as_errors=false 
is_debug=true
is_clang=true
target_cpu="x86"

编译命令:

ninja -C out.dll/x86.debug

x86 Release 动态库

点击查看配置详情
gn args out.dll/x86.release

配置内容:

v8_static_library=false
v8_monolithic=false
v8_enable_sandbox=false
v8_use_external_startup_data=false
v8_enable_disassembler=true
v8_enable_object_print=true
v8_enable_webassembly=true
v8_enable_i18n_support=true
v8_symbol_level=0
use_custom_libcxx=false
is_component_build=true
treat_warnings_as_errors=false
is_debug=false
is_clang=true
target_cpu="x86"

编译命令:

ninja -C out.dll/x86.release

2.4 关键配置参数注解

is_clang=true                 # 是否使用Clang编译,MSVC编译设为false
is_debug=true                 # 是否为Debug构建
enable_iterator_debugging=true # Debug模式必须为true,避免“_ITERATOR_DEBUG_LEVEL”不匹配错误
v8_enable_slow_dchecks=false  # Debug模式设为false,避免constexpr相关编译错误
v8_static_library=true        # 编译为静态库
v8_monolithic=true            # 编译为单一整体库(v8_monolith)
use_custom_libcxx=false       # 使用MSVC标准库,编译静态库时建议为false
v8_use_external_startup_data=false # 避免依赖外部数据文件
v8_enable_sandbox=true        # 启用V8沙箱功能,项目中需添加V8_ENABLE_SANDBOX宏
v8_enable_verify_heap=false   # 修正x64 Debug动态库链接时的VC++符号错误
target_cpu="x64"              # 目标CPU架构,可选"x86"或"x64"

三、在项目中使用编译的 V8 库

3.1 包含头文件

将 V8 源码根目录下的 include 文件夹复制到你的项目包含目录中,或直接在项目中添加该路径。
V8头文件目录

3.2 链接库文件

使用静态库 (v8_monolith)

  • 需链接的库文件: out.lib/<arch>.<config>/obj/v8_monolith.lib
  • 添加到项目: 在项目属性中,将此目录添加到 链接器 -> 常规 -> 附加库目录

使用动态库

  1. 运行时依赖(需与可执行文件放在同一目录):
    • icudtl.dat
    • icui18n.dll
    • icuuc.dll
    • v8.dll
    • v8_libbase.dll
    • v8_libplatform.dll
    • zlib.dll
  2. 链接时依赖(添加到项目库目录):
    • v8.dll.lib
    • v8_libbase.dll.lib
    • v8_libplatform.dll.lib

3.3 项目配置

  1. 预处理宏:
    对于 x64 架构,如果启用了沙箱和指针压缩,需在项目预处理器定义中添加:

    V8_COMPRESS_POINTERS
    V8_31BIT_SMIS_ON_64BIT_ARCH
    V8_ENABLE_SANDBOX
    
  2. 运行时库:
    C/C++ -> 代码生成 -> 运行时库 中,选择 多线程调试 (/MTd)多线程 (/MT),与编译 V8 时的选项保持一致。

3.4 示例代码

以下是一个简单的 V8 初始化示例程序:

#include <iostream>
#include <memory>

// 根据编译方式定义链接库
#ifdef _V8_DLL_IMPORT // 使用动态库
    #pragma comment(lib, "v8.dll.lib")
    #pragma comment(lib, "v8_libbase.dll.lib")
    #pragma comment(lib, "v8_libplatform.dll.lib")
#else // 使用静态库
    #pragma comment(lib, "v8_monolith.lib")
#endif
// 链接其他必要库
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "dbghelp.lib")
#pragma comment(lib, "shlwapi.lib")

#include "libplatform/libplatform.h"
#include "v8.h"

std::unique_ptr<v8::Platform> g_platform;
bool bInitializeV8EngineApp = false;

void InitializeV8EngineApp() {
    if (bInitializeV8EngineApp) return;
    bInitializeV8EngineApp = true;

    // 设置V8标志(可选)
    v8::V8::SetFlagsFromString("--gc-interval 3000000 --stack-trace-limit 10");
    
    // 创建并初始化平台
    g_platform = v8::platform::NewDefaultPlatform(
        2, // 线程池大小
        v8::platform::IdleTaskSupport::kEnabled
    );
    v8::V8::InitializePlatform(g_platform.get());
    
    if (!v8::V8::Initialize()) {
        std::cerr << "Failed to initialize V8!" << std::endl;
        return;
    }
    std::cout << "V8 version: " << v8::V8::GetVersion() << std::endl;
}

int main() {
    InitializeV8EngineApp();
    // 此处可创建Isolate、Context并执行JavaScript代码
    std::cout << "V8 initialized successfully." << std::endl;
    return 0;
}

3.5 运行结果

成功编译并运行示例程序后,控制台将输出 V8 引擎的版本信息。
示例程序输出


四、总结与注意事项

  1. 环境一致性:确保编译 V8 时使用的工具链(MSVC版本、Windows SDK)与你的主项目一致。
  2. 配置参数:文中提供的 gn 配置参数是针对 10.9-lkgr 分支和 VS2019 环境优化的。若使用其他 V8 版本或编译器,可能需调整部分参数。
  3. 沙箱支持:x86 架构通常需关闭沙箱 (v8_enable_sandbox=false),而 x64 架构建议开启以获得更好的安全性。
  4. 编译时间:V8 的完整编译过程非常耗时(可能长达数小时),请耐心等待。
  5. 内存消耗:编译过程,尤其是 Debug 版本,需要大量的系统内存(建议 16GB 或以上)。
  6. 错误排查:若编译失败,请首先检查:
    • 环境变量 DEPOT_TOOLS_WIN_TOOLCHAINGYP_MSVS_VERSION 是否设置正确。
    • 是否在正确的 VS 开发者命令行中执行。
    • gn args 的配置参数是否有语法错误。

通过以上步骤,你应该能够在 Windows 平台成功编译出适用于特定需求的 V8 引擎库,并将其集成到自己的 C++ 项目中。

posted @ 2024-04-12 15:35  倚剑问天  阅读(707)  评论(0)    收藏  举报