• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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