1#!/usr/bin/env python 2# 3# Copyright 2019 Espressif Systems (Shanghai) PTE LTD 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17from __future__ import print_function, unicode_literals 18 19import argparse 20import os 21import sys 22from io import open 23 24from check_kconfigs import valid_directory 25from idf_ci_utils import get_submodule_dirs 26 27# FILES_TO_CHECK used as "startswith" pattern to match sdkconfig.defaults variants 28FILES_TO_CHECK = ('sdkconfig.ci', 'sdkconfig.defaults') 29 30# ignored directories (makes sense only when run on IDF_PATH) 31# Note: IGNORE_DIRS is a tuple in order to be able to use it directly with the startswith() built-in function which 32# accepts tuples but no lists. 33IGNORE_DIRS = ( 34) 35 36 37def _parse_path(path, sep=None): 38 ret = set() 39 with open(path, 'r', encoding='utf-8') as f: 40 for line in f: 41 line = line.strip() 42 if not line.startswith('#') and len(line) > 0: 43 ret.add(line.split(sep)[0]) 44 return ret 45 46 47def _valid_directory(path): 48 if not os.path.isdir(path): 49 raise argparse.ArgumentTypeError('{} is not a valid directory!'.format(path)) 50 return path 51 52 53def main(): 54 parser = argparse.ArgumentParser(description='Kconfig options checker') 55 parser.add_argument('files', nargs='*', 56 help='Kconfig files') 57 parser.add_argument('--includes', '-d', nargs='*', 58 help='Extra paths for recursively searching Kconfig files. (for example $IDF_PATH)', 59 type=valid_directory) 60 parser.add_argument('--exclude-submodules', action='store_true', 61 help='Exclude submodules') 62 args = parser.parse_args() 63 64 success_counter = 0 65 failure_counter = 0 66 ignore_counter = 0 67 68 deprecated_options = set() 69 70 ignore_dirs = IGNORE_DIRS 71 if args.exclude_submodules: 72 for submodule in get_submodule_dirs(full_path=True): 73 ignore_dirs = ignore_dirs + tuple(submodule) 74 75 files = [os.path.abspath(file_path) for file_path in args.files] 76 77 if args.includes: 78 for directory in args.includes: 79 for root, dirnames, filenames in os.walk(directory): 80 for filename in filenames: 81 full_path = os.path.join(root, filename) 82 if filename.startswith(FILES_TO_CHECK): 83 files.append(full_path) 84 elif filename == 'sdkconfig.rename': 85 deprecated_options |= _parse_path(full_path) 86 87 for full_path in files: 88 if full_path.startswith(ignore_dirs): 89 print('{}: Ignored'.format(full_path)) 90 ignore_counter += 1 91 continue 92 used_options = _parse_path(full_path, '=') 93 used_deprecated_options = deprecated_options & used_options 94 if len(used_deprecated_options) > 0: 95 print('{}: The following options are deprecated: {}' 96 .format(full_path, ', '.join(used_deprecated_options))) 97 failure_counter += 1 98 else: 99 print('{}: OK'.format(full_path)) 100 success_counter += 1 101 102 if ignore_counter > 0: 103 print('{} files have been ignored.'.format(ignore_counter)) 104 if success_counter > 0: 105 print('{} files have been successfully checked.'.format(success_counter)) 106 if failure_counter > 0: 107 print('{} files have errors. Please take a look at the log.'.format(failure_counter)) 108 return 1 109 110 if not files: 111 print('WARNING: no files specified. Please specify files or use ' 112 '"--includes" to search Kconfig files recursively') 113 return 0 114 115 116if __name__ == '__main__': 117 sys.exit(main()) 118