diff --git a/tools/cmakev2/build.cmake b/tools/cmakev2/build.cmake index 8084e9095b..ae15ca22a7 100644 --- a/tools/cmakev2/build.cmake +++ b/tools/cmakev2/build.cmake @@ -112,6 +112,32 @@ function(__dump_build_properties) endforeach() endfunction() +#[[ + __idf_build_dispatch_build_event( ) + + *event[in]* + + Build event name. Currently only ``POST_ELF`` is supported. Other build + events may be extended when required. + + *target[in]* + + Name of the primary CMake target at this event point. Passed as the + sole argument to every registered callback so that callbacks can + operate on the correct target without querying build properties. + For ``POST_ELF`` this is the executable target name. + + Internal dispatcher called by the build system at well-defined lifecycle + points. Invokes every CMake function registered for + ``event`` via ``idf_component_register_build_event_callback``. +#]] +function(__idf_build_dispatch_build_event event target) + idf_build_get_property(callbacks "__BUILD_EVENT_CALLBACKS_${event}") + foreach(cb IN LISTS callbacks) + cmake_language(CALL "${cb}" "${target}") + endforeach() +endfunction() + #[[ __get_library_interface_or_die(LIBRARY OUTPUT ) @@ -610,6 +636,9 @@ function(idf_build_executable executable) endif() set_target_properties(${executable} PROPERTIES LIBRARY_INTERFACE ${library}) + + # Dispatch POST_ELF event once the executable target exists + __idf_build_dispatch_build_event(POST_ELF "${executable}") endfunction() #[[ diff --git a/tools/cmakev2/component.cmake b/tools/cmakev2/component.cmake index c8bd118c4f..a0262a9ac8 100644 --- a/tools/cmakev2/component.cmake +++ b/tools/cmakev2/component.cmake @@ -1058,3 +1058,62 @@ function(idf_component_include name) idf_build_get_compile_options(compile_options) target_compile_options("${component_real_target}" BEFORE PRIVATE "${compile_options}") endfunction() + +#[[api +.. cmakev2:function:: idf_component_register_build_event_callback + + .. code-block:: cmake + + idf_component_register_build_event_callback(EVENT CALLBACK ) + + *EVENT[in]* + + Build lifecycle event at which the callback will be invoked. Currently + only ``POST_ELF`` is supported. + + *CALLBACK[in]* + + Name of a CMake function defined in the component's project_include.cmake file. + The build system calls this function with the primary CMake target as its argument + at the specified event point. For ``POST_ELF`` this is the executable target. + + Example:: + + # project_include.cmake + function(my_component_post_elf_hook target) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND my_tool "$") + endfunction() + + idf_component_register_build_event_callback( + EVENT POST_ELF + CALLBACK my_component_post_elf_hook) + +#]] +function(idf_component_register_build_event_callback) + set(options) + set(one_value EVENT CALLBACK) + set(multi_value) + cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + if(NOT DEFINED ARG_EVENT) + idf_die("idf_component_register_build_event_callback: EVENT option is required") + endif() + + if(NOT DEFINED ARG_CALLBACK) + idf_die("idf_component_register_build_event_callback: CALLBACK option is required") + endif() + + set(valid_events POST_ELF) + if(NOT "${ARG_EVENT}" IN_LIST valid_events) + idf_die("idf_component_register_build_event_callback: unknown event '${ARG_EVENT}'. " + "Valid events: ${valid_events}") + endif() + + if(NOT COMMAND "${ARG_CALLBACK}") + idf_die("idf_component_register_build_event_callback: callback '${ARG_CALLBACK}' " + "is not a known CMake function. Define it before calling this function.") + endif() + + idf_build_set_property("__BUILD_EVENT_CALLBACKS_${ARG_EVENT}" "${ARG_CALLBACK}" APPEND) +endfunction()