Validate linked RISC-V executables when
CONFIG_COMPILER_ENABLE_RISCV_ZCMP is enabled on affected chips.
Disassemble each function and reject mstatus.MIE clears that lack an
earlier mintthresh write of 0xff.
Handle csrrci, csrrw, and register-mask csrrc patterns while ignoring
csrrs. Add build-only coverage for valid and invalid sequences with
CMake v1 and v2.
Stop the hardware stack guard before switching stacks during restart,
and keep ZCMP disabled for TEE test apps that still require the
workaround.
Migrate idf.py and its actions to the shared esp-pylib library:
- add esp-pylib (and esp-pylib[ide]) to the core/ide requirements
- base FatalError on esp_pylib.errors.FatalError, keeping the idf.py ctx cleanup
- replace the local raw-ANSI helpers (red_print/yellow_print/print_warning/
color_print) with esp_pylib.logger.log (warn/err/note/hint) across the
idf.py actions
- install esp_pylib exception reporting at the idf.py entry point and silence
the logger during shell completion
- update affected tests for the new prefixes/line wrapping
- add normalize_output() helper and unify terminal env in conftest to handle
Rich line-wrapping in CI assertions
Co-authored-by: Cursor <cursoragent@cursor.com>
Wire esp_blockdev, comp_a, and comp_b into the test app dependency graph
so ioctl def files are registered and the POST_BUILD overlap checker runs.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Harden prefix_map.cmake for paths with spaces on Windows
- ldgen: fragments-list-file, list normalization, CMake integration (tools/cmake + cmakev2)
- CI exclude list for check_tools; test_spaces bundle tweak
Made-with: Cursor
Add build-level tests verifying configdep selective rebuild behavior:
- test_configdep.py: selective rebuild (only affected .obj rebuilt) and
ELF string verification after Kconfig toggle
- test_rebuild_configdep.py: full rebuild graph tests with configdep enabled,
including the two-build "settle" pattern for .cdep stub timestamps
Place the configdep test app in tools/test_build_system/configdep_test_app/
alongside the build system test infrastructure. Split configdep-specific
rebuild coverage from pure CMake/Ninja rebuild tests (test_rebuild.py runs
with configdep disabled via a module-local idf_py fixture).
Any idf.py invocation could hang indefinitely with no output while
spawning an unbounded chain of "idf.py --version" subprocesses,
eventually exhausting system memory.
During init_cli(), idf.py parses the project's dependencies.lock to
vet trusted component-provided idf_ext.py extensions. If the lock
contains a component whose manifest has an "if: idf_version" clause,
evaluating it calls idf-component-manager's _get_idf_version(). Outside
a CMake build the IDF_VERSION environment variable is not set, so that
function falls back to running "idf.py --version" as a subprocess,
which re-enters init_cli() and recurses without bound.
During a normal CMake build the component manager runs as a subprocess
that already has IDF_VERSION in its environment (see build/config.env),
so the fallback is never reached. The recursion happens only because
idf.py runs component-manager code in-process during its own CLI
startup, outside that context.
Seed IDF_VERSION into os.environ early in init_cli(), before any
dependencies.lock parsing, using the subprocess-free
idf_version_from_cmake() helper. This gives in-process component-manager
code the same IDF_VERSION a CMake build would provide.
When a component's manifest declared a managed dep `<ns>/<name>` and the
project had a local `components/<name>` shadowing it, configure failed
with `IDF: Failed to resolve component '<ns>__<name>'`.
cmakev1 does a project-wide injection so the manager's _choose_component
sees every component name in known_components and rewrites the
namespaced dep to its locally-shadowing short name. cmakev2 invokes the
manager per component with a single-component requirements file, so
known_components has only one entry and the rewrite cannot fire --
`<ns>__<name>` is written verbatim into MANAGED_REQUIRES and the
force-include at component.cmake:995 aborts.
Seed the per-component requirements file with one __COMPONENT_SOURCE
entry per discovered component so handle_project_requirements() builds
the same known_components list cmakev1 produces. The seeded entries are
inert on the cmake side -- the __component_set_property shim ignores
__COMPONENT_SOURCE -- they exist purely to feed the manager's rewrite.
Add a regression test in tools/test_build_system/buildv2/test_component.py.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Two tests added in commit c21d05e612 (MR !46354 "Added cmake target
listing in help") fail under pytest_buildv2_system /
pytest_buildv2_system_win:
* test_idf_py_help_after_configure_with_no_custom_targets_has_no_section
* test_idf_py_help_lists_cmake_custom_targets_after_configure
The tests assert that internal phony build targets do not appear
under "CMake Custom Targets" in idf.py --help. Filtering is driven
by tools/idf_py_actions/help_custom_targets_skip.py, whose exact-name
allowlist and shape policy were calibrated against cmakev1 target
names. cmakev1 either hard-codes the names ("app_check_size") or
uses a prefix already covered by HELP_PHONY_NAME_PREFIXES
("gen_<project>_binary"), so v1 stays out of the section.
cmakev2 parameterizes the same logical targets by the project name
in tools/cmakev2/build.cmake and tools/cmakev2/project.cmake and
produces, for project "build_test_app":
build_test_app_binary
build_test_app_binary_check_size
build_test_app_mapfile
build_test_app.map
ldgen_libraries.in_library_build_test_app
None of these match the v1-shaped allowlist or shape policy, so
both tests fail on every cmakev2 project rather than only on this
test app. Skip them under buildv2 with @pytest.mark.buildv2_skip
to unblock CI while a more robust filtering strategy is worked out.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Add a buildv2 test that reconfigures the test app with both GCC and
clang toolchains and asserts that the selected IDF_TOOLCHAIN value
is propagated to sdkconfig. The clang case is skipped when a clang
compiler is not available in PATH.
Profiling shows that parsing the linker fragment (.lf) files with
pyparsing is the single largest cost in ldgen (~58% of total runtime).
parse_fragment_file() rebuilds its grammar from scratch on every call
because the conditional parser closure has to capture sdkconfig to
evaluate if/elif/else at parse time.
Add a cache that pickles the parsed FragmentFile object list to
<output>.lfcache. The cache is keyed on fragment file paths+mtimes
plus sdkconfig and kconfig mtimes — sdkconfig is included because
fragment if/elif/else blocks are evaluated against it at parse time.
This avoids the pyparsing cost on rebuilds where ldgen has to run
but the fragment files themselves are unchanged — for example when
a function is added or removed in a source file. Cache hits produce
the same sections.ld as a full parse, and any pickle load failure
falls through to a normal parse, so cache corruption or a Python
upgrade cannot produce a wrong build.
Print "Skipping linker fragment parsing, fragment files unchanged"
on the lf cache hit path so build logs show when the optimization
fired — this makes it easy to diagnose user reports of unexpected
ldgen behavior.
The LDGEN_NO_CACHE environment variable disables the lf cache. When
set, ldgen falls through to a normal parse without consulting or
writing the cache file.
Measured on wifi_station (205 libs, 67 .lf files), median of 10 runs:
before after
rebuild, section change, .lf unchanged 5.82s 1.34s
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
After running objdump on all libraries, extract section names from the
stored raw output using regex and compute a fingerprint (MD5 hash of
section names + mtimes of fragment files, sdkconfig, and kconfig).
If the fingerprint matches the cached value from the previous run,
skip the expensive pyparsing + generation step entirely and touch
the output file to update its timestamp. The fingerprint file is
stored next to the output (e.g. sections.ld.fingerprint) in the build
directory.
This avoids the pyparsing bottleneck for the common case of editing
function bodies without adding or removing symbols — section names
in the object files are unchanged, so the generated sections.ld
would be identical. When sections do change, the full generation
runs and the fingerprint is updated.
Print "Skipping linker script generation, section names unchanged"
on the fingerprint hit path so build logs show when the optimization
fired. This makes it easy to diagnose user reports of unexpected
ldgen behavior — the build log directly shows whether the cache was
used.
Add an LDGEN_NO_CACHE environment variable to disable the cache as a
workaround in case the optimization causes problems. When set, ldgen
prints "Linker script generation caches disabled by LDGEN_NO_CACHE"
and runs full generation as before, leaving any existing fingerprint
file untouched.
Measured on wifi_station (205 libs, 67 .lf files), median of 10 runs:
before after
rebuild, section names unchanged 5.82s 0.82s
Closes https://github.com/espressif/esp-idf/issues/18408
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
The TestIdfRootDependency tests (test_basic_build,
test_build_only_when_required, test_cleanup_unused) were introduced in
MR 39704 to validate the idf_extra_components.yml root dependency
feature. This feature relies on component manager integration that is
not yet implemented in the cmakev2 build system, causing all three
tests to fail when run with --buildv2.
Skip these tests for cmakev2 using the buildv2_skip marker until root
components support is added (IDF-14259).
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
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>
The check-all-apps-readmes pre-commit hook detected that
kconfig_test_app/README.md was missing the supported targets table.
Added the full table including esp32h21, esp32h4, and esp32s31.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>