15f9996aaSopenharmony_ci#!/usr/bin/env python 25f9996aaSopenharmony_ci# -*- coding: utf-8 -*- 35f9996aaSopenharmony_ci# Copyright (c) 2023 Huawei Device Co., Ltd. 45f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 55f9996aaSopenharmony_ci# you may not use this file except in compliance with the License. 65f9996aaSopenharmony_ci# You may obtain a copy of the License at 75f9996aaSopenharmony_ci# 85f9996aaSopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 95f9996aaSopenharmony_ci# 105f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software 115f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 125f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135f9996aaSopenharmony_ci# See the License for the specific language governing permissions and 145f9996aaSopenharmony_ci# limitations under the License. 155f9996aaSopenharmony_ci 165f9996aaSopenharmony_ciimport argparse 175f9996aaSopenharmony_ciimport copy 185f9996aaSopenharmony_ciimport os 195f9996aaSopenharmony_ciimport shutil 205f9996aaSopenharmony_ciimport subprocess 215f9996aaSopenharmony_ciimport sys 225f9996aaSopenharmony_ci 235f9996aaSopenharmony_cisys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) 245f9996aaSopenharmony_cifrom scripts.util.file_utils import read_json_file # noqa: E402 255f9996aaSopenharmony_ci 265f9996aaSopenharmony_citarget_data_dicts = dict() 275f9996aaSopenharmony_ci 285f9996aaSopenharmony_ci 295f9996aaSopenharmony_cidef get_value_from_file(file: str, target: list, key: str, must: bool = True): 305f9996aaSopenharmony_ci target_name = target[0] 315f9996aaSopenharmony_ci target_out_dir = target[1] 325f9996aaSopenharmony_ci file_path = os.path.join(target_out_dir, target_name + "_" + file + ".json") 335f9996aaSopenharmony_ci 345f9996aaSopenharmony_ci global target_data_dicts 355f9996aaSopenharmony_ci target_data = target_data_dicts.get(file_path) 365f9996aaSopenharmony_ci if target_data is not None: 375f9996aaSopenharmony_ci return target_data.get(key) 385f9996aaSopenharmony_ci 395f9996aaSopenharmony_ci if not os.path.exists(file_path): 405f9996aaSopenharmony_ci if must: 415f9996aaSopenharmony_ci raise Exception("File " + file_path + " not exists!") 425f9996aaSopenharmony_ci else: 435f9996aaSopenharmony_ci print(file_path + " not exists!") 445f9996aaSopenharmony_ci return "Unknown" 455f9996aaSopenharmony_ci 465f9996aaSopenharmony_ci target_data = read_json_file(file_path) 475f9996aaSopenharmony_ci target_data_dicts[file_path] = target_data 485f9996aaSopenharmony_ci return target_data.get(key) 495f9996aaSopenharmony_ci 505f9996aaSopenharmony_ci 515f9996aaSopenharmony_cidef get_valid_deps(module_deps: list, finish_list: list): 525f9996aaSopenharmony_ci already_check = [] 535f9996aaSopenharmony_ci valid_list = [] 545f9996aaSopenharmony_ci while len(module_deps) > 0: 555f9996aaSopenharmony_ci module_deps_copy = copy.deepcopy(module_deps) 565f9996aaSopenharmony_ci module_deps = [] 575f9996aaSopenharmony_ci for module_dep in module_deps_copy: 585f9996aaSopenharmony_ci target_name = module_dep.get("target_name") 595f9996aaSopenharmony_ci target_out_dir = module_dep.get("target_out_dir") 605f9996aaSopenharmony_ci 615f9996aaSopenharmony_ci element = (target_name, target_out_dir) 625f9996aaSopenharmony_ci if already_check.count(element) > 0: 635f9996aaSopenharmony_ci continue 645f9996aaSopenharmony_ci already_check.append(element) 655f9996aaSopenharmony_ci 665f9996aaSopenharmony_ci target_type = get_value_from_file("deps_data", element, "type", False) 675f9996aaSopenharmony_ci if target_type == "Unknown": 685f9996aaSopenharmony_ci continue 695f9996aaSopenharmony_ci elif target_type == "shared_library" or target_type == "etc": 705f9996aaSopenharmony_ci if finish_list.count(element) > 0: 715f9996aaSopenharmony_ci continue 725f9996aaSopenharmony_ci valid_list.append(element) 735f9996aaSopenharmony_ci else: 745f9996aaSopenharmony_ci deps = get_value_from_file("deps_data", element, "module_deps_info", False) 755f9996aaSopenharmony_ci for dep in deps: 765f9996aaSopenharmony_ci name = dep.get("target_name") 775f9996aaSopenharmony_ci out_dir = dep.get("target_out_dir") 785f9996aaSopenharmony_ci dep_tup = (name, out_dir) 795f9996aaSopenharmony_ci module_deps.append(dep) 805f9996aaSopenharmony_ci return valid_list 815f9996aaSopenharmony_ci 825f9996aaSopenharmony_ci 835f9996aaSopenharmony_cidef check_debug_info(check_file: str, readelf: str): 845f9996aaSopenharmony_ci out = subprocess.Popen([readelf, "-S", check_file], shell=False, stdout=subprocess.PIPE) 855f9996aaSopenharmony_ci infos = out.stdout.read().splitlines() 865f9996aaSopenharmony_ci for info in infos: 875f9996aaSopenharmony_ci info_str = info.decode() 885f9996aaSopenharmony_ci pos = info_str.find(".debug_info") 895f9996aaSopenharmony_ci if pos >= 0: 905f9996aaSopenharmony_ci return True 915f9996aaSopenharmony_ci return False 925f9996aaSopenharmony_ci 935f9996aaSopenharmony_ci 945f9996aaSopenharmony_cidef do_check(target_out_dir: str, target_name: str, stripped_dir: str, readelf: str, 955f9996aaSopenharmony_ci abidiff: str, abidw: str, abi_dumps_path: str): 965f9996aaSopenharmony_ci element = (target_name, target_out_dir) 975f9996aaSopenharmony_ci prebuilt = get_value_from_file("deps_data", element, "prebuilt") 985f9996aaSopenharmony_ci if prebuilt: 995f9996aaSopenharmony_ci check_file = get_value_from_file("deps_data", element, "source_path") 1005f9996aaSopenharmony_ci if not os.path.exists(check_file): 1015f9996aaSopenharmony_ci raise Exception("File " + check_file + " not exists!") 1025f9996aaSopenharmony_ci has_debug_info = check_debug_info(check_file, readelf) 1035f9996aaSopenharmony_ci if not has_debug_info: 1045f9996aaSopenharmony_ci raise Exception("Prebuilt target should be with debug info!") 1055f9996aaSopenharmony_ci else: 1065f9996aaSopenharmony_ci source = get_value_from_file("module_info", element, "source") 1075f9996aaSopenharmony_ci check_file = os.path.join(stripped_dir, source) 1085f9996aaSopenharmony_ci if not os.path.exists(check_file): 1095f9996aaSopenharmony_ci raise Exception("File " + check_file + " not exists!") 1105f9996aaSopenharmony_ci 1115f9996aaSopenharmony_ci out_file = os.path.join(target_out_dir, target_name + "_abi_info.dump") 1125f9996aaSopenharmony_ci ret = subprocess.call([abidw, "--out-file", out_file, check_file]) 1135f9996aaSopenharmony_ci if ret != 0: 1145f9996aaSopenharmony_ci raise Exception("Execute abidw failed! Return value: " + str(ret)) 1155f9996aaSopenharmony_ci 1165f9996aaSopenharmony_ci toolchain = get_value_from_file("deps_data", element, "toolchain") 1175f9996aaSopenharmony_ci toolchain_name = toolchain.split(':')[-1] 1185f9996aaSopenharmony_ci 1195f9996aaSopenharmony_ci base_name = os.path.basename(out_file) 1205f9996aaSopenharmony_ci base_file = os.path.join(abi_dumps_path, toolchain_name, base_name) 1215f9996aaSopenharmony_ci if not os.path.exists(base_file): 1225f9996aaSopenharmony_ci raise Exception("File " + base_file + " not exists!") 1235f9996aaSopenharmony_ci ret = subprocess.call([abidiff, out_file, base_file]) 1245f9996aaSopenharmony_ci if ret != 0: 1255f9996aaSopenharmony_ci raise Exception("ABI info in " + out_file + " and " + base_file + " are different!") 1265f9996aaSopenharmony_ci 1275f9996aaSopenharmony_ci 1285f9996aaSopenharmony_cidef get_copy_source_path(element: list): 1295f9996aaSopenharmony_ci prebuilt = get_value_from_file("deps_data", element, "prebuilt") 1305f9996aaSopenharmony_ci if prebuilt: 1315f9996aaSopenharmony_ci source = get_value_from_file("deps_data", element, "output_path") 1325f9996aaSopenharmony_ci else: 1335f9996aaSopenharmony_ci source = get_value_from_file("module_info", element, "source") 1345f9996aaSopenharmony_ci return (element, source) 1355f9996aaSopenharmony_ci 1365f9996aaSopenharmony_ci 1375f9996aaSopenharmony_cidef traverse_and_check(check_list: list, readelf: str, abidiff: str, abidw: str, abi_dumps_path: str): 1385f9996aaSopenharmony_ci copy_list = [] 1395f9996aaSopenharmony_ci finish_list = [] 1405f9996aaSopenharmony_ci loop_count = 0 1415f9996aaSopenharmony_ci while len(check_list) > 0: 1425f9996aaSopenharmony_ci check_list_copy = copy.deepcopy(check_list) 1435f9996aaSopenharmony_ci check_list = [] 1445f9996aaSopenharmony_ci for element in check_list_copy: 1455f9996aaSopenharmony_ci if finish_list.count(element) > 0: 1465f9996aaSopenharmony_ci continue 1475f9996aaSopenharmony_ci finish_list.append(element) 1485f9996aaSopenharmony_ci 1495f9996aaSopenharmony_ci target_name = element[0] 1505f9996aaSopenharmony_ci target_out_dir = element[1] 1515f9996aaSopenharmony_ci target_type = get_value_from_file("deps_data", element, "type") 1525f9996aaSopenharmony_ci if target_type == "etc": 1535f9996aaSopenharmony_ci copy_list.append(copy.deepcopy(get_copy_source_path(element))) 1545f9996aaSopenharmony_ci continue 1555f9996aaSopenharmony_ci 1565f9996aaSopenharmony_ci stable = get_value_from_file("deps_data", element, "stable") 1575f9996aaSopenharmony_ci if not stable: 1585f9996aaSopenharmony_ci if loop_count == 0: 1595f9996aaSopenharmony_ci raise Exception("Target '{}' is not stable! Check config in gn".format(target_name)) 1605f9996aaSopenharmony_ci else: 1615f9996aaSopenharmony_ci copy_list.append(copy.deepcopy(get_copy_source_path(element))) 1625f9996aaSopenharmony_ci module_deps = get_value_from_file("deps_data", element, "module_deps_info") 1635f9996aaSopenharmony_ci check_list.extend(get_valid_deps(module_deps, finish_list)) 1645f9996aaSopenharmony_ci else: 1655f9996aaSopenharmony_ci stripped_dir = "" 1665f9996aaSopenharmony_ci if target_type == "shared_library": 1675f9996aaSopenharmony_ci stripped_dir = "lib.unstripped" 1685f9996aaSopenharmony_ci elif target_type == "executable": 1695f9996aaSopenharmony_ci stripped_dir = "exe.unstripped" 1705f9996aaSopenharmony_ci else: 1715f9996aaSopenharmony_ci raise Exception("Invalid target type: '{}'".format(target_type)) 1725f9996aaSopenharmony_ci 1735f9996aaSopenharmony_ci do_check(target_out_dir, target_name, stripped_dir, readelf, abidiff, abidw, abi_dumps_path) 1745f9996aaSopenharmony_ci if loop_count == 0: 1755f9996aaSopenharmony_ci copy_list.append(copy.deepcopy(get_copy_source_path(element))) 1765f9996aaSopenharmony_ci 1775f9996aaSopenharmony_ci module_deps = get_value_from_file("deps_data", element, "module_deps_info") 1785f9996aaSopenharmony_ci check_list.extend(get_valid_deps(module_deps, finish_list)) 1795f9996aaSopenharmony_ci loop_count += 1 1805f9996aaSopenharmony_ci return copy_list 1815f9996aaSopenharmony_ci 1825f9996aaSopenharmony_ci 1835f9996aaSopenharmony_cidef get_copy_output_path(element: list, parent_output: str): 1845f9996aaSopenharmony_ci output_path = parent_output 1855f9996aaSopenharmony_ci target_type = get_value_from_file("deps_data", element, "type") 1865f9996aaSopenharmony_ci if target_type == "etc": 1875f9996aaSopenharmony_ci output_path = os.path.join(parent_output, "etc") 1885f9996aaSopenharmony_ci elif target_type == "executable": 1895f9996aaSopenharmony_ci output_path = os.path.join(parent_output, "bin") 1905f9996aaSopenharmony_ci elif target_type == "shared_library": 1915f9996aaSopenharmony_ci output_path = os.path.join(parent_output, get_value_from_file("module_info", element, "type")) 1925f9996aaSopenharmony_ci return output_path 1935f9996aaSopenharmony_ci 1945f9996aaSopenharmony_ci 1955f9996aaSopenharmony_cidef main(): 1965f9996aaSopenharmony_ci parser = argparse.ArgumentParser() 1975f9996aaSopenharmony_ci parser.add_argument('--clang-readelf', required=True) 1985f9996aaSopenharmony_ci parser.add_argument('--target-out-dir', required=True) 1995f9996aaSopenharmony_ci parser.add_argument('--check-datas-file', required=True) 2005f9996aaSopenharmony_ci parser.add_argument('--abidiff-target-name', required=True) 2015f9996aaSopenharmony_ci parser.add_argument('--abidiff-target-out-dir', required=True) 2025f9996aaSopenharmony_ci parser.add_argument('--abidw-target-name', required=True) 2035f9996aaSopenharmony_ci parser.add_argument('--abidw-target-out-dir', required=True) 2045f9996aaSopenharmony_ci parser.add_argument('--abi-dumps-path', required=True) 2055f9996aaSopenharmony_ci args = parser.parse_args() 2065f9996aaSopenharmony_ci 2075f9996aaSopenharmony_ci if not os.path.exists(args.check_datas_file): 2085f9996aaSopenharmony_ci raise Exception("File " + args.check_datas_file + " not exists!") 2095f9996aaSopenharmony_ci 2105f9996aaSopenharmony_ci abidiff_element = (args.abidiff_target_name, args.abidiff_target_out_dir) 2115f9996aaSopenharmony_ci abidiff_bin = get_value_from_file("module_info", abidiff_element, "source") 2125f9996aaSopenharmony_ci abidw_element = (args.abidw_target_name, args.abidw_target_out_dir) 2135f9996aaSopenharmony_ci abidw_bin = get_value_from_file("module_info", abidw_element, "source") 2145f9996aaSopenharmony_ci 2155f9996aaSopenharmony_ci parent_output = os.path.join(args.target_out_dir, "module_package", "img_input") 2165f9996aaSopenharmony_ci if not os.path.exists(parent_output): 2175f9996aaSopenharmony_ci os.makedirs(parent_output, exist_ok=True) 2185f9996aaSopenharmony_ci 2195f9996aaSopenharmony_ci check_list = [] 2205f9996aaSopenharmony_ci check_datas = read_json_file(args.check_datas_file) 2215f9996aaSopenharmony_ci for check_data in check_datas: 2225f9996aaSopenharmony_ci element = (check_data.get("target_name"), check_data.get("target_out_dir")) 2235f9996aaSopenharmony_ci check_list.append(element) 2245f9996aaSopenharmony_ci 2255f9996aaSopenharmony_ci copy_list = traverse_and_check(check_list, args.clang_readelf, abidiff_bin, abidw_bin, args.abi_dumps_path) 2265f9996aaSopenharmony_ci for copy_element in copy_list: 2275f9996aaSopenharmony_ci print("copy_list: '{}'".format(str(copy_element))) 2285f9996aaSopenharmony_ci output = get_copy_output_path(copy_element[0], parent_output) 2295f9996aaSopenharmony_ci if not os.path.exists(output): 2305f9996aaSopenharmony_ci os.makedirs(output, exist_ok=True) 2315f9996aaSopenharmony_ci if isinstance(copy_element[1], list): 2325f9996aaSopenharmony_ci for file in copy_element[1]: 2335f9996aaSopenharmony_ci shutil.copy(file, output) 2345f9996aaSopenharmony_ci else: 2355f9996aaSopenharmony_ci shutil.copy(copy_element[1], output) 2365f9996aaSopenharmony_ci os.remove(args.check_datas_file) 2375f9996aaSopenharmony_ci 2385f9996aaSopenharmony_ci 2395f9996aaSopenharmony_ciif __name__ == '__main__': 2405f9996aaSopenharmony_ci sys.exit(main()) 241