blob: 5a4a5b1a9b2b5f04eb457111ca81ba1c63286084 [file] [log] [blame]
#!/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()