You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
3.6 KiB

#!/usr/bin/env python3
#
# Copyright (C) 2018 The Android Open Source Project
#
# 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.
#
"""This script scans all Android.bp in an android source tree and check the
correctness of dependencies."""
from __future__ import print_function
import argparse
import itertools
import sys
import vndk
def _check_module_deps(all_libs, llndk_libs, module):
"""Check the dependencies of a module."""
bad_deps = set()
shared_deps, static_deps, header_deps = module.get_dependencies()
# Check vendor module dependencies requirements.
for dep_name in itertools.chain(shared_deps, static_deps, header_deps):
if dep_name in llndk_libs:
continue
dep_module = all_libs[dep_name]
if dep_module.is_vendor():
continue
if dep_module.is_vendor_available():
continue
if dep_module.is_vndk():
# dep_module is a VNDK-Private module.
if not module.is_vendor():
# VNDK-Core may link to VNDK-Private.
continue
bad_deps.add(dep_name)
# Check VNDK dependencies requirements.
if module.is_vndk() and not module.is_vendor():
is_vndk_sp = module.is_vndk_sp()
for dep_name in shared_deps:
if dep_name in llndk_libs:
continue
dep_module = all_libs[dep_name]
if not dep_module.is_vndk():
# VNDK must be self-contained.
bad_deps.add(dep_name)
break
if is_vndk_sp and not dep_module.is_vndk_sp():
# VNDK-SP must be self-contained.
bad_deps.add(dep_name)
break
return bad_deps
def _check_modules_deps(module_dicts):
"""Check the dependencies of modules."""
all_libs = module_dicts.all_libs
llndk_libs = module_dicts.llndk_libs
# Check the dependencies of modules
all_bad_deps = []
for name, module in all_libs.items():
if not module.has_vendor_variant() and not module.is_vendor():
continue
bad_deps = _check_module_deps(all_libs, llndk_libs, module)
if bad_deps:
all_bad_deps.append((name, sorted(bad_deps)))
return sorted(all_bad_deps)
def _parse_args():
"""Parse command line options."""
parser = argparse.ArgumentParser()
parser.add_argument('root_bp',
help='path to Android.bp in ANDROID_BUILD_TOP')
parser.add_argument('--namespace', action='append', default=[''],
help='extra module namespaces')
return parser.parse_args()
def main():
"""Main function."""
args = _parse_args()
module_dicts = vndk.ModuleClassifier.create_from_root_bp(
args.root_bp, args.namespace)
all_bad_deps = _check_modules_deps(module_dicts)
for name, bad_deps in all_bad_deps:
print('ERROR: {!r} must not depend on {}'.format(name, bad_deps),
file=sys.stderr)
if all_bad_deps:
# Note: Exit with 2 so that it is easier to distinguish bad
# dependencies from unexpected Python exceptions.
sys.exit(2)
if __name__ == '__main__':
main()