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 Text, List, Dict, AnyStr, DefaultDict 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 35def extension_handler(paragraph: Text): 36 return GnVariableParser.string_parser("output_extension", paragraph).strip('"') 37 38 39def hap_name_handler(paragraph: Text): 40 return GnVariableParser.string_parser("hap_name", paragraph).strip('"') 41 42 43def target_type_handler(paragraph: Text): 44 tt = GnVariableParser.string_parser("target_type", paragraph).strip('"') 45 return tt 46 47 48def mod_handler(paragraph: Text): 49 return GnVariableParser.string_parser("mode", paragraph).strip('"') 50 51 52def gn_lineno_collect(match_pattern: str, project_path: str) -> DefaultDict[str, List[int]]: 53 """ 54 在整个项目路径下搜索有特定target类型的BUILD.gn 55 :param match_pattern: 进行grep的pattern,支持扩展的正则 56 :param project_path: 项目路径(搜索路径) 57 :return: {gn_file: [line_no_1, line_no_2, ..]} 58 """ 59 black_list = _config.get("black_list") 60 tbl = [x for x in black_list if os.sep in x] 61 62 def handler(content: Text) -> List[str]: 63 t = list(filter(lambda y: len(y) > 0, list( 64 map(lambda x: x.strip(), content.split("\n"))))) 65 for item in tbl: 66 p = os.path.join(project_path, item) 67 t = list(filter(lambda x: p not in x, t)) 68 return t 69 70 grep_list = BasicTool.grep_ern(match_pattern, path=project_path, 71 include="BUILD.gn", exclude=tuple(black_list), post_handler=handler) 72 gn_line_dict: DefaultDict[str, List[int]] = defaultdict(list) 73 for gl in grep_list: 74 gn_file, line_no, _ = gl.split(":") 75 gn_line_dict[gn_file].append(line_no) 76 return gn_line_dict 77 78 79class TargetNameParser: 80 @classmethod 81 def single_parser(cls, paragraph: Text) -> str: 82 """ 83 查找类似shared_library("xxx")这种括号内只有一个参数的target的名称 84 :param paragraph: 要解析的段落 85 :return: target名称,如果是变量,不会对其进行解析 86 """ 87 return BasicTool.re_group_1(paragraph, r"\w+\((.*)\)") 88 89 @classmethod 90 def second_parser(cls, paragraph: Text) -> str: 91 """ 92 查找类似target("shared_library","xxx")这种的target名称(括号内第二个参数) 93 :param paragraph: 要解析的段落 94 :return: target名称,如果是变量,不会的其进行解析 95 """ 96 return BasicTool.re_group_1(paragraph, r"\w+\(.*?, *(.*?)\)") 97 98 99 100class BasePostHandler(ABC): 101 def __call__(self, unit: Dict[str, AnyStr]) -> str: 102 return self.run(unit) 103 104 @abstractmethod 105 def run(self, unit: Dict[str, AnyStr]) -> str: 106 ... 107 108 109def add_prefix(content: str, prefix: str) -> str: 110 if content and (not content.startswith(prefix)): 111 return prefix+content 112 return content 113 114 115def add_postfix(content: str, postfix: str) -> str: 116 if content and (not content.endswith(postfix)): 117 return content+postfix 118 return content 119 120 121class DefaultPostHandler(BasePostHandler): 122 def run(self, unit: Dict[str, AnyStr]): 123 if "extension" in unit.keys() and (not unit["output_name"].endswith(unit["extension"])): 124 out = unit["output_name"].rstrip( 125 ".")+"."+unit["extension"].lstrip(".") 126 return out 127 return unit["output_name"] 128 129 130class UnittestPostHandler(BasePostHandler): 131 def run(self, unit: Dict[str, AnyStr]): 132 if "output_extension" in unit.keys() and (not unit["output_name"].endswith(unit["output_extension"])): 133 out = unit["output_name"].rstrip( 134 ".")+"."+unit["output_extension"].lstrip(".") 135 return out 136 return unit["output_name"] 137 138 139class HapPackPostHandler(BasePostHandler): 140 def run(self, unit: Dict[str, AnyStr]): 141 hap_name = unit.get("hap_name") 142 mode = unit.get("mode") 143 return hap_name + "." + mode 144 145 146class HAPPostHandler(BasePostHandler): 147 """ 148 for ohos_hap 149 """ 150 151 def run(self, unit: Dict[str, AnyStr]): 152 extension = _config.get("default_extension").get("app") 153 gn_hap_name = unit.get("hap_name") 154 if gn_hap_name: 155 return add_postfix(gn_hap_name, extension) 156 return unit["output_name"]+extension 157 158 159class SOPostHandler(BasePostHandler): 160 """ 161 for shared_library 162 """ 163 164 def run(self, unit: Dict[str, AnyStr]): 165 output_name = unit["output_name"] 166 prefix = _config.get("default_prefix").get("shared_library") 167 if unit.get("extension"): 168 extension = unit.get("extension") 169 else: 170 extension = _config.get("default_extension").get("shared_library") 171 if not extension.startswith('.'): 172 extension = '.'+extension 173 output_name = add_postfix(output_name, extension) 174 return add_prefix(output_name, prefix) 175 176 177class APostHandler(BasePostHandler): 178 """ 179 for static library 180 """ 181 182 def run(self, unit: Dict[str, AnyStr]): 183 output_name = unit["output_name"] 184 prefix = _config.get("default_prefix").get("static_library") 185 extension: str = _config.get("default_extension").get("static_library") 186 if not extension.startswith('.'): 187 extension = '.'+extension 188 output_name = add_postfix(output_name, extension) 189 return add_prefix(output_name, prefix) 190 191 192class LiteLibPostHandler(BasePostHandler): 193 """ 194 for lite_library 195 """ 196 197 def run(self, unit: Dict[str, AnyStr]): 198 tp = unit["real_target_type"] 199 output_name = unit["output_name"] 200 if tp == "static_library": 201 prefix = _config.get("default_prefix").get("static_library") 202 extension = _config.get("default_extension").get("static_library") 203 elif tp == "shared_library": 204 prefix = _config.get("default_prefix").get("shared_library") 205 extension = _config.get("default_extension").get("shared_library") 206 else: 207 prefix = str() 208 extension = str() 209 if extension and (not extension.startswith('.')): 210 extension = '.'+extension 211 output_name = add_postfix(output_name, extension) 212 return add_prefix(output_name, prefix) 213 214 215class LiteComponentPostHandler(BasePostHandler): 216 """ 217 for lite_component 218 """ 219 220 def run(self, unit: Dict[str, AnyStr]): 221 tp = unit["real_target_type"] 222 output_name = unit["output_name"] 223 extension = unit.get("output_extension") 224 if tp == "shared_library": 225 prefix = _config.get("default_prefix").get("shared_library") 226 extension = _config.get("default_extension").get("shared_library") 227 else: 228 if tp != "executable": 229 unit["description"] = "virtual node" 230 prefix = str() 231 extension = str() 232 if extension and (not extension.startswith('.')): 233 extension = '.'+extension 234 output_name = add_postfix(output_name, extension) 235 return add_prefix(output_name, prefix) 236 237 238class TargetPostHandler(BasePostHandler): 239 """ 240 for target(a,b){} 241 """ 242 243 def run(self, unit: Dict[str, AnyStr]): 244 ... 245 246 247def lite_lib_s2m_post_handler(unit: Dict, result_dict: Dict) -> None: 248 rt = unit.get("real_target_type") 249 new_unit = copy.deepcopy(unit) 250 if rt == "shared_library": 251 new_unit["real_target_type"] = "static_library" 252 k = LiteLibPostHandler()(new_unit) 253 new_unit["description"] = "may not exist" 254 result_dict["lite_library"][k] = new_unit 255 elif rt == "static_library": 256 new_unit["real_target_type"] = "shared_library" 257 k = LiteLibPostHandler()(new_unit) 258 new_unit["description"] = "may not exist" 259 result_dict["lite_library"][k] = new_unit 260 else: 261 new_unit["real_target_type"] = "shared_library" 262 k = LiteLibPostHandler()(new_unit) 263 new_unit["description"] = "may not exist" 264 result_dict["lite_library"][k] = new_unit 265 266 new_new_unit = copy.deepcopy(unit) 267 new_new_unit["real_target_type"] = "static_library" 268 k = LiteLibPostHandler()(new_new_unit) 269 new_new_unit["description"] = "may not exist" 270 result_dict["lite_library"][k] = new_new_unit 271 272 273def target_s2m_post_handler(unit: Dict, result_dict: Dict) -> None: 274 unit["description"] = "may not exist" 275 tmp_a = copy.deepcopy(unit) 276 tmp_a["real_target_type"] = "static_library" 277 k = LiteLibPostHandler()(tmp_a) 278 result_dict["target"][k] = tmp_a 279 280 tmp_s = copy.deepcopy(unit) 281 tmp_s["real_target_type"] = "shared_library" 282 k = LiteLibPostHandler()(tmp_s) 283 result_dict["target"][k] = tmp_s