esp-idf/tools/ci/check_build_warnings.py

111 wiersze
3.4 KiB
Python
Executable File

#!/usr/bin/env python
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
# coding=utf-8
#
# CI script to check build logs for warnings.
# Reads the list of builds, in the format produced by find_apps.py or build_apps.py, and finds warnings in the
# log files for every build.
# Exits with a non-zero exit code if any warning is found.
import argparse
import logging
import os
import re
import sys
try:
from find_build_apps import BuildItem, setup_logging
except ImportError:
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from find_build_apps import BuildItem, setup_logging
WARNING_REGEX = re.compile(r'(?:error|warning)[^\w]', re.MULTILINE | re.IGNORECASE)
IGNORE_WARNS = [
re.compile(r_str) for r_str in [
r'library/error\.o',
r'/.*error\S*\.o',
r'.*error.*\.c\.obj',
r'.*error.*\.c',
r'.*error.*\.cpp\.obj',
r'.*error.*\.cxx\.obj',
r'.*error.*\.cc\.obj',
r'-Werror',
r'error\.d',
r'/.*error\S*.d',
r'reassigning to symbol',
r'changes choice state',
r'crosstool_version_check\.cmake',
r'CryptographyDeprecationWarning',
r'Warning: \d+/\d+ app partitions are too small for binary',
]
]
def line_has_warnings(line): # type: (str) -> bool
if not WARNING_REGEX.search(line):
return False
has_warnings = True
for ignored in IGNORE_WARNS:
if re.search(ignored, line):
has_warnings = False
break
return has_warnings
def main(): # type: () -> None
parser = argparse.ArgumentParser(description='ESP-IDF app builder')
parser.add_argument(
'-v',
'--verbose',
action='count',
help='Increase the logging level of the script. Can be specified multiple times.',
)
parser.add_argument(
'--log-file',
type=argparse.FileType('w'),
help='Write the script log to the specified file, instead of stderr',
)
parser.add_argument(
'build_list',
type=argparse.FileType('r'),
nargs='?',
default=sys.stdin,
help='Name of the file to read the list of builds from. If not specified, read from stdin.',
)
args = parser.parse_args()
setup_logging(args)
build_items = [BuildItem.from_json(line) for line in args.build_list]
if not build_items:
logging.warning('Empty build list')
SystemExit(0)
found_warnings = 0
for build_item in build_items:
if not build_item.build_log_path:
logging.debug('No log file for {}'.format(build_item.work_dir))
continue
with open(build_item.build_log_path, 'r') as log_file:
for line_no, line in enumerate(log_file):
if line_has_warnings(line):
logging.error('Issue in app {}, config {}:'.format(build_item.app_dir, build_item.config_name))
logging.error(line.rstrip('\n'))
logging.error('See {}:{} for details'.format(os.path.basename(build_item.build_log_path),
line_no + 1))
found_warnings += 1
break
if found_warnings:
logging.error('Checked {} builds, found {} warnings'.format(len(build_items), found_warnings))
raise SystemExit(1)
logging.info('No warnings found')
if __name__ == '__main__':
main()