From 61de7c016ba6e1b97c719b3b7e85bdaf34126f03 Mon Sep 17 00:00:00 2001 From: liangxinyan Date: Thu, 17 Apr 2025 14:40:09 +0800 Subject: [PATCH 1/4] IssueNo: https://gitee.com/openharmony/developtools_integration_verification/issues/IC1W0B Signed-off-by: liangxinyan --- .../chipsetsdk_sp_indirect_info.json | 0 .../ChipsetsdkSP/chipsetsdk_sp_info.json | 0 tools/deps_guard/rules/LLndk/llndk_info.json | 0 .../passthrough_indirect_info.json | 0 .../rules/Passthrough/passthrough_info.json | 0 tools/deps_guard/rules_checker/__init__.py | 4 +- .../rules_checker/base_innerapi_rule.py | 80 ++++++ tools/deps_guard/rules_checker/base_rule.py | 27 ++ tools/deps_guard/rules_checker/chipsetsdk.py | 18 ++ .../deps_guard/rules_checker/chipsetsdk_sp.py | 265 ++++++++++++++++++ tools/deps_guard/rules_checker/llndk.py | 119 ++++++++ tools/deps_guard/rules_checker/passthrough.py | 265 ++++++++++++++++++ 12 files changed, 777 insertions(+), 1 deletion(-) create mode 100755 tools/deps_guard/rules/ChipsetsdkSP/chipsetsdk_sp_indirect_info.json create mode 100755 tools/deps_guard/rules/ChipsetsdkSP/chipsetsdk_sp_info.json create mode 100755 tools/deps_guard/rules/LLndk/llndk_info.json create mode 100755 tools/deps_guard/rules/Passthrough/passthrough_indirect_info.json create mode 100755 tools/deps_guard/rules/Passthrough/passthrough_info.json create mode 100644 tools/deps_guard/rules_checker/base_innerapi_rule.py create mode 100644 tools/deps_guard/rules_checker/chipsetsdk_sp.py create mode 100644 tools/deps_guard/rules_checker/llndk.py create mode 100644 tools/deps_guard/rules_checker/passthrough.py diff --git a/tools/deps_guard/rules/ChipsetsdkSP/chipsetsdk_sp_indirect_info.json b/tools/deps_guard/rules/ChipsetsdkSP/chipsetsdk_sp_indirect_info.json new file mode 100755 index 0000000..e69de29 diff --git a/tools/deps_guard/rules/ChipsetsdkSP/chipsetsdk_sp_info.json b/tools/deps_guard/rules/ChipsetsdkSP/chipsetsdk_sp_info.json new file mode 100755 index 0000000..e69de29 diff --git a/tools/deps_guard/rules/LLndk/llndk_info.json b/tools/deps_guard/rules/LLndk/llndk_info.json new file mode 100755 index 0000000..e69de29 diff --git a/tools/deps_guard/rules/Passthrough/passthrough_indirect_info.json b/tools/deps_guard/rules/Passthrough/passthrough_indirect_info.json new file mode 100755 index 0000000..e69de29 diff --git a/tools/deps_guard/rules/Passthrough/passthrough_info.json b/tools/deps_guard/rules/Passthrough/passthrough_info.json new file mode 100755 index 0000000..e69de29 diff --git a/tools/deps_guard/rules_checker/__init__.py b/tools/deps_guard/rules_checker/__init__.py index 0e59df4..1133b7d 100755 --- a/tools/deps_guard/rules_checker/__init__.py +++ b/tools/deps_guard/rules_checker/__init__.py @@ -20,6 +20,7 @@ from .napi_rule import NapiRule from .sa_rule import SaRule from .hdi_rule import HdiRule from .chipsetsdk import ChipsetSDKRule +from .base_innerapi_rule import BaseInnerapiRule def check_all_rules(mgr, args): @@ -27,7 +28,8 @@ def check_all_rules(mgr, args): NapiRule, SaRule, HdiRule, - ChipsetSDKRule + ChipsetSDKRule, + BaseInnerapiRule ] passed = True diff --git a/tools/deps_guard/rules_checker/base_innerapi_rule.py b/tools/deps_guard/rules_checker/base_innerapi_rule.py new file mode 100644 index 0000000..63c8399 --- /dev/null +++ b/tools/deps_guard/rules_checker/base_innerapi_rule.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +#coding=utf-8 + +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import os +import json + +from .base_rule import BaseRule + + +class BaseInnerapiRule(BaseRule): + RULE_NAME = "BaseInnerApi" + + def __init__(self, mgr, args): + super().__init__(mgr, args) + self.__ignored_tags = ["platformsdk", "sasdk", "platformsdk_indirect", "ndk"] + self.__valid_system_tags = ["llndk", "chipsetsdk", "chipsetsdk_indirect", "chipsetsdk_sp" + "chipsetsdk_sp_indirect"] + self.__ignored_tags + self.__valid_vendor_tags = ["chipsetsdk", "chipsetsdk_indirect", "chipsetsdk_sp", "llndk", "passthrough", + "chipsetsdk_sp_indirect", "passthrough_indirect"] + self.__ignored_tags + + def is_only(self, ignored_tags, mod): + innerapi_tags = mod["innerapi_tags"] + # check whether each innerapi_tag of mod in ignored tags + if innerapi_tags: + for innerapi_tag in innerapi_tags: + if innerapi_tag not in ignored_tags: + return False + # check mod belongs to system module or vendor module + if mod["path"].startswith("system"): + return "system" + else: + return "vendor" + + def check(self): + passed = True + + for mod in self.get_mgr().get_all(): + innerapi_tags = mod["innerapi_tags"] + # mod is system only scene + if self.is_only(self.__ignored_tags, mod) == "system" and \ + all(item in self.__valid_system_tags for item in innerapi_tags): + for dep in mod["deps"]: + callee = dep["callee"] + callee_innerapi_tags = callee["innerapi_tags"] + if self.is_only(self.__ignored_tags, callee) == "system" or \ + all(item in self.__valid_system_tags for item in callee_innerapi_tags): + continue + else: + self.error("system only module %s depends on wrong module as %s in %s" + %(mod["name"], callee["name"], mod["labelPath"])) + passed = False + # mod is vendor only scene + elif self.is_only(self.__ignored_tags, mod) == "vendor" and \ + all(item in self.__valid_vendor_tags for item in innerapi_tags): + for dep in mod["deps"]: + callee = dep["callee"] + callee_innerapi_tags = callee["innerapi_tags"] + if self.is_only(self.__ignored_tags, callee) == "vendor" or \ + all(item in self.__valid_vendor_tags for item in callee_innerapi_tags): + continue + else: + self.error("vendor only module %s depends on wrong module as %s in %s" + %(mod["name"], callee["name"], mod["labelPath"])) + passed = False + return passed \ No newline at end of file diff --git a/tools/deps_guard/rules_checker/base_rule.py b/tools/deps_guard/rules_checker/base_rule.py index 5fbe93f..7b96d0a 100755 --- a/tools/deps_guard/rules_checker/base_rule.py +++ b/tools/deps_guard/rules_checker/base_rule.py @@ -68,3 +68,30 @@ class BaseRule(object): def check(self): # Default pass return True + + def check_if_deps_correctly(self, check_modules, valid_mod_tags, valid_dep_tags): + # check if mod and callee have wrong innerapi tags + passed = True + for mod in check_modules: + innerapi_tags = mod["innerapi_tags"] + if innerapi_tags and all(item in valid_mod_tags for item in innerapi_tags): + for dep in mod["deps"]: + callee = dep["callee"] + + dep_innerapi_tags = callee["innerapi_tags"] + if dep_innerapi_tags and all(item in valid_dep_tags for item in dep_innerapi_tags): + continue + elif not dep_innerapi_tags: + continue + + passed = False + wrong_tags = [item for item in dep_innerapi_tags if item not in valid_dep_tags] + self.error("module %s with %s contains wrong dep innerapi_tags [%s] in innerapi_tags [%s]" + %(callee["name"], callee["labelPath"], ",".join(wrong_tags), ",".join(dep_innerapi_tags))) + else: + wrong_tags = [item for item in innerapi_tags if item not in valid_mod_tags] + self.error("module %s with %s contains wrong mod innerapi_tags [%s] in innerapi_tags [%s]" + %(mod["name"], mod["labelPath"], ",".join(wrong_tags), ",".join(innerapi_tags))) + return False + + return passed \ No newline at end of file diff --git a/tools/deps_guard/rules_checker/chipsetsdk.py b/tools/deps_guard/rules_checker/chipsetsdk.py index cc4feef..e2a1f89 100755 --- a/tools/deps_guard/rules_checker/chipsetsdk.py +++ b/tools/deps_guard/rules_checker/chipsetsdk.py @@ -29,6 +29,9 @@ class ChipsetSDKRule(BaseRule): super().__init__(mgr, args) self.__out_path = mgr.get_product_out_path() self.__white_lists = self.load_chipsetsdk_json("chipsetsdk_info.json") + self.__ignored_tags = ["platformsdk", "sasdk", "platformsdk_indirect", "ndk"] + self.__valid_mod_tags = ["llndk", "chipsetsdk", "chipsetsdk_indirect", "chipsetsdk_sp", + "chipsetsdk_sp_indirect"] + self.__ignored_tags def get_white_lists(self): return self.__white_lists @@ -64,16 +67,31 @@ class ChipsetSDKRule(BaseRule): # Check if all chipset modules depends on chipsetsdk modules only passed = self.__check_depends_on_chipsetsdk() + self.log(f"****check_depends_on_chipsetsdk result:{passed}****") if not passed: return passed # Check if all chipsetsdk module depends on chipsetsdk or chipsetsdk_indirect modules only passed = self.__check_chipsetsdk_indirect() + self.log(f"****check_chipsetsdk_indirect result:{passed}****") if not passed: return passed # Check if all ChipsetSDK modules are correctly tagged by innerapi_tags passed = self.__check_if_tagged_correctly() + self.log(f"****check_if_tagged_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_chipsetsdk_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_chipsetsdk_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly indirect result:{passed}****") if not passed: return passed diff --git a/tools/deps_guard/rules_checker/chipsetsdk_sp.py b/tools/deps_guard/rules_checker/chipsetsdk_sp.py new file mode 100644 index 0000000..61288cd --- /dev/null +++ b/tools/deps_guard/rules_checker/chipsetsdk_sp.py @@ -0,0 +1,265 @@ +#!/usr/bin/env python +#coding=utf-8 + +# +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import os +import json + +from .base_rule import BaseRule + + +class ChipsetsdkSPRule(BaseRule): + RULE_NAME = "ChipsetsdkSP" + + def __init__(self, mgr, args): + super().__init__(mgr, args) + self.__out_path = mgr.get_product_out_path() + self.__white_lists = self.load_chipsetsdk_json("chipsetsdk_sp_info.json") + self.__ignored_tags = ["platformsdk", "sasdk", "platformsdk_indirect", "ndk"] + self.__valid_mod_tags = ["llndk", "chipsetsdk_sp", "chipsetsdk_sp_indirect"] + self.__ignored_tags + + def get_white_lists(self): + return self.__white_lists + + def get_out_path(self): + return self.__out_path + + def load_chipsetsdk_json(self, name): + rules_dir = [] + rules_dir.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../rules")) + if self._args and self._args.rules: + self.log("****add more chipsetsdk_sp info in:{}****".format(self._args.rules)) + rules_dir = rules_dir + self._args.rules + + chipsetsdk_rules_path = self.get_out_path().replace("out", "out/products_ext") + if os.path.exists(chipsetsdk_rules_path): + self.log("****add more chipsetsdk_sp info in dir:{}****".format(chipsetsdk_rules_path)) + rules_dir.append(chipsetsdk_rules_path) + else: + self.warn("****add chipsetsdk_sp_rules_path path not exist: {}****".format(chipsetsdk_rules_path)) + res = [] + for d in rules_dir: + rules_file = os.path.join(d, self.__class__.RULE_NAME, name) + if os.path.isfile(rules_file): + res = self.__parser_rules_file(rules_file, res) + else: + self.warn("****rules path not exist: {}****".format(rules_file)) + + return res + + def check(self): + self.__load_chipsetsdk_indirects() + + # Check if all chipset modules depends on chipsetsdk_sp modules only + passed = self.__check_depends_on_chipsetsdk() + self.log(f"****check_depends_on_chipsetsdk result:{passed}****") + if not passed: + return passed + + # Check if all chipsetsdk_sp module depends on chipsetsdk_sp or chipsetsdk_sp_indirect modules only + passed = self.__check_chipsetsdk_sp_indirect() + self.log(f"****check_chipsetsdk_sp_indirect result:{passed}****") + if not passed: + return passed + + # Check if all chipsetsdk_sp modules are correctly tagged by innerapi_tags + passed = self.__check_if_tagged_correctly() + self.log(f"****check_if_tagged_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_chipsetsdk_sp_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_chipsetsdk_sp_indirect_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly indirect result:{passed}****") + if not passed: + return passed + + self.__write_innerkits_header_files() + + return True + + def __parser_rules_file(self, rules_file, res): + try: + self.log("****Parsing rules file in {}****".format(rules_file)) + with open(rules_file, "r") as f: + contents = f.read() + if not contents: + self.log("****rules file {} is null****".format(rules_file)) + return res + json_data = json.loads(contents) + for so in json_data: + so_file_name = so.get("so_file_name") + if so_file_name and so_file_name not in res: + res.append(so_file_name) + except (FileNotFoundError, IOError, UnicodeDecodeError) as file_open_or_decode_err: + self.error(file_open_or_decode_err) + + return res + + def __is_chipsetsdk_sp_tagged(self, mod): + if not "innerapi_tags" in mod: + return False + if "chipsetsdk_sp" in mod["innerapi_tags"]: + return True + return False + + def __is_chipsetsdk_sp_indirect(self, mod): + if not "innerapi_tags" in mod: + return False + if "chipsetsdk_sp_indirect" in mod["innerapi_tags"]: + return True + return False + + def __write_innerkits_header_files(self): + inner_kits_info = os.path.join(self.get_mgr().get_product_out_path(), + "build_configs/parts_info/inner_kits_info.json") + with open(inner_kits_info, "r") as f: + info = json.load(f) + + headers = [] + for sdk in self.__chipsetsdk_sps: + path = sdk["labelPath"][:sdk["labelPath"].find(":")] + target_name = sdk["labelPath"][sdk["labelPath"].find(":") + 1:] + item = {"name": sdk["componentName"] + ":" + target_name, "so_file_name": + sdk["name"], "path": sdk["labelPath"], "headers": []} + if sdk["componentName"] not in info: + headers.append(item) + continue + + for name, innerapi in info[sdk["componentName"]].items(): + if innerapi["label"] != sdk["labelPath"]: + continue + got_headers = True + base = innerapi["header_base"] + for f in innerapi["header_files"]: + item["headers"].append(os.path.join(base, f)) + headers.append(item) + + try: + with os.fdopen(os.open(os.path.join(self.get_mgr().get_product_images_path(), + "chipsetsdk_sp_info.json"), + os.O_WRONLY | os.O_CREAT, 0o644), "w") as f: + json.dump(headers, f, indent=4) + except: + pass + + return headers + + def __check_chipsetsdk_sp_indirect(self): + passed = True + for mod in self.__chipsetsdk_sps: + for dep in mod["deps"]: + callee = dep["callee"] + + # ChipsetSDK SP is OK + if callee["name"] in self.get_white_lists(): + continue + + # chipsetsdk_sp_indirect module is OK + if self.__is_chipsetsdk_sp_indirect(callee) or callee["name"] in self.__indirects: + continue + + # Not correct + passed = False + self.error('ChipsetSPSDK module %s should not depends on non ChipsetSPSDK module \ + %s in %s with "chipsetsdk_indirect"' % (mod["name"], callee["name"], callee["labelPath"])) + + return passed + + def __check_depends_on_chipsetsdk(self): + lists = self.get_white_lists() + + passed = True + + self.__chipsetsdk_sps = [] + self.__modules_with_chipsetsdk_sp_tag = [] + self.__modules_with_chipsetsdk_sp_indirect_tag = [] + + # Check if any napi modules has dependedBy + for mod in self.get_mgr().get_all(): + # Collect all modules with chipsetsdk_sp tag + if self.__is_chipsetsdk_sp_tagged(mod): + self.__modules_with_chipsetsdk_sp_tag.append(mod) + + # Collect all modules with chipsetsdk_sp_indirect tag + if self.__is_chipsetsdk_sp_indirect(mod): + self.__modules_with_chipsetsdk_sp_indirect_tag.append(mod) + + # Check chipset modules only + if mod["path"].startswith("system"): + continue + + # Check chipset modules depends + for dep in mod["deps"]: + callee = dep["callee"] + + # If callee is chipset module, it is OK + if not callee["path"].startswith("system"): + continue + + # Add to list + if callee not in self.__chipsetsdk_sps: + if "hdiType" not in callee or callee["hdiType"] != "hdi_proxy": + self.__chipsetsdk_sps.append(callee) + + # If callee is in ChipsetSDKSP white list module, it is OK + if callee["name"] in lists: + continue + + # If callee is asan library, it is OK + if callee["name"].endswith(".asan.so"): + continue + + # If callee is hdi proxy module, it is OK + if "hdiType" in callee and callee["hdiType"] == "hdi_proxy": + continue + + # Not allowed + passed = False + self.error("chipset module %s depends on non ChipsetSDKSP module %s in %s" + % (mod["name"], callee["name"], mod["labelPath"])) + + return passed + + def __check_if_tagged_correctly(self): + passed = True + for mod in self.__chipsetsdk_sps: + if not self.__is_chipsetsdk_sp_tagged(mod): + self.warn('ChipsetSDK module %s has no innerapi_tags with "chipsetsdk_sp", add it in %s' + % (mod["name"], mod["labelPath"])) + + for mod in self.__modules_with_chipsetsdk_sp_tag: + if mod["name"] not in self.get_white_lists(): + passed = False + self.error('non chipsetsdk_sp module %s with innerapi_tags="chipsetsdk_sp", %s' + % (mod["name"], mod["labelPath"])) + + for mod in self.__modules_with_chipsetsdk_sp_indirect_tag: + if mod["name"] not in self.__indirects and mod["name"] not in self.get_white_lists(): + self.warn('non chipsetsdk_sp_indirect module %s with innerapi_tags="chipsetsdk_sp_indirect", %s' + % (mod["name"], mod["labelPath"])) + + return passed + + def __load_chipsetsdk_indirects(self): + self.__indirects = self.load_chipsetsdk_json("chipsetsdk_sp_indirect.json") diff --git a/tools/deps_guard/rules_checker/llndk.py b/tools/deps_guard/rules_checker/llndk.py new file mode 100644 index 0000000..991f985 --- /dev/null +++ b/tools/deps_guard/rules_checker/llndk.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +#coding=utf-8 + +# +# Copyright (c) 2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import os +import json + +from .base_rule import BaseRule + + +class ChipsetsdkSPRule(BaseRule): + RULE_NAME = "LLndk" + + def __init__(self, mgr, args): + super().__init__(mgr, args) + self.__out_path = mgr.get_product_out_path() + self.__white_lists = self.load_llndk_json("llndk_info.json") + self.__ignored_tags = ["platformsdk", "sasdk", "platformsdk_indirect", "ndk"] + self.__valid_mod_tags = ["llndk"] + self.__ignored_tags + + def get_white_lists(self): + return self.__white_lists + + def get_out_path(self): + return self.__out_path + + def load_llndk_json(self, name): + rules_dir = [] + rules_dir.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../rules")) + if self._args and self._args.rules: + self.log("****add more llndk info in:{}****".format(self._args.rules)) + rules_dir = rules_dir + self._args.rules + + llndk_rules_path = self.get_out_path().replace("out", "out/products_ext") + if os.path.exists(llndk_rules_path): + self.log("****add more llndk info in dir:{}****".format(llndk_rules_path)) + rules_dir.append(llndk_rules_path) + else: + self.warn("****add llndk_rules_path path not exist: {}****".format(llndk_rules_path)) + res = [] + for d in rules_dir: + rules_file = os.path.join(d, self.__class__.RULE_NAME, name) + if os.path.isfile(rules_file): + res = self.__parser_rules_file(rules_file, res) + else: + self.warn("****rules path not exist: {}****".format(rules_file)) + + return res + + def check(self): + self.__modules_with_llndk_tag = [] + + for mod in self.get_mgr().get_all(): + if self.__is_llndk_tagged(mod): + self.__modules_with_llndk_tag.append(mod) + + # Check if all llndk modules are correctly tagged by innerapi_tags + passed = self.__check_if_tagged_correctly() + self.log(f"****check_if_tagged_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_llndk_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly result:{passed}****") + if not passed: + return passed + + return True + + def __parser_rules_file(self, rules_file, res): + try: + self.log("****Parsing rules file in {}****".format(rules_file)) + with open(rules_file, "r") as f: + contents = f.read() + if not contents: + self.log("****rules file {} is null****".format(rules_file)) + return res + json_data = json.loads(contents) + for so in json_data: + so_file_name = so.get("so_file_name") + if so_file_name and so_file_name not in res: + res.append(so_file_name) + except (FileNotFoundError, IOError, UnicodeDecodeError) as file_open_or_decode_err: + self.error(file_open_or_decode_err) + + return res + + def __is_llndk_tagged(self, mod): + if not "innerapi_tags" in mod: + return False + if "llndk" in mod["innerapi_tags"]: + return True + return False + + def __check_if_tagged_correctly(self): + passed = True + + for mod in self.__modules_with_chipsetsdk_sp_tag: + if mod["name"] not in self.get_white_lists(): + passed = False + self.error('non chipsetsdk_sp module %s with innerapi_tags="chipsetsdk_sp", %s' + % (mod["name"], mod["labelPath"])) + + return passed diff --git a/tools/deps_guard/rules_checker/passthrough.py b/tools/deps_guard/rules_checker/passthrough.py new file mode 100644 index 0000000..66b030b --- /dev/null +++ b/tools/deps_guard/rules_checker/passthrough.py @@ -0,0 +1,265 @@ +#!/usr/bin/env python +#coding=utf-8 + +# +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import os +import json + +from .base_rule import BaseRule + + +class PassthroughRule(BaseRule): + RULE_NAME = "Passthrough" + + def __init__(self, mgr, args): + super().__init__(mgr, args) + self.__out_path = mgr.get_product_out_path() + self.__white_lists = self.load_passthrough_json("passthrough_info.json") + self.__ignored_tags = ["platformsdk", "sasdk", "platformsdk_indirect", "ndk"] + self.__valid_mod_tags = ["llndk", "chipsetsdk_sp", "passthrough", "passthrough_indirect"] + self.__ignored_tags + + def get_white_lists(self): + return self.__white_lists + + def get_out_path(self): + return self.__out_path + + def load_passthrough_json(self, name): + rules_dir = [] + rules_dir.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../rules")) + if self._args and self._args.rules: + self.log("****add more ChipsetSDK info in:{}****".format(self._args.rules)) + rules_dir = rules_dir + self._args.rules + + chipsetsdk_rules_path = self.get_out_path().replace("out", "out/products_ext") + if os.path.exists(chipsetsdk_rules_path): + self.log("****add more ChipsetSDK info in dir:{}****".format(chipsetsdk_rules_path)) + rules_dir.append(chipsetsdk_rules_path) + else: + self.warn("****add chipsetsdk_rules_path path not exist: {}****".format(chipsetsdk_rules_path)) + res = [] + for d in rules_dir: + rules_file = os.path.join(d, self.__class__.RULE_NAME, name) + if os.path.isfile(rules_file): + res = self.__parser_rules_file(rules_file, res) + else: + self.warn("****rules path not exist: {}****".format(rules_file)) + + return res + + def check(self): + self.__load_passthrough_indirects() + + # Check if all chipset modules depends on chipsetsdk modules only + passed = self.__check_depends_on_passthrough() + self.log(f"****check_depends_on_chipsetsdk result:{passed}****") + if not passed: + return passed + + # Check if all chipsetsdk module depends on chipsetsdk or chipsetsdk_indirect modules only + passed = self.__check_passthrough_indirect() + self.log(f"****check_chipsetsdk_indirect result:{passed}****") + if not passed: + return passed + + # Check if all ChipsetSDK modules are correctly tagged by innerapi_tags + passed = self.__check_if_passthrough_tagged_correctly() + self.log(f"****check_if_tagged_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_passthrough_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly result:{passed}****") + if not passed: + return passed + + passed = self.check_if_deps_correctly( + self.__modules_with_passthrough_tag, self.__valid_mod_tags, self.__valid_mod_tags) + self.log(f"****check_if_deps_correctly indirect result:{passed}****") + if not passed: + return passed + + self.__write_innerkits_header_files() + + return True + + def __parser_rules_file(self, rules_file, res): + try: + self.log("****Parsing rules file in {}****".format(rules_file)) + with open(rules_file, "r") as f: + contents = f.read() + if not contents: + self.log("****rules file {} is null****".format(rules_file)) + return res + json_data = json.loads(contents) + for so in json_data: + so_file_name = so.get("so_file_name") + if so_file_name and so_file_name not in res: + res.append(so_file_name) + except (FileNotFoundError, IOError, UnicodeDecodeError) as file_open_or_decode_err: + self.error(file_open_or_decode_err) + + return res + + def __is_passthrough_tagged(self, mod): + if not "innerapi_tags" in mod: + return False + if "passthrough" in mod["innerapi_tags"]: + return True + return False + + def __is_passthrough_indirect(self, mod): + if not "innerapi_tags" in mod: + return False + if "passthrough_indirect" in mod["innerapi_tags"]: + return True + return False + + def __write_innerkits_header_files(self): + inner_kits_info = os.path.join(self.get_mgr().get_product_out_path(), + "build_configs/parts_info/inner_kits_info.json") + with open(inner_kits_info, "r") as f: + info = json.load(f) + + headers = [] + for sdk in self.__passthroughs: + path = sdk["labelPath"][:sdk["labelPath"].find(":")] + target_name = sdk["labelPath"][sdk["labelPath"].find(":") + 1:] + item = {"name": sdk["componentName"] + ":" + target_name, "so_file_name": + sdk["name"], "path": sdk["labelPath"], "headers": []} + if sdk["componentName"] not in info: + headers.append(item) + continue + + for name, innerapi in info[sdk["componentName"]].items(): + if innerapi["label"] != sdk["labelPath"]: + continue + got_headers = True + base = innerapi["header_base"] + for f in innerapi["header_files"]: + item["headers"].append(os.path.join(base, f)) + headers.append(item) + + try: + with os.fdopen(os.open(os.path.join(self.get_mgr().get_product_images_path(), + "passthrough_info.json"), + os.O_WRONLY | os.O_CREAT, 0o644), "w") as f: + json.dump(headers, f, indent=4) + except: + pass + + return headers + + def __check_passthrough_indirect(self): + passed = True + for mod in self.__passthroughs: + for dep in mod["deps"]: + callee = dep["callee"] + + # Passthrough is OK + if callee["name"] in self.get_white_lists(): + continue + + # Passthrough_indirect module is OK + if self.__is_passthrough_indirect(callee) or callee["name"] in self.__indirects: + continue + + # Not correct + passed = False + self.error('Passthrough module %s should not depends on non Passthrough module \ + %s in %s with "chipsetsdk_indirect"' % (mod["name"], callee["name"], callee["labelPath"])) + + return passed + + def __check_depends_on_passthrough(self): + lists = self.get_white_lists() + + passed = True + + self.__passthroughs = [] + self.__modules_with_passthrough_tag = [] + self.__modules_with_passthrough_indirect_tag = [] + + # Check if any napi modules has dependedBy + for mod in self.get_mgr().get_all(): + # Collect all modules with passthrough tag + if self.__is_passthrough_tagged(mod): + self.__modules_with_passthrough_tag.append(mod) + + # Collect all modules with passthrough_indirect tag + if self.__is_passthrough_indirect(mod): + self.__modules_with_passthrough_indirect_tag.append(mod) + + # Check chipset modules only + if mod["path"].startswith("system"): + continue + + # Check chipset modules depends + for dep in mod["deps"]: + callee = dep["callee"] + + # If callee is chipset module, it is OK + if not callee["path"].startswith("system"): + continue + + # Add to list + if callee not in self.__passthroughs: + if "hdiType" not in callee or callee["hdiType"] != "hdi_proxy": + self.__passthroughs.append(callee) + + # If callee is in passthroughwhite list module, it is OK + if callee["name"] in lists: + continue + + # If callee is asan library, it is OK + if callee["name"].endswith(".asan.so"): + continue + + # If callee is hdi proxy module, it is OK + if "hdiType" in callee and callee["hdiType"] == "hdi_proxy": + continue + + # Not allowed + passed = False + self.error("chipset module %s depends on non Chipset SDK module %s in %s" + % (mod["name"], callee["name"], mod["labelPath"])) + + return passed + + def __check_if_passthrough_tagged_correctly(self): + passed = True + for mod in self.__passthroughs: + if not self.__is_passthrough_tagged(mod): + self.warn('passthrough module %s has no innerapi_tags with "passthrough", add it in %s' + % (mod["name"], mod["labelPath"])) + + for mod in self.__modules_with_passthrough_tag: + if mod["name"] not in self.get_white_lists(): + passed = False + self.error('non passthrough %s with innerapi_tags="passthrough", %s' + % (mod["name"], mod["labelPath"])) + + for mod in self.__modules_with_passthrough_indirect_tag: + if mod["name"] not in self.__indirects and mod["name"] not in self.get_white_lists(): + self.warn('non passthrough_indirect module %s with innerapi_tags="passthrough_indirect", %s' + % (mod["name"], mod["labelPath"])) + + return passed + + def __load_passthrough_indirects(self): + self.__indirects = self.load_passthrough_json("passthrough_indirect.json") -- Gitee From ec70180b88de3858e674e2b5487a538345231298 Mon Sep 17 00:00:00 2001 From: liangxinyan123 Date: Tue, 29 Apr 2025 11:14:49 +0000 Subject: [PATCH 2/4] update tools/deps_guard/rules_checker/llndk.py. Signed-off-by: liangxinyan123 --- tools/deps_guard/rules_checker/llndk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/deps_guard/rules_checker/llndk.py b/tools/deps_guard/rules_checker/llndk.py index 991f985..6e2ad8b 100644 --- a/tools/deps_guard/rules_checker/llndk.py +++ b/tools/deps_guard/rules_checker/llndk.py @@ -2,7 +2,7 @@ #coding=utf-8 # -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -- Gitee From 9847256c14599cf8add6b1eeb8062759e05b0ba7 Mon Sep 17 00:00:00 2001 From: liangxinyan123 Date: Tue, 29 Apr 2025 11:18:22 +0000 Subject: [PATCH 3/4] update tools/deps_guard/rules_checker/chipsetsdk_sp.py. Signed-off-by: liangxinyan123 --- tools/deps_guard/rules_checker/chipsetsdk_sp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/deps_guard/rules_checker/chipsetsdk_sp.py b/tools/deps_guard/rules_checker/chipsetsdk_sp.py index 61288cd..8418004 100644 --- a/tools/deps_guard/rules_checker/chipsetsdk_sp.py +++ b/tools/deps_guard/rules_checker/chipsetsdk_sp.py @@ -2,7 +2,7 @@ #coding=utf-8 # -# Copyright (c) 2022 Huawei Device Co., Ltd. +# Copyright (c) 2025 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -- Gitee From 8338ac20dc5b5a3eabb4dc3f44fa658eab2d7a80 Mon Sep 17 00:00:00 2001 From: liangxinyan123 Date: Wed, 30 Apr 2025 00:50:01 +0000 Subject: [PATCH 4/4] update tools/deps_guard/rules_checker/llndk.py. Signed-off-by: liangxinyan123 --- tools/deps_guard/rules_checker/llndk.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/deps_guard/rules_checker/llndk.py b/tools/deps_guard/rules_checker/llndk.py index 6e2ad8b..07f4f27 100644 --- a/tools/deps_guard/rules_checker/llndk.py +++ b/tools/deps_guard/rules_checker/llndk.py @@ -22,7 +22,7 @@ import json from .base_rule import BaseRule -class ChipsetsdkSPRule(BaseRule): +class LLndkRule(BaseRule): RULE_NAME = "LLndk" def __init__(self, mgr, args): -- Gitee