news 2026/9/16 19:29:06

workerd 的 V8 版本升级全流程指南:从补丁 Rebase 到 Bazel 依赖同步

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
workerd 的 V8 版本升级全流程指南:从补丁 Rebase 到 Bazel 依赖同步

workerd 的 V8 版本升级全流程指南:从补丁 Rebase 到 Bazel 依赖同步

【免费下载链接】workerdThe JavaScript / Wasm runtime that powers Cloudflare Workers项目地址: https://gitcode.com/GitHub_Trending/wo/workerd

导读

workerd(Cloudflare Workers 的 JavaScript / Wasm 运行时)深度内嵌 Google V8 引擎,并在其上维护了一套用于支撑 Workers 平台特性的定制补丁。当 Chrome Beta 推进 V8 版本时,workerd 需要把整套补丁迁移到新版本之上,并同步更新 Bazel 构建配置中的版本号、完整性校验值与对齐依赖。本文以仓库中的官方升级文档 docs/v8-updates.md 为骨架,结合 ci/v8_update.py 等源码实现,完整讲解手动升级的 12 个步骤与半自动更新助手的使用方法。读完本文,你将掌握 workerd 的 V8 升级机制、补丁再生成与依赖对齐的底层原理,能够独立完成一次完整的 V8 版本升级。

为什么 workerd 要单独维护 V8

V8 是 workerd 的运行时核心,但 workerd 并不直接使用上游原版 V8。仓库通过 Bazel 模块 build/deps/v8.MODULE.bazel 拉取 V8 官方源码 tarball,并在其上叠加一组自定义补丁。该文件头部注释解释了关键约束:googlesource 生成的 tarball 不具备确定性,无法使用http_archive,因此 V8 本体通过 GitHub 官方镜像以 tarball 方式引入,而 zlib(Chromium fork)、icu(Chromium fork)、trace_event 等依赖仍必须走 git 协议。

该文件的核心配置块如下(当前仓库中的实际取值):

  • VERSION = "15.3.76.11":当前锁定使用的 V8 版本标签;
  • INTEGRITY = "sha256-zhD6KsBTOQwTXzj1uuZ5gVbYJENz9+R38eAGOF0OCk0=":tarball 的 SHA-256 校验值(Bazel 偏好格式);
  • PATCHES = [...]:依次列出 patches/v8 下按数字前缀命名的补丁文件(当前为00010041共 41 个);
  • http_archive:从https://github.com/v8/v8/archive/refs/tags/<VERSION>.tar.gz下载,strip_prefixv8-<VERSION>,并按PATCHES列表逐个应用-p1补丁;
  • git_repository:拉取llvm-libc(Chromium googlesource 镜像)供 V8 使用;
  • local_path_override:将perfetto_cfggoogle_benchmark指向仓库内的build/perfettobuild/google-benchmark,并通过@workerd-v8间接引用 V8,以便内部非开源仓库可以覆写 V8 的构建方式。

这些补丁并非装饰品,而是 workerd 平台能力的一部分。例如 0001-Allow-manually-setting-ValueDeserializer-format-vers.patch 为 V8 的ValueDeserializer增加了SetWireFormatVersion()方法,允许 workerd 读取历史上缺失版本头的序列化数据时显式指定线格式版本;0006-Implement-Promise-Context-Tagging.patch0013-Implement-cross-request-context-promise-resolve-hand.patch等则与 Workers 的 Promise 上下文语义相关。正因为补丁与业务强耦合,升级 V8 不是简单改一个版本号,而是一次完整的补丁迁移工程。

升级前的准备工作

升级流程的第一步是确定目标版本。官方文档建议访问 Chromium Dash(chromiumdash.appspot.com),查看 Chrome Beta 渠道使用的 V8 版本——workerd 以 Chrome Beta 的 V8 为跟踪目标,这与 ci/v8_nightly.py 中通过chromiumdash.appspot.com/fetch_releases?platform=Win32&channel=beta探测最新 Beta V8 版本号的逻辑一致(latest_beta_v8()函数)。

随后需要在本机安装 Google 的depot_tools(提供fetchgclient等工具)。安装方式见 depot_tools 官方教程的 Setting up 一节,这里不再赘述。

获取 V8 源码时,官方文档特别强调:

mkdir v8 cd v8 fetch v8

并提醒务必把 V8 副本放在 workerd 仓库之外,否则仓库内的 V8 源码树可能干扰 Bazel 的依赖解析与//...通配构建。接下来把本地 V8 同步到 workerd 当前锁定的旧版本(记为<old_version>):

cd <path_to_v8>/v8 git checkout <old_version> gclient sync

其中<old_version>就是从build/deps/v8.MODULE.bazel中读出的VERSION值。gclient sync会把 V8 的 DEPS 文件声明的所有子依赖(icu、dragonbox、fast_float 等)一并检出到与<old_version>匹配的版本。

手动升级 V8 的 12 步流程

这是官方文档的核心章节,以下逐步展开。

第 1~3 步:确定目标版本并准备 V8 副本

即上一节所述:确认 Chrome Beta 的最新 V8 版本号、安装depot_tools、在仓库外fetch v8

第 4 步:将本地 V8 同步到 workerd 当前版本

build/deps/v8.MODULE.bazel读取当前VERSION作为<old_version>,然后git checkout <old_version>gclient sync,确保工作区与 workerd 的基线完全一致。

第 5 步:创建补丁分支并应用 workerd 补丁

git checkout -b workerd-patches git am --keep-non-patch <path_to_workerd>/patches/v8/*

--keep-non-patch是与第 7 步git format-patch-k参数配套的:它保留上游 V8 提交自带的主题前缀(如[wasm]),这样第 7 步重新生成的补丁能沿用既有的文件名前缀与编号,便于PATCHES列表稳定维护。若git am中途失败,可先用git am --abort回退并排查具体补丁。

第 6 步:将 workerd 补丁 Rebase 到新版本

假设目标版本为<new_version>,执行:

git rebase --onto <new_version> <old_version>

由于 workerd 补丁基于旧版 V8 编写,升级后上下文往往发生偏移,rebase 过程中通常需要少量手工修补。官方文档建议在此阶段就完成带补丁的本地 V8 构建与测试(参见 V8 官方 Testing 文档),尽早暴露补丁与新版本的兼容问题,而不是等回到 workerd 仓库再排查。这一步也是整个流程中风险最高的环节——补丁的语义(尤其是涉及 Promise 上下文、序列化格式、内存分配等平台行为的改动)必须由人来确认在新版本中依然成立。

第 7 步:重新生成补丁

rebase 成功后,用git format-patch<new_version>基线导出补丁:

git format-patch --full-index --no-signature --no-stat --zero-commit <new_version>

各参数含义:

  • --full-index:diff 中输出完整的 blob 哈希,保证补丁在任何克隆中都稳定可应用;
  • -k:保留原始提交的 subject 前缀(对应第 5 步的--keep-non-patch);
  • --no-signature:去掉git format-patch默认追加的签名信息;
  • --no-stat:省略 diffstat 统计,缩小补丁体积;
  • --zero-commit:将补丁头部的 commit 哈希置零,避免暴露提交哈希差异。

第 8 步:替换仓库中的补丁

删除 patches/v8 下原有的补丁文件,把第 7 步在 V8 目录生成的补丁复制进来。ci/v8_update.pyfinish_update()在自动流程中正是先清空旧补丁,再用shutil.copy2复制新生成的补丁,以保留时间戳等元数据。

第 9 步:更新v8.MODULE.bazel中的 VERSION / PATCHES / INTEGRITY

在 build/deps/v8.MODULE.bazel 中:

  1. VERSION改为<new_version>
  2. 根据新增/删除的补丁刷新PATCHES列表;
  3. 更新INTEGRITY。官方文档给出两种获取方式:
    • 直接用新版本编译 workerd,从 Bazel 报告的完整性不匹配错误中读出 Bazel 偏好格式的校验值;

    • 或先下载https://github.com/v8/v8/archive/refs/tags/<new_version>.tar.gz,再执行:

      openssl dgst -sha256 -binary <tarball_filename> | openssl base64 -A

      得到的 base64 值前加上sha256-前缀即为INTEGRITYci/v8_update.py中的_tarball_integrity()函数用 Python 的hashlib.sha256base64实现了完全相同的计算逻辑("sha256-" + base64(...)),两者结果一致,可相互校验。

第 10 步:更新 V8 的依赖并重新生成deps.MODULE.bazel

V8 的部分第三方依赖以独立 Bazel 依赖的形式由 workerd 管理,记录在 build/deps/deps.jsonc 中。升级 V8 后需要把这些依赖的提交同步到新版本 V8 的DEPS文件所引用的提交(可在本地 V8 副本的<path_to_v8>/DEPS中找到)。

文档明确指出当前需要跟踪的依赖包括perfettocom_googlesource_chromium_icusimdutf,并给出了一个重要提醒:V8 是通过 Chromium 间接依赖perfettosimdutf,无法直接从 V8 的 DEPS 推断出 V8 对应的是 GitHub 上的哪个版本,因此对这两个依赖采取"直接升到 GitHub 最新版"的安全策略即可。

从 build/deps/deps.jsonc 的注释与 ci/v8_update.py 的V8_DEPENDENCIES映射可以确认更完整的依赖清单及其对齐方式:

依赖名(deps.jsonc 中的 name)V8 内路径是否与 V8 提交严格对齐
com_googlesource_chromium_icuthird_party/icu是(freeze_commit对齐)
dragonboxthird_party/dragonbox/src是(freeze_commit对齐)
fast_floatthird_party/fast_float/src是(freeze_commit对齐)
fp16third_party/fp16/src是(freeze_commit对齐)
highwaythird_party/highway/src是(freeze_commit对齐)
perfettothird_party/perfetto否(github_release,取最新版)
simdutfthird_party/simdutf否(github_release,取最新版)

其中 icu、dragonbox、fast_float、fp16、highway 在deps.jsonc中都带注释"我们想避免与 V8 产生版本偏差,所以使用完全一致的版本",并以freeze_commit锁定提交哈希。更新依赖后,运行依赖更新脚本重新生成deps.MODULE.bazel

python3 build/deps/update-deps.py

(脚本也支持指定单个依赖名进行定向更新,见下文助手章节。)

第 11 步:运行 workerd 测试套件

bazel test //...

官方文档要求在提交前确认整个仓库的测试在升级后的 V8 下全部通过。若测试失败,需要回到补丁层排查,必要时调整补丁内容。

第 12 步:提交并推送评审

build/deps/v8.MODULE.bazelbuild/deps/deps.jsoncpatches/v8/*.patch以及可能涉及的源码改动一并提交,推送到远程分支进行代码评审。

半自动更新助手:ci/v8_update.py

手动 12 步中有大量机械性工作(创建分支、应用补丁、rebase、重新生成补丁、更新版本号与校验值),ci/v8_update.py 将这些步骤自动化,官方文档也特别提示该脚本"尚未被充分测试,若执行失败请回退到手动流程,并仔细审查其改动"。

检查是否有可用更新:check-update

python3 ci/v8_update.py check-update

脚本通过latest_beta_v8()访问 Chromium Dash 获取 Chrome Beta 的 V8 版本,与 build/deps/v8.MODULE.bazel 中当前的VERSION比较:

  • 有新版本时:打印<current_version> -> <new_version>并以退出码1结束;
  • 已是最新时:不打印任何内容并以退出码0结束;
  • --machine-readable参数:仅打印新版本号(便于在脚本或 CI 中取用)。

执行更新:update <new_version>

python3 ci/v8_update.py update <new_version>

从源码看,prepare_update()的机械流程与手动步骤一一对应:

  1. 删除并重建临时目录/tmp/workerd-v8/v8(常量CHECKOUT);
  2. --depth=1浅克隆拉取oldtarget两个标签(该脚本默认远程为https://github.com/v8/v8.git);
  3. 基于旧版本检出workerd-patches分支;
  4. git am --keep-non-patch --3way --committer-date-is-author-date依次应用patches/v8/*.patch
  5. 执行git rebase --onto <target> <old> workerd-patches

若 rebase 顺利结束,脚本会立即调用finish_update()完成补丁再生成与配置更新;若 rebase 因冲突失败,脚本打印提示并返回失败,此时需要在临时检出中人工处理:

cd /tmp/workerd-v8/v8 git status # 解决冲突并把文件加入暂存区(git add) git rebase --continue

重复此过程直到 rebase 完成。官方文档特别强调:补丁冲突必须人工审查,以确保 workerd 特有的行为(序列化、Promise 上下文、内存管理等)在新版本中仍然被保留,而不是机械地解决行级冲突。

收尾:finish <new_version>

python3 ci/v8_update.py finish <new_version>

finish_update()在临时检出中执行git format-patch --full-index -k --no-signature --no-stat --zero-commit --output-directory ... <new_version>重新生成补丁,然后清空patches/v8并用copy2复制新补丁,最后更新:

  • build/deps/v8.MODULE.bazel 中的VERSIONINTEGRITY(由_tarball_integrity()实时下载 tarball 计算)与PATCHES列表;
  • build/deps/deps.jsonc 中 icu、dragonbox、fast_float、fp16、highway 的freeze_commit(由_update_aligned_dependencies()从 V8 新版本的DEPS文件正则提取提交哈希写入)。

官方文档明确警告:rebase 未完成前不要运行finish,否则会用半成品状态重新生成补丁并覆写锁定配置。

手动补完依赖更新与验证

助手不会运行update-deps.py。文档要求手工对比新旧两个版本 V8 的DEPS文件,检查dragonboxfast_floatfp16highwayperfettosimdutf的提交是否有变化,对每个发生变化的依赖定向执行依赖更新脚本:

python3 build/deps/update-deps.py <dependency>

这一步会重新生成对应的deps.MODULE.bazel内容(build/deps/update-deps.py 是仓库所有 Bazel 依赖的自动生成器,输出文件头部带有 "AUTOGENERATED DO NOT EDIT" 警告)。注意脚本目录下update-deps.pyTARGET_FILTER正是从命令行参数读取依赖名,实现"只更新某一个依赖"的定向能力。

随后完成手动流程的第 11、12 步:运行bazel test //...验证全部测试,审查生成的改动后提交推送。

与 CI 夜间任务的关系

ci/v8_update.py并非孤立存在。仓库中的 ci/v8_nightly.py 将其作为底层库复用(导入prepare_updatefinish_updatechanged_dependencieslatest_beta_v8等),实现"探测 Chrome Beta 新 V8 → 自动 rebase 补丁 → 更新对齐依赖 → 构建//src/workerd/server:workerd→ 运行bazel test //..."的夜间流水线;ci/v8_nightly_shared.py 则提供共享的 git/subprocess/日志基础设施,并在补丁冲突或构建失败时调用 AI 助手(opencode)在有限轮次内尝试修复。理解这套 CI 可以帮你判断:当你手动执行ci/v8_update.py时,走的正是与 CI 相同的代码路径,只是没有自动化的 AI 修复环节。

常见问题与注意事项

  • V8 副本必须放在仓库外:仓库内的 V8 源码树会干扰 Bazel 的依赖图与//...构建,务必遵循文档建议。
  • --keep-non-patch-k必须成对使用:前者在git am时保留 subject 前缀,后者在git format-patch时保留同一前缀,二者配合才能维持补丁文件名的稳定性。
  • rebase 冲突是常态而非例外:文档明确"通常会有少量补丁编辑工作",且ci/v8_nightly.py中补丁冲突默认需要 AI 辅助或人工审查,切勿盲目--skip跳过错失补丁语义。
  • INTEGRITY 必须与 tarball 严格对应:可交叉验证——ci/v8_update.py_tarball_integrity()与文档给出的openssl dgst -sha256 -binary ... | openssl base64 -A计算同一文件会得到相同结果。
  • perfetto / simdutf 不要尝试从 V8 DEPS 反推 GitHub 版本:二者经由 Chromium 间接依赖,直接升级到最新版即可;icu、dragonbox、fast_float、fp16、highway 则必须与 V8 的DEPS提交严格对齐,避免版本偏差导致编译或行为不一致。
  • 助手脚本并非金标准:官方文档承认ci/v8_update.py未经过充分测试,失败时回退到手动 12 步流程,并以bazel test //...的最终结果为准。

通过上述流程,workerd 得以始终跟进 Chrome Beta 的 V8 版本,同时保证 41 个平台定制补丁持续生效。无论你是想手动完成一次升级,还是希望借助ci/v8_update.py半自动推进,本文对应的文档 docs/v8-updates.md 与源码 ci/v8_update.py 都是可以直接照做的权威参考。

【免费下载链接】workerdThe JavaScript / Wasm runtime that powers Cloudflare Workers项目地址: https://gitcode.com/GitHub_Trending/wo/workerd

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 19:29:00

MPI并行计算实战指南:核心概念、通信机制与性能优化

做了这么多年并行计算&#xff0c;兜兜转转一大圈&#xff0c;发现最终绕不开的还是MPI。不管是搞科学计算、深度学习大规模训练&#xff0c;还是处理海量数据的分布式任务&#xff0c;MPI这套消息传递接口始终是绕不过去的基础设施。今天这篇总结&#xff0c;我不打算从教科书…

作者头像 李华
网站建设 2026/9/16 19:28:55

SpringBoot+Vue构建高效OA系统的核心技术解析

1. 项目背景与核心价值十年前我刚入行时&#xff0c;参与的第一个项目就是给某制造企业开发办公系统。当时用Struts2JSP硬撸了三个月&#xff0c;光是处理一个请假审批流程就写了2000多行代码。如今基于SpringBootVue的技术栈&#xff0c;同样的功能两天就能跑通。这个技术组合…

作者头像 李华
网站建设 2026/9/16 19:28:17

内网Linux离线编译安装zlib、OpenSSL、PAM全攻略

前不久在客户现场碰到一个特别标准的内网项目&#xff1a;Linux 服务器完全隔离&#xff0c;数据库安装脚本一跑就报缺 zlib&#xff0c;OpenSSH 升级要新版 openssl&#xff0c;账号锁定策略依赖 pam 又一直不生效。离线安装 zlib、openssl、pam 这三个库&#xff0c;就这样变…

作者头像 李华
网站建设 2026/9/16 19:26:54

ESP8266 AT固件烧录与透传配置详解:从Flash布局到WiFi连接

简介&#xff1a;ESP8266-IDF-AT_V2.2.1.0.zip是乐鑫官方2022年发布的ESP8266 AT固件包&#xff0c;面向嵌入式开发者和物联网项目&#xff0c;用于通过AT指令快速接入Wi-Fi网络&#xff0c;实现透传、TCP/UDP通信、配网等典型场景&#xff0c;特别适合不深入协议栈但需要稳定联…

作者头像 李华
网站建设 2026/9/16 19:26:40

类型与对象:从底层原理到工程实践的完整梳理

类型和对象&#xff0c;是几乎所有编程语言教学里最容易被低估的两个词。哪怕你已经在写 Python、Java、C&#xff0c;每天和变量、类、接口打交道&#xff0c;一旦被问到"bool 和 int 有什么区别""对象在内存里到底怎么存""为什么 Vue 里对象赋值页面…

作者头像 李华