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