mirror of
https://github.com/espressif/esp-idf.git
synced 2026-08-18 06:35:35 +03:00
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>
189 lines
6.6 KiB
CMake
189 lines
6.6 KiB
CMake
# ULP subproject entry point for CMake v2 full-subproject builds.
|
|
#
|
|
# A ULP child project includes this file instead of tools/cmakev2/idf.cmake
|
|
# directly. It pulls in the cmakev2 build system and layers the ULP subproject
|
|
# API on top: ulp_project_init, ulp_build_executable, ulp_build_binary and
|
|
# ulp_project_default, the ULP analogs of idf_project_init,
|
|
# idf_build_executable, idf_build_binary and idf_project_default.
|
|
|
|
include(${IDF_PATH}/tools/cmakev2/idf.cmake)
|
|
include(${CMAKE_CURRENT_LIST_DIR}/IDFULPProjectCommon.cmake)
|
|
|
|
# Reset the compile/link state inherited from the parent app build and select
|
|
# ULP-specific build behavior. Idempotent within a child configure.
|
|
function(__ulp_prepare_build)
|
|
idf_build_get_property(ulp_build_prepared __ULP_BUILD_PREPARED)
|
|
if(ulp_build_prepared)
|
|
return()
|
|
endif()
|
|
|
|
if(BUILD_FSM)
|
|
check_expected_tool_version("esp32ulp-elf" ${CMAKE_ASM_COMPILER})
|
|
# FSM links with esp32ulp-elf-ld directly, not through GCC, so avoid
|
|
# GCC-driver link grouping flags from the generic executable helper.
|
|
idf_build_set_property(LINKER_TYPE ULP_FSM)
|
|
endif()
|
|
|
|
# ULP projects use their own toolchain files and component-provided options,
|
|
# so discard compile/link options added for normal app builds.
|
|
foreach(property IN ITEMS
|
|
COMPILE_OPTIONS
|
|
C_COMPILE_OPTIONS
|
|
CXX_COMPILE_OPTIONS
|
|
ASM_COMPILE_OPTIONS
|
|
COMPILE_DEFINITIONS
|
|
LINK_OPTIONS)
|
|
idf_build_set_property(${property} "")
|
|
endforeach()
|
|
|
|
# Do not apply the default app component closure to ULP child projects.
|
|
# ULP components should contribute dependencies explicitly.
|
|
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "")
|
|
idf_build_set_property(__COMMON_COMPONENT_INTERFACES "")
|
|
idf_build_set_property(__COMMON_COMPONENTS_INITIALIZED YES)
|
|
|
|
idf_build_set_property(__ULP_BUILD_PREPARED YES)
|
|
endfunction()
|
|
|
|
#[[api
|
|
.. cmakev2:macro:: ulp_project_init
|
|
|
|
.. code-block:: cmake
|
|
|
|
ulp_project_init()
|
|
|
|
Initialize a ULP full-subproject build. Calls :cmakev2:ref:`idf_project_init`
|
|
and then applies the ULP-specific setup: it detects the ULP type (RISC-V, LP
|
|
core or FSM) from the ``ULP_TYPE`` variable or the project configuration and
|
|
resets the compile and link options inherited from the parent application
|
|
build, so the ULP executable uses only its own toolchain and
|
|
component-provided options.
|
|
|
|
This is the ULP analog of :cmakev2:ref:`idf_project_init` and is the entry
|
|
point for projects that build more than one ULP executable, followed by
|
|
:cmakev2:ref:`ulp_build_executable` and :cmakev2:ref:`ulp_build_binary`
|
|
calls. For the common single-executable case use
|
|
:cmakev2:ref:`ulp_project_default` instead.
|
|
#]]
|
|
macro(ulp_project_init)
|
|
idf_project_init()
|
|
ulp_detect_build_type()
|
|
ulp_apply_build_type_options()
|
|
__ulp_prepare_build()
|
|
endmacro()
|
|
|
|
#[[api
|
|
.. cmakev2:function:: ulp_build_executable
|
|
|
|
.. code-block:: cmake
|
|
|
|
ulp_build_executable(<executable>
|
|
[COMPONENTS <component>...]
|
|
[MAPFILE_TARGET <target>])
|
|
|
|
*executable[in]*
|
|
|
|
Name of the ULP executable target to create.
|
|
|
|
Build a ULP executable. This is the ULP analog of
|
|
:cmakev2:ref:`idf_build_executable` and forwards its arguments to
|
|
:cmakev2:ref:`idf_build_executable`. Call :cmakev2:ref:`ulp_build_binary`
|
|
for each executable that should produce embeddable ULP artifacts.
|
|
#]]
|
|
function(ulp_build_executable executable)
|
|
if("PREFIX" IN_LIST ARGN)
|
|
message(FATAL_ERROR "Use ulp_build_binary(${executable} PREFIX ...) to set ULP symbol prefixes.")
|
|
endif()
|
|
|
|
idf_build_executable(${executable} ${ARGN})
|
|
endfunction()
|
|
|
|
#[[api
|
|
.. cmakev2:function:: ulp_build_binary
|
|
|
|
.. code-block:: cmake
|
|
|
|
ulp_build_binary(<executable>
|
|
[PREFIX <prefix>])
|
|
|
|
*executable[in]*
|
|
|
|
ULP executable target for which to generate embeddable artifacts.
|
|
|
|
*PREFIX[in,opt]*
|
|
|
|
Symbol name prefix for the generated symbol header and linker export
|
|
files. Defaults to ``ulp_``. Use a distinct prefix per executable when a
|
|
project builds several ULP binaries.
|
|
|
|
Generate the ``.bin`` payload and symbol header/linker export files for a
|
|
ULP executable. This is the ULP analog of :cmakev2:ref:`idf_build_binary`.
|
|
#]]
|
|
function(ulp_build_binary executable)
|
|
cmake_parse_arguments(_ULP "" "PREFIX" "" ${ARGN})
|
|
if(_ULP_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR "Unexpected arguments to ulp_build_binary(): ${_ULP_UNPARSED_ARGUMENTS}")
|
|
endif()
|
|
|
|
if(DEFINED _ULP_PREFIX)
|
|
ulp_add_build_binary_targets(${executable} PREFIX "${_ULP_PREFIX}")
|
|
elseif(ULP_PREFIX_APPEND_BIN_NAME)
|
|
set(prefix "ulp_")
|
|
if(DEFINED ULP_VAR_PREFIX)
|
|
set(prefix "${ULP_VAR_PREFIX}")
|
|
endif()
|
|
string(MAKE_C_IDENTIFIER "${prefix}${executable}_" prefix)
|
|
ulp_add_build_binary_targets(${executable} PREFIX "${prefix}")
|
|
else()
|
|
ulp_add_build_binary_targets("${executable}")
|
|
endif()
|
|
endfunction()
|
|
|
|
# Build the single default ULP executable from the main component.
|
|
function(__ulp_project_default)
|
|
set(ulp_app_name "${PROJECT_NAME}")
|
|
|
|
set(executable_args COMPONENTS main)
|
|
set(binary_args)
|
|
if(NOT BUILD_FSM)
|
|
list(APPEND executable_args MAPFILE_TARGET ${ulp_app_name}_mapfile)
|
|
endif()
|
|
if(DEFINED ULP_VAR_PREFIX AND NOT "${ULP_VAR_PREFIX}" STREQUAL "")
|
|
list(APPEND binary_args PREFIX ${ULP_VAR_PREFIX})
|
|
endif()
|
|
|
|
ulp_build_executable(${ulp_app_name} ${executable_args})
|
|
ulp_build_binary(${ulp_app_name} ${binary_args})
|
|
|
|
idf_build_generate_metadata(EXECUTABLE ${ulp_app_name})
|
|
|
|
if(TARGET "${ulp_app_name}_mapfile")
|
|
idf_create_size_report("${ulp_app_name}_mapfile" TARGET size)
|
|
endif()
|
|
|
|
idf_build_generate_depgraph("${ulp_app_name}")
|
|
endfunction()
|
|
|
|
#[[api
|
|
.. cmakev2:macro:: ulp_project_default
|
|
|
|
.. code-block:: cmake
|
|
|
|
ulp_project_default()
|
|
|
|
Build a single ULP executable from the ``main`` component and its transitive
|
|
dependencies, the ULP analog of :cmakev2:ref:`idf_project_default`. Calls
|
|
:cmakev2:ref:`ulp_project_init`, then builds the executable (named after
|
|
``PROJECT_NAME``) with :cmakev2:ref:`ulp_build_executable` and generates its
|
|
embeddable artifacts with :cmakev2:ref:`ulp_build_binary`.
|
|
#]]
|
|
macro(ulp_project_default)
|
|
ulp_project_init()
|
|
|
|
# A single executable is built, so DEFERRED optional-requires resolution is
|
|
# safe and keeps the linked component set minimal.
|
|
idf_build_set_property(IDF_COMPONENT_OPTIONAL_REQUIRES_MODE DEFERRED)
|
|
|
|
__ulp_project_default()
|
|
endmacro()
|