1import os 2import json 3 4 5class GnCommonTool: 6 """ 7 处理BUILD.gn文件的通用方法 8 """ 9 10 @classmethod 11 def is_gn_variable(cls, target: str, has_quote: bool = True): 12 """ 13 判断target是否是gn中的变量: 14 规则:如果是有引号的模式,则没有引号均认为是变量,有引号的情况下,如有是"$xxx"的模式,则认为xxx是变量;如果是无引号模式,则只要$开头就认为是变量 15 b = "xxx" 16 c = b 17 c = "${b}" 18 "$p" 19 """ 20 target = target.strip() 21 if not has_quote: 22 return target.startswith("$") 23 if target.startswith('"') and target.endswith('"'): 24 target = target.strip('"') 25 if target.startswith("${") and target.endswith("}"): 26 return True 27 elif target.startswith("$"): 28 return True 29 return False 30 else: 31 return True 32 33 # 给__find_variables_in_gn用的,减少io 34 __var_val_mem_dict = dict() 35 36 @classmethod 37 def find_variables_in_gn(cls, var_name_tuple: tuple, path: str, stop_tail: str = "home") -> tuple: 38 """ 39 同时查找多个gn变量的值 40 var_name_tuple:变量名的tuple,变量名应是未经过处理后的,如: 41 xxx 42 "${xxx}" 43 "$xxx" 44 """ 45 46 if os.path.isfile(path): 47 path = os.path.split(path)[0] 48 var_val_dict = dict() 49 not_found_count = len(var_name_tuple) 50 for var in var_name_tuple: 51 val = GnCommonTool.__var_val_mem_dict.get(var) 52 if val is not None: 53 not_found_count -= 1 54 var_val_dict[var] = val 55 while not path.endswith(stop_tail) and not_found_count != 0: 56 for v in var_name_tuple: 57 cmd = r"grep -Ern '^( *){} *= *\".*?\"' --include=*.gn* {}| grep -Ev '\$' | head -n 1 | grep -E '\".*\"' -wo".format( 58 v.strip('"').lstrip("${").rstrip('}'), path) 59 output = os.popen(cmd).read().strip().strip('"') 60 if len(output) != 0: 61 not_found_count -= 1 62 var_val_dict[v] = output 63 GnCommonTool.__var_val_mem_dict[v] = output 64 path = os.path.split(path)[0] 65 return tuple(var_val_dict.values()) 66 67 @classmethod 68 def __find_part_subsystem_from_bundle(cls, gnpath: str, stop_tail: str = "home") -> tuple: 69 """ 70 根据BUILD.gn的全路径,一层层往上面查找bundle.json文件, 71 并从bundle.json中查找part_name和subsystem 72 """ 73 filename = "bundle.json" 74 part_name = None 75 subsystem_name = None 76 if stop_tail not in gnpath: 77 return part_name, subsystem_name 78 if os.path.isfile(gnpath): 79 gnpath = os.path.split(gnpath)[0] 80 while not gnpath.endswith(stop_tail): 81 bundle_path = os.path.join(gnpath, filename) 82 if not os.path.isfile(bundle_path): # 如果该文件不在该目录下 83 gnpath = os.path.split(gnpath)[0] 84 continue 85 with open(bundle_path, 'r', encoding='utf-8') as f: 86 content = json.load(f) 87 try: 88 part_name = content["component"]["name"] 89 subsystem_name = content["component"]["subsystem"] 90 except KeyError: 91 ... 92 finally: 93 break 94 part_name = None if (part_name is not None and len( 95 part_name) == 0) else part_name 96 subsystem_name = None if (subsystem_name is not None and len( 97 subsystem_name) == 0) else subsystem_name 98 return part_name, subsystem_name 99 100 @classmethod 101 def find_part_subsystem(cls, gn_file: str, project_path: str) -> tuple: 102 """ 103 查找gn_file对应的part_name和subsystem 104 如果在gn中找不到,就到bundle.json中去找 105 """ 106 part_name = None 107 subsystem_name = None 108 part_var_flag = False # 标识这个变量从gn中取出的原始值是不是变量 109 subsystem_var_flag = False 110 var_list = list() 111 part_name_pattern = r"part_name *=\s*\S*" 112 subsystem_pattern = r"subsystem_name *=\s*\S*" 113 meta_grep_pattern = "grep -E '{}' {} | head -n 1" 114 part_cmd = meta_grep_pattern.format(part_name_pattern, gn_file) 115 subsystem_cmd = meta_grep_pattern.format(subsystem_pattern, gn_file) 116 part = os.popen(part_cmd).read().strip() 117 if len(part) != 0: 118 part = part.split('=')[-1].strip() 119 if GnCommonTool.is_gn_variable(part): 120 part_var_flag = True 121 var_list.append(part) 122 else: 123 part_name = part.strip('"') 124 if len(part_name) == 0: 125 part_name = None 126 subsystem = os.popen(subsystem_cmd).read().strip() 127 if len(subsystem) != 0: # 这里是只是看有没有grep到关键字 128 subsystem = subsystem.split('=')[-1].strip() 129 if GnCommonTool.is_gn_variable(subsystem): 130 subsystem_var_flag = True 131 var_list.append(subsystem) 132 else: 133 subsystem_name = subsystem.strip('"') 134 if len(subsystem_name) == 0: 135 subsystem_name = None 136 if part_var_flag and subsystem_var_flag: 137 part_name, subsystem_name = GnCommonTool.find_variables_in_gn( 138 tuple(var_list), gn_file, project_path) 139 elif part_var_flag: 140 t = GnCommonTool.find_variables_in_gn( 141 tuple(var_list), gn_file, project_path)[0] 142 part_name = t if t is not None and len(t) != 0 else part_name 143 elif subsystem_var_flag: 144 t = GnCommonTool.find_variables_in_gn( 145 tuple(var_list), gn_file, project_path)[0] 146 subsystem_name = t if t is not None and len( 147 t) != 0 else subsystem_name 148 if part_name is not None and subsystem_name is not None: 149 return part_name, subsystem_name 150 # 如果有一个没有找到,就要一层层去找bundle.json文件 151 t_part_name, t_subsystem_name = cls.__find_part_subsystem_from_bundle( 152 gn_file, stop_tail=project_path) 153 if t_part_name is not None: 154 part_name = t_part_name 155 if t_subsystem_name is not None: 156 subsystem_name = t_subsystem_name 157 return part_name, subsystem_name 158