check_cpp_guards.sh 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #!/bin/bash
  2. #
  3. # This script finds all files which do not contain "#ifdef __cplusplus", except the ones listed in check_cpp_guards_exceptions.txt
  4. set -euo pipefail
  5. if [ -z "${IDF_PATH:-}" ]; then
  6. echo "Please run export.sh before invoking this script"
  7. exit 1
  8. fi
  9. ##################### helper functions #####################
  10. # check_one_header <filename>
  11. #
  12. # Function used to implement the logic of checking a single header.
  13. # Returns 0 on success (as a normal bash function would).
  14. # Ideally shouldn't print anything.
  15. function check_one_header
  16. {
  17. include_file=$1
  18. grep -q '#ifdef __cplusplus' ${include_file}
  19. }
  20. # get_include_dir_list
  21. #
  22. # Get the list of public include directories from compile_commands.json.
  23. # Stores the result in INCLUDE_DIRS variable.
  24. function get_include_dirs_list
  25. {
  26. pushd $IDF_PATH/examples/get-started/blink
  27. idf.py reconfigure
  28. # Get the compiler command line from compile_commands.json
  29. # Poor man's replacement of `jq` in Python.
  30. extract_build_command_py='import json; print(json.load(open("build/compile_commands.json", "r"))[0]["command"])'
  31. build_command=$(python -c "${extract_build_command_py}")
  32. # build the list of include directories, only considering the directories in "components/"
  33. include_dirs=""
  34. for token in ${build_command}; do
  35. if [[ ! "${token}" =~ ^-I.*/components/.* ]]; then
  36. continue
  37. fi
  38. newline=$'\n'
  39. include_dirs="${include_dirs}${token##-I}${newline}"
  40. done
  41. export INCLUDE_DIRS=${include_dirs}
  42. }
  43. # check_include_dirs <include_dirs> <failed_headers_list_file>
  44. #
  45. # Check all header files in directories listed in include_dirs variable.
  46. # Places the list of header files with some issues into <failed_headers_list_file> file.
  47. # Calls check_one_header function to check a single header file.
  48. function check_include_dirs
  49. {
  50. local include_dirs="$1"
  51. local failed_headers_list_file="$2"
  52. rm -f ${failed_headers_list_file}
  53. touch ${failed_headers_list_file}
  54. for include_dir in ${include_dirs}; do
  55. echo "Processing include directory: ${include_dir}"
  56. include_files=$(find ${include_dir} -name '*.h')
  57. for include_file in ${include_files}; do
  58. printf " Processing ${include_file}"
  59. if ! check_one_header ${include_file}; then
  60. printf " FAIL!\n"
  61. echo ${include_file##${IDF_PATH}/} >> ${failed_headers_list_file}
  62. else
  63. printf " OK\n"
  64. fi
  65. done
  66. done
  67. }
  68. # filter_exclusions <input_list_file> <exclusions_list_file> <filtered_list_file>
  69. #
  70. # Takes the list of files in <input_list_file> file, and removes all files which
  71. # are listed in <exclusions_list_file> file.
  72. # Saves the final (filtered) list in <filtered_list_file> file.
  73. # The exclusions list file may contain comments and empty lines.
  74. function filter_exclusions
  75. {
  76. local input_list_file=$1
  77. local exclusions_list_file=$2
  78. local filtered_list_file=$3
  79. local temp_list=$(mktemp)
  80. cp ${input_list_file} ${filtered_list_file}
  81. touch ${temp_list}
  82. while read -r line; do
  83. if [[ "${line}" =~ ^\# || -z "${line}" ]]; then
  84. continue
  85. fi
  86. echo "Excluding ${line}"
  87. grep -vE "${line}" ${filtered_list_file} > ${temp_list} || true
  88. mv ${temp_list} ${filtered_list_file}
  89. done < ${exclusions_list_file}
  90. rm -f ${temp_list}
  91. }
  92. ##################### main logic starts here #####################
  93. EXCLUSIONS_LIST=${IDF_PATH}/tools/ci/check_cpp_guards_exceptions.txt
  94. MISSING_GUARDS_LIST=missing.txt
  95. FILTERED_LIST=filtered.txt
  96. LINE=---------------------------------------------------------------
  97. get_include_dirs_list
  98. check_include_dirs "${INCLUDE_DIRS}" ${MISSING_GUARDS_LIST}
  99. filter_exclusions ${MISSING_GUARDS_LIST} ${EXCLUSIONS_LIST} ${FILTERED_LIST}
  100. if [ -s ${FILTERED_LIST} ]; then
  101. echo "The following files don't have C++ guards:"
  102. echo ""
  103. cat ${FILTERED_LIST}
  104. exit 1
  105. fi
  106. echo "No errors found"