21 Commits

Author SHA1 Message Date
Frantisek Hrbata 44a610cbf0 feat(cmakev2/compat): allow to set commonly required components
The commonly required components are configured solely for backward
compatibility with cmakev1. Since the bootloader build explicitly sets
commonly required components, we need to support this feature in cmakev2
as well. Ideally, there should be no commonly required components, and
each component should specify its requirements explicitly.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-27 19:18:11 +08:00
Sudeep Mohanty 45dc2e5868 fix(cmakev2): Defer idf_component_optional_requires linking to library build time
This commit introduces a new build property, __OPTIONAL_REQUIRES_MODE,
and uses it to either defer or link immediately, optional requirements
to components that request such linkage via the
idf_component_optional_requires() function in build system v2. The
DEFERRED mode is intended for single-binary projects where in the linking
of optional components happens after the library target is created the
dependency graph is available to the build system, thereby allowing it to
behave like the v1 version of the function.

Made-with: Cursor
2026-03-04 15:09:15 +01:00
Sudeep Mohanty 454b944b76 feat(cmakev2): add idf_build_get_compile_options and use in compat and component
Add idf_build_get_compile_options() to aggregate COMPILE_OPTIONS,
C_COMPILE_OPTIONS, CXX_COMPILE_OPTIONS, and ASM_COMPILE_OPTIONS build
properties with generator expressions. Replace internal
__get_compile_options(OUTPUT ...) usage in idf_component_register and
idf_component_include with the new public function.
2026-02-24 11:21:19 +01:00
Frantisek Hrbata e1eae669bc fix(cmakev2/compat): change idf_component_optional_requires behavior
The idf_component_optional_requires compatibility function in cmakev2
currently attempts to mimic the behavior of cmakev1 by adding a
dependency only if a component is already included in the build. In
cmakev1, this is handled by checking the BUILD_COMPONENTS list, which is
created during an early evaluation phase. Because cmakev2 removed this
early phase to allow for configuration-based component dependencies, the
build system does not inherently know which components will be part of
the build beforehand. To compensate, the current compatibility function
relies on the TARGET_EXISTS generator expression to determine if a
component should be linked.

This approach poses a problem because generator expressions are not
evaluated until the generation phase, but cmakev2 processes linker
scripts during the configuration phase by recursively scanning targets
linked to a library. Because the scanner does not recognize and cannot
evaluate generator expressions, any component linked optionally through
generator expression is skipped. If that component carries a linker
script, the script is never added to the library interface, resulting in
build failures. Since cmakev2 aims to support multiple libraries, a
component might also exist globally, causing TARGET_EXISTS to evaluate
to true, yet still be missed during a specific library's recursive scan,
leading to the same omission of necessary linker scripts.

To resolve this, the implementation of idf_component_optional_requires
is changed to check if a component is known to the build system in
COMPONENTS_DISCOVERED build property. If so, it is explicitly included
and linked directly via its interface target. While this may pull more
components into a build than the previous generator expression method,
potentially increasing build times, it ensures that dependency trees are
fully visible to the library target scanner. This serves as a practical
middle ground that maintains compatibility with existing components and
ensures build stability. This approach allows for the gradual fixing of
idf_component_optional_requires usage in components for cmakev2, with
the eventual goal of removing its usage in cmakev2 entirely.

This change also fixes cases where idf_component_optional_requires is
used to conditionally add requirements based on configuration options.
In cmakev2, the presence of a configuration option does not guarantee[1]
that a component has been included via add_subdirectory, unlike the
behavior in cmakev1. With this change even constructions like

```cmake
if(CONFIG_VFS_SUPPORT_IO)
    idf_component_optional_requires(PRIVATE vfs)
endif()
```

will now work in cmakev2, as the updated idf_component_optional_requires
explicitly includes the required component if it is available to the
build system.

Closes https://github.com/espressif/esp-idf/issues/18133

[1] https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system-v2.html#id9

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-02-04 09:28:35 +01:00
Frantisek Hrbata c98146a8c6 fix(cmakev2/compat): add esp_stdio to common requires
The cmakev1 added esp_stdio to common requires, add it in cmakev2 too
for backward compatibility.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 11:06:02 +01:00
Frantisek Hrbata 997cd81675 feat(cmakev2/compat): add idf_component_register to the API
Using idf_component_register is the preferred method for creating new
components for cmakev2. This approach ensures compatibility with both
versions of the build system. The KCONFIG and KCONFIG_PROJBUILD options
have been removed from the API documentation, but are retained in code
in case a cmakev1 component uses these options to warn about
incompatibility. Also remove a note about `project_include.cmake`,
because cmakev2 includes all project_include files.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 2760eca984 feat(cmakev2/build): rename LINKER_SCRIPTS_STATIC to LINKER_SCRIPTS
Rename the LINKER_SCRIPTS_STATIC component property to LINKER_SCRIPTS.
This property stores linker scripts that are not processed by ldgen,
which essentially includes all of them. The only linker script processed
by ldgen is sections.ld, which is handled by the esp_system component.
This implies that there is likely no practical use case for other
components to utilize ldgen processed linker scripts. This change is
purely cosmetic to allow components to add linker scripts with:

idf_component_set_property(${COMPONENT_TARGET} LINKER_SCRIPTS linker_script.ld APPEND)

instead of

idf_component_set_property(${COMPONENT_TARGET} LINKER_SCRIPTS_STATIC linker_script.ld APPEND)

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 229000b186 fix(cmakev2/docs): keep only the very basic functions in API
Currently, we include numerous functions in the automatically generated
documentation for the build system API. Let's begin with only the
essential functions and gradually add more to the API based on requests
and actual needs.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Sudeep Mohanty e744534fca fix(cmakev2): Add workaround in idf_build_component for duplicate managed component
This commit adds a workaround in idf_build_component shim to avoid
initialization of a duplicate managed component. The component manager
when running on a Windows system returns duplicate managed components
upon successive invocations.
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 7ff30604fb fix(cmakev2/compat): newlib renamed to esp_libc
The component has been renamed, update the name in the common
requirements for the cmakev1 components.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata abddda342f fix(cmakev2/docs): reformat function arguments for API documentation
The function arguments in the documentation comments were using field
list, which caused text overflow in the generated documentation and
generally resulted in poor formatting. Let's use paragraphs for
the argument descriptions instead.

The documentation comments are written in reStructuredText, but
currently, they use inconsistent indentation. Standardize all the
documentation comments to use a four-character indentation.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
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 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 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 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 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 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 1fe41c4521 feat(cmakev2/compat): add idf_component_optional_requires function
Add the specified component as a dependency only if it is included in
the build. This functions the same way as in cmakev1, but it uses
generator expressions because cmake2 does not maintain the
BUILD_COMPONENTS build property, which would list all components
included in the build.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 07cffc73fa feat(cmakev2/compat): add target_linker_script stump
Currently, this is just a placeholder without implementation. The
implementation will be completed in a subsequent patch set that
integrates ldgen. For now, this is enough for ESP-IDF components can be
included by cmakev2.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata c67dabd5c3 feat(cmakev2/compat): add __get_component_sources helper
This helper function collects component sources within the component's
directory. It will be used by the idf_component_register.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-10-30 17:17:49 +08:00
Frantisek Hrbata 0d7d6f6b3e feat(cmakev2/compat): add check_expected_tool_version helper
The compat.cmake file is intended to include functions necessary for
backward compatibility with cmakev1.

Add the check_expected_tool_version function, which is used by some
project_include.cmake files to verify if the tool's version matches the
installed tool. This functionality is used, for example, by esp_common.

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