• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# coding=utf-8
3
4#
5# Copyright (c) 2025 Huawei Device Co., Ltd.
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18import os
19import sys
20import json
21import subprocess
22
23ES2PANDAPATH = "arkcompiler/runtime_core/static_core/out/bin/es2panda"
24ARKLINKPATH = "arkcompiler/runtime_core/static_core/out/bin/ark_link"
25ARKPATH = "arkcompiler/runtime_core/static_core/out/bin/ark"
26ETSSTDLIBPATH = "arkcompiler/runtime_core/static_core/out/plugins/ets/etsstdlib.abc"
27CONFIGPATH = "arkcompiler/runtime_core/static_core/out/bin/arktsconfig.json"
28HYPIUMPATH = "test/testfwk/arkxtest/jsunit/src_static/"
29
30
31def build_tools(compile_filelist):
32    """
33    编译工具类
34    """
35
36    abs_es2panda_path = get_path_code_dircetory(ES2PANDAPATH)
37    abs_test_path = os.getcwd()
38
39    # 1. 创建输出目录
40    output_dir = os.path.join(abs_test_path, "out")
41    os.makedirs(output_dir, exist_ok = True)
42
43    # 逐个执行编译命令
44    for ets_file in compile_filelist:
45        try:
46            # 获取文件名(不带路径)
47            file_name = os.path.base_name(ets_file)
48            base_name = os.path.splitext(file_name)[0]
49            output_filepath = os.path.join(output_dir, f"{base_name}.abc")
50
51            # 构造编译命令
52            command = [abs_es2panda_path, ets_file, "--output", output_filepath]
53
54            # 执行命令并获取输出
55            result = subprocess.run(
56                command,
57                check=True,
58                stdout=subprocess.PIPE,
59                stderr=subprocess.PIPE,
60                text=True
61            )
62
63            # 成功编译
64            print(f"成功编译'{ets_file}', 输出路径: {output_filepath}")
65
66        except Exception as e:
67            print(f"'{ets_file}'编译失败")
68
69
70def get_path_code_dircetory(after_dir):
71    """
72    拼接绝对路径工具类
73    """
74
75    current_path = os.path.abspath(__file__)
76    current_dir = os.path.dirname(current_path)
77
78    # 查找 /code/ 目录的位置
79    code_marker = "/code/"
80    code_index = current_dir.find(code_marker)
81
82    if code_index == -1:
83        raise FileNotFoundError(
84            f"路径中没有找到 '/code/',当前路径为: {current_dir}"
85        )
86
87    # 提取code路径 (包含code目录本身)
88    code_base = current_dir[:code_index + len(code_marker)]
89
90    # 拼接用户传入路径
91    full_path = os.path.join(code_base, after_dir)
92
93    return full_path
94
95
96def write_arktsconfig_file():
97    """
98    将当前目录下的 .ets文件生成 file_map, 并追加写入 arktsconfig.json
99    """
100
101    current_dir = os.path.dirname(os.path.abspath(__file__))
102
103    # 1. 获取当前目录下的所有.ets文件
104    ets_files = [f for f in os.listdir(current_dir) if f.endswith('.ets')]
105
106    # 2. 构建file_map:{文件名:[文件绝对路径]}
107    file_map = {}
108    for ets_file in ets_files:
109        module_name = os.path.splitext(ets_file)[0]
110        relative_path = os.path.join(current_dir, ets_file)
111        abs_path = get_path_code_dircetory(relative_path)
112        file_map[module_name] = [abs_path]
113
114    # 3. 定位要写入的 arktsconfig.json文件
115    abs_config_path = get_path_code_dircetory(CONFIGPATH)
116
117    # 4. 读取并更新配置
118    try:
119        with open(abs_config_path, 'r', encoding='utf-8') as f:
120            config = json.load(f)
121    except FileNotFoundError:
122        config = { "compilerOptions": { "baseUrl": "/code/arkcompiler/runtime_core/static_core", "paths": {} }}
123
124    # 5. 更新配置中的paths(保留之前的配置项)
125    config.setdefault("compilerOptions", {})
126    config["compilerOptions"].setdefault("paths", {})
127    config["compilerOptions"]["paths"].update(file_map)
128
129    with open(abs_config_path, 'w', encoding='utf-8') as f:
130        json.dump(config, f, indent=4, ensure_ascii=False)
131
132    print(f"已成功更新 {abs_config_path}")
133
134
135def build_ets_files():
136    """
137    编译hypium、tools、测试用例文件
138    """
139    abs_hypium_path = get_path_code_dircetory(HYPIUMPATH)
140
141    files_to_compile = []
142    for root, dirs, files in os.walk(abs_hypium_path):
143        if "testAbility" in dirs:
144            dirs.remove("testAbility")
145        if "testrunner" in dirs:
146            dirs.remove("testrunner")
147
148        for f in files:
149            if f.endswith(".ets"):
150                file_path = os.path.join(root, f)
151                files_to_compile.append(file_path)
152
153    if not files_to_compile:
154        print("未找到可编译的 .ets 文件,跳过编译。")
155        return
156    build_tools(files_to_compile)
157
158    current_dir = os.path.dirname(os.path.abspath(__file__))
159    ets_files = [os.path.join(current_dir, f) for f in os.listdir(current_dir) if f.endswith('.ets')]
160    build_tools(ets_files)
161
162    abs_test_path = os.getcwd()
163    test_files = []
164
165    for root, dirs, files in os.walk(abs_test_path):
166        for file in files:
167            if file.endswith(".ets"):
168                file_abs_path = os.path.join(root, file)
169                test_files.append(file_abs_path)
170    build_tools(test_files)
171
172
173def collect_abc_files(res_file_name):
174    abs_out_path = os.path.join(os.getcwd(), "out")
175    abc_files = []
176
177    # 1. 收集out目录下的.abc文件
178    if os.path.exists(abs_out_path):
179        out_files = [
180            os.path.join("./out", f)
181            for f in os.listdir(abs_out_path)
182            if f.endswith('.abc')
183        ]
184        abc_files.extend(out_files)
185
186    # 2. 收集src.json中配置的.abc文件
187    abc_files.extend(load_abc_from_src_json())
188
189    return abc_files
190
191
192def load_abc_from_src_json():
193    abc_files = []
194    src_json_path = os.path.join(os.getcwd(), "src.json")
195
196    if not os.path.exists(src_json_path):
197        print(f"提示: 配置文件 {src_json_path} 未找到,跳过src.json收集")
198        return abc_files
199
200    try:
201        with open(src_json_path, 'r') as f:
202            src_data = json.load(f)
203    except json.JSONDecodeError:
204        print(f"错误: 配置文件 {src_json_path} JSON格式错误")
205        return abc_files
206    except Exception as e:
207        print(f"读取src.json时发生意外错误: {str(e)}")
208        return abc_files
209
210    for path in src_data.get("src_path", []):
211        if os.path.isfile(path) and path.endswith('.abc'):
212            abc_files.append(path)
213        else:
214            print(f"警告: 路径 {path} 不存在或不是.abc文件,已跳过")
215
216    return abc_files
217
218
219def link_abc_files(res_file_name):
220    """
221    链接所有abc文件生成最终的test.abc
222    """
223    abs_arklink_path = get_path_code_dircetory(ARKLINKPATH)
224    abc_files = collect_abc_files(res_file_name)
225
226    if not abc_files:
227        print("终止: 没有找到可连接的.abc文件")
228        return
229
230    command = [
231        abs_arklink_path,
232        f"--output={res_file_name}.abc",
233        "--",
234        *abc_files
235    ]
236
237    print(f"执行命令: {' '.join(command)}")
238
239    try:
240        result = subprocess.run(
241            command,
242            check=True,
243            stdout=subprocess.PIPE,
244            stderr=subprocess.PIPE,
245            text=True
246        )
247        print("状态: 链接成功\n输出:", result.stdout.strip())
248
249    except subprocess.CalledProcessError as e:
250        print("错误: 链接失败")
251        print("错误详情:", e.stderr.strip())
252        raise  # 可以选择抛出异常或处理错误
253
254
255def run_test(res_file_name):
256    """
257    执行生成的abc文件并生成报告日志
258    """
259    abs_ark_path = get_path_code_dircetory(ARKPATH)
260    abs_etsstdlib_path = get_path_code_dircetory(ETSSTDLIBPATH)
261    tests_dir_name = res_file_name
262    log_file = os.path.join(os.getcwd(), f"{tests_dir_name}.log")
263    command = [
264        abs_ark_path,
265        f"--boot-panda-files={abs_etsstdlib_path}",
266        f"--load-runtimes=ets",
267        f"{tests_dir_name}.abc",
268        f"OpenHarmonyTestRunner/ETSGLOBAL::main"
269    ]
270    print(f"执行命令 {command}")
271    with open(log_file, "w") as f:
272        try:
273            result = subprocess.run(
274                command,
275                check=True,
276                stdout=f,
277                stderr=subprocess.PIPE,
278                text=True
279            )
280
281            print("命令执行成功")
282        except subprocess.CalledProcessError as e:
283            print("命令执行失败")
284            print(f"错误信息 {e.stderr.strip()}")
285
286
287def main():
288    if len(sys.argv) < 2:
289        print("使用方式: python3 build_test.py <resultFileName> ")
290        print("实例:")
291        print("python3 build_test.py functionsTest")
292        sys.exit(1)
293
294        res_file_name = sys.argv[1]
295        write_arktsconfig_file()
296        build_ets_files()
297        link_abc_files(res_file_name)
298        run_test(res_file_name)
299
300
301if __name__ == '__main__':
302    main()