diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 107b093778..7fbceeb1fa 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -142,6 +142,48 @@ before_script: - export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/ci/python_packages:$PYTHONPATH" - *fetch_submodules +.build_template_app_template: + stage: build + image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG + tags: + - build + variables: + BATCH_BUILD: "1" + LOG_PATH: "${CI_PROJECT_DIR}/log_template_app" + BUILD_PATH: "${CI_PROJECT_DIR}/build_template_app" + SIZE_INFO_LOCATION: "$CI_PROJECT_DIR/size_info.txt" + BUILD_DIR: "@t/@w" + BUILD_LOG_MAKE: "${LOG_PATH}/make_@t_@w.txt" + BUILD_LOG_CMAKE: "${LOG_PATH}/cmake_@t_@w.txt" + BUILD_COMMAND_ARGS: "" + artifacts: + when: always + paths: + - log_template_app/* + - size_info.txt + - build_template_app/**/size.json + only: + variables: + - $BOT_TRIGGER_WITH_LABEL == null + - $BOT_LABEL_BUILD + - $BOT_LABEL_REGULAR_TEST + script: + # Set the variable for 'esp-idf-template' testing + - ESP_IDF_TEMPLATE_GIT=${ESP_IDF_TEMPLATE_GIT:-"https://github.com/espressif/esp-idf-template.git"} + - ./tools/ci/retry_failed.sh git clone ${ESP_IDF_TEMPLATE_GIT} + # Try to use the same branch name for esp-idf-template that we're + # using on esp-idf. If it doesn't exist then just stick to the default branch + - python $CHECKOUT_REF_SCRIPT esp-idf-template esp-idf-template + - export PATH="$IDF_PATH/tools:$PATH" + - export EXTRA_CFLAGS=${PEDANTIC_CFLAGS} + - export EXTRA_CXXFLAGS=${PEDANTIC_CXXFLAGS} + # Only do the default cmake build for each target, remaining part are done in the build_template_app job + - tools/ci/build_template_app.sh ${BUILD_COMMAND_ARGS} + # Check if there are any stray printf/ets_printf references in WiFi libs + - cd components/esp_wifi/lib + - for dir in esp32 esp32s2; do test $(xtensa-esp32-elf-nm $dir/*.a | grep -w printf | wc -l) -eq 0; done; + - for dir in esp32 esp32s2; do test $(xtensa-esp32-elf-nm $dir/*.a | grep -w ets_printf | wc -l) -eq 0; done; + include: - '/tools/ci/config/pre_check.yml' - '/tools/ci/config/build.yml' diff --git a/tools/ci/build_template_app.sh b/tools/ci/build_template_app.sh new file mode 100755 index 0000000000..73195b1b31 --- /dev/null +++ b/tools/ci/build_template_app.sh @@ -0,0 +1,127 @@ +#!/usr/bin/env bash +# +# Usage: build_template_app.sh [-p] +# -p: optional, if specified, do a fast build for every chip target with cmake and only the default +# config. Otherwise permutations of (chip target, build system, configs) which were not built in +# the fast build will be built. +# +# Needs to be called under IDF root folder +# +# This script will call find_apps.py with the following arguments: +# - CMake build arguments: --work-dir {BUILD_PATH}/cmake --build-dir ${BUILD_DIR} --build-log ${BUILD_LOG_CMAKE} +# - Make build arguments: --work-dir {BUILD_PATH}/make/${BUILD_DIR} --build-dir build --build-log ${BUILD_LOG_MAKE} + +set -euo pipefail + +gen_configs() { + # CONFIG_COMPILER_OPTIMIZATION_NONE with flag -O0 + echo "CONFIG_COMPILER_OPTIMIZATION_NONE=y" > esp-idf-template/sdkconfig.ci.O0 + echo "CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE=y" >> esp-idf-template/sdkconfig.ci.O0 + # CONFIG_COMPILER_OPTIMIZATION_SIZE with flag -Os + echo "CONFIG_COMPILER_OPTIMIZATION_SIZE=y" > esp-idf-template/sdkconfig.ci.Os + echo "CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y" >> esp-idf-template/sdkconfig.ci.Os + # CONFIG_COMPILER_OPTIMIZATION_PERF with flag -O2 + echo "CONFIG_COMPILER_OPTIMIZATION_PERF=y" > esp-idf-template/sdkconfig.ci.O2 + echo "CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF=y" >> esp-idf-template/sdkconfig.ci.O2 + + # Only built in make, because CMake already build this config in pre_build job + # CONFIG_COMPILER_OPTIMIZATION_DEFAULT with flag -Og + echo "CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y" > esp-idf-template/sdkconfig.ci2.Og + echo "CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG=y" >> esp-idf-template/sdkconfig.ci2.Og + + # Needs to be built with specific extra flags + # Same as O2, but also disable assertions. + cp esp-idf-template/sdkconfig.ci.O2 esp-idf-template/sdkconfig.ci3.no_assert + echo "CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y" >> esp-idf-template/sdkconfig.ci3.no_assert +} + +get_config_str() { + CONFIG_STR= + until [ $# -eq 0 ] + do + CONFIG_STR+=" --config $1" + shift + done + echo ${CONFIG_STR} +} + +search_cmake() { + TARGET=$1 + shift + CONFIG_STR=$* + tools/find_apps.py -vv --format json --work-dir ${BUILD_PATH}/cmake --build-dir ${BUILD_DIR} --build-log ${BUILD_LOG_CMAKE} -p esp-idf-template --build-system cmake ${CONFIG_STR} --target ${TARGET} --output scan_temp.json + cat scan_temp.json >> scan.json + rm scan_temp.json +} + +search_make() { + TARGET=$1 + shift + CONFIG_STR=$* + tools/find_apps.py -vv --format json --work-dir ${BUILD_PATH}/make/${BUILD_DIR} --build-dir build --build-log ${BUILD_LOG_MAKE} -p esp-idf-template --build-system make ${CONFIG_STR} --target ${TARGET} --output scan_temp.json + cat scan_temp.json >> scan.json + rm scan_temp.json +} + +build() { + tools/build_apps.py -vv --format json --keep-going --parallel-count 1 --parallel-index 1 --size-info ${SIZE_INFO_LOCATION} scan.json + rm scan.json +} + +build_stage2() { + CONFIG_STR=$(get_config_str sdkconfig.ci.*=) + search_cmake esp32 ${CONFIG_STR} + search_cmake esp32s2 ${CONFIG_STR} + + CONFIG_STR=$(get_config_str sdkconfig.ci.*= sdkconfig.ci2.*=) + search_make esp32 ${CONFIG_STR} + search_make esp32s2 ${CONFIG_STR} + + build build_list_1.json + + CONFIG_STR=$(get_config_str sdkconfig.ci3.*=) + search_cmake esp32 ${CONFIG_STR} + search_make esp32 ${CONFIG_STR} + search_cmake esp32s2 ${CONFIG_STR} + search_make esp32s2 ${CONFIG_STR} + + # Override EXTRA_CFLAGS and EXTRA_CXXFLAGS in the environment + export EXTRA_CFLAGS=${PEDANTIC_CFLAGS/-Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function/} + export EXTRA_CXXFLAGS=${PEDANTIC_CXXFLAGS/-Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function/} + build +} + +build_stage1() { + CONFIG_STR=$(get_config_str sdkconfig.ci2.*=) + search_cmake esp32 ${CONFIG_STR} + search_cmake esp32s2 ${CONFIG_STR} + + build +} + +# Default arguments +# STAGE: +# 1 (-p): fast build, 2 (default): regular build +STAGE=2 + +# Parse arguments: -p for STAGE +for arg in $* +do + if [ ${arg} = "-p" ]; then + STAGE=1 + fi +done + +mkdir -p ${BUILD_PATH}/make +mkdir -p ${BUILD_PATH}/cmake +mkdir -p ${LOG_PATH} +rm -f scan.json + +gen_configs + +if [ ${STAGE} = 1 ] +then + build_stage1 +else + build_stage2 +fi \ No newline at end of file diff --git a/tools/ci/config/build.yml b/tools/ci/config/build.yml index 77d99cc15d..536d8addf7 100644 --- a/tools/ci/config/build.yml +++ b/tools/ci/config/build.yml @@ -404,3 +404,7 @@ build_installer: script: - cd tools/windows/tool_setup/ - ./build_installer.sh + +# This job builds template app with permutations of targets and optimization levels +build_template_app: + extends: .build_template_app_template diff --git a/tools/ci/config/pre_check.yml b/tools/ci/config/pre_check.yml index cc89f17010..b49e39bfaf 100644 --- a/tools/ci/config/pre_check.yml +++ b/tools/ci/config/pre_check.yml @@ -107,74 +107,12 @@ check_wifi_lib_md5: - IDF_TARGET=esp32 $IDF_PATH/components/esp_wifi/test_md5/test_md5.sh - IDF_TARGET=esp32s2 $IDF_PATH/components/esp_wifi/test_md5/test_md5.sh -.build_with_make_and_cmake: &build_with_make_and_cmake | - echo -e "section_end:"`date +%s`":build_script\r\e[0Ksection_start:"`date +%s`":build_make\r\e[0KBuild with Make" - make defconfig - make all - make clean - echo -e "section_end:"`date +%s`":build_make\r\e[0Ksection_start:"`date +%s`":build_cmake\r\e[0KBuild with CMake" - rm -rf build sdkconfig - idf.py build - echo -e "section_end:"`date +%s`":build_cmake\r\e[0Ksection_start:"`date +%s`":build_script\r\e[0K" - -build_template_app: +# Build at least one project for each target at earliest stage to reduce build cost for obvious failing commits +fast_template_app: + extends: .build_template_app_template 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: - # Set the variable for 'esp-idf-template' testing - - ESP_IDF_TEMPLATE_GIT=${ESP_IDF_TEMPLATE_GIT:-"https://github.com/espressif/esp-idf-template.git"} - - ./tools/ci/retry_failed.sh git clone ${ESP_IDF_TEMPLATE_GIT} - # Try to use the same branch name for esp-idf-template that we're - # using on esp-idf. If it doesn't exist then just stick to the default branch - - python $CHECKOUT_REF_SCRIPT esp-idf-template esp-idf-template - - cd esp-idf-template - - export PATH="$IDF_PATH/tools:$PATH" - - export EXTRA_CFLAGS=${PEDANTIC_CFLAGS} - - export EXTRA_CXXFLAGS=${PEDANTIC_CXXFLAGS} - - # CONFIG_COMPILER_OPTIMIZATION_DEFAULT with flag -Og - - echo "CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y" > sdkconfig.defaults - - echo "CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG=y" >> sdkconfig.defaults - - *build_with_make_and_cmake - - # CONFIG_COMPILER_OPTIMIZATION_NONE with flag -O0 - - echo "CONFIG_COMPILER_OPTIMIZATION_NONE=y" > sdkconfig.defaults - - echo "CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE=y" >> sdkconfig.defaults - - *build_with_make_and_cmake - - # CONFIG_COMPILER_OPTIMIZATION_SIZE with flag -Os - - echo "CONFIG_COMPILER_OPTIMIZATION_SIZE=y" > sdkconfig.defaults - - echo "CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y" >> sdkconfig.defaults - - *build_with_make_and_cmake - - # CONFIG_COMPILER_OPTIMIZATION_PERF with flag -O2 - - echo "CONFIG_COMPILER_OPTIMIZATION_PERF=y" > sdkconfig.defaults - - echo "CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF=y" >> sdkconfig.defaults - - *build_with_make_and_cmake - - # Same as above, but also disable assertions. - - echo "CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y" >> sdkconfig.defaults - # Don't error out on -Wunused, when assertions are disabled - - export EXTRA_CFLAGS=${PEDANTIC_CFLAGS/-Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function/} - - export EXTRA_CXXFLAGS=${PEDANTIC_CXXFLAGS/-Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function/} - - *build_with_make_and_cmake - - export EXTRA_CFLAGS=${PEDANTIC_CFLAGS} - - export EXTRA_CXXFLAGS=${PEDANTIC_CXXFLAGS} - - # Check if there are any stray printf/ets_printf references in WiFi libs - - pushd ../components/esp_wifi/lib - - for dir in esp32 esp32s2; do test $(xtensa-esp32-elf-nm $dir/*.a | grep -w printf | wc -l) -eq 0; done; - - for dir in esp32 esp32s2; do test $(xtensa-esp32-elf-nm $dir/*.a | grep -w ets_printf | wc -l) -eq 0; done; - - popd + BUILD_COMMAND_ARGS: "-p" check_public_headers: stage: pre_check diff --git a/tools/ci/executable-list.txt b/tools/ci/executable-list.txt index 7d9cc904b1..a45275aa09 100644 --- a/tools/ci/executable-list.txt +++ b/tools/ci/executable-list.txt @@ -35,6 +35,7 @@ tools/build_apps.py tools/check_kconfigs.py tools/check_python_dependencies.py tools/ci/apply_bot_filter.py +tools/ci/build_template_app.sh tools/ci/check-executable.sh tools/ci/check-line-endings.sh tools/ci/check_build_warnings.py diff --git a/tools/find_build_apps/common.py b/tools/find_build_apps/common.py index 2aa92a5974..7b0b1c95ef 100644 --- a/tools/find_build_apps/common.py +++ b/tools/find_build_apps/common.py @@ -147,7 +147,8 @@ class BuildItem(object): return self._expand(self._build_log_path) def __repr__(self): - return "Build app {} for target {}, sdkconfig {} in {}".format( + return "({}) Build app {} for target {}, sdkconfig {} in {}".format( + self.build_system, self.app_dir, self.target, self.sdkconfig_path or "(default)",