1*90c8c64dSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*90c8c64dSAndroid Build Coastguard Worker# 3*90c8c64dSAndroid Build Coastguard Worker# Copyright (C) 2021 The Android Open Source Project 4*90c8c64dSAndroid Build Coastguard Worker# 5*90c8c64dSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the 'License'); 6*90c8c64dSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*90c8c64dSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*90c8c64dSAndroid Build Coastguard Worker# 9*90c8c64dSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*90c8c64dSAndroid Build Coastguard Worker# 11*90c8c64dSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*90c8c64dSAndroid Build Coastguard Worker# distributed under the License is distributed on an 'AS IS' BASIS, 13*90c8c64dSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*90c8c64dSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*90c8c64dSAndroid Build Coastguard Worker# limitations under the License. 16*90c8c64dSAndroid Build Coastguard Worker# 17*90c8c64dSAndroid Build Coastguard Worker 18*90c8c64dSAndroid Build Coastguard Workerimport argparse 19*90c8c64dSAndroid Build Coastguard Workerimport glob 20*90c8c64dSAndroid Build Coastguard Workerimport logging 21*90c8c64dSAndroid Build Coastguard Workerimport os 22*90c8c64dSAndroid Build Coastguard Worker 23*90c8c64dSAndroid Build Coastguard Workerimport utils 24*90c8c64dSAndroid Build Coastguard Worker 25*90c8c64dSAndroid Build Coastguard WorkerLICENSE_KINDS_PREFIX = 'SPDX-license-identifier-' 26*90c8c64dSAndroid Build Coastguard WorkerLICENSE_KEYWORDS = { 27*90c8c64dSAndroid Build Coastguard Worker 'Apache-2.0': ('Apache License', 'Version 2.0',), 28*90c8c64dSAndroid Build Coastguard Worker 'BSD': ('BSD ',), 29*90c8c64dSAndroid Build Coastguard Worker 'CC0-1.0': ('CC0 Public Domain Dedication license',), 30*90c8c64dSAndroid Build Coastguard Worker 'FTL': ('FreeType Project LICENSE',), 31*90c8c64dSAndroid Build Coastguard Worker 'ISC': ('Internet Systems Consortium',), 32*90c8c64dSAndroid Build Coastguard Worker 'ISC': ('ISC license',), 33*90c8c64dSAndroid Build Coastguard Worker 'MIT': (' MIT ',), 34*90c8c64dSAndroid Build Coastguard Worker 'MPL-2.0': ('Mozilla Public License Version 2.0',), 35*90c8c64dSAndroid Build Coastguard Worker 'MPL': ('Mozilla Public License',), 36*90c8c64dSAndroid Build Coastguard Worker 'NCSA': ('University of Illinois', 'NCSA',), 37*90c8c64dSAndroid Build Coastguard Worker 'OpenSSL': ('The OpenSSL Project',), 38*90c8c64dSAndroid Build Coastguard Worker 'Zlib': ('zlib License',), 39*90c8c64dSAndroid Build Coastguard Worker 'LGPL-3.0': ('LESSER GENERAL PUBLIC LICENSE', 'Version 3,',), 40*90c8c64dSAndroid Build Coastguard Worker 'LGPL-2.1': ('LESSER GENERAL PUBLIC LICENSE', 'Version 2.1',), 41*90c8c64dSAndroid Build Coastguard Worker 'LGPL-2.0': ('GNU LIBRARY GENERAL PUBLIC LICENSE', 'Version 2,',), 42*90c8c64dSAndroid Build Coastguard Worker 'LGPL': ('LESSER GENERAL PUBLIC LICENSE',), 43*90c8c64dSAndroid Build Coastguard Worker 'GPL-2.0': ('GNU GENERAL PUBLIC LICENSE', 'Version 2,',), 44*90c8c64dSAndroid Build Coastguard Worker 'GPL': ('GNU GENERAL PUBLIC LICENSE',), 45*90c8c64dSAndroid Build Coastguard Worker} 46*90c8c64dSAndroid Build Coastguard Worker 47*90c8c64dSAndroid Build Coastguard WorkerLICENSE_INCLUDE = ['legacy_permissive', 'legacy_unencumbered'] 48*90c8c64dSAndroid Build Coastguard Worker 49*90c8c64dSAndroid Build Coastguard Workerclass LicenseCollector(object): 50*90c8c64dSAndroid Build Coastguard Worker """ Collect licenses from a VNDK snapshot directory 51*90c8c64dSAndroid Build Coastguard Worker 52*90c8c64dSAndroid Build Coastguard Worker This is to collect the license_kinds to be used in license modules. 53*90c8c64dSAndroid Build Coastguard Worker 54*90c8c64dSAndroid Build Coastguard Worker Initialize the LicenseCollector with a vndk snapshot directory. 55*90c8c64dSAndroid Build Coastguard Worker After run() is called, 'license_kinds' will include the licenses found from 56*90c8c64dSAndroid Build Coastguard Worker the snapshot directory. 57*90c8c64dSAndroid Build Coastguard Worker """ 58*90c8c64dSAndroid Build Coastguard Worker def __init__(self, install_dir): 59*90c8c64dSAndroid Build Coastguard Worker self._install_dir = install_dir 60*90c8c64dSAndroid Build Coastguard Worker self._paths_to_check = [os.path.join(install_dir, 61*90c8c64dSAndroid Build Coastguard Worker utils.NOTICE_FILES_DIR_PATH),] 62*90c8c64dSAndroid Build Coastguard Worker self._paths_to_check = self._paths_to_check + glob.glob(os.path.join(self._install_dir, '*/include')) 63*90c8c64dSAndroid Build Coastguard Worker 64*90c8c64dSAndroid Build Coastguard Worker self.license_kinds = set() 65*90c8c64dSAndroid Build Coastguard Worker 66*90c8c64dSAndroid Build Coastguard Worker def read_and_check_licenses(self, license_text, license_keywords): 67*90c8c64dSAndroid Build Coastguard Worker """ Read the license keywords and check if all keywords are in the file. 68*90c8c64dSAndroid Build Coastguard Worker 69*90c8c64dSAndroid Build Coastguard Worker The found licenses will be added to license_kinds set. This function will 70*90c8c64dSAndroid Build Coastguard Worker return True if any licenses are found, False otherwise. 71*90c8c64dSAndroid Build Coastguard Worker """ 72*90c8c64dSAndroid Build Coastguard Worker found = False 73*90c8c64dSAndroid Build Coastguard Worker for lic, patterns in license_keywords.items(): 74*90c8c64dSAndroid Build Coastguard Worker for pattern in patterns: 75*90c8c64dSAndroid Build Coastguard Worker if pattern not in license_text: 76*90c8c64dSAndroid Build Coastguard Worker break 77*90c8c64dSAndroid Build Coastguard Worker else: 78*90c8c64dSAndroid Build Coastguard Worker self.license_kinds.add(LICENSE_KINDS_PREFIX + lic) 79*90c8c64dSAndroid Build Coastguard Worker found = True 80*90c8c64dSAndroid Build Coastguard Worker return found 81*90c8c64dSAndroid Build Coastguard Worker 82*90c8c64dSAndroid Build Coastguard Worker def check_licenses(self, filepath): 83*90c8c64dSAndroid Build Coastguard Worker """ Read a license text file and find the license_kinds. 84*90c8c64dSAndroid Build Coastguard Worker """ 85*90c8c64dSAndroid Build Coastguard Worker with open(filepath, 'rt', encoding='utf-8') as file_to_check: 86*90c8c64dSAndroid Build Coastguard Worker try: 87*90c8c64dSAndroid Build Coastguard Worker file_string = file_to_check.read() 88*90c8c64dSAndroid Build Coastguard Worker self.read_and_check_licenses(file_string, LICENSE_KEYWORDS) 89*90c8c64dSAndroid Build Coastguard Worker except UnicodeDecodeError: 90*90c8c64dSAndroid Build Coastguard Worker # Read text files only. 91*90c8c64dSAndroid Build Coastguard Worker return 92*90c8c64dSAndroid Build Coastguard Worker 93*90c8c64dSAndroid Build Coastguard Worker def run(self, module=''): 94*90c8c64dSAndroid Build Coastguard Worker """ search licenses in vndk snapshots 95*90c8c64dSAndroid Build Coastguard Worker 96*90c8c64dSAndroid Build Coastguard Worker Args: 97*90c8c64dSAndroid Build Coastguard Worker module: module name to find the license kind. 98*90c8c64dSAndroid Build Coastguard Worker If empty, check all license files. 99*90c8c64dSAndroid Build Coastguard Worker """ 100*90c8c64dSAndroid Build Coastguard Worker if module == '': 101*90c8c64dSAndroid Build Coastguard Worker for path in self._paths_to_check: 102*90c8c64dSAndroid Build Coastguard Worker logging.info('Reading {}'.format(path)) 103*90c8c64dSAndroid Build Coastguard Worker for (root, _, files) in os.walk(path): 104*90c8c64dSAndroid Build Coastguard Worker for f in files: 105*90c8c64dSAndroid Build Coastguard Worker self.check_licenses(os.path.join(root, f)) 106*90c8c64dSAndroid Build Coastguard Worker self.license_kinds.update(LICENSE_INCLUDE) 107*90c8c64dSAndroid Build Coastguard Worker else: 108*90c8c64dSAndroid Build Coastguard Worker license_text_path = '{notice_dir}/{module}.txt'.format( 109*90c8c64dSAndroid Build Coastguard Worker notice_dir=utils.NOTICE_FILES_DIR_NAME, 110*90c8c64dSAndroid Build Coastguard Worker module=module) 111*90c8c64dSAndroid Build Coastguard Worker logging.info('Reading {}'.format(license_text_path)) 112*90c8c64dSAndroid Build Coastguard Worker self.check_licenses(os.path.join(self._install_dir, utils.COMMON_DIR_PATH, license_text_path)) 113*90c8c64dSAndroid Build Coastguard Worker if not self.license_kinds: 114*90c8c64dSAndroid Build Coastguard Worker # Add 'legacy_permissive' if no licenses are found for this file. 115*90c8c64dSAndroid Build Coastguard Worker self.license_kinds.add('legacy_permissive') 116*90c8c64dSAndroid Build Coastguard Worker 117*90c8c64dSAndroid Build Coastguard Workerdef get_args(): 118*90c8c64dSAndroid Build Coastguard Worker parser = argparse.ArgumentParser() 119*90c8c64dSAndroid Build Coastguard Worker parser.add_argument( 120*90c8c64dSAndroid Build Coastguard Worker 'vndk_version', 121*90c8c64dSAndroid Build Coastguard Worker type=utils.vndk_version_int, 122*90c8c64dSAndroid Build Coastguard Worker help='VNDK snapshot version to check, e.g. "{}".'.format( 123*90c8c64dSAndroid Build Coastguard Worker utils.MINIMUM_VNDK_VERSION)) 124*90c8c64dSAndroid Build Coastguard Worker parser.add_argument( 125*90c8c64dSAndroid Build Coastguard Worker '-v', 126*90c8c64dSAndroid Build Coastguard Worker '--verbose', 127*90c8c64dSAndroid Build Coastguard Worker action='count', 128*90c8c64dSAndroid Build Coastguard Worker default=0, 129*90c8c64dSAndroid Build Coastguard Worker help='Increase output verbosity, e.g. "-v", "-vv".') 130*90c8c64dSAndroid Build Coastguard Worker return parser.parse_args() 131*90c8c64dSAndroid Build Coastguard Worker 132*90c8c64dSAndroid Build Coastguard Workerdef main(): 133*90c8c64dSAndroid Build Coastguard Worker """ For the local testing purpose. 134*90c8c64dSAndroid Build Coastguard Worker """ 135*90c8c64dSAndroid Build Coastguard Worker ANDROID_BUILD_TOP = utils.get_android_build_top() 136*90c8c64dSAndroid Build Coastguard Worker PREBUILTS_VNDK_DIR = utils.join_realpath(ANDROID_BUILD_TOP, 137*90c8c64dSAndroid Build Coastguard Worker 'prebuilts/vndk') 138*90c8c64dSAndroid Build Coastguard Worker args = get_args() 139*90c8c64dSAndroid Build Coastguard Worker vndk_version = args.vndk_version 140*90c8c64dSAndroid Build Coastguard Worker install_dir = os.path.join(PREBUILTS_VNDK_DIR, 'v{}'.format(vndk_version)) 141*90c8c64dSAndroid Build Coastguard Worker utils.set_logging_config(args.verbose) 142*90c8c64dSAndroid Build Coastguard Worker 143*90c8c64dSAndroid Build Coastguard Worker license_collector = LicenseCollector(install_dir) 144*90c8c64dSAndroid Build Coastguard Worker license_collector.run() 145*90c8c64dSAndroid Build Coastguard Worker print(sorted(license_collector.license_kinds)) 146*90c8c64dSAndroid Build Coastguard Worker 147*90c8c64dSAndroid Build Coastguard Workerif __name__ == '__main__': 148*90c8c64dSAndroid Build Coastguard Worker main() 149