0.环境配置
1.安装了在环境变量里面的Python310和Git
2.安装有VS2022(可能需要安装上使用C++的桌面开发
、通用Windows平台开发
)
3、所有解压或安装的路径,不要有中文
1.下载开发工具-depot
需要确保Python3.10.12已经安装,并且Python的安装目录在环境变量里面。
之后的gclient、gn、git等命令都是depot_tools目录里的。
找到Download链接下载包
新建一个depot_tools文件夹解压压缩包,然后把文件夹路径添加到PATH环境变量里面
注意:depot_tools要在所有其它路径之前。
2.安装编译工具-ninja
打开cmd,找一个合适的目录,然后git克隆ninja项目,我是直接在E盘根目录搞
git clone https://github.com/ninja-build/ninja.git
然后进入ninja项目文件夹,调用git检出release
cd ninja
git checkout release
接下来打开vs的开发人员命令提示符Developer Command Prompt for VS 2022
如下图,进入ninja项目文件夹,运行下面的命令编译ninja
python configure.py --bootstrap
运行完成后就能看到ninja.exe在ninja项目文件夹里面
直接把它移动到之前下载解压的depot_tools目录下
3.选择v8项目源代码
V8已经停止在官方网站发布博客来公布最新稳定版本
我们需要访问谷歌的分支详情页
https://chromiumdash.appspot.com/branches
我选择了一年前的104版本(试过10.9版本,我编译一直失败)
记下对应的v8版本,10.4-lkgr
4.下载v8配置项目
找到一个合适的地方创建空文件夹v8,打开cmd,设定工作目录到v8文件夹
我们先设置一个环境变量,不然谷歌的工具不会下载Windows相关的依赖
set DEPOT_TOOLS_WIN_TOOLCHAIN=0
在cmd运行以下命令拉取源代码
fetch v8
拉取比较费时间,哪怕你的代理能到10MB/s也要几分钟才能拉取完
拉取代码完成后,我们可以看到它在我们的v8文件夹里面又创建了一个v8文件夹
所以说先进入v8文件夹
cd v8
接着检出我们记录的10.4-lkgr版本
git checkout 10.4-lkgr
确保你的cmd执行过开头的环境变量设置命令,
运行以下命令,depot_tools会根据此目录文件 自动下载和更新依赖文件
gclient sync -v
如果这一步报错,八成是忘记了设置环境变量set DEPOT_TOOLS_WIN_TOOLCHAIN=0
5.编译v8 x64 release动态库
设置编译信息,动态库编译模式
python3 tools\dev\v8gen.py x64.release -vv -- is_component_build=true v8_static_library=false
如果提示未安装vs2022、2019啥的,添加一个vs2022_install和GYP_MSVS_OVERRIDE_PATH的环境变量就行
再次编译,我们可以看到又报错了
提示You must install Windows 10 SDK version 10.0.20348.0 including the "Debugging Tools for Windows" feature.
所以说我们需要安装Windows 10 SDK,打开Visual Studio Installer
点击修改
选择单个组件,搜索Windows 10 SDK,勾上报错信息提示的版本,点击修改
如果你这里已经是勾上的,那么直接关闭Visual Studio Installer,进入下一步
完成后关闭Visual Studio Installer,在Windows搜索栏搜索添加或者删除程序
搜索Windows Software Development Kit.找到我们的版本,点击修改
选择Change,然后点击Next
勾上Debugging Tools for Windows,点击Change
完成后关闭窗口,回到cmd窗口,重新生成编译配置
python3 tools\dev\v8gen.py x64.release -vv -- is_component_build=true v8_static_library=false
配置生成成功了
使用ninja编译
ninja -C out.gn\x64.release
然后这个过程CPU会吃满,最好不要干其它事情。
跑完要个十几分钟,耐心等待。
跑完后我们进入v8\v8\out.gn\x64.release\文件夹
往下翻能找到d8.exe,打开看看正不正常
随便输入一串js代码看看结果
console.log("test"+4*8),5*7;
输出test32,返回35,说明编译的很成功
在别的地方创建个文件夹,先复制出运行时:
d8.exe
icudtl.dat
icui18n.dll
icuuc.dll
libc++.dll
snapshot_blob.bin
v8.dll
v8_libbase.dll
v8_libplatform.dll
zlib.dll
这就是动态版本v8程序运行所需的dll,运行d8.exe发现可以正常运行(路径包含中文会导致无法双击运行)
注:d8.exe仅供测试,它并不是运行v8所必须的
我们如果用动态方法调用v8,还需要dll文件对应的lib,所以说再创建个lib文件夹,复制出以下文件:
v8.dll.lib
v8_libbase.dll.lib
v8_libplatform.dll.lib
当我们能把上面的include和lib文件加入自己的项目的时候,编译报错提示
看来动态库不行,得用静态库
5.编译v8 x64静态库
回到v8\v8,我们删除out.gn文件夹
如果之前的cmd被关闭了,运行set DEPOT_TOOLS_WIN_TOOLCHAIN=0设置环境变量
在v8\v8下运行以下命令生成静态编译配置
使用gn命令编译,咱们先来看看它支持的参数说明
gn args out/x64.debug --list
我在后面直接把编译要用到的配置参数写好了
【debug版本】
···
gn args out/x64.debug
···
这个时候会自动弹出一个记事本,我们不要关闭它
往记事本里面输入这些配置
v8_monolithic=true
v8_use_external_startup_data=false
use_custom_libcxx=false
is_component_build=false
treat_warnings_as_errors=false
v8_symbol_level=0
is_clang=false
target_cpu = "x64"
enable_iterator_debugging=true
is_debug=true
输入后配置文件的内容应该和下图一样
然后我们Ctrl+S保存,然后关闭记事本窗口
等待一会,可以看到进度跑完了
用ninja编译
ninja -C out/x64.debug v8_monolith
很耗时,等跑完后我们进入v8\v8\out\x64.debug\obj文件夹
仔细寻找可以看到v8_monolith.lib,这个就是我们要的lib静态库了,大约450MB
【release版本】
···
gn args out/x64.release
···
这个时候会自动弹出一个记事本,我们不要关闭它
往记事本里面输入这些配置
v8_monolithic=true
v8_use_external_startup_data=false
use_custom_libcxx=false
is_component_build=false
treat_warnings_as_errors=false
v8_symbol_level=0
is_clang=false
target_cpu = "x64"
enable_iterator_debugging=false
is_debug=false
然后我们Ctrl+S保存,然后关闭记事本窗口
等待一会,可以看到进度跑完了
用ninja编译
ninja -C out/x64.release v8_monolith
这个过程也耗时,耐心等待编译完成
跑完后我们进入v8\v8\out\x64.release\obj文件夹
仔细寻找可以看到v8_monolith.lib,这个就是我们要的lib静态库了,大约280MB
编译32位库
如果是要生成32位的版本,那么只需要在配置中加入target_cpu = "x86"这个参数即可,目录名字随便取,比如gn args out/x86.debug
添加到项目
0.把lib复制到项目中
1、把v8的include文件夹复制到项目中,然后在项目属性,vc++目录,添加这个目录
2、附加依赖项
winmm.lib
shlwapi.lib
dbghelp.lib
3、添加预处理V8_COMPRESS_POINTERS
在移植过程中,遇到了初始化V8::Initialize()崩溃的问题,经过多方查找,终于确定和V8_COMPRESS_POINTERS导致的问题。
V8_COMPRESS_POINTERS是v8新加入的功能。可以节省不少内存占用。
如果设置v8_enable_pointer_compression = false就会关闭。
如果关闭了该功能,程序可以正常运行。
实际上,该功能只会在64位上开启。因为该功能是将64位指针压缩为32位指针。默认是开启的,那么项目中就需要加入V8_COMPRESS_POINTERS标识,否则会指针异常导致程序崩溃。
4、运行库 选MTd或MT
5、使用代码
//v8
#include "include/v8/include/v8.h"
#include "include/v8/include/libplatform/libplatform.h"
#ifdef _DEBUG
# pragma comment(lib, "include/v8/lib/x64/debug/v8_monolith.lib")
#else
# pragma comment(lib, "include/v8/lib/x64/release/v8_monolith.lib")
#endif
int runV8b() {
// 初始化V8
string v8_path = StringParse::WStringToString(OS::GetCurrentPath() + L"v8\\");
bool ret = v8::V8::InitializeICUDefaultLocation(v8_path.c_str());
printf("ret=%d\n", (int)ret);
//v8::V8::InitializeExternalStartupData(v8_path.c_str());
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
v8::V8::Initialize();
// 2、创建一个新的隔离区,并将这个隔离区置为当前使用
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
// 4、创建一个上下文
v8::Isolate* isolate = v8::Isolate::New(create_params);
{//括号不能少,这样括号里面的变量都是局部变量,后面isolate可以顺畅的Dispose,不会出错
// 3、创建一个栈分配的句柄范围
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
// 创建一个新的上下文
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
// 编译并运行JavaScript代码
const char* js_code = "'Hello' + ' World!'";
v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, js_code).ToLocalChecked();
v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
// 将结果转换为C++字符串并打印
v8::String::Utf8Value utf8(isolate, result);
std::cout << "JavaScript执行结果: " << *utf8 << std::endl;
}
// 清理V8
isolate->Dispose();
v8::V8::Dispose();
v8::V8::DisposePlatform();
delete create_params.array_buffer_allocator;
return 0;
}