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.sh → ark_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_toolchain 的 target_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

浙公网安备 33010602011771号