From c6d6fe031646cbca84e27268fcba1fb5e6c43829 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 18 Dec 2019 16:11:11 +0100 Subject: [PATCH] ci: add job to check for C++ guards in header files --- tools/ci/check_cpp_guards.sh | 127 +++++++++++++++++++++++ tools/ci/check_cpp_guards_exceptions.txt | 118 +++++++++++++++++++++ tools/ci/config/pre_check.yml | 16 +++ tools/ci/executable-list.txt | 1 + 4 files changed, 262 insertions(+) create mode 100755 tools/ci/check_cpp_guards.sh create mode 100644 tools/ci/check_cpp_guards_exceptions.txt diff --git a/tools/ci/check_cpp_guards.sh b/tools/ci/check_cpp_guards.sh new file mode 100755 index 0000000000..cc9f5fad12 --- /dev/null +++ b/tools/ci/check_cpp_guards.sh @@ -0,0 +1,127 @@ +#!/bin/bash +# +# This script finds all files which do not contain "#ifdef __cplusplus", except the ones listed in check_cpp_guards_exceptions.txt + +set -euo pipefail + +if [ -z "${IDF_PATH:-}" ]; then + echo "Please run export.sh before invoking this script" + exit 1 +fi + +##################### helper functions ##################### + +# check_one_header +# +# Function used to implement the logic of checking a single header. +# Returns 0 on success (as a normal bash function would). +# Ideally shouldn't print anything. +function check_one_header +{ + include_file=$1 + grep -q '#ifdef __cplusplus' ${include_file} +} + +# get_include_dir_list +# +# Get the list of public include directories from compile_commands.json. +# Stores the result in INCLUDE_DIRS variable. +function get_include_dirs_list +{ + pushd $IDF_PATH/examples/get-started/blink + idf.py reconfigure + + # Get the compiler command line from compile_commands.json + # Poor man's replacement of `jq` in Python. + extract_build_command_py='import json; print(json.load(open("build/compile_commands.json", "r"))[0]["command"])' + build_command=$(python -c "${extract_build_command_py}") + + # build the list of include directories, only considering the directories in "components/" + include_dirs="" + for token in ${build_command}; do + if [[ ! "${token}" =~ ^-I.*/components/.* ]]; then + continue + fi + newline=$'\n' + include_dirs="${include_dirs}${token##-I}${newline}" + done + + export INCLUDE_DIRS=${include_dirs} +} + +# check_include_dirs +# +# Check all header files in directories listed in include_dirs variable. +# Places the list of header files with some issues into file. +# Calls check_one_header function to check a single header file. +function check_include_dirs +{ + local include_dirs="$1" + local failed_headers_list_file="$2" + + rm -f ${failed_headers_list_file} + touch ${failed_headers_list_file} + + for include_dir in ${include_dirs}; do + echo "Processing include directory: ${include_dir}" + include_files=$(find ${include_dir} -name '*.h') + for include_file in ${include_files}; do + printf " Processing ${include_file}" + if ! check_one_header ${include_file}; then + printf " FAIL!\n" + echo ${include_file##${IDF_PATH}/} >> ${failed_headers_list_file} + else + printf " OK\n" + fi + done + done +} + +# filter_exclusions +# +# Takes the list of files in file, and removes all files which +# are listed in file. +# Saves the final (filtered) list in file. +# The exclusions list file may contain comments and empty lines. +function filter_exclusions +{ + local input_list_file=$1 + local exclusions_list_file=$2 + local filtered_list_file=$3 + local temp_list=$(mktemp) + + cp ${input_list_file} ${filtered_list_file} + touch ${temp_list} + + while read -r line; do + if [[ "${line}" =~ ^\# || -z "${line}" ]]; then + continue + fi + echo "Excluding ${line}" + grep -vE "${line}" ${filtered_list_file} > ${temp_list} || true + mv ${temp_list} ${filtered_list_file} + done < ${exclusions_list_file} + + rm -f ${temp_list} +} + +##################### main logic starts here ##################### + +EXCLUSIONS_LIST=${IDF_PATH}/tools/ci/check_cpp_guards_exceptions.txt +MISSING_GUARDS_LIST=missing.txt +FILTERED_LIST=filtered.txt +LINE=--------------------------------------------------------------- + + +get_include_dirs_list +check_include_dirs "${INCLUDE_DIRS}" ${MISSING_GUARDS_LIST} +filter_exclusions ${MISSING_GUARDS_LIST} ${EXCLUSIONS_LIST} ${FILTERED_LIST} + +if [ -s ${FILTERED_LIST} ]; then + echo "The following files don't have C++ guards:" + echo "" + cat ${FILTERED_LIST} + exit 1 +fi + +echo "No errors found" diff --git a/tools/ci/check_cpp_guards_exceptions.txt b/tools/ci/check_cpp_guards_exceptions.txt new file mode 100644 index 0000000000..4985524812 --- /dev/null +++ b/tools/ci/check_cpp_guards_exceptions.txt @@ -0,0 +1,118 @@ +components/xtensa/include/xtensa/* +components/xtensa/include/* +components/xtensa/esp32/include/xtensa/config/* + +components/newlib/platform_include/* + +components/freertos/include/freertos/* + +components/log/include/esp_log_internal.h + +components/soc/esp32/include/hal/* +components/soc/esp32/include/soc/* +components/soc/include/hal/* +components/soc/include/soc/* + +components/esp_rom/include/esp32s2beta/rom/rsa_pss.h + +components/esp_common/include/esp_types.h +components/esp_common/include/esp_assert.h +components/esp_common/include/esp_bit_defs.h +components/esp_common/include/esp_task.h +components/esp_common/include/esp_private/* + +components/esp32/include/esp32/* +components/esp32/include/rom/* +components/esp32/include/esp_clk.h +components/esp32/include/esp_intr.h +components/esp32/include/esp_himem.h +components/esp32/include/esp_spiram.h +components/driver/include/driver/touch_pad.h + +components/driver/include/driver/sdmmc_defs.h +components/driver/include/driver/sdmmc_types.h +components/driver/include/driver/rtc_cntl.h +components/driver/include/driver/sigmadelta.h + +components/esp_event/include/esp_event_loop.h + +components/lwip/include/apps/dhcpserver/* +components/lwip/include/apps/esp_sntp.h +components/lwip/lwip/src/include/compat/* +components/lwip/lwip/src/include/lwip/* +components/lwip/lwip/src/include/netif/* +components/lwip/port/esp32/include/* + +components/vfs/include/sys/dirent.h + +components/esp_wifi/include/esp_private/* +components/esp_wifi/include/esp_wifi_netif.h +components/esp_wifi/include/esp_wifi_default.h +components/esp_wifi/esp32/include/phy_init_data.h + +components/tcpip_adapter/include/tcpip_adapter_compatible/tcpip_adapter_compat.h +components/tcpip_adapter/include/tcpip_adapter.h +components/tcpip_adapter/include/tcpip_adapter_types.h + +components/spi_flash/include/spi_flash_chip_issi.h +components/spi_flash/include/spi_flash_chip_gd.h +components/spi_flash/include/memspi_host_driver.h +components/spi_flash/include/spi_flash_chip_driver.h +components/spi_flash/include/spi_flash_chip_generic.h + +components/bootloader_support/include/esp_flash_data_types.h +components/bootloader_support/include/esp_app_format.h + +components/wpa_supplicant/include/* +components/wpa_supplicant/port/* + +components/mbedtls/port/include/* +components/mbedtls/mbedtls/include/mbedtls/* + +components/espcoredump/include/esp_core_dump.h + +components/perfmon/include/perfmon.h + +components/asio/* +components/coap/* +components/nghttp/* +components/cbor/* + +components/esp-tls/private_include/* + +components/esp_http_server/include/http_server.h + +components/protobuf-c/* + +components/mdns/include/mdns_console.h + +components/esp_serial_slave_link/include/esp_serial_slave_link/essl.h +components/esp_serial_slave_link/include/esp_serial_slave_link/essl_sdio.h + +components/expat/* + +components/fatfs/vfs/vfs_fat_internal.h +components/fatfs/src/ffconf.h + +components/freemodbus/common/include/esp_modbus_common.h +components/freemodbus/common/include/mbcontroller.h +components/freemodbus/common/include/esp_modbus_master.h +components/freemodbus/common/include/esp_modbus_slave.h + +components/idf_test/include/idf_performance.h + +components/json/cJSON/* + +components/libsodium/* + +components/mqtt/esp-mqtt/include/mqtt_supported_features.h +components/mqtt/esp-mqtt/include/mqtt_config.h + +components/openssl/include/platform/ssl_opt.h + +components/spiffs/include/spiffs_config.h + +components/unity/unity/src/unity_internals.h +components/unity/include/priv/setjmp.h + + diff --git a/tools/ci/config/pre_check.yml b/tools/ci/config/pre_check.yml index 881cc2c2ef..f057904728 100644 --- a/tools/ci/config/pre_check.yml +++ b/tools/ci/config/pre_check.yml @@ -151,3 +151,19 @@ build_template_app: - for dir in esp32 esp32s2beta; do test $(xtensa-esp32-elf-nm $dir/*.a | grep -w printf | wc -l) -eq 0; done; - for dir in esp32 esp32s2beta; do test $(xtensa-esp32-elf-nm $dir/*.a | grep -w ets_printf | wc -l) -eq 0; done; - popd + +check_header_files_cpp_guards: + stage: pre_check + image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG + tags: + - build + variables: + BATCH_BUILD: "1" + only: + variables: + - $BOT_TRIGGER_WITH_LABEL == null + - $BOT_LABEL_BUILD + - $BOT_LABEL_REGULAR_TEST + script: + - tools/ci/check_cpp_guards.sh + diff --git a/tools/ci/executable-list.txt b/tools/ci/executable-list.txt index bea16d10f5..443053f0e5 100644 --- a/tools/ci/executable-list.txt +++ b/tools/ci/executable-list.txt @@ -36,6 +36,7 @@ tools/ci/build_examples_cmake.sh tools/ci/check-executable.sh tools/ci/check-line-endings.sh tools/ci/check_build_warnings.py +tools/ci/check_cpp_guards.sh tools/ci/check_deprecated_kconfigs.py tools/ci/check_examples_cmake_make.sh tools/ci/check_examples_rom_header.sh