check_build_warnings.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #!/usr/bin/env python
  2. # coding=utf-8
  3. #
  4. # CI script to check build logs for warnings.
  5. # Reads the list of builds, in the format produced by find_apps.py or build_apps.py, and finds warnings in the
  6. # log files for every build.
  7. # Exits with a non-zero exit code if any warning is found.
  8. import argparse
  9. import logging
  10. import os
  11. import re
  12. import sys
  13. try:
  14. from find_build_apps import BuildItem, setup_logging
  15. except ImportError:
  16. sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
  17. from find_build_apps import BuildItem, setup_logging
  18. WARNING_REGEX = re.compile(r'(?:error|warning)[^\w]', re.MULTILINE | re.IGNORECASE)
  19. IGNORE_WARNS = [
  20. re.compile(r_str) for r_str in [
  21. r'library/error\.o',
  22. r'/.*error\S*\.o',
  23. r'.*error.*\.c\.obj',
  24. r'.*error.*\.c',
  25. r'.*error.*\.cpp\.obj',
  26. r'.*error.*\.cxx\.obj',
  27. r'.*error.*\.cc\.obj',
  28. r'-Werror',
  29. r'error\.d',
  30. r'/.*error\S*.d',
  31. r'reassigning to symbol',
  32. r'changes choice state',
  33. r'crosstool_version_check\.cmake',
  34. r'CryptographyDeprecationWarning',
  35. r'Warning: \d+/\d+ app partitions are too small for binary',
  36. r'CMake Deprecation Warning at main/lib/tinyxml2/CMakeLists\.txt:11 \(cmake_policy\)',
  37. ]
  38. ]
  39. def line_has_warnings(line): # type: (str) -> bool
  40. if not WARNING_REGEX.search(line):
  41. return False
  42. has_warnings = True
  43. for ignored in IGNORE_WARNS:
  44. if re.search(ignored, line):
  45. has_warnings = False
  46. break
  47. return has_warnings
  48. def main(): # type: () -> None
  49. parser = argparse.ArgumentParser(description='ESP-IDF app builder')
  50. parser.add_argument(
  51. '-v',
  52. '--verbose',
  53. action='count',
  54. help='Increase the logging level of the script. Can be specified multiple times.',
  55. )
  56. parser.add_argument(
  57. '--log-file',
  58. type=argparse.FileType('w'),
  59. help='Write the script log to the specified file, instead of stderr',
  60. )
  61. parser.add_argument(
  62. 'build_list',
  63. type=argparse.FileType('r'),
  64. nargs='?',
  65. default=sys.stdin,
  66. help='Name of the file to read the list of builds from. If not specified, read from stdin.',
  67. )
  68. args = parser.parse_args()
  69. setup_logging(args)
  70. build_items = [BuildItem.from_json(line) for line in args.build_list]
  71. if not build_items:
  72. logging.warning('Empty build list')
  73. SystemExit(0)
  74. found_warnings = 0
  75. for build_item in build_items:
  76. if not build_item.build_log_path:
  77. logging.debug('No log file for {}'.format(build_item.work_dir))
  78. continue
  79. with open(build_item.build_log_path, 'r') as log_file:
  80. for line_no, line in enumerate(log_file):
  81. if line_has_warnings(line):
  82. logging.error('Issue in app {}, config {}:'.format(build_item.app_dir, build_item.config_name))
  83. logging.error(line.rstrip('\n'))
  84. logging.error('See {}:{} for details'.format(os.path.basename(build_item.build_log_path),
  85. line_no + 1))
  86. found_warnings += 1
  87. break
  88. if found_warnings:
  89. logging.error('Checked {} builds, found {} warnings'.format(len(build_items), found_warnings))
  90. raise SystemExit(1)
  91. logging.info('No warnings found')
  92. if __name__ == '__main__':
  93. main()