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
|
bool
|
||||||
default "n"
|
default "n"
|
||||||
|
|
||||||
|
config IDF_TARGET_ARCH
|
||||||
|
string
|
||||||
|
default "riscv" if IDF_TARGET_ARCH_RISCV
|
||||||
|
default "xtensa" if IDF_TARGET_ARCH_XTENSA
|
||||||
|
|
||||||
config IDF_TARGET
|
config IDF_TARGET
|
||||||
# This option records the IDF target when sdkconfig is generated the first time.
|
# 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
|
# 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(reqs TARGET ${component_target} PROPERTY REQUIRES)
|
||||||
get_property(priv_reqs TARGET ${component_target} PROPERTY PRIV_REQUIRES)
|
get_property(priv_reqs TARGET ${component_target} PROPERTY PRIV_REQUIRES)
|
||||||
|
__component_get_property(component_name ${component_target} COMPONENT_NAME)
|
||||||
|
|
||||||
foreach(req ${reqs})
|
foreach(req ${reqs})
|
||||||
|
depgraph_add_edge(${component_name} ${req} REQUIRES)
|
||||||
__build_resolve_and_add_req(_component_target ${component_target} ${req} __REQUIRES)
|
__build_resolve_and_add_req(_component_target ${component_target} ${req} __REQUIRES)
|
||||||
__build_expand_requirements(${_component_target})
|
__build_expand_requirements(${_component_target})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
foreach(req ${priv_reqs})
|
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_resolve_and_add_req(_component_target ${component_target} ${req} __PRIV_REQUIRES)
|
||||||
__build_expand_requirements(${_component_target})
|
__build_expand_requirements(${_component_target})
|
||||||
endforeach()
|
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(kconfig)
|
||||||
include(component)
|
include(component)
|
||||||
include(utilities)
|
include(utilities)
|
||||||
|
include(depgraph)
|
||||||
include(targets)
|
include(targets)
|
||||||
include(ldgen)
|
include(ldgen)
|
||||||
include(dfu)
|
include(dfu)
|
||||||
|
@ -120,6 +120,9 @@ function(__project_info test_components)
|
|||||||
configure_file("${idf_path}/tools/cmake/project_description.json.in"
|
configure_file("${idf_path}/tools/cmake/project_description.json.in"
|
||||||
"${build_dir}/project_description.json")
|
"${build_dir}/project_description.json")
|
||||||
|
|
||||||
|
# Generate component dependency graph
|
||||||
|
depgraph_generate("${build_dir}/component_deps.dot")
|
||||||
|
|
||||||
# We now have the following component-related variables:
|
# We now have the following component-related variables:
|
||||||
#
|
#
|
||||||
# build_components is the list of components to include in the build.
|
# build_components is the list of components to include in the build.
|
||||||
|
Loading…
Reference in New Issue
Block a user