diff --git a/components/bootloader/subproject/CMakeLists.txt b/components/bootloader/subproject/CMakeLists.txt index 4fba9e1ce55..68200320c08 100644 --- a/components/bootloader/subproject/CMakeLists.txt +++ b/components/bootloader/subproject/CMakeLists.txt @@ -55,13 +55,25 @@ if(IGNORE_EXTRA_COMPONENT) OUTPUT_VARIABLE EXTRA_COMPONENT_EXCLUDE_DIRS) endif() -# Consider each directory in the project's bootloader_components as a component to be compiled -file(GLOB proj_components RELATIVE ${PROJECT_EXTRA_COMPONENTS} ${PROJECT_EXTRA_COMPONENTS}/*) -foreach(component ${proj_components}) - # Only directories are considered components - if(IS_DIRECTORY "${PROJECT_EXTRA_COMPONENTS}/${component}" AND NOT ${component} IN_LIST IGNORE_EXTRA_COMPONENT) - list(APPEND COMPONENTS ${component}) - endif() +foreach(extra_component_dir ${EXTRA_COMPONENT_DIRS}) + if(EXISTS "${extra_component_dir}/CMakeLists.txt") + # BOOTLOADER_EXTRA_COMPONENT_DIRS may point directly to a single component. + # Add the directory name so the bootloader COMPONENTS filter keeps it. + get_filename_component(component "${extra_component_dir}" NAME) + if(NOT ${component} IN_LIST IGNORE_EXTRA_COMPONENT) + list(APPEND COMPONENTS ${component}) + endif() + else() + # BOOTLOADER_EXTRA_COMPONENT_DIRS may also point to a directory containing + # multiple component directories. Add each child directory to the filter. + file(GLOB proj_components RELATIVE ${extra_component_dir} ${extra_component_dir}/*) + foreach(component ${proj_components}) + # Only directories are considered components. + if(IS_DIRECTORY "${extra_component_dir}/${component}" AND NOT ${component} IN_LIST IGNORE_EXTRA_COMPONENT) + list(APPEND COMPONENTS ${component}) + endif() + endforeach() + endif() endforeach() set(BOOTLOADER_BUILD 1) diff --git a/examples/custom_bootloader/bootloader_extra_dir/CMakeLists.txt b/examples/custom_bootloader/bootloader_extra_dir/CMakeLists.txt index c10daedebe9..9295c1272a3 100644 --- a/examples/custom_bootloader/bootloader_extra_dir/CMakeLists.txt +++ b/examples/custom_bootloader/bootloader_extra_dir/CMakeLists.txt @@ -6,9 +6,34 @@ cmake_minimum_required(VERSION 3.22) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -idf_build_set_property(BOOTLOADER_EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_LIST_DIR}/extra_bootloader_components/" APPEND) +# The bootloader always uses the "bootloader_components" folder name +# as the project-local search path for bootloader components added to the bootloader build. +# +# Use BOOTLOADER_EXTRA_COMPONENT_DIRS when bootloader components already lives somewhere else, +# for example in a shared components directory or in a component reused by several projects. +# The path may point to a directory containing multiple components. +idf_build_set_property(BOOTLOADER_EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_LIST_DIR}/extra_bootloader_components" APPEND) + +# The path may also point directly to a single component when adding a wrapper directory +# just for the bootloader build would be unnecessary. +idf_build_set_property(BOOTLOADER_EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_LIST_DIR}/extra_component4" APPEND) +idf_build_set_property(BOOTLOADER_EXTRA_COMPONENT_DIRS "${CMAKE_CURRENT_LIST_DIR}/extra_component5" APPEND) + +# A shared extra directory may contain components that are not needed in this bootloader build. +# Ignore them by component name, including direct single-component paths. +set(BOOTLOADER_IGNORE_EXTRA_COMPONENT extra_component3 extra_component5) # "Trim" the build. Include the minimal set of components, main, and anything it depends on. idf_build_set_property(MINIMAL_BUILD ON) project(main) + +# Check which extra bootloader components are included and which ones are ignored. +add_custom_target(check_bootloader_extra_components ALL + COMMAND ${CMAKE_COMMAND} + -DPROJECT_DESCRIPTION=${CMAKE_BINARY_DIR}/bootloader/project_description.json + -DEXPECTED_COMPONENTS=extra_component1,extra_component2,extra_component4 + -DIGNORED_COMPONENTS=extra_component3,extra_component5 + -P ${CMAKE_CURRENT_LIST_DIR}/check_bootloader_component.cmake + DEPENDS bootloader + VERBATIM) diff --git a/examples/custom_bootloader/bootloader_extra_dir/README.md b/examples/custom_bootloader/bootloader_extra_dir/README.md index cc7482a3d7a..e90cbf28503 100644 --- a/examples/custom_bootloader/bootloader_extra_dir/README.md +++ b/examples/custom_bootloader/bootloader_extra_dir/README.md @@ -5,9 +5,11 @@ (See the README.md file in the upper level for more information about bootloader examples.) -The purpose of this example is to show how to add a custom directory that contains a component to the bootloader build. +The purpose of this example is to show how to add bootloader components that are not placed in the conventional `bootloader_components` directory. -Registering extra components for the bootloader can be done thanks to the IDF property `BOOTLOADER_EXTRA_COMPONENT_DIRS`. It can either refer to a directory that contains several components, either refer to a single component. +The bootloader always uses the `bootloader_components` folder name as the project-local search path for bootloader components. Use this folder for bootloader-specific code that belongs to the project, such as hooks or overrides. + +Use the `BOOTLOADER_EXTRA_COMPONENT_DIRS` property when bootloader components already live somewhere else, for example in a shared components directory or in a component reused by several projects. Each path can point either to a directory containing multiple components or directly to a single component. If the extra location contains components that are not needed in a particular bootloader build, list them by component name in `BOOTLOADER_IGNORE_EXTRA_COMPONENT`. ## Usage of this example: @@ -33,9 +35,11 @@ User application is loaded and running. ## Organization of this example -This project contains a `main` directory that represents an application. It also has a `bootloader_components` directory that contains a component that will be compiled and linked with the bootloader. This `bootloader_components` can contain several components, each of them would be in a different directory. +This project contains a `main` directory that represents an application. It also has a `bootloader_components` directory with `my_boot_hooks`, a bootloader-specific hook component that belongs to this project. -The directory `extra_bootloader_components/extra_component/` contains a component that is meant to be included in the bootloader build. To do so, the CMake property `BOOTLOADER_EXTRA_COMPONENT_DIRS` is set from the `CMakeLists.txt` file. +The `extra_bootloader_components/` directory demonstrates an extra path that contains several components. `extra_component1` is required by `my_boot_hooks`, while `extra_component2` is included directly from `BOOTLOADER_EXTRA_COMPONENT_DIRS` without being required by another component. `extra_component3` is present in the same directory but is excluded from this bootloader build with `BOOTLOADER_IGNORE_EXTRA_COMPONENT`. + +The `extra_component4/` and `extra_component5/` directories demonstrate extra paths that point directly to individual components. `extra_component4` is included directly, while `extra_component5` is excluded with `BOOTLOADER_IGNORE_EXTRA_COMPONENT`. Below is a short explanation of files in the project folder. @@ -49,8 +53,20 @@ Below is a short explanation of files in the project folder. │   ├── CMakeLists.txt │   └── hooks.c Implementation of the hooks to execute on boot ├── extra_bootloader_components -│   └── extra_component +│   ├── extra_component1 +│   │   ├── CMakeLists.txt +│   │   └── extra_component1.c Implementation of the extra component +│   ├── extra_component2 +│   │   ├── CMakeLists.txt +│   │   └── extra_component2.c Implementation of the 2nd extra component +│   └── extra_component3 │   ├── CMakeLists.txt -│   └── extra_component.c Implementation of the extra component +│   └── extra_component3.c Extra component excluded from this bootloader build +├── extra_component4 +│   ├── CMakeLists.txt +│   └── extra_component4.c Extra component included directly +├── extra_component5 +│   ├── CMakeLists.txt +│   └── extra_component5.c Extra component excluded directly └── README.md This is the file you are currently reading ``` diff --git a/examples/custom_bootloader/bootloader_extra_dir/bootloader_components/my_boot_hooks/CMakeLists.txt b/examples/custom_bootloader/bootloader_extra_dir/bootloader_components/my_boot_hooks/CMakeLists.txt index 6b620571a47..ce482610cd9 100644 --- a/examples/custom_bootloader/bootloader_extra_dir/bootloader_components/my_boot_hooks/CMakeLists.txt +++ b/examples/custom_bootloader/bootloader_extra_dir/bootloader_components/my_boot_hooks/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register(SRCS "hooks.c" - REQUIRES extra_component) + REQUIRES extra_component1) # We need to force GCC to integrate this static library into the # bootloader link. Indeed, by default, as the hooks in the bootloader are weak, diff --git a/examples/custom_bootloader/bootloader_extra_dir/check_bootloader_component.cmake b/examples/custom_bootloader/bootloader_extra_dir/check_bootloader_component.cmake new file mode 100644 index 00000000000..426850c6885 --- /dev/null +++ b/examples/custom_bootloader/bootloader_extra_dir/check_bootloader_component.cmake @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 + +file(READ "${PROJECT_DESCRIPTION}" project_description) +string(JSON component_count LENGTH "${project_description}" build_components) + +set(build_components) +if(component_count GREATER 0) + math(EXPR last_component_index "${component_count} - 1") + foreach(component_index RANGE 0 ${last_component_index}) + string(JSON component_name GET "${project_description}" build_components ${component_index}) + if(NOT component_name STREQUAL "") + list(APPEND build_components "${component_name}") + endif() + endforeach() +endif() + +string(REPLACE "," ";" expected_components "${EXPECTED_COMPONENTS}") +foreach(expected_component ${expected_components}) + list(FIND build_components "${expected_component}" component_index) + if(component_index EQUAL -1) + message(FATAL_ERROR "${expected_component} was not included in the bootloader build") + endif() +endforeach() + +string(REPLACE "," ";" ignored_components "${IGNORED_COMPONENTS}") +foreach(ignored_component ${ignored_components}) + list(FIND build_components "${ignored_component}" component_index) + if(NOT component_index EQUAL -1) + message(FATAL_ERROR "${ignored_component} was included in the bootloader build") + endif() +endforeach() diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component/CMakeLists.txt b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component/CMakeLists.txt deleted file mode 100644 index ac58fa9c07e..00000000000 --- a/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -idf_component_register(SRCS "extra_component.c") diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component1/CMakeLists.txt b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component1/CMakeLists.txt new file mode 100644 index 00000000000..706d10816b5 --- /dev/null +++ b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component1/CMakeLists.txt @@ -0,0 +1 @@ +idf_component_register(SRCS "extra_component1.c") diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component/extra_component.c b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component1/extra_component1.c similarity index 100% rename from examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component/extra_component.c rename to examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component1/extra_component1.c diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component2/CMakeLists.txt b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component2/CMakeLists.txt new file mode 100644 index 00000000000..573ebd90436 --- /dev/null +++ b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component2/CMakeLists.txt @@ -0,0 +1 @@ +idf_component_register(SRCS "extra_component2.c") diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component2/extra_component2.c b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component2/extra_component2.c new file mode 100644 index 00000000000..3633dcc4e29 --- /dev/null +++ b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component2/extra_component2.c @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +void bootloader_extra_component2_marker(void) +{ +} diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component3/CMakeLists.txt b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component3/CMakeLists.txt new file mode 100644 index 00000000000..a95c4d92bab --- /dev/null +++ b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component3/CMakeLists.txt @@ -0,0 +1 @@ +idf_component_register(SRCS "extra_component3.c") diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component3/extra_component3.c b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component3/extra_component3.c new file mode 100644 index 00000000000..411b1b34017 --- /dev/null +++ b/examples/custom_bootloader/bootloader_extra_dir/extra_bootloader_components/extra_component3/extra_component3.c @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +void bootloader_extra_component3_marker(void) +{ +} diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_component4/CMakeLists.txt b/examples/custom_bootloader/bootloader_extra_dir/extra_component4/CMakeLists.txt new file mode 100644 index 00000000000..0b9343f95fa --- /dev/null +++ b/examples/custom_bootloader/bootloader_extra_dir/extra_component4/CMakeLists.txt @@ -0,0 +1 @@ +idf_component_register(SRCS "extra_component4.c") diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_component4/extra_component4.c b/examples/custom_bootloader/bootloader_extra_dir/extra_component4/extra_component4.c new file mode 100644 index 00000000000..815f61018d4 --- /dev/null +++ b/examples/custom_bootloader/bootloader_extra_dir/extra_component4/extra_component4.c @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +void bootloader_extra_component4_marker(void) +{ +} diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_component5/CMakeLists.txt b/examples/custom_bootloader/bootloader_extra_dir/extra_component5/CMakeLists.txt new file mode 100644 index 00000000000..0c866b67b8f --- /dev/null +++ b/examples/custom_bootloader/bootloader_extra_dir/extra_component5/CMakeLists.txt @@ -0,0 +1 @@ +idf_component_register(SRCS "extra_component5.c") diff --git a/examples/custom_bootloader/bootloader_extra_dir/extra_component5/extra_component5.c b/examples/custom_bootloader/bootloader_extra_dir/extra_component5/extra_component5.c new file mode 100644 index 00000000000..87f67a037d9 --- /dev/null +++ b/examples/custom_bootloader/bootloader_extra_dir/extra_component5/extra_component5.c @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +void bootloader_extra_component5_marker(void) +{ +}