From b702d3c077af24fabcd067038bea23e96d6e0b31 Mon Sep 17 00:00:00 2001 From: Frantisek Hrbata Date: Thu, 24 Jul 2025 17:04:01 +0200 Subject: [PATCH] feat(cmakev2/utilities): add __set_property and __get_property helpers The `idf_build_(set|get)_property` and `idf_component_(set|get)_property` functions share a lot of similar code. Move these common parts into new `__(set|get)_property` helper functions. With the upcoming `idf_build_library` API function, we might need to add properties for the interface target created for the library, which would otherwise lead to yet another code duplication for setting and getting library interface properties. Update the current implementations of `idf_build_(set|get)_property` and `idf_component_(set|get)_property` to utilize these new helper functions. Signed-off-by: Frantisek Hrbata --- tools/cmakev2/build.cmake | 27 +++++---- tools/cmakev2/component.cmake | 30 +++++----- tools/cmakev2/utilities.cmake | 100 ++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 24 deletions(-) diff --git a/tools/cmakev2/build.cmake b/tools/cmakev2/build.cmake index 9839027a4c1..3ed7b3a95ce 100644 --- a/tools/cmakev2/build.cmake +++ b/tools/cmakev2/build.cmake @@ -27,16 +27,16 @@ function(idf_build_set_property property value) set(multi_value) cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN}) - get_property(properties TARGET idf_build_properties PROPERTY BUILD_PROPERTIES) - if(NOT property IN_LIST properties) - list(APPEND properties "${property}") - set_property(TARGET idf_build_properties PROPERTY BUILD_PROPERTIES "${properties}") - endif() + set(append) if(ARG_APPEND) - set_property(TARGET idf_build_properties APPEND PROPERTY "${property}" "${value}") - else() - set_property(TARGET idf_build_properties PROPERTY "${property}" "${value}") + set(append APPEND) endif() + + __set_property(TARGET idf_build_properties + PROPERTY "${property}" + PROPERTIES BUILD_PROPERTIES + VALUE "${value}" + ${append}) endfunction() #[[api @@ -62,11 +62,16 @@ function(idf_build_get_property variable property) if("${property}" STREQUAL BUILD_COMPONENTS) idf_die("Build property 'BUILD_COMPONENTS' is not supported") endif() + + set(genexpr) if(ARG_GENERATOR_EXPRESSION) - set(value "$") - else() - get_property(value TARGET idf_build_properties PROPERTY ${property}) + set(genexpr GENERATOR_EXPRESSION) endif() + + __get_property(TARGET idf_build_properties + PROPERTY "${property}" + OUTPUT value + ${genexpr}) set(${variable} ${value} PARENT_SCOPE) endfunction() diff --git a/tools/cmakev2/component.cmake b/tools/cmakev2/component.cmake index 746d6d9c982..2ee80cad407 100644 --- a/tools/cmakev2/component.cmake +++ b/tools/cmakev2/component.cmake @@ -28,17 +28,17 @@ function(idf_component_set_property component property value) set(multi_value) cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN}) - __get_component_interface_or_die(COMPONENT "${component}" OUTPUT component_interface) - get_property(properties TARGET ${component_interface} PROPERTY COMPONENT_PROPERTIES) - if(NOT property IN_LIST properties) - list(APPEND properties "${property}") - set_property(TARGET ${component_interface} PROPERTY COMPONENT_PROPERTIES "${properties}") - endif() + set(append) if(ARG_APPEND) - set_property(TARGET ${component_interface} APPEND PROPERTY ${property} "${value}") - else() - set_property(TARGET ${component_interface} PROPERTY ${property} "${value}") + set(append APPEND) endif() + + __get_component_interface_or_die(COMPONENT "${component}" OUTPUT component_interface) + __set_property(TARGET "${component_interface}" + PROPERTY "${property}" + PROPERTIES COMPONENT_PROPERTIES + VALUE "${value}" + ${append}) endfunction() #[[api @@ -61,12 +61,16 @@ function(idf_component_get_property variable component property) set(multi_value) cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN}) - __get_component_interface_or_die(COMPONENT "${component}" OUTPUT component_interface) + set(genexpr) if(ARG_GENERATOR_EXPRESSION) - set(value "$") - else() - get_property(value TARGET ${component_interface} PROPERTY ${property}) + set(genexpr GENERATOR_EXPRESSION) endif() + + __get_component_interface_or_die(COMPONENT "${component}" OUTPUT component_interface) + __get_property(TARGET "${component_interface}" + PROPERTY "${property}" + OUTPUT value + ${genexpr}) set(${variable} ${value} PARENT_SCOPE) endfunction() diff --git a/tools/cmakev2/utilities.cmake b/tools/cmakev2/utilities.cmake index 72205a7bf5d..c2237f07082 100644 --- a/tools/cmakev2/utilities.cmake +++ b/tools/cmakev2/utilities.cmake @@ -260,3 +260,103 @@ function(__get_sdkconfig_option) set(${ARG_OUTPUT} "${value}" PARENT_SCOPE) endfunction() + +#[[ + __set_property(TARGET + PROPERTY ) + PROPERTIES + VALUE + APPEND) + + :TARGET[in]: The target name to attach the property. + :PROPERTY[in]: Property name. + :PROPERTIES[in]: The target property containing list of properties. + :VALUE[in]: Property value. + :APPEND: Append the value to the property's current value instead of + replacing it. + + Set the ``PROPERTY`` to ``VALUE`` for the ``TARGET``, and also record the + ``PROPERTY`` name in the list of all properties for the ``TARGET``. The + property name where all ``TARGET`` property names are stored is specified + by the ``PROPERTIES`` option. If ``APPEND`` is specified, the property will + be added rather than set. + + Note: The cmake_parse_arguments function does not preserve empty arguments, + as explained in CMP0174. We do not verify if VALUE is defined because it + might have been passed as an empty string or list. + + Note: The VALUE is treated as a multi-value because if a list is provided + as the value, CMake assigns only the first entry to the VALUE if parsed as + one-value. The remaining entries are stored in _UNPARSED_ARGUMENTS. +#]] +function(__set_property) + set(options APPEND) + set(one_value TARGET PROPERTY PROPERTIES) + set(multi_value VALUE) + cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + if(NOT DEFINED ARG_TARGET) + idf_die("TARGET option is required") + endif() + + if(NOT DEFINED ARG_PROPERTY) + idf_die("PROPERTY option is required") + endif() + + if(NOT DEFINED ARG_PROPERTIES) + idf_die("PROPERTIES option is required") + endif() + + get_property(properties TARGET ${ARG_TARGET} PROPERTY ${ARG_PROPERTIES}) + if(NOT ARG_PROPERTY IN_LIST properties) + list(APPEND properties "${ARG_PROPERTY}") + set_property(TARGET ${ARG_TARGET} PROPERTY ${ARG_PROPERTIES} "${properties}") + endif() + if(ARG_APPEND) + set_property(TARGET ${ARG_TARGET} APPEND PROPERTY ${ARG_PROPERTY} "${ARG_VALUE}") + else() + set_property(TARGET ${ARG_TARGET} PROPERTY ${ARG_PROPERTY} "${ARG_VALUE}") + endif() +endfunction() + +#[[ + __get_property(TARGET + PROPERTY ) + OUTPUT + GENERATOR_EXPRESSION) + + :TARGET[in]: The target from which to obtain the property value. + :PROPERTY[in]: Property name. + :OUTPUT[out]: Output variable to store the property value. + :GENERATOR_EXPRESSION: Obtain the generator expression for the property + rather than the actual value. + + Get the value of the specified ``PROPERTY`` from ``TARGET`` and store it in + the ``OUTPUT`` variable. +#]] +function(__get_property) + set(options GENERATOR_EXPRESSION) + set(one_value TARGET PROPERTY OUTPUT) + set(multi_value) + cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + if(NOT DEFINED ARG_TARGET) + idf_die("TARGET option is required") + endif() + + if(NOT DEFINED ARG_PROPERTY) + idf_die("PROPERTY option is required") + endif() + + if(NOT DEFINED ARG_OUTPUT) + idf_die("PROPERTIES option is required") + endif() + + if(ARG_GENERATOR_EXPRESSION) + set(value "$") + else() + get_property(value TARGET ${ARG_TARGET} PROPERTY ${ARG_PROPERTY}) + endif() + + set(${ARG_OUTPUT} ${value} PARENT_SCOPE) +endfunction()