1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# Copyright (c) 2022 Huawei Device Co., Ltd. 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16# This file is for get the mapping relationship of subsystem_name/component_name 17# and their directory. The code is from Yude Chen. 18 19import logging 20import copy 21import os 22import logging 23from abc import ABC, abstractmethod 24from collections import defaultdict 25from typing import * 26from pprint import pprint 27import preprocess 28from pkgs.gn_common_tool import GnVariableParser 29from pkgs.simple_yaml_tool import SimpleYamlTool 30from pkgs.basic_tool import BasicTool 31 32 33_config = SimpleYamlTool.read_yaml("config.yaml") 34""" 35===============info handlers=============== 36""" 37 38 39def extension_handler(paragraph: Text): 40 return GnVariableParser.string_parser("output_extension", paragraph).strip('"') 41 42 43def hap_name_handler(paragraph: Text): 44 return GnVariableParser.string_parser("hap_name", paragraph).strip('"') 45 46 47def target_type_handler(paragraph: Text): 48 tt = GnVariableParser.string_parser("target_type", paragraph).strip('"') 49 return tt 50 51 52def mod_handler(paragraph: Text): 53 return GnVariableParser.string_parser("mode", paragraph).strip('"') 54 55 56""" 57===============gn lineno collector=============== 58""" 59 60 61def gn_lineno_collect(match_pattern: str, project_path: str) -> DefaultDict[str, List[int]]: 62 """ 63 在整个项目路径下搜索有特定target类型的BUILD.gn 64 :param match_pattern: 进行grep的pattern,支持扩展的正则 65 :param project_path: 项目路径(搜索路径) 66 :return: {gn_file: [line_no_1, line_no_2, ..]} 67 """ 68 black_list = _config.get("black_list") 69 tbl = [x for x in black_list if os.sep in x] 70 71 def handler(content: Text) -> List[str]: 72 t = list(filter(lambda y: len(y) > 0, list( 73 map(lambda x: x.strip(), content.split("\n"))))) 74 for item in tbl: 75 p = os.path.join(project_path, item) 76 t = list(filter(lambda x: p not in x, t)) 77 return t 78 79 grep_list = BasicTool.grep_ern(match_pattern, path=project_path, 80 include="BUILD.gn", exclude=tuple(black_list), post_handler=handler) 81 gn_line_dict: DefaultDict[str, List[int]] = defaultdict(list) 82 for gl in grep_list: 83 gn_file, line_no, _ = gl.split(":") 84 gn_line_dict[gn_file].append(line_no) 85 return gn_line_dict 86 87 88""" 89===============target name parser=============== 90""" 91 92 93class TargetNameParser: 94 @classmethod 95 def single_parser(cls, paragraph: Text) -> str: 96 """ 97 查找类似shared_library("xxx")这种括号内只有一个参数的target的名称 98 :param paragraph: 要解析的段落 99 :return: target名称,如果是变量,不会对其进行解析 100 """ 101 return BasicTool.re_group_1(paragraph, r"\w+\((.*)\)") 102 103 @classmethod 104 def second_parser(cls, paragraph: Text) -> str: 105 """ 106 查找类似target("shared_library","xxx")这种的target名称(括号内第二个参数) 107 :param paragraph: 要解析的段落 108 :return: target名称,如果是变量,不会的其进行解析 109 """ 110 return BasicTool.re_group_1(paragraph, r"\w+\(.*?, *(.*?)\)") 111 112 113""" 114===============post handlers=============== 115""" 116 117 118class BasePostHandler(ABC): 119 @abstractmethod 120 def run(self, unit: Dict[str, AnyStr]) -> str: 121 ... 122 123 def __call__(self, unit: Dict[str, AnyStr]) -> str: 124 return self.run(unit) 125 126 127def add_prefix(content: str, prefix: str) -> str: 128 if content and (not content.startswith(prefix)): 129 return prefix+content 130 return content 131 132 133def add_postfix(content: str, postfix: str) -> str: 134 if content and (not content.endswith(postfix)): 135 return content+postfix 136 return content 137 138 139class DefaultPostHandler(BasePostHandler): 140 def run(self, unit: Dict[str, AnyStr]): 141 if "extension" in unit.keys() and (not unit["output_name"].endswith(unit["extension"])): 142 out = unit["output_name"].rstrip( 143 ".")+"."+unit["extension"].lstrip(".") 144 return out 145 return unit["output_name"] 146 147 148class UnittestPostHandler(BasePostHandler): 149 def run(self, unit: Dict[str, AnyStr]): 150 if "output_extension" in unit.keys() and (not unit["output_name"].endswith(unit["output_extension"])): 151 out = unit["output_name"].rstrip( 152 ".")+"."+unit["output_extension"].lstrip(".") 153 return out 154 return unit["output_name"] 155 156 157class HapPackPostHandler(BasePostHandler): 158 def run(self, unit: Dict[str, AnyStr]): 159 hap_name = unit.get("hap_name") 160 mode = unit.get("mode") 161 return hap_name + "." + mode 162 163 164class HAPPostHandler(BasePostHandler): 165 """ 166 for ohos_hap""" 167 168 def run(self, unit: Dict[str, AnyStr]): 169 extension = _config.get("default_extension").get("app") 170 gn_hap_name = unit.get("hap_name") 171 if gn_hap_name: 172 return add_postfix(gn_hap_name, extension) 173 return unit["output_name"]+extension 174 175 176class SOPostHandler(BasePostHandler): 177 """ 178 for shared_library""" 179 180 def run(self, unit: Dict[str, AnyStr]): 181 output_name = unit["output_name"] 182 prefix = _config.get("default_prefix").get("shared_library") 183 if unit.get("extension"): 184 extension = unit.get("extension") 185 else: 186 extension = _config.get("default_extension").get("shared_library") 187 if not extension.startswith('.'): 188 extension = '.'+extension 189 output_name = add_postfix(output_name, extension) 190 return add_prefix(output_name, prefix) 191 192 193class APostHandler(BasePostHandler): 194 """ 195 for static library""" 196 197 def run(self, unit: Dict[str, AnyStr]): 198 output_name = unit["output_name"] 199 prefix = _config.get("default_prefix").get("static_library") 200 extension: str = _config.get("default_extension").get("static_library") 201 if not extension.startswith('.'): 202 extension = '.'+extension 203 output_name = add_postfix(output_name, extension) 204 return add_prefix(output_name, prefix) 205 206 207class LiteLibPostHandler(BasePostHandler): 208 """ 209 for lite_library""" 210 211 def run(self, unit: Dict[str, AnyStr]): 212 tp = unit["real_target_type"] 213 output_name = unit["output_name"] 214 if tp == "static_library": 215 prefix = _config.get("default_prefix").get("static_library") 216 extension = _config.get("default_extension").get("static_library") 217 elif tp == "shared_library": 218 prefix = _config.get("default_prefix").get("shared_library") 219 extension = _config.get("default_extension").get("shared_library") 220 else: 221 prefix = str() 222 extension = str() 223 if extension and (not extension.startswith('.')): 224 extension = '.'+extension 225 output_name = add_postfix(output_name, extension) 226 return add_prefix(output_name, prefix) 227 228 229class LiteComponentPostHandler(BasePostHandler): 230 """ 231 for lite_component""" 232 233 def run(self, unit: Dict[str, AnyStr]): 234 tp = unit["real_target_type"] 235 output_name = unit["output_name"] 236 extension = unit.get("output_extension") 237 if tp == "shared_library": 238 prefix = _config.get("default_prefix").get("shared_library") 239 extension = _config.get("default_extension").get("shared_library") 240 else: 241 if tp != "executable": 242 unit["description"] = "virtual node" 243 prefix = str() 244 extension = str() 245 if extension and (not extension.startswith('.')): 246 extension = '.'+extension 247 output_name = add_postfix(output_name, extension) 248 return add_prefix(output_name, prefix) 249 250 251class TargetPostHandler(BasePostHandler): 252 """ 253 for target(a,b){}""" 254 255 def run(self, unit: Dict[str, AnyStr]): 256 ... 257 258 259def LiteLibS2MPostHandler(unit: Dict, result_dict: Dict) -> None: 260 rt = unit.get("real_target_type") 261 new_unit = copy.deepcopy(unit) 262 if rt == "shared_library": 263 new_unit["real_target_type"] = "static_library" 264 k = LiteLibPostHandler()(new_unit) 265 new_unit["description"] = "may not exist" 266 result_dict["lite_library"][k] = new_unit 267 elif rt == "static_library": 268 new_unit["real_target_type"] = "shared_library" 269 k = LiteLibPostHandler()(new_unit) 270 new_unit["description"] = "may not exist" 271 result_dict["lite_library"][k] = new_unit 272 else: 273 new_unit["real_target_type"] = "shared_library" 274 k = LiteLibPostHandler()(new_unit) 275 new_unit["description"] = "may not exist" 276 result_dict["lite_library"][k] = new_unit 277 278 new_new_unit = copy.deepcopy(unit) 279 new_new_unit["real_target_type"] = "static_library" 280 k = LiteLibPostHandler()(new_new_unit) 281 new_new_unit["description"] = "may not exist" 282 result_dict["lite_library"][k] = new_new_unit 283 284 285def TargetS2MPostHandler(unit: Dict, result_dict: Dict) -> None: 286 unit["description"] = "may not exist" 287 tmp_a = copy.deepcopy(unit) 288 tmp_a["real_target_type"] = "static_library" 289 k = LiteLibPostHandler()(tmp_a) 290 result_dict["target"][k] = tmp_a 291 292 tmp_s = copy.deepcopy(unit) 293 tmp_s["real_target_type"] = "shared_library" 294 k = LiteLibPostHandler()(tmp_s) 295 result_dict["target"][k] = tmp_s 296