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