feat(cmakev2/build): add idf_build_library stub

Add idf_build_library function and enable setting and getting its
properties. This lays the groundwork for future initialization that
needs to occur after the project() call, such as determining compilation
options and others.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
This commit is contained in:
Frantisek Hrbata
2025-11-04 07:48:12 +01:00
parent f4a71830d5
commit affa714a15
2 changed files with 200 additions and 1 deletions
+159
View File
@@ -88,3 +88,162 @@ function(__dump_build_properties)
idf_msg(" ${property}: ${value}")
endforeach()
endfunction()
#[[
__get_library_interface_or_die(LIBRARY <library>
OUTPUT <variable>)
:LIBRARY[in]: Library interface or alias.
:OUTPUT[out]: Output variable to store the library interface.
Verify that "LIBRARY" is a known interface created by ``idf_build_library``
or its alias. If it is, return the library interface; otherwise, terminate
the build process.
#]]
function(__get_library_interface_or_die)
set(options)
set(one_value LIBRARY OUTPUT)
set(multi_value)
cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN})
if(NOT DEFINED ARG_LIBRARY)
idf_die("LIBRARY option is required")
endif()
if(NOT DEFINED ARG_OUTPUT)
idf_die("OUTPUT option is required")
endif()
__get_real_target(TARGET ${ARG_LIBRARY} OUTPUT library_interface)
idf_build_get_property(library_interfaces LIBRARY_INTERFACES)
if(NOT "${library_interface}" IN_LIST library_interfaces)
idf_die("Library interface '${ARG_LIBRARY}' does not exist")
endif()
set(${ARG_OUTPUT} ${library_interface} PARENT_SCOPE)
endfunction()
#[[api
.. cmakev2:function:: idf_library_set_property
.. code-block:: cmake
idf_library_set_property(<library> <property> <value> [APPEND])
:library[in]: Library interface target or alias.
:property[in]: Property name.
:value[in]: Property value.
:APPEND: Append the value to the property's current value instead of
replacing it.
Set the value of the specified library property. The property is also
added to the internal list of library properties if it isn't already
there.
#]]
function(idf_library_set_property library property value)
set(options APPEND)
set(one_value)
set(multi_value)
cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN})
set(append)
if(ARG_APPEND)
set(append APPEND)
endif()
__get_library_interface_or_die(LIBRARY "${library}" OUTPUT library_interface)
__set_property(TARGET "${library_interface}"
PROPERTY "${property}"
PROPERTIES LIBRARY_PROPERTIES
VALUE "${value}"
${append})
endfunction()
#[[api
.. cmakev2:function:: idf_library_get_property
.. code-block:: cmake
idf_library_get_property(<variable> <library> <property> [GENERATOR_EXPRESSION])
:variable[out]: Variable to store the value in.
:library[in]: Library interface target or alias.
:property[in]: Property name to get the value of.
:GENERATOR_EXPRESSION: Obtain the generator expression for the property
rather than the actual value.
Retrieve the value of the specified library property.
#]]
function(idf_library_get_property variable library property)
set(options GENERATOR_EXPRESSION)
set(one_value)
set(multi_value)
cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN})
set(genexpr)
if(ARG_GENERATOR_EXPRESSION)
set(genexpr GENERATOR_EXPRESSION)
endif()
__get_library_interface_or_die(LIBRARY "${library}" OUTPUT library_interface)
__get_property(TARGET "${library_interface}"
PROPERTY "${property}"
OUTPUT value
${genexpr})
set(${variable} ${value} PARENT_SCOPE)
endfunction()
#[[
__dump_library_properties(<libraries>)
:libraries: List of library interfaces whose properties should be displayed.
Dump all properties for the libraries listed in ``<libraries>``.
#]]
function(__dump_library_properties libraries)
foreach(library IN LISTS libraries)
idf_library_get_property(properties "${library}" LIBRARY_PROPERTIES)
idf_msg("library '${library}' properties: ${properties}")
foreach(property IN LISTS properties)
idf_library_get_property(value "${library}" "${property}")
idf_msg(" ${property}: ${value}")
endforeach()
endforeach()
endfunction()
#[[api
.. cmakev2:function:: idf_build_library
.. code-block:: cmake
idf_build_library(INTERFACE <interface>
[COMPONENTS <component>...])
:INTERFACE[in,out]: Name of the library interface to be created.
:COMPONENTS[in,opt]: List of component names to add to the library.
Create a new library interface target with the name specified in the
``INTERFACE`` option and link component targets to it based on the component
names provided in the ``COMPONENTS`` option. If ``COMPONENTS`` option is not
set, link component targets of all discovered components.
#]]
function(idf_build_library)
set(options)
set(one_value INTERFACE)
set(multi_value COMPONENTS)
cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN})
if(NOT DEFINED ARG_INTERFACE)
idf_die("INTERFACE option is required")
endif()
if(NOT DEFINED ARG_COMPONENTS)
# The library should include all discovered components.
idf_build_get_property(component_names COMPONENTS_DISCOVERED)
set(ARG_COMPONENTS "${component_names}")
endif()
add_library("${ARG_INTERFACE}" INTERFACE)
idf_build_set_property(LIBRARY_INTERFACES "${ARG_INTERFACE}" APPEND)
idf_library_set_property("${ARG_INTERFACE}" LIBRARY_COMPONENTS "${ARG_COMPONENTS}")
endfunction()
+41 -1
View File
@@ -14,6 +14,8 @@ function(test_dump_properties)
__dump_build_properties()
idf_build_get_property(component_names COMPONENTS_DISCOVERED)
__dump_component_properties("${component_names}")
idf_build_get_property(library_interfaces LIBRARY_INTERFACES)
__dump_library_properties("${library_interfaces}")
endfunction()
# Test component priority
@@ -100,11 +102,49 @@ function(test_toolchain)
endif()
endfunction()
# Test idf_build_library
function(test_idf_build_library)
# Create idflibtest with specific set of components and test that it
# contains them.
set(components app_trace app_update bootloader bootloader_support bt cmock)
set(idflib idflibtest)
idf_build_library(INTERFACE "${idflib}"
COMPONENTS "${components}")
if(NOT TARGET "${idflib}")
idf_die("'${idflib}' not created")
endif()
idf_library_get_property(lib_components "${idflib}" LIBRARY_COMPONENTS)
if(NOT "${lib_components}" STREQUAL "${components}")
idf_die("Library '${idflib}' components '${lib_components}' do not match "
"expected components '${components}'")
endif()
# Create idflibtest2 without specifying COMPONENTS and test that it
# contains all discovered components.
set(idflib idflibtest2)
idf_build_library(INTERFACE "${idflib}")
if(NOT TARGET "${idflib}")
idf_die("'${idflib}' not created")
endif()
idf_library_get_property(lib_components "${idflib}" LIBRARY_COMPONENTS)
idf_build_get_property(component_names COMPONENTS_DISCOVERED)
if(NOT "${lib_components}" STREQUAL "${component_names}")
idf_die("Library '${idflib}' components '${lib_components}' do not match "
"COMPONENTS_DISCOVERED")
endif()
endfunction()
# Run tests
test_dump_properties()
test_component_priority()
test_idf_version()
test_python()
test_toolchain()
test_idf_build_library()
test_dump_properties()
message("ALL TESTS PASSED")