diff --git a/tools/cmakev2/compat.cmake b/tools/cmakev2/compat.cmake index cfac2f8bdc6..aad749ca9cb 100644 --- a/tools/cmakev2/compat.cmake +++ b/tools/cmakev2/compat.cmake @@ -702,8 +702,30 @@ function(idf_component_register) # Embedded files are managed in the idf_component_include function. idf_component_set_property("${COMPONENT_NAME}" EMBED_FILES "${ARG_EMBED_FILES}") idf_component_set_property("${COMPONENT_NAME}" EMBED_TXTFILES "${ARG_EMBED_TXTFILES}") - idf_component_set_property("${COMPONENT_NAME}" REQUIRES "${ARG_REQUIRES}") - idf_component_set_property("${COMPONENT_NAME}" PRIV_REQUIRES "${ARG_PRIV_REQUIRES}") + # The component manager's dependency injection runs before this component's + # CMakeLists.txt is evaluated (see idf_component_include() in + # component.cmake), and writes the manifest-derived names into both the + # MANAGED_* properties and the regular REQUIRES / PRIV_REQUIRES properties. + # The latter must not be overwritten by the component's own register call, + # else the manifest-derived transitive deps disappear from the build. Union + # the two so the persisted property is what the component author wrote + # PLUS what the manifest contributed. + idf_component_get_property(__existing_requires "${COMPONENT_NAME}" REQUIRES) + idf_component_get_property(__existing_priv_requires "${COMPONENT_NAME}" PRIV_REQUIRES) + set(__merged_requires "${ARG_REQUIRES}") + set(__merged_priv_requires "${ARG_PRIV_REQUIRES}") + foreach(__r IN LISTS __existing_requires) + if(__r AND NOT __r IN_LIST __merged_requires) + list(APPEND __merged_requires "${__r}") + endif() + endforeach() + foreach(__r IN LISTS __existing_priv_requires) + if(__r AND NOT __r IN_LIST __merged_priv_requires) + list(APPEND __merged_priv_requires "${__r}") + endif() + endforeach() + idf_component_set_property("${COMPONENT_NAME}" REQUIRES "${__merged_requires}") + idf_component_set_property("${COMPONENT_NAME}" PRIV_REQUIRES "${__merged_priv_requires}") idf_component_set_property("${COMPONENT_NAME}" REQUIRED_IDF_TARGETS "${ARG_REQUIRED_IDF_TARGETS}") idf_component_set_property("${COMPONENT_NAME}" COMPONENT_TYPE "${component_type}") endfunction() diff --git a/tools/cmakev2/component.cmake b/tools/cmakev2/component.cmake index cde6f103d8f..021dd9d357c 100644 --- a/tools/cmakev2/component.cmake +++ b/tools/cmakev2/component.cmake @@ -925,6 +925,29 @@ function(idf_component_include name) endif() list(APPEND __DEPENDENCY_CHAIN "${component_interface}") + + # Inject managed dependencies BEFORE add_subdirectory() evaluates the + # component's CMakeLists.txt — otherwise any component that queries a + # managed dependency at register time via + # idf_component_get_property(... COMPONENT_LIB) finds nothing because the + # target hasn't been created yet. + idf_build_get_property(idf_component_manager IDF_COMPONENT_MANAGER) + if(idf_component_manager EQUAL 1) + idf_component_get_property(_comp_dir "${component_name}" COMPONENT_DIR) + if(EXISTS "${_comp_dir}/idf_component.yml") + __inject_requirements_for_component_from_manager("${component_name}") + + idf_component_get_property(_managed_req "${component_name}" MANAGED_REQUIRES) + idf_component_get_property(_managed_priv_req "${component_name}" MANAGED_PRIV_REQUIRES) + + foreach(_dep IN LISTS _managed_req _managed_priv_req) + if(_dep) + idf_component_include("${_dep}") + endif() + endforeach() + endif() + endif() + # Evaluate the CMakeLists.txt file of the component. idf_component_get_property(component_build_dir "${component_name}" COMPONENT_BUILD_DIR) add_subdirectory("${component_directory}" "${component_build_dir}") @@ -1011,25 +1034,16 @@ function(idf_component_include name) target_add_binary_data(${COMPONENT_TARGET} "${file}" "TEXT") endforeach() - # Inject managed dependencies if component manager is enabled + # Link managed dependencies for cmakev1 components (backward compat). + # The injection and inclusion already happened before add_subdirectory(). idf_build_get_property(idf_component_manager IDF_COMPONENT_MANAGER) idf_component_get_property(component_format "${component_name}" COMPONENT_FORMAT) if(idf_component_manager EQUAL 1) idf_component_get_property(component_dir "${component_name}" COMPONENT_DIR) - # Check if component has manifest for managed dependency injection if(EXISTS "${component_dir}/idf_component.yml") - __inject_requirements_for_component_from_manager("${component_name}") - - # Include any managed dependencies idf_component_get_property(managed_requires "${component_name}" MANAGED_REQUIRES) idf_component_get_property(managed_priv_requires "${component_name}" MANAGED_PRIV_REQUIRES) - foreach(dep IN LISTS managed_requires managed_priv_requires) - if(dep) - idf_component_include("${dep}") - endif() - endforeach() - # For cmakev1 components, automatically link managed dependencies to maintain # backward compatibility. if("${component_format}" STREQUAL "CMAKEV1")