mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
cmake: add component dependency graph generation helpers
These optional feature produces a graphviz file showing component dependencies. It is useful for debugging reasons why certain components got added to the build.
This commit is contained in:
parent
f4d1bb017a
commit
ae7d1fff49
5
Kconfig
5
Kconfig
@ -22,6 +22,11 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
bool
|
||||
default "n"
|
||||
|
||||
config IDF_TARGET_ARCH
|
||||
string
|
||||
default "riscv" if IDF_TARGET_ARCH_RISCV
|
||||
default "xtensa" if IDF_TARGET_ARCH_XTENSA
|
||||
|
||||
config IDF_TARGET
|
||||
# This option records the IDF target when sdkconfig is generated the first time.
|
||||
# It is not updated if environment variable $IDF_TARGET changes later, and
|
||||
|
@ -221,13 +221,16 @@ function(__build_expand_requirements component_target)
|
||||
|
||||
get_property(reqs TARGET ${component_target} PROPERTY REQUIRES)
|
||||
get_property(priv_reqs TARGET ${component_target} PROPERTY PRIV_REQUIRES)
|
||||
__component_get_property(component_name ${component_target} COMPONENT_NAME)
|
||||
|
||||
foreach(req ${reqs})
|
||||
depgraph_add_edge(${component_name} ${req} REQUIRES)
|
||||
__build_resolve_and_add_req(_component_target ${component_target} ${req} __REQUIRES)
|
||||
__build_expand_requirements(${_component_target})
|
||||
endforeach()
|
||||
|
||||
foreach(req ${priv_reqs})
|
||||
depgraph_add_edge(${component_name} ${req} PRIV_REQUIRES)
|
||||
__build_resolve_and_add_req(_component_target ${component_target} ${req} __PRIV_REQUIRES)
|
||||
__build_expand_requirements(${_component_target})
|
||||
endforeach()
|
||||
|
30
tools/cmake/component_deps.dot.in
Normal file
30
tools/cmake/component_deps.dot.in
Normal file
@ -0,0 +1,30 @@
|
||||
digraph G {
|
||||
|
||||
${depgraph}
|
||||
|
||||
subgraph cluster_g0 {
|
||||
rank = same;
|
||||
label = "G0";
|
||||
|
||||
soc;
|
||||
hal;
|
||||
esp_common;
|
||||
esp_rom;
|
||||
${CONFIG_IDF_TARGET_ARCH};
|
||||
${CONFIG_IDF_TARGET};
|
||||
}
|
||||
|
||||
subgraph cluster_g1 {
|
||||
rank = same;
|
||||
label = "G1";
|
||||
|
||||
spi_flash;
|
||||
freertos;
|
||||
log;
|
||||
heap;
|
||||
newlib;
|
||||
esp_system;
|
||||
esp_hw_support;
|
||||
}
|
||||
|
||||
}
|
61
tools/cmake/depgraph.cmake
Normal file
61
tools/cmake/depgraph.cmake
Normal file
@ -0,0 +1,61 @@
|
||||
# Component dependency graph generation helpers.
|
||||
# To enable this functionality, add:
|
||||
# idf_build_set_property(__BUILD_COMPONENT_DEPGRAPH_ENABLED 1)
|
||||
# in the project CMakeLists.txt file between include(project.cmake) and project(name) calls.
|
||||
#
|
||||
# Graphviz file component_deps.dot will be produced in the build directory.
|
||||
# To change the template, see component_deps.dot.in.
|
||||
|
||||
# depgraph_add_edge
|
||||
#
|
||||
# @brief Record an edge in the component dependency graph (dependent -> dependency)
|
||||
#
|
||||
# @param[in] dep_from dependent name
|
||||
# @param[in] dep_to dependency name
|
||||
# @param[in, optional] REQUIRES if given, record this as "REQUIRES" (public/interface) dependency
|
||||
# @param[in, optional] PRIV_REQUIRES if given, record this as "PRIV_REQUIRES" (private) dependency
|
||||
#
|
||||
function(depgraph_add_edge dep_from dep_to)
|
||||
cmake_parse_arguments(_ "REQUIRES;PRIV_REQUIRES" "" "" ${ARGN})
|
||||
idf_build_get_property(depgraph_enabled __BUILD_COMPONENT_DEPGRAPH_ENABLED)
|
||||
if(NOT depgraph_enabled)
|
||||
return()
|
||||
endif()
|
||||
idf_build_get_property(common_reqs __COMPONENT_REQUIRES_COMMON)
|
||||
|
||||
set(attr)
|
||||
if(__REQUIRES)
|
||||
set(attr "[class=\"requires\"]")
|
||||
elseif(__PRIV_REQUIRES)
|
||||
set(attr "[class=\"priv_requires\" style=\"dotted\"]")
|
||||
endif()
|
||||
|
||||
if(dep_to IN_LIST common_reqs)
|
||||
# Don't record graph edges leading to "common" components, since every component has these dependencies.
|
||||
# However, show which components are "common" by adding an edge from a node named "common".
|
||||
# If necessary, add a new build property to customize this behavior.
|
||||
if(NOT dep_from IN_LIST common_reqs)
|
||||
idf_build_set_property(__BUILD_COMPONENT_DEPGRAPH "common -> ${dep_to}" APPEND)
|
||||
endif()
|
||||
else()
|
||||
idf_build_set_property(__BUILD_COMPONENT_DEPGRAPH "${dep_from} -> ${dep_to} ${attr}" APPEND)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# depgraph_generate
|
||||
#
|
||||
# @brief Write the collected component dependency graph to a file. The file is in Graphviz (.dot) format.
|
||||
#
|
||||
# @param[in] out_path name of the output file
|
||||
#
|
||||
function(depgraph_generate out_path)
|
||||
idf_build_get_property(depgraph_enabled __BUILD_COMPONENT_DEPGRAPH_ENABLED)
|
||||
if(NOT depgraph_enabled)
|
||||
return()
|
||||
endif()
|
||||
idf_build_get_property(depgraph __BUILD_COMPONENT_DEPGRAPH)
|
||||
list(REMOVE_DUPLICATES depgraph)
|
||||
string(REPLACE ";" ";\n" depgraph "${depgraph}")
|
||||
configure_file("${IDF_PATH}/tools/cmake/component_deps.dot.in"
|
||||
"${out_path}")
|
||||
endfunction()
|
@ -41,6 +41,7 @@ if(NOT __idf_env_set)
|
||||
include(kconfig)
|
||||
include(component)
|
||||
include(utilities)
|
||||
include(depgraph)
|
||||
include(targets)
|
||||
include(ldgen)
|
||||
include(dfu)
|
||||
|
@ -120,6 +120,9 @@ function(__project_info test_components)
|
||||
configure_file("${idf_path}/tools/cmake/project_description.json.in"
|
||||
"${build_dir}/project_description.json")
|
||||
|
||||
# Generate component dependency graph
|
||||
depgraph_generate("${build_dir}/component_deps.dot")
|
||||
|
||||
# We now have the following component-related variables:
|
||||
#
|
||||
# build_components is the list of components to include in the build.
|
||||
|
Loading…
Reference in New Issue
Block a user