mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
998c8870eb
This is a revised version of the existing __create_confserver_target function. It creates a specified confserver target for a given executable. The kconfig_menus.json file, used by the IDEs, is generated when the confserver starts. This differs from the previous behavior, where kconfig_menus.json was created globally along with other sdkconfig formats. The reason for this change is that kconfig_menus.json contains the Kconfig menu hierarchy and it is not just a flat option-value format. It needs to accurately reflect which configurations for which components are included or excluded. The kconfig_menus.json is generated at `build/kconfig_menus.json`, where IDEs expect it. This means the file is overwritten every time the server starts by kconfig_menus.json version for given executable, so only one confserver can run at a time. This is likely acceptable, as I don't believe it's possible to safely run multiple instances of confserver due to the potential race conditions when the sdkconfig file are generated. In the future, we may include the location of kconfig_menus.json in project_description.json so it can be easily identified by IDEs for each executable. Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
279 lines
9.9 KiB
CMake
279 lines
9.9 KiB
CMake
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
# Simple project for basic cmakev2 testing
|
|
# Run: cmake -S . -B build
|
|
cmake_minimum_required(VERSION 3.22)
|
|
|
|
include($ENV{IDF_PATH}/tools/cmakev2/idf.cmake)
|
|
|
|
project(cmakev2
|
|
VERSION 1.2.3
|
|
LANGUAGES C CXX ASM)
|
|
|
|
add_custom_target(flash)
|
|
|
|
idf_project_init()
|
|
|
|
# Test component priority
|
|
function(test_component_priority)
|
|
# Set the idf component to be replaced with a testing component of higher
|
|
# priority.
|
|
set(component_name "esp_system")
|
|
|
|
# Check that idf component is between discovered components.
|
|
__get_component_interface(COMPONENT "${component_name}"
|
|
OUTPUT component_interface)
|
|
if("${component_interface}" STREQUAL "NOTFOUND")
|
|
idf_die("Component '${component_name}' not found")
|
|
endif()
|
|
|
|
# Check that idf component has "idf_components" as source.
|
|
idf_component_get_property(component_source
|
|
${component_interface}
|
|
COMPONENT_SOURCE)
|
|
if(NOT "${component_source}" STREQUAL "idf_components")
|
|
idf_die("Unexpected idf component '${component_name}' source '${component_source}'")
|
|
endif()
|
|
|
|
# Create fake component with same name as idf component.
|
|
set(component_dir "${CMAKE_CURRENT_BINARY_DIR}/${component_name}")
|
|
file(MAKE_DIRECTORY "${component_dir}")
|
|
file(TOUCH "${component_dir}/CMakeLists.txt")
|
|
|
|
# Initialize fake component with higher "project_components" priority.
|
|
idf_build_get_property(component_prefix PREFIX)
|
|
__init_component(DIRECTORY "${component_dir}"
|
|
PREFIX "${component_prefix}"
|
|
SOURCE "project_components")
|
|
|
|
# Check that the idf component was replaced with fake component.
|
|
idf_component_get_property(component_source
|
|
${component_interface}
|
|
COMPONENT_SOURCE)
|
|
if(NOT "${component_source}" STREQUAL "project_components")
|
|
idf_die("Unexpected fake component '${component_name}' source '${component_source}'")
|
|
endif()
|
|
|
|
idf_component_get_property(component_dir
|
|
${component_interface}
|
|
COMPONENT_DIR)
|
|
if(NOT "${component_dir}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}/${component_name}")
|
|
idf_die("Unexpected fake component '${component_name}' directory '${component_dir}'")
|
|
endif()
|
|
__dump_component_properties("${component_name}")
|
|
endfunction()
|
|
|
|
# Test that IDF_VERSION and IDF_VER build property is set
|
|
function(test_idf_version)
|
|
if(NOT DEFINED IDF_VERSION_MAJOR OR
|
|
NOT DEFINED IDF_VERSION_MINOR OR
|
|
NOT DEFINED IDF_VERSION_PATCH OR
|
|
NOT DEFINED ENV{IDF_VERSION})
|
|
idf_die("IDF_VERSION not set")
|
|
endif()
|
|
idf_build_get_property(idf_ver IDF_VER)
|
|
if(NOT idf_ver)
|
|
idf_die("IDF_VER build property not set")
|
|
endif()
|
|
endfunction()
|
|
|
|
# Test that Python interpreter is set
|
|
function(test_python)
|
|
if(NOT DEFINED PYTHON OR "${PYTHON}" STREQUAL "")
|
|
idf_die("PYTHON variable not defined or empty")
|
|
endif()
|
|
endfunction()
|
|
|
|
# Test that toolchain is properly set
|
|
function(test_toolchain)
|
|
if(NOT IDF_TOOLCHAIN)
|
|
idf_die("IDF_TOOLCHAIN variable not defined or empty")
|
|
endif()
|
|
if(NOT CMAKE_TOOLCHAIN_FILE)
|
|
idf_die("CMAKE_TOOLCHAIN_FILE variable not defined or empty")
|
|
endif()
|
|
idf_build_get_property(toolchain IDF_TOOLCHAIN)
|
|
if(NOT toolchain)
|
|
idf_die("IDF_TOOLCHAIN build property not set")
|
|
endif()
|
|
idf_build_get_property(toolchain_file IDF_TOOLCHAIN_FILE)
|
|
if(NOT toolchain_file)
|
|
idf_die("IDF_TOOLCHAIN_FILE build property not set")
|
|
endif()
|
|
endfunction()
|
|
|
|
# Test idf_build_library
|
|
function(test_idf_build_library)
|
|
# Create idflibtest with specific set of components and test that it
|
|
# contains them.
|
|
set(components app_trace app_update bootloader bootloader_support bt cmock)
|
|
|
|
set(idflib idflibtest)
|
|
idf_build_library("${idflib}" COMPONENTS "${components}")
|
|
|
|
if(NOT TARGET "${idflib}")
|
|
idf_die("'${idflib}' not created")
|
|
endif()
|
|
|
|
idf_library_get_property(lib_components "${idflib}" LIBRARY_COMPONENTS)
|
|
if(NOT "${lib_components}" STREQUAL "${components}")
|
|
idf_die("Library '${idflib}' components '${lib_components}' do not match "
|
|
"expected components '${components}'")
|
|
endif()
|
|
|
|
# Create idflibtest2 without specifying COMPONENTS and test that it
|
|
# contains all discovered components.
|
|
set(idflib idflibtest2)
|
|
idf_build_library("${idflib}")
|
|
|
|
if(NOT TARGET "${idflib}")
|
|
idf_die("'${idflib}' not created")
|
|
endif()
|
|
|
|
idf_library_get_property(lib_components "${idflib}" LIBRARY_COMPONENTS)
|
|
idf_build_get_property(component_names COMPONENTS_DISCOVERED)
|
|
if(NOT "${lib_components}" STREQUAL "${component_names}")
|
|
idf_die("Library '${idflib}' components '${lib_components}' do not match "
|
|
"COMPONENTS_DISCOVERED")
|
|
endif()
|
|
endfunction()
|
|
|
|
function(test_kconfig)
|
|
# Check that kconfig output files were generated
|
|
idf_build_get_property(config_dir CONFIG_DIR)
|
|
set(output_files sdkconfig.h sdkconfig.cmake sdkconfig.json)
|
|
|
|
foreach(file ${output_files})
|
|
set(file_path "${config_dir}/${file}")
|
|
if(NOT EXISTS "${file_path}")
|
|
idf_die("Missing kconfig output: ${file_path}")
|
|
endif()
|
|
file(SIZE "${file_path}" file_size)
|
|
if(file_size EQUAL 0)
|
|
idf_die("Empty kconfig output: ${file_path}")
|
|
endif()
|
|
endforeach()
|
|
|
|
# Check that kconfig targets were created
|
|
set(targets menuconfig confserver save-defconfig)
|
|
foreach(target ${targets})
|
|
if(NOT TARGET ${target})
|
|
idf_die("Missing kconfig target: ${target}")
|
|
endif()
|
|
endforeach()
|
|
endfunction()
|
|
|
|
# Test that PROJECT_NAME and PROJECT_VER build property is set and contain
|
|
# values provided in project() call.
|
|
function(test_project_properties)
|
|
idf_build_get_property(project_name PROJECT_NAME)
|
|
if(NOT project_name)
|
|
idf_die("PROJECT_NAME build property not set")
|
|
endif()
|
|
if(NOT "${project_name}" STREQUAL "${PROJECT_NAME}")
|
|
idf_die("PROJECT_NAME build property '${project_name}' != '${PROJECT_NAME}'")
|
|
endif()
|
|
idf_build_get_property(project_ver PROJECT_VER)
|
|
if(NOT project_ver)
|
|
idf_die("PROJECT_VER build property not set")
|
|
endif()
|
|
if(NOT "${project_ver}" STREQUAL "${PROJECT_VERSION}")
|
|
idf_die("PROJECT_VER build property '${project_ver}' != '${PROJECT_VERSION}'")
|
|
endif()
|
|
endfunction()
|
|
|
|
# Test that the targets for component1 and component2 are created when
|
|
# component2 is included.
|
|
function(test_include_component)
|
|
idf_build_library(idflibtest3 COMPONENTS component2)
|
|
idf_component_get_property(component_real_target
|
|
component2
|
|
COMPONENT_REAL_TARGET)
|
|
if(NOT TARGET ${component_real_target})
|
|
idf_die("Missing component2 target")
|
|
endif()
|
|
|
|
# Test that component1 is included as a dependency of component2.
|
|
idf_component_get_property(component_real_target
|
|
component1
|
|
COMPONENT_REAL_TARGET)
|
|
if(NOT TARGET ${component_real_target})
|
|
idf_die("Missing component1 target")
|
|
endif()
|
|
endfunction()
|
|
|
|
# Add two executables fatfs_example and hello_world_example, generate
|
|
# binary images for them and add flash and menuconfig targets.
|
|
# After configuration these can be build with
|
|
# idf.py hello_world_example_bin
|
|
# idf.py fatfs_example_bin
|
|
# or simply
|
|
# idf.py hello_world_example-flash monitor
|
|
# idf.py fatfs-flash monitor
|
|
# The menuconfig can be invoked with
|
|
# idf.py --no-hints menuconfig-hello_world
|
|
# idf.py --no-hints menuconfig-fatfs
|
|
# The confserver can be invoked with
|
|
# idf.py confserver-hello_world
|
|
# idf.py confserver-fatfs
|
|
function(test_executable)
|
|
idf_build_executable(fatfs_example
|
|
COMPONENTS fatfs_example)
|
|
idf_build_binary(fatfs_example
|
|
TARGET fatfs_example_bin
|
|
OUTPUT_FILE fatfs_example.bin)
|
|
idf_check_binary_size(fatfs_example_bin)
|
|
idf_flash_binary(fatfs_example_bin
|
|
TARGET fatfs_example-flash
|
|
NAME fatfs_example)
|
|
idf_create_menuconfig(fatfs_example
|
|
TARGET menuconfig-fatfs)
|
|
idf_build_generate_metadata(fatfs_example
|
|
OUTPUT_FILE project_description_fatfs.json)
|
|
idf_create_confserver(fatfs_example
|
|
TARGET confserver-fatfs)
|
|
|
|
|
|
idf_build_executable(hello_world_example
|
|
COMPONENTS hello_world_example)
|
|
idf_build_binary(hello_world_example
|
|
TARGET hello_world_example_bin
|
|
OUTPUT_FILE hello_world_example.bin)
|
|
idf_check_binary_size(hello_world_example_bin)
|
|
idf_flash_binary(hello_world_example_bin
|
|
TARGET hello_world_example-flash
|
|
NAME hello_world_example)
|
|
idf_create_menuconfig(hello_world_example
|
|
TARGET menuconfig-hello_world)
|
|
idf_build_generate_metadata(hello_world_example
|
|
OUTPUT_FILE project_description_hello_world.json)
|
|
idf_create_confserver(hello_world_example
|
|
TARGET confserver-hello_world)
|
|
endfunction()
|
|
|
|
# Run tests
|
|
test_idf_version()
|
|
test_python()
|
|
test_toolchain()
|
|
test_idf_build_library()
|
|
test_project_properties()
|
|
test_include_component()
|
|
test_executable()
|
|
|
|
# Create default project
|
|
idf_project_default()
|
|
|
|
# The kconfig test also verifies whether kconfig-related targets, such as
|
|
# menuconfig, are created. These targets are now generated within
|
|
# idf_project_default rather than globally, so this test should be run only
|
|
# after the default project is created.
|
|
test_kconfig()
|
|
|
|
# Call this test last because it replaces the ESP system component.
|
|
test_component_priority()
|
|
|
|
__dump_all_properties()
|
|
|
|
message("ALL TESTS PASSED")
|