From 211b2da4371c02721c8be9acaa97b9ae16a2b65f Mon Sep 17 00:00:00 2001 From: Frantisek Hrbata Date: Thu, 27 Nov 2025 15:25:25 +0100 Subject: [PATCH] feat(cmakev2/build): add idf_build_generate_depgraph function The idf_build_generate_depgraph function creates a component dependency graph in dot (graphviz) format for a specified executable. It uses existing helper functions from cmakev1, ensuring that the generated dot files are produced in the same manner as in cmakev1. While adjustments might be needed in the future if necessary, the current implementation is intended to offer the same functionality as cmakev1. Similar to cmakev1, the dot files are only generated only when the __BUILD_COMPONENT_DEPGRAPH_ENABLED build property is set. Signed-off-by: Frantisek Hrbata --- tools/cmakev2/build.cmake | 72 +++++++++++++++++++++++++++++-- tools/cmakev2/idf.cmake | 5 +++ tools/cmakev2/project.cmake | 2 + tools/cmakev2/test/CMakeLists.txt | 6 +++ 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/tools/cmakev2/build.cmake b/tools/cmakev2/build.cmake index 0e9096e111..f7f0121ef6 100644 --- a/tools/cmakev2/build.cmake +++ b/tools/cmakev2/build.cmake @@ -703,7 +703,7 @@ endfunction() .. code-block:: cmake idf_build_generate_metadata( - [FILE ]) + [OUTPUT_FILE ]) *binary[in]* @@ -715,8 +715,8 @@ endfunction() the default path ``/project_description.json`` is used. Generate metadata for the specified ``binary`` and store it in the - specified ``FILE``. If no ``FILE`` is provided, the default location - ``/project_description.json`` will be used. + specified ``OUTPUT_FILE``. If no ``OUTPUT_FILE`` is provided, the default + location ``/project_description.json`` will be used. #]] function(idf_build_generate_metadata binary) set(options) @@ -1180,3 +1180,69 @@ function(idf_check_binary_signed binary) "${binary_path}" VERBATIM) endfunction() + +#[[ +.. cmakev2:function:: idf_build_generate_depgraph + + .. code-block:: cmake + + idf_build_generate_depgraph( + [OUTPUT_FILE ]) + + *executable[in]* + + Executable target for which to generate a dependency graph. + + *OUTPUT_FILE[in,opt]* + + Optional output file path for storing the dependency graph. If not + provided, the default path ``/component_deps.dot`` is used. + + Generate dependency graph for the specified ``executable`` and store it in + the specified ``OUTPUT_FILE``. If no ``OUTPUT_FILE`` is provided, the + default location ``/component_deps.dot`` will be used. +#]] +function(idf_build_generate_depgraph executable) + set(options) + set(one_value OUTPUT_FILE) + set(multi_value) + cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + idf_build_get_property(depgraph_enabled __BUILD_COMPONENT_DEPGRAPH_ENABLED) + if(NOT depgraph_enabled) + return() + endif() + + __get_executable_library_or_die(TARGET "${executable}" OUTPUT library) + + idf_build_set_property(__BUILD_COMPONENT_DEPGRAPH "") + idf_build_get_property(common_reqs __COMPONENT_REQUIRES_COMMON) + + idf_library_get_property(build_components "${library}" LIBRARY_COMPONENTS_LINKED) + + foreach(component_name IN LISTS build_components) + idf_component_get_property(reqs "${component_name}" REQUIRES) + idf_component_get_property(component_format "${component_name}" COMPONENT_FORMAT) + if("${component_format}" STREQUAL "CMAKEV1") + # For cmakev1 components, also include commonly required + # components. + list(APPEND reqs ${common_reqs}) + endif() + + foreach(req IN LISTS reqs) + depgraph_add_edge(${component_name} ${req} REQUIRES) + endforeach() + + idf_component_get_property(priv_reqs "${component_name}" PRIV_REQUIRES) + foreach(priv_req IN LISTS priv_reqs) + depgraph_add_edge(${component_name} ${priv_req} PRIV_REQUIRES) + endforeach() + endforeach() + + if(NOT DEFINED ARG_OUTPUT_FILE) + idf_build_get_property(build_dir BUILD_DIR) + set(ARG_OUTPUT_FILE "${build_dir}/component_deps.dot") + endif() + + depgraph_generate("${ARG_OUTPUT_FILE}") +endfunction() diff --git a/tools/cmakev2/idf.cmake b/tools/cmakev2/idf.cmake index 6824a9296c..7aaf3f64ad 100644 --- a/tools/cmakev2/idf.cmake +++ b/tools/cmakev2/idf.cmake @@ -27,6 +27,11 @@ include(${CMAKE_CURRENT_LIST_DIR}/../cmake/gdbinit.cmake) # project_description.json. include(${CMAKE_CURRENT_LIST_DIR}/../cmake/openocd.cmake) +# The depgraph.cmake file from cmakev1 contains helper functions for generating +# a component dependency graph. Let's reuse these functions in the +# idf_build_generate_depgraph function. +include(${CMAKE_CURRENT_LIST_DIR}/../cmake/depgraph.cmake) + include(component) include(build) include(kconfig) diff --git a/tools/cmakev2/project.cmake b/tools/cmakev2/project.cmake index f42712b516..d5fed77a53 100644 --- a/tools/cmakev2/project.cmake +++ b/tools/cmakev2/project.cmake @@ -770,6 +770,8 @@ function(__project_default) idf_create_size_report("${executable}_mapfile" TARGET size) endif() + + idf_build_generate_depgraph("${executable}") endfunction() #[[api diff --git a/tools/cmakev2/test/CMakeLists.txt b/tools/cmakev2/test/CMakeLists.txt index bc0e3fa2e5..0981ec92af 100644 --- a/tools/cmakev2/test/CMakeLists.txt +++ b/tools/cmakev2/test/CMakeLists.txt @@ -15,6 +15,8 @@ add_custom_target(flash) idf_project_init() +idf_build_set_property(__BUILD_COMPONENT_DEPGRAPH_ENABLED 1) + # Test component priority function(test_component_priority) # Set the idf component to be replaced with a testing component of higher @@ -232,6 +234,8 @@ function(test_executable) TARGET menuconfig-fatfs) idf_build_generate_metadata(fatfs_example_bin OUTPUT_FILE project_description_fatfs.json) + idf_build_generate_depgraph(fatfs_example + OUTPUT_FILE component_deps_fatfs.dot) idf_create_confserver(fatfs_example TARGET confserver-fatfs) @@ -255,6 +259,8 @@ function(test_executable) TARGET menuconfig-hello_world) idf_build_generate_metadata(hello_world_example_bin OUTPUT_FILE project_description_hello_world.json) + idf_build_generate_depgraph(hello_world_example + OUTPUT_FILE component_deps_hello_world.dot) idf_create_confserver(hello_world_example TARGET confserver-hello_world)