Commit Graph

7346 Commits

Author SHA1 Message Date
Frantisek Hrbata dc846dbe8d feat(cmakev2/docs): add esp_docs_cmakev2_extension sphinx extension
Add a Sphinx extension that introduces a new `cmakev2` domain with
multiple directives, allowing for the automatic extraction of
documentation comments from CMake files and their inclusion in the
Sphinx-generated documentation.

Directives:

- `cmakev2:include`: The included CMake file is processed for
  documentation comments within the `#[[api` and `#]]` marks, which
  should contain valid reStructuredText markup.

- `cmakev2:function`: Creates a CMake function node. All function nodes
  are sorted by name and placed into the `_cmakev2_functions` section.

- `cmakev2:macro`: Creates a CMake macro node. All macro nodes are
  sorted by name and placed into the `_cmakev2_macros` section.

- `cmakev2:variable`: Describes a CMake variable node. All variable
  nodes are sorted by name and placed into the `_cmakev2_variables`
  section.

Each node can be referenced with `` :cmakev2:ref:`<node name>` ``, where
the node name is the function, macro, or variable name as used in the
related directive.

Example:

CMake file:
```
 #[[api
        .. cmakev2:function:: idf_flash_binary
 #]]
```

This function can be referenced with `` :cmakev2:ref:`idf_flash_binary` ``
and will be placed in the `.. _cmakev2_functions:` section.

The extension is currently located in esp-idf, but in the future, we
should consider moving it to esp-docs.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Sudeep Mohanty 0c69d53b68 test(cmakev2): Enable CI tests for component manager for cmakev2
This commit adapts the component manager build tests for cmakev2 and
enables them for CI test runs.
2025-10-30 17:17:49 +08:00
Sudeep Mohanty 1017be951b feat(cmakev2): Allow users to set the dependencies lock file 2025-10-30 17:17:49 +08:00
Sudeep Mohanty 012670a6e0 fix(cmakev2): Build must include component manager output when re-run is expected
The build system should include the file generated by the component
manager after downloading components even if the component manager
requested a re-run due to a missing Kconfig.
2025-10-30 17:17:49 +08:00
Sudeep Mohanty 79eefd1ba9 feat(cmakev2): Reorganise build system initialization
This commit updates the order of initialization for build system v2. All
non-project initializations are handled in idf.cmake and all
project-specific initializations are now moved to idf_project_init().
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 63695ad838 feat(cmakev2/project): add idf_build_generate_flasher_args function
Generate the flasher_args.json file for the global flash target for
tools that require it.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 7e808b34ec feat(cmakev2/test): add binary image generation and flash targets
Generate binary images and add flash targets for hello_world_example and
fatfs_example.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata aacbd1773b fix(cmakev2/build): rename FILE to OUTPUT_FILE option for idf_build_generate_metadata
All other functions, such as idf_build_binary, use OUTPUT_FILE. This is
more descriptive and provides more flexibility to add additional
file-related options in the future if necessary. Make
idf_build_generate_metadata consistent with the other function
interfaces by using OUTPUT_FILE.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata df9010f894 feat(cmakev2/project): add binary genration and flash targets to idf_project_default
Use idf_build_binary, idf_sign_binary, and idf_flash_binary to generate
and flash the default project application.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata b514ed5ae7 feat(cmakev2/build): add idf_check_binary_signed function
Given the binary target generated by the idf_build_binary or
idf_sign_binary function, add a new POST_BUILD dependency that displays
a message indicating the binary image must be manually signed before
flashing. This situation arises when CONFIG_SECURE_SIGNED_APPS is
enabled, but CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES is not set.  As a
result, the binary image is not signed during the build process and
requires manual signing.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 73ee5ee8e2 feat(cmakev2/build): add idf_check_binary_size function
Given the binary target created by the idf_build_binary or
idf_sign_binary function, add a new dependency that verifies whether the
binary image fits within the smallest application partition.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 1dbdeb6bb1 feat(cmakev2/build): add idf_flash_binary function
Create a new flash target for a previously created binary target using
the idf_build_binary or idf_sign_binary function. Specify the new target
name with the TARGET option. The binary image path is stored in the
BINARY_PATH property of the binary target and is set when the binary
target is created using the idf_build_binary or idf_sign_binary
function. Use the NAME option as a prefix for the generated esptool
argument file, and the FLASH option can be used to include the binary
image flashing in the global flash target.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata db2770b281 feat(cmakev2/build): add idf_sign_binary function
Create a signed binary image from a previously generated binary using
the `idf_build_binary` function. This image can be signed with an
optional key from a KEYFILE or, by default, with the key specified in
the sdkconfig. A new custom command is added to generate the signed
binary, which is stored at the location specified by the OUTPUT_FILE
option and a new custom target is created for it, with the name provided
in the TARGET option. The BINARY_PATH property is added to this new
TARGET, containing the path to the signed binary image.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 646c16f4f2 feat(cmakev2/build): add idf_build_binary function
The `idf_build_binary` function generates a binary image for a specified
executable target, which may or may not have been created using the
`idf_build_executable` function. It adds a custom command to generate
the binary image file at the location specified by the `OUTPUT_FILE`
option and creates a new target for it, with the name specified by the
`TARGET` option. The path of the generated binary file is also stored in
the `BINARY_PATH` property of the newly created binary target.
Additionally, this binary path is stored in the `EXECUTABLE_BINARY`
property of the given executable. This information is used by the
`idf_build_generate_metadata` function, which takes the executable
target as an argument and includes the binary name in the
`project_description.json`.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata c7bde33b67 feat(cmakev2/project): initialize global flash targets
The global flash targets are created using
__create_project_flash_targets, but these are merely placeholders that
allow components to declare their dependencies on the global flash or
encrypted-flash target in their project_include.cmake. The actual logic
for flash targets is located in the project_include.cmake of the
esptool_py component. Therefore, the targets must be initialized
after this file has been included. To address this, a new function,
__init_project_flash_targets, has been added for this purpose.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata efae51696f feat(cmakev2/idf): enable ccache if requested
Enable ccache if CCACHE_ENABLE is set.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata c60f7bec27 feat(cmakev2/utilities): add fail_at_build_time helper
Create a phony target that intentionally fails the build, displaying the
error messages specified in the message arguments. An empty CMake file is
created and included, which is then deleted when the target is executed.
This forces CMake to rerun, as the file is added to the CMake rerun
dependencies.

This has been carried over from cmakev1 as it is used by several
components.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Sudeep Mohanty 65ed7732fe feat(cmakev2): Added support for injecting dependencies for components 2025-10-30 17:17:49 +08:00
Sudeep Mohanty c7e9385427 feat(cmakev2): Added download of component-level managed components 2025-10-30 17:17:49 +08:00
Sudeep Mohanty 37d1a3064f feat(cmakev2): Added idf_build_component shim to compat.cmake 2025-10-30 17:17:49 +08:00
Frantisek Hrbata 020cceab23 feat(cmakev2/project): add __init_project_flash_targets helper
Some components rely on the existence of flash targets to declare
dependencies. Add flash and encrypted-flash targets during project
initialization to ensure they are available before including
project_include.cmake files.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata e45b86ac9d fix(test_build_system): use idf_project_default in buildv2 test app
Since the idf_project_default is already available, let's use it in the
buildv2 testing application. Also change the test app name from
buildv2_test_app to build_test_app, as some tests require the ELF and
bin images to be created under this name.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata a6c6193232 fix(cmakev2/compat): use alias target in idf_component_optional_requires
The optional dependency is currently added if the optional component
interface target exists, which is always the case unless a non-existent
component is requested. Instead, base the optional dependency on the
component interface target alias, as it is created only when the
component is included in the project.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata fdd8a924bc feat(cmakev2/project): allow to include all discovered components
If the IDF_INCLUDE_ALL_COMPONENTS variable is set, all discovered
components will be included. By default, components are included based
on their requirements. When IDF_INCLUDE_ALL_COMPONENTS is enabled, the
all_component_info dictionary in the project_description.json file will
be fully populated.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata b36e5adeff feat(cmakev2/build): add idf_build_generate_metadata function
The `idf_build_generate_metadata()` function is used to generate project
metadata, specifically the `project_description.json` file, for a given
executable target. The output file path can be specified as an argument
to the function, allowing metadata generation for multiple executables.
It identifies the library, created by the `idf_build_library` function,
that is linked to the executable based on the `LINK_LIBRARIES`
executable target property. The `LIBRARY_INTERFACES` build property
tracks all library interfaces created with the `idf_build_library`
function, so the targets in the `LINK_LIBRARIES` executable property are
checked against this list to find the library. The library contains
information about components linked to it in the
`LIBRARY_COMPONENTS_LINKED` library property. These components are
processed and added to the `build_component_info` dictionary in the
`project_description.json` along with other information.

Note that, compared to cmakev1, the `all_component_info` dictionary in
`project_description` does not include some information by default, such
as included directories. This information is available in cmakev1 due to
early component evaluation, which is not done in cmakev2. This will
likely require some adjustments on the hints side.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 767e73b811 feat(cmakev2/utilities): add __make_json_list helper
Helper function for converting a CMake list to a JSON list.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 2e667ee990 feat(cmakev2/component): add __PREFIX component property in __init_component()
The cmakev1 sets __PREFIX as a component property. To maintain backward
compatibility, set it in cmakev2 as well.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 06449dc17d feat(cmakev2/utilities): add __get_executable_library_or_die helper
Search for the library interface target created with the
idf_build_library() function and linked to the executable, examine the
LINK_LIBRARIES for the executable and the LIBRARY_INTERFACES build
property, which stores all library interface targets created by the
idf_build_library() function.

This helper is intended for use by functions, such as the
idf_build_generate_metadata() function, which accepts the executable
target as an argument to find the library linked to it.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 1af119a431 feat(cmakev2/project): add idf_project_default macro
The idf_project_default macro is intended to be used by default for
ESP-IDF projects. Currently, it handles the necessary project
initialization that must occur after CMake's project() is called. It
creates the default executable based on the project name and links a
library to it, based on the main component and its transitive
dependencies. This macro will be further extended to also generate
binary image, project metadata, and add other expected targets. It
primarily serves as a replacement for the project() macro used in
cmakev1.

Expected typical usage:
```
cmake_minimum_required(VERSION 3.22)
include($ENV{IDF_PATH}/tools/cmakev2/idf.cmake)
project(hello_world LANGUAGES C CXX ASM)
idf_project_default()
```

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 2a093bcb0c feat(cmakev2/build): add idf_build_executable function
Create an empty source file for the add_executable target, along with a
library containing specified components, and then create an executable.
This approach allows for the easy creation of multiple executables by
specifying the component with the app_main function, as demonstrated in
the test.

```
idf_build_executable(fatfs_example COMPONENTS fatfs_example)
idf_build_executable(hello_world_example COMPONENTS hello_world_example)
```

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 213d128718 feat(cmakev2/build): remove INTERFACE option from idf_build_library
The option is unnecessary and complicates the interface. Additionally,
it does not adhere to the previously established naming convention. The
target name for the library interface is provided as a standard function
argument.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 6152758c99 feat(cmakev2/test): add fatfs_example and hello_world_example
Add two components: fatfs_example and hello_world_example. These are
simply copies of the main components from the existing examples.

Enhance the test_executable test to create targets for two
executables, which can be built after CMake configuration.

```
cmake --build build/ --target hello_world_example
cmake --build build/ --target fatfs_example
```

Additionally, move the test_component_priority to the end of the test
chain, as it modifies the esp_system component, which interferes with
the linkage of the executables.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 3804fcfb2c feat(cmakev2/ldgen): add ldgen integration
Integrate the ldgen into cmakev2. With this change, it becomes possible
to actually link the project executables.

In cmakev2, the handling of linker scripts is deferred to
idf_build_library, unlike in cmakev1, where linker scripts were added
and generated during the target_linker_script call. In cmakev2, the
target_linker_script only adds the linker scripts and templates, along
with the output filenames for the linker scripts generated from the
templates, to the component property. When idf_build_library is called
and all the requested components are included, it uses the
__get_target_dependencies function to obtain all transitively linked
targets to the library interface target. These targets are mapped to the
components, and the LIBRARY_COMPONENTS_LINKED library property is set.
It contains all components linked to the library interface target. The
components from LIBRARY_COMPONENTS_LINKED are used to collect linker
fragments and linker scripts utilized in the library. Additionally, all
targets transitively linked to the library are used to identify archive
files used in the library. This includes component archives and archives
added with the add_prebuilt_library function. The archives and
ldfragments related to the components linked to the library are used
when ldgen generates the linker scripts from templates.

The linker scripts, both static and generated by ldgen, are added to the
library interface link options and INTERFACE_LINK_DEPENDS property. For
generated linker scripts, a custom target is created and added as a
dependency for the library interface to ensure they are generated before
the link.

The difference compared to cmakev1 is that the generated linker scripts,
currently only sections.ld, are not global in the project but are
generated per library. This means there might be multiple versions of
sections.ld depending on the components included in the library. For
example, a component like esp_system may be linked to multiple library
interface targets, each with a different set of components. This results
in different sets of fragment files and library archives and different
versions of the sections.ld linker script. This should ensure proper
dependencies between targets. In other words, if a component changes its
linker fragment, only executables linked to libraries using this
component should be re-linked. As a consequence of this approach, the
generated linker scripts for different libraries need to have different
names or be stored in different directories to avoid overwriting the
linker script for one library with the linker script for another library
using the same component. This is handled with a suffix, which is based
on the library interface target name and appended to the generated
linker script. So, for example, there is no sections.ld, but instead
sections.ld_fatfs_lib or sections.ld_hello_world_lib. As a next step, we
can add a DEFAULT option to idf_build_library and avoid adding the
suffix for the default library.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata e06624f552 feat(cmakev2/build): track components linked to library
There may be multiple libraries, each linking a different set of
components. Introduce a new library property, LIBRARY_COMPONENTS_LINKED,
to track the components linked with a specific library. This property
can be used, for example, by menuconfig to distinguish between included
and excluded components on a per-library or per-executable basis, or by
ldgen to identify linker scripts for the linked components.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 965650dc11 feat(cmakev2/feat): add __get_target_dependencies helper
Based on the INTERFACE_LINK_LIBRARIES and LINK_LIBRARIES properties,
recursively retrieve the list of dependencies for the specified target.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata f000545630 feat(cmakev2/compat): initialize common components within idf_component_register
Currently, the common components are initialized in the idf_project_init
macro, which means they are included even for cmakev2 components.
However, cmakev2 components are expected to explicitly specify all their
dependencies instead of relying on common components being automatically
linked. Therefore, common components are only relevant within the
context of cmakev1 components. To address this, move the
__init_common_components function call to idf_component_register and
include common components only when they are truly needed for a cmakev1
component.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata edf62c3557 feat(cmakev2/test): add simple executable test
Add a simple test_executable that links to all discovered components.
This is intended to verify if the component sources can be compiled
using the command `cmake --build build/ --target test_executable`. The
ldgen is not yet integrated, so the test_executable is not actually
created or linked. However, this process can be used to check if the
components are compiled.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata ff79ab7733 fix(cmakev2/project): add ESP_PLATFORM to compile_definitions
Set the ESP_PLATFORM macro to indicate to component sources that they
are being compiled with ESP-IDF.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 663460379c fix(cmakev2/utilities): avoid overwriting compile_options in __get_compile_options
Currently, the generic compile_options are ignored because they are
unset after retrieving the build property. To fix this, avoid explicitly
setting compile_options, as this variable is initialized with the
idf_build_get_property(compile_options ...) call.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata d9eb78c1fd feat(cmakev2/compat): link common components in idf_component_register
Automatically link commonly required components to the component target
created in the idf_component_register function. This is still necessary
even in cmakev2, as existing components depend on this behavior.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata bede750fcd feat(cmakev2/project): initialize and include commonly required components
Identify the commonly required components based on the target and
architecture, and store them in the __COMPONENT_REQUIRES_COMMON build
property. These components are automatically included, and their
interfaces are stored in the __COMMON_COMPONENT_INTERFACES build
property. The commonly required component interfaces are automatically
linked to each component.

Existing components for cmakev1 rely on the automatic linking of common
components. Therefore, at least initially, we need to implement the same
functionality in cmakev2.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 69a67e7e6e feat(cmakev2/idf): initialize IDF_TARGET_ARCH build property
Based on the configuration, set the IDF_TARGET build property. This is
also set by cmakev1 and can be used to easily determine the architecture
for the project.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 9040925c1c feat(cmakev2/component): add embedded files in idf_component_include
Add embedded source files to the component target sources. This is
intentionally managed in idf_component_include instead of
idf_component_register, allowing even cmakev2 components to set the
component's EMBED_FILES and EMBED_TXTFILES properties. Although it might
be more convenient to call the target_add_binary_data helper function
directly in cmakev2.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata e84250998d feat(cmakev2/compat): add idf_component_register function
Add a backward-compatible idf_component_register function. This is
necessary to enable existing components to integrate with cmakev2. Note
that, by design, when the configuration is evaluated first, the KCONFIG
and KCONFIG_PROJBUILD options become obsolete, and an error is reported
if non-default configuration file names are specified.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 4c88b9c31b feat(cmakev2/component): create component alias only after it has been included
Add a component interface alias only after the actual target is created,
meaning the component is included. The alias has a well-defined name and
can be used in generator expressions like
`$<$<TARGET_EXISTS:idf::esp_netif>:>` without needing to retrieve the
COMPONENT_ALIAS property.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 1129e8b8d4 feat(cmakev2/utilities): add add_prebuilt_library function
Imported from cmakev1 to enable the addition of prebuilt libraries into
the build.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 6431c056f7 feat(cmakev2/utilities): add target_add_binary_data function
Add binary data into the build target by converting it into a generated
source file, which is then compiled into a binary object as part of the
build process.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata cb426066d7 feat(cmakev2/utilities): add add_deprecated_target_alias function
The add_deprecated_target_alias function is used by some existing
components, so it should be added to cmakev2 as well.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata c83102eb5e feat(cmakev2/utilities): add file_generate function
The file_generate function is used by some existing components, so it
should be added to cmakev2 as well.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata d03257c9a9 feat(cmakev2/utilities): add fail_target function
The fail_target function is used by some existing components, so it
should be added to cmakev2 as well.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00