mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
fix(cmakev2/component_validation): accelerate component validation
The commitf951ae5b18("feat(cmakev2): Added component validation checks for ...") introduced support for validating component sources and include directories. It heavily relies on iterating through the registered components to obtain their properties. For instance, it examines all components for each component source file to ensure that the source files do not originate from other components. However, it turns out that `idf_component_get_property` is a bottleneck in this process, causing reconfiguration to take 3-4 times longer than before the introduction of this check. Since we know of all the component interfaces, we can bypass the checks performed by `idf_component_get_property` and instead use the raw version, `__idf_component_get_property_unchecked`, which operates much faster. Following are hello_world example reconfigure times before and after. before: -- Configuring done (11.1s) -- Generating done (0.2s) after: -- Configuring done (3.9s) -- Generating done (0.2s) A new library property LIBRARY_COMPONENT_INTERFACES_LINKED is added that keeps component interfaces linked to the library. Fixes:f951ae5b18("feat(cmakev2): Added component validation checks for ..") Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
This commit is contained in:
@@ -289,8 +289,13 @@ endfunction()
|
||||
List of component as specified by the ``COMPONENTS`` option.
|
||||
|
||||
LIBRARY_COMPONENTS_LINKED
|
||||
List of components linked to the library based on recursive evaluations
|
||||
List of component names linked to the library based on recursive evaluations
|
||||
of the INTERFACE_LINK_LIBRARIES and LINK_LIBRARIES target properties.
|
||||
|
||||
LIBRARY_COMPONENT_INTERFACES_LINKED
|
||||
List of component interfaces linked to the library based on recursive
|
||||
evaluations of the INTERFACE_LINK_LIBRARIES and LINK_LIBRARIES target
|
||||
properties.
|
||||
#]]
|
||||
function(idf_build_library library)
|
||||
set(options)
|
||||
@@ -336,26 +341,27 @@ function(idf_build_library library)
|
||||
|
||||
# Identify the components linked to the library by looking at all targets
|
||||
# that are transitively linked to the library and mapping these targets to
|
||||
# components. Store the linked component interfaces in
|
||||
# LIBRARY_COMPONENTS_LINKED property.
|
||||
set(component_interfaces_linked)
|
||||
# components. Store the linked component name in LIBRARY_COMPONENTS_LINKED
|
||||
# and component interface in LIBRARY_COMPONENT_INTERFACES_LINKED property.
|
||||
foreach(dep IN LISTS dependencies)
|
||||
__get_component_interface(COMPONENT "${dep}" OUTPUT component_interface)
|
||||
if(NOT component_interface)
|
||||
continue()
|
||||
endif()
|
||||
idf_library_get_property(component_interfaces_linked "${library}" LIBRARY_COMPONENT_INTERFACES_LINKED)
|
||||
if("${component_interface}" IN_LIST component_interfaces_linked)
|
||||
continue()
|
||||
endif()
|
||||
|
||||
list(APPEND component_interfaces_linked "${component_interface}")
|
||||
idf_component_get_property(component_name "${component_interface}" COMPONENT_NAME)
|
||||
idf_library_set_property("${library}" LIBRARY_COMPONENTS_LINKED "${component_name}" APPEND)
|
||||
idf_library_set_property("${library}" LIBRARY_COMPONENT_INTERFACES_LINKED "${component_interface}" APPEND)
|
||||
endforeach()
|
||||
|
||||
# Collect linker fragment files from all components linked to the library
|
||||
# interface and store them in the __LDGEN_FRAGMENT_FILES files. This
|
||||
# property is used by ldgen to generate template-based linker scripts.
|
||||
idf_library_get_property(component_interfaces_linked "${library}" LIBRARY_COMPONENT_INTERFACES_LINKED)
|
||||
foreach(component_interface IN LISTS component_interfaces_linked)
|
||||
idf_component_get_property(component_ldfragments "${component_interface}" LDFRAGMENTS)
|
||||
idf_component_get_property(component_directory "${component_interface}" COMPONENT_DIR)
|
||||
@@ -369,6 +375,7 @@ function(idf_build_library library)
|
||||
# mutable, in the __LDGEN_MUTABLE_LIBS library property. These libraries
|
||||
# are placed by ldgen into a separate location in the linker script,
|
||||
# enabling the fast reflashing feature.
|
||||
idf_library_get_property(component_interfaces_linked "${library}" LIBRARY_COMPONENT_INTERFACES_LINKED)
|
||||
foreach(component_interface IN LISTS component_interfaces_linked)
|
||||
idf_component_get_property(component_source "${component_interface}" COMPONENT_SOURCE)
|
||||
idf_component_get_property(component_target "${component_interface}" COMPONENT_TARGET)
|
||||
@@ -414,6 +421,7 @@ function(idf_build_library library)
|
||||
# for files and targets specific to the library.
|
||||
string(MAKE_C_IDENTIFIER "_${library}" suffix)
|
||||
|
||||
idf_library_get_property(component_interfaces_linked "${library}" LIBRARY_COMPONENT_INTERFACES_LINKED)
|
||||
foreach(component_interface IN LISTS component_interfaces_linked)
|
||||
set(scripts)
|
||||
idf_component_get_property(component_dir "${component_interface}" COMPONENT_DIR)
|
||||
|
||||
@@ -29,7 +29,7 @@ function(__component_validation_get_component_for_path var path)
|
||||
endif()
|
||||
|
||||
# Get all component names
|
||||
idf_build_get_property(component_names COMPONENTS_DISCOVERED)
|
||||
idf_build_get_property(component_interfaces COMPONENT_INTERFACES)
|
||||
|
||||
# Walk up the directory tree from the deepest path towards root and return
|
||||
# the first component whose COMPONENT_DIR matches exactly. This guarantees
|
||||
@@ -37,9 +37,10 @@ function(__component_validation_get_component_for_path var path)
|
||||
while(NOT "${current_dir}" STREQUAL "" AND
|
||||
NOT "${current_dir}" STREQUAL "/" AND
|
||||
NOT "${current_dir}" MATCHES "^[A-Za-z]:/$")
|
||||
foreach(component_name ${component_names})
|
||||
idf_component_get_property(component_dir ${component_name} COMPONENT_DIR)
|
||||
foreach(component_interface ${component_interfaces})
|
||||
__idf_component_get_property_unchecked(component_dir ${component_interface} COMPONENT_DIR)
|
||||
if(current_dir STREQUAL component_dir)
|
||||
__idf_component_get_property_unchecked(component_name ${component_interface} COMPONENT_NAME)
|
||||
set(${var} ${component_name} PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
@@ -52,18 +53,19 @@ function(__component_validation_get_component_for_path var path)
|
||||
endfunction()
|
||||
|
||||
#[[
|
||||
__component_validation_check_sources(<component_name>)
|
||||
__component_validation_check_sources(<component_interface>)
|
||||
|
||||
*component_name[in]*
|
||||
*component_interface[in]*
|
||||
|
||||
Component name to validate.
|
||||
Component interface to validate.
|
||||
|
||||
Validate that all source files of the specified component belong to that
|
||||
component's directory tree. Issues warnings if source files belong to other
|
||||
components.
|
||||
#]]
|
||||
function(__component_validation_check_sources component_name)
|
||||
idf_component_get_property(sources ${component_name} SRCS)
|
||||
function(__component_validation_check_sources component_interface)
|
||||
__idf_component_get_property_unchecked(component_name ${component_interface} COMPONENT_NAME)
|
||||
__idf_component_get_property_unchecked(sources ${component_interface} SRCS)
|
||||
|
||||
# Skip validation if component does not have any sources
|
||||
if(NOT sources)
|
||||
@@ -97,10 +99,11 @@ endfunction()
|
||||
properties) of the specified component belong to that component's directory
|
||||
tree. Issues warnings if include directories belong to other components.
|
||||
#]]
|
||||
function(__component_validation_check_include_dirs component_name)
|
||||
idf_component_get_property(include_dirs ${component_name} INCLUDE_DIRS)
|
||||
idf_component_get_property(priv_include_dirs ${component_name} PRIV_INCLUDE_DIRS)
|
||||
idf_component_get_property(component_dir ${component_name} COMPONENT_DIR)
|
||||
function(__component_validation_check_include_dirs component_interface)
|
||||
__idf_component_get_property_unchecked(component_name ${component_interface} COMPONENT_NAME)
|
||||
__idf_component_get_property_unchecked(include_dirs ${component_interface} INCLUDE_DIRS)
|
||||
__idf_component_get_property_unchecked(priv_include_dirs ${component_interface} PRIV_INCLUDE_DIRS)
|
||||
__idf_component_get_property_unchecked(component_dir ${component_interface} COMPONENT_DIR)
|
||||
|
||||
# Check public include directories
|
||||
foreach(dir ${include_dirs})
|
||||
@@ -163,11 +166,11 @@ function(__component_validation_run_checks)
|
||||
endif()
|
||||
|
||||
# Validate only components linked to the specified library
|
||||
idf_library_get_property(component_names "${ARG_LIBRARY}" LIBRARY_COMPONENTS_LINKED)
|
||||
idf_library_get_property(component_interfaces "${ARG_LIBRARY}" LIBRARY_COMPONENT_INTERFACES_LINKED)
|
||||
|
||||
# Run validation checks for each component
|
||||
foreach(component_name ${component_names})
|
||||
__component_validation_check_sources(${component_name})
|
||||
__component_validation_check_include_dirs(${component_name})
|
||||
foreach(component_interface ${component_interfaces})
|
||||
__component_validation_check_sources(${component_interface})
|
||||
__component_validation_check_include_dirs(${component_interface})
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
Reference in New Issue
Block a user