| #------------------------------------------------------------------------------- |
| # Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved. |
| # |
| # SPDX-License-Identifier: BSD-3-Clause |
| # |
| #------------------------------------------------------------------------------- |
| |
| #[===[.rst: |
| STGT utility file |
| ----------------- |
| The STGT ("simple target") API is a collection of functions which wrap the CMake |
| target functions and extend the built-in functionality. The main purpose of this |
| utility is to connect the :cmake:module:`group`\s and the build targets. It |
| handles the creation of new build targets, collecting the groups that will be |
| applied on the target, and setting the target type. Also it provides functions |
| to add source files and include paths in view of the properties already applied |
| to the target, assign a linker script to the target, etc. |
| |
| After the configuration step, the targets created by STGT are the same, in the |
| end, as normal CMake binary targets. However, the concept of STGT is to have |
| "virtual" targets when collecting the setting groups, etc. and only "tie" them |
| to a CMake target at the end of setup. This provides more flexibilty and |
| expandabilty for the future, without additional complexity to the user, because |
| the functionality is hidden behind the API. |
| |
| Internally the utility uses global properties and groups. Global property |
| ``STGT.<name of target>`` is defined to indicate that the target is defined. |
| Global property ``STGT.<name of target>.GROUPS`` stores the list of groups added |
| to the target. Adding a group to a target only results in modifying this list, |
| the parameters stored in the group are actually applied only by the |
| :cmake:command:`stgt_set_target` function. This function creates a normal CMake |
| binary target for the STGT target and calls :cmake:command:`group_apply`, which |
| transfers all the parameters stored in the groups selected for the STGT target |
| into normal CMake target properties (compile flags, defines, etc.). |
| |
| .. todo:: How to include compiler file? |
| |
| #]===] |
| |
| include_guard(DIRECTORY) |
| include(Common/Group) |
| include(Common/Utils) |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_create |
| |
| .. code-block:: cmake |
| |
| stgt_create(NAME foo) |
| |
| Create new target. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the new target, use |C identifier like string|. The name must be |
| unique within the global namespace, otherwise an error is generated. |
| |
| .. todo:: TYPE and SRCS properties unused. |
| |
| #]===] |
| function(stgt_create) |
| 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(stgt_create NAME) |
| |
| set(_null " ") |
| define_property(GLOBAL PROPERTY STGT.${_MY_PARAMS_NAME} BRIEF_DOCS ${_null} FULL_DOCS ${_null}) |
| foreach(_type IN ITEMS GROUPS TYPE SRCS) |
| define_property(GLOBAL PROPERTY STGT.${_MY_PARAMS_NAME}.${_type} BRIEF_DOCS ${_null} FULL_DOCS ${_null}) |
| endforeach() |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_is_defined |
| |
| .. code-block:: cmake |
| |
| stgt_is_defined(NAME foo RET ret) |
| |
| Helper function to check if a target has been defined. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the target. |
| |
| Outputs: |
| |
| ``RET`` |
| Name of the variable in the parent scope, where the return value is written. |
| |
| #]===] |
| function(stgt_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(stgt_is_defined NAME RET) |
| |
| get_property(_is_defined GLOBAL PROPERTY STGT.${_MY_PARAMS_NAME} DEFINED) |
| set(${_MY_PARAMS_RET} ${_is_defined} PARENT_SCOPE) |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_add_setting |
| |
| .. code-block:: cmake |
| |
| stgt_add_setting(NAME foo GROUPS group1 group2) |
| |
| Add setting groups to a target. The groups are not applied yet, only collected |
| to the group list of the target. Multiple groups can be added in one call. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the target. |
| |
| ``GROUPS`` (multi) |
| Name of the groups. |
| |
| #]===] |
| function(stgt_add_setting) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME) |
| set(_MULTI_VALUE_ARGS GROUPS) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_add_setting NAME GROUPS) |
| |
| stgt_is_defined(NAME ${_MY_PARAMS_NAME} RET _is_stgt_defined) |
| if(NOT _is_stgt_defined) |
| message(FATAL_ERROR "stgt_add_setting(): '${_MY_PARAMS_NAME}' stgt is not defined.") |
| endif() |
| |
| foreach(_group IN LISTS _MY_PARAMS_GROUPS) |
| group_is_defined(NAME ${_group} RET _is_group_defined) |
| if(NOT _is_group_defined) |
| message(FATAL_ERROR "stgt_add_setting(): '${_group}' group is not defined.") |
| endif() |
| endforeach() |
| |
| get_property(_groups GLOBAL PROPERTY STGT.${_MY_PARAMS_NAME}.GROUPS) |
| list(APPEND _groups "${_MY_PARAMS_GROUPS}") |
| set_property(GLOBAL PROPERTY STGT.${_MY_PARAMS_NAME}.GROUPS ${_groups}) |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_set_target |
| |
| .. code-block:: cmake |
| |
| stgt_set_target(NAME foo TYPE lib [ARGS arg1 ...]) |
| |
| Set target type. This function creates a normal CMake binary target, and |
| applies the list of groups previously associated to the target. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the target. |
| |
| ``TYPE`` |
| Type can be EXE, LIB, OBJLIB. |
| |
| ``ARGS`` (multi) |
| Additional arguments to pass through to add_executable or add_library |
| |
| .. todo:: New functionality might be needed to handle situations when order of |
| include paths matters. |
| |
| #]===] |
| function(stgt_set_target) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME TYPE) |
| set(_MULTI_VALUE_ARGS ARGS) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_set_target NAME TYPE) |
| |
| string(TOUPPER ${_MY_PARAMS_TYPE} _type) |
| if(_type STREQUAL "EXE") |
| add_executable(${_MY_PARAMS_NAME} ${_MY_PARAMS_ARGS}) |
| elseif(_type STREQUAL "LIB") |
| add_library(${_MY_PARAMS_NAME} STATIC ${_MY_PARAMS_ARGS}) |
| elseif(_type STREQUAL "OBJLIB") |
| add_library(${_MY_PARAMS_NAME} OBJECT ${_MY_PARAMS_ARGS}) |
| else() |
| message(FATAL_ERROR "stgt_set_target(): '${_MY_PARAMS_TYPE}' target type is invalid.") |
| endif() |
| |
| get_property(_groups GLOBAL PROPERTY STGT.${_MY_PARAMS_NAME}.GROUPS) |
| foreach(_group IN LISTS _groups) |
| group_apply(NAME ${_group} TARGETS ${_MY_PARAMS_NAME}) |
| endforeach() |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_get_param |
| |
| .. code-block:: cmake |
| |
| stgt_get_param(NAME foo KEY one RET ret) |
| |
| Get the value of a property on a specific target. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the target. |
| |
| ``KEY`` |
| Which property to read. |
| |
| Outputs: |
| |
| ``RET`` |
| Name of the variable in the parent scope, where the return value is written. |
| |
| #]===] |
| function(stgt_get_param) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME KEY RET) |
| set(_MULTI_VALUE_ARGS) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_get_param NAME KEY RET) |
| |
| stgt_is_defined(NAME ${_MY_PARAMS_NAME} RET _is_stgt_defined) |
| if(NOT _is_stgt_defined) |
| message(FATAL_ERROR "stgt_get_param(): '${_MY_PARAMS_NAME}' stgt is not defined.") |
| endif() |
| |
| get_target_property(_val ${_MY_PARAMS_NAME} ${_MY_PARAMS_KEY}) |
| if(_val MATCHES ".*-NOTFOUND") |
| message(FATAL_ERROR "stgt_get_param(): parameter '${_MY_PARAMS_KEY}' of target |
| '${_MY_PARAMS_NAME}' is missing.") |
| endif() |
| |
| set(${_MY_PARAMS_RET} ${_val} PARENT_SCOPE) |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_add_src |
| |
| .. code-block:: cmake |
| |
| stgt_add_src(NAME foo SRC main.c) |
| |
| Add source files to a target. Multiple source files can be added to multiple |
| targets in one call. |
| |
| Inputs: |
| |
| ``NAME`` (multi) |
| Name of the targets. |
| |
| ``SRC`` (multi) |
| Source files to add. |
| |
| #]===] |
| function(stgt_add_src) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS) |
| set(_MULTI_VALUE_ARGS NAME SRC) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_add_src NAME SRC) |
| |
| foreach(_target IN LISTS _MY_PARAMS_NAME) |
| if(NOT TARGET ${_target}) |
| message(FATAL_ERROR "stgt_add_src(): '${_target}' target is not defined.") |
| endif() |
| |
| get_property(_object_lib TARGET "${_target}" PROPERTY "OBJECT_LIB") |
| if(_object_lib) |
| target_sources(${_object_lib} PRIVATE ${_MY_PARAMS_SRC}) |
| else() |
| target_sources(${_target} PRIVATE ${_MY_PARAMS_SRC}) |
| endif() |
| endforeach() |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_add_src_cond |
| |
| .. code-block:: cmake |
| |
| stgt_add_src_cond(NAME foo bar SRC uart.c spi.c KEY one VAL 1) |
| stgt_add_src_cond(NAME foo bar SRC uart.c spi.c KEY one VAL 1 OPTIONAL true) |
| |
| Add source files to a target based on a condition: if value of KEY property on |
| the target equals VAL, the source files will be added. Multiple source files |
| can be added to multiple targets in one call. In this case the condition is |
| evaluated for each target separately. If the KEY property is not defined for |
| the target and OPTIONAL is not true, an error will be generated. |
| |
| Inputs: |
| |
| ``NAME`` (multi) |
| Name of the targets. |
| |
| ``SRC`` (multi) |
| Source files to add. |
| |
| ``KEY`` |
| Which property to read. |
| |
| ``VAL`` |
| Condition is true if value of KEY equals this value. |
| |
| ``OPTIONAL`` (bool) |
| If true, no error will be generated if KEY is not defined for the target. |
| Can be omitted, default value is false. |
| |
| #]===] |
| function(stgt_add_src_cond) |
| set(_OPTIONS_ARGS OPTIONAL) |
| set(_ONE_VALUE_ARGS KEY VAL) |
| set(_MULTI_VALUE_ARGS NAME SRC) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_add_src_cond NAME KEY VAL SRC) |
| |
| foreach(_target IN LISTS _MY_PARAMS_NAME) |
| get_target_property(_val ${_target} ${_MY_PARAMS_KEY}) |
| if((_val MATCHES ".*-NOTFOUND") AND (NOT _MY_PARAMS_OPTIONAL)) |
| message(FATAL_ERROR "stgt_add_src_cond: mandatory parameter '${_MY_PARAMS_KEY}' |
| of target '${_target}' is missing.") |
| endif() |
| |
| if(${_val} STREQUAL ${_MY_PARAMS_VAL}) |
| stgt_add_src(NAME ${_target} SRC ${_MY_PARAMS_SRC}) |
| endif() |
| endforeach() |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_add_src_param |
| |
| .. code-block:: cmake |
| |
| stgt_add_src_param(NAME foo bar SRC ../@prop_name@/uart.c KEY prop_name) |
| |
| Add source files to a target using a parameter dependent path. The name of KEY |
| can be used in the path of the source file with the @prop_name@ syntax. This |
| field will be replaced by the value of the property on the target. Multiple |
| source files can be added to multiple targets in one call. In this case the |
| parameter value is evaluated for each target separately. |
| |
| Inputs: |
| |
| ``NAME`` (multi) |
| Name of the targets. |
| |
| ``SRC`` (multi) |
| Source files to add. |
| |
| ``KEY`` |
| Which property to read. |
| |
| .. todo:: Fix syntax highlight warning. |
| |
| #]===] |
| function(stgt_add_src_param) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS KEY) |
| set(_MULTI_VALUE_ARGS NAME SRC) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_add_src_param NAME KEY SRC) |
| |
| foreach(_target IN LISTS _MY_PARAMS_NAME) |
| get_target_property(_val ${_target} ${_MY_PARAMS_KEY}) |
| if(_val MATCHES ".*-NOTFOUND") |
| message(FATAL_ERROR "stgt_add_src_param: mandatory parameter '${_MY_PARAMS_KEY}' |
| of target '${_target}' is missing.") |
| endif() |
| |
| set(_src ${_MY_PARAMS_SRC}) |
| list(TRANSFORM _src REPLACE @${_MY_PARAMS_KEY}@ ${_val}) |
| stgt_add_src(NAME ${_target} SRC ${_src}) |
| endforeach() |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_add_inc |
| |
| .. code-block:: cmake |
| |
| stgt_add_inc(NAME foo INC ${ROOT_DIR}/include) |
| |
| Add include paths to a target. Multiple paths can be added to a target in one |
| call. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the target. |
| |
| ``INC`` (multi) |
| Include paths to add. |
| |
| #]===] |
| function(stgt_add_inc) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME) |
| set(_MULTI_VALUE_ARGS INC) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_add_inc NAME INC) |
| |
| if(NOT TARGET ${_MY_PARAMS_NAME}) |
| message(FATAL_ERROR "stgt_add_inc(): '${_MY_PARAMS_NAME}' target is not defined.") |
| endif() |
| |
| target_include_directories(${_MY_PARAMS_NAME} PRIVATE ${_MY_PARAMS_INC}) |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_add_inc_cond |
| |
| .. code-block:: cmake |
| |
| stgt_add_inc_cond(NAME foo INC ${ROOT_DIR}/include KEY one VAL 1) |
| stgt_add_inc_cond(NAME foo INC ${ROOT_DIR}/include KEY one VAL 1 OPTIONAL true) |
| |
| Add include paths to a target based on a condition: if value of KEY property |
| on the target equals VAL, the include paths will be added. Multiple paths can |
| be added in one call. If the KEY property is not defined for the target and |
| OPTIONAL is not true, an error will be generated. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the target. |
| |
| ``INC`` (multi) |
| Include paths to add. |
| |
| ``KEY`` |
| Which property to read. |
| |
| ``VAL`` |
| Condition is true if value of KEY equals this value. |
| |
| ``OPTIONAL`` (bool) |
| If true, no error will be generated if KEY is not defined for the target. |
| Can be omitted, default value is false. |
| |
| #]===] |
| function(stgt_add_inc_cond) |
| set(_OPTIONS_ARGS OPTIONAL) |
| set(_ONE_VALUE_ARGS NAME KEY VAL) |
| set(_MULTI_VALUE_ARGS INC) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_add_inc_cond NAME KEY VAL INC) |
| |
| get_target_property(_val ${_MY_PARAMS_NAME} ${_MY_PARAMS_KEY}) |
| if(NOT (_val OR _MY_PARAMS_OPTIONAL)) |
| message(FATAL_ERROR "stgt_add_inc_cond: mandatory parameter '${_MY_PARAMS_KEY}' |
| of target '${_MY_PARAMS_NAME}' is missing.") |
| endif() |
| |
| if(${_val} STREQUAL ${_MY_PARAMS_VAL}) |
| stgt_add_inc(NAME ${_MY_PARAMS_NAME} INC ${_MY_PARAMS_INC}) |
| endif() |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_add_inc_param |
| |
| .. code-block:: cmake |
| |
| stgt_add_inc_param(NAME foo INC ../@prop_name@/include KEY prop_name) |
| |
| Add include paths to a target using a parameter dependent path. The name of |
| KEY can be used in the include path with the @prop_name@ syntax. This field |
| will be replaced by the value of the property on the target. Multiple paths |
| can be added in one call. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the target. |
| |
| ``INC`` (multi) |
| Include paths to add. |
| |
| ``KEY`` |
| Which property to read. |
| |
| .. todo:: Fix syntax highlight warning. |
| |
| #]===] |
| function(stgt_add_inc_param) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME KEY) |
| set(_MULTI_VALUE_ARGS INC) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_add_inc_param NAME KEY INC) |
| |
| get_target_property(_val ${_MY_PARAMS_NAME} ${_MY_PARAMS_KEY}) |
| if(NOT _val) |
| message(FATAL_ERROR "stgt_add_inc_param: mandatory parameter '${_MY_PARAMS_KEY}' |
| of target '${_MY_PARAMS_NAME}' is missing.") |
| endif() |
| |
| list(TRANSFORM _MY_PARAMS_INC REPLACE @${_MY_PARAMS_KEY}@ ${_val}) |
| stgt_add_inc(NAME ${_MY_PARAMS_NAME} INC ${_MY_PARAMS_INC}) |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_link_libraries |
| |
| .. code-block:: cmake |
| |
| stgt_link_libraries(NAME foo LIBS lib1 lib2) |
| |
| Link libraries to target. Multiple libraries can be linked in one call. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the target. |
| |
| ``LIBS`` (multi) |
| Libraries to link. |
| |
| #]===] |
| function(stgt_link_libraries) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME) |
| set(_MULTI_VALUE_ARGS LIBS) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_link_libraries NAME LIBS) |
| |
| target_link_libraries(${_MY_PARAMS_NAME} PRIVATE ${_MY_PARAMS_LIBS}) |
| |
| get_property(_object_lib TARGET "${_MY_PARAMS_NAME}" PROPERTY "OBJECT_LIB") |
| if(_object_lib) |
| get_property(_sources TARGET "${_MY_PARAMS_NAME}" PROPERTY "SOURCES") |
| set_property(TARGET "${_object_lib}" APPEND PROPERTY "SOURCES" "$<TARGET_GENEX_EVAL:${_MY_PARAMS_NAME},${_sources}>") |
| set_property(TARGET "${_MY_PARAMS_NAME}" PROPERTY "SOURCES" "") |
| |
| set(_deps "${_MY_PARAMS_LIBS}") |
| foreach(_lib ${_MY_PARAMS_LIBS}) |
| get_target_property(_type "${_lib}" "TYPE") |
| if(_type STREQUAL "OBJECT_LIBRARY") |
| list(APPEND _deps "$<TARGET_OBJECTS:${_lib}>") |
| else() |
| list(APPEND _deps "$<TARGET_FILE:${_lib}>") |
| endif() |
| endforeach() |
| |
| get_property(_build_messages TARGET "${_MY_PARAMS_NAME}" PROPERTY "BUILD_MESSAGES") |
| foreach(_message ${_build_messages}) |
| set_property(TARGET "${_message}" APPEND PROPERTY "BUILD_MESSAGE_DEPENDS" "${_deps}") |
| endforeach() |
| endif() |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_link_build_messages |
| |
| .. code-block:: cmake |
| |
| stgt_link_build_messages(NAME target LIBS msg1 [msg2 ...]) |
| |
| Link one or more object libraries to the target, treating them as "build messages". |
| This function configures the libraries as order-only dependencies of the target, |
| and appends the list of all (non-build message) libraries linked to the target, |
| as well as their output files to the property named BUILD_MESSAGE_DEPENDS, found |
| on the build message libraries. |
| |
| This property can be used with add_custom_command to cause the build message to rebuild |
| if any of these linker-input files are modified in the following way: |
| |
| .. code-block:: cmake |
| |
| add_custom_command([...] DEPENDS "$<TARGET_GENEX_EVAL:msg1,$<TARGET_PROPERTY:msg1,BUILD_MESSAGE_DEPENDS>>") |
| |
| Calling this function on a target causes it to be split into two targets behind the scenes: |
| an object library, which compiles all the source files, and the original target, which |
| performs the linking step. |
| |
| The practical implication of this is that the SOURCES property on the original target will |
| appear empty. Please refrain from updating this property directly, or using native |
| CMake commands that update this variable. Use the equivalent STGT functions instead. |
| |
| If you need to use the value of the SOURCES property, you can check for the presence |
| of the OBJECT_LIB property. This will contain the name of the object library target, which |
| will have its SOURCES property populated normally. |
| |
| With generator expressions you would acomplish this in the following way: |
| |
| .. code-block:: cmake |
| |
| set(foo_src_tgt "$<IF:$<BOOL:$<TARGET_PROPERTY:foo,OBJECT_LIB>>,$<TARGET_PROPERTY:foo,OBJECT_LIB>,foo>") |
| $<TARGET_GENEX_EVAL:${foo_src_tgt},$<TARGET_PROPERTY:${foo_src_tgt},SOURCES>> |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the target. |
| |
| ``LIBS`` (multi) |
| Libraries to link. |
| |
| #]===] |
| function(stgt_link_build_messages) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME) |
| set(_MULTI_VALUE_ARGS LIBS) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_add_build_message NAME LIBS) |
| |
| get_property(_OBJECT_LIB TARGET "${_MY_PARAMS_NAME}" PROPERTY "OBJECT_LIB") |
| if(NOT _OBJECT_LIB) |
| set(_OBJECT_LIB "${_MY_PARAMS_NAME}_o") |
| set_property(TARGET "${_MY_PARAMS_NAME}" PROPERTY "OBJECT_LIB" "${_OBJECT_LIB}") |
| |
| stgt_create(NAME "${_OBJECT_LIB}") |
| stgt_set_target(NAME "${_OBJECT_LIB}" TYPE objlib ARGS EXCLUDE_FROM_ALL) |
| |
| get_property(_sources TARGET "${_MY_PARAMS_NAME}" PROPERTY "SOURCES") |
| set_property(TARGET "${_OBJECT_LIB}" PROPERTY "SOURCES" "$<TARGET_GENEX_EVAL:${_MY_PARAMS_NAME},${_sources}>") |
| set_property(TARGET "${_MY_PARAMS_NAME}" PROPERTY "SOURCES" "") |
| |
| foreach(_prop "COMPILE_DEFINITIONS" "COMPILE_OPTIONS" "LINK_OPTIONS" "INCLUDE_DIRECTORIES") |
| set_property(TARGET "${_OBJECT_LIB}" PROPERTY "${_prop}" "$<TARGET_GENEX_EVAL:${_MY_PARAMS_NAME},$<TARGET_PROPERTY:${_MY_PARAMS_NAME},${_prop}>>") |
| endforeach() |
| |
| stgt_link_libraries(NAME "${_MY_PARAMS_NAME}" LIBS "${_OBJECT_LIB}") |
| endif() |
| |
| set_property(TARGET "${_MY_PARAMS_NAME}" APPEND PROPERTY "BUILD_MESSAGES" "${_MY_PARAMS_LIBS}") |
| |
| get_property(_libs TARGET "${_MY_PARAMS_NAME}" PROPERTY "LINK_LIBRARIES") |
| set(_deps "${_libs}" "$<TARGET_GENEX_EVAL:${_MY_PARAMS_NAME},$<TARGET_PROPERTY:${_MY_PARAMS_NAME},LINK_DEPENDS>>") |
| foreach(_lib ${_libs}) |
| get_target_property(_type "${_lib}" "TYPE") |
| if(_type STREQUAL "OBJECT_LIBRARY") |
| list(APPEND _deps "$<TARGET_OBJECTS:${_lib}>") |
| else() |
| list(APPEND _deps "$<TARGET_FILE:${_lib}>") |
| endif() |
| endforeach() |
| |
| foreach(_message ${_MY_PARAMS_LIBS}) |
| set_property(TARGET "${_message}" APPEND PROPERTY "BUILD_MESSAGE_DEPENDS" "${_deps}") |
| target_link_options("${_MY_PARAMS_NAME}" PRIVATE "$<TARGET_OBJECTS:${_message}>") |
| endforeach() |
| |
| add_dependencies("${_MY_PARAMS_NAME}" ${_MY_PARAMS_LIBS}) |
| endfunction() |
| |
| #[===[.rst: |
| .. cmake:command:: stgt_set_linker_script |
| |
| .. code-block:: cmake |
| |
| stgt_set_linker_script(NAME foo FILE foo.ld) |
| stgt_set_linker_script(NAME foo FILE foo.ld.S DEF RAM_SIZE=1024 INC include/mem) |
| |
| Set linker file for target. FILE will be assigned to the target as linker |
| script. The function uses the compiler_set_linker_script() function call, |
| therefore the compiler abstraction API should be included. DEF and INC are |
| also passed to this function, which should use them when preprocessing the |
| linker script. The compiler_set_linker_script() function should add an LDFLAG |
| using the toolchain specific syntax to the TARGET_linker_script group. |
| |
| Inputs: |
| |
| ``NAME`` |
| Name of the target. |
| |
| ``FILE`` |
| Linker script file for the target. |
| |
| ``DEF`` (multi, optional) |
| Defines for the linker script preprocessor. |
| |
| ``INC`` (multi, optional) |
| Include paths for the linker script preprocessor. |
| |
| #]===] |
| function(stgt_set_linker_script) |
| set(_OPTIONS_ARGS) |
| set(_ONE_VALUE_ARGS NAME FILE) |
| set(_MULTI_VALUE_ARGS DEF INC) |
| cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN}) |
| |
| check_args(stgt_set_linker_script NAME FILE) |
| |
| if(NOT TARGET ${_MY_PARAMS_NAME}) |
| message(FATAL_ERROR "stgt_set_linker_script(): '${_MY_PARAMS_NAME}' target is not defined.") |
| endif() |
| |
| group_new(NAME "${_MY_PARAMS_NAME}_linker_script") |
| compiler_set_linker_script( |
| TARGET "${_MY_PARAMS_NAME}" |
| FILE "${_MY_PARAMS_FILE}" |
| DEF "${_MY_PARAMS_DEF}" |
| INC "${_MY_PARAMS_INC}" |
| ) |
| group_apply(NAME "${_MY_PARAMS_NAME}_linker_script" TARGETS "${_MY_PARAMS_NAME}") |
| endfunction() |