OpenHarmony ArkTS 编译器与运行时 x86 环境构建全记录

基于 ohos_master 分支(2026-06)源码分析
更新至最终可用的 CMake 独立构建方案


目录


1. 背景

在 OpenHarmony rk3568 产品(ARM 目标)构建环境中,需要编译新版 ArkTS 编译器并能在 x86-64 开发主机上执行编译产出的 .abc 字节码文件,完成"编译→运行"的全链路本地验证。

2. 发现:两套独立体系

OpenHarmony 的 ArkCompiler 包含 两套独立的编译-运行时体系,共存于同一源码树中:

维度 动态运行时(ArkTS-Dyn / ets_runtime) 静态运行时(ArkTS-Sta / static_core)
编译器 es2abc(旧版) ets2panda / es2panda(新版)
运行时 ark_js_vm ark / arkts_bin
字节码版本 v24 (0x00000018) v0x07000100 (458753)
源码路径 arkcompiler/ets_runtime/ arkcompiler/runtime_core/static_core/
前端源码 arkcompiler/ets_frontend/es2panda/ arkcompiler/ets_frontend/ets2panda/
二进制前缀 libpanda* libark*
构建方式(x86-64) ./build.shark_js_host_linux_tools_packages CMake 独立构建(推荐);GN 受限

两套体系的字节码格式完全不兼容,相互不能读取对方的 .abc 文件。

2.1 核心架构差异

维度 动态运行时 静态运行时
执行方式 解释器 + 可选 JIT AOT 编译 + LLVM 后端
优化重心 运行时灵活性 静态编译性能
类型系统 运行时类型推导 编译时类型分析
标准库 ECMAScript 标准库 ETS 标准库(更小,更静态)
AOT 编译 ark_aot_compiler(基于 PGO) ark_aot(基于 LLVM)
代码生成 IR + JIT 后端 LLVM 后端 + irtoc
并发模型 Actor(Worker/TaskPool) Actor(优化后)
支持语言 ArkTS/TS/JS ArkTS(原生)+ JS/TS(兼容)
OEM/设备 rk3568 等 ARM 设备 ARM + x86-64(CMake 独立构建)

2.2 字节码格式差异

v24 (.es2abc 产物):
  PANDA\0\0\0  |  checksum  |  18000000  |  ...

v0x07000100 (.ets2panda 产物):
  PANDA\0\0\0  |  checksum  |  00010007  |  ...

v24 使用 libpandafile(动态运行时)解析,v0x07000100 使用 libarkfile(静态运行时)解析。两套解析器各有独立的文件格式校验逻辑,运行时拒绝加载非本体系字节码。

2.3 发布时间线(估算)

阶段 时间 事件
v1 OpenHarmony 3.x 动态运行时(ArkTS-Dyn)首发,es2abc 支持 JS/TS
v2 OpenHarmony 4.x ets_runtime 独立仓库,增加 ArkTS 支持
v3 OpenHarmony 5.x static_core 引入,ets2panda 新增编译器前端
当前 master(2026) 两套并行;CMake 独立构建中 es2panda 为默认前端

2.4 命名混淆:ets2panda vs es2panda

arkcompiler/ets_frontend/ets2panda/aot/BUILD.gn 中:

ohos_executable("ets2panda") {
  output_name = "es2panda"    # ← 产物名是 es2panda!
}
源码目录 GN target output_name 实际产物 说明
es2panda/ es2panda:es2panda es2abc es2abc 旧版前端
ets2panda/ ets2panda/aot:ets2panda es2panda es2panda 新版前端,命名误导

新版编译器的 GN target 名是 ets2panda,但 output_name = "es2panda",导致与旧版同名冲突。CMake 独立构建中产物名为 es2panda。实际使用时需注意:es2panda 二进制可能来自两套不同的源码,需要根据路径和 --help 中的选项来判断版本。

3. 构建尝试过程(完整记录)

3.1 第一阶段:尝试 OHOS GN 构建新版链路

3.1.1 编译 ets2panda(新版前端)

通过 OHOS GN 构建系统的 ninja 直接编译(./build.sh --build-target 会误触发独立构建/HPM 模式,导致 flatbuffers 版本路径不匹配等问题):

ninja -C out/rk3568 -w dupbuild=warn ohos_ets/build-tools/ets2panda/bin/es2panda

注意: 中间遇到 ModuleNotFoundError: No module named 'yaml',需先安装 pip install pyyaml
构建中使用 -w dupbuild=warn 绕过了 ohos_clang_arm toolchain 的重复规则错误。

结果: ✅ 编译成功(4117 步)

  • 产物:out/rk3568/clang_x64/arkcompiler/ets_frontend/es2panda
  • 可正常编译 .ets.abc(新版字节码格式 v0x07000100)

问题: 找不到能执行新版 .abc 的运行时。

3.1.2 尝试 ark_js_vm 运行新版 .abc

Invalid panda file index_section_off 0 or num_indexes 992. Abc file is corrupted

根因: ark_js_vm 是旧版动态运行时,只能读 v24 字节码。

3.1.3 尝试构建 x86-64 版 static_core 运行时

./build.sh --product-name rk3568 --build-target arkcompiler/runtime_core/static_core:ark_host_linux_tools_packages

失败:irtoc ARM 对象不兼容 x86-64

ld.lld: error: clang_x64/gen/ark_sig/irtoc_fastpath.o is incompatible with elf64-x86-64

根因: target_cpu = "arm"out/rk3568/args.gn 全局设置,clang_x64 host 工具链继承此值。irtoc 模板的 action() 使用 default_toolchain 作用域,导致始终生成 ARM 代码。

尝试修复 1: 改用 ninja 直接构建(绕开独立构建系统)

ninja -C out/rk3568 -w dupbuild=warn arkcompiler/runtime_core/static_core:ark_host_linux_tools_packages
  • 结果:irtoc 生成步骤仍然产生 ARM 对象(--arch arm 硬编码在生成的 toolchain.ninja 中)

尝试修复 2: 修改 build/toolchain/linux/BUILD.gn,在 clang_x64 工具链参数加入 target_cpu = "x64"

  • 结果:不生效。irtoc 模板强制使用 default_toolchain(ARM)的作用域。

尝试修复 3: 手工 sed 修改 toolchain.ninja,将 --arch arm--compiler-cross-arch arm 改为 x64

  • 结果:参数传递成功,但 irtoc 执行器 SIGSEGV(exit -11)
  • 根因:生成 C++ 代码时 irtoc.rb 收到的是 ARM 架构参数,生成的代码调用 ARM-specific 接口;运行时传入 --compiler-cross-arch x64 后,缺少 x86-64 后端导致崩溃。

3.2 第二阶段:尝试 QEMU 模拟

sudo apt install qemu-user
# 构建 ARM sysroot
qemu-arm -L /path/to/sysroot ark_js_vm test.abc

结果: ❌ 不可行。libark_jsruntime.so 依赖数十个 OHOS 系统共享库(hilog、hitrace、ffrt、sandboxlog、hisysevent 等),与设备系统深度耦合,无法在 Linux 桌面完整模拟。

3.3 第三阶段:发现旧版链路的可用性

查阅 arkcompiler/ets_runtime/docs/README_zh.md,使用 ninja 直接构建:

ninja -C out/rk3568 ark_js_host_linux_tools_packages

结果: ✅ 成功构建,产物包括:

产物 路径 用途
ark_js_vm out/.../clang_x64/arkcompiler/ets_runtime/ark_js_vm x86-64 运行时 VM
es2abc out/.../clang_x64/arkcompiler/ets_frontend/es2abc 旧版前端编译器
ark_aot_compiler out/.../clang_x64/arkcompiler/ets_runtime/ark_aot_compiler AOT 编译器
ark_stub_compiler out/.../clang_x64/arkcompiler/ets_runtime/ark_stub_compiler Stub 编译器
libark_jsoptimizer.so out/.../clang_x64/arkcompiler/ets_runtime/libark_jsoptimizer.so JS 优化器

关键发现:es2abc --extension=ts 可以编译 .ets 文件为 v24 字节码。

3.4 第四阶段:CMake 独立构建(最终成功方案)

根据 arkcompiler/runtime_core/static_core/README.md

# 创建 symlink
ln -sf ../../../ets_frontend/ets2panda \
  runtime_core/static_core/tools/es2panda

# 安装依赖
sudo apt install libdwarf-dev
pip install jinja2-cli

# CMake 配置 + 构建
cd arkcompiler/runtime_core/static_core
cmake -B build2 -GNinja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_C_COMPILER=/path/to/prebuilts/clang/ohos/linux-x86_64/llvm/bin/clang \
  -DCMAKE_CXX_COMPILER=/path/to/prebuilts/clang/ohos/linux-x86_64/llvm/bin/clang++ \
  -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja \
  -DPANDA_WITH_ETS=ON \
  -DPANDA_WITH_TESTS=OFF

ninja ark es2panda

结果: ✅ 1010/1010 全部成功!

产物:

build2/
├── bin/
│   ├── es2panda              # 新版编译器(x86-64, 330K)
│   ├── ark                   # 新版运行时(x86-64, 313K)
│   ├── verifier              # 字节码校验器
│   └── arktsconfig.json      # 默认配置
└── plugins/ets/
    └── etsstdlib.abc          # ETS 标准库

4. 验证结果

4.1 旧版链路(OHOS GN 构建)

es2abc test.ets --output=test.abc --extension=ts
ark_js_vm test.abc
步骤 结果
编译 .ets → .abc ✅ exit 0,v24 字节码
执行 ✅ exit 0,无报错

4.2 新版链路(CMake 独立构建)← 推荐

./bin/es2panda --extension=ets --output=hello.abc hello.ets
./bin/ark --load-runtimes=ets \
  --boot-panda-files=plugins/ets/etsstdlib.abc \
  hello.abc hello.ETSGLOBAL::main
步骤 结果
编译 .ets → .abc ✅ exit 0,v0x07000100 字节码
执行 ✅ exit 0,无报错

4.3 已验证的 ArkTS 语法特性

特性 旧版链路 新版链路
强类型注解 (: number, : string)
类与继承 (class Dog extends Animal)
super() 构造函数调用
泛型函数 (identity<T>)
三元表达式 (a > b ? a : b)
实例方法调用
字符串拼接

5. 最终方案对比

链路 编译器 字节码 运行时 构建方式 x86 可行性
1️⃣ 旧版 GN es2abc --extension=ts v24 ark_js_vm OHOS ./build.sh ✅ 全流程 x86-64
2️⃣ 新版 CMake es2panda --extension=ets v0x07000100 ark CMake 独立构建 ✅ 全流程 x86-64
3️⃣ 新版 GN es2panda --extension=ets v0x07000100 arkts_bin OHOS ./build.sh ❌ irtoc 限制,需推送设备

链路 2 是推荐方案——纯 x86-64 本地开发,使用新版编译器产出新版字节码,直接在本机执行。

6. 为什么 OHOS GN 构建下 x86 运行时受限

6.1 irtoc 的架构依赖

irtoc 是 static_core 的特色技术,用 Ruby DSL 编写,在构建时生成架构特定的快速路径代码:

.irt 文件(Ruby DSL)
  ↓ irtoc.rb --arch ${target_cpu}
_code.cpp(C++,架构相关)
  ↓ 编译
irtoc_*_exec(可执行文件)
  ↓ 执行 --compiler-cross-arch ${target_cpu}
最终 .o(字节码解释器/快速路径)

irtoc 支持多架构代码生成——CMake 独立构建中能成功输出 x86-64 的 .o 文件证明其 x86-64 后端是完整的。但在 OHOS GN 交叉编译环境下,由于 target_cpu = "arm" 全局设置,irtoc.rb 接收到 --arch arm,生成的 C++ 代码只调用了 ARM 后端的 emit/encode 接口。即使后续改为 --compiler-cross-arch x64,运行时 _exec 可执行文件中也缺少 x86-64 的 dispatch 逻辑,导致 SIGSEGV。

本质上不是 irtoc 不支持 x86-64,而是 OHOS GN 构建的 preprocess/propagate 阶段被 target_cpu 锁死在 ARM 路径上。

6.2 GN 交叉编译的配置约束

OHOS 构建系统是交叉编译:x86-64 开发主机 → ARM 目标设备。target_cpu = "arm"out/rk3568/args.gn 中全局设置。irtoc 模板的 action() 使用 default_toolchain 的作用域,绕过了 host 工具链的参数覆盖。

6.3 CMake 如何绕过这个限制

CMake 独立构建的 default target 就是 x86-64 主机,target_cpu 自然为 x86_64,irtoc 生成的代码和运行时架构一致,不会触发 ARM-only 的问题。

结论:irtoc 其实支持 x86-64,问题出在 OHOS GN 交叉编译的构建配置上,而非 irtoc 源码本身。修复方向:让 irtoc 模板在 host 工具链下使用 host_toolchaintarget_cpu

7. 快速使用指南

7.1 旧版链路(已构建好)

export ARK_OUT=out/rk3568/clang_x64
export ARK_LIBS=$ARK_OUT/thirdparty/icu:$ARK_OUT/thirdparty/zlib

# 编译
$ARK_OUT/arkcompiler/ets_frontend/es2abc input.ets \
  --output=input.abc --extension=ts

# 执行
LD_LIBRARY_PATH=$ARK_LIBS:$ARK_OUT/arkcompiler/ets_runtime:$ARK_OUT/arkcompiler/runtime_core \
  $ARK_OUT/arkcompiler/ets_runtime/ark_js_vm input.abc

7.2 新版链路(CMake 独立构建,推荐)

export STATIC_CORE=/path/to/arkcompiler/runtime_core/static_core/build2
export ES2PANDA=$STATIC_CORE/bin/es2panda
export ARK=$STATIC_CORE/bin/ark
export STDLIB=$STATIC_CORE/plugins/ets/etsstdlib.abc

# 编译
$ES2PANDA --extension=ets --output=hello.abc hello.ets

# 执行
$ARK --load-runtimes=ets --boot-panda-files=$STDLIB \
  hello.abc hello.ETSGLOBAL::main

7.3 CMake 独立构建的完整命令

# 从源码根目录
cd arkcompiler/runtime_core/static_core

# 确保 symlink
ln -sf ../../../ets_frontend/ets2panda tools/es2panda

# 配置
cmake -B build2 -GNinja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_C_COMPILER=$(which clang) \
  -DCMAKE_CXX_COMPILER=$(which clang++) \
  -DCMAKE_MAKE_PROGRAM=/usr/bin/ninja \
  -DPANDA_WITH_ETS=ON \
  -DPANDA_WITH_TESTS=OFF

# 构建
ninja -C build2 ark es2panda
posted @ 2026-06-05 16:34  getmoon  阅读(40)  评论(0)    收藏  举报