From f2c3fd3966687534ea34afc72e25190b9d0ca85e Mon Sep 17 00:00:00 2001 From: Frantisek Hrbata Date: Mon, 15 Jun 2026 14:29:37 +0200 Subject: [PATCH] feat(cmakev2): Export public API in the generated build system v2 reference Promote the build system v2 functions and macros used by the examples/build_system/cmakev2 examples to the generated API reference, document the component-scope and version variables, the public build properties, and the public component properties, and add cmakev2 build_property and component_property directives with dedicated Build Properties and Component Properties sections to the esp-docs extension. Signed-off-by: Frantisek Hrbata --- tools/cmakev2/build.cmake | 12 +- tools/cmakev2/component.cmake | 48 ++++++ tools/cmakev2/esp_docs_cmakev2_extension.py | 22 ++- tools/cmakev2/idf.cmake | 159 ++++++++++++++++---- tools/cmakev2/kconfig.cmake | 4 +- tools/cmakev2/project.cmake | 4 +- tools/cmakev2/utilities.cmake | 55 ++++--- 7 files changed, 238 insertions(+), 66 deletions(-) diff --git a/tools/cmakev2/build.cmake b/tools/cmakev2/build.cmake index ab6d71ed0de..7cbc3b536ef 100644 --- a/tools/cmakev2/build.cmake +++ b/tools/cmakev2/build.cmake @@ -288,7 +288,7 @@ function(__dump_library_properties libraries) endforeach() endfunction() -#[[ +#[[api .. cmakev2:function:: idf_build_library .. code-block:: cmake @@ -547,7 +547,7 @@ function(idf_build_library library) __component_validation_run_checks(LIBRARY "${library}") endfunction() -#[[ +#[[api .. cmakev2:function:: idf_build_executable .. code-block:: cmake @@ -747,7 +747,7 @@ function(__get_components_metadata) set(${ARG_OUTPUT} "${components_json}" PARENT_SCOPE) endfunction() -#[[ +#[[api .. cmakev2:function:: idf_build_generate_metadata .. code-block:: cmake @@ -906,7 +906,7 @@ function(idf_build_generate_metadata) endif() endfunction() -#[[ +#[[api .. cmakev2:function:: idf_build_binary .. code-block:: cmake @@ -1133,7 +1133,7 @@ function(idf_sign_binary binary) set_target_properties(${ARG_TARGET} PROPERTIES EXECUTABLE_TARGET ${executable}) endfunction() -#[[ +#[[api .. cmakev2:function:: idf_flash_binary .. code-block:: cmake @@ -1214,7 +1214,7 @@ function(idf_flash_binary binary) endif() endfunction() -#[[ +#[[api .. cmakev2:function:: idf_check_binary_size .. code-block:: cmake diff --git a/tools/cmakev2/component.cmake b/tools/cmakev2/component.cmake index cde6f103d8f..e7afd0f1c40 100644 --- a/tools/cmakev2/component.cmake +++ b/tools/cmakev2/component.cmake @@ -801,6 +801,54 @@ function(__set_component_cmakev1_properties component_name) idf_component_set_property(${component_name} PRIV_REQUIRES "${priv_requires}") endfunction() +#[[api +.. cmakev2:variable:: COMPONENT_TARGET + + The name of the library target that the component must create, for example + with ``add_library``. The build system sets this variable in the component's + scope when the component is evaluated, and links the created target into the + component's interface target so that other components can depend on it. + +.. cmakev2:variable:: COMPONENT_LIB + + The cmakev1-compatible alias of :cmakev2:ref:`COMPONENT_TARGET`. It holds the + same value and refers to the same library target. + +.. cmakev2:variable:: COMPONENT_NAME + + The name of the component being evaluated, which is the name of its directory. + +.. cmakev2:variable:: ESP_PLATFORM + + Set to ``1`` on any build driven by ``idf.py``, which passes + ``-DESP_PLATFORM=1`` to CMake as a cache variable. It is therefore defined + throughout the project, in both the top-level and component + ``CMakeLists.txt`` files, and is also added as a compile definition so that + source code can test it with ``#ifdef ESP_PLATFORM``. Use it to detect that + the build is driven by ESP-IDF, for example to guard ESP-IDF-specific code + in a project that can also build as a plain host application. +#]] + +#[[api +.. cmakev2:component_property:: WHOLE_ARCHIVE + + When set to a true value, every object file from the component's static + library is kept in the final binary (linked with ``--whole-archive`` on GNU + or ``-force_load`` on Apple). Useful for link-time registration, where object + files may have no directly referenced symbols. + +.. cmakev2:component_property:: LDFRAGMENTS + + List of linker fragment files contributed by the component. They are + processed by the linker script generator. See + :doc:`/api-guides/linker-script-generation`. + +.. cmakev2:component_property:: LINKER_SCRIPTS + + List of linker script files added to the link command (with ``-T``) for the + component. +#]] + #[[api .. cmakev2:function:: idf_component_include diff --git a/tools/cmakev2/esp_docs_cmakev2_extension.py b/tools/cmakev2/esp_docs_cmakev2_extension.py index 4fae4b6acd2..9d2255751b9 100644 --- a/tools/cmakev2/esp_docs_cmakev2_extension.py +++ b/tools/cmakev2/esp_docs_cmakev2_extension.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import re @@ -89,6 +89,14 @@ class CMakeV2MacroDirective(CMakeV2Description): cmakev2_type = 'macro' +class CMakeV2BuildPropertyDirective(CMakeV2Description): + cmakev2_type = 'build_property' + + +class CMakeV2ComponentPropertyDirective(CMakeV2Description): + cmakev2_type = 'component_property' + + class CMakeV2Domain(Domain): name = 'cmakev2' label = 'ESP-IDF build system v2' @@ -101,6 +109,8 @@ class CMakeV2Domain(Domain): 'variable': CMakeV2VariableDirective, 'function': CMakeV2FunctionDirective, 'macro': CMakeV2MacroDirective, + 'build_property': CMakeV2BuildPropertyDirective, + 'component_property': CMakeV2ComponentPropertyDirective, 'include': CMakeV2IncludeDirective, } @@ -136,9 +146,11 @@ def insert_cmakev2_comment_nodes(app: Sphinx, doctree: nodes.document) -> None: # Split nodes parsed in CMakeV2IncludeDirective into buckets based on their # type. - buckets: dict = {'function': [], 'macro': [], 'variable': []} + buckets: dict = {'function': [], 'macro': [], 'variable': [], 'build_property': [], 'component_property': []} for node in pending: - buckets[node['cmakev2-type']].append(node) + node_type = node.get('cmakev2-type') + if node_type in buckets: + buckets[node_type].append(node) # Sort functions, macros, and variables based on their names. buckets_sorted = {} @@ -155,6 +167,10 @@ def insert_cmakev2_comment_nodes(app: Sphinx, doctree: nodes.document) -> None: section.extend(buckets_sorted['function']) elif 'cmakev2-macros' in section['ids']: section.extend(buckets_sorted['macro']) + elif 'cmakev2-build-properties' in section['ids']: + section.extend(buckets_sorted['build_property']) + elif 'cmakev2-component-properties' in section['ids']: + section.extend(buckets_sorted['component_property']) def setup(app: Sphinx) -> dict: diff --git a/tools/cmakev2/idf.cmake b/tools/cmakev2/idf.cmake index 5f401f4fb16..b19a12137b7 100644 --- a/tools/cmakev2/idf.cmake +++ b/tools/cmakev2/idf.cmake @@ -58,6 +58,23 @@ include(GetGitRevisionDescription) # should probably be included there instead. include(ExternalProject) +#[[api +.. cmakev2:variable:: IDF_BUILD_V2 + + Set to ``y`` when the project is built with the CMake-based build system + v2. Use it to write component code that works with both v1 and v2, for + example ``if(IDF_BUILD_V2)``. It is also exported as an environment variable + and stored as a build property. + +.. cmakev2:variable:: IDF_BUILD_VER + + The major version number of the build system, ``2`` for v2. + +.. cmakev2:variable:: IDF_BUILD_VER_TAG + + The build system version tag, ``v2`` for v2. +#]] + #[[ __init_build_version() @@ -556,43 +573,125 @@ function(__init_idf_target_arch) endif() endfunction() -#[[ - The idf_build_properties interface target is exclusively used to store - information about global build properties and is not linked or used in any - other way. This is created very early so that all the initialization - functions can use it. +# The idf_build_properties interface target stores all global build +# properties. It is created very early so that the initialization functions +# can use it. Build properties are read and written with the +# idf_build_get_property and idf_build_set_property functions. - List of build properties +#[[api +.. cmakev2:build_property:: IDF_PATH - IDF_PATH - Path to esp-idf directory. + Absolute path to the ESP-IDF directory. - PREFIX - Prefix used for component target names. +.. cmakev2:build_property:: IDF_TARGET - COMPONENTS_DISCOVERED - List of component names identified by the build system. These - components are initialized and can have properties attached to them. - However, they are not necessarily included in the build through - add_subdirectory. + The target chip the project is built for, for example ``esp32``. - COMPONENT_INTERFACES - This is a list of component interface targets for the components in - ``COMPONENTS_DISCOVERED``. It is used when searching for a component, - such as by its name, to set or retrieve the component's properties. +.. cmakev2:build_property:: IDF_TARGET_ARCH - COMPONENTS_INCLUDED - This is a list of component names that were included in the build, - meaning their CMakeLists.txt files were processed with an - add_subdirectory call. Each component is evaluated exactly once, and - this list serves as a record of which components have already been - evaluated. Although each component can only be evaluated once, it can - be used in multiple idf_component_include calls. If a component is - requested to be included a second time, this list is checked. If the - component is already included, the idf_component_include function - simply returns, as there is nothing further to do except add a new - alias target if requested. + The architecture of the target, ``xtensa`` or ``riscv`` (empty for the Linux host build). + +.. cmakev2:build_property:: IDF_VER + + The ESP-IDF version string. + +.. cmakev2:build_property:: IDF_TOOLCHAIN + + The selected toolchain, ``gcc`` or ``clang``. + +.. cmakev2:build_property:: PROJECT_NAME + + The project name. Defaults to the name passed to CMake's ``project()`` command. + +.. cmakev2:build_property:: PROJECT_VER + + The project version. + +.. cmakev2:build_property:: PROJECT_DIR + + Absolute path to the project directory. + +.. cmakev2:build_property:: BUILD_DIR + + Absolute path to the build directory. + +.. cmakev2:build_property:: PYTHON + + Path to the Python interpreter used by the build. + +.. cmakev2:build_property:: COMPONENTS_DISCOVERED + + List of the names of all discovered components. + +.. cmakev2:build_property:: COMPONENT_INTERFACES + + List of the interface targets of all discovered components. + +.. cmakev2:build_property:: COMPONENTS_INCLUDED + + List of the components that have been included (evaluated) in the build. + +.. cmakev2:build_property:: SDKCONFIG + + Path to the project ``sdkconfig`` file. + +.. cmakev2:build_property:: SDKCONFIG_DEFAULTS + + List of ``sdkconfig.defaults`` files applied to the configuration. + +.. cmakev2:build_property:: SDKCONFIG_HEADER + + Path to the generated ``sdkconfig.h`` with C and C++ preprocessor defines. + +.. cmakev2:build_property:: SDKCONFIG_CMAKE + + Path to the generated ``sdkconfig.cmake`` with the ``CONFIG_*`` CMake variables. + +.. cmakev2:build_property:: SDKCONFIG_JSON + + Path to the generated ``sdkconfig.json``. + +.. cmakev2:build_property:: COMPILE_OPTIONS + + Compile options applied to all components, for all languages. + +.. cmakev2:build_property:: C_COMPILE_OPTIONS + + Compile options applied to all components, for C only. + +.. cmakev2:build_property:: CXX_COMPILE_OPTIONS + + Compile options applied to all components, for C++ only. + +.. cmakev2:build_property:: ASM_COMPILE_OPTIONS + + Compile options applied to all components, for assembly only. + +.. cmakev2:build_property:: COMPILE_DEFINITIONS + + Preprocessor definitions applied to all components. + +.. cmakev2:build_property:: LINK_OPTIONS + + Link options applied when linking the application. + +.. cmakev2:build_property:: INCLUDE_DIRECTORIES + + Include directories applied to all components. + +.. cmakev2:build_property:: LINKER_TYPE + + The linker family, ``GNU`` or ``Darwin``. + +.. cmakev2:build_property:: IDF_COMPONENT_MANAGER + + Whether the component manager is enabled (``1``) or disabled (``0``). + +.. cmakev2:build_property:: IDF_COMPONENT_OPTIONAL_REQUIRES_MODE + + How :cmakev2:ref:`idf_component_optional_requires` is resolved, ``IMMEDIATE`` or ``DEFERRED``. #]] + add_library(idf_build_properties INTERFACE) # The __idf_component_interface_cache target is used to maintain internal diff --git a/tools/cmakev2/kconfig.cmake b/tools/cmakev2/kconfig.cmake index a5b219bbced..eaf42079032 100644 --- a/tools/cmakev2/kconfig.cmake +++ b/tools/cmakev2/kconfig.cmake @@ -806,7 +806,7 @@ endfunction() # KCONFIG TARGETS FUNCTIONS # ============================================================================= -#[[ +#[[api .. cmakev2:function:: idf_create_menuconfig .. code-block:: cmake @@ -945,7 +945,7 @@ function(idf_create_menuconfig executable) endif() endfunction() -#[[ +#[[api .. cmakev2:function:: idf_create_confserver .. code-block:: cmake diff --git a/tools/cmakev2/project.cmake b/tools/cmakev2/project.cmake index 22189e962aa..69b105a9b55 100644 --- a/tools/cmakev2/project.cmake +++ b/tools/cmakev2/project.cmake @@ -540,7 +540,7 @@ function(__init_project_flash_targets) endif() endfunction() -#[[ +#[[api .. cmakev2:macro:: idf_project_init .. code-block:: cmake @@ -679,7 +679,7 @@ macro(idf_project_init) unset(project_initialized) endmacro() -#[[ +#[[api .. cmakev2:function:: idf_build_generate_flasher_args .. code-block:: cmake diff --git a/tools/cmakev2/utilities.cmake b/tools/cmakev2/utilities.cmake index 4e2a7c5fabf..5be6325b6ff 100644 --- a/tools/cmakev2/utilities.cmake +++ b/tools/cmakev2/utilities.cmake @@ -16,7 +16,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/../cmake/deduplicate_flags.cmake) # Using these functions has a side effect: the actual origin of the message # appears as the first line of the backtrace. -#[[ +#[[api .. cmakev2:function:: idf_die .. code-block:: cmake @@ -40,7 +40,7 @@ function(idf_die) message(FATAL_ERROR " IDF: ${joined}") endfunction() -#[[ +#[[api .. cmakev2:function:: idf_warn .. code-block:: cmake @@ -63,7 +63,7 @@ function(idf_warn) message(WARNING " IDF: ${joined}") endfunction() -#[[ +#[[api .. cmakev2:function:: idf_msg .. code-block:: cmake @@ -86,7 +86,7 @@ function(idf_msg) message(STATUS " IDF: ${joined}") endfunction() -#[[ +#[[api .. cmakev2:function:: idf_dbg .. code-block:: cmake @@ -634,18 +634,22 @@ function(__split) set(${ARG_OUTPUT} "${filtered_lines}" PARENT_SCOPE) endfunction() -#[[ - idf_build_get_compile_options() +#[[api +.. cmakev2:function:: idf_build_get_compile_options - *variable* + .. code-block:: cmake - Variable name in which the list of generator expressions for C, CXX, - and ASM compile options will be stored. + idf_build_get_compile_options() - Gather the compilation options from COMPILE_OPTIONS, C_COMPILE_OPTIONS, - CXX_COMPILE_OPTIONS, and ASM_COMPILE_OPTIONS build properties into a single - list using generator expressions. This list can then be used with the - target_compile_options call. + *variable[out]* + + Variable in which the list of compile option generator expressions is + stored. + + Gather the compile options from the ``COMPILE_OPTIONS``, + ``C_COMPILE_OPTIONS``, ``CXX_COMPILE_OPTIONS``, and ``ASM_COMPILE_OPTIONS`` + build properties into a single list of generator expressions, suitable for + passing to ``target_compile_options``. #]] function(idf_build_get_compile_options output) idf_build_get_property(compile_options COMPILE_OPTIONS GENERATOR_EXPRESSION) @@ -917,29 +921,34 @@ function(target_add_binary_data target embed_file embed_type) target_sources("${target}" PRIVATE "${embed_srcfile}") endfunction() -#[[ - add_prebuilt_library( - [REQUIRES ...]) - [PRIV_REQUIRES ...]) +#[[api +.. cmakev2:function:: add_prebuilt_library + + .. code-block:: cmake + + add_prebuilt_library( + [REQUIRES ...] + [PRIV_REQUIRES ...]) *target[in]* Target name for the imported library. - *library[in]* + *lib[in]* - Imported library path. + Path to the prebuilt static library. *REQUIRES[in,opt]* - Optional dependency on other components. + Components this library depends on publicly. *PRIV_REQUIRES[in,opt]* - Optional private dependency on other components. + Components this library depends on privately. - Add prebuilt library with support for adding dependencies on ESP-IDF - components. + Import a prebuilt static library as a CMake target, optionally linking it + against other ESP-IDF components. The resulting target can be linked into a + component or executable like any other library. #]] function(add_prebuilt_library target_name lib_path) cmake_parse_arguments(_ "" "" "REQUIRES;PRIV_REQUIRES" ${ARGN})