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()