Build ULP full subprojects through a dedicated entry file,
components/ulp/cmake/ulp_project.cmake, that wraps tools/cmakev2/idf.cmake
and layers a small ULP API on top, mirroring the cmakev2 layering:
ulp_project_init like idf_project_init (init, detect the ULP type,
reset the compile/link options inherited from the app)
ulp_build_executable like idf_build_executable, plus the embeddable
.bin/.h/.ld artifacts
ulp_project_default like idf_project_default (single-executable case)
A child project now includes this one file instead of idf.cmake and calls
these helpers directly, so idf_build_executable is used as-is for the
multi-binary case and the module-path indirection (include(IDFULPProject)
resolved via -DCMAKE_MODULE_PATH) is gone.
As a result:
- IDFULPProjectv2.cmake is removed; its setup moves into the wrapper.
- IDFULPProject.cmake becomes the CMake v1-only entry point.
- The ULP component no longer registers a POST_ELF callback; the binary
artifacts are produced by ulp_build_executable.
- The v2 full-subproject examples (lp_core, riscv, fsm, multi_binary,
combined) are updated to the new API.
- The ULP subproject API is documented in build-system-v2.rst.
Also fix a latent bug this exercises: idf_build_library emitted linker
scripts as "-T <name>" relying on a following "-L" search directory. GNU
ld only searches -L directories that precede -T, so the direct
esp32ulp-elf-ld link used for ULP FSM failed to open the script. Emit the
absolute path instead, matching what the CMake v1 ULP build already does.
Finally, replace the parent-argument bypass loop that used to live in
IDFULPProjectv2.cmake with --no-warn-unused-cli on the child configure,
and stop passing the unused IDF_PARENT_BUILD_DIR.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
The ULP sub-project's editable sdkconfig and dependencies.lock previously
landed in the source tree (the defaults of __init_kconfig and the
component manager). A typical cleanup before changing target (rm -rf
build/ sdkconfig) did not reach them, so a stale CONFIG_IDF_TARGET would
survive into the next build and trip the cross-check in the ULP's
__init_idf_target.
In the cmakev2 path of __setup_ulp_project, anchor the ULP binary dir to
${BUILD_DIR}/subprojects/${app_name} and pass -DSDKCONFIG and
-DDEPENDENCIES_LOCK so both files live alongside the rest of the ULP
build artifacts. Wiping build/ (or idf.py fullclean, which set-target
pulls in) now reverts all sub-project state in one shot.
Also add a safety-net rename of any pre-existing sub-project sdkconfig
to .old when _IDF_PY_SET_TARGET_ACTION=1 is set in the parent's
configure environment. This mirrors what cmakev1 does for its own
sdkconfig and covers the off-path case where someone reconfigures via
cmake -B build -DIDF_TARGET=... directly, without running fullclean. In
the normal idf.py set-target flow the rename is a no-op because
fullclean has already removed the build tree.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Sub-projects that grow their own configuration (e.g. the ULP cmakev2
flow, where the sub-project runs its own kconfgen and writes its own
sdkconfig) need a way to expose that configuration via `idf.py
menuconfig` without forcing every caller to know per-sub-project target
names.
Add a small registration + dispatcher mechanism in cmakev2:
* `idf_register_menuconfig(NAME <label> TARGET <cmake-target>)` records
a menuconfig target with the build. It is intentionally decoupled
from `idf_create_menuconfig` so that any custom target may be
registered, including the parent-side proxy targets that sub-projects
add via `externalproject_add` (e.g. ULP's `menuconfig-<app_name>`).
* `__finalize_menuconfig()` at project finalization creates the
user-facing `menuconfig` target:
- With a single registration, `menuconfig` is a thin alias for that
target. Behaviour is identical to before for all existing single
-menuconfig projects (bootloader/TEE share the main configuration,
so they do not register).
- With two or more registrations, `menuconfig` runs a small Python
dispatcher (`tools/kconfig_new/menuconfig_dispatcher.py`) that
lists the registered configurations and re-invokes the selected
target. The prompt surfaces the direct target name (e.g.
`idf.py menuconfig-ulp_app`) so users learn the per-sub-project
target after first use.
`__project_default()` is updated to register the main application as
`menuconfig-app` and then call `__finalize_menuconfig`. The component
side change is one line in `components/ulp/project_include.cmake`,
registering the existing `menuconfig-<app_name>` proxy target.
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Add cmakev2 support for the ULP sub-project, allowing it to be built
using the standard idf_project_init() flow when the main project uses
cmakev2. The existing cmakev1 path is preserved — the ULP
CMakeLists.txt checks IDF_BUILD_V2 and delegates to CMakeLists_v2.txt,
following the same pattern used by the bootloader sub-project.
The parent's project_include.cmake now has separate externalproject_add
blocks for cmakev1 and cmakev2, making the different requirements of
each build system explicit:
cmakev1 path:
Passes -DSDKCONFIG_HEADER and -DSDKCONFIG_CMAKE from the parent.
The ULP sub-project includes the parent's sdkconfig.cmake directly
(no kconfgen). This is the existing behavior.
cmakev2 path:
Passes -DSDKCONFIG_DEFAULTS pointing to the parent's sdkconfig.
The ULP sub-project runs its own kconfgen with its own component
set, generating separate sdkconfig.h and sdkconfig.cmake outputs.
The parent's sdkconfig serves as defaults, so the ULP inherits
the parent's IDF configuration while adding ULP-specific options
from its own components. A menuconfig-<app_name> proxy target is
registered in the parent build for ULP-specific configuration.
The proxy target depends on the ULP configure step to ensure the
cmake cache exists before menuconfig runs.
Passes -DIDF_CUSTOM_TOOLCHAIN=1 so that __init_toolchain() skips
IDF_TARGET-based toolchain resolution and component
project_include.cmake files skip IDF toolchain flag manipulation.
IDFULPProject.cmake is updated to skip the direct
include(${SDKCONFIG_CMAKE}) when running under cmakev2, as
idf_project_init() handles sdkconfig loading.
Verified with identical ULP artifacts (bin, ld, h) across all three
ULP types:
- LP Core (esp32c6, lp_core/lp_uart/lp_uart_print example)
- RISC-V (esp32s3, ulp_riscv/adc example)
- FSM (esp32, ulp_fsm/ulp example)
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Updated kconfig option type and other supporting changes in build system
to allow enabling both ULP FSM and ULP RISCV simultaneously. Users can
choose at run time which one to initialize and use.
NOTE: Both ULP FSM and ULP RISCV can't be used simultaneously at run
time because they share some common hardware like RTC slow memory space.
Closes https://github.com/espressif/esp-idf/issues/12999
This commit adds the ability to use LP ROM functions from the LP core.
This allows the LP core code to utilize standard functions such as those
for printing from the LP ROM and therefore help reduce the code size on
the LP core.
This commit refactors the ulp component.
Files are now divided based on type of ulp, viz., fsm or risc-v.
Files common to both are maintained in the ulp_common folder.
This commit also adds menuconfig options for ULP within the ulp
component instead of presenting target specific configuations for ulp.
!4452 used setting LINK_LIBRARIES and INTERFACE_LINK_LIBRARIES to link
components built under ESP-IDF build system. However, LINK_LIBRARIES does
not produce behavior same as linking PRIVATE. This MR uses the new
signature for target_link_libraries directly instead. This also moves
setting dependencies during component registration rather than after all
components have been processed.
The consequence is that internally, components have to use the new
signature form as well. This does not affect linking the components to
external targets, such as with idf_as_lib example. This only affects
linking additional libraries to ESP-IDF libraries outside component processing (after
idf_build_process), which is not even possible for CMake<v3.13 as
target_link_libraries is not valid for targets not created in current
directory. See https://cmake.org/cmake/help/v3.13/policy/CMP0079.html#policy:CMP0079