#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Copyright (c) 2022 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This file is for get the mapping relationship of subsystem_name/component_name # and their directory. The code is from Yude Chen. import logging import copy import os import logging from abc import ABC, abstractmethod from collections import defaultdict from typing import Text, List, Dict, AnyStr, DefaultDict from pprint import pprint import preprocess from pkgs.gn_common_tool import GnVariableParser from pkgs.simple_yaml_tool import SimpleYamlTool from pkgs.basic_tool import BasicTool _config = SimpleYamlTool.read_yaml("config.yaml") def extension_handler(paragraph: Text): return GnVariableParser.string_parser("output_extension", paragraph).strip('"') def hap_name_handler(paragraph: Text): return GnVariableParser.string_parser("hap_name", paragraph).strip('"') def target_type_handler(paragraph: Text): tt = GnVariableParser.string_parser("target_type", paragraph).strip('"') return tt def mod_handler(paragraph: Text): return GnVariableParser.string_parser("mode", paragraph).strip('"') def gn_lineno_collect(match_pattern: str, project_path: str) -> DefaultDict[str, List[int]]: """ 在整个项目路径下搜索有特定target类型的BUILD.gn :param match_pattern: 进行grep的pattern,支持扩展的正则 :param project_path: 项目路径(搜索路径) :return: {gn_file: [line_no_1, line_no_2, ..]} """ black_list = _config.get("black_list") tbl = [x for x in black_list if os.sep in x] def handler(content: Text) -> List[str]: t = list(filter(lambda y: len(y) > 0, list( map(lambda x: x.strip(), content.split("\n"))))) for item in tbl: p = os.path.join(project_path, item) t = list(filter(lambda x: p not in x, t)) return t grep_list = BasicTool.grep_ern(match_pattern, path=project_path, include="BUILD.gn", exclude=tuple(black_list), post_handler=handler) gn_line_dict: DefaultDict[str, List[int]] = defaultdict(list) for gl in grep_list: gn_file, line_no, _ = gl.split(":") gn_line_dict[gn_file].append(line_no) return gn_line_dict class TargetNameParser: @classmethod def single_parser(cls, paragraph: Text) -> str: """ 查找类似shared_library("xxx")这种括号内只有一个参数的target的名称 :param paragraph: 要解析的段落 :return: target名称,如果是变量,不会对其进行解析 """ return BasicTool.re_group_1(paragraph, r"\w+\((.*)\)") @classmethod def second_parser(cls, paragraph: Text) -> str: """ 查找类似target("shared_library","xxx")这种的target名称(括号内第二个参数) :param paragraph: 要解析的段落 :return: target名称,如果是变量,不会的其进行解析 """ return BasicTool.re_group_1(paragraph, r"\w+\(.*?, *(.*?)\)") class BasePostHandler(ABC): def __call__(self, unit: Dict[str, AnyStr]) -> str: return self.run(unit) @abstractmethod def run(self, unit: Dict[str, AnyStr]) -> str: ... def add_prefix(content: str, prefix: str) -> str: if content and (not content.startswith(prefix)): return prefix+content return content def add_postfix(content: str, postfix: str) -> str: if content and (not content.endswith(postfix)): return content+postfix return content class DefaultPostHandler(BasePostHandler): def run(self, unit: Dict[str, AnyStr]): if "extension" in unit.keys() and (not unit["output_name"].endswith(unit["extension"])): out = unit["output_name"].rstrip( ".")+"."+unit["extension"].lstrip(".") return out return unit["output_name"] class UnittestPostHandler(BasePostHandler): def run(self, unit: Dict[str, AnyStr]): if "output_extension" in unit.keys() and (not unit["output_name"].endswith(unit["output_extension"])): out = unit["output_name"].rstrip( ".")+"."+unit["output_extension"].lstrip(".") return out return unit["output_name"] class HapPackPostHandler(BasePostHandler): def run(self, unit: Dict[str, AnyStr]): hap_name = unit.get("hap_name") mode = unit.get("mode") return hap_name + "." + mode class HAPPostHandler(BasePostHandler): """ for ohos_hap """ def run(self, unit: Dict[str, AnyStr]): extension = _config.get("default_extension").get("app") gn_hap_name = unit.get("hap_name") if gn_hap_name: return add_postfix(gn_hap_name, extension) return unit["output_name"]+extension class SOPostHandler(BasePostHandler): """ for shared_library """ def run(self, unit: Dict[str, AnyStr]): output_name = unit["output_name"] prefix = _config.get("default_prefix").get("shared_library") if unit.get("extension"): extension = unit.get("extension") else: extension = _config.get("default_extension").get("shared_library") if not extension.startswith('.'): extension = '.'+extension output_name = add_postfix(output_name, extension) return add_prefix(output_name, prefix) class APostHandler(BasePostHandler): """ for static library """ def run(self, unit: Dict[str, AnyStr]): output_name = unit["output_name"] prefix = _config.get("default_prefix").get("static_library") extension: str = _config.get("default_extension").get("static_library") if not extension.startswith('.'): extension = '.'+extension output_name = add_postfix(output_name, extension) return add_prefix(output_name, prefix) class LiteLibPostHandler(BasePostHandler): """ for lite_library """ def run(self, unit: Dict[str, AnyStr]): tp = unit["real_target_type"] output_name = unit["output_name"] if tp == "static_library": prefix = _config.get("default_prefix").get("static_library") extension = _config.get("default_extension").get("static_library") elif tp == "shared_library": prefix = _config.get("default_prefix").get("shared_library") extension = _config.get("default_extension").get("shared_library") else: prefix = str() extension = str() if extension and (not extension.startswith('.')): extension = '.'+extension output_name = add_postfix(output_name, extension) return add_prefix(output_name, prefix) class LiteComponentPostHandler(BasePostHandler): """ for lite_component """ def run(self, unit: Dict[str, AnyStr]): tp = unit["real_target_type"] output_name = unit["output_name"] extension = unit.get("output_extension") if tp == "shared_library": prefix = _config.get("default_prefix").get("shared_library") extension = _config.get("default_extension").get("shared_library") else: if tp != "executable": unit["description"] = "virtual node" prefix = str() extension = str() if extension and (not extension.startswith('.')): extension = '.'+extension output_name = add_postfix(output_name, extension) return add_prefix(output_name, prefix) class TargetPostHandler(BasePostHandler): """ for target(a,b){} """ def run(self, unit: Dict[str, AnyStr]): ... def lite_lib_s2m_post_handler(unit: Dict, result_dict: Dict) -> None: rt = unit.get("real_target_type") new_unit = copy.deepcopy(unit) if rt == "shared_library": new_unit["real_target_type"] = "static_library" k = LiteLibPostHandler()(new_unit) new_unit["description"] = "may not exist" result_dict["lite_library"][k] = new_unit elif rt == "static_library": new_unit["real_target_type"] = "shared_library" k = LiteLibPostHandler()(new_unit) new_unit["description"] = "may not exist" result_dict["lite_library"][k] = new_unit else: new_unit["real_target_type"] = "shared_library" k = LiteLibPostHandler()(new_unit) new_unit["description"] = "may not exist" result_dict["lite_library"][k] = new_unit new_new_unit = copy.deepcopy(unit) new_new_unit["real_target_type"] = "static_library" k = LiteLibPostHandler()(new_new_unit) new_new_unit["description"] = "may not exist" result_dict["lite_library"][k] = new_new_unit def target_s2m_post_handler(unit: Dict, result_dict: Dict) -> None: unit["description"] = "may not exist" tmp_a = copy.deepcopy(unit) tmp_a["real_target_type"] = "static_library" k = LiteLibPostHandler()(tmp_a) result_dict["target"][k] = tmp_a tmp_s = copy.deepcopy(unit) tmp_s["real_target_type"] = "shared_library" k = LiteLibPostHandler()(tmp_s) result_dict["target"][k] = tmp_s