fix(cmakev2/build): pass binary target to idf_build_generate_metadata

Currently, the `idf_build_generate_metadata` function takes an
executable target as an argument, and the binary name is stored in the
`EXECUTABLE_BINARY` property. This approach is inconvenient because a
single executable might generate multiple binary images, making it
unreliable to store the binary image name in the executable property due
to the N:1 relationship. To address this, pass the binary image target
instead of the executable target to the `idf_build_generate_metadata`
function. This change is facilitated by linking the binary target,
executable target, and library interface targets with the following
properties:

binary:EXECUTABLE_TARGET -> executable:LIBRARY_INTERFACE -> library

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
This commit is contained in:
Frantisek Hrbata
2025-11-17 11:37:46 +01:00
parent 5130b7d228
commit e97027214e
4 changed files with 67 additions and 35 deletions
+42 -18
View File
@@ -507,7 +507,9 @@ endfunction()
``executable`` argument, and link it to the library created with the
component names provided in the ``COMPONENTS`` option. If the
``COMPONENTS`` option is not set, all discovered components are added to
the library. Optinaly set the executable name and suffix.
the library. Optionally set the executable name and suffix. The executable
library target name is added to the ``LIBRARY_INTERFACE`` executable
property.
#]]
function(idf_build_executable executable)
set(options)
@@ -543,6 +545,8 @@ function(idf_build_executable executable)
endif()
target_link_libraries(${executable} PRIVATE ${library})
set_target_properties(${executable} PROPERTIES LIBRARY_INTERFACE ${library})
endfunction()
#[[
@@ -647,28 +651,34 @@ endfunction()
.. code-block:: cmake
idf_build_generate_metadata(<executable>
idf_build_generate_metadata(<binary>
[FILE <file>])
*executable[in]*
*binary[in]*
Executable target for which to generate a metadata file.
Binary target for which to generate a metadata file.
*OUTPUT_FILE[in,opt]*
Optional output file path for storing the metadata. If not provided,
the default path ``<build>/project_description.json`` is used.
Generate metadata for the specified ``executable`` and store it in the
Generate metadata for the specified ``binary`` and store it in the
specified ``FILE``. If no ``FILE`` is provided, the default location
``<build>/project_description.json`` will be used.
#]]
function(idf_build_generate_metadata executable)
function(idf_build_generate_metadata binary)
set(options)
set(one_value OUTPUT_FILE)
set(multi_value)
cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN})
# The EXECUTABLE_TARGET property is set by the idf_build_binary or
# the idf_sign_binary function.
get_target_property(executable "${binary}" EXECUTABLE_TARGET)
if(NOT executable)
idf_die("Binary target '${binary}' is missing 'EXECUTABLE_TARGET' property.")
endif()
__get_executable_library_or_die(TARGET "${executable}" OUTPUT library)
idf_build_get_property(PROJECT_NAME PROJECT_NAME)
@@ -679,9 +689,13 @@ function(idf_build_generate_metadata executable)
idf_build_get_property(SDKCONFIG SDKCONFIG)
idf_build_get_property(SDKCONFIG_DEFAULTS SDKCONFIG_DEFAULTS)
set(PROJECT_EXECUTABLE "$<TARGET_FILE_NAME:${executable}>")
# The PROJECT_BIN executable property must be set by the idf_build_binary
# function.
get_target_property(PROJECT_BIN "${executable}" EXECUTABLE_BINARY)
# The BINARY_PATH property is set by the idf_build_binary or
# the idf_sign_binary function.
get_target_property(binary_path ${binary} BINARY_PATH)
if(NOT binary_path)
idf_die("Binary target '${binary}' is missing 'BINARY_PATH' property.")
endif()
get_filename_component(PROJECT_BIN "${binary_path}" NAME)
if(NOT PROJECT_BIN)
set(PROJECT_BIN "")
endif()
@@ -767,8 +781,9 @@ endfunction()
Create a binary image for the specified ``executable`` target and save it
in the file specified with the ``OUTPUT_FILE`` option. A custom target
named ``TARGET`` will be created for the generated binary image. The path
of the generated binary image will be also stored in the ``BINARY_PATH``
property of the ``TARGET``.
of the generated binary image will be stored in the ``BINARY_PATH``
property and the executable target in the ``EXECUTABLE_TARGET`` property of
the ``TARGET``.
#]]
function(idf_build_binary executable)
set(options)
@@ -828,13 +843,13 @@ function(idf_build_binary executable)
# Create a custom target to generate the binary file
add_custom_target(${ARG_TARGET} DEPENDS "${ARG_OUTPUT_FILE}")
# The EXECUTABLE_BINARY property is used by idf_build_generate_metadata to
# store the name of the binary image.
set_target_properties(${executable} PROPERTIES EXECUTABLE_BINARY ${binary_name})
# Store the path of the binary file in the BINARY_PATH property of the
# custom binary target, which is used by the idf_flash_binary.
set_target_properties(${ARG_TARGET} PROPERTIES BINARY_PATH ${ARG_OUTPUT_FILE})
# Store executable target name in the EXECUTABLE_TARGET property. This is used
# by the idf_build_generate_metadata function.
set_target_properties(${ARG_TARGET} PROPERTIES EXECUTABLE_TARGET ${executable})
endfunction()
#[[
@@ -870,9 +885,10 @@ endfunction()
Sign binary image specified by ``binary`` target with ``KEYFILE`` and save
it in the file specified with the `OUTPUT_FILE` option. A custom target
named ``TARGET`` will be created for the signed binary image. The path of
the signed binary image will be also stored in the ``BINARY_PATH`` property
of the ``TARGET``.
named ``TARGET`` will be created for the signed binary image. The path of
the signed binary image will be stored in the ``BINARY_PATH`` property and
the executable target in the ``EXECUTABLE_TARGET`` property of the
``TARGET``.
#]]
function(idf_sign_binary binary)
set(options)
@@ -936,6 +952,14 @@ function(idf_sign_binary binary)
# Store the path of the binary file in the BINARY_PATH property of the
# custom signed binary target, which is used by the idf_flash_binary.
set_target_properties(${ARG_TARGET} PROPERTIES BINARY_PATH ${ARG_OUTPUT_FILE})
# Store executable target name in the EXECUTABLE_TARGET property. This is used
# by the idf_build_generate_metadata function.
get_target_property(executable "${binary}" EXECUTABLE_TARGET)
if(NOT executable)
idf_die("Binary target '${binary}' is missing 'EXECUTABLE_TARGET' property.")
endif()
set_target_properties(${ARG_TARGET} PROPERTIES EXECUTABLE_TARGET ${executable})
endfunction()
#[[
+2 -2
View File
@@ -734,6 +734,7 @@ macro(idf_project_default)
TARGET app-flash
NAME "app"
FLASH)
idf_build_generate_metadata("${executable}_binary_signed")
else()
idf_build_binary("${executable}"
OUTPUT_FILE "${build_dir}/${executable}.bin"
@@ -750,6 +751,7 @@ macro(idf_project_default)
idf_create_dfu("${executable}_binary"
TARGET dfu)
idf_build_generate_metadata("${executable}_binary")
endif()
idf_build_generate_flasher_args()
@@ -769,8 +771,6 @@ macro(idf_project_default)
TARGET uf2-app
APP_ONLY)
idf_build_generate_metadata("${executable}")
unset(build_dir)
unset(executable)
endmacro()
+2 -2
View File
@@ -229,7 +229,7 @@ function(test_executable)
NAME fatfs_example)
idf_create_menuconfig(fatfs_example
TARGET menuconfig-fatfs)
idf_build_generate_metadata(fatfs_example
idf_build_generate_metadata(fatfs_example_bin
OUTPUT_FILE project_description_fatfs.json)
idf_create_confserver(fatfs_example
TARGET confserver-fatfs)
@@ -246,7 +246,7 @@ function(test_executable)
NAME hello_world_example)
idf_create_menuconfig(hello_world_example
TARGET menuconfig-hello_world)
idf_build_generate_metadata(hello_world_example
idf_build_generate_metadata(hello_world_example_bin
OUTPUT_FILE project_description_hello_world.json)
idf_create_confserver(hello_world_example
TARGET confserver-hello_world)
+21 -13
View File
@@ -981,11 +981,12 @@ endfunction()
Output variable to store the library interface target linked to the
executable.
Search for the library interface target created with the
idf_build_library() function and linked to the executable, examine the
LINK_LIBRARIES for the executable and the LIBRARY_INTERFACES build
property, which stores all library interface targets created by the
idf_build_library() function.
Search for the library interface target in the LIBRARY_INTERFACE executable
property. If not found, search for the library interface target created with
the idf_build_library() function and linked to the executable. Examine the
LINK_LIBRARIES for the executable and the LIBRARY_INTERFACES build property,
which stores all library interface targets created by the idf_build_library()
function.
#]]
function(__get_executable_library_or_die)
set(options)
@@ -1007,15 +1008,22 @@ function(__get_executable_library_or_die)
"but an 'EXECUTABLE' target type is expected.")
endif()
set(library NOTFOUND)
get_target_property(targets "${ARG_TARGET}" LINK_LIBRARIES)
idf_build_get_property(libraries LIBRARY_INTERFACES)
foreach(target IN LISTS targets)
if("${target}" IN_LIST libraries)
set(library "${target}")
break()
endif()
endforeach()
get_target_property(library "${ARG_TARGET}" LIBRARY_INTERFACE)
if(NOT "${library}" IN_LIST libraries)
# The library interface is not stored in the LIBRARY_INTERFACE
# executable property, so the executable was not created by the
# idf_build_executable function. Try searching for the library
# interface in the LINK_LIBRARIES property.
set(library NOTFOUND)
get_target_property(targets "${ARG_TARGET}" LINK_LIBRARIES)
foreach(target IN LISTS targets)
if("${target}" IN_LIST libraries)
set(library "${target}")
break()
endif()
endforeach()
endif()
if("${library}" STREQUAL "NOTFOUND")
idf_die("No library interface target linked to the '${ARG_TARGET}' executable")