Commit Graph
100 Commits
Author SHA1 Message Date
Frantisek Hrbata 4e767b9a26 test(cmakev2): add test for build with IDF_COMPONENT_MANAGER=0
Verify that setting IDF_COMPONENT_MANAGER=0 skips the component manager
flow entirely and produces a successful build. The test also asserts that
no "Component manager round" messages appear in the output, confirming
the manager loop is not entered.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-24 08:10:14 +01:00
Frantisek Hrbata ede97294aa fix(cmakev2): skip component manager flow when IDF_COMPONENT_MANAGER=0
When the component manager is disabled via IDF_COMPONENT_MANAGER=0, the
cmakev2 build system still entered the full component manager flow
(__fetch_components_from_registry), which called
__download_managed_component(). That function returned early with
result=0 without creating the expected output file, violating the
post-condition in __download_component_level_managed_components() that
checks result==0 => file exists, causing a fatal error.

Instead of patching the low-level function to write an empty stub file,
this commit properly skips the entire component manager flow when the
manager is disabled:

- Move __init_component_manager() to idf.cmake global initialization
  sequence alongside other __init_*() calls, so IDF_COMPONENT_MANAGER
  build property is available early.

- Set __SDKCONFIG_ORIG to the real sdkconfig path in __init_kconfig()
  as its default value. Previously it was only set inside
  __create_sdkconfig_orig_copy() and had a defensive fallback in
  __create_base_kconfgen_command(). The default ensures __SDKCONFIG_ORIG
  is always valid regardless of whether the component manager runs.

- Guard __create_sdkconfig_orig_copy() with an IDF_COMPONENT_MANAGER
  check. The sdkconfig backup exists solely to preserve unknown Kconfig
  options from managed components during intermediate kconfgen rounds.
  When the manager is disabled, no managed components exist, so the
  backup is unnecessary.

- Guard __fetch_components_from_registry() call in project.cmake behind
  IDF_COMPONENT_MANAGER == 1. When disabled, only the manifest warning
  is issued. No download loop runs, no temp files are created, and no
  "Component manager round N..." messages are printed.

- Remove the now-redundant IDF_COMPONENT_MANAGER guard from
  __download_managed_component(), since it is only reachable when the
  manager is enabled.

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

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-24 08:10:14 +01:00
Frantisek Hrbata fa14a9df47 Merge branch 'feat/cmakev2-backports-v6.0' into 'release/v6.0'
feat(cmakev2): sync pending v6.0 MRs for cmakev2

See merge request espressif/esp-idf!46778
2026-03-21 07:17:43 +01:00
Frantisek Hrbata 8ed25711ac fix(cmakev2): remove stale test CMakeLists.txt missed by cherry-pick
The cherry-pick in the backport of \!46287 (test/buildv2_pytest_build_v6.0)
dropped the deletion of tools/cmakev2/test/CMakeLists.txt. The original MR
deleted all 15 files from the tools/cmakev2/test/ directory, but the
cherry-pick only captured 14 deletions. This commit removes the missed file.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:16:52 +01:00
Frantisek Hrbata e14d50b79b fix(ulp): add sdkconfig directory to ULP target include directories
The ULP sources include sdkconfig.h for compile-time configuration
values. The sdkconfig directory was previously available to the ULP
target indirectly through the COMPONENT_INCLUDES variable, which is
populated from the parent component's INTERFACE_INCLUDE_DIRECTORIES.
In cmake v1, idf_component_register() adds the config_dir as PUBLIC
include directory to every component (component.cmake:498), so it
ends up in INTERFACE_INCLUDE_DIRECTORIES and gets passed to the ULP
subproject via COMPONENT_INCLUDES.

In cmakev2, the config_dir is added as a build-level property and
applied to components as PRIVATE (component.cmake:1053), so it no
longer appears in INTERFACE_INCLUDE_DIRECTORIES. As a result, the
sdkconfig directory is missing from the ULP target's include paths.

Add the sdkconfig directory explicitly to the ULP target's include
directories. Note that SDKCONFIG_HEADER is already passed to the ULP
subproject and its directory is already extracted into sdkconfig_dir
for linker script preprocessing (IDFULPProject.cmake:40).

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:16:52 +01:00
Frantisek Hrbata 53b684c00d fix(cmakev2/project): export build properties as variables for project_include.cmake
In cmake v1, __build_process_project_includes() exports all build
properties as CMake variables before including project_include.cmake
files. cmakev2 was missing this step, causing components like ULP that
reference build properties as CMake variables (e.g. ${SDKCONFIG_HEADER})
to receive empty values.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:16:52 +01:00
Frantisek Hrbata cdbc0244e0 fix(cmakev2/kconfig): add public aliases for sdkconfig output properties
The cmakev2 kconfig module sets sdkconfig output paths using internal
property names (__SDKCONFIG_HEADER, __SDKCONFIG_CMAKE, etc.), but
components like ULP read the public names (SDKCONFIG_HEADER,
SDKCONFIG_CMAKE). This results in empty values being passed to the ULP
sub-project, causing its CMake configure step to fail.

Add public aliases matching the cmake v1 property names for backward
compatibility.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:16:52 +01:00
Frantisek Hrbata 22626469de fix(cmakev2/utilities): add a dependency target for the embedded file
Currently, embedded files can be added in two ways. First, by calling
the `target_add_binary_data` function directly within a component.
Second, by passing `EMBED_FILES` or `EMBED_TXTFILES` to
`idf_component_register`, or in cmakev2 by setting the `EMBED_FILES` or
`EMBED_TXTFILES` component properties.

The source file for an embedded file is generated using
`add_custom_command`. When the embedded file is added directly in the
component's CMakeLists.txt file by using the `target_add_binary_data`
function, the `add_custom_command` command is evaluated in the same
directory context where the component target is created. As a result,
the generated embedded file can be used automatically as a file
dependency in component's sources.

However, when an embedded file is added via `idf_component_register` or
by setting the component property, the call to `add_custom_command`
inside `target_add_binary_data` occurs after the component has been
evaluated, specifically after the `add_subdirectory` call, within
`idf_component_include`. This means it is not created in the same
directory context as the component's target. In this case, the embedded
file dependency is not added to the component's target, and the embedded
file is not generated. This behavior is described in the
`add_custom_command` documentation [1].

   > A target created in the same directory (CMakeLists.txt file)
   > that specifies any output of the custom command as a source
   > file is given a rule to generate the file using the command at
   > build time.

To fix this issue, an explicit custom target for the generated embedded
file is created and added as a dependency of the component's target,
ensuring that the file is generated correctly.

[1] - https://cmake.org/cmake/help/latest/command/add_custom_command.html

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata a06f85a79f fix(esp_phy/cmake): initialize embed_files variable
In cmakev2, a component can be evaluated within the context of another
component, so it's important to properly initialize each variable used
by the component.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata 9d19eba6e2 fix(test_build_system): add __init__.py to buildv2 test directory
Pytest's default import mode (prepend/rootdir) imports test modules as
top-level modules keyed by filename. When two directories contain test
files with the same basename (e.g. test_sdkconfig.py in both
test_build_system/ and test_build_system/buildv2/), pytest tries to
register both as the module name "test_sdkconfig". The second collection
fails with "import file mismatch" because the module object already
cached in sys.modules points to the first file.

Adding __init__.py to the buildv2/ directory makes it a proper Python
package. Pytest then imports its test modules under the package
namespace (buildv2.test_sdkconfig), which is distinct from the
top-level test_sdkconfig, resolving the collision.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata 2aacc2ad0c fix(cmakev2/kconfig): preserve sdkconfig options from managed components
The sdkconfig file may contain configuration options defined in Kconfig
files of managed components. Since kconfgen runs before the component
manager fetches these components, the Kconfig definitions for managed
component options are not yet available. The kconfgen --output config
flag regenerates sdkconfig from kconfiglib's internal state, which only
knows about options with loaded Kconfig definitions. This causes unknown
options (i.e., those from managed components) to be silently dropped
from sdkconfig during intermediate regeneration rounds.

Note that kconfgen's --config flag (used for reading sdkconfig) only
performs deprecated option name replacement and does NOT drop unknown
options. The problem is exclusively in --output config, which writes a
fresh sdkconfig from the parsed Kconfig tree state.

Fix this by introducing a __SDKCONFIG_ORIG build property that provides
an indirection layer for the --config input path:

- Before the component manager runs: __SDKCONFIG_ORIG points to a copy
  of the original sdkconfig (build/sdkconfig.orig), created by the new
  __create_sdkconfig_orig_copy() function. This copy preserves all
  original options, including those from managed components.

- During intermediate kconfgen runs: --config reads from the preserved
  copy (so unknown options survive as input), while --output config
  writes to the real sdkconfig (unknown options may be dropped there,
  but this is harmless since kconfgen always reads from the copy).

- After the component manager completes: __SDKCONFIG_ORIG is reset to
  point to the real sdkconfig and __BASE_KCONFGEN_CMD is rebuilt, so
  that subsequent operations (menuconfig, save-defconfig, confserver)
  read and write the actual sdkconfig file directly.

The flow is:

  __create_sdkconfig_orig_copy()
    -> __SDKCONFIG_ORIG = build/sdkconfig.orig

  __generate_sdkconfig()
    -> --config build/sdkconfig.orig --output config project/sdkconfig

  __fetch_components_from_registry():
    loop:
      download_components()
      __generate_sdkconfig()
        -> --config build/sdkconfig.orig --output config project/sdkconfig
      if success: break
    endloop
    -> __SDKCONFIG_ORIG = project/sdkconfig
    -> rebuild __BASE_KCONFGEN_CMD

  idf_create_menuconfig() / save-defconfig / confserver
    -> uses --config project/sdkconfig (the real file)

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata ac3217a9e4 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-03-20 08:13:26 +01:00
Frantisek Hrbata 4f18ef68d4 feat(test_build_system): add buildv2 test for linux target build
Add a simple test to verify that the buildv2_test_app can be built for
the Linux target.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata 2abd858e61 feat(test_build_system): allow buildv2 specific tests
Currently, cmakev2 is being tested only in backward-compatible mode by
using the existing cmakev1 tests with the cmakev2 test application. We
also need to add tests specific to cmakev2, and it is convenient to
reuse the existing build system testing framework. Let's add a `buildv2`
subdirectory to the existing `tools/test_build_system` directory and use
the `pytest_collection_modifyitems` hook to ignore tests in this
directory unless the `--buildv2` option is used.

Without the `--buildv2` option, only the existing cmakev1 tests are
executed and tests in `buildv2` directory are skipped. With the
`--buildv2` option, the existing cmakev1 tests run with the cmakev2
testing application for backward compatibility testing, and all cmakev2
tests within the `buildv2` subdirectory are also executed.

Note: we cannot use the `pytest_ignore_collect` hook, because the
`--buildv2` option is not known to the pytest, so the
`config.getoption('--buildv2', False)` returns always False. We would
likely need to add the `--buildv2` option in the conftest.py in the
esp-idf root directory.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>

fix: lsadjf las jflasjfl aslfsald asl fsadlf sladsal jfsadfas

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata 4c0566361e feat(test_build_system): add pytest header whether buildv1 or buildv2 is running
This adds a clear header to the pytest output, indicating which build
system version is currently being tested.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata 33680597c7 fix(freertos): set app_main as undefined even for linux target
In cmakev1, the initial order of components linked to the executable is
determined by the `__build_expand_requirements` function and stored as a
list in the `BUILD_COMPONENT_ALIASES` build property. Later, the
components from `BUILD_COMPONENT_ALIASES` are linked to the executable
using `target_link_libraries`. The issue is that
`BUILD_COMPONENT_ALIASES` contains components in a "reversed" order
compared to how they would typically appear on the link command line. In
other words, components (archives) deeper in the dependency chain are
placed first. As a result, cmake has to repeat the archives in the link
command more times than is actually necessary. This has the beneficial
side effect of placing libfreertos.a before libmain.a, allowing the
`app_main` symbol to be resolved.

In cmakev2, there is no predefined order because it does not perform
early evaluation. Instead, the entire link command is created based on
actual component dependencies using `target_link_libraries`.
Consequently, freertos must set the `app_main` symbols as undefined.
This is already done for non-Linux targets, but it must also be done for
the Linux target.

Another issue arises with macOS, which mangles C symbols by prepending
an underscore. We cannot use the same method as in
`components/linux/assert_func.c` for `__assert_func`, so for macOS,
`_app_main` is used. In the future, if more undefined symbols need to be
added for the Linux target, we should consider introducing a helper.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata b56b3547f5 fix(cmakev2/build): extend idf_build_generate_metadata to also accept executable
Currently, idf_build_generate_metadata only accepts binary targets for
which it generates metadata (project_description.json). On Linux
targets, binary images are not generated, but we still need to generate
project_description.json. Extend the current function to accept both
executable and binary targets and ensure project_description.json is
generated when a Linux target is used.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata 60e46a1b3f fix(cmakev2/compat): display empty components as excluded into menuconfig
Some components simply return when included in a build for the Linux
target. This is silently ignored in the `idf_component_include`, and the
component interface target is linked as requirement in
`idf_component_register`. This has the side
effect of such components being reported as included, with their
configuration displayed in the menuconfig for included components,
rather than in the submenu for excluded components. For example, the
`bt` component, if added as a dependency in `idf_component_register`,
will be displayed in menuconfig as an included component for Linux
target. The `idf_component_include` function sets the component's
`COMPONENT_REAL_TARGET` property to `NOTFOUND` in such situations. Use
this information when config.env is generated put such components into
excluded submenu. Note that we cannot avoid linking empty component interface
into library, because there might be recursive dependencies and at the
time when the component is included we might not now if it has a real
target or not.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata 82a063957a fix(cmakev2/project): generate binaries only if esptool_py component is present
Currently, the CONFIG_APP_BUILD_GENERATE_BINARIES option is used to
determine whether binary images will be generated in
idf_project_default. At present, this option is enabled even for the
Linux target, where the esptool_py component is not included, preventing
the generation of binary images. To address this issue, verify if the
target for esptool_py is present.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata f90f706e6e fix(bt/config): use osource for target controller configuration
In cmakev2, the configuration for all components is included because the
complete configuration is generated very early, before any component is
actually evaluated. This poses a problem for the Linux target, which
does not have a controller Kconfig.in file, causing kconfgen to fail due
to the missing include. To address this, let's use the osource command,
which does not include the referenced Kconfig file if it does not exist.

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

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata 5e9e17ef09 fix(cmakev2/idf): fix IDF_TOOLCHAIN build property for linux target
The IDF_TOOLCHAIN build property is currently incorrectly set to the
default `gcc` value for the linux target, whereas it should be empty.
This misconfiguration causes confusion for components like `soc`, which
adjust toolchain options based on the
IDF_TOOLCHAIN(CONFIG_IDF_TOOLCHAIN_GCC) build property's setting.

When sdkconfig is generated, the IDF_TOOLCHAIN build property is passed
as an environmental variable to kconfgen, and the CONFIG_IDF_TOOLCHAIN
configuration option is set based on this variable. Additionally, the
CONFIG_IDF_TOOLCHAIN_GCC and CONFIG_IDF_TOOLCHAIN_CLANG configuration
options are set accordingly. Subsequently, CONFIG_IDF_TOOLCHAIN_GCC is
used in several places, such as `components/soc/project_include.cmake`,
to configure the toolchain (compiler flags) by invoking functions from
`tools/cmake/toolchain_flags.cmake`, which is included only for
non-linux targets. As a result the configuration fails, because
functions from `tools/cmake/toolchain_flags.cmake` are not available on
linux target.

Since the IDF_TOOLCHAIN cmake cache variable is actually set in the
`tools/cmake/toolchain.cmake` file, the IDF_TOOLCHAIN build property
should be set after the toolchain is initialized in cmakev2's project
initialization. Note that each toolchain file, except for linux,
includes `toolchain.cmake`, which in turn includes
`toolchain_flags.cmake`. This means the IDF_TOOLCHAIN cmake cache
variable is set for every target except linux, because the toolchain
file for linux is empty. As a result CONFIG_IDF_TOOLCHAIN is empty and
CONFIG_IDF_TOOLCHAIN_GCC not set as for cmakev1.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata 15f885bbf0 fix(soc/cmake): fix the usage of the uninitialized variable
The `srcs` list variable is used without initialization when building
for linux target. Initialize it explicitly.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata f83ec13a2f fix(linux/cmake): fix the usage of the uninitialized variable
The `srcs` list variable is used without initialization when building
for linux target. Initialize it explicitly.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek Hrbata 50876225a3 fix(cmakev2/component): use component interface in dependency chain
The dependency chain currently tracks component names that are included
recursively with `idf_component_include`. However, these component names
can be ambiguous because a component may be referenced by different
names, such as with a namespace. Additionally, `idf_component_include`
can accept anything that `__get_component_interface` accepts, meaning
even the component interface target can be used to include the component
in the build. To uniquely identify each component, use component
interface targets instead of names in the dependency chain.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-03-20 08:13:26 +01:00
Frantisek HrbataandClaude Opus 4.6 90875ec492 fix(cmake): Fall back to version from components when git describe fails
When version.txt does not exist and git describe fails (e.g. in
release archives or environments without git), IDF_VER was set to
the raw git_describe output which resolves to "-128-NOTFOUND",
causing esp_get_idf_version() to return a garbled string.

Add a fallback that constructs the version string from the
IDF_VERSION_MAJOR, IDF_VERSION_MINOR and IDF_VERSION_PATCH
variables when git describe is not available.

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

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-02-24 12:55:20 +01:00
Frantisek Hrbata 1e5d8fbf82 fix(build): ensure the main component exists when MINIMAL_BUILD is enabled
The minimal build property is simply a shorthand for `set(COMPONENTS
main)`. The issue is that there is currently no check to verify whether
the `main` component actually exists or is known to the build system.
If the `main` component is not present, print an error message along
with suggestions on how to fix this inconsistency.

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

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-02-17 06:59:55 +01:00
Frantisek Hrbata b0d7f55d2a fix(ci): add rules.yml to check-tools-files-patterns pre-commit hook pattern
If `.gitlab/ci/rules\.yml` is changed, make sure the
`check-tools-files-patterns` pre-commit hooks is triggered to verify
that all `tools/*` files are covered by rules.yml.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-01-19 18:34:11 +08:00
Frantisek Hrbata fb61fa2209 fix(cmake): disable MINIMAL_BUILD build property if COMPONENTS is defined
The MINIMAL_BUILD build property and the COMPONENTS variable are both
used to determine the initial component list for the build.

Currently, if the COMPONENTS variable is set, the MINIMAL_BUILD logic
is ignored during component selection, but the MINIMAL_BUILD build
property remains set. This leads to an inconsistent state where
menuconfig displays information indicating MINIMAL_BUILD is active,
even though it was ignored in favor of the COMPONENTS variable.

Fix this by setting the MINIMAL_BUILD property to OFF if the
COMPONENTS variable is used.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-01-19 18:34:11 +08:00
Frantisek Hrbata 6278ca37f9 fix(cmakev2/component): use __idf_component_get_property_unchecked
In some instances, the COMPONENTS_DISCOVERED build property is used to
walk through the component list and obtain component properties, such as
during configuration preparation or the inclusion of project_include
files. Since we know the component interfaces from the
COMPONENT_INTERFACES build property, we can switch to the faster
`__idf_component_get_property_unchecked` method to obtain component properties
in these cases. This change reduces the reconfiguration time by 0.4
seconds on my computer.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-01-17 09:56:47 +01:00
Frantisek Hrbata 638444f0fd fix(cmakev2/component_validation): accelerate component validation
The commit f951ae5b18 ("feat(cmakev2): Added component validation
checks for ...") introduced support for validating component sources and
include directories. It heavily relies on iterating through the
registered components to obtain their properties. For instance, it
examines all components for each component source file to ensure that
the source files do not originate from other components. However, it
turns out that `idf_component_get_property` is a bottleneck in this
process, causing reconfiguration to take 3-4 times longer than before
the introduction of this check. Since we know of all the component
interfaces, we can bypass the checks performed by
`idf_component_get_property` and instead use the raw version,
`__idf_component_get_property_unchecked`, which operates much faster.

Following are hello_world example reconfigure times before and after.

before:

-- Configuring done (11.1s)
-- Generating done (0.2s)

after:

-- Configuring done (3.9s)
-- Generating done (0.2s)

A new library property LIBRARY_COMPONENT_INTERFACES_LINKED is added that
keeps component interfaces linked to the library.

Fixes: f951ae5b18 ("feat(cmakev2): Added component validation checks for ..")
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-01-17 09:56:47 +01:00
Frantisek Hrbata 82193cdbb2 feat(cmakev2): introduce __idf_component_get_property_unchecked helper
Retrieve the value of the specified component property quickly. The
existing `idf_component_get_property` function performs various checks
to identify the component interface target, which keeps the component
properties, and accepts a component name, target, target alias, or
interface. While `idf_component_get_property` uses a cache to identify
the component interface relatively quickly, it is still much slower
compared to the raw `get_property`. The
`__idf_component_get_property_unchecked` function provides a faster way how to
obtain component property if the component interface is already known.
It skips all the checks, so it must be used carefully.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-01-17 09:56:47 +01:00
Frantisek Hrbata 7d81ee3b0f fix(ldgen): correct formatting issues reported by ruff
Resolve ruff's UP031 errors related to the use of percent formatting for
strings and lines longer than 120 characters.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-01-15 11:36:10 +01:00
Frantisek Hrbata 0d6ba577da fix(ldgen): correctly place symbols generated by compiler during IPA
As part of inter-procedural optimizations (IPA), the compiler may
perform tasks such as constant propagation for functions. This involves
generating a specialized version of a given function with a new symbol
name that includes a suffix. For example, during constant propagation,
the compiler might create a specialized version named
`spiflash_start_core.constprop.0` for the `spiflash_start_core`
function. Additionally, the compiler may generate multiple clones of a
single function. Currently, when ldgen performs symbol placement, it
does not account for these compiler-generated functions, leading to
their incorrect or unexpected placement in memory (markers).

Consider a linker fragment with:

```
[mapping:spi_flash]
archive: libspi_flash.a
entries:
    esp_flash_api: spiflash_start_core (noflash)
```

The `spiflash_start_core` function should be placed in IRAM. However,
the compiler might generate an optimized version of this function with a
`.constprop.0` suffix, resulting in a
`.text.spiflash_start_core.constprop.0` input section. Currently, ldgen
does not handle this situation, leading to misplaced symbols.

Since `.` is not allowed in C identifiers, it should be safe to consider
all input sections for a symbol with any `.` suffix as representing that
symbol. This means considering the symbol suffixes should not cause any
ambiguity.

This change automatically places all input sections, including those
with possible suffixes for a given symbol, into the specified memory. In
other words, specifying a function name like `spiflash_start_core` in a
linker fragment automatically includes input section names matching
`spiflash_start_core(\..*)?$`.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2026-01-14 13:21:57 +01:00
Frantisek Hrbata 211b2da437 feat(cmakev2/build): add idf_build_generate_depgraph function
The idf_build_generate_depgraph function creates a component dependency
graph in dot (graphviz) format for a specified executable. It uses
existing helper functions from cmakev1, ensuring that the generated dot
files are produced in the same manner as in cmakev1. While adjustments
might be needed in the future if necessary, the current implementation
is intended to offer the same functionality as cmakev1.  Similar to
cmakev1, the dot files are only generated only when the
__BUILD_COMPONENT_DEPGRAPH_ENABLED build property is set.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-12-12 11:55:35 +01:00
Frantisek Hrbata c1b24d739a feat(cmakev2/ldgen): provide ldgen with a list of mutable libraries
The build system keeps track of each component source. Currently
there are four types of sources:

1. "project_components" - project components
2. "project_extra_components" - components from EXTRA_COMPONENT_DIRS
3. "project_managed_components" - custom project dependencies managed by the IDF Component Manager
4. "idf_components" - ESP-IDF built-in components, typically under /components

This can be used to identify the component libraries that are likely to
change during application development and pass them to ldgen as mutable
libraries. Add all components with "project_components" as their source
as mutable.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-26 16:18:35 +01:00
Frantisek Hrbata ada84b3ac4 fix(cmakev2/kconfig): avoid unnecessary sdkconfig generation
Add a helper function `__should_generate_sdkconfig()` that checks
whether the sdkconfig file should be generated.  The
`__generate_sdkconfig()` function can be called multiple times, such as
when the initial sdkconfig is generated at the start of the build
process and later after additional components are fetched by the
component manager.  There might be no components fetched by the
component manager, for example, in the hello_world example, or the
downloaded components may not contain any configuration files. In such
cases, there is no need to regenerate the sdkconfig. This helper
function stores the list of configuration files in the
`__PREV_KCONFIGS`, `__PREV_KCONFIG_PROJBUILDS`, and
`__PREV_SDKCONFIG_RENAMES` build properties at its end, and at the
beginning, it compares them with the current lists of configuration
files.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-26 16:17:43 +01:00
Frantisek Hrbata 91add83a38 feat(cmakev2/size): add idf_create_size_report function
The idf_create_size_report function allows for the creation of size
report targets based on the generated link map file. The size report
targets are created using the TARGET option name: "<target>",
"<target>-files", and "<target>-components". These size report targets
are added to the idf_default_project with the TARGET set to "size",
resulting in the creation of "size", "size-files", and "size-components"
targets for the default project.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-20 10:22:51 +01:00
Frantisek Hrbata 3318bd4c1d fix(cmakev2/project): unset global variables in idf_project_init macro
The idf_project_init macro is evaluated within the global variable
scope, and currently, there are a few variables still set. Let's ensure
all variables are properly unset to avoid polluting the global variable
namespace.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-20 10:22:51 +01:00
Frantisek Hrbata a500965fcb fix(cmakev2/build): display a warning when the MINIMAL_BUILD property is set
The MINIMAL_BUILD property is not relevant in cmakev2, as only
components explicitly linked through targets are included in the build
by design. Display a warning when this outdated build property is set.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-20 10:22:50 +01:00
Frantisek Hrbata 177483ec55 fix(cmakev2/build): fix the generation of the link map file
The link flag for generating the map file is currently added globally to
the link_options. If multiple executables are generated, the link map
file is overwritten by the last created executable. Since cmakev2
supports building multiple executables, the link map file options need
to be set for each executable individually. To address this, add a new
MAPFILE_TARGET option to the idf_build_executable function. When set,
the link map file will be generated by the linker, and a target
specified in the MAPFILE_TARGET option will be created for the map file.

This also splits the idf_project_default macro.  Only the
idf_project_init macro needs be called within the global scope, as it
includes the project_include.cmake files and the cmake version of the
configuration. The remaining functionality of the idf_project_default
macro is implemented in a __project_default helper function to avoid
polluting the global variable space.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-20 10:22:50 +01:00
Frantisek Hrbata f23de1f518 fix(cmakev2/build): pass binary target to idf_build_generate_metadata
Currently, the `idf_build_generate_metadata` function takes an
executable target as an argument, and the binary name is stored in the
`EXECUTABLE_BINARY` property. This approach is inconvenient because a
single executable might generate multiple binary images, making it
unreliable to store the binary image name in the executable property due
to the N:1 relationship. To address this, pass the binary image target
instead of the executable target to the `idf_build_generate_metadata`
function. This change is facilitated by linking the binary target,
executable target, and library interface targets with the following
properties:

binary:EXECUTABLE_TARGET -> executable:LIBRARY_INTERFACE -> library

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-20 10:22:50 +01:00
Frantisek Hrbata 621af79762 fix(cmakev2/project): remove temporary workaround for partition and bootloader flash dependencies
With commit b719292b75 ("refactor(build-system): Simplify flash target creation"),
partition table and bootloader components are correctly adding their
dependency on the flash target, so there is no need for this to be done
in the build system. This removes the temporary workaround.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-20 10:22:50 +01:00
Frantisek Hrbata d5fcecbe85 ci(pre-commit): exclude buildv2_test_app from check-readmes
The `tools/test_build_system/buildv2_test_app` is a cmakev2 build system
testing application, same as `build_test_app`, which should be removed
from the readme check performed by check_build_test_rules.py.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-05 12:02:08 +01:00
Frantisek Hrbata dd5aae9c56 feat(cmakev2/project): add warning for usage of deprecated variables
The COMPONENTS and EXCLUDE_COMPONENTS variables are unused in cmakev2. A
deprecation warning will be printed if they are set. This change also
includes a helper functions for printing deprecation warnings.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-05 11:23:03 +01:00
Frantisek Hrbata 5724a6e1e4 fix(cmakev2/project): drop prefix_map_gdbinit in favor of gdbinit/prefix_map
The cmakev1 dropped generation of prefix_map_gdbinit, reflect this
change also in cmakev2.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-05 11:23:03 +01:00
Frantisek Hrbata c4d76cf7f4 fix(kconfig): distinguish project configuration menu for excluded components
Currently both menu configs, for component's project configuration and
component's configuration, for components not included in the build have
the same name: "Configuration for components not included in the build".
This might be confusing. Let's use "Project configuration for components
not included in the build" for component Kconfig.projbuild files.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-05 11:23:03 +01:00
Frantisek Hrbata a384cde5ae fix(cmakev2/project): bump C and CXX standard
The cmakev1 bumped C and CXX standard to gnu23 and gnu++26, do the same
in cmakev2.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-05 11:23:03 +01:00
Frantisek Hrbata 33e7824e33 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-05 11:23:03 +01:00
Frantisek Hrbata 48b1594238 feat(toolchain): more remove_duplicated_flags function to separate file
Currently, the toolchain CMake files use the remove_duplicated_flags
function from utilities.cmake. The cmakev2 implementation also includes
this function for backward compatibility. Move the
remove_duplicated_flags function to a separate file,
deduplicate_flags.cmake, so it can be shared between cmakev1 and
cmakev2.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:49:45 +01:00
Frantisek Hrbata 5985242d82 ci(pre-commit): revert temporary disable check-kconfig-files
Enable check-kconfig-files. It was temporarily disabled because it was
not possible to add a new sourced file through an environment variable,
as kconfcheck had a fixed list of allowed environment variable names.
This issue should now be resolved.
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 6653cf5c1f ci(cmakev2): run the buildv2 tests only if the buildv2 label is set
Currently, the buildv2 tests are initiated using the same patterns as
the tests for the current build system. This means that any change in
the current build system will also trigger the buildv2 tests. Initially,
it might be wise not to block the CI for changes in the current build
system in case there is an issue with buildv2. Therefore, let's
explicitly start the buildv2 tests only when the buildv2 label is set.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata f93a0d9ff2 fix(esp_libc/cmake): add vfs as requirement if CONFIG_VFS_SUPPORT_IO is enabled
The esp_libc relies on the stdio implementation of the vfs component if
CONFIG_VFS_SUPPORT_IO is enabled. This is not an issue in cmakev1
because if the vfs component is not included in the project build, its
configuration is not available, and CONFIG_VFS_SUPPORT_IO is not set.
However, in cmakev2, the configuration for all components is available,
and the presence of some component configuration options does not
necessarily mean that the component is included in the project build.
When esp_libc is compiled without the vfs dependency but with
CONFIG_VFS_SUPPORT_IO enabled, the libc initialization will encounter a
panic due to a NULL pointer dereference (fp->_flags) in __swsetup_r, as
fopen in esp_libc_init_global_stdio will return NULL.
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 78d07f5a2f feat(cmakev2/docs): add note about v2 being technical preview
Although the current documentation exposes only limited functionality,
which is unlikely to change, add an explicit note that the build system
v2 is currently a technical preview intended for testing and early
evaluation.

Ensure consistency in referring to v2 throughout the documentation. In
some places, it is referred to as V2 or Version 2; unify this to v2.

Additionally, update the hello_world example for v2 to use the
idf::spi_flash alias instead of the interface variable to maintain
consistency with the rest of the documentation.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 9c4b7ca488 feat(cmakev2/docs): prefer idf_component_register to create new components
Extend the current documentation to recommend using the
idf_component_register function as the preferred method for creating a
new component for v2.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 07a7581187 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-11-04 07:48:15 +01:00
Frantisek Hrbata ee1dec6145 feat(cmakev2/docs): extend esp_target_info component example
Enhance the `esp_target_info` component example by adding some of
the missing features that the component might require. This includes
adding a linker script, a linker fragment, linking the component archive
as a whole library, and providing an example of how the linker options
can be set.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata d82866aaf9 feat(cmakev2/docs): add information about cmakev2 component incompatibility with cmakev1
Components designed exclusively for cmakev2 are not compatible with
cmakev1 due to the lack of forward compatibility. It is important to
clarify this at the very beginning of the `Creating a New Component`
section. Additionally recommended a guidance on how to create a
component that will be compatible with both versions.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 832128e864 fix(cmakev2/component): set the cmakev2 component archive name
Currently, the archive file name is set only in the cmakev1
idf_component_register shim. The predictable component archive file name
is important, for example, for usage in linker fragments. Ensure that
the cmakev2 component also has the archive file name set.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 6f516845fc fix(cmakev2/component): fix setting SOURCES for cmakev2 components
Currently, when the cmakev2 component sources are set, the SRCS target
property is used.  This is obviously wrong because the correct CMake
property is SOURCES.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata e6b1c5857b 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-11-04 07:48:15 +01:00
Frantisek Hrbata 6373cc540b feat(cmakev2/docs): initial basic documentation
Add very basic documentation. It is currently written with the
expectation that the reader is already familiar with the existing build
system and focuses more on the changes that might be necessary to adapt
existing components to work with cmakev2.  Additionally, it provides
basic information on how to create a new component and project.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 65052dfbdd 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-11-04 07:48:15 +01:00
Frantisek Hrbata 72e96e4907 fix(cmakev2/component): fix component library link with whole archive
The current approach involves wrapping the library target within the
library interface target with the whole-archive flags, such as for the
GCC linker. However, this does not work as expected because the library
target is expanded, and the whole-archive flags are also applied to
other library targets that the wrapped library target depends on. IOW
the whole-archive flags surround multiple archives, not just the one
requrested.  Generally, using linker flags like whole-archive in the
library INTERFACE(INTERFACE_LINK_LIBRARIES) does not seem to work as
CMake may perform deduplication and rearrange the flags [1].

The proof of concept used `CMAKE_LINK_LIBRARY_USING_<FEATURE>` with the
WHOLE_ARCHIVE feature, which was introduced in CMake 3.24 to specify how
the library target should be linked. There are two issues with this.
First, this feature is only available from CMake 3.24 onwards, while our
minimum CMake version is set to 3.22. More importantly, all occurrences
of a library on the link line are wrapped.  For example, if a library
like `vfs` appears multiple times on the link line due to dependencies,
each occurrence will be wrapped with whole-archive, causing the linker
to complain about multiple symbol definitions. Therefore, even though
WHOLE_ARCHIVE is recommended for handling whole-archive linkage, it does
not seem suitable for our purposes. This was overlooked in the PoC
because only a simple testing component was used to check the
WHOLE_ARCHIVE behavior.

One way to address this issue is to adopt the same approach used in
cmakev1, which involves specifying the whole-archive flags when linking
component library targets to the final executable. In this case, CMake
retains the flags without any alteration, unlike when the flags are
specified in INTERFACE_LINK_LIBRARIES for the component interface
targets. While this approach is feasible, it would alter the current
logic, where we have a single library interface for the entire idf
library that can be linked to the executable. This change would also
complicate the direct use of the idf library, as it would no longer be
possible to simply link it to the executable. Instead, the executable
would need to correctly link the component libraries with the
whole-archive flags. We could encapsulate this process within the
idf_build_executable function, but projects that only use
idf_build_library would need to implement the same solution.

It appears possible to address this issue by using target_link_options
instead. This allows to specify exactly what should appear on the link
command line. One side effect of this approach is that the library
appears on the link command line multiple times: first when used with
target_link_options and second when used in target_link_libraries.
However, this does not seem to pose a problem. The flags specified with
target_link_options appear on the command line first, ensuring that the
whole-archive is prioritized, and the component archive libraries may be
repeated on the link line anyway due to dependencies. Essentially, the
final link command line is very similar to the one from cmakev1. We may
revisit this approach in the future, but for now, it seems to work as
expected.

[1] https://gitlab.kitware.com/cmake/cmake/-/issues/20078
[2] https://cmake.org/cmake/help/latest/variable/CMAKE_LINK_LIBRARY_USING_FEATURE.html
[3] https://discourse.cmake.org/t/automatically-wrapping-a-static-library-
    in-whole-archive-no-whole-archive-when-used-during-linking/5883

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata c2e54b259c fix(cmakev2/component): sanitize PATHS argument before calling __get_relative_paths
Currently, when the cmakev1 properties for INCLUDE_DIRS and
PRIV_INCLUDE_DIRS are constructed in the
__set_component_cmakev1_properties function, the return values from the
get_target_property function for INCLUDE_DIRECTORIES and
INTERFACE_INCLUDE_DIRECTORIES properties are not checked. If a component
target does not set e.g. INCLUDE_DIRECTORIES property,
get_target_property will return a value such as `include_dirs-NOTFOUND`.
This value is subsequently passed to __get_relative_paths in the PATHS
argument, causing the file(RELATIVE_PATH) call in __get_relative_paths
to fail with an error.

```
CMake Error at /home/fhrbata/work/esp-idf/tools/cmakev2/utilities.cmake:235 (file):
  file RELATIVE_PATH must be passed a full path to the file:
  include_dirs-NOTFOUND
```

Fix this by explicitly set the PATHS to an empty list before passing it
to the __get_relative_paths function if the property is not set.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata e56168dbb5 fix(test_build_system): disable tests related to outside component dependencies
The commit adb2d5deee ("feat(cmake): Produce warnings when component dependen..")
introduced additional checks for source files and include directories
used by a component that are located outside the component's directory.
If these files and directories belong to another component, a warning is
issued. This feature has not yet been implemented in cmakev2, so related
tests are temporary disabled.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 25d1ceb9c7 feat(cmakev2/component): add __set_component_cmakev1_properties function
In cmakev1, certain arguments provided to the idf_component_register
function are stored as component properties. These properties are used
to generate the project_description.json file, which other tools rely
on. Since the idf_component_register function is obsolete in cmakev2, we
need to recreate component properties such as INCLUDE_DIRS,
PRIV_INCLUDE_DIRS, REQUIRES, and PRIV_REQUIRES, which were previously
provided by the idf_component_register function in cmakev1.  To achieve
this, let's examine the component's real target cmake properties and
reconstruct them to maintain compatibility with cmakev1.

The real target cmake properties may include generator expressions,
which are ignored. This should be acceptable, as they were not addressed
in cmakev1 either, and handling them is likely not feasible.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 4e85b3f5a5 feat(cmakev2/utilities): add __list_difference function
Return the difference between two lists, meaning the elements that are
present in the first list but not in the second.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 6b2b630d90 feat(cmakev2/utilities): add __list_intersection function
Return the intersection of elements in the two lists.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 2e82aa7017 feat(cmakev2/utilities): add __remove_genex function
This helper function removes entries containing generator expressions
from the given list. The list is modified in place.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 579b591f36 feat(cmakev2/utilities): add __get_relative_paths function
This is a helper function that returns a list of paths relative to a
given base directory for a list of input paths.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 1360674f89 feat(cmakev2/build): preprocess linker scripts with the C preprocessor
When a linker script file with a .in extension is added using the
target_linker_script function, it is processed with the C preprocessor.
The linker scripts are preprocessed only once, even if they are used in
multiple libraries, because they are the same.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 2ee43966b7 feat(cmakev2/utilities): add __preprocess_linker_script function
Add a helper function to enable C preprocessing of linker script files.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata 6aa25ff65e feat(cmakev2/component): add COMPONENT_BUILD_DIR component property
During the initialization of a component in the __init_component
function, add the COMPONENT_BUILD_DIR property. This can be used to
store component-specific generated files, such as preprocessed linker
scripts.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:15 +01:00
Frantisek Hrbata ce5646b354 fix(esp_hal_i2c/cmake): fix the usage of the uninitialized variable
The `includes` list variable is used without initialization. Initialize
it explicitly.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata 041756d274 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-11-04 07:48:14 +01:00
Frantisek Hrbata 1afc554e6c feat(cmakev2/build): introduce component interface cache
The component can be referenced by multiple identifiers such as the
component name, which is derived from the component directory name,
component target, interface, or aliases. All component properties are
attached to the component interface target, which is also used for
declaring component dependencies. The cmakev2 build system has a
function called __get_component_interface, which is responsible for
identifying the component interface based on the given component
identifier. Since this function is called frequently, it needs to be
reasonably fast.

This introduces a new __idf_component_interface_cache INTERFACE target,
which serves as a mapping cache between component identifiers and the
component interface. The cache for each component is initialized in the
__init_component function, which introduces a component to the build
system. Currently, the component interface search is conducted by
examining the COMPONENTS_DISCOVERED and COMPONENT_INTERFACES lists
stored as build properties. Since the build system is aware of most
component identifiers, such as component name, target, and alias, during
component initialization, it can add mappings between component
identifiers and the component interface to a cache, which is built as
the components are initialized. This cache is used in the
__get_component_interface function instead of looking into the
COMPONENTS_DISCOVERED or COMPONENT_INTERFACES lists. This significantly
speeds up the component interface search and also makes the code much
simpler and more readable.

The component interface cache also completely replaces the existing
component name resolution, which was introduced because of the component
manager, and the cache used for resolved component names. This is
possible because all the necessary information is available during
component initialization when the component interface cache is
populated. The ambiguity of components is resolved based on component
source/priority.

Here is an example of the component interface mapping for the
espressif__led_strip component to the idf_espressif__led_strip interface
target. The component name, without the namespace, is referred to as the
short name. In this example, it is led_strip.

- espressif__led_strip -> idf_espressif__led_strip      # name(directory name)
- idf_espressif__led_strip -> idf_espressif__led_strip  # interface
- idf::espressif__led_strip -> idf_espressif__led_strip # alias
- _idf_espressif__led_strip -> idf_espressif__led_strip # real target
- led_strip -> idf_espressif__led_strip                 # short name

When another component with the same espressif__led_strip name is
initialized with a different priority, there is no need to change
anything in the cache, because the mapping stays the same.

The cache must be updated when two components share the same short name
but belong to different namespaces. This situation is likely uncommon.
For instance, consider espressif__led_strip and my__led_strip. If
my__led_strip has a higher priority, the cache is updated to reflect the
short name as follows:

- led_strip -> idf_my__led_strip

If both components have the same priority, the short name mapping for
led_strip is entirely removed. Conversely, if my__led_strip has a lower
priority, no short name mapping is added for it.

The short name is also added to the COMPONENT_SHORT_NAME property of the
component.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata aa6f4e076a feat(cmakev2/kconfig): add idf_create_confserver function
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>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata f382edf40d fix(cmakev2/kconfig): do not automatically generate the kconfig_menus.json file
Currently, when the initial sdkconfig is generated, the
kconfig_menus.json format is also created alongside other formats like
CMake, JSON, or C header. The kconfig_menus.json depends on the Kconfig
hierarchy and cannot be generated globally. It must be generated for
each executable to ensure that included and excluded components are
correctly positioned within the Kconfig menu hierarchy. Remove the
automatic generation of kconfig_menus.json.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata 1fa10aa26a fix(cmakev2/kconfig): remove --env-file argument from base kconfgen command
The current base kconfgen command is stored in the __BASE_KCONFGEN_CMD
build property, and it includes the --env-file option pointing to the
`build/config.env` file. The `build/config.env` file does not separate
component configuration files into included and excluded components,
because it is created before any executable is added and we need it for
the initial sdkconfig generation. The global `build/config.env` can be
used for every sdkconfig format (cmake, json, txt), but not for the
kconfig_menus.json format, because kconfig_menus.json relies on the
Kconfig layout and hierarchy. Let's allow specifying the --env-file for
each kconfgen invocation and remove it from the base kconfgen command.
This allows you to specify an --env-file for each executable, each with
its own config.env file.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata a2d05cb92d fix(cmakev2/kconfig): __run_kconfgen does not take any arguments
The __run_kconfgen function does not take any arguments. The output
formats and related files are stored in the __KCONFGEN_OUTPUTS_CMD build
property.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata 325c796ae7 feat(cmakev2/kconfig): add idf_create_save_defconfig function
This is basically a renamed version of __create_save_defconfig_target.
The creation of the save-defconfig target is done in
`idf_project_default()`.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata e117462137 feat(cmakev2/kconfig): add idf_create_menuconfig function
For a specified executable, create a menuconfig target using the name
provided in the TARGET option. The function generates a config.env file
specific to the executable, where Kconfig files for components linked to
the executable and Kconfig files for components not linked to it are
separated. This separation allows for a clear visual distinction between
the configuration of components that are linked and those that are not
linked to the executable within the menuconfig.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata b4197aabe6 feat(cmakev2/kconfig): add __create_executable_config_env_file function
Generate the config.env file for the specified executable. The
configuration file will be stored in the build directory, within a
directory named after the executable target name. The kconfigs*.in
files, which are generated by prepare_kconfig_files.py, will also be
stored in this directory.

This function primarily prepares the arguments for the
__create_config_env_file function based on the components linked to the
executable, ensuring that component Kconfig files are stored in the
appropriate kconfigs*.in files, depending on whether the component is
linked to the executable.

The directory where the generated files are stored is added to the
executable CONFIG_ENV_DIR property.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata dfc6bcb55f feat(cmakev2/kconfig): allow to specify Kconfig files for __create_config_env_file
The __create_config_env_file function generates a configuration file for
the prepare_kconfig_files.py script. Currently, it specifies the paths
for the kconfigs*.in files, which are generated by
prepare_kconfig_files.py, to be located in the build directory. The
kconfigs*.in files, along with the configuration file, must also be
generated for each executable, as each executable may have a
different set of linked components. Set the paths for the
kconfigs*.in files to be generated by the prepare_kconfig_files.py
script in the same directory as the configuration file.

Also allow explicit specification of which component configuration files
should be placed in different kconfigs*.in files. For sdkconfig
generation, it is not relevant whether a component's Kconfig file is
placed in the kconfigs.in or kconfigs_excluded.in file. This distinction
is only important for visually separating the configuration of included
and excluded components in the menuconfig. For the main sdkconfig, all
component Kconfig files are placed in the kconfigs.in file, and the
generated kconfigs*.in files are stored in the build directory. For
executables, the generated kconfigs*.in files will be stored in separate
directories for each executable.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata dc62a4c950 fix(cmakev2/kconfig): do not add excluded Kconfig files in the build properties
The excluded Kconfig files cannot be collected globally, they must be
collected per executable. The distinction between included and excluded
Kconfig files is relevant only for menuconfig, which is specific to each
executable, as each executable may have a different set of linked
components. For the global sdkconfig file and its CMake and JSON
variants, whether the Kconfig files are excluded or not is irrelevant.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata 6f8e59c505 fix(test_build_system): use block comment instead of return for cmakev2 test app
Commit 46b41dfec187 ("test(cmakev2): Enable CI tests for component manager ..")
introduced a temporary workaround for the cmakev2 testing
application by including the cmakev1 project.cmake file after the
return() statement. The issue is that some tests, such as
test_build_fail_on_build_time, append commands to the project's
CMakeLists.txt. These commands are placed after the newly added return()
statement, causing them to be ignored and resulting in test failures. To
resolve this, include the cmakev1 project.cmake within the cmake block
comment.

Fixes: 46b41dfec187 ("test(cmakev2): Enable CI tests for component manager ..")
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata ea746c2ef5 ci(cmakev2): enable test_build.py test for cmakev2
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata dce6fca6f4 feat(test_build_system): enable test_build.py to be executed using cmakev2
Three tests are disabled for cmakev2:
* test_build_dfu
* test_build_uf2
* test_build_loadable_elf

and one is modified:
* test_build_skdconfig_phy_init_data

the other 14 tests should pass.

The tests, test_build_dfu and test_build_uf2, are temporarily disabled
because cmakev2 currently does not include the dfu and uf2 targets.
These tests should be re-enabled once support is added to cmakev2.

The test_build_loadable_elf is disabled because the bootloader_support
component determines its requirements based on the sdkconfig values,
specifically the CONFIG_APP_BUILD_TYPE_RAM used in this test. When
CONFIG_APP_BUILD_TYPE_RAM is set, bootloader_support declares a
dependency on micro-ecc. This is wrong even in cmakev1 and should be
fixed.

The test_build_skdconfig_phy_init_data test requires the esp_phy
component but does not specify it in its requirements. It relies on the
cmakev1 behavior, where all components are included in the build by
default. This approach does not work for cmakev2. To resolve this, make
the dependency on esp_phy explicit, ensuring compatibility with both
versions.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata a8e8a0ad8e fix(cmakev2/kconfig): make warnings about misspelled Kconfig names consistent with cmakev1
Currently, the cmakev2 implementation of Kconfig name consistency has a
slightly different warning message compared to cmakev2, causing the test
`test_build.py::test_build_with_misspelled_kconfig` to fail.  Make the
warning messages consistent with cmakev1.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata 4156b85868 fix(test_build_system): rename Kconfig.projbuild to KConfig.projbuild
The test_build_with_misspelled_kconfig test expects a KConfig.projbuild
file in the main component. However, the file is correctly named
Kconfig.projbuild, which causes the test to fail for cmakev2.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata b663ebd1da fix(cmakev2/component): remove EXCLUDE_FROM_ALL when calling add_subdirectory
Currently, cmakev2 evaluates each component using add_subdirectory with
the EXCLUDE_FROM_ALL option. The intention was to exclude all components
from being built by default unless they are explicitly linked to an
executable based on dependencies. This approach aims to avoid building
components that are included but not actually linked to the executable.
However, this has the side effect of preventing components from adding
their custom targets to the "all" target, which is used, for example, by
esp_phy. Generally, we should not restrict components from adding
targets to "all". Since components are only included if explicitly
requested by default, removing the EXCLUDE_FROM_ALL option should be
acceptable.

The downside is that if IDF_INCLUDE_ALL_COMPONENTS is set and the user
runs `idf.py build`, all components will be built, even if they are not
linked to the executable.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata de26190732 fix(cmakev2/idf): target consistency check with sdkconfig
Currently, the check is based on the existence of sdkconfig, but there
may be situations where sdkconfig exists without containing
CONFIG_IDF_TARGET. Perform a target consistency check only if the target
is identified in the main sdkconfig file.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata d1a69f40da fix(cmakev2/utilities): fix typo in __get_sdkconfig_option description
The function name is __get_sdkconfig_option, not __get_config_option.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata a4f8ef8188 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-11-04 07:48:14 +01:00
Frantisek Hrbata 5c24972a01 feat(docs): add build system v2 documentation files
Add stump files for the build system v2 documentation with automatic API
generation from CMake files.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata bab96ce3d7 feat(docs): load esp_docs_cmakev2_extension
Load the esp_docs_cmakev2_extension to process documentation comments
from CMake files.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2025-11-04 07:48:14 +01:00
Frantisek Hrbata 4d5d27e3e5 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-11-04 07:48:14 +01:00
Frantisek Hrbata 5157690109 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-11-04 07:48:14 +01:00
Frantisek Hrbata 89c4a36c05 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-11-04 07:48:14 +01:00
Frantisek Hrbata 1fe1900ddf 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-11-04 07:48:14 +01:00