1570af302Sopenharmony_ciimport argparse 2570af302Sopenharmony_ciimport os 3570af302Sopenharmony_ciimport sys 4570af302Sopenharmony_ciimport json 5570af302Sopenharmony_ciimport ccsyspath 6570af302Sopenharmony_ciimport time 7570af302Sopenharmony_ciimport clang.cindex 8570af302Sopenharmony_cifrom clang.cindex import Cursor 9570af302Sopenharmony_cifrom clang.cindex import CursorKind 10570af302Sopenharmony_cifrom pathlib import Path 11570af302Sopenharmony_cifrom clang.cindex import TranslationUnit 12570af302Sopenharmony_ci 13570af302Sopenharmony_ci 14570af302Sopenharmony_cidef get_args(): 15570af302Sopenharmony_ci ''' 16570af302Sopenharmony_ci Get and parse the parameters from the console 17570af302Sopenharmony_ci ''' 18570af302Sopenharmony_ci parse = argparse.ArgumentParser(prog='python3.8 compare.py') 19570af302Sopenharmony_ci parse.add_argument('-l', 20570af302Sopenharmony_ci type=str, 21570af302Sopenharmony_ci required=True, 22570af302Sopenharmony_ci help='input lib file path') 23570af302Sopenharmony_ci parse.add_argument('-i', 24570af302Sopenharmony_ci type=str, 25570af302Sopenharmony_ci required=True, 26570af302Sopenharmony_ci help='input head file path') 27570af302Sopenharmony_ci parse.add_argument('-m', type=str, help='input macros file path') 28570af302Sopenharmony_ci parse.add_argument('-b', type=str, help='input blacklist file path') 29570af302Sopenharmony_ci parse.add_argument('-o', type=str, help='result file output path') 30570af302Sopenharmony_ci args = parse.parse_args() 31570af302Sopenharmony_ci paramers_value = vars(args) 32570af302Sopenharmony_ci global INPUT_HEAD_PATH 33570af302Sopenharmony_ci INPUT_HEAD_PATH = paramers_value['i'] 34570af302Sopenharmony_ci global INPUT_LIB_PATH 35570af302Sopenharmony_ci INPUT_LIB_PATH = paramers_value['l'] 36570af302Sopenharmony_ci global INPUT_MACROS_PATH 37570af302Sopenharmony_ci INPUT_MACROS_PATH = paramers_value['m'] 38570af302Sopenharmony_ci INPUT_MACROS_PATH = '' if INPUT_MACROS_PATH == None else INPUT_MACROS_PATH 39570af302Sopenharmony_ci global INPUT_BLACK_PATH 40570af302Sopenharmony_ci INPUT_BLACK_PATH = paramers_value['b'] 41570af302Sopenharmony_ci INPUT_BLACK_PATH = '' if INPUT_BLACK_PATH == None else INPUT_BLACK_PATH 42570af302Sopenharmony_ci global OUTPUT_RESULT_PATH 43570af302Sopenharmony_ci OUTPUT_RESULT_PATH = paramers_value['o'] 44570af302Sopenharmony_ci OUTPUT_RESULT_PATH = '' if OUTPUT_RESULT_PATH == None else OUTPUT_RESULT_PATH 45570af302Sopenharmony_ci check_parameters() 46570af302Sopenharmony_ci 47570af302Sopenharmony_ci 48570af302Sopenharmony_cidef check_parameters(): 49570af302Sopenharmony_ci ''' 50570af302Sopenharmony_ci Check whether the obtained parameters are correct 51570af302Sopenharmony_ci ''' 52570af302Sopenharmony_ci my_file = Path(INPUT_LIB_PATH) 53570af302Sopenharmony_ci if not my_file.is_file(): 54570af302Sopenharmony_ci print('please input correct lib file path') 55570af302Sopenharmony_ci exit() 56570af302Sopenharmony_ci my_file = Path(INPUT_HEAD_PATH) 57570af302Sopenharmony_ci if not my_file.is_dir(): 58570af302Sopenharmony_ci print('please input correct head file path') 59570af302Sopenharmony_ci exit() 60570af302Sopenharmony_ci global INPUT_BLACK_PATH 61570af302Sopenharmony_ci if not INPUT_BLACK_PATH == '': 62570af302Sopenharmony_ci my_file = Path(INPUT_BLACK_PATH) 63570af302Sopenharmony_ci if not my_file.is_file(): 64570af302Sopenharmony_ci print('warring:input correct blacklist file path is error') 65570af302Sopenharmony_ci INPUT_BLACK_PATH = '' 66570af302Sopenharmony_ci global INPUT_MACROS_PATH 67570af302Sopenharmony_ci if not INPUT_MACROS_PATH == '': 68570af302Sopenharmony_ci my_file = Path(INPUT_MACROS_PATH) 69570af302Sopenharmony_ci if not my_file.is_file(): 70570af302Sopenharmony_ci print('warring:input correct macros file path is error') 71570af302Sopenharmony_ci INPUT_MACROS_PATH = '' 72570af302Sopenharmony_ci global OUTPUT_RESULT_PATH 73570af302Sopenharmony_ci if not OUTPUT_RESULT_PATH == '': 74570af302Sopenharmony_ci my_file = Path(OUTPUT_RESULT_PATH) 75570af302Sopenharmony_ci if not my_file.is_dir(): 76570af302Sopenharmony_ci print('warring:input correct output file path is error') 77570af302Sopenharmony_ci OUTPUT_RESULT_PATH = '' 78570af302Sopenharmony_ci 79570af302Sopenharmony_ci 80570af302Sopenharmony_cidef os_popen(stmt): 81570af302Sopenharmony_ci ''' 82570af302Sopenharmony_ci Get the result of execution according to command parameter 83570af302Sopenharmony_ci ''' 84570af302Sopenharmony_ci re = os.popen(stmt).readlines() 85570af302Sopenharmony_ci result = [] 86570af302Sopenharmony_ci for i in range(0, len(re)): 87570af302Sopenharmony_ci res = re[i].strip('\n') 88570af302Sopenharmony_ci result.append(res) 89570af302Sopenharmony_ci return result 90570af302Sopenharmony_ci 91570af302Sopenharmony_ci 92570af302Sopenharmony_cidef get_info_from_file(file_path): 93570af302Sopenharmony_ci ''' 94570af302Sopenharmony_ci Get the list of contents in the file based on the path parameter 95570af302Sopenharmony_ci ''' 96570af302Sopenharmony_ci temp_file_list = [] 97570af302Sopenharmony_ci with open(file_path) as file_object: 98570af302Sopenharmony_ci for line in file_object: 99570af302Sopenharmony_ci temp_file_list.append(line.rstrip()) 100570af302Sopenharmony_ci return temp_file_list 101570af302Sopenharmony_ci 102570af302Sopenharmony_ci 103570af302Sopenharmony_cidef get_lib_strs(): 104570af302Sopenharmony_ci ''' 105570af302Sopenharmony_ci Get a list of library file symbols 106570af302Sopenharmony_ci ''' 107570af302Sopenharmony_ci temp_lib_name_list = os_popen( 108570af302Sopenharmony_ci 'nm -D ' + INPUT_LIB_PATH + 109570af302Sopenharmony_ci '| grep -Ev " U " | grep -Ev " W " | grep -Ev " D " | grep -Ev " V " | grep -Ev " w " | awk \'{print $3}\' | xargs c++filt' 110570af302Sopenharmony_ci ) 111570af302Sopenharmony_ci if len(temp_lib_name_list) == 0: 112570af302Sopenharmony_ci print("canot find lib file error") 113570af302Sopenharmony_ci exit() 114570af302Sopenharmony_ci global LIB_FILE_NAME_LIST 115570af302Sopenharmony_ci for i in temp_lib_name_list: 116570af302Sopenharmony_ci LIB_FILE_NAME_LIST.append(sub_str_name(i)) 117570af302Sopenharmony_ci LIB_FILE_NAME_LIST = list(set(LIB_FILE_NAME_LIST)) 118570af302Sopenharmony_ci LIB_FILE_NAME_LIST.sort() 119570af302Sopenharmony_ci 120570af302Sopenharmony_ci 121570af302Sopenharmony_cidef get_permission_num(permissions): 122570af302Sopenharmony_ci ''' 123570af302Sopenharmony_ci Get the number of arguments of c++ function 124570af302Sopenharmony_ci ''' 125570af302Sopenharmony_ci if not permissions.find('()') == -1: 126570af302Sopenharmony_ci return 0 127570af302Sopenharmony_ci else: 128570af302Sopenharmony_ci count_premission = 1 129570af302Sopenharmony_ci current_sym_num = 0 130570af302Sopenharmony_ci for i in permissions: 131570af302Sopenharmony_ci if i == '<': 132570af302Sopenharmony_ci current_sym_num = current_sym_num + 1 133570af302Sopenharmony_ci if i == '>': 134570af302Sopenharmony_ci current_sym_num = current_sym_num - 1 135570af302Sopenharmony_ci if i == ',' and current_sym_num == 0: 136570af302Sopenharmony_ci count_premission = count_premission + 1 137570af302Sopenharmony_ci return count_premission 138570af302Sopenharmony_ci 139570af302Sopenharmony_ci 140570af302Sopenharmony_cidef sub_str_name(iteam): 141570af302Sopenharmony_ci ''' 142570af302Sopenharmony_ci Handling redundant information in library file symbol table 143570af302Sopenharmony_ci ''' 144570af302Sopenharmony_ci if not iteam.find('non-virtual thunk to ') == -1: 145570af302Sopenharmony_ci iteam = iteam.replace('non-virtual thunk to ', '') 146570af302Sopenharmony_ci if not iteam.find('virtual thunk to ') == -1: 147570af302Sopenharmony_ci iteam = iteam.replace('virtual thunk to ', '') 148570af302Sopenharmony_ci if iteam.find('(') == -1: 149570af302Sopenharmony_ci return iteam 150570af302Sopenharmony_ci else: 151570af302Sopenharmony_ci return iteam[:iteam.index('(')] + '@' + str(get_permission_num(iteam)) 152570af302Sopenharmony_ci 153570af302Sopenharmony_ci 154570af302Sopenharmony_cidef get_head_strs(): 155570af302Sopenharmony_ci ''' 156570af302Sopenharmony_ci Get a list of header file symbols 157570af302Sopenharmony_ci ''' 158570af302Sopenharmony_ci head_file_name_list = os_popen('find ' + INPUT_HEAD_PATH + ' -name "*.h"') 159570af302Sopenharmony_ci if len(head_file_name_list) == 0: 160570af302Sopenharmony_ci print('canot find head file error') 161570af302Sopenharmony_ci exit() 162570af302Sopenharmony_ci compile_args = ['-x', 'c++'] 163570af302Sopenharmony_ci marcros_list = [] 164570af302Sopenharmony_ci if not INPUT_MACROS_PATH == '': 165570af302Sopenharmony_ci temp_macros = get_info_from_file(INPUT_MACROS_PATH) 166570af302Sopenharmony_ci for i in temp_macros: 167570af302Sopenharmony_ci marcros_list.append('-D' + i) 168570af302Sopenharmony_ci for i in head_file_name_list: 169570af302Sopenharmony_ci global CURRENT_FILE_TYPE 170570af302Sopenharmony_ci CURRENT_FILE_TYPE = 0 171570af302Sopenharmony_ci index = clang.cindex.Index.create() 172570af302Sopenharmony_ci parser = index.parse(i, args=compile_args) 173570af302Sopenharmony_ci cursor = parser.cursor 174570af302Sopenharmony_ci traverse(cursor) 175570af302Sopenharmony_ci if CURRENT_FILE_TYPE == 0: 176570af302Sopenharmony_ci index_temp = clang.cindex.Index.create() 177570af302Sopenharmony_ci syspath = ccsyspath.system_include_paths('clang') 178570af302Sopenharmony_ci incargs = [b'-I' + inc for inc in syspath] 179570af302Sopenharmony_ci incargs.append('-I'+INPUT_HEAD_PATH) 180570af302Sopenharmony_ci parser_temp = index_temp.parse(i, args=marcros_list + incargs) 181570af302Sopenharmony_ci cursor_temp = parser_temp.cursor 182570af302Sopenharmony_ci traverse_c(cursor_temp, 0) 183570af302Sopenharmony_ci else: 184570af302Sopenharmony_ci index_temp = clang.cindex.Index.create() 185570af302Sopenharmony_ci syspath = ccsyspath.system_include_paths('clang++') 186570af302Sopenharmony_ci incargs = [b'-I' + inc for inc in syspath] 187570af302Sopenharmony_ci incargs.append('-I'+INPUT_HEAD_PATH) 188570af302Sopenharmony_ci parser_temp = index_temp.parse(i, 189570af302Sopenharmony_ci args=marcros_list + compile_args + 190570af302Sopenharmony_ci incargs) 191570af302Sopenharmony_ci cursor_temp = parser_temp.cursor 192570af302Sopenharmony_ci traverse_cpp(cursor_temp, '') 193570af302Sopenharmony_ci global HEAD_FILE_NAME_LIST 194570af302Sopenharmony_ci HEAD_FILE_NAME_LIST = list(set(HEAD_FILE_NAME_LIST)) 195570af302Sopenharmony_ci HEAD_FILE_NAME_LIST.sort() 196570af302Sopenharmony_ci 197570af302Sopenharmony_ci 198570af302Sopenharmony_cidef traverse_c(node, depth): 199570af302Sopenharmony_ci ''' 200570af302Sopenharmony_ci Recursively obtain the symbol list from the c language header file and store it in HEAD_FILE_NAME_LIST 201570af302Sopenharmony_ci ''' 202570af302Sopenharmony_ci global HEAD_FILE_NAME_LIST 203570af302Sopenharmony_ci if node.kind == CursorKind.FUNCTION_DECL: 204570af302Sopenharmony_ci if is_has_extern_in_node(node): 205570af302Sopenharmony_ci HEAD_FILE_NAME_LIST.append(node.spelling) 206570af302Sopenharmony_ci if node.kind == CursorKind.VAR_DECL and depth == 1: 207570af302Sopenharmony_ci if is_has_extern_in_node(node): 208570af302Sopenharmony_ci HEAD_FILE_NAME_LIST.append(node.spelling) 209570af302Sopenharmony_ci for n in node.get_children(): 210570af302Sopenharmony_ci traverse_c(n, depth + 1) 211570af302Sopenharmony_ci 212570af302Sopenharmony_ci 213570af302Sopenharmony_cidef check_cpp_namespace(depth): 214570af302Sopenharmony_ci if not depth.find('std') == -1: 215570af302Sopenharmony_ci return False 216570af302Sopenharmony_ci if not depth.find('__gnu_cxx') == -1: 217570af302Sopenharmony_ci return False 218570af302Sopenharmony_ci if not depth.find('__cxxabiv1') == -1: 219570af302Sopenharmony_ci return False 220570af302Sopenharmony_ci if not depth.find('__pthread_cleanup_class') == -1: 221570af302Sopenharmony_ci return False 222570af302Sopenharmony_ci return True 223570af302Sopenharmony_ci 224570af302Sopenharmony_ci 225570af302Sopenharmony_cidef traverse_cpp(node, depth): 226570af302Sopenharmony_ci ''' 227570af302Sopenharmony_ci Recursively obtain the symbol list from the c++ language header file and store it in HEAD_FILE_NAME_LIST 228570af302Sopenharmony_ci ''' 229570af302Sopenharmony_ci global HEAD_FILE_NAME_LIST 230570af302Sopenharmony_ci if node.kind == CursorKind.NAMESPACE or node.kind == CursorKind.CLASS_DECL: 231570af302Sopenharmony_ci if depth == '': 232570af302Sopenharmony_ci depth = node.spelling 233570af302Sopenharmony_ci else: 234570af302Sopenharmony_ci depth = depth + '::' + node.spelling 235570af302Sopenharmony_ci if node.kind == CursorKind.CXX_METHOD and check_cpp_namespace( 236570af302Sopenharmony_ci depth) and not depth == '' and not node.is_pure_virtual_method(): 237570af302Sopenharmony_ci HEAD_FILE_NAME_LIST.append(depth + '::' + node.spelling + '@' + 238570af302Sopenharmony_ci str(get_permission_num(node.displayname))) 239570af302Sopenharmony_ci if node.kind == CursorKind.FUNCTION_TEMPLATE and check_cpp_namespace( 240570af302Sopenharmony_ci depth) and not depth == '': 241570af302Sopenharmony_ci HEAD_FILE_NAME_LIST.append(depth + '::' + node.spelling + '@' + 242570af302Sopenharmony_ci str(get_permission_num(node.displayname))) 243570af302Sopenharmony_ci if node.kind == CursorKind.DESTRUCTOR and check_cpp_namespace(depth): 244570af302Sopenharmony_ci HEAD_FILE_NAME_LIST.append(depth + '::' + node.spelling + '@0') 245570af302Sopenharmony_ci if node.kind == CursorKind.VAR_DECL and check_cpp_namespace( 246570af302Sopenharmony_ci depth) and not depth == '': 247570af302Sopenharmony_ci HEAD_FILE_NAME_LIST.append(depth + '::' + node.spelling) 248570af302Sopenharmony_ci if node.kind == CursorKind.CONSTRUCTOR and check_cpp_namespace(depth): 249570af302Sopenharmony_ci HEAD_FILE_NAME_LIST.append(depth + '::' + node.spelling + '@' + 250570af302Sopenharmony_ci str(get_permission_num(node.displayname))) 251570af302Sopenharmony_ci for n in node.get_children(): 252570af302Sopenharmony_ci traverse_cpp(n, depth) 253570af302Sopenharmony_ci 254570af302Sopenharmony_ci 255570af302Sopenharmony_cidef is_has_extern_in_node(node): 256570af302Sopenharmony_ci for i in node.get_tokens(): 257570af302Sopenharmony_ci if i.spelling == 'extern' or i.spelling == '__inline': 258570af302Sopenharmony_ci return False 259570af302Sopenharmony_ci return True 260570af302Sopenharmony_ci 261570af302Sopenharmony_ci 262570af302Sopenharmony_cidef traverse(node): 263570af302Sopenharmony_ci ''' 264570af302Sopenharmony_ci Determine the type of the file parameter 265570af302Sopenharmony_ci ''' 266570af302Sopenharmony_ci global CURRENT_FILE_TYPE 267570af302Sopenharmony_ci if node.kind == CursorKind.CLASS_DECL: 268570af302Sopenharmony_ci CURRENT_FILE_TYPE = 1 269570af302Sopenharmony_ci for n in node.get_children(): 270570af302Sopenharmony_ci traverse(n) 271570af302Sopenharmony_ci 272570af302Sopenharmony_ci 273570af302Sopenharmony_cidef get_compare_result(): 274570af302Sopenharmony_ci ''' 275570af302Sopenharmony_ci Compare the symbol lists of header and library files and generate a file that stores the results of the comparison 276570af302Sopenharmony_ci ''' 277570af302Sopenharmony_ci only_lib_have = list( 278570af302Sopenharmony_ci set(LIB_FILE_NAME_LIST).difference(set(HEAD_FILE_NAME_LIST))) 279570af302Sopenharmony_ci only_head_have = list( 280570af302Sopenharmony_ci set(HEAD_FILE_NAME_LIST).difference(set(LIB_FILE_NAME_LIST))) 281570af302Sopenharmony_ci not_compare_list = [] 282570af302Sopenharmony_ci if not INPUT_BLACK_PATH == '': 283570af302Sopenharmony_ci not_compare_list = not_compare_list + get_info_from_file( 284570af302Sopenharmony_ci INPUT_BLACK_PATH) 285570af302Sopenharmony_ci only_lib_have = list(set(only_lib_have).difference(set(not_compare_list))) 286570af302Sopenharmony_ci only_head_have = list( 287570af302Sopenharmony_ci set(only_head_have).difference(set(not_compare_list))) 288570af302Sopenharmony_ci only_lib_have.sort() 289570af302Sopenharmony_ci only_head_have.sort() 290570af302Sopenharmony_ci result = {} 291570af302Sopenharmony_ci result['head_file_path'] = INPUT_HEAD_PATH 292570af302Sopenharmony_ci result['lib_file_path'] = INPUT_LIB_PATH 293570af302Sopenharmony_ci result['only_in_head_file'] = only_head_have 294570af302Sopenharmony_ci result['only_in_lib_file'] = only_lib_have 295570af302Sopenharmony_ci result['head_file_symble_list_num:lib_file_symble_list_nmu'] = str( 296570af302Sopenharmony_ci len(HEAD_FILE_NAME_LIST)) + ':' + str(len(LIB_FILE_NAME_LIST)) 297570af302Sopenharmony_ci seconds = time.time() 298570af302Sopenharmony_ci time_str = time.strftime('%Y-%m-%d-%H:%M:%S', time.localtime(seconds)) 299570af302Sopenharmony_ci out_difference_path = OUTPUT_RESULT_PATH + 'compare_result_' + time_str + '.json' 300570af302Sopenharmony_ci out_lib_path = OUTPUT_RESULT_PATH + 'lib_file_list_' + time_str + '.txt' 301570af302Sopenharmony_ci out_head_path = OUTPUT_RESULT_PATH + 'head_file_list_' + time_str + '.txt' 302570af302Sopenharmony_ci with open(out_difference_path, 'w') as file_obj: 303570af302Sopenharmony_ci json.dump(result, file_obj, indent=4, separators=(',', ':')) 304570af302Sopenharmony_ci file_obj.close() 305570af302Sopenharmony_ci f = open(out_lib_path, 'w') 306570af302Sopenharmony_ci for line in LIB_FILE_NAME_LIST: 307570af302Sopenharmony_ci f.write(line + '\n') 308570af302Sopenharmony_ci f.close() 309570af302Sopenharmony_ci f = open(out_head_path, 'w') 310570af302Sopenharmony_ci for line in HEAD_FILE_NAME_LIST: 311570af302Sopenharmony_ci f.write(line + '\n') 312570af302Sopenharmony_ci f.close() 313570af302Sopenharmony_ci 314570af302Sopenharmony_ci 315570af302Sopenharmony_ciINPUT_LIB_PATH = '' #The path to the entered library file 316570af302Sopenharmony_ciINPUT_HEAD_PATH = '' #The path to the entered header file 317570af302Sopenharmony_ciINPUT_BLACK_PATH = '' #The path to the entered blacklist file 318570af302Sopenharmony_ciINPUT_MACROS_PATH = '' #The path to the entered macro definition file 319570af302Sopenharmony_ciOUTPUT_RESULT_PATH = '' #The output path of the result file 320570af302Sopenharmony_ciHEAD_FILE_NAME_LIST = [] #header file symbol list 321570af302Sopenharmony_ciLIB_FILE_NAME_LIST = [] #library file symbol list 322570af302Sopenharmony_ciCURRENT_FILE_TYPE = 0 #current file type 323570af302Sopenharmony_ciget_args() 324570af302Sopenharmony_ciget_head_strs() 325570af302Sopenharmony_ciget_lib_strs() 326570af302Sopenharmony_ciget_compare_result() 327