• 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        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