news 2026/10/15 3:48:55

React Native 鸿蒙化启用 Hermes V1 引擎:从源码构建到字节码验证的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
React Native 鸿蒙化启用 Hermes V1 引擎:从源码构建到字节码验证的完整指南
  • OpenHarmony
  • 移动开发
  • 跨平台

【免费下载链接】ohos_react_native

React Native鸿蒙化仓库

项目地址:https://gitcode.com/CPF-RN/ohos_react_native
点击查看免费下载

本文基于 ohos_react_native(React Native 鸿蒙化仓库,简称 RNOH)中的实验特性说明文档 packages/react-native-harmony/scripts/hermesv1.md,完整讲解 Hermes V1 引擎的启用流程。文章将覆盖:Hermes V1 二进制源码构建(仅 macOS)、hermes-compiler覆盖安装、Hermes V1 字节码打包、原生侧 CMake 开关配置,以及构建日志、objdump字节码版本与运行时属性三层验证手段,并结合仓库源码(build-hermes.sh、hermesv1_cmakelists.patch、bundle-harmony.ts、各CMakeLists.txt)逐层解释其底层原理。

一、Hermes V1 是什么:实验特性与适用前提

在 React Native 鸿蒙化体系中,Hermes 是默认的 JavaScript 引擎(见 packages/react-native-harmony/scripts/resources/react-native-harmony.cmake 中if(USE_HERMES) ... target_link_libraries(... hermesvm ...)的默认分支)。而Hermes V1是仓库提供的一套独立于社区主线的 Hermes 引擎变体:它从 Facebook Hermes 仓库的特定稳定分支250829098.0.0-stable检出并固定到提交3477757eb2475555cf8d8df24bfb1deb0613880d,再打上鸿蒙化适配补丁后编译产出。

在深入流程前,必须明确两点关键前提:

  1. 实验特性,默认不开启:原文档明确说明,Hermes V1 当前仅是实验性功能,默认不启用,现阶段只能保证其"能正常运行",尚不能等同于稳定的生产能力。因此在生产项目中启用它需自行评估风险。
  2. 构建环境限制:Hermes V1 二进制只能在 macOS 上构建。仓库中 packages/react-native-harmony/scripts/build-hermes.sh 里对hermesc主机构建、交叉编译工具链的使用方式也表明,整个构建链依赖 macOS 环境的工具链组织(bundle-harmony.ts中hermesc的路径解析同样按darwin/linux/win32三平台区分,但 Hermes V1 的源码构建环节以 macOS 为准)。

从源码结构看,Hermes V1 与社区版 Hermes 的差异主要体现在三处:

  • 版本基线不同:社区版按HERMES_TAG="hermes-v0.17.0"(对应 RN 0.86.3)浅克隆,而 V1 按HERMES_V1_BRANCH="250829098.0.0-stable"单分支克隆并锁定固定提交,产出版本号固定为250829098.0.17(见 build-hermes.sh 第 19-23 行)。
  • 构型不同:V1 分支在 32 位(armeabi-v7a)上存在内联汇编约束问题无法构建,因此ARCHITECTURES只含arm64-v8a与x86_64;社区版则额外包含armeabi-v7a。
  • 鸿蒙化补丁不同:V1 应用 packages/react-native-harmony/scripts/hermesv1_cmakelists.patch,社区版应用hermes_cmakelists.patch。

Hermes V1 补丁中的鸿蒙适配要点

V1 专属补丁hermesv1_cmakelists.patch的内容可以印证 V1 变体与鸿蒙(OHOS)系统的深度绑定:

  • 移除 Android 专属依赖:注释掉find_package(fbjni REQUIRED CONFIG)与add_subdirectory(android/intltest/java/com/facebook/hermes/test),使 Hermes 源码可在非 Android 平台(OHOS)上独立编译;
  • Linux/OHOS 内存标记适配:将OSCompatPosix.cpp中PR_SET_VMA/vm_name相关的#ifdef __ANDROID__扩展为#if defined(__linux__) || defined(__ANDROID__),使匿名内存命名机制在 Linux 内核(鸿蒙底层)上生效;
  • 新增 restrace 内存追踪插桩:新增include/hermes/Support/restrace.h,并在CompactArray、ArrayStorage、CopyableVector、DictPropertyMap、HadesGC、MallocGC等核心数据结构和 GC 路径上以弱符号方式(__attribute__((weak)))调用restrace/resTraceMove/resTraceFreeRegion,实现对RES_RN_HERMES_HEAP堆内存的分配、迁移、释放追踪,便于鸿蒙系统侧进行内存监控与异常定位;
  • 扩展 JSI 接口:为Runtime增加getObjectProperties虚方法,用于枚举对象属性,供鸿蒙侧集成使用。

这些补丁内容决定了 V1 构建产物与社区版 Hermes 在行为上存在差异,因此不能直接复用社区版构建产物,必须按下文流程单独构建。

二、Step 1:在 macOS 上构建 Hermes V1 二进制

2.1 环境准备

在运行构建命令前,请确认:

  • 使用macOS系统;
  • 已配置好鸿蒙开发环境,即DEVECO_SDK_HOME环境变量已定义。构建脚本会在开头直接检查该变量,未定义时立即报错退出:
if [ -z "$DEVECO_SDK_HOME" ]; then echo "Environment variable DEVECO_SDK_HOME is not defined" exit 1 fi
  • 已在本仓库根目录安装好依赖(pnpm install),仓库根 package.json 已通过"overrides": { "hermes-compiler": "250829098.0.17" }将hermes-compiler固定到 Hermes V1 配套版本。

2.2 执行构建

在仓库根目录执行:

pnpm build:hermesv1

该命令由根 package.json 的脚本"build:hermesv1": "pnpm run --filter ./packages/react-native-harmony build:hermesv1"转发到 packages/react-native-harmony/package.json 中定义的:

"build:hermesv1": "cross-env HERMES_V1_ENABLED=true sh ./scripts/build-hermes.sh", "build:hermesv1:debug": "cross-env HERMES_V1_ENABLED=true HERMES_ENABLE_DEBUGGER=true sh ./scripts/build-hermes.sh"

两者差异仅在于HERMES_ENABLE_DEBUGGER是否置为true:

  • build:hermesv1:关闭调试器,CMAKE_BUILD_TYPE=MinSizeRel,编译选项-O3 -DNDEBUG,产物进入prebuilt/release/目录;
  • build:hermesv1:debug:开启调试器(HERMES_ENABLE_DEBUGGER=True),编译选项-g,产物进入prebuilt/debug/目录。

2.3 构建脚本做了什么(源码级解读)

build-hermes.sh 的完整执行逻辑如下:

  1. 确认环境变量:检查DEVECO_SDK_HOME(见上文),并从DEVECO_SDK_HOME/default/openharmony/native定位 OHOS Native SDK(cmake、ninja、工具链)。
  2. 克隆并固定 Hermes 源码:在$OUTPUT_DIR/hermes(packages/react-native-harmony/scripts/out/hermes)克隆 V1 分支并git checkout到固定提交。
  3. 应用 V1 补丁:git apply hermesv1_cmakelists.patch,若失败则提示人工修复后重新生成补丁。
  4. 确定目标架构:V1 模式下仅arm64-v8a与x86_64(跳过 armeabi-v7a)。
  5. 先构建主机的hermesc编译器:使用 OHOS SDK 的 cmake 配置-DJSI_DIR=$JSI_DIR -DCMAKE_BUILD_TYPE=Release并构建hermesc目标。这一步产出的hermesc会被作为"导入主机编译器"(IMPORT_HOST_COMPILERS)用于后续交叉编译。
  6. 交叉编译 Hermes 运行时:对每个架构,以-DCMAKE_SYSTEM_NAME=OHOS、-DOHOS_ARCH=$ARCHITECTURE、-DOHOS_STL=c++_shared、-DCMAKE_TOOLCHAIN_FILE=ohos.toolchain.cmake、-DHERMES_IS_ANDROID=True、-DHERMES_RELEASE_VERSION="$HERMES_RELEASE_VERSION"、-DHERMES_ENABLE_INTL=False、-DHERMES_UNICODE_LITE=True、-DHERMESVM_HEAP_HV_MODE=HEAP_HV_PREFER32等参数配置,再用 ninja 构建hermesvm目标产出libhermesvm.so。
  7. 符号分离与产物拷贝:用llvm-objcopy/objcopy对libhermesvm.so做--only-keep-debug提取.sym、--strip-debug剥离调试符号、--add-gnu-debuglink建立调试链接,并把libhermesvm.so、.sym、.debug.txt(含 Build ID、架构、构建类型、时间戳)拷贝到packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/prebuilt/{release|debug}/{arm64-v8a|x86_64}/目录下。

当前仓库 prebuilt 目录 中已可见debug/与release/两个目录,各含arm64-v8a、x86_64两个架构的libhermesvm.so、.sym与.debug.txt,正是该构建流程的产物落点。

三、Step 2:配置 Hermes 编译器覆盖(overrides)

Hermes V1 的字节码必须由配套的hermesc编译器生成,因此需要在仓库根目录的package.json中为hermes-compiler包添加覆盖版本:

"pnpm": { "overrides": { "hermes-compiler": "250829098.0.17" } }

注:250829098.0.17即为HERMES_V1_VERSION(见 build-hermes.sh 第 23 行),它与 V1 运行时版本严格对应,混用其他版本的编译器与运行时可能产生字节码版本不匹配。

随后执行安装,使覆盖生效:

pnpm install

在仓库中,根 package.json 实际使用的是简化写法"overrides": { "hermes-compiler": "250829098.0.17" }(pnpm 的pnpm.overrides简写),效果与原文档中的完整写法一致。安装完成后,node_modules/hermes-compiler下即为 V1 配套的hermesc。

为什么编译器版本必须与运行时一致

打包链路中,bundle-harmony命令(packages/react-native-harmony-cli/src/commands/bundle-harmony.ts)会根据HERMES_V1_ENABLED环境变量选择编译器路径:

const isHermesV1Enabled = process.env.HERMES_V1_ENABLED?.toLowerCase() === 'true'; const HERMESC_PATH_PREFIX = pathUtils.normalize( isHermesV1Enabled ? './node_modules/hermes-compiler/hermesc' : './node_modules/react-native/sdks/hermesc/' );

即:V1 模式默认使用node_modules/hermes-compiler/hermesc(这正是 overrides 替换的目标包),非 V1 模式使用react-native/sdks/hermesc。Hermes 的 HBC 字节码带版本标识,运行时加载字节码时会校验版本,因此编译器与运行时版本错配会导致运行期失败——这也是验证环节(下文)要专门检查字节码版本#0x62的原因。

四、Step 3:使用 Hermes V1 编译器打包 JavaScript

进入 tester 工程并执行 V1 打包:

cd packages/tester pnpm bundle:hermesv1

对应的脚本定义在 packages/tester/package.json:

"bundle:hermesv1": "cross-env RNOH_TESTER_ONLY__TARGET_PLATFORM=harmony react-native bundle-harmony --dev=false --minify=true --js-engine=hermes --hermesc-dir ../../node_modules/hermes-compiler/hermesc"

该脚本要点解析:

  • --dev=false --minify=true:生产模式,关闭警告并压缩;
  • --js-engine=hermes:指示bundle-harmony生成HBC 字节码而非普通 JS 包。从 bundle-harmony.ts 看,jsEngine为hermes时默认输出文件名为hermes_bundle.hbc,并且只有当输出路径以.hbc结尾时才会走saveHbcBundle的字节码编译分支;
  • --hermesc-dir ../../node_modules/hermes-compiler/hermesc:显式指定编译器为 V1 配套的hermesc。saveHbcBundle内部会按平台拼接二进制路径(osx-bin/hermesc、linux64-bin/hermesc、win64-bin/hermesc.exe),并校验该路径存在,否则抛出Couldn't find hermesc at ...的引导性错误;
  • 可通过--hermesc-options追加传给hermesc的额外选项,例如--hermesc-options O g reuse-prop-cache(见bundle-harmony.ts的选项说明)。

打包完成后,字节码产物默认输出到harmony/entry/src/main/resources/rawfile/hermes_bundle.hbc,资源同时拷贝至harmony/entry/src/main/resources/rawfile/assets。

五、Step 4:配置原生构建以启用 V1 运行时

Hermes V1 在原生侧的启用通过 CMake 变量HERMES_V1_ENABLED控制。有两种方式:

方式 A:直接编辑 tester 工程的 CMakeLists.txt

编辑文件 packages/tester/harmony/react_native_openharmony/src/main/cpp/RNOH/JSEngine/hermes/CMakeLists.txt:

# 原来(第 1 行): set(HERMES_V1_ENABLED OFF CACHE BOOL "Build with support for Hermes v1") # 改为: set(HERMES_V1_ENABLED ON CACHE BOOL "Build with support for Hermes v1")

方式 B:通过 CMake 命令行参数传入

在你的 cmake 构建配置中加入(具体方式取决于工程构建脚本组织):

-DHERMES_V1_ENABLED=ON

在实际工程中,更常见的做法是在build-profile.json5的externalNativeOptions.arguments数组中加入"-DHERMES_V1_ENABLED=ON"。仓库中 tester 各模块的 build-profile.json5 已经通过arguments传入-DRNOH_APP_DIR、-DWITH_HITRACE_SYSTRACE=ON等参数,可仿照追加。

HERMES_V1_ENABLED 在构建链中的实际作用

  • 在 tester 根 CMake 配置 packages/tester/harmony/react_native_openharmony/src/main/cpp/CMakeLists.txt 中:if (USE_HERMES) set(HERMES_V1_ENABLED ON) endif(),即默认使用 Hermes 时 V1 即被置为 ON,并在第 106 行打印HERMES_V1_ENABLED is set to: ${HERMES_V1_ENABLED}供日志验证;
  • 在 Hermes 集成子 CMake packages/tester/harmony/react_native_openharmony/src/main/cpp/RNOH/JSEngine/hermes/CMakeLists.txt 中:当HERMES_V1_ENABLED为真时,会向hermes_executor_common、bridgelesshermes、hermes_inspector_modern三个目标注入HERMES_V1_ENABLED=1编译宏(第 38-42 行)。该宏的作用可从 packages/react-native.patch 中看到:#if defined(HERMES_ENABLE_DEBUGGER) && !defined(HERMES_V1_ENABLED)这类条件编译逻辑表明,V1 模式下会跳过某些仅用于社区版调试器的适配分支(如HermesExecutorRuntimeAdapter、调试器强引用封装等),从而适配 V1 运行时与鸿蒙侧的集成差异;
  • 该 CMake 还会根据HERMES_ENABLE_DEBUGGER选择链接prebuilt/debug/${OHOS_ARCH}/libhermesvm.so或prebuilt/release/${OHOS_ARCH}/libhermesvm.so——这正好对应 Step 1 中选择build:hermesv1还是build:hermesv1:debug构建。

六、Step 5:构建并运行应用

完成上述配置后,按 tester 工程的常规方式构建并运行:

cd packages/tester/harmony # 使用 DevEco Studio / hvigor 构建 HAP,或使用: pnpm harmony # 在 packages/tester 下,等价 react-native run-harmony

应用启动时加载hermes_bundle.hbc,由 V1 运行时解释执行。

七、验证:确认 Hermes V1 真正生效

原文档提供了三层验证手段,由浅入深。

7.1 构建日志验证

在 CMake 配置输出中查找:

HERMES_V1_ENABLED is set to: ON

该日志在 tester 根 CMakeLists.txt(第 106 行)、hermes 集成 CMakeLists.txt(第 2 行)以及 react-native-harmony.cmake(第 47 行)中均会打印,说明 V1 开关在各级 CMake 配置中均被正确传递。

7.2 字节码版本验证(objdump)

运行以下命令,检查输出中是否打印了#0x62:

objdump -d packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/prebuilt/debug/arm64-v8a/libhermesvm.so | grep -A 2 getBytecodeVersion | grep "mov.*#0x" | awk '{print $5, $6}'
  • 该命令反汇编libhermesvm.so,在getBytecodeVersion符号附近查找mov ... #0x...立即数加载指令;
  • 0x62(十进制 98)即 Hermes V1(250829098.0.17)对应的字节码版本号。若输出为#0x62,说明运行时支持的字节码版本与 V1 编译器产物一致;
  • 注意命令中路径为debug/arm64-v8a,若构建的是 release 产物,应相应替换为prebuilt/release/arm64-v8a/libhermesvm.so;
  • 前提:需要本机安装objdump/binutils。若不可用,可跳过此项,直接进行运行时验证。

7.3 运行时属性验证

在应用 JS 侧调用 Hermes 内部 API,检查返回的版本号:

HermesInternal.getRuntimeProperties()["OSS Release Version"];

若 Hermes V1 正常运行,该调用应返回"250829098.0.17"——该版本字符串正是构建脚本中HERMES_V1_VERSION="250829098.0.17"(build-hermes.sh 第 23 行)通过-DHERMES_RELEASE_VERSION="$HERMES_RELEASE_VERSION"编译进运行时的,因此可作为运行时确实为 V1 的最直接证据。

八、常见问题与注意事项

  1. 构建必须使用 macOS:pnpm build:hermesv1依赖 macOS 环境组织工具链与主机编译器,Windows/Linux 上无法完成 Hermes V1 源码构建;而使用编译好的二进制进行打包(Step 2-3)与原生集成(Step 4-5)不限于 macOS。
  2. DEVECO_SDK_HOME未定义:构建脚本会在入口直接报错Environment variable DEVECO_SDK_HOME is not defined,请先完成鸿蒙原生开发环境配置。
  3. hermesc 路径不存在:执行bundle:hermesv1前请确认pnpm install已生效(overrides 已落地),否则saveHbcBundle会抛出Couldn't find hermesc at ...。
  4. 架构限制:Hermes V1 仅构建arm64-v8a与x86_64,不支持 32 位架构;若目标设备/模拟器为 32 位,无法使用 V1。
  5. 实验性质:V1 当前只保证基本功能正常,官方(仓库说明)不承诺其生产级稳定性;社区版 Hermes(hermes-v0.17.0)仍是默认基线。
  6. release/debug 产物要匹配:Step 1 中选择的构建模式(build:hermesv1或build:hermesv1:debug)需与 Step 4 构建时的HERMES_ENABLE_DEBUGGER状态对应,CMake 会根据该变量从prebuilt/release或prebuilt/debug中选取libhermesvm.so。

九、结语:Hermes V1 启用路径一览

回顾全文,启用 Hermes V1 的完整链路为:

步骤操作关键命令/配置产物/落点
1构建 V1 二进制(仅 macOS)pnpm build:hermesv1(或:debug)third-party/prebuilt/{release\|debug}/{arm64-v8a,x86_64}/libhermesvm.so
2覆盖编译器版本pnpm.overrides.hermes-compiler = 250829098.0.17+pnpm installnode_modules/hermes-compiler/hermesc
3编译 JS 为 V1 字节码cd packages/tester && pnpm bundle:hermesv1hermes_bundle.hbc(rawfile)
4启用 V1 原生开关编辑RNOH/JSEngine/hermes/CMakeLists.txt或-DHERMES_V1_ENABLED=ON编译宏HERMES_V1_ENABLED=1注入各 Hermes 目标
5构建运行pnpm harmony/ DevEco 构建应用加载 HBC 运行
验证三层验证CMake 日志 /objdump ... #0x62/HermesInternal...确认 V1 生效

该链路中,"编译器版本覆盖 + 字节码打包 + 原生开关 + 运行时版本核对"四个环节环环相扣:编译器决定字节码格式,运行时决定能否加载该格式,任何一环版本错配都会导致失败。本文中涉及的构建脚本(build-hermes.sh)、V1 补丁(hermesv1_cmakelists.patch)、打包命令(bundle-harmony.ts)与各级 CMake 配置均已给出仓库内路径,读者可对照源码进一步深入验证。

  • OpenHarmony
  • 移动开发
  • 跨平台

【免费下载链接】ohos_react_native

React Native鸿蒙化仓库

项目地址:https://gitcode.com/CPF-RN/ohos_react_native
点击查看免费下载

相关推荐

上一篇:G6 图可视化引擎入门指南:从核心能力到快速上手(AntV G6 手册 Introduction 深度解读)
下一篇:Agent Substrate 声明式 API 验证(DV)实践指南:基于 Kubernetes validation-gen 的字段校验体系

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

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

联盟场-提高组-R4 ZYZSC-S-Round 7

QOJ7018 Insertion Sort 原题链接:Insertion Sort 分析 分讨的本质就是有问题的。如果继续容斥的话,那就完蛋了。 正确的式子就是: ansk!(1Cn−k1Cn−11)ansk!\times(1C_{n-k}^{1}\times C_{n-1}^{1}) ansk!(1Cn−k1​Cn−11​) 就是相当于…

作者头像 李华
网站建设 2026/10/15 3:47:41

OpenEMR免费部署指南:从零搭建一套完整的开源电子病历系统

OpenEMR免费部署指南:从零搭建一套完整的开源电子病历系统 【免费下载链接】openemr The most popular open source electronic health records and medical practice management solution. 项目地址: https://gitcode.com/GitHub_Trending/op/openemr OpenE…

作者头像 李华
网站建设 2026/10/15 3:47:24

【点此获取源码】联系博主获取计算机毕设选题以及答辩资料

🙊作者简介:多年一线开发工作经验,分享技术代码帮助学生学习。自有计算机毕设的工作室团队,专注计算机毕设开发、定制、远程、文档编写指导等。👍 文末查看联系方式 ⭐🍅 文末查看联系方式🍅 ⬇…

作者头像 李华
网站建设 2026/10/15 3:45:54

cloudpods 中的 JWE 数据加密:基于 lestrrat-go/jwx 的 RFC 7516 加密实战指南

后端云原生运维虚拟化人工智能AI 应用 【免费下载链接】cloudpods 开源、云原生的多云管理及混合云融合平台 项目地址: https://gitcode.com/yunionio/cloudpods 点击查看 免费下载 导读 本文以 cloudpods 仓库内置的 vendor/github.com/lestrrat-go/jwx/jwe 包为…

作者头像 李华