blob: b7705fd0074e25e258baf9ca9be1217352028d29 [file] [log] [blame]
#-------------------------------------------------------------------------------
# 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()