| #------------------------------------------------------------------------------- |
| # Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved. |
| # |
| # SPDX-License-Identifier: BSD-3-Clause |
| # |
| #------------------------------------------------------------------------------- |
| |
| #[===[.rst: |
| Group utility file |
| ------------------ |
| Group is an unordered collection of interrelated :cmake:module:`map`\s. |
| |
| The main purpose of this utility is to pack a set of coherent configuration data |
| description into one unit, which can be applied on a target in one step. This |
| means e.g. defines, compiler flags, include paths, etc. |
| |
| Internally the utility uses global properties and maps. Global property |
| ``GROUPS.<name of group>`` is defined to indicate that the group is defined, and |
| for each element in the :cmake:variable:`GROUPS_VALID_TYPES`: |
| |
| * a map is created, using ``<name of group>.<type>`` as name, |
| * a global property ``GROUPS.<name of group>.<type>`` is defined to indicate |
| that the type is valid in the group. |
| |
| .. todo:: Investigate alternatives to global properties (name collision possible). |
| .. todo:: Investigate if import/export group functions would be necessary. |
| |
| #]===] |
| |
| include_guard(DIRECTORY) |
| include(Common/Map) |
| include(Common/Utils) |
| |
| #[===[.rst: |
| .. cmake:variable:: GROUPS_VALID_TYPES |
| |
| List of configuration data types that can be stored in a group. The |
| implementation of :cmake:command:`group_new` creates a map for each of these |
| types automatically. |
| |
| #]===] |
| set(GROUPS_VALID_TYPES "CONFIG;DEFINE;CFLAG;ASFLAG;LDFLAG;INCLUDE") |
| |
| #[===[.rst: |
| .. cmake:command:: group_new |
| |
| .. code-block:: cmake |
| |
| group_new(NAME foo) |
| |
| Create a new group. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the new group, use |C identifier like string|. The name must be |
| unique within the global namespace, otherwise an error is generated. |
| |
| #]===] |
| function(group_new) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME) |
| set(_MULTI_VALUE_ARGS) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(group_new NAME) |
| |
| group_is_defined(NAME ${_MY_PARAMS_NAME} RET _is_defined) |
| if(_is_defined) |
| message(FATAL_ERROR "group_new(): '${_MY_PARAMS_NAME}' is already defined.") |
| endif() |
| |
| set(_null " ") |
| define_property(GLOBAL PROPERTY GROUPS.${_MY_PARAMS_NAME} BRIEF_DOCS ${_null} FULL_DOCS ${_null}) |
| |
| foreach(_type IN LISTS GROUPS_VALID_TYPES) |
| define_property(GLOBAL PROPERTY GROUPS.${_MY_PARAMS_NAME}.${_type} BRIEF_DOCS ${_null} FULL_DOCS ${_null}) |
| map_new(NAME ${_MY_PARAMS_NAME}.${_type}) |
| endforeach() |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: group_is_defined |
| |
| .. code-block:: cmake |
| |
| group_is_defined(NAME foo RET ret) |
| |
| Helper function to check if a group has been defined. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the group. |
| |
| Outputs: |
| |
| ``RET`` |
| Name of the variable in the parent scope, where the return value is written. |
| |
| #]===] |
| function(group_is_defined) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME RET) |
| set(_MULTI_VALUE_ARGS) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(group_is_defined NAME RET) |
| |
| get_property(_is_defined GLOBAL PROPERTY GROUPS.${_MY_PARAMS_NAME} DEFINED) |
| set(${_MY_PARAMS_RET} ${_is_defined} PARENT_SCOPE) |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: group_add |
| |
| .. code-block:: cmake |
| |
| group_add(NAME foo TYPE type KEY one VAL 1) |
| |
| Add new key-value pair to the map called ``type`` within a group. Multiple |
| types can be defined in one function call, the key-value pair will be added to |
| each of those types. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the group. Trying to add to a non-existing group generates an error. |
| |
| ``TYPE`` (multi) |
| Type can be one or more of the values defined in |
| :cmake:variable:`GROUPS_VALID_TYPES`. |
| |
| ``KEY`` |
| New key to add. Same constraints apply as described in |
| :cmake:command:`map_add`. |
| |
| ``VAL`` (optional) |
| Value for new key. Same constraints apply as described in |
| :cmake:command:`map_add`. |
| |
| #]===] |
| function(group_add) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME KEY VAL) |
| set(_MULTI_VALUE_ARGS TYPE) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(group_add NAME TYPE KEY) |
| |
| group_is_defined(NAME ${_MY_PARAMS_NAME} RET _is_group_defined) |
| if(NOT _is_group_defined) |
| message(FATAL_ERROR "group_add(): '${_MY_PARAMS_NAME}' group is not defined.") |
| endif() |
| |
| if(DEFINED _MY_PARAMS_VAL) |
| if(DEFINED CFG_${_MY_PARAMS_KEY}) |
| set(_val ${CFG_${_MY_PARAMS_KEY}}) |
| message(STATUS "group_add(): '${_MY_PARAMS_KEY}' in group '${_MY_PARAMS_NAME}' is |
| overwritten by command line parameter.") |
| else() |
| set(_val ${_MY_PARAMS_VAL}) |
| endif() |
| else() |
| set(_val " ") |
| endif() |
| |
| foreach(_type IN LISTS _MY_PARAMS_TYPE) |
| get_property(_is_type_defined GLOBAL PROPERTY GROUPS.${_MY_PARAMS_NAME}.${_type} DEFINED) |
| if(NOT _is_type_defined) |
| message(FATAL_ERROR "group_add(): '${_type}' type is invalid.") |
| endif() |
| |
| map_add(NAME ${_MY_PARAMS_NAME}.${_type} KEY ${_MY_PARAMS_KEY} VAL ${_val}) |
| endforeach() |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: group_apply |
| |
| .. code-block:: cmake |
| |
| group_apply(NAME foo TARGETS target1 target2) |
| |
| Apply a group onto the selected target(s). All settings contained in the group |
| will be added to the targets. Use this function only for the build targets |
| created with :cmake:command:`stgt_create`. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the group. |
| |
| ``TARGETS`` (multi) |
| Name of the targets. |
| |
| .. todo:: Move this to STGT? |
| .. todo:: Revise implementation for INCLUDE type. |
| |
| #]===] |
| function(group_apply) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME) |
| set(_MULTI_VALUE_ARGS TARGETS) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(group_apply NAME TARGETS) |
| |
| group_is_defined(NAME ${_MY_PARAMS_NAME} RET _is_defined) |
| if(NOT _is_defined) |
| message(FATAL_ERROR "group_apply(): '${_MY_PARAMS_NAME}' group is not defined.") |
| endif() |
| |
| foreach(_target IN LISTS _MY_PARAMS_TARGETS) |
| if(NOT TARGET ${_target}) |
| message(FATAL_ERROR "group_apply(): target '${_target}' is not defined.") |
| endif() |
| |
| map_read(NAME ${_MY_PARAMS_NAME}.CONFIG KEYS _keys VALS _vals) |
| if(_keys AND _vals) |
| list(LENGTH _keys _count) |
| math(EXPR _count "${_count}-1") |
| |
| foreach(i RANGE ${_count}) |
| list(GET _keys ${i} _key) |
| list(GET _vals ${i} _val) |
| set_property(TARGET ${_target} PROPERTY ${_key} ${_val}) |
| endforeach() |
| endif() |
| |
| map_read(NAME ${_MY_PARAMS_NAME}.DEFINE KEYS _keys VALS _vals) |
| if(_keys AND _vals) |
| map_to_list(KEYS ${_keys} VALS ${_vals} OUT _defines) |
| target_compile_definitions(${_target} PRIVATE ${_defines}) |
| endif() |
| |
| map_read(NAME ${_MY_PARAMS_NAME}.CFLAG KEYS _keys VALS _vals) |
| if(_keys AND _vals) |
| map_to_list(KEYS ${_keys} VALS ${_vals} OUT _cflags) |
| target_compile_options(${_target} PRIVATE ${_cflags}) |
| endif() |
| |
| map_read(NAME ${_MY_PARAMS_NAME}.ASFLAG KEYS _keys VALS _vals) |
| if(_keys AND _vals) |
| map_to_list(KEYS ${_keys} VALS ${_vals} OUT _asflags) |
| target_compile_options(${_target} PRIVATE $<$<COMPILE_LANGUAGE:ASM>:${_asflags}>) |
| endif() |
| |
| map_read(NAME ${_MY_PARAMS_NAME}.LDFLAG KEYS _keys VALS _vals) |
| if(_keys AND _vals) |
| map_to_list(KEYS ${_keys} VALS ${_vals} OUT _ldflags) |
| target_link_options(${_target} PRIVATE ${_ldflags}) |
| endif() |
| |
| map_read(NAME ${_MY_PARAMS_NAME}.INCLUDE KEYS _keys VALS _vals) |
| if(_keys) |
| stgt_add_inc_param(NAME ${_target} KEY ARCH INC ${_keys}) |
| endif() |
| endforeach() |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: group_print |
| |
| .. code-block:: cmake |
| |
| group_print(NAME foo) |
| |
| Print contents of the group, for debug purposes. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the group. |
| |
| #]===] |
| function(group_print) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME) |
| set(_MULTI_VALUE_ARGS) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| if (NOT DEFINED _MY_PARAMS_NAME) |
| message(FATAL_ERROR "group_print(): mandatory parameter 'NAME' missing.") |
| endif() |
| |
| message("\n====Group '${_MY_PARAMS_NAME}'====") |
| foreach(_type IN LISTS GROUPS_VALID_TYPES) |
| map_print(NAME ${_MY_PARAMS_NAME}.${_type}) |
| endforeach() |
| message("====Group '${_MY_PARAMS_NAME}' end====\n") |
| endfunction() |