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