| #!/usr/bin/env python3 |
| # |
| # Copyright (C) 2021 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. |
| # |
| |
| import argparse |
| import glob |
| import logging |
| import os |
| |
| import utils |
| |
| LICENSE_KINDS_PREFIX = 'SPDX-license-identifier-' |
| LICENSE_KEYWORDS = { |
| 'Apache-2.0': ('Apache License', 'Version 2.0',), |
| 'BSD': ('BSD ',), |
| 'CC0-1.0': ('CC0 Public Domain Dedication license',), |
| 'FTL': ('FreeType Project LICENSE',), |
| 'ISC': ('Internet Systems Consortium',), |
| 'ISC': ('ISC license',), |
| 'MIT': (' MIT ',), |
| 'MPL-2.0': ('Mozilla Public License Version 2.0',), |
| 'MPL': ('Mozilla Public License',), |
| 'NCSA': ('University of Illinois', 'NCSA',), |
| 'OpenSSL': ('The OpenSSL Project',), |
| 'Zlib': ('zlib License',), |
| 'LGPL-3.0': ('LESSER GENERAL PUBLIC LICENSE', 'Version 3,',), |
| 'LGPL-2.1': ('LESSER GENERAL PUBLIC LICENSE', 'Version 2.1',), |
| 'LGPL-2.0': ('GNU LIBRARY GENERAL PUBLIC LICENSE', 'Version 2,',), |
| 'LGPL': ('LESSER GENERAL PUBLIC LICENSE',), |
| 'GPL-2.0': ('GNU GENERAL PUBLIC LICENSE', 'Version 2,',), |
| 'GPL': ('GNU GENERAL PUBLIC LICENSE',), |
| } |
| |
| LICENSE_INCLUDE = ['legacy_permissive', 'legacy_unencumbered'] |
| |
| class LicenseCollector(object): |
| """ Collect licenses from a VNDK snapshot directory |
| |
| This is to collect the license_kinds to be used in license modules. |
| |
| Initialize the LicenseCollector with a vndk snapshot directory. |
| After run() is called, 'license_kinds' will include the licenses found from |
| the snapshot directory. |
| """ |
| def __init__(self, install_dir): |
| self._install_dir = install_dir |
| self._paths_to_check = [os.path.join(install_dir, |
| utils.NOTICE_FILES_DIR_PATH),] |
| self._paths_to_check = self._paths_to_check + glob.glob(os.path.join(self._install_dir, '*/include')) |
| |
| self.license_kinds = set() |
| |
| def read_and_check_licenses(self, license_text, license_keywords): |
| """ Read the license keywords and check if all keywords are in the file. |
| |
| The found licenses will be added to license_kinds set. This function will |
| return True if any licenses are found, False otherwise. |
| """ |
| found = False |
| for lic, patterns in license_keywords.items(): |
| for pattern in patterns: |
| if pattern not in license_text: |
| break |
| else: |
| self.license_kinds.add(LICENSE_KINDS_PREFIX + lic) |
| found = True |
| return found |
| |
| def check_licenses(self, filepath): |
| """ Read a license text file and find the license_kinds. |
| """ |
| with open(filepath, 'rt', encoding='utf-8') as file_to_check: |
| try: |
| file_string = file_to_check.read() |
| self.read_and_check_licenses(file_string, LICENSE_KEYWORDS) |
| except UnicodeDecodeError: |
| # Read text files only. |
| return |
| |
| def run(self, module=''): |
| """ search licenses in vndk snapshots |
| |
| Args: |
| module: module name to find the license kind. |
| If empty, check all license files. |
| """ |
| if module == '': |
| for path in self._paths_to_check: |
| logging.info('Reading {}'.format(path)) |
| for (root, _, files) in os.walk(path): |
| for f in files: |
| self.check_licenses(os.path.join(root, f)) |
| self.license_kinds.update(LICENSE_INCLUDE) |
| else: |
| license_text_path = '{notice_dir}/{module}.txt'.format( |
| notice_dir=utils.NOTICE_FILES_DIR_NAME, |
| module=module) |
| logging.info('Reading {}'.format(license_text_path)) |
| self.check_licenses(os.path.join(self._install_dir, utils.COMMON_DIR_PATH, license_text_path)) |
| if not self.license_kinds: |
| # Add 'legacy_permissive' if no licenses are found for this file. |
| self.license_kinds.add('legacy_permissive') |
| |
| def get_args(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument( |
| 'vndk_version', |
| type=utils.vndk_version_int, |
| help='VNDK snapshot version to check, e.g. "{}".'.format( |
| utils.MINIMUM_VNDK_VERSION)) |
| parser.add_argument( |
| '-v', |
| '--verbose', |
| action='count', |
| default=0, |
| help='Increase output verbosity, e.g. "-v", "-vv".') |
| return parser.parse_args() |
| |
| def main(): |
| """ For the local testing purpose. |
| """ |
| ANDROID_BUILD_TOP = utils.get_android_build_top() |
| PREBUILTS_VNDK_DIR = utils.join_realpath(ANDROID_BUILD_TOP, |
| 'prebuilts/vndk') |
| args = get_args() |
| vndk_version = args.vndk_version |
| install_dir = os.path.join(PREBUILTS_VNDK_DIR, 'v{}'.format(vndk_version)) |
| utils.set_logging_config(args.verbose) |
| |
| license_collector = LicenseCollector(install_dir) |
| license_collector.run() |
| print(sorted(license_collector.license_kinds)) |
| |
| if __name__ == '__main__': |
| main() |