13af6ab5fSopenharmony_ci#!/usr/bin/env python3 23af6ab5fSopenharmony_ci# -*- coding: utf-8 -*- 33af6ab5fSopenharmony_ci 43af6ab5fSopenharmony_ci""" 53af6ab5fSopenharmony_ciCopyright (c) 2021-2024 Huawei Device Co., Ltd. 63af6ab5fSopenharmony_ciLicensed under the Apache License, Version 2.0 (the "License"); 73af6ab5fSopenharmony_ciyou may not use this file except in compliance with the License. 83af6ab5fSopenharmony_ciYou may obtain a copy of the License at 93af6ab5fSopenharmony_ci 103af6ab5fSopenharmony_ci http://www.apache.org/licenses/LICENSE-2.0 113af6ab5fSopenharmony_ci 123af6ab5fSopenharmony_ciUnless required by applicable law or agreed to in writing, software 133af6ab5fSopenharmony_cidistributed under the License is distributed on an "AS IS" BASIS, 143af6ab5fSopenharmony_ciWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 153af6ab5fSopenharmony_ciSee the License for the specific language governing permissions and 163af6ab5fSopenharmony_cilimitations under the License. 173af6ab5fSopenharmony_ci 183af6ab5fSopenharmony_ciDescription: Implement the public interface in the 262 use case 193af6ab5fSopenharmony_ci""" 203af6ab5fSopenharmony_ci 213af6ab5fSopenharmony_ciimport os 223af6ab5fSopenharmony_ciimport signal 233af6ab5fSopenharmony_ciimport sys 243af6ab5fSopenharmony_ciimport subprocess 253af6ab5fSopenharmony_ciimport datetime 263af6ab5fSopenharmony_ciimport time 273af6ab5fSopenharmony_ciimport shutil 283af6ab5fSopenharmony_ciimport platform 293af6ab5fSopenharmony_ciimport re 303af6ab5fSopenharmony_cifrom config import DEFAULT_TIMEOUT, DEFAULT_RETRIES 313af6ab5fSopenharmony_ci 323af6ab5fSopenharmony_ciTERM_NORMAL = '\033[0m' 333af6ab5fSopenharmony_ciTERM_YELLOW = '\033[1;33m' 343af6ab5fSopenharmony_ciTERM_BLUE = '\033[1;34m' 353af6ab5fSopenharmony_ciTERM_RED = '\033[1;31m' 363af6ab5fSopenharmony_ciTERM_FUCHSIA = '\033[1;35m' 373af6ab5fSopenharmony_ci 383af6ab5fSopenharmony_ciABC_EXT = ".abc" 393af6ab5fSopenharmony_ciTEMP_ABC_EXT = ".temp.abc" 403af6ab5fSopenharmony_ciTXT_EXT = ".txt" 413af6ab5fSopenharmony_ciTEMP_TXT_EXT = ".temp.txt" 423af6ab5fSopenharmony_ci 433af6ab5fSopenharmony_ci 443af6ab5fSopenharmony_cidef output(retcode, msg): 453af6ab5fSopenharmony_ci if retcode == 0: 463af6ab5fSopenharmony_ci if msg != '': 473af6ab5fSopenharmony_ci print(str(msg)) 483af6ab5fSopenharmony_ci elif retcode == -6: 493af6ab5fSopenharmony_ci sys.stderr.write("Aborted (core dumped)") 503af6ab5fSopenharmony_ci elif retcode == -4: 513af6ab5fSopenharmony_ci sys.stderr.write("Aborted (core dumped)") 523af6ab5fSopenharmony_ci elif retcode == -11: 533af6ab5fSopenharmony_ci sys.stderr.write("Segmentation fault (core dumped)") 543af6ab5fSopenharmony_ci elif msg != '': 553af6ab5fSopenharmony_ci sys.stderr.write(str(msg)) 563af6ab5fSopenharmony_ci else: 573af6ab5fSopenharmony_ci sys.stderr.write("Unknown Error: " + str(retcode)) 583af6ab5fSopenharmony_ci 593af6ab5fSopenharmony_ci 603af6ab5fSopenharmony_cidef filter_arm_specific_errors(errs_str): 613af6ab5fSopenharmony_ci list_errs = [] 623af6ab5fSopenharmony_ci for err in errs_str.split("\n"): 633af6ab5fSopenharmony_ci if err: 643af6ab5fSopenharmony_ci if ("memset will be used instead" not in err and 653af6ab5fSopenharmony_ci "This is the expected behaviour if you are running under QEMU" not in err and 663af6ab5fSopenharmony_ci "Can't connect to server" not in err): 673af6ab5fSopenharmony_ci list_errs.append(err) 683af6ab5fSopenharmony_ci 693af6ab5fSopenharmony_ci if len(list_errs) != 0: 703af6ab5fSopenharmony_ci output(1, " ".join(list_errs)) 713af6ab5fSopenharmony_ci return False 723af6ab5fSopenharmony_ci 733af6ab5fSopenharmony_ci return True 743af6ab5fSopenharmony_ci 753af6ab5fSopenharmony_ci 763af6ab5fSopenharmony_cidef exec_command(cmd_args, timeout=DEFAULT_TIMEOUT, custom_cwd=None): 773af6ab5fSopenharmony_ci proc = subprocess.Popen(cmd_args, 783af6ab5fSopenharmony_ci stderr=subprocess.PIPE, 793af6ab5fSopenharmony_ci stdout=subprocess.PIPE, 803af6ab5fSopenharmony_ci close_fds=True, 813af6ab5fSopenharmony_ci start_new_session=True, 823af6ab5fSopenharmony_ci cwd=custom_cwd) 833af6ab5fSopenharmony_ci cmd_string = " ".join(cmd_args) 843af6ab5fSopenharmony_ci code_format = 'utf-8' 853af6ab5fSopenharmony_ci if platform.system() == "Windows": 863af6ab5fSopenharmony_ci code_format = 'gbk' 873af6ab5fSopenharmony_ci 883af6ab5fSopenharmony_ci try: 893af6ab5fSopenharmony_ci (output_res, errs) = proc.communicate(timeout=timeout) 903af6ab5fSopenharmony_ci ret_code = proc.poll() 913af6ab5fSopenharmony_ci 923af6ab5fSopenharmony_ci errs_str = errs.decode(code_format, 'ignore') 933af6ab5fSopenharmony_ci if filter_arm_specific_errors(errs_str): 943af6ab5fSopenharmony_ci errs = None 953af6ab5fSopenharmony_ci else: 963af6ab5fSopenharmony_ci return 1 973af6ab5fSopenharmony_ci 983af6ab5fSopenharmony_ci if ret_code and ret_code != 1: 993af6ab5fSopenharmony_ci code = ret_code 1003af6ab5fSopenharmony_ci msg = f"Command {cmd_string}: \n" 1013af6ab5fSopenharmony_ci msg += f"error: {errs_str}" 1023af6ab5fSopenharmony_ci else: 1033af6ab5fSopenharmony_ci code = 0 1043af6ab5fSopenharmony_ci msg = str(output_res.decode(code_format, 'ignore')) 1053af6ab5fSopenharmony_ci 1063af6ab5fSopenharmony_ci except subprocess.TimeoutExpired: 1073af6ab5fSopenharmony_ci proc.kill() 1083af6ab5fSopenharmony_ci proc.terminate() 1093af6ab5fSopenharmony_ci os.kill(proc.pid, signal.SIGTERM) 1103af6ab5fSopenharmony_ci code = 1 1113af6ab5fSopenharmony_ci msg = f"Timeout:'{cmd_string}' timed out after' {str(timeout)} seconds" 1123af6ab5fSopenharmony_ci except Exception as err: 1133af6ab5fSopenharmony_ci code = 1 1143af6ab5fSopenharmony_ci msg = f"{cmd_string}: unknown error: {str(err)}" 1153af6ab5fSopenharmony_ci output(code, msg) 1163af6ab5fSopenharmony_ci return code 1173af6ab5fSopenharmony_ci 1183af6ab5fSopenharmony_ci 1193af6ab5fSopenharmony_cidef print_command(cmd_args): 1203af6ab5fSopenharmony_ci sys.stderr.write("\n") 1213af6ab5fSopenharmony_ci sys.stderr.write(" ".join(cmd_args)) 1223af6ab5fSopenharmony_ci sys.stderr.write("\n") 1233af6ab5fSopenharmony_ci 1243af6ab5fSopenharmony_ci 1253af6ab5fSopenharmony_ci# for debug use, to keep aot file 1263af6ab5fSopenharmony_cidef run_command(cmd_args): 1273af6ab5fSopenharmony_ci return subprocess.run(" ".join(cmd_args)) 1283af6ab5fSopenharmony_ci 1293af6ab5fSopenharmony_ci 1303af6ab5fSopenharmony_cidef get_formated_path(path): 1313af6ab5fSopenharmony_ci # In the case of Windows, it is necessary to convert ' \\' to '/', otherwise there will be a crash or the file cannot be found 1323af6ab5fSopenharmony_ci # Maintain consistent interface path with DevEco Studio 1333af6ab5fSopenharmony_ci if platform.system() == "Windows": 1343af6ab5fSopenharmony_ci return path.replace("\\", "/") 1353af6ab5fSopenharmony_ci return path 1363af6ab5fSopenharmony_ci 1373af6ab5fSopenharmony_ci 1383af6ab5fSopenharmony_cidef current_time(): 1393af6ab5fSopenharmony_ci return datetime.datetime.now().strftime('%m-%d %H:%M:%S.%f') 1403af6ab5fSopenharmony_ci 1413af6ab5fSopenharmony_ci 1423af6ab5fSopenharmony_ciclass Logging(): 1433af6ab5fSopenharmony_ci def __init__(self): 1443af6ab5fSopenharmony_ci self.is_logging = True 1453af6ab5fSopenharmony_ci 1463af6ab5fSopenharmony_ci def debug(self, info): 1473af6ab5fSopenharmony_ci if self.is_logging: 1483af6ab5fSopenharmony_ci print( 1493af6ab5fSopenharmony_ci f'{current_time()} D:>>> {TERM_BLUE}{str(info)}{TERM_NORMAL}') 1503af6ab5fSopenharmony_ci 1513af6ab5fSopenharmony_ci def info(self, info): 1523af6ab5fSopenharmony_ci if self.is_logging: 1533af6ab5fSopenharmony_ci if len(str(info)) > 100: 1543af6ab5fSopenharmony_ci print(f'{current_time()} I:>>> \n{str(info)} ') 1553af6ab5fSopenharmony_ci else: 1563af6ab5fSopenharmony_ci print(f'{current_time()} I:>>> {str(info)} ') 1573af6ab5fSopenharmony_ci 1583af6ab5fSopenharmony_ci 1593af6ab5fSopenharmony_ciLOGGING = Logging() 1603af6ab5fSopenharmony_ci 1613af6ab5fSopenharmony_ci 1623af6ab5fSopenharmony_ciclass Command(): 1633af6ab5fSopenharmony_ci def __init__(self, cmd): 1643af6ab5fSopenharmony_ci self.cmd = cmd 1653af6ab5fSopenharmony_ci 1663af6ab5fSopenharmony_ci def run(self): 1673af6ab5fSopenharmony_ci LOGGING.debug("command: " + self.cmd) 1683af6ab5fSopenharmony_ci out = os.popen(self.cmd).read() 1693af6ab5fSopenharmony_ci LOGGING.info(out) 1703af6ab5fSopenharmony_ci return out 1713af6ab5fSopenharmony_ci 1723af6ab5fSopenharmony_ci 1733af6ab5fSopenharmony_cidef run_cmd(command): 1743af6ab5fSopenharmony_ci cmd = Command(command) 1753af6ab5fSopenharmony_ci return cmd.run() 1763af6ab5fSopenharmony_ci 1773af6ab5fSopenharmony_ci 1783af6ab5fSopenharmony_ciclass CommandCwd(): 1793af6ab5fSopenharmony_ci def __init__(self, cmds, cwd): 1803af6ab5fSopenharmony_ci self.cmds = cmds 1813af6ab5fSopenharmony_ci self.cwd = cwd 1823af6ab5fSopenharmony_ci 1833af6ab5fSopenharmony_ci def run(self): 1843af6ab5fSopenharmony_ci cmd = " ".join(self.cmds) 1853af6ab5fSopenharmony_ci LOGGING.debug("command: " + cmd + " | " + "dir: " + self.cwd) 1863af6ab5fSopenharmony_ci if platform.system() == "Windows" : 1873af6ab5fSopenharmony_ci proc = subprocess.Popen(self.cmds, cwd=self.cwd ,shell=True) 1883af6ab5fSopenharmony_ci else : 1893af6ab5fSopenharmony_ci proc = subprocess.Popen(self.cmds, cwd=self.cwd) 1903af6ab5fSopenharmony_ci return proc.wait() 1913af6ab5fSopenharmony_ci 1923af6ab5fSopenharmony_ci 1933af6ab5fSopenharmony_cidef run_cmd_cwd(commands, cwd=os.getcwd()): 1943af6ab5fSopenharmony_ci cmd = CommandCwd(commands, cwd) 1953af6ab5fSopenharmony_ci return cmd.run() 1963af6ab5fSopenharmony_ci 1973af6ab5fSopenharmony_ci 1983af6ab5fSopenharmony_cidef sleep(duration): 1993af6ab5fSopenharmony_ci LOGGING.debug("sleeping %d" % duration) 2003af6ab5fSopenharmony_ci time.sleep(duration) 2013af6ab5fSopenharmony_ci 2023af6ab5fSopenharmony_ci 2033af6ab5fSopenharmony_cidef write_file(save_file, result): 2043af6ab5fSopenharmony_ci LOGGING.debug(f"write file:{save_file}") 2053af6ab5fSopenharmony_ci with open(save_file, "a+") as file: 2063af6ab5fSopenharmony_ci file.write(result + "\n") 2073af6ab5fSopenharmony_ci file.flush() 2083af6ab5fSopenharmony_ci 2093af6ab5fSopenharmony_ci 2103af6ab5fSopenharmony_cidef remove_dir(path): 2113af6ab5fSopenharmony_ci if os.path.exists(path): 2123af6ab5fSopenharmony_ci shutil.rmtree(path) 2133af6ab5fSopenharmony_ci 2143af6ab5fSopenharmony_ci 2153af6ab5fSopenharmony_cidef remove_file(file): 2163af6ab5fSopenharmony_ci if os.path.exists(file): 2173af6ab5fSopenharmony_ci os.remove(file) 2183af6ab5fSopenharmony_ci 2193af6ab5fSopenharmony_ci 2203af6ab5fSopenharmony_cidef mkdir(path): 2213af6ab5fSopenharmony_ci if not os.path.exists(path): 2223af6ab5fSopenharmony_ci os.makedirs(path) 2233af6ab5fSopenharmony_ci 2243af6ab5fSopenharmony_ci 2253af6ab5fSopenharmony_cidef report_command(cmd_type, cmd, env=None): 2263af6ab5fSopenharmony_ci sys.stderr.write(f'{TERM_BLUE}{cmd_type}{TERM_NORMAL}\n') 2273af6ab5fSopenharmony_ci if env is not None: 2283af6ab5fSopenharmony_ci sys.stderr.write(''.join(f'{TERM_BLUE}{var}={val} \\{TERM_NORMAL}\n' 2293af6ab5fSopenharmony_ci for var, val in sorted(env.items()))) 2303af6ab5fSopenharmony_ci cmd_str = (f'{TERM_NORMAL}\n\t{TERM_BLUE}').join(cmd) 2313af6ab5fSopenharmony_ci sys.stderr.write(f'\t{TERM_BLUE}{cmd_str}{TERM_NORMAL}\n') 2323af6ab5fSopenharmony_ci sys.stderr.write("\n") 2333af6ab5fSopenharmony_ci 2343af6ab5fSopenharmony_ci 2353af6ab5fSopenharmony_cidef git_clone(git_url, code_dir): 2363af6ab5fSopenharmony_ci cmd = ['git', 'clone', git_url, code_dir] 2373af6ab5fSopenharmony_ci retries = 1 2383af6ab5fSopenharmony_ci while retries <= DEFAULT_RETRIES: 2393af6ab5fSopenharmony_ci ret = run_cmd_cwd(cmd) 2403af6ab5fSopenharmony_ci if ret == 0: 2413af6ab5fSopenharmony_ci break 2423af6ab5fSopenharmony_ci else: 2433af6ab5fSopenharmony_ci print(f"\n warning: Atempt: #{retries} to clone '{git_url}' failed. Try cloining again") 2443af6ab5fSopenharmony_ci retries += 1 2453af6ab5fSopenharmony_ci assert not ret, f"\n error: Cloning '{git_url}' failed." 2463af6ab5fSopenharmony_ci 2473af6ab5fSopenharmony_ci 2483af6ab5fSopenharmony_cidef git_checkout(git_bash, cwd): 2493af6ab5fSopenharmony_ci cmd = ['git', 'checkout', '-f', git_bash] 2503af6ab5fSopenharmony_ci ret = run_cmd_cwd(cmd, cwd) 2513af6ab5fSopenharmony_ci assert not ret, f"\n error: git checkout '{git_bash}' failed." 2523af6ab5fSopenharmony_ci 2533af6ab5fSopenharmony_ci 2543af6ab5fSopenharmony_cidef git_apply(patch_file, cwd): 2553af6ab5fSopenharmony_ci cmd = ['git', 'apply', patch_file] 2563af6ab5fSopenharmony_ci ret = run_cmd_cwd(cmd, cwd) 2573af6ab5fSopenharmony_ci assert not ret, f"\n error: Failed to apply '{patch_file}'" 2583af6ab5fSopenharmony_ci 2593af6ab5fSopenharmony_ci 2603af6ab5fSopenharmony_cidef git_clean(cwd): 2613af6ab5fSopenharmony_ci cmd = ['git', 'checkout', '--', '.'] 2623af6ab5fSopenharmony_ci run_cmd_cwd(cmd, cwd) 2633af6ab5fSopenharmony_ci 2643af6ab5fSopenharmony_ci 2653af6ab5fSopenharmony_cidef npm_install(cwd): 2663af6ab5fSopenharmony_ci cmd = ['npm', 'install'] 2673af6ab5fSopenharmony_ci ret = run_cmd_cwd(cmd, cwd) 2683af6ab5fSopenharmony_ci assert not ret, f"\n error: Failed to 'npm install'" 2693af6ab5fSopenharmony_ci 2703af6ab5fSopenharmony_ci 2713af6ab5fSopenharmony_cidef search_dependency(file, directory): 2723af6ab5fSopenharmony_ci for root, dirs, files in os.walk(directory, topdown=True): 2733af6ab5fSopenharmony_ci for f in files: 2743af6ab5fSopenharmony_ci if f == file: 2753af6ab5fSopenharmony_ci return os.path.join(root, f) 2763af6ab5fSopenharmony_ci return "FILE_NOT_FOUND" 2773af6ab5fSopenharmony_ci 2783af6ab5fSopenharmony_ci 2793af6ab5fSopenharmony_cidef collect_module_dependencies(file, directory, traversedDependencies): 2803af6ab5fSopenharmony_ci dependencies = [] 2813af6ab5fSopenharmony_ci traversedDependencies.append(file) 2823af6ab5fSopenharmony_ci with open(file, 'r', encoding='utf-8') as f: 2833af6ab5fSopenharmony_ci content = f.read() 2843af6ab5fSopenharmony_ci module_import_list = re.findall(r'(import|from)(?:\s*)\(?(\'(\.\/.*)\'|"(\.\/.*)")\)?', content) 2853af6ab5fSopenharmony_ci 2863af6ab5fSopenharmony_ci for result in list(set(module_import_list)): 2873af6ab5fSopenharmony_ci specifier = (result[2] if len(result[2]) != 0 else result[3]).lstrip('./') 2883af6ab5fSopenharmony_ci if os.path.basename(file) is not specifier: 2893af6ab5fSopenharmony_ci dependency = search_dependency(specifier, directory) 2903af6ab5fSopenharmony_ci if dependency == "FILE_NOT_FOUND": 2913af6ab5fSopenharmony_ci continue 2923af6ab5fSopenharmony_ci 2933af6ab5fSopenharmony_ci if dependency not in traversedDependencies: 2943af6ab5fSopenharmony_ci dependencies.extend(collect_module_dependencies(dependency, directory, 2953af6ab5fSopenharmony_ci list(set(traversedDependencies)))) 2963af6ab5fSopenharmony_ci dependencies.append(dependency) 2973af6ab5fSopenharmony_ci 2983af6ab5fSopenharmony_ci return dependencies