Skip to content

Commit b43b200

Browse files
committed
Merge branch 'feat/support_kconfig_in_pacman_v5.5' into 'release/v5.5'
feat: support kconfig in component manager (v5.5) See merge request espressif/esp-idf!40492
2 parents 7bed0d3 + ddfb596 commit b43b200

File tree

6 files changed

+177
-23
lines changed

6 files changed

+177
-23
lines changed

.gitlab/ci/test-win.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ test_cli_installer_win:
3030
variables:
3131
IDF_PATH: "$CI_PROJECT_DIR"
3232
timeout: 3h
33+
allow_failure: true
3334
script:
3435
# Tools must be downloaded for testing
3536
- python ${IDF_PATH}\tools\idf_tools.py download required qemu-riscv32 qemu-xtensa cmake

tools/cmake/build.cmake

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -579,11 +579,15 @@ macro(idf_build_process target)
579579

580580
# Call for component manager to download dependencies for all components
581581
idf_build_get_property(idf_component_manager IDF_COMPONENT_MANAGER)
582+
583+
set(result 0)
582584
if(idf_component_manager EQUAL 1)
583585
idf_build_get_property(build_dir BUILD_DIR)
584586
set(managed_components_list_file ${build_dir}/managed_components_list.temp.cmake)
585587
set(local_components_list_file ${build_dir}/local_components_list.temp.yml)
586588

589+
set(__RERUN_EXITCODE 10) # missing kconfig
590+
587591
set(__contents "components:\n")
588592
idf_build_get_property(build_component_targets BUILD_COMPONENT_TARGETS)
589593
foreach(__build_component_target ${build_component_targets})
@@ -610,6 +614,7 @@ macro(idf_build_process target)
610614
"idf_component_manager.prepare_components"
611615
"--project_dir=${project_dir}"
612616
"--lock_path=${dependencies_lock_file}"
617+
"--sdkconfig_json_file=${build_dir}/config/sdkconfig.json"
613618
"--interface_version=${component_manager_interface_version}"
614619
"prepare_dependencies"
615620
"--local_components_list_file=${local_components_list_file}"
@@ -618,7 +623,11 @@ macro(idf_build_process target)
618623
ERROR_VARIABLE error)
619624

620625
if(NOT result EQUAL 0)
621-
message(FATAL_ERROR "${error}")
626+
if(result EQUAL ${__RERUN_EXITCODE})
627+
message(WARNING "${error}")
628+
else()
629+
message(FATAL_ERROR "${error}")
630+
endif()
622631
endif()
623632

624633
include(${managed_components_list_file})
@@ -689,21 +698,30 @@ macro(idf_build_process target)
689698
# Generate config values in different formats
690699
idf_build_get_property(sdkconfig SDKCONFIG)
691700
idf_build_get_property(sdkconfig_defaults SDKCONFIG_DEFAULTS)
692-
__kconfig_generate_config("${sdkconfig}" "${sdkconfig_defaults}")
701+
702+
# add target here since we have all components
703+
if(result EQUAL 0)
704+
__kconfig_generate_config("${sdkconfig}" "${sdkconfig_defaults}" CREATE_MENUCONFIG_TARGET)
705+
else()
706+
__kconfig_generate_config("${sdkconfig}" "${sdkconfig_defaults}")
707+
endif()
708+
693709
__build_import_configs()
694710

695-
# All targets built under this scope is with the ESP-IDF build system
696-
set(ESP_PLATFORM 1)
697-
idf_build_set_property(COMPILE_DEFINITIONS "ESP_PLATFORM" APPEND)
711+
if(result EQUAL 0)
712+
# All targets built under this scope is with the ESP-IDF build system
713+
set(ESP_PLATFORM 1)
714+
idf_build_set_property(COMPILE_DEFINITIONS "ESP_PLATFORM" APPEND)
698715

699-
# Perform component processing (inclusion of project_include.cmake, adding component
700-
# subdirectories, creating library targets, linking libraries, etc.)
701-
__build_process_project_includes()
716+
# Perform component processing (inclusion of project_include.cmake, adding component
717+
# subdirectories, creating library targets, linking libraries, etc.)
718+
__build_process_project_includes()
702719

703-
idf_build_get_property(idf_path IDF_PATH)
704-
add_subdirectory(${idf_path} ${build_dir}/esp-idf)
720+
idf_build_get_property(idf_path IDF_PATH)
721+
add_subdirectory(${idf_path} ${build_dir}/esp-idf)
705722

706-
unset(ESP_PLATFORM)
723+
unset(ESP_PLATFORM)
724+
endif()
707725
endmacro()
708726

709727
# idf_build_executable

tools/cmake/kconfig.cmake

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,14 @@ function(__get_init_config_version config version_out)
7979
endforeach()
8080
endfunction()
8181

82-
8382
#
8483
# Generate the config files and create config related targets and configure
8584
# dependencies.
8685
#
8786
function(__kconfig_generate_config sdkconfig sdkconfig_defaults)
87+
set(options OPTIONAL CREATE_MENUCONFIG_TARGET)
88+
cmake_parse_arguments(PARSE_ARGV 2 "ARG" "${options}" "" "")
89+
8890
# List all Kconfig and Kconfig.projbuild in known components
8991
idf_build_get_property(component_targets __COMPONENT_TARGETS)
9092
idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
@@ -243,6 +245,10 @@ function(__kconfig_generate_config sdkconfig sdkconfig_defaults)
243245
set(MENUCONFIG_CMD ${python} -m menuconfig)
244246
set(TERM_CHECK_CMD ${python} ${idf_path}/tools/check_term.py)
245247

248+
if(NOT ${ARG_CREATE_MENUCONFIG_TARGET})
249+
return()
250+
endif()
251+
246252
# Generate the menuconfig target
247253
add_custom_target(menuconfig
248254
${menuconfig_depends}

tools/cmake/project.cmake

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ if(NOT "$ENV{IDF_COMPONENT_MANAGER}" EQUAL "0")
6161
idf_build_set_property(IDF_COMPONENT_MANAGER 1)
6262
endif()
6363
# Set component manager interface version
64-
idf_build_set_property(__COMPONENT_MANAGER_INTERFACE_VERSION 3)
64+
idf_build_set_property(__COMPONENT_MANAGER_INTERFACE_VERSION 4)
6565

6666
#
6767
# Parse and store the VERSION argument provided to the project() command.
@@ -733,14 +733,31 @@ macro(project project_name)
733733

734734
message(STATUS "Building ESP-IDF components for target ${IDF_TARGET}")
735735

736-
idf_build_process(${IDF_TARGET}
737-
SDKCONFIG_DEFAULTS "${sdkconfig_defaults}"
738-
SDKCONFIG ${sdkconfig}
739-
BUILD_DIR ${build_dir}
740-
PROJECT_NAME ${CMAKE_PROJECT_NAME}
741-
PROJECT_DIR ${CMAKE_CURRENT_LIST_DIR}
742-
PROJECT_VER "${project_ver}"
743-
COMPONENTS "${components};${test_components}")
736+
set(result 0)
737+
set(retried 0)
738+
739+
while(true)
740+
idf_build_process(${IDF_TARGET}
741+
SDKCONFIG_DEFAULTS "${sdkconfig_defaults}"
742+
SDKCONFIG ${sdkconfig}
743+
BUILD_DIR ${build_dir}
744+
PROJECT_NAME ${CMAKE_PROJECT_NAME}
745+
PROJECT_DIR ${CMAKE_CURRENT_LIST_DIR}
746+
PROJECT_VER "${project_ver}"
747+
COMPONENTS "${components};${test_components}"
748+
)
749+
750+
if(result EQUAL 0)
751+
break()
752+
elseif(result EQUAL 10 AND retried EQUAL 0)
753+
message(WARNING "Missing kconfig option. Re-run the build process...")
754+
set(retried 1)
755+
elseif(result EQUAL 10 AND retried EQUAL 1)
756+
message(FATAL_ERROR "Missing required kconfig option after retry.")
757+
else()
758+
message(FATAL_ERROR "idf_build_process failed with exit code ${result}")
759+
endif()
760+
endwhile()
744761

745762
# Special treatment for 'main' component for standard projects (not part of core build system).
746763
# Have it depend on every other component in the build. This is

tools/requirements/requirements.core.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pyserial
1313
cryptography
1414
pyparsing
1515
pyelftools
16-
idf-component-manager
16+
idf-component-manager~=2.2
1717
esp-coredump
1818
esptool
1919
esp-idf-kconfig

tools/test_build_system/test_component_manager.py

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
1+
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
22
# SPDX-License-Identifier: Apache-2.0
33
import os.path
44
from pathlib import Path
@@ -44,3 +44,115 @@ def test_trimmed_components_still_passed_to_cmake(idf_py: IdfPyFunc, test_app_co
4444
fs = f.read()
4545

4646
assert ' example/cmp:' in fs
47+
48+
49+
class TestOptionalDependencyWithKconfig:
50+
def test_direct_kconfig(self, idf_py: IdfPyFunc, test_app_copy: Path) -> None:
51+
(test_app_copy / 'main' / 'idf_component.yml').write_text("""
52+
dependencies:
53+
example/cmp:
54+
version: "*"
55+
rules:
56+
- if: $CONFIG{BOOTLOADER_PROJECT_VER} == 1
57+
""")
58+
59+
idf_py('reconfigure')
60+
61+
with open('dependencies.lock', 'r') as f:
62+
fs = f.read()
63+
assert ' example/cmp:' in fs
64+
65+
(test_app_copy / 'main' / 'idf_component.yml').write_text("""
66+
dependencies:
67+
example/cmp:
68+
version: "*"
69+
rules:
70+
- if: $CONFIG{BOOTLOADER_PROJECT_VER} != 1
71+
""")
72+
73+
idf_py('reconfigure')
74+
75+
with open('dependencies.lock', 'r') as f:
76+
fs = f.read()
77+
assert ' example/cmp:' not in fs
78+
79+
def test_missing_kconfig_first_round(self, idf_py: IdfPyFunc, test_app_copy: Path) -> None:
80+
(test_app_copy / 'main' / 'idf_component.yml').write_text("""
81+
dependencies:
82+
espressif/mdns:
83+
version: "*"
84+
85+
example/cmp:
86+
version: "*"
87+
rules:
88+
- if: $CONFIG{MDNS_MAX_SERVICES} == 10 # mdns kconfig CONFIG_MDNS_MAX_SERVICES default to 10
89+
""")
90+
91+
idf_py('reconfigure')
92+
93+
with open('dependencies.lock', 'r') as f:
94+
fs = f.read()
95+
assert ' example/cmp:' in fs
96+
97+
def test_kconfig_load_existing_sdkconfig_defaults(self, idf_py: IdfPyFunc, test_app_copy: Path) -> None:
98+
(test_app_copy / 'main' / 'idf_component.yml').write_text("""
99+
dependencies:
100+
example/cmp:
101+
version: "*"
102+
rules:
103+
- if: $CONFIG{BOOTLOADER_LOG_LEVEL_WARN} == True
104+
""")
105+
106+
(test_app_copy / 'sdkconfig.defaults').write_text("""
107+
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
108+
CONFIG_LOG_DEFAULT_LEVEL_WARN=y
109+
""")
110+
111+
idf_py('reconfigure')
112+
113+
with open('dependencies.lock', 'r') as f:
114+
fs = f.read()
115+
assert ' example/cmp:' in fs
116+
117+
def test_kconfig_load_missing_sdkconfig_defaults(self, idf_py: IdfPyFunc, test_app_copy: Path) -> None:
118+
(test_app_copy / 'main' / 'idf_component.yml').write_text("""
119+
dependencies:
120+
espressif/mdns:
121+
version: "*"
122+
123+
example/cmp:
124+
version: "*"
125+
rules:
126+
- if: $CONFIG{MDNS_MAX_SERVICES} == 30 # mdns kconfig CONFIG_MDNS_MAX_SERVICES default to 10
127+
""")
128+
129+
(test_app_copy / 'sdkconfig.defaults').write_text("""
130+
CONFIG_MDNS_MAX_SERVICES=30
131+
""")
132+
133+
idf_py('reconfigure')
134+
135+
with open('dependencies.lock', 'r') as f:
136+
fs = f.read()
137+
assert ' example/cmp:' in fs
138+
139+
def test_missing_kconfig_second_round(self, idf_py: IdfPyFunc, test_app_copy: Path) -> None:
140+
(test_app_copy / 'main' / 'idf_component.yml').write_text("""
141+
dependencies:
142+
espressif/mdns:
143+
version: "*"
144+
145+
example/cmp:
146+
version: "*"
147+
rules:
148+
- if: $CONFIG{OF_COURSE_NO_ONE_USE_FOO} == "bar"
149+
""")
150+
151+
res = idf_py('reconfigure', check=False)
152+
153+
assert res.returncode != 0
154+
assert (
155+
f'OF_COURSE_NO_ONE_USE_FOO, introduced by example/cmp, '
156+
f'defined in {str(test_app_copy / "main" / "idf_component.yml")}' in res.stderr
157+
)
158+
assert 'Missing required kconfig option after retry.' in res.stderr

0 commit comments

Comments
 (0)