1#!/usr/bin/env python 2#coding=utf-8 3 4# 5# Copyright (c) 2022 Huawei Device Co., Ltd. 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19import os 20import json 21 22from .base_rule import BaseRule 23 24class ChipsetSDKRule(BaseRule): 25 RULE_NAME = "ChipsetSDK" 26 27 def __init__(self, mgr, args): 28 super().__init__(mgr, args) 29 self.__out_path = mgr.get_product_out_path() 30 self.__white_lists = self.load_chipsetsdk_json("chipsetsdk_info.json") 31 32 def get_white_lists(self): 33 return self.__white_lists 34 35 def get_out_path(self): 36 return self.__out_path 37 38 def load_chipsetsdk_json(self, name): 39 rules_dir = [] 40 rules_dir.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../rules")) 41 if self._args and self._args.rules: 42 self.log("****add more ChipsetSDK info in:{}****".format(self._args.rules)) 43 rules_dir = rules_dir + self._args.rules 44 45 chipsetsdk_rules_path = self.get_out_path().replace("out", "out/products_ext") 46 if os.path.exists(chipsetsdk_rules_path): 47 self.log("****add more ChipsetSDK info in dir:{}****".format(chipsetsdk_rules_path)) 48 rules_dir.append(chipsetsdk_rules_path) 49 else: 50 self.warn("****add chipsetsdk_rules_path path not exist: {}****".format(chipsetsdk_rules_path)) 51 res = [] 52 for d in rules_dir: 53 rules_file = os.path.join(d, self.__class__.RULE_NAME, name) 54 if os.path.isfile(rules_file): 55 res = self.__parser_rules_file(rules_file, res) 56 else: 57 self.warn("****rules path not exist: {}****".format(rules_file)) 58 59 return res 60 61 def __parser_rules_file(self, rules_file, res): 62 try: 63 self.log("****Parsing rules file in {}****".format(rules_file)) 64 with open(rules_file, "r") as f: 65 contents = f.read() 66 if not contents: 67 self.log("****rules file {} is null****".format(rules_file)) 68 return res 69 json_data = json.loads(contents) 70 for so in json_data: 71 so_file_name = so.get("so_file_name") 72 if so_file_name and so_file_name not in res: 73 res.append(so_file_name) 74 except(FileNotFoundError, IOError, UnicodeDecodeError) as file_open_or_decode_err: 75 self.error(file_open_or_decode_err) 76 77 return res 78 79 def __is_chipsetsdk_tagged(self, mod): 80 if not "innerapi_tags" in mod: 81 return False 82 if "chipsetsdk" in mod["innerapi_tags"]: 83 return True 84 return False 85 86 def __is_chipsetsdk_indirect(self, mod): 87 if not "innerapi_tags" in mod: 88 return False 89 if "chipsetsdk_indirect" in mod["innerapi_tags"]: 90 return True 91 return False 92 93 def __write_innerkits_header_files(self): 94 inner_kits_info = os.path.join(self.get_mgr().get_product_out_path(), 95 "build_configs/parts_info/inner_kits_info.json") 96 with open(inner_kits_info, "r") as f: 97 info = json.load(f) 98 99 headers = [] 100 for sdk in self.__chipsetsdks: 101 path = sdk["labelPath"][:sdk["labelPath"].find(":")] 102 target_name = sdk["labelPath"][sdk["labelPath"].find(":") + 1:] 103 item = {"name": sdk["componentName"] + ":" + target_name, "so_file_name": 104 sdk["name"], "path": sdk["labelPath"], "headers": []} 105 if sdk["componentName"] not in info: 106 headers.append(item) 107 continue 108 109 for name, innerapi in info[sdk["componentName"]].items(): 110 if innerapi["label"] != sdk["labelPath"]: 111 continue 112 gotHeaders = True 113 base = innerapi["header_base"] 114 for f in innerapi["header_files"]: 115 item["headers"].append(os.path.join(base, f)) 116 headers.append(item) 117 118 try: 119 with open(os.path.join(self.get_mgr().get_product_images_path(), "chipsetsdk_info.json"), "w") as f: 120 json.dump(headers, f, indent = 4) 121 except: 122 pass 123 124 return headers 125 126 def __check_chipsetsdk_indirect(self): 127 passed = True 128 for mod in self.__chipsetsdks: 129 for dep in mod["deps"]: 130 callee = dep["callee"] 131 132 # Chipset SDK is OK 133 if callee["name"] in self.get_white_lists(): 134 continue 135 136 # chipsetsdk_indirect module is OK 137 if self.__is_chipsetsdk_indirect(callee) or callee["name"] in self.__indirects: 138 continue 139 140 # Not correct 141 passed = False 142 self.error('Chipset SDK module %s should not depends on non Chipset SDK module \ 143 %s in %s with "chipsetsdk_indirect"' % (mod["name"], callee["name"], callee["labelPath"])) 144 145 return passed 146 147 def __check_depends_on_chipsetsdk(self): 148 lists = self.get_white_lists() 149 150 passed = True 151 152 self.__chipsetsdks = [] 153 self.__modules_with_chipsetsdk_tag = [] 154 self.__modules_with_chipsetsdk_indirect_tag = [] 155 156 # Check if any napi modules has dependedBy 157 for mod in self.get_mgr().get_all(): 158 # Collect all modules with chipsetsdk tag 159 if self.__is_chipsetsdk_tagged(mod): 160 self.__modules_with_chipsetsdk_tag.append(mod) 161 162 # Collect all modules with chipsetsdk_indirect tag 163 if self.__is_chipsetsdk_indirect(mod): 164 self.__modules_with_chipsetsdk_indirect_tag.append(mod) 165 166 # Check chipset modules only 167 if mod["path"].startswith("system"): 168 continue 169 170 # Check chipset modules depends 171 for dep in mod["deps"]: 172 callee = dep["callee"] 173 174 # If callee is chipset module, it is OK 175 if not callee["path"].startswith("system"): 176 continue 177 178 # Add to list 179 if callee not in self.__chipsetsdks: 180 if "hdiType" not in callee or callee["hdiType"] != "hdi_proxy": 181 self.__chipsetsdks.append(callee) 182 183 # If callee is in Chipset SDK white list module, it is OK 184 if callee["name"] in lists: 185 continue 186 187 # If callee is asan library, it is OK 188 if callee["name"].endswith(".asan.so"): 189 continue 190 191 # If callee is hdi proxy module, it is OK 192 if "hdiType" in callee and callee["hdiType"] == "hdi_proxy": 193 continue 194 195 # Not allowed 196 passed = False 197 self.error("chipset module %s depends on non Chipset SDK module %s in %s" 198 % (mod["name"], callee["name"], mod["labelPath"])) 199 200 return passed 201 202 203 def __check_if_tagged_correctly(self): 204 passed = True 205 for mod in self.__chipsetsdks: 206 if not self.__is_chipsetsdk_tagged(mod): 207 self.warn('Chipset SDK module %s has no innerapi_tags with "chipsetsdk", add it in %s' 208 % (mod["name"], mod["labelPath"])) 209 210 for mod in self.__modules_with_chipsetsdk_tag: 211 if mod["name"] not in self.get_white_lists(): 212 passed = False 213 self.error('non chipsetsdk module %s with innerapi_tags="chipsetsdk", %s' 214 % (mod["name"], mod["labelPath"])) 215 216 for mod in self.__modules_with_chipsetsdk_indirect_tag: 217 if mod["name"] not in self.__indirects and mod["name"] not in self.get_white_lists(): 218 self.warn('non chipsetsdk_indirect module %s with innerapi_tags="chipsetsdk_indirect", %s' 219 % (mod["name"], mod["labelPath"])) 220 221 return passed 222 223 def __load_chipsetsdk_indirects(self): 224 self.__indirects = self.load_chipsetsdk_json("chipsetsdk_indirect.json") 225 226 def check(self): 227 self.__load_chipsetsdk_indirects() 228 229 # Check if all chipset modules depends on chipsetsdk modules only 230 passed = self.__check_depends_on_chipsetsdk() 231 if not passed: 232 return passed 233 234 # Check if all chipsetsdk module depends on chipsetsdk or chipsetsdk_indirect modules only 235 passed = self.__check_chipsetsdk_indirect() 236 if not passed: 237 return passed 238 239 # Check if all ChipsetSDK modules are correctly tagged by innerapi_tags 240 passed = self.__check_if_tagged_correctly() 241 if not passed: 242 return passed 243 244 self.__write_innerkits_header_files() 245 246 return True 247