方舟编译器(ArkCompiler)是为支持多种编程语言、多种芯片平台的联合编译、运行而设计的统一编译运行时平台。
要了解虚拟机的详细设计请参考 概述
初始环境软件安装(Ubuntu版本推荐18.04或20.04)
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git-lfs git bison flex gnupg build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses-dev x11proto-core-dev libx11-dev libc++1 lib32z1-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 libtinfo5 bc npm genext2fs liblz4-tool libssl-dev ruby openjdk-8-jre-headless gdb python3-pip libelf-dev libxcursor-dev libxrandr-dev libxinerama-dev
详细Ubuntu安装搭建请参考 搭建Ubuntu环境
下载源码请参考 下载说明
注意:下列命令需在源码根目录下执行
首次编译:
./build.sh --product-name rk3568
首次编译后增量编译方舟运行时:
编译linux-x86版本:
./build.sh --product-name rk3568 --build-target ark_js_host_linux_tools_packages
编译oh-arm64版本:
./build.sh --product-name rk3568 --gn-args use_musl=true --target-cpu arm64 --build-target ark_js_packages
编译oh-arm32版本:
./build.sh --product-name rk3568 --build-target ark_js_packages
首次编译后增量编译方舟前端:
./build.sh --product-name rk3568 --build-target ets_frontend_build
更多编译命令请参考 编译命令
说明:上述编译命令为release版本,编译debug版本需增加编译选项:--gn-args is_debug=true。
方舟相关的二进制文件在如下路径:
out/rk3568/arkcompiler/runtime_core/
out/rk3568/arkcompiler/ets_frontend/
out/rk3568/arkcompiler/ets_runtime/
out/rk3568/clang_x64/arkcompiler/runtime_core/
out/rk3568/clang_x64/arkcompiler/ets_frontend/
out/rk3568/clang_x64/arkcompiler/ets_runtime
本章节将介绍基于方舟运行时的开发测试实例。
编译编译方舟运行时和方舟前端
./build.sh --product-name rk3568 --build-target ark_js_host_linux_tools_packages --build-target ets_frontend_build
新建hello-world.js文件,写入以下源码:
print("Hello World!!!");
运行步骤:
通过方舟前端生成hello-world.abc文件,编译命令:
/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_frontend/es2abc hello-world.js
执行hello-world.abc文件:
设置搜索路径:
export LD_LIBRARY_PATH=/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_runtime:/your_code_path/prebuilts/clang/ohos/linux-x86_64/llvm/lib:/your_code_path/out/rk3568/clang_x64/thirdparty/zlib
执行ark_js_vm:
/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_runtime/ark_js_vm hello-world.abc
执行结果如下:
Hello World!!!
说明:此处“your_code_path”为源码目录路径。
编译生成反汇编工具:
./build.sh --product-name rk3568 --build-target arkcompiler/runtime_core:ark_host_linux_tools_packages
执行如下命令,结果输出到output.pa文件中:
/your_code_path/out/rk3568/clang_x64/arkcompiler/runtime_core/ark_disasm hello-world.abc output.pa
hello-world.abc反汇编结果如下:
#
# source binary: hello-world.abc
#
# ====================
# LITERALS
# ====================
# RECORDS
.record _ESAnnotation
.record _ESModuleMode {
u8 isModule
}
# ====================
# METHODS
.function any func_main_0_any_any_any_any_(any a0, any a1, any a2) {
mov v2, a2
mov v1, a1
mov v0, a0
builtin.acc
sta v5
builtin.idi "print", 0x0 // 加载print函数
sta v3
lda.str "Hello World!!!" // 加载Hello World!!!字符串
sta v4
builtin.tern3 v3, v4 // 调用print函数
builtin.acc
}
./build.sh --product-name rk3568 --build-target ark_js_host_linux_tools_packages
./build.sh --product-name rk3568 --build-target ets_frontend_build
说明:编译命令执行路径为项目根目录。
运行run_test262.py脚本,下载及运行Test262用例。
命令行格式:
python3 test262/run_test262.py [options]
执行路径为:项目根目录/arkcompiler/ets_frontend。
选项 |
描述 |
---|---|
--h,--help |
帮助提示 |
--dir DIR |
选定要测试的目录 |
--file FILE |
选定要测试的文件 |
--mode [{1, 2, 3}] |
模式选择,1:仅默认值;2:仅严格模式;3:默认模式和严格模式 |
--es51 |
运行Test262 ES5.1版本 |
--es2015 [{all, only}] |
运行Test262 ES2015版本,all:包含的所有用例;only:仅包括ES2015 |
--esnext |
运行Test262-ES.next |
--engine FILE |
运行测试的其他引擎,指定二进制文件(如:d8,hermes,jsc,qjs...) |
--babel |
是否使用Babel转换 |
--timeout TIMEOUT |
设置测试超时时间(以毫秒为单位) |
--threads THREADS |
设置并行运行线程数 |
--hostArgs HOSTARGS |
传递给eshost主机的命令行参数 |
--ark-tool ARK_TOOL |
方舟运行时的二进制工具 |
--ark-frontend-tool ARK_FRONTEND_TOOL |
方舟前端转换工具 |
--libs-dir LIBS_DIR |
依赖so的路径集合,通过“:”分割 |
--ark-frontend [{ts2panda, es2panda}] |
指定前端 |
运行ES51测试用例:
python3 test262/run_test262.py --es51
仅运行ES2015测试用例:
python3 test262/run_test262.py --es2015
仅运行ES2021测试用例:
python3 test262/run_test262.py --es2021 only
运行ES2015和ES51和ES2021所有测试用例:
python3 test262/run_test262.py --es2021 all
运行单一测试用例:
python3 test262/run_test262.py --file test262/data/test_es5/language/statements/break/12.8-1.js
运行某目录下所有测试用例:
python3 test262/run_test262.py --dir test262/data/test_es5/language/statements
使用`babel`把单个测试用例转换成es5后再运行:
python3 test262/run_test262.py --babel --file test262/data/test_es5/language/statements/break/12.8-1.js
Test262所有用例的测试结果位于项目根目录/arkcompiler/ets_frontend/out下。shell中测试输出结果如下:
$python3 test262/run_test262.py --file test262/data/test_es2015/built-ins/Array/15.4.5.1-5-1.js
Wait a moment..........
Test command:
node
test262/harness/bin/run.js
--hostType=panda
--hostPath=python3
--hostArgs='-B test262/run_sunspider.py --ark-tool=/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_runtime/ark_js_vm --ark-frontend-tool=/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_frontend/build/src/index.js --libs-dir=/your_code_path/out/rk3568/clang_x64/global/i18n:/your_code_path/prebuilts/clang/ohos/linux-x86_64/llvm/lib:/your_code_path/out/rk3568/clang_x64/thirdparty/zlib/ --ark-frontend=ts2panda'
--threads=15
--mode=only strict mode
--timeout=60000
--tempDir=build/test262
--test262Dir=test262/data
--saveCompiledTests
test262/data/test_es5/language/statements/break/12.8-1.js
PASS test262/data/test_es2015/built-ins/Array/15.4.5.1-5-1.js (strict mode)
Ran 1 tests
1 passed
0 failed
used time is: 0:01:04.439642
编译生成AOT编译器:
./build.sh --product-name rk3568 --build-target ets_frontend_build --build-target ark_js_host_linux_tools_packages --build-target arkcompiler/runtime_core:ark_host_linux_tools_packages
新建hello-world.ts文件,写入以下源码:
declare function print(arg:any):string;
print('Hello World!!!')
通过方舟前端生成hello-world.abc文件,编译命令:
/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_frontend/es2abc --module --merge-abc hello-world.ts
设置搜索路径:
export LD_LIBRARY_PATH=/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_runtime:/your_code_path/prebuilts/clang/ohos/linux-x86_64/llvm/lib:/your_code_path/out/rk3568/clang_x64/thirdparty/icu:/your_code_path/out/rk3568/clang_x64/thirdparty/zlib
运行ark_js_vm,采集PGO信息,生成的PGO信息落盘在文件hello-world.ap:
/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_runtime/ark_js_vm --enable-pgo-profiler=true --compiler-pgo-profiler-path=hello-world.ap --entry-point=hello-world hello-world.abc
通过AOT编译器生成an和ai文件,可以通过info日志观察到被编译的函数列表:
/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_runtime/ark_aot_compiler --enable-pgo-profiler=true --compiler-pgo-profiler-path=hello-world.ap --log-level=info --aot-file=./hello-world hello-world.abc
执行ark_js_vm:
/your_code_path/out/rk3568/clang_x64/arkcompiler/ets_runtime/ark_js_vm --aot-file=./hello-world --entry-point=hello-world hello-world.abc
执行结果如下:
Hello World!!!
说明:此处“your_code_path”为源码目录路径。
方舟前端工具采用命令行交互方式,支持将ArkTS代码转换为方舟字节码,使其能够在方舟运行时上运行。支持Windows/Linux/Mac平台。
使用前端工具将ArkTS文件转换为方舟字节码文件。方舟前端工具在linux平台上可通过全量编译或指定编译前端工具链获取。
构建编译:
$ ./build.sh --product-name rk3568 --build-target ets_frontend_build
$ cd out/rk3568/clang_x64/arkcompiler/ets_frontend/
$ ./es2abc [options] file.js
选项 |
描述 |
取值范围 |
默认值 |
---|---|---|---|
--debug-info |
携带debug信息 |
- |
- |
--debugger-evaluate-expression |
debugger下对输入的base64形式的表达式求值 |
- |
- |
--dump-assembly |
输出为汇编文件 |
- |
- |
--dump-ast |
打印解析得到的ast(抽象语法树) |
- |
- |
--dump-debug-info |
打印debug信息 |
- |
- |
--dump-literal-buffer |
打印literal buffer内容 |
- |
- |
--dump-size-stat |
显示字节码相关的统计信息 |
- |
- |
--extension |
指定输入类型 |
['js', 'ts', 'as'] |
- |
--help |
帮助提示 |
- |
- |
--module |
按照ESM模式编译 |
- |
- |
--opt-level |
指定编译优化等级 |
['0', '1', '2'] |
0 |
--output |
输出文件路径 |
- |
- |
--parse-only |
只对输入文件做解析动作 |
- |
- |
--thread |
指定生成字节码时所用的线程数目 |
0-机器支持的线程数目 |
0 |
工具名称为ark_disasm,用于将二进制格式的方舟字节码文件转换为文本格式的方舟字节码文件。
编译生成反汇编工具:
./build.sh --product-name rk3568 --build-target arkcompiler/runtime_core:ark_host_linux_tools_packages
命令行格式:
ark_disasm [选项] 输入文件 输出文件
选项 |
描述 |
---|---|
--debug |
使能调试信息, 如果没有指定"--debug-file", 输出形式将会是标准输出。默认值是false |
--debug-file |
调试信息输出文件路径,默认为std::cout |
--skip-string-literals |
将字符串用对应的string_ID代替,可以减少输出文件的大小。默认值是false |
--quiet |
打开所有--skip-*选项。默认值是false |
--help |
帮助提示 |
--verbose |
输出更多关于类和方法在文件中的信息。默认值是false |
输入文件:二进制格式的方舟字节码
输出文件:文本格式的方舟字节码
AOT为Ahead Of Time的简称,也即提前编译,能够在Host端将字节码提前编译成Target端可运行的机器码,这样字节码可以获得充分编译优化,从而加速Target端的运行速度。
编译生成aot编译器:
./build.sh --product-name rk3568 --build-target ark_js_host_linux_tools_packages
命令行格式:
ark_aot_compiler [选项] 输入文件
选项 | 描述 |
---|---|
--aot-file | AOT输出文件的路径(不需要文件后缀)。默认值:“aot_file” |
--compiler-opt-type-lowering | 利用类型信息,生成优化级别更高的机器码。默认值:“true” |
--compiler-opt-max-method | 设置AOT编译方法的大小阈值,当方法的大小超过该值时,则不进行编译。默认值:“32KB” |
--compiler-opt-level | 设置AOT的优化级别。默认值:“3” |
--compiler-log | AOT的日志选项,可打印出AOT生成的IR图、汇编码等信息。默认值“none” |
--compiler-log-snapshot | 打印与序列化有关的日志信息。默认值“false” |
--compiler-log-time | 打印AOT过程中各个优化pass的耗时情况。默认值值“false” |
输入文件:二进制格式的方舟字节码
输出文件:直接执行的机器码的an文件、存储序列化后ConstPool的ai文件(输出文件路径需使用--aot-file选项指定)
PGO为Profile-guided optimization的简称,也即配置文件引导的优化。该工具能够记录应用启动和性能场景中的高频(热点)函数,并将信息记录于对应的PGO Profiler文件。AOT编译器则可通过这些信息决策部分函数进行编译,从而在基本不影响应用运行性能的情况下,缩短编译时间,减少.an文件的大小。
编译生成aot编译器和ark js虚拟机
./build.sh --product-name rk3568 --build-target ark_js_host_linux_tools_packages
命令行格式:
ark_js_vm [选项] 输入文件
选项 | 描述 |
---|---|
--enable-pgo-profiler | 开启pgo工具。默认值:“false” |
--compiler-pgo-profiler-path | pgo profiler文件的保存路径。默认值:"none" |
--compiler-pgo-hotness-threshold | 热点函数的阈值,当函数的调用次数大于该值,则认为是热点函数。默认值:“2” |
输入文件:二进制格式的方舟字节码
输出文件:保存有热点函数信息的ap文件
命令行格式:
ark_aot_compiler [选项] 输入文件
选项 | 描述 |
---|---|
--compiler-pgo-profiler-path | pgo profiler文件路径。默认值:"none" |
--compiler-pgo-hotness-threshold | 使能pgo编译的函数调用次数阈值,profile文件中记录的调用次数大于该阈值的函数才会进行编译。默认值:“2” |
输入文件:二进制格式的方舟字节码,ap文件
输出文件:直接执行的机器码的an文件(基于pgo)