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