diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index ac57d66a3e9..b7b9b0ce8bc 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -149,6 +149,43 @@ If using an IDE with CMake, setting the ``PYTHON`` value as a CMake cache overri To manage the Python version more generally via the command line, check out the tools pyenv_ or virtualenv_. These let you change the default Python version. +.. _build-acceleration: + +Build Acceleration +------------------ + +ESP-IDF supports several tools to accelerate the build process. These tools work as compiler launchers that wrap the actual compiler invocation. + +CCache +^^^^^^ + +CCache_ is a compiler cache that speeds up recompilation by caching previous compilations. When enabled, if a compilation is repeated with the same source code and compiler flags, CCache returns the cached result instead of recompiling. + +See the :ref:`idf_py_global_options` section for more information about how to enable or disable it. + +Configdep Wrapper +^^^^^^^^^^^^^^^^^ + +The ``esp-idf-configdep`` tool post-processes compiler-generated dependency files to reduce unnecessary rebuilds caused by ``sdkconfig.h`` changes. + +Normally, every source file that includes ``sdkconfig.h`` would be rebuilt whenever any configuration option changes, because the compiler records ``sdkconfig.h`` as a direct dependency. The configdep tool edits the dependency files after the initial build so that source files no longer depend directly on ``sdkconfig.h``. Instead, they depend on a special file structure created by ``esp-idf-kconfig``: each configuration option has its own file, and when a given option is changed, only the corresponding file is touched. That way only the source files that actually use the changed option are rebuilt, not the entire project. + +Important: source files are not modified. They still contain ``#include `` and there is no need to alter anything in the source code for configdep to work. The tool operates purely on the generated dependency (``.d``) files. + +This is particularly useful when there are frequent changes of a small number of config options between rebuilds. Configdep is enabled by default. + +See the :ref:`idf_py_global_options` section for more information about how to enable or disable it. + +Chaining Acceleration Tools +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When multiple acceleration tools are enabled, they are chained together as compiler launchers. The chain is applied in a specific order: + +1. **esp-idf-configdep** (if enabled) - processes dependency files and optimizes rebuilds caused by ``sdkconfig.h`` changes +2. **ccache** (if enabled) - caches compilations + +Each tool in the chain wraps the next, ultimately invoking the actual compiler. This allows combining the benefits of multiple tools. However, combining multiple tools may not always result in optimal performance and it may be needed to experiment with different combinations of the acceleration tools to achieve the best performance for your project. + .. _example-project-structure: Example Project diff --git a/docs/en/api-guides/tools/idf-py.rst b/docs/en/api-guides/tools/idf-py.rst index ae804f7363a..4dda25fcf33 100644 --- a/docs/en/api-guides/tools/idf-py.rst +++ b/docs/en/api-guides/tools/idf-py.rst @@ -459,6 +459,8 @@ By default, the ``sdkconfig`` file is created in the project root directory. How For a complete example, see the :example_file:`Multiple Build Configurations Example `. +.. _idf_py_global_options: + Global Options ============== @@ -472,6 +474,8 @@ To list all available root level options, run ``idf.py --help``. To list options Note that some older versions of CCache_ may exhibit bugs on some platforms, so if files are not rebuilt as expected, try disabling CCache_ and rebuilding the project. To enable CCache_ by default, set the ``IDF_CCACHE_ENABLE`` environment variable to a non-zero value. +- ``--configdep`` or ``--no-configdep`` enables or disables the rebuild optimization using ``esp-idf-configdep``. This tool post-processes compiler-generated dependency files to reduce unnecessary rebuilds caused by ``sdkconfig.h`` changes. This is particularly useful when there are frequent changes of small number of config options between rebuilds. Enabled by default. To permanently enable or disable configdep, set the ``IDF_CONFIGDEP_ENABLE`` environment variable to ``1`` or ``0`` respectively. + - ``-v`` flag causes both ``idf.py`` and the build system to produce verbose build output. This can be useful for debugging build problems. - ``--cmake-warn-uninitialized`` (or ``-w``) causes CMake to print uninitialized variable warnings found in the project directory only. This only controls CMake variable warnings inside CMake itself, not other types of build warnings. This option can also be set permanently by setting the ``IDF_CMAKE_WARN_UNINITIALIZED`` environment variable to a non-zero value. - ``--no-hints`` flag disables hints on resolving errors and disable capturing output. diff --git a/docs/en/api-guides/tools/idf-tools-notes.inc b/docs/en/api-guides/tools/idf-tools-notes.inc index 37a2b631c22..36d5d27174d 100644 --- a/docs/en/api-guides/tools/idf-tools-notes.inc +++ b/docs/en/api-guides/tools/idf-tools-notes.inc @@ -89,6 +89,11 @@ Some ESP-specific instructions for running QEMU for Xtensa chips are here: https Some ESP-specific instructions for running QEMU for RISC-V chips are here: https://github.com/espressif/esp-toolchain-docs/blob/main/qemu/esp32c3/README.md +--- + +.. tool-esp-idf-configdep-notes + + --- .. tool-idf-python-notes diff --git a/docs/zh_CN/api-guides/tools/idf-tools-notes.inc b/docs/zh_CN/api-guides/tools/idf-tools-notes.inc index da663966cc4..1836a427caf 100644 --- a/docs/zh_CN/api-guides/tools/idf-tools-notes.inc +++ b/docs/zh_CN/api-guides/tools/idf-tools-notes.inc @@ -91,6 +91,11 @@ Some ESP-specific instructions for running QEMU for Xtensa chips are here: https Some ESP-specific instructions for running QEMU for RISC-V chips are here: https://github.com/espressif/esp-toolchain-docs/blob/main/qemu/esp32c3/README.md +--- + +.. tool-esp-idf-configdep-notes + + --- .. tool-idf-python-notes diff --git a/tools/cmake/kconfig.cmake b/tools/cmake/kconfig.cmake index 892e981f6a3..ea332478f0f 100644 --- a/tools/cmake/kconfig.cmake +++ b/tools/cmake/kconfig.cmake @@ -8,6 +8,9 @@ set(ESP_MENUCONFIG_MIN_KCONFIG_VERSION "3.1.0") # (fused menuconfig + deprecated-options post-processing in a single invocation). set(MENUCONFIG_INLINE_MIN_KCONFIG_VERSION "3.9.0") +# Minimum esp-idf-kconfig version required for cdep_tree / configdep (--output cdep_tree) +set(CONFIGDEP_MIN_KCONFIG_VERSION "3.6.0") + function(__kconfig_init) idf_build_get_property(idf_path IDF_PATH) @@ -239,6 +242,12 @@ function(__kconfig_generate_config sdkconfig sdkconfig_defaults) if(output_sdkconfig) list(APPEND kconfgen_output_options --output config ${sdkconfig}) endif() + # If configdep feature is enabled in ESP-IDF and esp-idf-kconfig version supports cdep_tree, + # add output option for configdep (requires esp-idf-kconfig >= CONFIGDEP_MIN_KCONFIG_VERSION) + __check_python_package_min_version(${python} esp-idf-kconfig "${CONFIGDEP_MIN_KCONFIG_VERSION}" CONFIGDEP_SUPPORTED) + if(CONFIGDEP_SUPPORTED AND CONFIGDEP_ENABLE) + list(APPEND kconfgen_output_options --output cdep_tree ${config_dir}) + endif() execute_process( COMMAND ${prepare_kconfig_files_command}) diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index 04dc1da4652..1868a336559 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -608,16 +608,52 @@ macro(project project_name) __target_set_toolchain() + # Build compiler launcher chain + set(compiler_launcher_chain "") + # Add custom wrapper if enabled (FIRST in chain) + if(CONFIGDEP_ENABLE) + # Check that esp-idf-kconfig >= CONFIGDEP_MIN_KCONFIG_VERSION is installed + # (required for cdep_tree / configdep support; version is defined in kconfig.cmake) + __check_python_package_min_version(${PYTHON} esp-idf-kconfig + "${CONFIGDEP_MIN_KCONFIG_VERSION}" _kconfig_version_ok) + if(_kconfig_version_ok) + find_program(CONFIGDEP_FOUND esp-idf-configdep) + if(CONFIGDEP_FOUND) + message(STATUS "esp-idf-configdep will be used for faster recompilation") + list(APPEND compiler_launcher_chain "esp-idf-configdep") + else() + message(WARNING "esp-idf-configdep enabled but not found. Re-run install and export scripts.") + endif() + else() + message(WARNING "esp-idf-configdep not supported by esp-idf-kconfig " + "(>= ${CONFIGDEP_MIN_KCONFIG_VERSION} required). Re-run install and export scripts.") + endif() + endif() + + # Add ccache if enabled (SECOND in chain) if(CCACHE_ENABLE) find_program(CCACHE_FOUND ccache) if(CCACHE_FOUND) message(STATUS "ccache will be used for faster recompilation") - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) + list(APPEND compiler_launcher_chain "ccache") else() message(WARNING "enabled ccache in build but ccache program not found") endif() endif() + # Apply the launcher chain - CMake automatically creates semicolon-separated list + if(compiler_launcher_chain) + set(CMAKE_C_COMPILER_LAUNCHER ${compiler_launcher_chain}) + set(CMAKE_CXX_COMPILER_LAUNCHER ${compiler_launcher_chain}) + set(CMAKE_ASM_COMPILER_LAUNCHER ${compiler_launcher_chain}) + + # Debug: show what the launcher chain looks like + string(REPLACE ";" " -> " launcher_display "${compiler_launcher_chain}") + message(STATUS "Compiler launcher chain: ${launcher_display}") + else() + message(STATUS "No compiler launcher chain will be used.") + endif() + # The actual call to project() __project(${project_name} C CXX ASM) __linux_build_set_lang_version() diff --git a/tools/idf_py_actions/core_ext.py b/tools/idf_py_actions/core_ext.py index f94f9c6db08..de88952af12 100644 --- a/tools/idf_py_actions/core_ext.py +++ b/tools/idf_py_actions/core_ext.py @@ -530,6 +530,13 @@ def action_extensions(base_actions: dict, project_path: str) -> Any: 'envvar': 'IDF_CCACHE_ENABLE', 'default': False, }, + { + 'names': ['--configdep/--no-configdep'], + 'help': 'Use configdep wrapper to optimize rebuild process. Enabled by default.', + 'is_flag': True, + 'envvar': 'IDF_CONFIGDEP_ENABLE', + 'default': True, + }, { 'names': ['-G', '--generator'], 'help': 'CMake generator.', diff --git a/tools/idf_py_actions/tools.py b/tools/idf_py_actions/tools.py index d9e4daceec2..0065e69c204 100644 --- a/tools/idf_py_actions/tools.py +++ b/tools/idf_py_actions/tools.py @@ -788,6 +788,7 @@ def ensure_build_directory( cache = _parse_cmakecache(cache_path) if os.path.exists(cache_path) else {} args.define_cache_entry.append(f'CCACHE_ENABLE={args.ccache}') + args.define_cache_entry.append(f'CONFIGDEP_ENABLE={args.configdep}') cache_cmdl = _parse_cmdl_cmakecache(args.define_cache_entry) diff --git a/tools/test_idf_tools/test_idf_tools.py b/tools/test_idf_tools/test_idf_tools.py index bce1276151b..f2a4e8f2920 100755 --- a/tools/test_idf_tools/test_idf_tools.py +++ b/tools/test_idf_tools/test_idf_tools.py @@ -65,6 +65,7 @@ NINJA = 'ninja' IDF_EXE = 'idf-exe' CCACHE = 'ccache' DFU_UTIL = 'dfu-util' +ESP_IDF_CONFIGDEP = 'esp-idf-configdep' def get_version_dict(): @@ -98,6 +99,7 @@ NINJA_VERSION = version_dict[NINJA] IDF_EXE_VERSION = version_dict[IDF_EXE] CCACHE_VERSION = version_dict[CCACHE] DFU_UTIL_VERSION = version_dict[DFU_UTIL] +ESP_IDF_CONFIGDEP_VERSION = version_dict[ESP_IDF_CONFIGDEP] # There are some complex search patterns to detect download snippets @@ -383,7 +385,7 @@ class TestUsageUnix(TestUsage): self.assertIn(f'* {CLANGD}:', output) self.assertIn(f'- {CLANGD_VERSION} (recommended)', output) - required_tools_installed = 8 + required_tools_installed = 9 output = self.run_idf_tools_with_action(['install']) self.assert_tool_installed(output, OPENOCD, OPENOCD_VERSION) self.assert_tool_installed(output, RISCV_ELF, RISCV_ELF_VERSION, RISCV_ELF_ARCHIVE_PATTERN) @@ -393,6 +395,7 @@ class TestUsageUnix(TestUsage): self.assert_tool_installed(output, RISCV_ESP_GDB, RISCV_ESP_GDB_VERSION) self.assert_tool_installed(output, ESP_ROM_ELFS, ESP_ROM_ELFS_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) @@ -406,6 +409,7 @@ class TestUsageUnix(TestUsage): RISCV_ESP_GDB_VERSION, ESP_ROM_ELFS_VERSION, CLANGD_VERSION, + ESP_IDF_CONFIGDEP_VERSION, ]: self.assertIn('version installed in tools directory: ' + tool_version, output) @@ -424,6 +428,11 @@ class TestUsageUnix(TestUsage): ) self.assertIn(f'{self.temp_tools_dir}/tools/esp-rom-elfs/{ESP_ROM_ELFS_VERSION}/', output) self.assertIn(f'{self.temp_tools_dir}/tools/esp-clangd/{CLANGD_VERSION}/esp-clangd/bin', output) + self.assertIn( + f'{self.temp_tools_dir}/tools/{ESP_IDF_CONFIGDEP}/{ESP_IDF_CONFIGDEP_VERSION}/' + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}/bin', + output, + ) output = self.run_idf_tools_with_action(['list', '--outdated']) self.assertEqual('', output) @@ -451,7 +460,7 @@ class TestUsageUnix(TestUsage): self.assertIn((f'{XTENSA_ELF}: version {XTENSA_ELF_VERSION} is outdated by {new_version}'), output) def test_tools_for_esp32(self): - required_tools_installed = 6 + required_tools_installed = 7 output = self.run_idf_tools_with_action(['install', '--targets=esp32']) self.assert_tool_installed(output, XTENSA_ELF, XTENSA_ELF_VERSION, XTENSA_ELF_ARCHIVE_PATTERN) self.assert_tool_installed(output, OPENOCD, OPENOCD_VERSION) @@ -461,6 +470,7 @@ class TestUsageUnix(TestUsage): self.assert_tool_not_installed(output, RISCV_ESP_GDB, RISCV_ESP_GDB_VERSION) self.assert_tool_installed(output, ESP_ROM_ELFS, ESP_ROM_ELFS_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) @@ -472,6 +482,7 @@ class TestUsageUnix(TestUsage): XTENSA_ESP_GDB_VERSION, ESP_ROM_ELFS_VERSION, CLANGD_VERSION, + ESP_IDF_CONFIGDEP_VERSION, ]: self.assertIn('version installed in tools directory: ' + tool_version, output) @@ -490,9 +501,14 @@ class TestUsageUnix(TestUsage): ) self.assertIn(f'{self.temp_tools_dir}/tools/esp-rom-elfs/{ESP_ROM_ELFS_VERSION}/', output) self.assertIn(f'{self.temp_tools_dir}/tools/esp-clangd/{CLANGD_VERSION}/esp-clangd/bin', output) + self.assertIn( + f'{self.temp_tools_dir}/tools/{ESP_IDF_CONFIGDEP}/{ESP_IDF_CONFIGDEP_VERSION}/' + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}/bin', + output, + ) def test_tools_for_esp32c3(self): - required_tools_installed = 5 + required_tools_installed = 6 output = self.run_idf_tools_with_action(['install', '--targets=esp32c3']) self.assert_tool_installed(output, OPENOCD, OPENOCD_VERSION) self.assert_tool_installed(output, RISCV_ELF, RISCV_ELF_VERSION, RISCV_ELF_ARCHIVE_PATTERN) @@ -502,11 +518,18 @@ class TestUsageUnix(TestUsage): self.assert_tool_not_installed(output, XTENSA_ESP_GDB, XTENSA_ESP_GDB_VERSION) self.assert_tool_installed(output, ESP_ROM_ELFS, ESP_ROM_ELFS_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) output = self.run_idf_tools_with_action(['check']) - for tool_version in [OPENOCD_VERSION, RISCV_ELF_VERSION, RISCV_ESP_GDB_VERSION, ESP_ROM_ELFS_VERSION]: + for tool_version in [ + OPENOCD_VERSION, + RISCV_ELF_VERSION, + RISCV_ESP_GDB_VERSION, + ESP_ROM_ELFS_VERSION, + ESP_IDF_CONFIGDEP_VERSION, + ]: self.assertIn('version installed in tools directory: ' + tool_version, output) output = self.run_idf_tools_with_action(['export']) @@ -520,9 +543,14 @@ class TestUsageUnix(TestUsage): ) self.assertIn(f'{self.temp_tools_dir}/tools/esp-rom-elfs/{ESP_ROM_ELFS_VERSION}/', output) self.assertIn(f'{self.temp_tools_dir}/tools/esp-clangd/{CLANGD_VERSION}/esp-clangd/bin', output) + self.assertIn( + f'{self.temp_tools_dir}/tools/{ESP_IDF_CONFIGDEP}/{ESP_IDF_CONFIGDEP_VERSION}/' + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}/bin', + output, + ) def test_tools_for_esp32s2(self): - required_tools_installed = 7 + required_tools_installed = 8 output = self.run_idf_tools_with_action(['install', '--targets=esp32s2']) self.assert_tool_installed(output, XTENSA_ELF, XTENSA_ELF_VERSION, XTENSA_ELF_ARCHIVE_PATTERN) self.assert_tool_installed(output, OPENOCD, OPENOCD_VERSION) @@ -532,11 +560,18 @@ class TestUsageUnix(TestUsage): self.assert_tool_installed(output, ESP_ROM_ELFS, ESP_ROM_ELFS_VERSION) self.assert_tool_not_installed(output, RISCV_ESP_GDB, RISCV_ESP_GDB_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) output = self.run_idf_tools_with_action(['check']) - for tool_version in [OPENOCD_VERSION, XTENSA_ELF_VERSION, XTENSA_ESP_GDB_VERSION, ESP_ROM_ELFS_VERSION]: + for tool_version in [ + OPENOCD_VERSION, + XTENSA_ELF_VERSION, + XTENSA_ESP_GDB_VERSION, + ESP_ROM_ELFS_VERSION, + ESP_IDF_CONFIGDEP_VERSION, + ]: self.assertIn('version installed in tools directory: ' + tool_version, output) output = self.run_idf_tools_with_action(['export']) @@ -554,9 +589,14 @@ class TestUsageUnix(TestUsage): ) self.assertIn(f'{self.temp_tools_dir}/tools/esp-rom-elfs/{ESP_ROM_ELFS_VERSION}/', output) self.assertIn(f'{self.temp_tools_dir}/tools/esp-clangd/{CLANGD_VERSION}/esp-clangd/bin', output) + self.assertIn( + f'{self.temp_tools_dir}/tools/{ESP_IDF_CONFIGDEP}/{ESP_IDF_CONFIGDEP_VERSION}/' + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}/bin', + output, + ) def test_tools_for_esp32s3(self): - required_tools_installed = 7 + required_tools_installed = 8 output = self.run_idf_tools_with_action(['install', '--targets=esp32s3']) self.assert_tool_installed(output, XTENSA_ELF, XTENSA_ELF_VERSION, XTENSA_ELF_ARCHIVE_PATTERN) self.assert_tool_installed(output, OPENOCD, OPENOCD_VERSION) @@ -566,6 +606,7 @@ class TestUsageUnix(TestUsage): self.assert_tool_installed(output, ESP_ROM_ELFS, ESP_ROM_ELFS_VERSION) self.assert_tool_not_installed(output, RISCV_ESP_GDB, RISCV_ESP_GDB_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) @@ -577,6 +618,7 @@ class TestUsageUnix(TestUsage): RISCV_ESP_GDB_VERSION, ESP_ROM_ELFS_VERSION, CLANGD_VERSION, + ESP_IDF_CONFIGDEP_VERSION, ]: self.assertIn('version installed in tools directory: ' + tool_version, output) @@ -595,9 +637,14 @@ class TestUsageUnix(TestUsage): ) self.assertIn(f'{self.temp_tools_dir}/tools/esp-rom-elfs/{ESP_ROM_ELFS_VERSION}/', output) self.assertIn(f'{self.temp_tools_dir}/tools/esp-clangd/{CLANGD_VERSION}/esp-clangd/bin', output) + self.assertIn( + f'{self.temp_tools_dir}/tools/{ESP_IDF_CONFIGDEP}/{ESP_IDF_CONFIGDEP_VERSION}/' + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}/bin', + output, + ) def test_tools_for_esp32p4(self): - required_tools_installed = 5 + required_tools_installed = 6 output = self.run_idf_tools_with_action(['install', '--targets=esp32p4']) self.assert_tool_installed(output, OPENOCD, OPENOCD_VERSION) self.assert_tool_installed(output, RISCV_ELF, RISCV_ELF_VERSION, RISCV_ELF_ARCHIVE_PATTERN) @@ -607,10 +654,17 @@ class TestUsageUnix(TestUsage): self.assert_tool_not_installed(output, ESP32ULP, ESP32ULP_VERSION) self.assert_tool_not_installed(output, XTENSA_ESP_GDB, XTENSA_ESP_GDB_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertEqual(required_tools_installed, output.count('Done')) output = self.run_idf_tools_with_action(['check']) - for tool_version in [OPENOCD_VERSION, RISCV_ELF_VERSION, ESP_ROM_ELFS_VERSION, RISCV_ESP_GDB_VERSION]: + for tool_version in [ + OPENOCD_VERSION, + RISCV_ELF_VERSION, + ESP_ROM_ELFS_VERSION, + RISCV_ESP_GDB_VERSION, + ESP_IDF_CONFIGDEP_VERSION, + ]: self.assertIn(f'version installed in tools directory: {tool_version}', output) output = self.run_idf_tools_with_action(['export']) @@ -623,6 +677,17 @@ class TestUsageUnix(TestUsage): os.path.join(self.temp_tools_dir, 'tools', RISCV_ESP_GDB, RISCV_ESP_GDB_VERSION, RISCV_ESP_GDB, 'bin'), output, ) + self.assertIn( + os.path.join( + self.temp_tools_dir, + 'tools', + ESP_IDF_CONFIGDEP, + ESP_IDF_CONFIGDEP_VERSION, + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}', + 'bin', + ), + output, + ) self.assertNotIn( os.path.join(self.temp_tools_dir, 'tools', ESP32ULP, ESP32ULP_VERSION, ESP32ULP, 'bin'), output ) @@ -637,7 +702,7 @@ class TestUsageUnix(TestUsage): # a different test for qemu because of "on_request" def test_tools_for_qemu_with_required(self): - required_tools_installed = 10 + required_tools_installed = 11 output = self.run_idf_tools_with_action(['install', 'required', 'qemu-xtensa', 'qemu-riscv32']) self.assert_tool_installed(output, OPENOCD, OPENOCD_VERSION) self.assert_tool_installed(output, RISCV_ELF, RISCV_ELF_VERSION, RISCV_ELF_ARCHIVE_PATTERN) @@ -646,6 +711,7 @@ class TestUsageUnix(TestUsage): self.assert_tool_installed(output, XTENSA_ESP_GDB, XTENSA_ESP_GDB_VERSION) self.assert_tool_installed(output, RISCV_ESP_GDB, RISCV_ESP_GDB_VERSION) self.assert_tool_installed(output, ESP_ROM_ELFS, ESP_ROM_ELFS_VERSION) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assert_tool_installed(output, QEMU_RISCV, QEMU_RISCV_VERSION) self.assert_tool_installed(output, QEMU_XTENSA, QEMU_XTENSA_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) @@ -675,7 +741,8 @@ class TestUsageWin(TestUsage): self.assertIn(f'- {XTENSA_ELF_VERSION} (recommended)', output) self.assertIn(f'* {CLANGD}:', output) self.assertIn(f'- {CLANGD_VERSION} (recommended)', output) - required_tools_installed = 12 + + required_tools_installed = 13 output = self.run_idf_tools_with_action(['install']) self.assert_tool_installed(output, OPENOCD, OPENOCD_VERSION) self.assert_tool_installed(output, RISCV_ELF, RISCV_ELF_VERSION, RISCV_ELF_ARCHIVE_PATTERN) @@ -690,6 +757,7 @@ class TestUsageWin(TestUsage): self.assert_tool_installed(output, CCACHE, CCACHE_VERSION) self.assert_tool_installed(output, DFU_UTIL, DFU_UTIL_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) @@ -708,6 +776,7 @@ class TestUsageWin(TestUsage): CCACHE_VERSION, DFU_UTIL_VERSION, CLANGD_VERSION, + ESP_IDF_CONFIGDEP_VERSION, ]: self.assertIn('version installed in tools directory: ' + tool_version, output) @@ -749,6 +818,17 @@ class TestUsageWin(TestUsage): os.path.join(self.temp_tools_dir, 'tools', DFU_UTIL, DFU_UTIL_VERSION, 'dfu-util-0.11-win64'), output ) self.assertIn(os.path.join(self.temp_tools_dir, 'tools', CLANGD, CLANGD_VERSION, CLANGD, 'bin'), output) + self.assertIn( + os.path.join( + self.temp_tools_dir, + 'tools', + ESP_IDF_CONFIGDEP, + ESP_IDF_CONFIGDEP_VERSION, + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}', + 'bin', + ), + output, + ) output = self.run_idf_tools_with_action(['list', '--outdated']) self.assertEqual('', output) @@ -791,6 +871,7 @@ class TestUsageWin(TestUsage): self.assert_tool_installed(output, CCACHE, CCACHE_VERSION) self.assert_tool_not_installed(output, DFU_UTIL, DFU_UTIL_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) @@ -806,6 +887,7 @@ class TestUsageWin(TestUsage): IDF_EXE_VERSION, CCACHE_VERSION, CLANGD_VERSION, + ESP_IDF_CONFIGDEP_VERSION, ]: self.assertIn('version installed in tools directory: ' + tool_version, output) self.assertNotIn('version installed in tools directory: ' + DFU_UTIL_VERSION, output) @@ -856,6 +938,17 @@ class TestUsageWin(TestUsage): os.path.join(self.temp_tools_dir, 'tools', DFU_UTIL, DFU_UTIL_VERSION, 'dfu-util-0.11-win64'), output ) self.assertNotIn(os.path.join(self.temp_tools_dir, 'tools', CLANGD, CLANGD_VERSION, CLANGD, 'bin'), output) + self.assertIn( + os.path.join( + self.temp_tools_dir, + 'tools', + ESP_IDF_CONFIGDEP, + ESP_IDF_CONFIGDEP_VERSION, + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}', + 'bin', + ), + output, + ) def test_tools_for_esp32c3_win(self): required_tools_installed = 9 @@ -873,6 +966,7 @@ class TestUsageWin(TestUsage): self.assert_tool_installed(output, CCACHE, CCACHE_VERSION) self.assert_tool_not_installed(output, DFU_UTIL, DFU_UTIL_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) @@ -887,6 +981,7 @@ class TestUsageWin(TestUsage): IDF_EXE_VERSION, CCACHE_VERSION, CLANGD_VERSION, + ESP_IDF_CONFIGDEP_VERSION, ]: self.assertIn('version installed in tools directory: ' + tool_version, output) self.assertNotIn('version installed in tools directory: ' + DFU_UTIL_VERSION, output) @@ -931,6 +1026,17 @@ class TestUsageWin(TestUsage): os.path.join(self.temp_tools_dir, 'tools', DFU_UTIL, DFU_UTIL_VERSION, 'dfu-util-0.11-win64'), output ) self.assertNotIn(os.path.join(self.temp_tools_dir, 'tools', CLANGD, CLANGD_VERSION, CLANGD, 'bin'), output) + self.assertIn( + os.path.join( + self.temp_tools_dir, + 'tools', + ESP_IDF_CONFIGDEP, + ESP_IDF_CONFIGDEP_VERSION, + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}', + 'bin', + ), + output, + ) def test_tools_for_esp32s2_win(self): required_tools_installed = 12 @@ -948,6 +1054,7 @@ class TestUsageWin(TestUsage): self.assert_tool_installed(output, CCACHE, CCACHE_VERSION) self.assert_tool_installed(output, DFU_UTIL, DFU_UTIL_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) @@ -963,6 +1070,7 @@ class TestUsageWin(TestUsage): IDF_EXE_VERSION, CCACHE_VERSION, CLANGD_VERSION, + ESP_IDF_CONFIGDEP_VERSION, ]: self.assertIn('version installed in tools directory: ' + tool_version, output) @@ -1012,6 +1120,17 @@ class TestUsageWin(TestUsage): os.path.join(self.temp_tools_dir, 'tools', DFU_UTIL, DFU_UTIL_VERSION, 'dfu-util-0.11-win64'), output ) self.assertIn(os.path.join(self.temp_tools_dir, 'tools', CLANGD, CLANGD_VERSION, CLANGD, 'bin'), output) + self.assertIn( + os.path.join( + self.temp_tools_dir, + 'tools', + ESP_IDF_CONFIGDEP, + ESP_IDF_CONFIGDEP_VERSION, + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}', + 'bin', + ), + output, + ) def test_tools_for_esp32s3_win(self): required_tools_installed = 12 @@ -1030,6 +1149,7 @@ class TestUsageWin(TestUsage): self.assert_tool_installed(output, CCACHE, CCACHE_VERSION) self.assert_tool_installed(output, DFU_UTIL, DFU_UTIL_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) @@ -1046,6 +1166,7 @@ class TestUsageWin(TestUsage): IDF_EXE_VERSION, CCACHE_VERSION, CLANGD_VERSION, + ESP_IDF_CONFIGDEP_VERSION, ]: self.assertIn('version installed in tools directory: ' + tool_version, output) @@ -1095,6 +1216,17 @@ class TestUsageWin(TestUsage): os.path.join(self.temp_tools_dir, 'tools', DFU_UTIL, DFU_UTIL_VERSION, 'dfu-util-0.11-win64'), output ) self.assertIn(os.path.join(self.temp_tools_dir, 'tools', CLANGD, CLANGD_VERSION, CLANGD, 'bin'), output) + self.assertIn( + os.path.join( + self.temp_tools_dir, + 'tools', + ESP_IDF_CONFIGDEP, + ESP_IDF_CONFIGDEP_VERSION, + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}', + 'bin', + ), + output, + ) def test_tools_for_esp32p4_win(self): required_tools_installed = 9 @@ -1112,6 +1244,7 @@ class TestUsageWin(TestUsage): self.assert_tool_not_installed(output, XTENSA_ESP_GDB, XTENSA_ESP_GDB_VERSION) self.assert_tool_not_installed(output, DFU_UTIL, DFU_UTIL_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertEqual(required_tools_installed, output.count('Done')) output = self.run_idf_tools_with_action(['check']) @@ -1125,6 +1258,7 @@ class TestUsageWin(TestUsage): IDF_EXE_VERSION, CCACHE_VERSION, CLANGD_VERSION, + ESP_IDF_CONFIGDEP_VERSION, ]: self.assertIn(f'version installed in tools directory: {tool_version}', output) @@ -1144,6 +1278,17 @@ class TestUsageWin(TestUsage): self.assertIn( os.path.join(self.temp_tools_dir, 'tools', CCACHE, CCACHE_VERSION, 'ccache-4.12.1-windows-x86_64'), output ) + self.assertIn( + os.path.join( + self.temp_tools_dir, + 'tools', + ESP_IDF_CONFIGDEP, + ESP_IDF_CONFIGDEP_VERSION, + f'{ESP_IDF_CONFIGDEP}-{ESP_IDF_CONFIGDEP_VERSION}', + 'bin', + ), + output, + ) self.assertNotIn( os.path.join(self.temp_tools_dir, 'tools', XTENSA_ELF, XTENSA_ELF_VERSION, XTENSA_ELF, 'bin'), output ) @@ -1178,6 +1323,7 @@ class TestUsageWin(TestUsage): self.assert_tool_installed(output, CCACHE, CCACHE_VERSION) self.assert_tool_installed(output, DFU_UTIL, DFU_UTIL_VERSION) self.assert_tool_installed(output, CLANGD, CLANGD_VERSION, CLANGD_ARCHIVE) + self.assert_tool_installed(output, ESP_IDF_CONFIGDEP, ESP_IDF_CONFIGDEP_VERSION) self.assertIn('Destination: {}'.format(os.path.join(self.temp_tools_dir, 'dist')), output) self.assertEqual(required_tools_installed, output.count('Done')) diff --git a/tools/tools.json b/tools/tools.json index c113028c43a..578d26b835c 100644 --- a/tools/tools.json +++ b/tools/tools.json @@ -1150,6 +1150,79 @@ } } ] + }, + { + "description": "ESP-IDF configuration dependency tool", + "export_paths": [ + [ + "esp-idf-configdep-0.2.2", + "bin" + ] + ], + "export_vars": {}, + "info_url": "https://github.com/espressif/esp-idf-configdep", + "install": "always", + "license": "Apache-2.0", + "name": "esp-idf-configdep", + "supported_targets": [ + "all" + ], + "version_cmd": [ + "esp-idf-configdep", + "--version" + ], + "version_regex": "version: ([0-9.]+)", + "versions": [ + { + "linux-amd64": { + "sha256": "999aa895c25d5c7edb6823884d3017f146b133f7ae2c580fffe4c989d7ce8c36", + "size": 28505, + "url": "https://github.com/espressif/esp-idf-configdep/releases/download/v0.2.2/esp-idf-configdep-0.2.2-linux-x86_64.tar.gz" + }, + "linux-arm64": { + "sha256": "0ea8f5e0de463ecfa3354a27b32ba34c4b999570e92127952fe7363f034ab7e9", + "size": 59608, + "url": "https://github.com/espressif/esp-idf-configdep/releases/download/v0.2.2/esp-idf-configdep-0.2.2-linux-arm64.tar.gz" + }, + "linux-armel": { + "sha256": "0e1663a6f9d8c030f11feb214aab0ffc3b9f6029ebc7ce10cad974db13667632", + "size": 36797, + "url": "https://github.com/espressif/esp-idf-configdep/releases/download/v0.2.2/esp-idf-configdep-0.2.2-linux-armel.tar.gz" + }, + "linux-armhf": { + "sha256": "98759c0a16e56ec96cc72f2d6b60d2f548194cfcc2adde11cd65c694241912b6", + "size": 34310, + "url": "https://github.com/espressif/esp-idf-configdep/releases/download/v0.2.2/esp-idf-configdep-0.2.2-linux-armhf.tar.gz" + }, + "linux-i686": { + "sha256": "e337582b1570ac90fcfde0b724e41d62b01581ec0a755c97ac38024c5def55ac", + "size": 32114, + "url": "https://github.com/espressif/esp-idf-configdep/releases/download/v0.2.2/esp-idf-configdep-0.2.2-linux-x86.tar.gz" + }, + "macos": { + "sha256": "8e7ad2fd91214219c276c6b371f0cd3e315f22055554d60856e88d84eb6422e9", + "size": 12755, + "url": "https://github.com/espressif/esp-idf-configdep/releases/download/v0.2.2/esp-idf-configdep-0.2.2-macos-x86_64.tar.gz" + }, + "macos-arm64": { + "sha256": "458fa0e3193184ca6360bf35058c63e763545f0ef6cb0b659b01985a5dfafdbf", + "size": 13023, + "url": "https://github.com/espressif/esp-idf-configdep/releases/download/v0.2.2/esp-idf-configdep-0.2.2-macos-arm64.tar.gz" + }, + "name": "0.2.2", + "status": "recommended", + "win32": { + "sha256": "6bec5711daa5196df8ec3fa2d3c2c79623e7dc6cb5e0b6cede03ef49b71ac6ac", + "size": 114156, + "url": "https://github.com/espressif/esp-idf-configdep/releases/download/v0.2.2/esp-idf-configdep-0.2.2-win-x86.zip" + }, + "win64": { + "sha256": "1827c449c9294036f94fa82f5da65f10be1edbc2de6920ce9837cbee1393cac8", + "size": 117734, + "url": "https://github.com/espressif/esp-idf-configdep/releases/download/v0.2.2/esp-idf-configdep-0.2.2-win-x86_64.zip" + } + } + ] } ], "version": 3