diff --git a/tools/cmakev2/utilities.cmake b/tools/cmakev2/utilities.cmake index 36715986407..28588cba59c 100644 --- a/tools/cmakev2/utilities.cmake +++ b/tools/cmakev2/utilities.cmake @@ -819,7 +819,12 @@ function(target_add_binary_data target embed_file embed_type) idf_build_get_property(build_dir BUILD_DIR) idf_build_get_property(idf_path IDF_PATH) - get_filename_component(embed_file "${embed_file}" ABSOLUTE) + # The target_add_binary_data function is also called within the + # idf_component_include function, which is not executed in the component + # directory context. Therefore, ensure that the absolute path of the + # embedded file is resolved relative to the component directory. + idf_component_get_property(component_directory "${target}" COMPONENT_DIR) + get_filename_component(embed_file "${embed_file}" ABSOLUTE BASE_DIR "${component_directory}") get_filename_component(name "${embed_file}" NAME) set(embed_srcfile "${build_dir}/${name}.S") @@ -841,6 +846,22 @@ function(target_add_binary_data target embed_file embed_type) WORKING_DIRECTORY "${build_dir}" VERBATIM) + # A file generated by `add_custom_command` can be used as a dependency only + # within the directory context where the target was created (see + # https://cmake.org/cmake/help/latest/command/add_custom_command.html). + # Since embedded files are collected in the EMBED_FILES and EMBED_TXTFILES + # component properties, and the source files are generated in the + # idf_component_include function, which is not called in the component’s + # directory context, we must create an explicit target and add it as a + # dependency of the component target. To avoid potential target name + # collisions with embedded files that share the same name but reside in + # different directories, add a hash of the full embedded file path to + # the generated target name. + string(MD5 hash "${embed_file}") + string(MAKE_C_IDENTIFIER "gen_${name}_${hash}" embed_srcfile_target) + add_custom_target(${embed_srcfile_target} DEPENDS "${embed_srcfile}") + add_dependencies(${target} ${embed_srcfile_target}) + set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_CLEAN_FILES "${embed_srcfile}") target_sources("${target}" PRIVATE "${embed_srcfile}")