check_build_warnings.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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 os
  9. import sys
  10. import argparse
  11. import logging
  12. import re
  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 = r"error|warning"
  19. IGNORE_WARNS = [
  20. re.compile(r_str) for r_str in [
  21. r"library/error\.o",
  22. r".*error.*\.c\.obj",
  23. r"-Werror",
  24. r"error\.d",
  25. r"reassigning to symbol",
  26. r"changes choice state",
  27. r"crosstool_version_check\.cmake",
  28. ]
  29. ]
  30. def line_has_warnings(line): # type: (str) -> bool
  31. if not re.search(WARNING_REGEX, line):
  32. return False
  33. has_warnings = True
  34. for ignored in IGNORE_WARNS:
  35. if re.search(ignored, line):
  36. has_warnings = False
  37. break
  38. return has_warnings
  39. def main():
  40. parser = argparse.ArgumentParser(description="ESP-IDF app builder")
  41. parser.add_argument(
  42. "-v",
  43. "--verbose",
  44. action="count",
  45. help="Increase the logging level of the script. Can be specified multiple times.",
  46. )
  47. parser.add_argument(
  48. "--log-file",
  49. type=argparse.FileType("w"),
  50. help="Write the script log to the specified file, instead of stderr",
  51. )
  52. parser.add_argument(
  53. "build_list",
  54. type=argparse.FileType("r"),
  55. nargs="?",
  56. default=sys.stdin,
  57. help="Name of the file to read the list of builds from. If not specified, read from stdin.",
  58. )
  59. args = parser.parse_args()
  60. setup_logging(args)
  61. build_items = [BuildItem.from_json(line) for line in args.build_list]
  62. if not build_items:
  63. logging.error("Empty build list!")
  64. raise SystemExit(1)
  65. found_warnings = 0
  66. for build_item in build_items:
  67. if not build_item.build_log_path:
  68. logging.debug("No log file for {}".format(build_item.work_dir))
  69. continue
  70. with open(build_item.build_log_path, "r") as log_file:
  71. for line_no, line in enumerate(log_file):
  72. if line_has_warnings(line):
  73. logging.error("Issue in app {}, config {}:".format(build_item.app_dir, build_item.config_name))
  74. logging.error(line.rstrip("\n"))
  75. logging.error("See {}:{} for details".format(os.path.basename(build_item.build_log_path),
  76. line_no + 1))
  77. found_warnings += 1
  78. break
  79. if found_warnings:
  80. logging.error("Checked {} builds, found {} warnings".format(len(build_items), found_warnings))
  81. raise SystemExit(1)
  82. logging.info("No warnings found")
  83. if __name__ == "__main__":
  84. main()