#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2021 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 sys import argparse sys.path.append( os.path.dirname(os.path.dirname(os.path.dirname( os.path.abspath(__file__))))) from scripts.util.file_utils import read_json_file # noqa: E402 def check_third_party_deps(args, dep_part, parts_deps_info, _tips_info, third_deps_allow_list): """check whether the three-party dependency is in the part declaration""" if args.part_name == dep_part: return part_deps_info = parts_deps_info.get(args.part_name) if not part_deps_info: _warning_info = f"{_tips_info} {args.part_name}." elif not part_deps_info.get('third_party') or \ not dep_part in part_deps_info.get('third_party'): _warning_info = f"{_tips_info} {part_deps_info.get('build_config_file')}." else: _warning_info = "" if _warning_info != "": if args.target_path in third_deps_allow_list: print(f"[0/0] WARNING: {_warning_info}") else: raise Exception(_warning_info) return def load_part_info(depfiles:list): """load part path info from parts_info""" # load parts path info file parts_path_file = 'build_configs/parts_info/parts_path_info.json' parts_path_info = read_json_file(parts_path_file) if parts_path_info is None: raise Exception("read pre_build parts_path_info failed.") depfiles.append(parts_path_file) # load path to parts info file path_parts_file = 'build_configs/parts_info/path_to_parts.json' path_parts_info = read_json_file(path_parts_file) if path_parts_info is None: raise Exception("read pre_build path to parts failed.") depfiles.append(path_parts_file) return parts_path_info, path_parts_info def get_path_from_label(label): """get part path from target label, the format is //path:module""" return label.lstrip('//').split(':')[0] def get_path_from_module_list(cur_part_name, depfiles:list): parts_module_lists = [] parts_modules_file = "build_configs/parts_info/parts_modules_info.json" parts_modules_info = read_json_file(parts_modules_file) if parts_modules_info is None: raise Exception("read pre_build parts module info failed.") depfiles.append(parts_modules_file) for parts_module in parts_modules_info.get("parts"): if parts_module.get("part_name") == cur_part_name: parts_module_lists = parts_module["module_list"] break parts_path = [get_path_from_label(x) for x in parts_module_lists] return parts_path def get_part_pattern(cur_part_name, parts_path_info, path_parts_info, depfiles:list): """get all part path from part info""" part_pattern = [] part_path = parts_path_info.get(cur_part_name) if part_path is None: return part_pattern path_to_part = path_parts_info.get(part_path) if len(path_to_part) == 1: part_pattern.append(part_path) else: part_pattern.extend(get_path_from_module_list(cur_part_name, depfiles)) return part_pattern def get_dep_part(dep_path, third_part_info): """gets the part by the longest path match""" for part_info in third_part_info: path = part_info[0] part = part_info[1][0] if dep_path.find(path) != -1: return part return "" def check_part_deps(args, part_pattern, path_parts_info, compile_standard_allow_info, depfiles:list): deps_allow_list = compile_standard_allow_info.get("deps_added_external_part_module", []) third_deps_allow_list = compile_standard_allow_info.get("third_deps_bundle_not_add", []) parts_deps_file = 'build_configs/parts_info/parts_deps.json' parts_deps_info = read_json_file(parts_deps_file) if parts_deps_info is None: raise Exception("read pre_build parts_deps failed.") depfiles.append(parts_deps_file) # filter third_party part info, sort by longest path match third_party_info = [x for x in path_parts_info.items() if x[0].find('third_party') != -1] third_party_info.reverse() for dep in args.deps: dep_path = get_path_from_label(dep) if dep_path.find('third_party/rust/crates') != -1: continue if dep_path.find('third_party') != -1: dep_part = get_dep_part(dep_path, third_party_info) tips_info = "{} depend part {}, need set part deps {} info to".format( args.target_path, dep, dep_part) check_third_party_deps(args, dep_part, parts_deps_info, tips_info, third_deps_allow_list) continue match_flag = False for pattern in part_pattern: if dep_path.startswith(pattern): match_flag = True break if match_flag is False: message = "deps validation part_name: '{}', target: '{}', dep: '{}' failed!!!".format( args.part_name, args.target_path, dep) if args.target_path in deps_allow_list: print(f"[0/0] WARNING:{message}") else: raise Exception(message) def check(args): depfiles = [] # ignore test related parts test_allow_set = {'benchmark', 'performance', 'security', 'reliability'} if args.part_name.find('test') != -1 or args.part_name in test_allow_set: return depfiles compile_standard_allow_file = args.compile_standard_allow_file compile_standard_allow_info = read_json_file(compile_standard_allow_file) parts_path_info, path_parts_info = load_part_info(depfiles) part_pattern = get_part_pattern(args.part_name, parts_path_info, path_parts_info, depfiles) if not part_pattern: gn_allow_list = compile_standard_allow_info.get("gn_part_or_subsystem_error", []) message = "part_name: '{}' path is not exist, please check target: '{}'".format( args.part_name, args.target_path) if args.target_path in gn_allow_list: print(f"[0/0] {message}") return depfiles else: raise Exception(message) check_part_deps(args, part_pattern, path_parts_info,compile_standard_allow_info, depfiles) return depfiles def main(): parser = argparse.ArgumentParser() parser.add_argument('--deps', nargs='*', required=True) parser.add_argument('--part-name', required=True) parser.add_argument('--target-path', required=True) args = parser.parse_args() check(args) return 0 if __name__ == '__main__': sys.exit(main())