Skip to content

Commit

Permalink
tools: extend information in project_description.json
Browse files Browse the repository at this point in the history
This extends information provided in the project_description.json file.
Newly added information can be used in the SBOM generating tool and
also to improve hints regarding the the component dependency issues.

Added fields

version:
   This adds versioning to the project_description.json file,
   so it's easy to identify if it contains the required information.

project_version:
   Can be used as a version for the resulting binary e.g. `hello_world.bin`.

idf_path:
   This one is probably not necessary, but it allows tools to run even without
   esp-idf environment exported(e.g. export.sh).

c_compiler:
   The `CMAKE_C_COMPILER` value with full path to the compiler binary. This can
   be used to get information about toolchain, which was used to build the project.

common_component_reqs:
   List of common components as presented in cmake's __COMPONENT_REQUIRES_COMMON
   and set in tools/cmake/build.cmake:__build_init().

build_component_info:
   Detailed information about components used during build. It's a
   dictionary with the component name as a key and each component has
   a dictionary with detailed information. Following is an example for
   the efuse component.

   "efuse": {
       "alias": "idf::efuse",
       "target": "___idf_efuse",
       "prefix": "idf",
       "dir": "/home/fhrbata/work/esp-idf/components/efuse",
       "type": "LIBRARY",
       "lib": "__idf_efuse",
       "reqs": [],
       "priv_reqs": [ "bootloader_support", "soc", "spi_flash" ],
       "managed_reqs": [],
       "managed_priv_reqs": [],
       "file": "/home/fhrbata/work/blink/build/esp-idf/efuse/libefuse.a",
       "sources": [ "/home/fhrbata/work/esp-idf/components/efuse/esp32s3/esp_efuse_table.c", ... ],
       "include_dirs": [ "include", "esp32s3/include" ]
   }

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
  • Loading branch information
fhrbata committed Jun 8, 2023
1 parent 30735b3 commit 9156bbb
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 1 deletion.
86 changes: 85 additions & 1 deletion tools/cmake/project.cmake
Expand Up @@ -103,6 +103,74 @@ function(paths_with_spaces_to_list variable_name)
endif()
endfunction()

function(__component_info components output)
set(components_json "")
foreach(name ${components})
__component_get_target(target ${name})
__component_get_property(alias ${target} COMPONENT_ALIAS)
__component_get_property(prefix ${target} __PREFIX)
__component_get_property(dir ${target} COMPONENT_DIR)
__component_get_property(type ${target} COMPONENT_TYPE)
__component_get_property(lib ${target} COMPONENT_LIB)
__component_get_property(reqs ${target} REQUIRES)
__component_get_property(include_dirs ${target} INCLUDE_DIRS)
__component_get_property(priv_reqs ${target} PRIV_REQUIRES)
__component_get_property(managed_reqs ${target} MANAGED_REQUIRES)
__component_get_property(managed_priv_reqs ${target} MANAGED_PRIV_REQUIRES)
if("${type}" STREQUAL "LIBRARY")
set(file "$<TARGET_LINKER_FILE:${lib}>")

# The idf_component_register function is converting each source file path defined
# in SRCS into absolute one. But source files can be also added with cmake's
# target_sources and have relative paths. This is used for example in log
# component. Let's make sure all source files have absolute path.
set(sources "")
get_target_property(srcs ${lib} SOURCES)
foreach(src ${srcs})
get_filename_component(src "${src}" ABSOLUTE BASE_DIR "${dir}")
list(APPEND sources "${src}")
endforeach()

else()
set(file "")
set(sources "")
endif()

make_json_list("${reqs}" reqs)
make_json_list("${priv_reqs}" priv_reqs)
make_json_list("${managed_reqs}" managed_reqs)
make_json_list("${managed_priv_reqs}" managed_priv_reqs)
make_json_list("${include_dirs}" include_dirs)
make_json_list("${sources}" sources)

string(JOIN "\n" component_json
" \"${name}\": {"
" \"alias\": \"${alias}\","
" \"target\": \"${target}\","
" \"prefix\": \"${prefix}\","
" \"dir\": \"${dir}\","
" \"type\": \"${type}\","
" \"lib\": \"${lib}\","
" \"reqs\": ${reqs},"
" \"priv_reqs\": ${priv_reqs},"
" \"managed_reqs\": ${managed_reqs},"
" \"managed_priv_reqs\": ${managed_priv_reqs},"
" \"file\": \"${file}\","
" \"sources\": ${sources},"
" \"include_dirs\": ${include_dirs}"
" }"
)
string(CONFIGURE "${component_json}" component_json)
if(NOT "${components_json}" STREQUAL "")
string(APPEND components_json ",\n")
endif()
string(APPEND components_json "${component_json}")
endforeach()
string(PREPEND components_json "{\n")
string(APPEND components_json "\n }")
set(${output} "${components_json}" PARENT_SCOPE)
endfunction()

#
# Output the built components to the user. Generates files for invoking idf_monitor.py
# that doubles as an overview of some of the more important build properties.
Expand Down Expand Up @@ -139,13 +207,15 @@ function(__project_info test_components)
endforeach()

set(PROJECT_NAME ${CMAKE_PROJECT_NAME})
idf_build_get_property(PROJECT_VER PROJECT_VER)
idf_build_get_property(PROJECT_PATH PROJECT_DIR)
idf_build_get_property(BUILD_DIR BUILD_DIR)
idf_build_get_property(SDKCONFIG SDKCONFIG)
idf_build_get_property(SDKCONFIG_DEFAULTS SDKCONFIG_DEFAULTS)
idf_build_get_property(PROJECT_EXECUTABLE EXECUTABLE)
set(PROJECT_BIN ${CMAKE_PROJECT_NAME}.bin)
idf_build_get_property(IDF_VER IDF_VER)
idf_build_get_property(common_component_reqs __COMPONENT_REQUIRES_COMMON)

idf_build_get_property(sdkconfig_cmake SDKCONFIG_CMAKE)
include(${sdkconfig_cmake})
Expand All @@ -157,8 +227,22 @@ function(__project_info test_components)
idf_build_get_property(build_dir BUILD_DIR)
make_json_list("${build_components};${test_components}" build_components_json)
make_json_list("${build_component_paths};${test_component_paths}" build_component_paths_json)
make_json_list("${common_component_reqs}" common_component_reqs_json)

__component_info("${build_components};${test_components}" build_component_info_json)

# The configure_file function doesn't process generator expressions, which are needed
# e.g. to get component target library(TARGET_LINKER_FILE), so the project_description
# file is created in two steps. The first step, with configure_file, creates a temporary
# file with cmake's variables substituted and unprocessed generator expressions. The second
# step, with file(GENERATE), processes the temporary file and substitute generator expression
# into the final project_description.json file.
configure_file("${idf_path}/tools/cmake/project_description.json.in"
"${build_dir}/project_description.json")
"${build_dir}/project_description.json.templ")
file(READ "${build_dir}/project_description.json.templ" project_description_json_templ)
file(REMOVE "${build_dir}/project_description.json.templ")
file(GENERATE OUTPUT "${build_dir}/project_description.json"
CONTENT "${project_description_json_templ}")

# Generate component dependency graph
depgraph_generate("${build_dir}/component_deps.dot")
Expand Down
6 changes: 6 additions & 0 deletions tools/cmake/project_description.json.in
@@ -1,6 +1,9 @@
{
"version": "1",
"project_name": "${PROJECT_NAME}",
"project_version": "${PROJECT_VER}",
"project_path": "${PROJECT_PATH}",
"idf_path": "${IDF_PATH}",
"build_dir": "${BUILD_DIR}",
"config_file": "${SDKCONFIG}",
"config_defaults": "${SDKCONFIG_DEFAULTS}",
Expand All @@ -15,11 +18,14 @@
"phy_data_partition": "${CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION}",
"monitor_baud" : "${CONFIG_ESPTOOLPY_MONITOR_BAUD}",
"monitor_toolprefix": "${_CMAKE_TOOLCHAIN_PREFIX}",
"c_compiler": "${CMAKE_C_COMPILER}",
"config_environment" : {
"COMPONENT_KCONFIGS" : "${COMPONENT_KCONFIGS}",
"COMPONENT_KCONFIGS_PROJBUILD" : "${COMPONENT_KCONFIGS_PROJBUILD}"
},
"common_component_reqs": ${common_component_reqs_json},
"build_components" : ${build_components_json},
"build_component_paths" : ${build_component_paths_json},
"build_component_info" : ${build_component_info_json},
"debug_prefix_map_gdbinit": "${debug_prefix_map_gdbinit}"
}

0 comments on commit 9156bbb

Please sign in to comment.