From 30083e07bea405b0d776bce001e776698fb409f4 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Tue, 1 Jul 2025 10:30:38 +0200 Subject: [PATCH 1/8] refactor(esptool_py): Re-evalute dependencies of esptool_py This commit establishes the foundation for making the esptool_py component idempotent. The following changes are made in this commit: - Removes unnecessary dependency of esp_wifi component on esptool_py. - Add missing esptool_py dependencies to components which directly use esptool_py specific functions or variables but do not declare a public or private dependency. --- components/bootloader_support/CMakeLists.txt | 6 +++--- components/esp_phy/CMakeLists.txt | 2 +- components/esp_tee/CMakeLists.txt | 2 +- components/esp_wifi/CMakeLists.txt | 2 +- components/fatfs/CMakeLists.txt | 2 +- components/nvs_flash/CMakeLists.txt | 2 +- components/spiffs/CMakeLists.txt | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index bae865dc3b..4e477f6b59 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -28,7 +28,7 @@ if(esp_tee_build) idf_component_register(SRCS ${tee_srcs} INCLUDE_DIRS ${tee_inc_dirs} - PRIV_REQUIRES efuse esp_app_format) + PRIV_REQUIRES efuse esp_app_format esptool_py) return() endif() @@ -72,7 +72,7 @@ endif() if(BOOTLOADER_BUILD OR CONFIG_APP_BUILD_TYPE_RAM) set(include_dirs "include" "bootloader_flash/include" "private_include") - set(priv_requires micro-ecc spi_flash efuse esp_bootloader_format esp_app_format) + set(priv_requires micro-ecc spi_flash efuse esp_bootloader_format esp_app_format esptool_py) list(APPEND srcs "src/bootloader_init.c" "src/bootloader_clock_loader.c" @@ -89,7 +89,7 @@ else() set(include_dirs "include" "bootloader_flash/include") set(priv_include_dirs "private_include") # heap is required for `heap_memory_layout.h` header - set(priv_requires spi_flash mbedtls efuse heap esp_bootloader_format esp_app_format) + set(priv_requires spi_flash mbedtls efuse heap esp_bootloader_format esp_app_format esptool_py) endif() if(BOOTLOADER_BUILD) diff --git a/components/esp_phy/CMakeLists.txt b/components/esp_phy/CMakeLists.txt index 24defd87b1..fe5d19423b 100644 --- a/components/esp_phy/CMakeLists.txt +++ b/components/esp_phy/CMakeLists.txt @@ -55,7 +55,7 @@ endif() idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "include" "${idf_target}/include" - PRIV_REQUIRES nvs_flash esp_driver_gpio efuse esp_timer esp_wifi + PRIV_REQUIRES nvs_flash esp_driver_gpio efuse esp_timer esp_wifi esptool_py LDFRAGMENTS "${ldfragments}" EMBED_FILES ${embed_files} ) diff --git a/components/esp_tee/CMakeLists.txt b/components/esp_tee/CMakeLists.txt index 21a70d6b8c..a0c6a6f248 100644 --- a/components/esp_tee/CMakeLists.txt +++ b/components/esp_tee/CMakeLists.txt @@ -73,7 +73,7 @@ else() idf_component_register(INCLUDE_DIRS include SRCS ${srcs} - PRIV_REQUIRES efuse esp_security esp_system spi_flash) + PRIV_REQUIRES efuse esp_security esp_system spi_flash esptool_py) if(CONFIG_SECURE_ENABLE_TEE) set(EXTRA_LINK_FLAGS) diff --git a/components/esp_wifi/CMakeLists.txt b/components/esp_wifi/CMakeLists.txt index 99984c96e2..2683cf9a02 100644 --- a/components/esp_wifi/CMakeLists.txt +++ b/components/esp_wifi/CMakeLists.txt @@ -60,7 +60,7 @@ idf_component_register(SRCS "${srcs}" INCLUDE_DIRS "include" "include/local" "wifi_apps/include" "wifi_apps/nan_app/include" REQUIRES esp_event esp_phy esp_netif - PRIV_REQUIRES esptool_py esp_pm esp_timer nvs_flash + PRIV_REQUIRES esp_pm esp_timer nvs_flash wpa_supplicant hal lwip esp_coex PRIV_INCLUDE_DIRS ../wpa_supplicant/src/ ../wpa_supplicant/esp_supplicant/src/ wifi_apps/roaming_app/include diff --git a/components/fatfs/CMakeLists.txt b/components/fatfs/CMakeLists.txt index f641ca860a..dddcb8905f 100644 --- a/components/fatfs/CMakeLists.txt +++ b/components/fatfs/CMakeLists.txt @@ -24,7 +24,7 @@ else() list(APPEND requires "sdmmc" "esp_driver_sdmmc" "esp_driver_sdspi") - list(APPEND priv_requires "vfs" "esp_driver_gpio") + list(APPEND priv_requires "vfs" "esp_driver_gpio" "esptool_py") endif() idf_component_register(SRCS ${srcs} diff --git a/components/nvs_flash/CMakeLists.txt b/components/nvs_flash/CMakeLists.txt index 693e510de9..8872c5ea19 100644 --- a/components/nvs_flash/CMakeLists.txt +++ b/components/nvs_flash/CMakeLists.txt @@ -63,7 +63,7 @@ else() if(${target} STREQUAL "linux") set(priv_requires spi_flash) else() - set(priv_requires spi_flash newlib) + set(priv_requires spi_flash newlib esptool_py) endif() idf_component_register(SRCS "${srcs}" diff --git a/components/spiffs/CMakeLists.txt b/components/spiffs/CMakeLists.txt index ed85c16ac1..e53ea7166d 100644 --- a/components/spiffs/CMakeLists.txt +++ b/components/spiffs/CMakeLists.txt @@ -9,7 +9,7 @@ set(original_srcs "spiffs/src/spiffs_cache.c" list(APPEND srcs "spiffs_api.c" ${original_srcs}) if(NOT ${target} STREQUAL "linux") - list(APPEND pr bootloader_support esptool_py vfs) + list(APPEND pr bootloader_support vfs esptool_py) list(APPEND srcs "esp_spiffs.c") endif() From ef4d6462e21112fb7e3a64970ea499149d712186 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Tue, 1 Jul 2025 14:48:34 +0200 Subject: [PATCH 2/8] refactor(esptool_py): Move flash target creation to project level and add utility functions This commit refactors the esptool_py component to provide utility functions for flash target management instead of creating the targets directly. Flash target creation is now moved to the project level in build.cmake file when idf_build_executable() runs. The following changes were done in this commit: - Added __esptool_py_setup_tools(), __esptool_py_setup_estool_py_args() and __ensure_esptool_py_setup() functions to centralize esptool_py setup. - Added __esptool_py_setup_main_flash_target() which is called by idf_build_executable() to create the flash targets. - Updated esptool_py_flash_target(), esptool_py_custom_target() to accept an optional FILENAME_PREFIX argument to enable creation of build artifacts based on custom names. - Create placeholder flash targets early in the build process when idf_build_process() is called for components to add dependencies on these targets. - Moved app-flash target creation from esptool_py/CMakeLists.txt to build.cmake. - Added function description to esptool_py functions. --- components/app_update/CMakeLists.txt | 4 +- components/esp_tee/CMakeLists.txt | 4 +- components/esptool_py/CMakeLists.txt | 6 - components/esptool_py/project_include.cmake | 339 ++++++++++++++++++-- components/nvs_flash/project_include.cmake | 4 +- tools/cmake/build.cmake | 56 ++++ 6 files changed, 371 insertions(+), 42 deletions(-) diff --git a/components/app_update/CMakeLists.txt b/components/app_update/CMakeLists.txt index 96806d30f8..6c910d71cf 100644 --- a/components/app_update/CMakeLists.txt +++ b/components/app_update/CMakeLists.txt @@ -29,7 +29,9 @@ if(NOT BOOTLOADER_BUILD) add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file}) add_dependencies(flash blank_ota_data) - add_dependencies(encrypted-flash blank_ota_data) + if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + add_dependencies(encrypted-flash blank_ota_data) + endif() set(otatool_py "${python}" "${COMPONENT_DIR}/otatool.py") diff --git a/components/esp_tee/CMakeLists.txt b/components/esp_tee/CMakeLists.txt index a0c6a6f248..e3df1b47ce 100644 --- a/components/esp_tee/CMakeLists.txt +++ b/components/esp_tee/CMakeLists.txt @@ -50,7 +50,9 @@ else() add_custom_target(blank_tee_ota_data ALL DEPENDS ${blank_tee_otadata_file}) add_dependencies(flash blank_tee_ota_data) - add_dependencies(encrypted-flash blank_tee_ota_data) + if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + add_dependencies(encrypted-flash blank_tee_ota_data) + endif() partition_table_get_partition_info(tee_otadata_part "--partition-type data --partition-subtype tee_ota" "name") diff --git a/components/esptool_py/CMakeLists.txt b/components/esptool_py/CMakeLists.txt index 955c63a0fa..925cb59550 100644 --- a/components/esptool_py/CMakeLists.txt +++ b/components/esptool_py/CMakeLists.txt @@ -15,13 +15,7 @@ idf_component_register(REQUIRES bootloader PRIV_REQUIRES partition_table) if(NOT BOOTLOADER_BUILD) idf_build_get_property(build_dir BUILD_DIR) - if(CONFIG_APP_BUILD_GENERATE_BINARIES) - partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset") - esptool_py_custom_target(app-flash app "app") - esptool_py_flash_target_image(app-flash app "${app_partition_offset}" "${build_dir}/${PROJECT_BIN}") - esptool_py_flash_target_image(flash app "${app_partition_offset}" "${build_dir}/${PROJECT_BIN}") - endif() # If anti-rollback option is set then factory partition should not be in Partition Table. # In this case, should be used the partition table with two ota app without the factory. diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake index 24db465076..e3997f139d 100644 --- a/components/esptool_py/project_include.cmake +++ b/components/esptool_py/project_include.cmake @@ -274,6 +274,16 @@ idf_component_set_property(esptool_py FLASH_ARGS "${esptool_flash_main_args}") idf_component_set_property(esptool_py FLASH_SUB_ARGS "--flash_mode ${ESPFLASHMODE} --flash_freq ${ESPFLASHFREQ} \ --flash_size ${ESPFLASHSIZE}") +# esptool_py_partition_needs_encryption +# +# @brief Determine if a partition needs to be encrypted when flash encryption is enabled. +# +# When flash encryption is enabled in development mode, this function checks +# the type and subtype of a partition to determine if its contents should be +# encrypted before flashing. +# +# @param[out] retencrypted Variable to store the result (TRUE if encryption needed, FALSE otherwise) +# @param[in] partition_name Name of the partition to check function(esptool_py_partition_needs_encryption retencrypted partition_name) # Check if encryption is enabled if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) @@ -311,6 +321,17 @@ function(esptool_py_partition_needs_encryption retencrypted partition_name) endfunction() +# esptool_py_flash_to_partition +# +# @brief Add a binary image to be flashed to a specific partition. +# +# This function is a convenience wrapper that automatically determines the partition +# offset and encryption requirements, then calls esptool_py_flash_target_image() with +# the appropriate parameters. It simplifies flashing to named partitions. +# +# @param[in] target_name Name of the flash target to add the image to +# @param[in] partition_name Name of the partition where the image should be flashed +# @param[in] binary_path Path to the binary file to flash function(esptool_py_flash_to_partition target_name partition_name binary_path) # Retrieve the offset for the partition to flash the image on partition_table_get_partition_info(offset "--partition-name ${partition_name}" "offset") @@ -333,12 +354,21 @@ function(esptool_py_flash_to_partition target_name partition_name binary_path) ${binary_path} ${option}) endfunction() -# This function takes a fifth optional named parameter: "ALWAYS_PLAINTEXT". As -# its name states, it marks whether the image should be flashed as plain text or -# not. If build macro CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT is set and -# this parameter is provided, then the image will be flashed as plain text -# (not encrypted) on the target. This parameter will be ignored if build macro -# CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT is not set. +# esptool_py_flash_target_image +# +# @brief Add a binary image to a flash target at a specific offset. +# +# This function adds a binary image to the specified flash target, which will be +# included when the target is executed. It handles both plain and encrypted flash +# scenarios, automatically setting up the appropriate target properties. +# +# @param[in] target_name Name of the flash target to add the image to +# @param[in] image_name Logical name for the image (used in flasher_args.json) +# @param[in] offset Flash offset where the image should be written (in hex format like 0x1000) +# @param[in] image Path to the binary file to flash +# @param[in, optional] ALWAYS_PLAINTEXT (option) Force the image to be flashed as plain text +# even when flash encryption is enabled. Ignored if flash encryption +# is not configured. function(esptool_py_flash_target_image target_name image_name offset image) set(options ALWAYS_PLAINTEXT) idf_build_get_property(build_dir BUILD_DIR) @@ -391,21 +421,56 @@ function(esptool_py_flash_target_image target_name image_name offset image) endfunction() +# esptool_py_flash_target +# +# @brief Create a flash target that can flash multiple images using esptool.py. +# +# This function is the core of the flashing mechanism. It creates a custom target +# and attaches the actual esptool.py command to it as a POST_BUILD step. This +# ensures that the flash command only runs after all of the target's dependencies +# (like binary generation) have been successfully built. +# +# It works by generating an argument file (`_args`) that contains all the +# necessary parameters for esptool.py. This file's content is constructed using +# CMake generator expressions, which are resolved at build time. This allows the +# final list of binaries to be flashed to be collected from properties on the +# target. +# +# If flash encryption is enabled, it also creates a corresponding `encrypted-` +# target, which handles the logic for encrypting all or a subset of the binaries. +# +# @param[in] target_name Name of the flash target to create +# @param[in] main_args Main esptool.py arguments (before write_flash command) +# @param[in] sub_args Sub-arguments for write_flash command (flash mode, frequency, size) +# @param[in, optional] FILENAME_PREFIX (single value) Prefix for generated argument files. +# If not specified, uses target_name as prefix. +# @param[in, optional] ALWAYS_PLAINTEXT (option) Force all images to be flashed as plain text. function(esptool_py_flash_target target_name main_args sub_args) - set(single_value OFFSET IMAGE) # template file to use to be able to - # flash the image individually using esptool + set(single_value OFFSET IMAGE FILENAME_PREFIX) # template file to use to be able to + # flash the image individually using esptool set(options ALWAYS_PLAINTEXT) cmake_parse_arguments(_ "${options}" "${single_value}" "" "${ARGN}") + if(__FILENAME_PREFIX) + set(filename_prefix ${__FILENAME_PREFIX}) + else() + set(filename_prefix ${target_name}) + endif() + idf_build_get_property(idf_path IDF_PATH) idf_build_get_property(build_dir BUILD_DIR) idf_component_get_property(esptool_py_dir esptool_py COMPONENT_DIR) + idf_component_get_property(esptool_py_cmd esptool_py ESPTOOLPY_CMD) - add_custom_target(${target_name} + if(NOT TARGET ${target_name}) + add_custom_target(${target_name}) + endif() + + add_custom_command(TARGET ${target_name} POST_BUILD COMMAND ${CMAKE_COMMAND} -D "IDF_PATH=${idf_path}" - -D "SERIAL_TOOL=${ESPTOOLPY}" - -D "SERIAL_TOOL_ARGS=${main_args};write_flash;@${target_name}_args" + -D "SERIAL_TOOL=${esptool_py_cmd}" + -D "SERIAL_TOOL_ARGS=${main_args};write_flash;@${filename_prefix}_args" -D "WORKING_DIRECTORY=${build_dir}" -P ${esptool_py_dir}/run_serial_tool.cmake WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} @@ -421,13 +486,13 @@ function(esptool_py_flash_target target_name main_args sub_args) $,\n>") # Write the previous expression to the target_name_args.in file - file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_args.in" + file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${filename_prefix}_args.in" CONTENT "${flash_args_content}") # Generate the actual expression value from the content of the file # we just wrote - file(GENERATE OUTPUT "${build_dir}/${target_name}_args" - INPUT "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_args.in") + file(GENERATE OUTPUT "${build_dir}/${filename_prefix}_args" + INPUT "${CMAKE_CURRENT_BINARY_DIR}/${filename_prefix}_args.in") # Check if the target has to be plain text or not, depending on the macro # CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT and the parameter @@ -443,11 +508,15 @@ $,\n>") # For example, if 'target_name' is app-flash and 'encrypted' is TRUE, # 'build' directory will contain a file name 'encrypted_app-flash_args' if(${encrypted}) - add_custom_target(encrypted-${target_name} + if(NOT TARGET encrypted-${target_name}) + add_custom_target(encrypted-${target_name}) + endif() + + add_custom_command(TARGET encrypted-${target_name} POST_BUILD COMMAND ${CMAKE_COMMAND} -D "IDF_PATH=${idf_path}" - -D "SERIAL_TOOL=${ESPTOOLPY}" - -D "SERIAL_TOOL_ARGS=${main_args};write_flash;@encrypted_${target_name}_args" + -D "SERIAL_TOOL=${esptool_py_cmd}" + -D "SERIAL_TOOL_ARGS=${main_args};write_flash;@encrypted_${filename_prefix}_args" -D "WORKING_DIRECTORY=${build_dir}" -P ${esptool_py_dir}/run_serial_tool.cmake WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} @@ -493,12 +562,12 @@ ${encrypted_files}") # The expression is ready to be generated, write it to the file which # extension is .in - file_generate("${CMAKE_CURRENT_BINARY_DIR}/encrypted_${target_name}_args.in" + file_generate("${CMAKE_CURRENT_BINARY_DIR}/encrypted_${filename_prefix}_args.in" CONTENT "${flash_args_content}") # Generate the actual string from the content of the file we just wrote - file_generate("${build_dir}/encrypted_${target_name}_args" - INPUT "${CMAKE_CURRENT_BINARY_DIR}/encrypted_${target_name}_args.in") + file_generate("${build_dir}/encrypted_${filename_prefix}_args" + INPUT "${CMAKE_CURRENT_BINARY_DIR}/encrypted_${filename_prefix}_args.in") else() fail_target(encrypted-${target_name} "Error: The target encrypted-${target_name} requires" "CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT to be enabled.") @@ -507,46 +576,250 @@ ${encrypted_files}") endfunction() +# esptool_py_custom_target +# +# @brief Create a custom flash target with dependencies. +# +# This function creates a flash target that depends on other build targets. +# +# @param[in] target_name Name of the flash target to create +# @param[in] flasher_filename Base name for generated flasher argument files +# @param[in] dependencies List of CMake targets that this flash target depends on +# @param[in, optional] FILENAME_PREFIX (single value) Custom prefix for argument files. +# If not specified, uses target_name as prefix. function(esptool_py_custom_target target_name flasher_filename dependencies) + __ensure_esptool_py_setup() + idf_component_get_property(main_args esptool_py FLASH_ARGS) idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS) idf_build_get_property(build_dir BUILD_DIR) - esptool_py_flash_target(${target_name} "${main_args}" "${sub_args}") + # Parse optional arguments like FILENAME_PREFIX. + set(one_value_args FILENAME_PREFIX) + cmake_parse_arguments(arg "" "${one_value_args}" "" ${ARGN}) + + # Call the underlying flash target function, explicitly passing the prefix if it exists. + if(arg_FILENAME_PREFIX) + esptool_py_flash_target(${target_name} "${main_args}" "${sub_args}" FILENAME_PREFIX "${arg_FILENAME_PREFIX}") + set(filename_prefix ${arg_FILENAME_PREFIX}) + else() + esptool_py_flash_target(${target_name} "${main_args}" "${sub_args}") + set(filename_prefix ${target_name}) + endif() # Copy the file to flash_xxx_args for compatibility for select target file_generate("${build_dir}/flash_${flasher_filename}_args" - INPUT "${build_dir}/${target_name}_args") + INPUT "${build_dir}/${filename_prefix}_args") add_dependencies(${target_name} ${dependencies}) if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) file_generate("${build_dir}/flash_encrypted_${flasher_filename}_args" - INPUT "${build_dir}/encrypted_${target_name}_args") + INPUT "${build_dir}/encrypted_${filename_prefix}_args") add_dependencies(encrypted-${target_name} ${dependencies}) endif() endfunction() -if(NOT non_os_build) - set(flash_deps "") +# __esptool_py_setup_tools +# +# @brief Sets up esptool.py, espsecure.py, and espefuse.py tool commands. +# +# This function retrieves the necessary paths and Python interpreter, then +# constructs the full command-line strings for `esptool.py`, `espsecure.py`, +# and `espefuse.py`. It stores these commands as properties of the `esptool_py` +# component for later use by other functions or components. +function(__esptool_py_setup_tools) + idf_build_get_property(target IDF_TARGET) + idf_build_get_property(python PYTHON) + idf_component_get_property(esptool_py_dir esptool_py COMPONENT_DIR) - if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT) - list(APPEND flash_deps "partition_table_bin") + set(esptool_py_cmd ${python} "$ENV{ESPTOOL_WRAPPER}" "${esptool_py_dir}/esptool/esptool.py" --chip ${target}) + idf_component_set_property(esptool_py ESPTOOLPY_CMD "${esptool_py_cmd}") + + set(espsecure_py_cmd ${python} "${esptool_py_dir}/esptool/espsecure.py") + idf_component_set_property(esptool_py ESPSECUREPY_CMD "${espsecure_py_cmd}") + + set(espefuse_py_cmd ${python} "${esptool_py_dir}/esptool/espefuse.py") + idf_component_set_property(esptool_py ESPEFUSEPY_CMD "${espefuse_py_cmd}") +endfunction() + +# __esptool_py_setup_esptool_py_args +# +# @brief Sets up esptool.py arguments for elf2image and flash targets. +# +# This function determines the appropriate flash mode, frequency, and size based +# on the project configuration (Kconfig values). It assembles argument lists +# for both the `elf2image` operation (converting ELF to BIN), for general +# flashing commands and for creating the flasher_args.json file. +# These argument lists are then stored as properties of the `esptool_py` +# component for consistent use across the build system. +function(__esptool_py_setup_esptool_py_args) + if(NOT CONFIG_APP_BUILD_TYPE_RAM AND CONFIG_APP_BUILD_GENERATE_BINARIES) + if(CONFIG_BOOTLOADER_FLASH_DC_AWARE) + # When set flash frequency to 120M, must keep 1st bootloader work under ``DOUT`` mode + # because on some flash chips, 120M will modify the status register, + # which will make ROM won't work. + # This change intends to be for esptool only and the bootloader should keep use + # ``DOUT`` mode. + set(ESPFLASHMODE "dout") + message("Note: HPM is enabled for the flash, force the ROM bootloader into DOUT mode for stable boot on") + else() + set(ESPFLASHMODE ${CONFIG_ESPTOOLPY_FLASHMODE}) + endif() + set(ESPFLASHFREQ ${CONFIG_ESPTOOLPY_FLASHFREQ}) + set(ESPFLASHSIZE ${CONFIG_ESPTOOLPY_FLASHSIZE}) + + set(esptool_elf2image_args + --flash_mode ${ESPFLASHMODE} + --flash_freq ${ESPFLASHFREQ} + --flash_size ${ESPFLASHSIZE} + ) + + if(BOOTLOADER_BUILD AND CONFIG_SECURE_BOOT_V2_ENABLED) + # The bootloader binary needs to be 4KB aligned in order to append a secure boot V2 signature block. + # If CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES is NOT set, the bootloader + # image generated is not 4KB aligned for external HSM to sign it readily. + # Following esptool option --pad-to-size 4KB generates a 4K aligned bootloader image. + # In case of signing during build, espsecure.py "sign_data" operation handles the 4K alignment of the image. + if(NOT CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + list(APPEND esptool_elf2image_args --pad-to-size 4KB) + endif() + endif() + + set(MMU_PAGE_SIZE ${CONFIG_MMU_PAGE_MODE}) + + if(NOT BOOTLOADER_BUILD) + list(APPEND esptool_elf2image_args --elf-sha256-offset 0xb0) + # For chips that support configurable MMU page size feature + # If page size is configured to values other than the default "64KB" in menuconfig, + # then we need to pass the actual size to flash-mmu-page-size arg + if(NOT MMU_PAGE_SIZE STREQUAL "64KB") + list(APPEND esptool_elf2image_args --flash-mmu-page-size ${MMU_PAGE_SIZE}) + endif() + endif() + + if(NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION AND NOT BOOTLOADER_BUILD) + if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) + list(APPEND esptool_elf2image_args --secure-pad) + elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME) + list(APPEND esptool_elf2image_args --secure-pad-v2) + endif() + endif() endif() - if(CONFIG_APP_BUILD_GENERATE_BINARIES) - list(APPEND flash_deps "app") + if(CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE) + # Set ESPFLASHSIZE to 'detect' *after* esptool_elf2image_args are generated, + # as elf2image can't have 'detect' as an option... + set(ESPFLASHSIZE detect) endif() - if(CONFIG_APP_BUILD_BOOTLOADER) - list(APPEND flash_deps "bootloader") + if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) + set(ESPFLASHSIZE keep) endif() - esptool_py_custom_target(flash project "${flash_deps}") -endif() + # We still set "--min-rev" to keep the app compatible with older bootloaders where this field is controlled. + if(CONFIG_IDF_TARGET_ESP32) + # for this chip min_rev is major revision + math(EXPR min_rev "${CONFIG_ESP_REV_MIN_FULL} / 100") + endif() + if(CONFIG_IDF_TARGET_ESP32C3) + # for this chip min_rev is minor revision + math(EXPR min_rev "${CONFIG_ESP_REV_MIN_FULL} % 100") + endif() + + if(min_rev) + list(APPEND esptool_elf2image_args --min-rev ${min_rev}) + endif() + + list(APPEND esptool_elf2image_args --min-rev-full ${CONFIG_ESP_REV_MIN_FULL}) + list(APPEND esptool_elf2image_args --max-rev-full ${CONFIG_ESP_REV_MAX_FULL}) + + # Save esptool_elf2image_args to component property + idf_component_set_property(esptool_py ESPTOOL_PY_ELF2IMAGE_ARGS "${esptool_elf2image_args}") + + set(esptool_flash_main_args "--before=${CONFIG_ESPTOOLPY_BEFORE}") + + if(CONFIG_SECURE_BOOT OR CONFIG_SECURE_FLASH_ENC_ENABLED) + # If security enabled then override post flash option + list(APPEND esptool_flash_main_args "--after=no_reset") + else() + list(APPEND esptool_flash_main_args "--after=${CONFIG_ESPTOOLPY_AFTER}") + endif() + + if(CONFIG_ESPTOOLPY_NO_STUB) + list(APPEND esptool_flash_main_args "--no-stub") + endif() + + # Save flash arguments to component property + idf_component_set_property(esptool_py FLASH_ARGS "${esptool_flash_main_args}") + idf_component_set_property(esptool_py FLASH_SUB_ARGS + "--flash_mode ${ESPFLASHMODE} --flash_freq ${ESPFLASHFREQ} --flash_size ${ESPFLASHSIZE}") + + # Save arguments for flasher_args.json + idf_component_set_property(esptool_py ESPFLASHMODE "${ESPFLASHMODE}") + idf_component_set_property(esptool_py ESPFLASHFREQ "${ESPFLASHFREQ}") + idf_component_set_property(esptool_py ESPFLASHSIZE "${ESPFLASHSIZE}") +endfunction() + +# __ensure_esptool_py_setup +# +# @brief Ensures that the esptool.py setup functions have been called once. +# +# This function acts as an initializer. It checks if the esptool_py +# setup has already been performed by checking a component property. If not, it +# calls __esptool_py_setup_tools() and __esptool_py_setup_esptool_py_args() +# to configure the component. +function(__ensure_esptool_py_setup) + idf_component_get_property(esptool_py_setup_done esptool_py _ESPTOOL_PY_SETUP_DONE) + if(NOT esptool_py_setup_done) + __esptool_py_setup_tools() + __esptool_py_setup_esptool_py_args() + idf_component_set_property(esptool_py _ESPTOOL_PY_SETUP_DONE TRUE) + endif() +endfunction() + + +# __esptool_py_setup_main_flash_target +# +# @brief Sets up the main `flash` target and its dependencies. +# +# This function creates the main `flash` target, which is used to flash multiple +# images to the target device. It determines the dependencies for a full +# project flash (bootloader, partition table, the main app) and then calls +# +function(__esptool_py_setup_main_flash_target) + __ensure_esptool_py_setup() + + idf_build_get_property(non_os_build NON_OS_BUILD) + + if(NOT non_os_build) + set(flash_deps "") + + if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT) + list(APPEND flash_deps "partition_table_bin") + endif() + + if(CONFIG_APP_BUILD_GENERATE_BINARIES) + list(APPEND flash_deps "app") + endif() + + if(CONFIG_APP_BUILD_BOOTLOADER) + list(APPEND flash_deps "bootloader") + endif() + + # Create the flash target. If encryption is enabled, it will also create + # an encrypted-flash target. + esptool_py_custom_target(flash project "${flash_deps}" FILENAME_PREFIX "flash") + endif() +endfunction() # Adds espefuse functions for global use idf_component_get_property(esptool_py_dir esptool_py COMPONENT_DIR) include(${esptool_py_dir}/espefuse.cmake) + +# Initialize the esptool_py component. +# This ensures that all its properties are set before any other components that +# depend on it try to access them. +__ensure_esptool_py_setup() diff --git a/components/nvs_flash/project_include.cmake b/components/nvs_flash/project_include.cmake index b465024a2b..5503753c54 100644 --- a/components/nvs_flash/project_include.cmake +++ b/components/nvs_flash/project_include.cmake @@ -53,7 +53,9 @@ function(nvs_create_partition_image partition csv) if(arg_FLASH_IN_PROJECT) esptool_py_flash_to_partition(flash "${partition}" "${image_file}") add_dependencies(flash nvs_${partition}_bin) - add_dependencies(encrypted-flash nvs_${partition}_bin) + if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + add_dependencies(encrypted-flash nvs_${partition}_bin) + endif() endif() else() set(message diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 6f77a72278..76dfdde8c8 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -469,6 +469,22 @@ macro(__build_process_project_includes) endforeach() endmacro() +# +# Add placeholder flash targets to the build. +# This is used by components to declare dependencies on the flash target. +# +macro(__build_create_flash_targets) + if(NOT TARGET flash) + add_custom_target(flash) + endif() + + # When flash encryption is enabled, a corresponding 'encrypted-flash' target will be created. + idf_build_get_config(encrypted_flash_enabled CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) + if(encrypted_flash_enabled AND NOT TARGET encrypted-flash) + add_custom_target(encrypted-flash) + endif() +endmacro() + # # Utility macro for setting default property value if argument is not specified # for idf_build_process(). @@ -713,6 +729,13 @@ macro(idf_build_process target) set(ESP_PLATFORM 1) idf_build_set_property(COMPILE_DEFINITIONS "ESP_PLATFORM" APPEND) + # Create flash targets early so components can attach images to them. + # These targets will be appended with actual esptool.py command later + # in the build process when __idf_build_setup_flash_targets() is called. + if(NOT BOOTLOADER_BUILD AND NOT ESP_TEE_BUILD AND NOT "${target}" STREQUAL "linux") + __build_create_flash_targets() + endif() + # Perform component processing (inclusion of project_include.cmake, adding component # subdirectories, creating library targets, linking libraries, etc.) __build_process_project_includes() @@ -752,6 +775,39 @@ function(idf_build_executable elf) # Add dependency of the build target to the executable add_dependencies(${elf} __idf_build_target) + + # Set up esptool_py flash targets + # This must be done after the executable properties are set but before the function exits + # so that all components have had a chance to add their images to the phony flash targets + idf_build_get_property(bootloader_build BOOTLOADER_BUILD) + idf_build_get_property(esp_tee_build ESP_TEE_BUILD) + idf_build_get_property(target IDF_TARGET) + + if(NOT bootloader_build AND NOT esp_tee_build AND NOT "${target}" STREQUAL "linux") + # Check if esptool_py component is available before calling its functions + if(TARGET idf::esptool_py) + # The following block is placed here to ensure that the application binary is added to the 'flash' + # target's properties *before* __esptool_py_setup_main_flash_target is called. + # This is because __esptool_py_setup_main_flash_target copies properties from the 'flash' + # target to an internal '_flash_impl' target, from which the final 'flash_args' file is generated. + # If the app target is not added to the 'flash' target *before* the properties are copied, + # the app binary will be missing from the final 'flash_args' file. + # + # Set up app-flash and flash targets. The app-flash target is specifically for flashing + # just the application, while the flash target is for flashing the entire system. + if(CONFIG_APP_BUILD_GENERATE_BINARIES) + idf_build_get_property(build_dir BUILD_DIR) + idf_build_get_property(project_bin PROJECT_BIN) + partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset") + esptool_py_custom_target(app-flash app "app") + + esptool_py_flash_target_image(app-flash app "${app_partition_offset}" "${build_dir}/${project_bin}") + esptool_py_flash_target_image(flash app "${app_partition_offset}" "${build_dir}/${project_bin}") + endif() + + __esptool_py_setup_main_flash_target() + endif() + endif() endfunction() # idf_build_get_config From 7c75795a0be199e69d1d9c780077c64343be0cb4 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Wed, 2 Jul 2025 10:25:48 +0200 Subject: [PATCH 3/8] refactor(esptool_py): Move binary generation to project level and add utility functions This commit refactors the esptool_py component to provide utility functions for binary file generation targets instead of creating the targets. Binary generation targets are now moved to the respective projects. The following changes were done in this commit: - Added __idf_build_binary() function to esptool_py to create the binary file generation target. - Added __idf_build_secure_binary() as the secure boot equivalent of the above function. - Top level project build now creates its own binary targets in idf_build_executable() in build.cmake. - Bootloader and esp_tee subprojects create their binary file generation targets in their respective CMakeLists.txt files. - All post-build targets such as the app_size_check target are now created by the respective projects and not esptool_py. - General clean-up of the esptool_py cmake files. --- .../bootloader/subproject/CMakeLists.txt | 93 +++++--- components/esp_tee/subproject/CMakeLists.txt | 68 +++--- components/esptool_py/CMakeLists.txt | 36 --- components/esptool_py/project_include.cmake | 214 ++++++++++++------ tools/cmake/build.cmake | 91 ++++++-- 5 files changed, 322 insertions(+), 180 deletions(-) diff --git a/components/bootloader/subproject/CMakeLists.txt b/components/bootloader/subproject/CMakeLists.txt index 60accb480f..068b5b09e8 100644 --- a/components/bootloader/subproject/CMakeLists.txt +++ b/components/bootloader/subproject/CMakeLists.txt @@ -75,16 +75,36 @@ idf_build_set_property(COMPILE_DEFINITIONS "BOOTLOADER_BUILD=1" APPEND) idf_build_set_property(COMPILE_DEFINITIONS "NON_OS_BUILD=1" APPEND) idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND) +# Set up the bootloader binary generation targets +set(PROJECT_BIN "bootloader.bin") +if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + set(bootloader_unsigned_bin "bootloader-unsigned.bin") +else() + set(bootloader_unsigned_bin "${PROJECT_BIN}") +endif() + +# Set the final binary name as a project property +idf_build_set_property(PROJECT_BIN "${PROJECT_BIN}") + +# Generate the unsigned binary from the ELF file. +if(CONFIG_APP_BUILD_GENERATE_BINARIES) + set(target_name "gen_bootloader_binary") + __idf_build_binary("${bootloader_unsigned_bin}" "${target_name}") +endif() + idf_component_get_property(main_args esptool_py FLASH_ARGS) idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS) +idf_component_get_property(esptool_py_cmd esptool_py ESPTOOLPY_CMD) +idf_component_get_property(espsecure_py_cmd esptool_py ESPSECUREPY_CMD) +idf_component_get_property(espefuse_py_cmd esptool_py ESPEFUSEPY_CMD) # String for printing flash command string(REPLACE ";" " " esptoolpy_write_flash - "${ESPTOOLPY} --port=(PORT) --baud=(BAUD) ${main_args} " + "${esptool_py_cmd} --port=(PORT) --baud=(BAUD) ${main_args} " "write_flash ${sub_args}") -string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}") -string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}") +string(REPLACE ";" " " espsecurepy "${espsecure_py_cmd}") +string(REPLACE ";" " " espefusepy "${espefuse_py_cmd}") # Suppress warning: "Manually-specified variables were not used by the project: SECURE_BOOT_SIGNING_KEY" set(ignore_signing_key "${SECURE_BOOT_SIGNING_KEY}") @@ -105,7 +125,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE) ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}") add_custom_command(OUTPUT "${secure_bootloader_key}" - COMMAND ${ESPSECUREPY} digest_private_key + COMMAND ${espsecure_py_cmd} digest_private_key --keylen "${key_digest_len}" --keyfile "${SECURE_BOOT_SIGNING_KEY}" "${secure_bootloader_key}" @@ -130,7 +150,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE) add_custom_command(OUTPUT "${bootloader_digest_bin}" COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}" - COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}" + COMMAND ${espsecure_py_cmd} digest_secure_bootloader --keyfile "${secure_bootloader_key}" -o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin" MAIN_DEPENDENCY "${CMAKE_BINARY_DIR}/.bin_timestamp" DEPENDS gen_secure_bootloader_key gen_project_binary @@ -139,39 +159,34 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE) add_custom_target(gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}") endif() +# If secure boot is enabled, generate the signed binary from the unsigned one. if(CONFIG_SECURE_BOOT_V2_ENABLED) - if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) - get_filename_component(secure_boot_signing_key - "${SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${project_dir}") + set(target_name "gen_signed_bootloader") - if(NOT EXISTS "${secure_boot_signing_key}") - message(FATAL_ERROR - "Secure Boot Signing Key Not found." - "\nGenerate the Secure Boot V2 RSA-PSS 3072 Key." - "\nTo generate one, you can use this command:" - "\n\t${espsecurepy} generate_signing_key --version 2 ${SECURE_BOOT_SIGNING_KEY}") + if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + # The SECURE_BOOT_SIGNING_KEY is passed in from the parent build and + # is already an absolute path. + if(NOT EXISTS "${SECURE_BOOT_SIGNING_KEY}") + message(FATAL_ERROR + "Secure Boot Signing Key Not found." + "\nGenerate the Secure Boot V2 RSA-PSS 3072 Key." + "\nTo generate one, you can use this command:" + "\n\t${espsecurepy} generate_signing_key --version 2 your_key.pem" + ) endif() - set(bootloader_unsigned_bin "bootloader-unsigned.bin") - add_custom_command(OUTPUT ".signed_bin_timestamp" - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" - "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}" - COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile "${secure_boot_signing_key}" - -o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}" - COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}" - "from ${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}" - COMMAND ${CMAKE_COMMAND} -E md5sum "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" - > "${CMAKE_BINARY_DIR}/.signed_bin_timestamp" - DEPENDS "${build_dir}/.bin_timestamp" - VERBATIM - COMMENT "Generated the signed Bootloader") + set(comment "Generated the signed Bootloader") + set(key_arg KEYFILE "${SECURE_BOOT_SIGNING_KEY}") else() - add_custom_command(OUTPUT ".signed_bin_timestamp" - VERBATIM - COMMENT "Bootloader generated but not signed") + # If we are not building signed binaries, we don't pass a key. + set(comment "Bootloader generated but not signed") + set(key_arg "") endif() - add_custom_target(gen_signed_bootloader ALL DEPENDS "${build_dir}/.signed_bin_timestamp") + __idf_build_secure_binary("${bootloader_unsigned_bin}" "${PROJECT_BIN}" "${target_name}" + COMMENT "${comment}" + ${key_arg} + ) endif() if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) @@ -255,3 +270,19 @@ elseif(CONFIG_SECURE_BOOT_V2_ENABLED AND NOT CONFIG_SECURE_BOOT_FLASH_BOOTLOADER DEPENDS gen_signed_bootloader VERBATIM) endif() + +# Generate bootloader post-build check of the bootloader size against the offset +partition_table_add_check_bootloader_size_target(bootloader_check_size + DEPENDS gen_project_binary + BOOTLOADER_BINARY_PATH "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" + RESULT bootloader_check_size_command) +add_dependencies(app bootloader_check_size) + +if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + # Check the size of the bootloader + signature block. + partition_table_add_check_bootloader_size_target(bootloader_check_size_signed + DEPENDS gen_signed_bootloader + BOOTLOADER_BINARY_PATH "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" + RESULT bootloader_check_size_signed_command) + add_dependencies(app bootloader_check_size_signed) +endif() diff --git a/components/esp_tee/subproject/CMakeLists.txt b/components/esp_tee/subproject/CMakeLists.txt index b4d77bd32b..a5f2a1198d 100644 --- a/components/esp_tee/subproject/CMakeLists.txt +++ b/components/esp_tee/subproject/CMakeLists.txt @@ -51,37 +51,51 @@ idf_build_set_property(COMPILE_DEFINITIONS "ESP_TEE_BUILD=1" APPEND) idf_build_set_property(COMPILE_DEFINITIONS "NON_OS_BUILD=1" APPEND) idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND) -if(CONFIG_SECURE_BOOT_V2_ENABLED) - if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) - get_filename_component(secure_boot_signing_key - "${SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${project_dir}") +# Set up the TEE binary generation targets +set(project_bin "esp_tee.bin") +if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + set(esp_tee_unsigned_bin "esp_tee-unsigned.bin") +else() + set(esp_tee_unsigned_bin "${project_bin}") +endif() - if(NOT EXISTS "${secure_boot_signing_key}") - message(FATAL_ERROR - "Secure Boot Signing Key Not found." - "\nGenerate the Secure Boot V2 RSA-PSS 3072 Key." - "\nTo generate one, you can use this command:" - "\n\t${espsecurepy} generate_signing_key --version 2 ${SECURE_BOOT_SIGNING_KEY}") +# Set the final binary name as a project property. +idf_build_set_property(PROJECT_BIN "${project_bin}") + +# Generate the unsigned binary from the ELF file. +if(CONFIG_APP_BUILD_GENERATE_BINARIES) + set(target_name "gen_esp_tee_binary") + __idf_build_binary("${esp_tee_unsigned_bin}" "${target_name}") +endif() + +idf_component_get_property(espsecure_py_cmd esptool_py ESPSECUREPY_CMD) + +# If secure boot is enabled, generate the signed binary from the unsigned one. +if(CONFIG_SECURE_BOOT_V2_ENABLED) + set(target_name "gen_signed_esp_tee_binary") + + if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + # The SECURE_BOOT_SIGNING_KEY is passed in from the parent build and + # is already an absolute path. + if(NOT EXISTS "${SECURE_BOOT_SIGNING_KEY}") + message(FATAL_ERROR + "Secure Boot Signing Key Not found." + "\nGenerate the Secure Boot V2 RSA-PSS 3072 Key." + "\nTo generate one, you can use this command:" + "\n\t${espsecure_py_cmd} generate_signing_key --version 2 your_key.pem" + ) endif() - set(esp_tee_unsigned_bin "esp_tee-unsigned.bin") - add_custom_command(OUTPUT ".signed_bin_timestamp" - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" - "${CMAKE_BINARY_DIR}/${esp_tee_unsigned_bin}" - COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile "${secure_boot_signing_key}" - -o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${esp_tee_unsigned_bin}" - COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}" - "from ${CMAKE_BINARY_DIR}/${esp_tee_unsigned_bin}" - COMMAND ${CMAKE_COMMAND} -E md5sum "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" - > "${CMAKE_BINARY_DIR}/.signed_bin_timestamp" - DEPENDS "${build_dir}/.bin_timestamp" - VERBATIM - COMMENT "Generated the signed TEE") + set(comment "Generated the signed TEE") + set(key_arg KEYFILE "${SECURE_BOOT_SIGNING_KEY}") else() - add_custom_command(OUTPUT ".signed_bin_timestamp" - VERBATIM - COMMENT "TEE generated but not signed") + # If we are not building signed binaries, we don't pass a key. + set(comment "TEE generated but not signed") + set(key_arg "") endif() - add_custom_target(gen_signed_esp_tee ALL DEPENDS "${build_dir}/.signed_bin_timestamp") + __idf_build_secure_binary("${esp_tee_unsigned_bin}" "${project_bin}" "${target_name}" + COMMENT "${comment}" + ${key_arg} + ) endif() diff --git a/components/esptool_py/CMakeLists.txt b/components/esptool_py/CMakeLists.txt index 925cb59550..63a6582f6f 100644 --- a/components/esptool_py/CMakeLists.txt +++ b/components/esptool_py/CMakeLists.txt @@ -17,16 +17,6 @@ if(NOT BOOTLOADER_BUILD) - # If anti-rollback option is set then factory partition should not be in Partition Table. - # In this case, should be used the partition table with two ota app without the factory. - partition_table_get_partition_info(factory_offset "--partition-type app --partition-subtype factory" "offset") - partition_table_get_partition_info(test_offset "--partition-type app --partition-subtype test" "offset") - if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND (factory_offset OR test_offset)) - fail_at_build_time(check_table_contents "\ -ERROR: Anti-rollback option is enabled. Partition table should \ -consist of two ota app without factory or test partitions.") - add_dependencies(app check_table_contents) - endif() # Generate flasher_args.json for tools that need it. The variables below are used # in configuring the template flasher_args.json.in. @@ -54,31 +44,5 @@ consist of two ota app without factory or test partitions.") CONTENT "${flasher_args_content}") file_generate("${CMAKE_BINARY_DIR}/flasher_args.json" INPUT "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in") - if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT) - # Generate app_check_size_command target to check the app size against the partition table parameters - partition_table_add_check_size_target(app_check_size - DEPENDS gen_project_binary - BINARY_PATH "${build_dir}/${PROJECT_BIN}" - PARTITION_TYPE app) - add_dependencies(app app_check_size) - endif() endif() endif() # NOT BOOTLOADER_BUILD - -if(BOOTLOADER_BUILD) - # Generate bootloader post-build check of the bootloader size against the offset - partition_table_add_check_bootloader_size_target(bootloader_check_size - DEPENDS gen_project_binary - BOOTLOADER_BINARY_PATH "${build_dir}/${PROJECT_BIN}" - RESULT bootloader_check_size_command) - add_dependencies(app bootloader_check_size) # note: in the subproject, so the target is 'app'... - - if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) - # Check the size of the bootloader + signature block. - partition_table_add_check_bootloader_size_target(bootloader_check_size_signed - DEPENDS gen_signed_bootloader - BOOTLOADER_BINARY_PATH "${build_dir}/${PROJECT_BIN}" - RESULT bootloader_check_size_signed_command) - add_dependencies(app bootloader_check_size_signed) # note: in the subproject, so the target is 'app'... - endif() -endif() diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake index e3997f139d..88832ef10c 100644 --- a/components/esptool_py/project_include.cmake +++ b/components/esptool_py/project_include.cmake @@ -112,79 +112,6 @@ idf_build_get_property(build_dir BUILD_DIR) idf_build_get_property(elf_name EXECUTABLE_NAME GENERATOR_EXPRESSION) idf_build_get_property(elf EXECUTABLE GENERATOR_EXPRESSION) -if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES AND NOT non_os_build) - set(unsigned_project_binary "${elf_name}-unsigned.bin") -else() - set(unsigned_project_binary "${elf_name}.bin") -endif() - -set(PROJECT_BIN "${elf_name}.bin") - -# -# Add 'app.bin' target - generates with elf2image -# -if(CONFIG_APP_BUILD_GENERATE_BINARIES) - add_custom_command(OUTPUT "${build_dir}/.bin_timestamp" - COMMAND ${ESPTOOLPY} elf2image ${esptool_elf2image_args} - -o "${build_dir}/${unsigned_project_binary}" "$>" - COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/${unsigned_project_binary}" - COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${unsigned_project_binary}" > "${build_dir}/.bin_timestamp" - DEPENDS "$>" - VERBATIM - WORKING_DIRECTORY ${build_dir} - COMMENT "Generating binary image from built executable" - ) - add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp") -endif() - -set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - APPEND PROPERTY ADDITIONAL_CLEAN_FILES - "${build_dir}/${unsigned_project_binary}" - ) - -if(CONFIG_APP_BUILD_GENERATE_BINARIES) - add_custom_target(app ALL DEPENDS gen_project_binary) -endif() - -if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) - set(secure_boot_version "1") -elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME) - set(secure_boot_version "2") -endif() - -if(NOT non_os_build AND CONFIG_SECURE_SIGNED_APPS) - if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) - # for locally signed secure boot image, add a signing step to get from unsigned app to signed app - get_filename_component(secure_boot_signing_key "${CONFIG_SECURE_BOOT_SIGNING_KEY}" - ABSOLUTE BASE_DIR "${project_dir}") - add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp" - COMMAND ${ESPSECUREPY} sign_data --version ${secure_boot_version} --keyfile ${secure_boot_signing_key} - -o "${build_dir}/${PROJECT_BIN}" "${build_dir}/${unsigned_project_binary}" - COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}" - "from ${build_dir}/${unsigned_project_binary}" - COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${PROJECT_BIN}" > "${build_dir}/.signed_bin_timestamp" - DEPENDS "${build_dir}/.bin_timestamp" - VERBATIM - COMMENT "Generating signed binary image" - ) - add_custom_target(gen_signed_project_binary DEPENDS "${build_dir}/.signed_bin_timestamp") - add_dependencies(gen_project_binary gen_signed_project_binary) - - set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - APPEND PROPERTY ADDITIONAL_CLEAN_FILES - "${build_dir}/${PROJECT_BIN}" - ) - else() - string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}") - add_custom_command(TARGET app POST_BUILD - COMMAND ${CMAKE_COMMAND} -E echo - "App built but not signed. Sign app before flashing" - COMMAND ${CMAKE_COMMAND} -E echo - "\t${espsecurepy} sign_data --keyfile KEYFILE --version ${secure_boot_version} \ - ${build_dir}/${PROJECT_BIN}" - VERBATIM) - endif() -endif() add_custom_target(erase_flash COMMAND ${CMAKE_COMMAND} @@ -781,6 +708,147 @@ function(__ensure_esptool_py_setup) endfunction() +# __idf_build_binary +# +# @brief Sets up the primary target for generating a .bin file from an .elf file. +# +# This function creates the custom command and target required to generate a +# project binary (`.bin`) file from the final `.elf` executable. It uses `esptool.py +# elf2image` to perform the conversion and manages dependencies to ensure the +# binary is regenerated whenever the ELF file changes. +# +# @param[in] OUTPUT_BIN_FILENAME The name of the output binary file to generate. +# @param[in] TARGET_NAME The unique name for the custom target that +# generates the binary. +function(__idf_build_binary OUTPUT_BIN_FILENAME TARGET_NAME) + __ensure_esptool_py_setup() + + idf_build_get_property(build_dir BUILD_DIR) + idf_build_get_property(elf EXECUTABLE GENERATOR_EXPRESSION) + idf_component_get_property(esptool_py_cmd esptool_py ESPTOOLPY_CMD) + + # Get esptool.py arguments for elf2image target + idf_component_get_property(esptool_elf2image_args esptool_py ESPTOOL_PY_ELF2IMAGE_ARGS) + + # Create a custom command and target to generate binary from elf file + add_custom_command(OUTPUT "${build_dir}/.bin_timestamp" + COMMAND ${esptool_py_cmd} elf2image ${esptool_elf2image_args} + -o "${build_dir}/${OUTPUT_BIN_FILENAME}" "$>" + COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/${OUTPUT_BIN_FILENAME}" + COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${OUTPUT_BIN_FILENAME}" > "${build_dir}/.bin_timestamp" + DEPENDS "$>" + VERBATIM + WORKING_DIRECTORY ${build_dir} + COMMENT "Generating binary image from built executable" + ) + # Create a custom target to generate the binary file + add_custom_target(${TARGET_NAME} DEPENDS "${build_dir}/.bin_timestamp") + + # We need to create a gen_project_binary target for backward compatibility + # since many other components depend on it. Add the new target as a dependency + # to the gen_project_binary target. + if(NOT TARGET gen_project_binary) + add_custom_target(gen_project_binary DEPENDS ${TARGET_NAME}) + else() + add_dependencies(gen_project_binary ${TARGET_NAME}) + endif() + + # Add an 'app' alias that is part of the default build + if(NOT TARGET app) + add_custom_target(app ALL DEPENDS gen_project_binary) + else() + add_dependencies(app gen_project_binary) + endif() + + set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + APPEND PROPERTY ADDITIONAL_CLEAN_FILES + "${build_dir}/${OUTPUT_BIN_FILENAME}" + ) +endfunction() + +# __idf_build_secure_binary +# +# @brief Sets up targets for generating a signed binary for Secure Boot. +# +# If Secure Boot is enabled, this function adds a custom command to sign the +# previously generated application binary using `espsecure.py`. It creates a +# target that depends on the unsigned binary and produces a signed one, which +# is required for the bootloader to authenticate the application. +# +# @param[in] UNSIGNED_BIN_FILENAME The name of the unsigned input binary file. +# @param[in] SIGNED_BIN_FILENAME The name of the signed output binary file. +# @param[in] TARGET_NAME The unique name for the custom target that +# generates the signed binary. +# @param[in, optional] KEYFILE Path to the keyfile for signing. +# @param[in, optional] COMMENT Custom message to display during build. +function(__idf_build_secure_binary UNSIGNED_BIN_FILENAME SIGNED_BIN_FILENAME TARGET_NAME) + cmake_parse_arguments(arg "" "KEYFILE;COMMENT" "" ${ARGN}) + + __ensure_esptool_py_setup() + + idf_build_get_property(build_dir BUILD_DIR) + idf_component_get_property(espsecure_py_cmd esptool_py ESPSECUREPY_CMD) + + if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) + set(secure_boot_version "1") + elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME) + set(secure_boot_version "2") + endif() + + if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + if(arg_KEYFILE) + # If a keyfile is provided, use it for signing. + set(secure_boot_signing_key "${arg_KEYFILE}") + else() + # for locally signed secure boot image, add a signing step to get from unsigned app to signed app + idf_build_get_property(project_dir PROJECT_DIR) + get_filename_component(secure_boot_signing_key "${CONFIG_SECURE_BOOT_SIGNING_KEY}" + ABSOLUTE BASE_DIR "${project_dir}") + endif() + + if(arg_COMMENT) + set(comment_text "${arg_COMMENT}") + else() + set(comment_text "Generating signed binary image") + endif() + + add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp" + COMMAND ${espsecure_py_cmd} sign_data + --version ${secure_boot_version} --keyfile "${secure_boot_signing_key}" + -o "${build_dir}/${SIGNED_BIN_FILENAME}" "${build_dir}/${UNSIGNED_BIN_FILENAME}" + COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${SIGNED_BIN_FILENAME}" + "from ${build_dir}/${UNSIGNED_BIN_FILENAME}" + COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${SIGNED_BIN_FILENAME}" + > "${build_dir}/.signed_bin_timestamp" + DEPENDS "${build_dir}/.bin_timestamp" + VERBATIM + COMMENT "${comment_text}" + ) + add_custom_target(${TARGET_NAME} DEPENDS "${build_dir}/.signed_bin_timestamp") + + # Add the new target as a dependency to the gen_project_binary target. + if(NOT TARGET gen_project_binary) + add_custom_target(gen_project_binary DEPENDS ${TARGET_NAME}) + else() + add_dependencies(gen_project_binary ${TARGET_NAME}) + endif() + + set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + APPEND PROPERTY ADDITIONAL_CLEAN_FILES + "${build_dir}/${SIGNED_BIN_FILENAME}" + ) + else() + string(REPLACE ";" " " espsecurepy "${espsecure_py_cmd}") + add_custom_command(TARGET app POST_BUILD + COMMAND ${CMAKE_COMMAND} -E echo + "App built but not signed. Sign app before flashing" + COMMAND ${CMAKE_COMMAND} -E echo + "\t${espsecurepy} sign_data --keyfile KEYFILE --version ${secure_boot_version} \ + ${build_dir}/${UNSIGNED_BIN_FILENAME}" + VERBATIM) + endif() +endfunction() + # __esptool_py_setup_main_flash_target # # @brief Sets up the main `flash` target and its dependencies. diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 76dfdde8c8..46af1d5d3c 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -783,9 +783,51 @@ function(idf_build_executable elf) idf_build_get_property(esp_tee_build ESP_TEE_BUILD) idf_build_get_property(target IDF_TARGET) - if(NOT bootloader_build AND NOT esp_tee_build AND NOT "${target}" STREQUAL "linux") - # Check if esptool_py component is available before calling its functions - if(TARGET idf::esptool_py) + # This is the main orchestrator for generating binaries and flash targets + # It is responsible for - + # - Setting up the binary generation targets + # - Setting up the signed binary generation targets + # - Setting up the main 'flash' target + # - Setting up the app-flash and flash targets + # - Setting up the app_check_size target + # + # Note: We need to wrap this code in a if(NOT BOOTLOADER_BUILD AND NOT ESP_TEE_BUILD) block + # because the bootloader and esp_tee subprojects also call our overridden project() + # macro. + # + # Note: We need to have this block here instead of in project.cmake because + # idf_build_executable() is called directly when ESP-IDF is compiled + # as a library (idf_as_lib). + if(NOT bootloader_build AND NOT esp_tee_build) + # All of the following logic for generating binaries and flash targets + # depends on the esptool_py component. For some builds (such as those + # that are built for the linux target), this component may not be included. + # We must guard these calls to ensure they only run when esptool_py is part + # of the build. We also only do this if CONFIG_APP_BUILD_GENERATE_BINARIES is set. + if(TARGET idf::esptool_py AND CONFIG_APP_BUILD_GENERATE_BINARIES) + # Determine the output filename for the binary. + idf_build_get_property(elf_name EXECUTABLE_NAME GENERATOR_EXPRESSION) + idf_build_get_property(non_os_build NON_OS_BUILD) + + set(project_bin "${elf_name}.bin") + if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES AND NOT non_os_build) + set(project_bin_unsigned "${elf_name}-unsigned.bin") + else() + set(project_bin_unsigned "${project_bin}") + endif() + + idf_build_set_property(PROJECT_BIN "${project_bin}") + + # Create the binary file generation target for the main project + set(target_name "gen_${CMAKE_PROJECT_NAME}_binary") + __idf_build_binary("${project_bin_unsigned}" "${target_name}") + + # Generate the signed binary file generation target for the main project + if(NOT non_os_build AND CONFIG_SECURE_SIGNED_APPS) + set(signed_target_name "gen_signed_${CMAKE_PROJECT_NAME}_binary") + __idf_build_secure_binary("${project_bin_unsigned}" "${project_bin}" "${signed_target_name}") + endif() + # The following block is placed here to ensure that the application binary is added to the 'flash' # target's properties *before* __esptool_py_setup_main_flash_target is called. # This is because __esptool_py_setup_main_flash_target copies properties from the 'flash' @@ -795,19 +837,42 @@ function(idf_build_executable elf) # # Set up app-flash and flash targets. The app-flash target is specifically for flashing # just the application, while the flash target is for flashing the entire system. - if(CONFIG_APP_BUILD_GENERATE_BINARIES) - idf_build_get_property(build_dir BUILD_DIR) - idf_build_get_property(project_bin PROJECT_BIN) - partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset") - esptool_py_custom_target(app-flash app "app") + idf_build_get_property(build_dir BUILD_DIR) + idf_build_get_property(project_bin PROJECT_BIN) + partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset") + esptool_py_custom_target(app-flash app "app") - esptool_py_flash_target_image(app-flash app "${app_partition_offset}" "${build_dir}/${project_bin}") - esptool_py_flash_target_image(flash app "${app_partition_offset}" "${build_dir}/${project_bin}") + esptool_py_flash_target_image(app-flash app "${app_partition_offset}" "${build_dir}/${project_bin}") + esptool_py_flash_target_image(flash app "${app_partition_offset}" "${build_dir}/${project_bin}") + + # Setup the main flash target and dependencies + __esptool_py_setup_main_flash_target() + + # Create the following post-build targets after __idf_build_binary() is called to ensure that the + # app target is available. + + # If anti-rollback option is set then factory partition should not be in Partition Table. + # In this case, should be used the partition table with two ota app without the factory. + partition_table_get_partition_info(factory_offset + "--partition-type app --partition-subtype factory" "offset") + partition_table_get_partition_info(test_offset "--partition-type app --partition-subtype test" "offset") + if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND (factory_offset OR test_offset)) + fail_at_build_time(check_table_contents "\ + ERROR: Anti-rollback option is enabled. Partition table should \ + consist of two ota app without factory or test partitions.") + add_dependencies(app check_table_contents) endif() - __esptool_py_setup_main_flash_target() - endif() - endif() + if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT) + # Generate app_check_size_command target to check the app size against the partition table parameters + partition_table_add_check_size_target(app_check_size + DEPENDS gen_project_binary + BINARY_PATH "${build_dir}/${project_bin}" + PARTITION_TYPE app) + add_dependencies(app app_check_size) + endif() + endif() # if(TARGET idf::esptool_py AND CONFIG_APP_BUILD_GENERATE_BINARIES) + endif() # if(NOT bootloader_build AND NOT esp_tee_build) endfunction() # idf_build_get_config From 3a1f34386c30bbdf35f71fe57d38eec0daa6064a Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Wed, 2 Jul 2025 13:09:34 +0200 Subject: [PATCH 4/8] refactor(esptool_py): Move flasher_args.json generation to project level This commit refactors the esptool_py component to move the flasher_args.json file generation to the main project level cmake file when idf_build_executable() runs. --- components/esptool_py/CMakeLists.txt | 35 --------------------------- tools/cmake/build.cmake | 36 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/components/esptool_py/CMakeLists.txt b/components/esptool_py/CMakeLists.txt index 63a6582f6f..c5a406e3f0 100644 --- a/components/esptool_py/CMakeLists.txt +++ b/components/esptool_py/CMakeLists.txt @@ -11,38 +11,3 @@ if(esp_tee_build) endif() idf_component_register(REQUIRES bootloader PRIV_REQUIRES partition_table) - -if(NOT BOOTLOADER_BUILD) - idf_build_get_property(build_dir BUILD_DIR) - - - - - # Generate flasher_args.json for tools that need it. The variables below are used - # in configuring the template flasher_args.json.in. - # Some of the variables (flash mode, size, frequency, chip) are already set in project_include.cmake. - - set(ESPTOOLPY_BEFORE "${CONFIG_ESPTOOLPY_BEFORE}") - set(ESPTOOLPY_AFTER "${CONFIG_ESPTOOLPY_AFTER}") - if(CONFIG_ESPTOOLPY_NO_STUB) - set(ESPTOOLPY_WITH_STUB false) - else() - set(ESPTOOLPY_WITH_STUB true) - endif() - - if(CONFIG_SECURE_BOOT OR CONFIG_SECURE_FLASH_ENC_ENABLED) - # If security enabled then override post flash option - set(ESPTOOLPY_AFTER "no_reset") - endif() - - if(CONFIG_APP_BUILD_GENERATE_BINARIES) - # Generate flasher args files - file(READ "flasher_args.json.in" flasher_args_content) - string(CONFIGURE "${flasher_args_content}" flasher_args_content) - - file_generate("${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in" - CONTENT "${flasher_args_content}") - file_generate("${CMAKE_BINARY_DIR}/flasher_args.json" - INPUT "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in") - endif() -endif() # NOT BOOTLOADER_BUILD diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 46af1d5d3c..71d8831bd7 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -848,6 +848,42 @@ function(idf_build_executable elf) # Setup the main flash target and dependencies __esptool_py_setup_main_flash_target() + # Generate flasher_args.json for tools that need it. The variables below are used + # in configuring the template flasher_args.json.in. + # Some of the variables (flash mode, size, frequency) are set as esptool_py component's properties. + + idf_build_get_property(target IDF_TARGET) + set(ESPTOOLPY_CHIP "${target}") + set(ESPTOOLPY_BEFORE "${CONFIG_ESPTOOLPY_BEFORE}") + set(ESPTOOLPY_AFTER "${CONFIG_ESPTOOLPY_AFTER}") + if(CONFIG_ESPTOOLPY_NO_STUB) + set(ESPTOOLPY_WITH_STUB false) + else() + set(ESPTOOLPY_WITH_STUB true) + endif() + + if(CONFIG_SECURE_BOOT OR CONFIG_SECURE_FLASH_ENC_ENABLED) + # If security enabled then override post flash option + set(ESPTOOLPY_AFTER "no_reset") + endif() + + idf_component_get_property(ESPFLASHMODE esptool_py ESPFLASHMODE) + idf_component_get_property(ESPFLASHFREQ esptool_py ESPFLASHFREQ) + idf_component_get_property(ESPFLASHSIZE esptool_py ESPFLASHSIZE) + idf_component_get_property(esptool_py_dir esptool_py COMPONENT_DIR) + + # Generate flasher args files + file(READ "${esptool_py_dir}/flasher_args.json.in" flasher_args_content) + string(CONFIGURE "${flasher_args_content}" flasher_args_content) + + # We need to create a flasher_args.json.in to create the final flasher_args.json + # because CMake only resolves generator expressions in the file_generate command + # with the INPUT keyword during the generation phase. + file_generate("${build_dir}/flasher_args.json.in" + CONTENT "${flasher_args_content}") + file_generate("${build_dir}/flasher_args.json" + INPUT "${build_dir}/flasher_args.json.in") + # Create the following post-build targets after __idf_build_binary() is called to ensure that the # app target is available. From 8582294caf45723cb0365dd31df423360819fa9c Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Wed, 2 Jul 2025 13:30:07 +0200 Subject: [PATCH 5/8] refactor(esptool_py): Move utility target creation to project level This commit refactors the esptool_py component to provide utility functions for creating utility targets such as erase_flash, merge-bin and monitor. The following changes were done in this commit: - Added __esptool_py_setup_utility_targets() to create utility targets. - Utility target creation now happens in idf_build_executable() in build.cmake. - Removed more global scope processing and variables from esptool_py component project_include.cmake. --- components/esptool_py/project_include.cmake | 278 +++++++------------- tools/cmake/build.cmake | 3 + 2 files changed, 93 insertions(+), 188 deletions(-) diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake index 88832ef10c..0a2b7ce750 100644 --- a/components/esptool_py/project_include.cmake +++ b/components/esptool_py/project_include.cmake @@ -1,5 +1,5 @@ -# Set some global esptool.py variables -# +# esptool_py component project_include.cmake + # Many of these are read when generating flash_app_args & flash_project_args idf_build_get_property(target IDF_TARGET) idf_build_get_property(python PYTHON) @@ -15,192 +15,6 @@ set(ESPEFUSEPY ${python} "${CMAKE_CURRENT_LIST_DIR}/esptool/espefuse.py") set(ESPMONITOR ${python} -m esp_idf_monitor) set(ESPTOOLPY_CHIP "${chip_model}") -if(NOT CONFIG_APP_BUILD_TYPE_RAM AND CONFIG_APP_BUILD_GENERATE_BINARIES) - if(CONFIG_BOOTLOADER_FLASH_DC_AWARE) - # When set flash frequency to 120M, must keep 1st bootloader work under ``DOUT`` mode - # because on some flash chips, 120M will modify the status register, - # which will make ROM won't work. - # This change intends to be for esptool only and the bootloader should keep use - # ``DOUT`` mode. - set(ESPFLASHMODE "dout") - message("Note: HPM is enabled for the flash, force the ROM bootloader into DOUT mode for stable boot on") - else() - set(ESPFLASHMODE ${CONFIG_ESPTOOLPY_FLASHMODE}) - endif() - set(ESPFLASHFREQ ${CONFIG_ESPTOOLPY_FLASHFREQ}) - set(ESPFLASHSIZE ${CONFIG_ESPTOOLPY_FLASHSIZE}) - - - set(esptool_elf2image_args - --flash_mode ${ESPFLASHMODE} - --flash_freq ${ESPFLASHFREQ} - --flash_size ${ESPFLASHSIZE} - ) - - if(BOOTLOADER_BUILD AND CONFIG_SECURE_BOOT_V2_ENABLED) - # The bootloader binary needs to be 4KB aligned in order to append a secure boot V2 signature block. - # If CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES is NOT set, the bootloader - # image generated is not 4KB aligned for external HSM to sign it readily. - # Following esptool option --pad-to-size 4KB generates a 4K aligned bootloader image. - # In case of signing during build, espsecure.py "sign_data" operation handles the 4K alignment of the image. - if(NOT CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) - list(APPEND esptool_elf2image_args --pad-to-size 4KB) - endif() - endif() - - set(MMU_PAGE_SIZE ${CONFIG_MMU_PAGE_MODE}) - - if(NOT BOOTLOADER_BUILD) - list(APPEND esptool_elf2image_args --elf-sha256-offset 0xb0) - # For chips that support configurable MMU page size feature - # If page size is configured to values other than the default "64KB" in menuconfig, - # then we need to pass the actual size to flash-mmu-page-size arg - if(NOT MMU_PAGE_SIZE STREQUAL "64KB") - list(APPEND esptool_elf2image_args --flash-mmu-page-size ${MMU_PAGE_SIZE}) - endif() - endif() - - if(NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION AND - NOT BOOTLOADER_BUILD) - if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) - list(APPEND esptool_elf2image_args --secure-pad) - elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME) - list(APPEND esptool_elf2image_args --secure-pad-v2) - endif() - endif() - - if(CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE) - # Set ESPFLASHSIZE to 'detect' *after* esptool_elf2image_args are generated, - # as elf2image can't have 'detect' as an option... - set(ESPFLASHSIZE detect) - endif() - - if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) - set(ESPFLASHSIZE keep) - endif() -endif() - -# We still set "--min-rev" to keep the app compatible with older bootloaders where this field is controlled. -if(CONFIG_IDF_TARGET_ESP32) - # for this chip min_rev is major revision - math(EXPR min_rev "${CONFIG_ESP_REV_MIN_FULL} / 100") -endif() -if(CONFIG_IDF_TARGET_ESP32C3) - # for this chip min_rev is minor revision - math(EXPR min_rev "${CONFIG_ESP_REV_MIN_FULL} % 100") -endif() - -if(min_rev) - list(APPEND esptool_elf2image_args --min-rev ${min_rev}) -endif() - -list(APPEND esptool_elf2image_args --min-rev-full ${CONFIG_ESP_REV_MIN_FULL}) -list(APPEND esptool_elf2image_args --max-rev-full ${CONFIG_ESP_REV_MAX_FULL}) - -if(CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE) - # Set ESPFLASHSIZE to 'detect' *after* esptool_elf2image_args are generated, - # as elf2image can't have 'detect' as an option... - set(ESPFLASHSIZE detect) -endif() - -if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME) - set(ESPFLASHSIZE keep) -endif() - -idf_build_get_property(build_dir BUILD_DIR) - -idf_build_get_property(elf_name EXECUTABLE_NAME GENERATOR_EXPRESSION) -idf_build_get_property(elf EXECUTABLE GENERATOR_EXPRESSION) - - -add_custom_target(erase_flash - COMMAND ${CMAKE_COMMAND} - -D "IDF_PATH=${idf_path}" - -D "SERIAL_TOOL=${ESPTOOLPY}" - -D "SERIAL_TOOL_ARGS=erase_flash" - -P run_serial_tool.cmake - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} - USES_TERMINAL - VERBATIM - ) - -set(MERGE_BIN_ARGS merge_bin) -if(DEFINED ENV{ESP_MERGE_BIN_OUTPUT}) - list(APPEND MERGE_BIN_ARGS "-o" "$ENV{ESP_MERGE_BIN_OUTPUT}") -else() - if(DEFINED ENV{ESP_MERGE_BIN_FORMAT} AND "$ENV{ESP_MERGE_BIN_FORMAT}" STREQUAL "hex") - list(APPEND MERGE_BIN_ARGS "-o" "${CMAKE_CURRENT_BINARY_DIR}/merged-binary.hex") - else() - list(APPEND MERGE_BIN_ARGS "-o" "${CMAKE_CURRENT_BINARY_DIR}/merged-binary.bin") - endif() -endif() - -if(DEFINED ENV{ESP_MERGE_BIN_FORMAT}) - list(APPEND MERGE_BIN_ARGS "-f" "$ENV{ESP_MERGE_BIN_FORMAT}") -endif() - -list(APPEND MERGE_BIN_ARGS "@${CMAKE_CURRENT_BINARY_DIR}/flash_args") - -add_custom_target(merge-bin - COMMAND ${CMAKE_COMMAND} - -D "IDF_PATH=${idf_path}" - -D "SERIAL_TOOL=${ESPTOOLPY}" - -D "SERIAL_TOOL_ARGS=${MERGE_BIN_ARGS}" - -D "WORKING_DIRECTORY=${CMAKE_CURRENT_BINARY_DIR}" - -P run_serial_tool.cmake - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} - DEPENDS gen_project_binary bootloader - USES_TERMINAL - VERBATIM - ) - -set(MONITOR_ARGS "") - -list(APPEND MONITOR_ARGS "--toolchain-prefix;${_CMAKE_TOOLCHAIN_PREFIX};") - -if(CONFIG_ESP_COREDUMP_DECODE) -list(APPEND MONITOR_ARGS "--decode-coredumps;${CONFIG_ESP_COREDUMP_DECODE};") -endif() - -list(APPEND MONITOR_ARGS "--target;${target};") - -list(APPEND MONITOR_ARGS "--revision;${CONFIG_ESP_REV_MIN_FULL};") - -if(CONFIG_IDF_TARGET_ARCH_RISCV) - list(APPEND MONITOR_ARGS "--decode-panic;backtrace;") -endif() - -list(APPEND MONITOR_ARGS "$>") - -add_custom_target(monitor - COMMAND ${CMAKE_COMMAND} - -D "IDF_PATH=${idf_path}" - -D "SERIAL_TOOL=${ESPMONITOR}" - -D "SERIAL_TOOL_ARGS=${MONITOR_ARGS}" - -D "WORKING_DIRECTORY=${build_dir}" - -P run_serial_tool.cmake - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} - USES_TERMINAL - VERBATIM - ) - -set(esptool_flash_main_args "--before=${CONFIG_ESPTOOLPY_BEFORE}") - -if(CONFIG_SECURE_BOOT OR CONFIG_SECURE_FLASH_ENC_ENABLED) - # If security enabled then override post flash option - list(APPEND esptool_flash_main_args "--after=no_reset") -else() - list(APPEND esptool_flash_main_args "--after=${CONFIG_ESPTOOLPY_AFTER}") -endif() - -if(CONFIG_ESPTOOLPY_NO_STUB) - list(APPEND esptool_flash_main_args "--no-stub") -endif() - -idf_component_set_property(esptool_py FLASH_ARGS "${esptool_flash_main_args}") -idf_component_set_property(esptool_py FLASH_SUB_ARGS "--flash_mode ${ESPFLASHMODE} --flash_freq ${ESPFLASHFREQ} \ ---flash_size ${ESPFLASHSIZE}") - # esptool_py_partition_needs_encryption # # @brief Determine if a partition needs to be encrypted when flash encryption is enabled. @@ -849,6 +663,94 @@ function(__idf_build_secure_binary UNSIGNED_BIN_FILENAME SIGNED_BIN_FILENAME TAR endif() endfunction() +# __esptool_py_setup_utility_targets +# +# @brief Sets up common utility targets like `erase_flash`, `merge-bin`, and `monitor` +# +function(__esptool_py_setup_utility_targets) + __ensure_esptool_py_setup() + + idf_build_get_property(build_dir BUILD_DIR) + idf_build_get_property(idf_path IDF_PATH) + idf_build_get_property(python PYTHON) + idf_build_get_property(target IDF_TARGET) + idf_build_get_property(elf_name EXECUTABLE_NAME GENERATOR_EXPRESSION) + idf_build_get_property(elf EXECUTABLE GENERATOR_EXPRESSION) + idf_component_get_property(esptool_py_cmd esptool_py ESPTOOLPY_CMD) + idf_component_get_property(esptool_py_dir esptool_py COMPONENT_DIR) + + add_custom_target(erase_flash + COMMAND ${CMAKE_COMMAND} + -D "IDF_PATH=${idf_path}" + -D "SERIAL_TOOL=${esptool_py_cmd}" + -D "SERIAL_TOOL_ARGS=erase_flash" + -P run_serial_tool.cmake + WORKING_DIRECTORY ${esptool_py_dir} + USES_TERMINAL + VERBATIM + ) + + set(MERGE_BIN_ARGS merge_bin) + if(DEFINED ENV{ESP_MERGE_BIN_OUTPUT}) + list(APPEND MERGE_BIN_ARGS "-o" "$ENV{ESP_MERGE_BIN_OUTPUT}") + else() + if(DEFINED ENV{ESP_MERGE_BIN_FORMAT} AND "$ENV{ESP_MERGE_BIN_FORMAT}" STREQUAL "hex") + list(APPEND MERGE_BIN_ARGS "-o" "${CMAKE_CURRENT_BINARY_DIR}/merged-binary.hex") + else() + list(APPEND MERGE_BIN_ARGS "-o" "${CMAKE_CURRENT_BINARY_DIR}/merged-binary.bin") + endif() + endif() + + if(DEFINED ENV{ESP_MERGE_BIN_FORMAT}) + list(APPEND MERGE_BIN_ARGS "-f" "$ENV{ESP_MERGE_BIN_FORMAT}") + endif() + + list(APPEND MERGE_BIN_ARGS "@${CMAKE_CURRENT_BINARY_DIR}/flash_args") + + add_custom_target(merge-bin + COMMAND ${CMAKE_COMMAND} + -D "IDF_PATH=${idf_path}" + -D "SERIAL_TOOL=${esptool_py_cmd}" + -D "SERIAL_TOOL_ARGS=${MERGE_BIN_ARGS}" + -D "WORKING_DIRECTORY=${CMAKE_CURRENT_BINARY_DIR}" + -P run_serial_tool.cmake + WORKING_DIRECTORY ${esptool_py_dir} + DEPENDS gen_project_binary bootloader + USES_TERMINAL + VERBATIM + ) + + set(MONITOR_ARGS "") + + list(APPEND MONITOR_ARGS "--toolchain-prefix;${_CMAKE_TOOLCHAIN_PREFIX};") + + if(CONFIG_ESP_COREDUMP_DECODE) + list(APPEND MONITOR_ARGS "--decode-coredumps;${CONFIG_ESP_COREDUMP_DECODE};") + endif() + + list(APPEND MONITOR_ARGS "--target;${target};") + + list(APPEND MONITOR_ARGS "--revision;${CONFIG_ESP_REV_MIN_FULL};") + + if(CONFIG_IDF_TARGET_ARCH_RISCV) + list(APPEND MONITOR_ARGS "--decode-panic;backtrace;") + endif() + + list(APPEND MONITOR_ARGS "$>") + + add_custom_target(monitor + COMMAND ${CMAKE_COMMAND} + -D "IDF_PATH=${idf_path}" + -D "SERIAL_TOOL=${python} -m esp_idf_monitor" + -D "SERIAL_TOOL_ARGS=${MONITOR_ARGS}" + -D "WORKING_DIRECTORY=${build_dir}" + -P run_serial_tool.cmake + WORKING_DIRECTORY ${esptool_py_dir} + USES_TERMINAL + VERBATIM + ) +endfunction() + # __esptool_py_setup_main_flash_target # # @brief Sets up the main `flash` target and its dependencies. diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 71d8831bd7..83606ed271 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -845,6 +845,9 @@ function(idf_build_executable elf) esptool_py_flash_target_image(app-flash app "${app_partition_offset}" "${build_dir}/${project_bin}") esptool_py_flash_target_image(flash app "${app_partition_offset}" "${build_dir}/${project_bin}") + # Setup utility targets such as monitor, erase_flash, merge-bin + __esptool_py_setup_utility_targets() + # Setup the main flash target and dependencies __esptool_py_setup_main_flash_target() From b6ea668e6e95823acdbd070f7690db78442bd53f Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Wed, 2 Jul 2025 14:55:03 +0200 Subject: [PATCH 6/8] refactor(esptool_py): Removed global scope variables from esptool_py project_include.cmake This commit global variables such as ESPTOOLPY, ESPSECUREPY, ESPEFUSEPY, ESPMONITOR and ESPTOOLPY_CHIP from the project_include.cmake file of esptool_py component. All other components which use these variables have been updated to fetch the same from esptool_py component's properties. --- components/bootloader_support/CMakeLists.txt | 5 +++-- components/esptool_py/espefuse.cmake | 12 ++++++++++++ components/esptool_py/project_include.cmake | 15 --------------- components/partition_table/CMakeLists.txt | 5 +++-- examples/system/efuse/CMakeLists.txt | 3 ++- tools/cmake/project.cmake | 3 ++- .../security/secure_boot/main/CMakeLists.txt | 14 ++++++++------ 7 files changed, 30 insertions(+), 27 deletions(-) diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index 4e477f6b59..65c9252d8d 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -153,6 +153,7 @@ if(NOT BOOTLOADER_BUILD) endif() if(CONFIG_SECURE_SIGNED_APPS AND (CONFIG_SECURE_BOOT_V1_ENABLED OR CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)) + idf_component_get_property(espsecure_py_cmd esptool_py ESPSECUREPY_CMD) if(BOOTLOADER_BUILD) # Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed # in the library. @@ -165,7 +166,7 @@ if(CONFIG_SECURE_SIGNED_APPS AND (CONFIG_SECURE_BOOT_V1_ENABLED OR CONFIG_SECURE "signature_verification_key.bin" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}") add_custom_command(OUTPUT "${secure_boot_verification_key}" - COMMAND ${ESPSECUREPY} + COMMAND ${espsecure_py_cmd} extract_public_key --keyfile "${secure_boot_signing_key}" "${secure_boot_verification_key}" DEPENDS ${secure_boot_signing_key} @@ -193,7 +194,7 @@ if(CONFIG_SECURE_SIGNED_APPS AND (CONFIG_SECURE_BOOT_V1_ENABLED OR CONFIG_SECURE ABSOLUTE BASE_DIR "${project_dir}") add_custom_command(OUTPUT "${secure_boot_verification_key}" - COMMAND ${ESPSECUREPY} + COMMAND ${espsecure_py_cmd} extract_public_key --keyfile "${secure_boot_signing_key}" "${secure_boot_verification_key}" WORKING_DIRECTORY ${project_dir} diff --git a/components/esptool_py/espefuse.cmake b/components/esptool_py/espefuse.cmake index 8911f51942..2d5d160e00 100644 --- a/components/esptool_py/espefuse.cmake +++ b/components/esptool_py/espefuse.cmake @@ -2,6 +2,18 @@ cmake_minimum_required(VERSION 3.16) # Executes a espefuse.py command and returns a cleaned log function(espefuse_cmd cmd output_log) + # espefuse_cmd can be called from a project's CMakeLists.txt file, which + # can invoke this function in CMake scripting mode (-P). If that is the case, + # we do not have access to convenience functions like idf_component_get_property. + # In scripting mode, the path to espefuse.py must be passed in via the + # 'ESPEFUSEPY' variable using the -D flag. + # + # When called during the normal build configuration phase, 'ESPEFUSEPY' is not + # defined as a variable, and we must fetch it from the esptool_py component's + # properties. + if(NOT DEFINED ESPEFUSEPY) + idf_component_get_property(ESPEFUSEPY esptool_py ESPEFUSEPY_CMD) + endif() set(SERIAL_TOOL ${ESPEFUSEPY}) if(${ESPEFUSEPY_OFFLINE}) set(VIRT_OPTION "--virt") diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake index 0a2b7ce750..170afda587 100644 --- a/components/esptool_py/project_include.cmake +++ b/components/esptool_py/project_include.cmake @@ -1,20 +1,5 @@ # esptool_py component project_include.cmake -# Many of these are read when generating flash_app_args & flash_project_args -idf_build_get_property(target IDF_TARGET) -idf_build_get_property(python PYTHON) -idf_build_get_property(idf_path IDF_PATH) - -idf_build_get_property(non_os_build NON_OS_BUILD) - -set(chip_model ${target}) - -set(ESPTOOLPY ${python} "$ENV{ESPTOOL_WRAPPER}" "${CMAKE_CURRENT_LIST_DIR}/esptool/esptool.py" --chip ${chip_model}) -set(ESPSECUREPY ${python} "${CMAKE_CURRENT_LIST_DIR}/esptool/espsecure.py") -set(ESPEFUSEPY ${python} "${CMAKE_CURRENT_LIST_DIR}/esptool/espefuse.py") -set(ESPMONITOR ${python} -m esp_idf_monitor) -set(ESPTOOLPY_CHIP "${chip_model}") - # esptool_py_partition_needs_encryption # # @brief Determine if a partition needs to be encrypted when flash encryption is enabled. diff --git a/components/partition_table/CMakeLists.txt b/components/partition_table/CMakeLists.txt index 61fe492c7b..d6b296b497 100644 --- a/components/partition_table/CMakeLists.txt +++ b/components/partition_table/CMakeLists.txt @@ -139,18 +139,19 @@ endif() # Add signing steps if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) + idf_component_get_property(espsecure_py_cmd esptool_py ESPSECUREPY_CMD) if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) add_custom_target(gen_unsigned_partition_bin ALL DEPENDS "${build_dir}/partition_table/${unsigned_partition_bin}") add_custom_command(OUTPUT "${build_dir}/partition_table/${final_partition_bin}" - COMMAND ${ESPSECUREPY} sign_data --version 1 --keyfile "${SECURE_BOOT_SIGNING_KEY}" + COMMAND ${espsecure_py_cmd} sign_data --version 1 --keyfile "${SECURE_BOOT_SIGNING_KEY}" -o "${build_dir}/partition_table/${final_partition_bin}" "${build_dir}/partition_table/${unsigned_partition_bin}" DEPENDS "${build_dir}/partition_table/${unsigned_partition_bin}" VERBATIM) else() - string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}") + string(REPLACE ";" " " espsecurepy "${espsecure_py_cmd}") add_custom_command(TARGET partition-table POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Partition table built but not signed. Sign partition data before flashing:" diff --git a/examples/system/efuse/CMakeLists.txt b/examples/system/efuse/CMakeLists.txt index 1ae11a7d56..0d8deed3e6 100644 --- a/examples/system/efuse/CMakeLists.txt +++ b/examples/system/efuse/CMakeLists.txt @@ -8,12 +8,13 @@ idf_build_set_property(MINIMAL_BUILD ON) project(efuse) idf_component_get_property(esptool_py_dir esptool_py COMPONENT_DIR) +idf_component_get_property(espefuse_py_cmd esptool_py ESPEFUSEPY_CMD) set(efuse_names "MAC" "WR_DIS") add_custom_target(efuse-filter COMMAND ${CMAKE_COMMAND} -D "IDF_PATH=${IDF_PATH}" -D "esptool_py_dir=${esptool_py_dir}" - -D "ESPEFUSEPY=${ESPEFUSEPY}" + -D "ESPEFUSEPY=${espefuse_py_cmd}" -D "ESPEFUSEPY_OFFLINE=${CONFIG_IDF_CI_BUILD}" # Only for CI tests. Do not establish a connection with the chip -D "IDF_TARGET=${IDF_TARGET}" -D "efuse_names=${efuse_names}" diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index 18d6955fa7..10839d63ef 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -948,9 +948,10 @@ macro(project project_name) # Add uf2 related targets idf_build_get_property(idf_path IDF_PATH) idf_build_get_property(python PYTHON) + idf_build_get_property(target IDF_TARGET) set(UF2_ARGS --json "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json") - set(UF2_CMD ${python} "${idf_path}/tools/mkuf2.py" write --chip ${chip_model}) + set(UF2_CMD ${python} "${idf_path}/tools/mkuf2.py" write --chip ${target}) add_custom_target(uf2 COMMAND ${CMAKE_COMMAND} diff --git a/tools/test_apps/security/secure_boot/main/CMakeLists.txt b/tools/test_apps/security/secure_boot/main/CMakeLists.txt index 5201d97810..bce7659f1a 100644 --- a/tools/test_apps/security/secure_boot/main/CMakeLists.txt +++ b/tools/test_apps/security/secure_boot/main/CMakeLists.txt @@ -9,13 +9,16 @@ idf_component_register(SRCS "${main_src}" INCLUDE_DIRS ".") target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") if(CONFIG_EXAMPLE_TARGET_QEMU) + set(PROJECT_BIN "${CMAKE_PROJECT_NAME}") set(bootloader_unsigned_bin "bootloader-unsigned.bin") set(app_unsigned_bin "${PROJECT_BIN}-unsigned.bin") + idf_component_get_property(espsecure_py_cmd esptool_py ESPSECUREPY_CMD) + add_custom_target(sign_bootloader ALL COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/bootloader/bootloader.bin" "${CMAKE_BINARY_DIR}/bootloader/${bootloader_unsigned_bin}" - COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile + COMMAND ${espsecure_py_cmd} sign_data --version 2 --keyfile ${PROJECT_DIR}/test/secure_boot_signing_key0.pem ${PROJECT_DIR}/test/secure_boot_signing_key1.pem ${PROJECT_DIR}/test/secure_boot_signing_key2.pem @@ -29,14 +32,13 @@ if(CONFIG_EXAMPLE_TARGET_QEMU) add_dependencies(sign_bootloader bootloader) add_custom_target(sign_app ALL - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/${PROJECT_BIN}.bin" "${CMAKE_BINARY_DIR}/${app_unsigned_bin}" - COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile + COMMAND ${espsecure_py_cmd} sign_data --version 2 --keyfile ${PROJECT_DIR}/test/secure_boot_signing_key1.pem - -o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" + -o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}.bin" "${CMAKE_BINARY_DIR}/${app_unsigned_bin}" - COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${CMAKE_BINARY_DIR}/${PROJECT_BIN}" - "from ${CMAKE_BINARY_DIR}/${app_unsigned_bin}" + COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${CMAKE_BINARY_DIR}/${PROJECT_BIN}.bin" VERBATIM COMMENT "Generated the test-specific signed application") From c29f473a7893521584ab45cc2dd6fefab82d021e Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Wed, 2 Jul 2025 15:27:54 +0200 Subject: [PATCH 7/8] refactor(esptool_py): Remove elf variable dependencies This commit updates all test_apps that have dependency on the elf variable. Such test_apps now fetch the executable target from the build properties. --- components/driver/test_apps/legacy_i2c_driver/CMakeLists.txt | 1 + components/driver/test_apps/legacy_twai/CMakeLists.txt | 1 + components/esp_adc/test_apps/adc/CMakeLists.txt | 1 + .../test_apps/analog_comparator/CMakeLists.txt | 1 + components/esp_driver_dac/test_apps/dac/CMakeLists.txt | 1 + components/esp_driver_gpio/test_apps/gpio/CMakeLists.txt | 1 + .../esp_driver_gpio/test_apps/gpio_extensions/CMakeLists.txt | 1 + components/esp_driver_gptimer/test_apps/gptimer/CMakeLists.txt | 1 + .../esp_driver_i2c/test_apps/i2c_test_apps/CMakeLists.txt | 1 + components/esp_driver_i2s/test_apps/i2s/CMakeLists.txt | 1 + components/esp_driver_ledc/test_apps/ledc/CMakeLists.txt | 1 + components/esp_driver_mcpwm/test_apps/mcpwm/CMakeLists.txt | 1 + components/esp_driver_parlio/test_apps/parlio/CMakeLists.txt | 1 + components/esp_driver_pcnt/test_apps/pulse_cnt/CMakeLists.txt | 1 + components/esp_driver_rmt/test_apps/rmt/CMakeLists.txt | 1 + components/esp_driver_sdm/test_apps/sigma_delta/CMakeLists.txt | 1 + components/esp_driver_spi/test_apps/master/CMakeLists.txt | 1 + components/esp_driver_spi/test_apps/slave/CMakeLists.txt | 1 + .../esp_driver_touch_sens/test_apps/touch_sens/CMakeLists.txt | 1 + components/esp_driver_twai/test_apps/test_twai/CMakeLists.txt | 2 ++ components/esp_driver_uart/test_apps/uart/CMakeLists.txt | 1 + components/esp_driver_uart/test_apps/uhci/CMakeLists.txt | 1 + components/esp_lcd/test_apps/mipi_dsi_lcd/CMakeLists.txt | 1 + components/esp_lcd/test_apps/rgb_lcd/CMakeLists.txt | 1 + components/esp_mm/test_apps/mm/CMakeLists.txt | 1 + components/esp_mm/test_apps/mmap_hw/CMakeLists.txt | 1 + components/heap/test_apps/heap_tests/CMakeLists.txt | 1 + components/spi_flash/test_apps/mspi_test/CMakeLists.txt | 1 + 28 files changed, 29 insertions(+) diff --git a/components/driver/test_apps/legacy_i2c_driver/CMakeLists.txt b/components/driver/test_apps/legacy_i2c_driver/CMakeLists.txt index 7f6a4ab7bc..447256e12b 100644 --- a/components/driver/test_apps/legacy_i2c_driver/CMakeLists.txt +++ b/components/driver/test_apps/legacy_i2c_driver/CMakeLists.txt @@ -12,6 +12,7 @@ set(COMPONENTS main esp_pm) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(legacy_i2c_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/driver/test_apps/legacy_twai/CMakeLists.txt b/components/driver/test_apps/legacy_twai/CMakeLists.txt index 205aa32c24..954671347d 100644 --- a/components/driver/test_apps/legacy_twai/CMakeLists.txt +++ b/components/driver/test_apps/legacy_twai/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(twai_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_adc/test_apps/adc/CMakeLists.txt b/components/esp_adc/test_apps/adc/CMakeLists.txt index f5a1bb70ea..9534f2424b 100644 --- a/components/esp_adc/test_apps/adc/CMakeLists.txt +++ b/components/esp_adc/test_apps/adc/CMakeLists.txt @@ -9,6 +9,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(adc_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_ana_cmpr/test_apps/analog_comparator/CMakeLists.txt b/components/esp_driver_ana_cmpr/test_apps/analog_comparator/CMakeLists.txt index 72ee984b6a..03783649e4 100644 --- a/components/esp_driver_ana_cmpr/test_apps/analog_comparator/CMakeLists.txt +++ b/components/esp_driver_ana_cmpr/test_apps/analog_comparator/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(test_ana_cmpr) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_dac/test_apps/dac/CMakeLists.txt b/components/esp_driver_dac/test_apps/dac/CMakeLists.txt index 3bb25973d8..afd43564dc 100644 --- a/components/esp_driver_dac/test_apps/dac/CMakeLists.txt +++ b/components/esp_driver_dac/test_apps/dac/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(dac_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_gpio/test_apps/gpio/CMakeLists.txt b/components/esp_driver_gpio/test_apps/gpio/CMakeLists.txt index 705e3c5154..89635577a0 100644 --- a/components/esp_driver_gpio/test_apps/gpio/CMakeLists.txt +++ b/components/esp_driver_gpio/test_apps/gpio/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(gpio_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_gpio/test_apps/gpio_extensions/CMakeLists.txt b/components/esp_driver_gpio/test_apps/gpio_extensions/CMakeLists.txt index fb191523e9..9f257cb548 100644 --- a/components/esp_driver_gpio/test_apps/gpio_extensions/CMakeLists.txt +++ b/components/esp_driver_gpio/test_apps/gpio_extensions/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(gpio_extension_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_gptimer/test_apps/gptimer/CMakeLists.txt b/components/esp_driver_gptimer/test_apps/gptimer/CMakeLists.txt index 6e95a94e77..bcf6898bfc 100644 --- a/components/esp_driver_gptimer/test_apps/gptimer/CMakeLists.txt +++ b/components/esp_driver_gptimer/test_apps/gptimer/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(gptimer_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_i2c/test_apps/i2c_test_apps/CMakeLists.txt b/components/esp_driver_i2c/test_apps/i2c_test_apps/CMakeLists.txt index ec730ed174..5588fca271 100644 --- a/components/esp_driver_i2c/test_apps/i2c_test_apps/CMakeLists.txt +++ b/components/esp_driver_i2c/test_apps/i2c_test_apps/CMakeLists.txt @@ -11,6 +11,7 @@ set(EXTRA_COMPONENT_DIRS include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(i2c_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_i2s/test_apps/i2s/CMakeLists.txt b/components/esp_driver_i2s/test_apps/i2s/CMakeLists.txt index a5d1a43fad..d0c89315d8 100644 --- a/components/esp_driver_i2s/test_apps/i2s/CMakeLists.txt +++ b/components/esp_driver_i2s/test_apps/i2s/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(i2s_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_ledc/test_apps/ledc/CMakeLists.txt b/components/esp_driver_ledc/test_apps/ledc/CMakeLists.txt index 34bad95b94..3fe082b008 100644 --- a/components/esp_driver_ledc/test_apps/ledc/CMakeLists.txt +++ b/components/esp_driver_ledc/test_apps/ledc/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(ledc_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target( check_test_app_sections ALL diff --git a/components/esp_driver_mcpwm/test_apps/mcpwm/CMakeLists.txt b/components/esp_driver_mcpwm/test_apps/mcpwm/CMakeLists.txt index 6a3fcc3a30..88727a0802 100644 --- a/components/esp_driver_mcpwm/test_apps/mcpwm/CMakeLists.txt +++ b/components/esp_driver_mcpwm/test_apps/mcpwm/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mcpwm_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_parlio/test_apps/parlio/CMakeLists.txt b/components/esp_driver_parlio/test_apps/parlio/CMakeLists.txt index 1848fb89df..fac52100ad 100644 --- a/components/esp_driver_parlio/test_apps/parlio/CMakeLists.txt +++ b/components/esp_driver_parlio/test_apps/parlio/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(parlio_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_pcnt/test_apps/pulse_cnt/CMakeLists.txt b/components/esp_driver_pcnt/test_apps/pulse_cnt/CMakeLists.txt index aac9520484..c9d2784d43 100644 --- a/components/esp_driver_pcnt/test_apps/pulse_cnt/CMakeLists.txt +++ b/components/esp_driver_pcnt/test_apps/pulse_cnt/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(pcnt_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_rmt/test_apps/rmt/CMakeLists.txt b/components/esp_driver_rmt/test_apps/rmt/CMakeLists.txt index aec93de5d1..68262acdd7 100644 --- a/components/esp_driver_rmt/test_apps/rmt/CMakeLists.txt +++ b/components/esp_driver_rmt/test_apps/rmt/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(rmt_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_sdm/test_apps/sigma_delta/CMakeLists.txt b/components/esp_driver_sdm/test_apps/sigma_delta/CMakeLists.txt index ca89d987bb..59909eae12 100644 --- a/components/esp_driver_sdm/test_apps/sigma_delta/CMakeLists.txt +++ b/components/esp_driver_sdm/test_apps/sigma_delta/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(sigma_delta_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_spi/test_apps/master/CMakeLists.txt b/components/esp_driver_spi/test_apps/master/CMakeLists.txt index 4dcfbc1419..c40f0ecc46 100644 --- a/components/esp_driver_spi/test_apps/master/CMakeLists.txt +++ b/components/esp_driver_spi/test_apps/master/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(spi_master_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_spi/test_apps/slave/CMakeLists.txt b/components/esp_driver_spi/test_apps/slave/CMakeLists.txt index 272b5680b6..cbca1ebc3c 100644 --- a/components/esp_driver_spi/test_apps/slave/CMakeLists.txt +++ b/components/esp_driver_spi/test_apps/slave/CMakeLists.txt @@ -7,6 +7,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(spi_slave_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_touch_sens/test_apps/touch_sens/CMakeLists.txt b/components/esp_driver_touch_sens/test_apps/touch_sens/CMakeLists.txt index 8c138d6cdb..9b02c7f693 100644 --- a/components/esp_driver_touch_sens/test_apps/touch_sens/CMakeLists.txt +++ b/components/esp_driver_touch_sens/test_apps/touch_sens/CMakeLists.txt @@ -8,6 +8,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(touch_sens) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_twai/test_apps/test_twai/CMakeLists.txt b/components/esp_driver_twai/test_apps/test_twai/CMakeLists.txt index 9d7ea4d248..3d053a2718 100644 --- a/components/esp_driver_twai/test_apps/test_twai/CMakeLists.txt +++ b/components/esp_driver_twai/test_apps/test_twai/CMakeLists.txt @@ -7,6 +7,8 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(test_twai) +idf_build_get_property(elf EXECUTABLE) + message(STATUS "Checking TWAI registers are not read-write by half-word") include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake) check_register_rw_half_word(SOC_MODULES "twai*" "pcr" "hp_sys_clkrst" diff --git a/components/esp_driver_uart/test_apps/uart/CMakeLists.txt b/components/esp_driver_uart/test_apps/uart/CMakeLists.txt index 35ec00faba..8b31eea32e 100644 --- a/components/esp_driver_uart/test_apps/uart/CMakeLists.txt +++ b/components/esp_driver_uart/test_apps/uart/CMakeLists.txt @@ -9,6 +9,7 @@ set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(uart_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_driver_uart/test_apps/uhci/CMakeLists.txt b/components/esp_driver_uart/test_apps/uhci/CMakeLists.txt index 1f8e0a7419..1c824f4877 100644 --- a/components/esp_driver_uart/test_apps/uhci/CMakeLists.txt +++ b/components/esp_driver_uart/test_apps/uhci/CMakeLists.txt @@ -9,6 +9,7 @@ set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(uhci_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_lcd/test_apps/mipi_dsi_lcd/CMakeLists.txt b/components/esp_lcd/test_apps/mipi_dsi_lcd/CMakeLists.txt index e895a0deed..8d9735e83a 100644 --- a/components/esp_lcd/test_apps/mipi_dsi_lcd/CMakeLists.txt +++ b/components/esp_lcd/test_apps/mipi_dsi_lcd/CMakeLists.txt @@ -10,6 +10,7 @@ project(mipi_dsi_lcd_panel_test) target_add_binary_data(mipi_dsi_lcd_panel_test.elf "resources/pictures/hello.yuv" BINARY) target_add_binary_data(mipi_dsi_lcd_panel_test.elf "resources/pictures/world.yuv" BINARY) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_lcd/test_apps/rgb_lcd/CMakeLists.txt b/components/esp_lcd/test_apps/rgb_lcd/CMakeLists.txt index 7ab2d486d5..093e4fd937 100644 --- a/components/esp_lcd/test_apps/rgb_lcd/CMakeLists.txt +++ b/components/esp_lcd/test_apps/rgb_lcd/CMakeLists.txt @@ -10,6 +10,7 @@ project(rgb_lcd_panel_test) target_add_binary_data(rgb_lcd_panel_test.elf "resources/pictures/hello.yuv" BINARY) target_add_binary_data(rgb_lcd_panel_test.elf "resources/pictures/world.yuv" BINARY) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_mm/test_apps/mm/CMakeLists.txt b/components/esp_mm/test_apps/mm/CMakeLists.txt index cf0f0e0182..439c18c227 100644 --- a/components/esp_mm/test_apps/mm/CMakeLists.txt +++ b/components/esp_mm/test_apps/mm/CMakeLists.txt @@ -20,6 +20,7 @@ if(CONFIG_SOC_MMU_PER_EXT_MEM_TARGET AND CONFIG_SPIRAM_FLASH_LOAD_TO_PSRAM) list(APPEND ignore_refs esp_mmu_map_init/*) endif() +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/esp_mm/test_apps/mmap_hw/CMakeLists.txt b/components/esp_mm/test_apps/mmap_hw/CMakeLists.txt index fac8366284..8cfc84f6ee 100644 --- a/components/esp_mm/test_apps/mmap_hw/CMakeLists.txt +++ b/components/esp_mm/test_apps/mmap_hw/CMakeLists.txt @@ -9,6 +9,7 @@ set(COMPONENTS main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mmap_hw_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py diff --git a/components/heap/test_apps/heap_tests/CMakeLists.txt b/components/heap/test_apps/heap_tests/CMakeLists.txt index f0d2972932..f5e3ef093f 100644 --- a/components/heap/test_apps/heap_tests/CMakeLists.txt +++ b/components/heap/test_apps/heap_tests/CMakeLists.txt @@ -9,6 +9,7 @@ set(COMPONENTS main) project(test_heap) +idf_build_get_property(elf EXECUTABLE) string(JOIN "," ignore_refs heap_caps_*/__func__* tlsf_*/__func__* diff --git a/components/spi_flash/test_apps/mspi_test/CMakeLists.txt b/components/spi_flash/test_apps/mspi_test/CMakeLists.txt index 4f17001095..42b2b6a669 100644 --- a/components/spi_flash/test_apps/mspi_test/CMakeLists.txt +++ b/components/spi_flash/test_apps/mspi_test/CMakeLists.txt @@ -8,6 +8,7 @@ set(COMPONENTS main esp_psram) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mspi_test) +idf_build_get_property(elf EXECUTABLE) if(CONFIG_COMPILER_DUMP_RTL_FILES) add_custom_target(check_test_app_sections ALL COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py From 7204704b53ee6c808ddf7eccfb3b93ba54f7a039 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Thu, 3 Jul 2025 18:15:46 +0200 Subject: [PATCH 8/8] refactor(esptool_py): Move flash target creation and post-build activities into separate files This commit trims the idf_build_executable() logic and refactors flash target creation, utility target creation and post-build target creation into their own separate cmake files/or functions. --- tools/cmake/build.cmake | 99 ++++--------------------- tools/cmake/flash_targets.cmake | 66 +++++++++++++++++ tools/cmake/post_build_validation.cmake | 34 +++++++++ 3 files changed, 113 insertions(+), 86 deletions(-) create mode 100644 tools/cmake/flash_targets.cmake create mode 100644 tools/cmake/post_build_validation.cmake diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 83606ed271..63b3c9837e 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -1,3 +1,7 @@ +# Include additional cmake files for specific functionalities +include("${CMAKE_CURRENT_LIST_DIR}/flash_targets.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/post_build_validation.cmake") + # idf_build_get_property # # @brief Retrieve the value of the specified property related to ESP-IDF build. @@ -776,18 +780,11 @@ function(idf_build_executable elf) # Add dependency of the build target to the executable add_dependencies(${elf} __idf_build_target) - # Set up esptool_py flash targets - # This must be done after the executable properties are set but before the function exits - # so that all components have had a chance to add their images to the phony flash targets - idf_build_get_property(bootloader_build BOOTLOADER_BUILD) - idf_build_get_property(esp_tee_build ESP_TEE_BUILD) - idf_build_get_property(target IDF_TARGET) - # This is the main orchestrator for generating binaries and flash targets # It is responsible for - # - Setting up the binary generation targets # - Setting up the signed binary generation targets - # - Setting up the main 'flash' target + # - Setting up the main 'flash' target and generating flasher_args.json # - Setting up the app-flash and flash targets # - Setting up the app_check_size target # @@ -798,6 +795,10 @@ function(idf_build_executable elf) # Note: We need to have this block here instead of in project.cmake because # idf_build_executable() is called directly when ESP-IDF is compiled # as a library (idf_as_lib). + + idf_build_get_property(bootloader_build BOOTLOADER_BUILD) + idf_build_get_property(esp_tee_build ESP_TEE_BUILD) + if(NOT bootloader_build AND NOT esp_tee_build) # All of the following logic for generating binaries and flash targets # depends on the esptool_py component. For some builds (such as those @@ -828,88 +829,14 @@ function(idf_build_executable elf) __idf_build_secure_binary("${project_bin_unsigned}" "${project_bin}" "${signed_target_name}") endif() - # The following block is placed here to ensure that the application binary is added to the 'flash' - # target's properties *before* __esptool_py_setup_main_flash_target is called. - # This is because __esptool_py_setup_main_flash_target copies properties from the 'flash' - # target to an internal '_flash_impl' target, from which the final 'flash_args' file is generated. - # If the app target is not added to the 'flash' target *before* the properties are copied, - # the app binary will be missing from the final 'flash_args' file. - # - # Set up app-flash and flash targets. The app-flash target is specifically for flashing - # just the application, while the flash target is for flashing the entire system. - idf_build_get_property(build_dir BUILD_DIR) - idf_build_get_property(project_bin PROJECT_BIN) - partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset") - esptool_py_custom_target(app-flash app "app") - - esptool_py_flash_target_image(app-flash app "${app_partition_offset}" "${build_dir}/${project_bin}") - esptool_py_flash_target_image(flash app "${app_partition_offset}" "${build_dir}/${project_bin}") + # Setup flash targets and flash configuration + __idf_build_setup_flash_targets() # Setup utility targets such as monitor, erase_flash, merge-bin __esptool_py_setup_utility_targets() - # Setup the main flash target and dependencies - __esptool_py_setup_main_flash_target() - - # Generate flasher_args.json for tools that need it. The variables below are used - # in configuring the template flasher_args.json.in. - # Some of the variables (flash mode, size, frequency) are set as esptool_py component's properties. - - idf_build_get_property(target IDF_TARGET) - set(ESPTOOLPY_CHIP "${target}") - set(ESPTOOLPY_BEFORE "${CONFIG_ESPTOOLPY_BEFORE}") - set(ESPTOOLPY_AFTER "${CONFIG_ESPTOOLPY_AFTER}") - if(CONFIG_ESPTOOLPY_NO_STUB) - set(ESPTOOLPY_WITH_STUB false) - else() - set(ESPTOOLPY_WITH_STUB true) - endif() - - if(CONFIG_SECURE_BOOT OR CONFIG_SECURE_FLASH_ENC_ENABLED) - # If security enabled then override post flash option - set(ESPTOOLPY_AFTER "no_reset") - endif() - - idf_component_get_property(ESPFLASHMODE esptool_py ESPFLASHMODE) - idf_component_get_property(ESPFLASHFREQ esptool_py ESPFLASHFREQ) - idf_component_get_property(ESPFLASHSIZE esptool_py ESPFLASHSIZE) - idf_component_get_property(esptool_py_dir esptool_py COMPONENT_DIR) - - # Generate flasher args files - file(READ "${esptool_py_dir}/flasher_args.json.in" flasher_args_content) - string(CONFIGURE "${flasher_args_content}" flasher_args_content) - - # We need to create a flasher_args.json.in to create the final flasher_args.json - # because CMake only resolves generator expressions in the file_generate command - # with the INPUT keyword during the generation phase. - file_generate("${build_dir}/flasher_args.json.in" - CONTENT "${flasher_args_content}") - file_generate("${build_dir}/flasher_args.json" - INPUT "${build_dir}/flasher_args.json.in") - - # Create the following post-build targets after __idf_build_binary() is called to ensure that the - # app target is available. - - # If anti-rollback option is set then factory partition should not be in Partition Table. - # In this case, should be used the partition table with two ota app without the factory. - partition_table_get_partition_info(factory_offset - "--partition-type app --partition-subtype factory" "offset") - partition_table_get_partition_info(test_offset "--partition-type app --partition-subtype test" "offset") - if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND (factory_offset OR test_offset)) - fail_at_build_time(check_table_contents "\ - ERROR: Anti-rollback option is enabled. Partition table should \ - consist of two ota app without factory or test partitions.") - add_dependencies(app check_table_contents) - endif() - - if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT) - # Generate app_check_size_command target to check the app size against the partition table parameters - partition_table_add_check_size_target(app_check_size - DEPENDS gen_project_binary - BINARY_PATH "${build_dir}/${project_bin}" - PARTITION_TYPE app) - add_dependencies(app app_check_size) - endif() + # Setup post-build validation checks + __idf_build_setup_post_build_validation() endif() # if(TARGET idf::esptool_py AND CONFIG_APP_BUILD_GENERATE_BINARIES) endif() # if(NOT bootloader_build AND NOT esp_tee_build) endfunction() diff --git a/tools/cmake/flash_targets.cmake b/tools/cmake/flash_targets.cmake new file mode 100644 index 0000000000..9856bf7d3d --- /dev/null +++ b/tools/cmake/flash_targets.cmake @@ -0,0 +1,66 @@ +# flash_targets.cmake +# +# Functions for setting up flash-related targets and configuration + +# +# Setup flash targets for the application +# +function(__idf_build_setup_flash_targets) + # Set up app-flash and flash targets. The app-flash target is specifically for flashing + # just the application, while the flash target is for flashing the entire system. + idf_build_get_property(build_dir BUILD_DIR) + idf_build_get_property(project_bin PROJECT_BIN) + partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset") + esptool_py_custom_target(app-flash app "app") + + esptool_py_flash_target_image(app-flash app "${app_partition_offset}" "${build_dir}/${project_bin}") + esptool_py_flash_target_image(flash app "${app_partition_offset}" "${build_dir}/${project_bin}") + + # Setup the main flash target and dependencies + __esptool_py_setup_main_flash_target() + + # Generate flasher_args.json configuration files + __idf_build_generate_flasher_args() +endfunction() + +# +# Generate flasher_args.json configuration files +# +function(__idf_build_generate_flasher_args) + # Generate flasher_args.json for tools that need it. The variables below are used + # in configuring the template flasher_args.json.in. + # Some of the variables (flash mode, size, frequency) are set as esptool_py component's properties. + + idf_build_get_property(target IDF_TARGET) + set(ESPTOOLPY_CHIP "${target}") + set(ESPTOOLPY_BEFORE "${CONFIG_ESPTOOLPY_BEFORE}") + set(ESPTOOLPY_AFTER "${CONFIG_ESPTOOLPY_AFTER}") + if(CONFIG_ESPTOOLPY_NO_STUB) + set(ESPTOOLPY_WITH_STUB false) + else() + set(ESPTOOLPY_WITH_STUB true) + endif() + + if(CONFIG_SECURE_BOOT OR CONFIG_SECURE_FLASH_ENC_ENABLED) + # If security enabled then override post flash option + set(ESPTOOLPY_AFTER "no_reset") + endif() + + idf_component_get_property(ESPFLASHMODE esptool_py ESPFLASHMODE) + idf_component_get_property(ESPFLASHFREQ esptool_py ESPFLASHFREQ) + idf_component_get_property(ESPFLASHSIZE esptool_py ESPFLASHSIZE) + idf_component_get_property(esptool_py_dir esptool_py COMPONENT_DIR) + + # Generate flasher args files + idf_build_get_property(build_dir BUILD_DIR) + file(READ "${esptool_py_dir}/flasher_args.json.in" flasher_args_content) + string(CONFIGURE "${flasher_args_content}" flasher_args_content) + + # We need to create a flasher_args.json.in to create the final flasher_args.json + # because CMake only resolves generator expressions in the file_generate command + # with the INPUT keyword during the generation phase. + file_generate("${build_dir}/flasher_args.json.in" + CONTENT "${flasher_args_content}") + file_generate("${build_dir}/flasher_args.json" + INPUT "${build_dir}/flasher_args.json.in") +endfunction() diff --git a/tools/cmake/post_build_validation.cmake b/tools/cmake/post_build_validation.cmake new file mode 100644 index 0000000000..8e7568e4c1 --- /dev/null +++ b/tools/cmake/post_build_validation.cmake @@ -0,0 +1,34 @@ +# post_build_validation.cmake +# +# Functions for post-build validation and checks + +# +# Setup post-build validation checks +# +function(__idf_build_setup_post_build_validation) + # Create the following post-build targets after __idf_build_binary() is called to ensure that the + # app target is available. + + # If anti-rollback option is set then factory partition should not be in Partition Table. + # In this case, should be used the partition table with two ota app without the factory. + partition_table_get_partition_info(factory_offset + "--partition-type app --partition-subtype factory" "offset") + partition_table_get_partition_info(test_offset "--partition-type app --partition-subtype test" "offset") + if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND (factory_offset OR test_offset)) + fail_at_build_time(check_table_contents "\ + ERROR: Anti-rollback option is enabled. Partition table should \ + consist of two ota app without factory or test partitions.") + add_dependencies(app check_table_contents) + endif() + + if(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT) + # Generate app_check_size_command target to check the app size against the partition table parameters + idf_build_get_property(build_dir BUILD_DIR) + idf_build_get_property(project_bin PROJECT_BIN) + partition_table_add_check_size_target(app_check_size + DEPENDS gen_project_binary + BINARY_PATH "${build_dir}/${project_bin}" + PARTITION_TYPE app) + add_dependencies(app app_check_size) + endif() +endfunction()