Merge branch 'fix/cmakev2_idf_component_optional_requires' into 'master'

fix(cmakev2/compat): change idf_component_optional_requires behavior

Closes IDFGH-17112

See merge request espressif/esp-idf!45588
This commit is contained in:
Frantisek Hrbata
2026-02-12 08:50:24 +01:00
2 changed files with 38 additions and 8 deletions
+7
View File
@@ -432,6 +432,13 @@ Strict Component Precedence
The v2 strictly adheres to the component precedence for components with the same name, as described in :ref:`cmake-components-same-name`. While v1 allows components discovered in directories specified with the ``EXTRA_COMPONENT_DIRS`` variable to be overridden by `Local Directory Dependencies`_ specified in the ``idf_component.yml`` manifest file, this is no longer possible in v2.
The Behavior of ``idf_component_optional_requires`` has Changed
---------------------------------------------------------------
In v1, the ``idf_component_optional_requires`` function adds a dependency on a specified component only if that component is already included in the build (for instance, if it is already required by another component). To achieve this, v1 examines the ``BUILD_COMPONENTS`` build property, which is generated during the early evaluation phase and lists all components involved in the build.
In v2, the ``BUILD_COMPONENTS`` build property is no longer available because the early evaluation phase has been removed. Consequently, the function now adds the dependency if the component is recognized by the build system. This behavior may pull unnecessary components into the build, leading to longer build times. Using ``idf_component_optional_requires`` in v2 should be avoided, instead, optional dependencies should be added using conditional logic based on the project configuration.
API Reference
=============
+31 -8
View File
@@ -211,21 +211,44 @@ endfunction()
The component name that should be added as a dependency to the
evaluated component. It may be provided multiple times.
Add a dependency on a specific component only if it is included in the
build.
Add a dependency on a specific component only if the component is
recognized by the build system. The component is included if needed and
added as a requirement for the currently evaluated component using
target_link_libraries. This function should be avoided in cmakev2, where
dependencies should be added based on configuration options. This is purely
for backward compatibility with cmakev1.
#]]
function(idf_component_optional_requires req_type)
function(idf_component_optional_requires type)
set(optional_reqs ${ARGN})
foreach(req ${optional_reqs})
__get_component_interface(COMPONENT "${req}" OUTPUT req_interface)
if("${req_interface}" STREQUAL "NOTFOUND")
# The component is not recognized by the build system.
continue()
endif()
idf_component_get_property(req_alias "${req}" COMPONENT_ALIAS)
# The component alias is created only after the component is included,
# meaning the add_subdirectory command for it has been called. This can
# be used to detect if a component has already been added to the build.
target_link_libraries(${COMPONENT_TARGET} ${req_type} "$<$<TARGET_EXISTS:${req_alias}>:${req_interface}>")
idf_component_include("${req}")
# Map the requested type into PRIV_REQUIRES and REQUIRES, allowing the
# requirement to be added to the appropriate component dependency
# property.
if("${type}" STREQUAL "PRIVATE")
set(req_type PRIV_REQUIRES)
elseif("${type}" STREQUAL "PUBLIC")
set(req_type REQUIRES)
else()
set(req_type "")
endif()
if(req_type)
idf_component_get_property(req_name "${req}" COMPONENT_NAME)
idf_component_get_property(target_reqs ${COMPONENT_TARGET} ${req_type})
if(NOT "${req_name}" IN_LIST target_reqs)
idf_component_set_property(${COMPONENT_TARGET} ${req_type} "${req_name}" APPEND)
target_link_libraries(${COMPONENT_TARGET} ${type} ${req_interface})
endif()
else()
target_link_libraries(${COMPONENT_TARGET} ${type} ${req_interface})
endif()
endforeach()
endfunction()