1#!/usr/bin/env python3 2 3# 4# Copyright (C) 2018 The Android Open Source Project 5# 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 19"""This script scans all Android.bp in an android source tree and check the 20correctness of dependencies.""" 21 22from __future__ import print_function 23 24import argparse 25import itertools 26import sys 27 28import vndk 29 30 31def _check_module_deps(all_libs, llndk_libs, module): 32 """Check the dependencies of a module.""" 33 34 bad_deps = set() 35 shared_deps, static_deps, header_deps = module.get_dependencies() 36 37 # Check vendor module dependencies requirements. 38 for dep_name in itertools.chain(shared_deps, static_deps, header_deps): 39 if dep_name in llndk_libs: 40 continue 41 dep_module = all_libs[dep_name] 42 if dep_module.is_vendor(): 43 continue 44 if dep_module.is_vendor_available(): 45 continue 46 if dep_module.is_vndk(): 47 # dep_module is a VNDK-Private module. 48 if not module.is_vendor(): 49 # VNDK-Core may link to VNDK-Private. 50 continue 51 bad_deps.add(dep_name) 52 53 # Check VNDK dependencies requirements. 54 if module.is_vndk() and not module.is_vendor(): 55 is_vndk_sp = module.is_vndk_sp() 56 for dep_name in shared_deps: 57 if dep_name in llndk_libs: 58 continue 59 dep_module = all_libs[dep_name] 60 if not dep_module.is_vndk(): 61 # VNDK must be self-contained. 62 bad_deps.add(dep_name) 63 break 64 if is_vndk_sp and not dep_module.is_vndk_sp(): 65 # VNDK-SP must be self-contained. 66 bad_deps.add(dep_name) 67 break 68 69 return bad_deps 70 71 72def _check_modules_deps(module_dicts): 73 """Check the dependencies of modules.""" 74 75 all_libs = module_dicts.all_libs 76 llndk_libs = module_dicts.llndk_libs 77 78 # Check the dependencies of modules 79 all_bad_deps = [] 80 for name, module in all_libs.items(): 81 if not module.has_vendor_variant() and not module.is_vendor(): 82 continue 83 84 bad_deps = _check_module_deps(all_libs, llndk_libs, module) 85 86 if bad_deps: 87 all_bad_deps.append((name, sorted(bad_deps))) 88 89 return sorted(all_bad_deps) 90 91 92def _parse_args(): 93 """Parse command line options.""" 94 parser = argparse.ArgumentParser() 95 parser.add_argument('root_bp', 96 help='path to Android.bp in ANDROID_BUILD_TOP') 97 parser.add_argument('--namespace', action='append', default=[''], 98 help='extra module namespaces') 99 return parser.parse_args() 100 101 102def main(): 103 """Main function.""" 104 105 args = _parse_args() 106 107 module_dicts = vndk.ModuleClassifier.create_from_root_bp( 108 args.root_bp, args.namespace) 109 110 all_bad_deps = _check_modules_deps(module_dicts) 111 for name, bad_deps in all_bad_deps: 112 print('ERROR: {!r} must not depend on {}'.format(name, bad_deps), 113 file=sys.stderr) 114 115 if all_bad_deps: 116 # Note: Exit with 2 so that it is easier to distinguish bad 117 # dependencies from unexpected Python exceptions. 118 sys.exit(2) 119 120 121if __name__ == '__main__': 122 main() 123