#------------------------------------------------------------------------------- # Copyright (c) 2017-2019, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # #------------------------------------------------------------------------------- #This file defines project-specific overrides to cmake default behaviour for: # * compiler detection # * target system detection cmake_minimum_required(VERSION 3.3) #IN_LIST was introduced in 3.3 cmake_policy(SET CMP0057 NEW) Include(CMakeParseArguments) #The CMAKE_SYSTEM_XXX settings make cmake to stop applying some target system specific settings. #Tell cmake we are compiling for ARM chips. set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE INTERNAL "Set target processor type to force cmake include some of our scripts." FORCE) #Tell cmake this is an "Embedded" system set(CMAKE_SYSTEM_NAME "Embedded" CACHE INTERNAL "Set target system name to force cmake include some of our scripts." FORCE) #Stop built in CMakeDetermine.cmake scripts to run. set (CMAKE_CXX_COMPILER_ID_RUN 1) #Stop cmake run compiler tests. set (CMAKE_CXX_COMPILER_FORCED true) #Stop built in CMakeDetermine.cmake scripts to run. set (CMAKE_C_COMPILER_ID_RUN 1) #Stop cmake run compiler tests. set (CMAKE_C_COMPILER_FORCED true) #This macro is used to enforce the ARM project structure. #Inputs: (This macro uses some "global" variables) # global variable PROJ_CONFIG - a global configuration file to be used by all projects. # It overrides value of CONFIG parameter. # CONFIG - the configuration file which shall be used #Examples # To use global project config: # embedded_project_start() # To use config file relative to the top level CmakeLists.txt: # embedded_project_start(./configs/ConfigDefault.cmake) # To use config file relative to the CmakeLists.txt file where this macro is used: # embedded_project_start(${TFM_ROOT_DIR}/configs/ConfigDefault.cmake) macro(embedded_project_start) #Default project configuration file if (DEFINED PROJ_CONFIG) #Take the global setting as default value set(_PROJ_CONFIG ${PROJ_CONFIG}) endif() set( _OPTIONS_ARGS ) #No option (on/off) arguments set( _ONE_VALUE_ARGS CONFIG) #Single option arguments (e.g. PROJ_NAME "bubu_project") set( _MULTI_VALUE_ARGS ) #One list argument (e.g. LANGUAGES C ASM CXX) cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) #Check passed parameters if(NOT _MY_PARAMS_CONFIG) if(NOT DEFINED _PROJ_CONFIG) set(_PROJ_CONFIG "${TFM_ROOT_DIR}/configs/ConfigDefault.cmake") message(STATUS "embedded_project_start: no project configuration file defined, falling back to default.") endif() elseif(NOT DEFINED PROJ_CONFIG) set(_PROJ_CONFIG ${_MY_PARAMS_CONFIG}) endif() get_filename_component(_ABS_PROJ_CONFIG ${_PROJ_CONFIG} ABSOLUTE) message(STATUS "embedded_project_start: using project specific config file (PROJ_CONFIG = ${_ABS_PROJ_CONFIG})") include("${_PROJ_CONFIG}") endmacro() #Override CMake default behaviour macro(embedded_project_fixup) get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES) #Merge CPU and configuration specific compiler and linker flags. foreach(LNG ${languages}) include(Common/CompilerDetermine${LNG}) #since all CMake "built in" scripts already executed, we need fo fix up some things here. embedded_fixup_build_type_vars(${LNG}) #Apply CPU specific and configuration specific compile flags. if(NOT CMAKE_${LNG}_FLAGS MATCHES ".*${CMAKE_${LNG}_FLAGS_CPU}.*") set(CMAKE_${LNG}_FLAGS "${CMAKE_${LNG}_FLAGS} ${CMAKE_${LNG}_FLAGS_CPU}") endif() #Fix output file extension. set (CMAKE_EXECUTABLE_SUFFIX_${LNG} ".axf") unset(ALL_SRC_${LNG}) unset(ALL_SRC_${LNG}_S) unset(ALL_SRC_${LNG}_NS) endforeach() set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_LINK_FLAGS_CPU}") endmacro() #Allow project specific script to do configuration after all targets are specified; it has to be done for each target defined macro (embedded_project_end TARGET) get_property(_MAC DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY MACROS) if ("embedded_project_build_config_apply" IN_LIST _MAC) message(WARNING "embedded_project_end(): macro embedded_project_build_config_apply() is defined. Your build config file may be out-dated.") endif() #Apply compile flags. _embedded_apply_compile_flags(${TARGET}) #Apply macro definitions _embedded_apply_compile_defines(${TARGET}) #Apply include paths _embedded_apply_include_directories(${TARGET}) #Apply linker flags. _embedded_apply_link_flags(${TARGET}) #If target is executable, apply linker command file setting. get_property(_TGT_TYPE TARGET ${TARGET} PROPERTY TYPE) if(_TGT_TYPE STREQUAL "EXECUTABLE") _embedded_apply_linker_cmd_file_setting(${TARGET}) endif() endmacro() macro(embedded_fixup_build_type_vars LANG) #since all CMake "built in" scripts already executed, we need fo fix up some things here. set (CMAKE_${LANG}_FLAGS_DEBUG "${CMAKE_${LANG}_FLAGS_DEBUG_INIT}" CACHE STRING "Flags used by the compiler during debug builds." FORCE) set (CMAKE_${LANG}_FLAGS_MINSIZEREL "${CMAKE_${LANG}_FLAGS_MINSIZEREL_INIT}" CACHE STRING "Flags used by the compiler during release builds for minimum size." FORCE) set (CMAKE_${LANG}_FLAGS_RELEASE "${CMAKE_${LANG}_FLAGS_RELEASE_INIT}" CACHE STRING "Flags used by the compiler during release builds." FORCE) set (CMAKE_${LANG}_FLAGS_RELWITHDEBINFO "${CMAKE_${LANG}_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING "Flags used by the compiler during release builds with debug info." FORCE) endmacro() #Convert a CMake list to a string # #Examples: # list_to_string(my_string 1 2 3 4) # list_to_string(my_string ${CMAKE_C_FLAGS}) # #INPUTS: # RES - (mandatory) - name of variable to put result in # The list to be converted. # #OUTPUTS # List items concatenated to a string. # function(list_to_string RES) foreach(_ITEM ${ARGN}) set(_RES "${_RES} ${_ITEM}") endforeach() set(${RES} "${_RES}" PARENT_SCOPE) endfunction() #Ensure current generator is supported. # # This function takes a list of supported generators (e.g. "Unix Makefiles") and # exits with fatal error is the current generator is not on the list. #Examples: # assert_generator_is("MSYS Makefiles" "MinGW Makefiles") # #INPUTS: # The list of supported generators. # #OUTPUTS # n/a # function(assert_generator_is) if (NOT CMAKE_GENERATOR IN_LIST ARGN) message(FATAL_ERROR "assert_generator_is(): Generator '${CMAKE_GENERATOR}' is not on the list of supported generators.") endif() endfunction() #Check the value of a cache variable whether it is valid. # # This function currently only supports 'STRING' type variables and uses # the 'STRINGS' cache entry property as the validation list. # #Examples: # validate_cache_value(MCUBOOT_SIGNATURE_TYPE) # #INPUTS: # variable_name - (mandatory) - Name of the cache variable to be checked. # #OUTPUTS: # n/a # function(validate_cache_value variable_name) #Check if the type of the variable is STRING. get_property(_type CACHE ${variable_name} PROPERTY TYPE) if(NOT ${_type} STREQUAL "STRING") message(FATAL_ERROR "validate_cache_value: type of CACHE variable must be 'STRING', the type of '${variable_name}' variable is '${_type}'.") endif() get_property(_validation_list CACHE ${variable_name} PROPERTY STRINGS) #Check if validation list is set. if (NOT _validation_list) message(FATAL_ERROR "validate_cache_value: CACHE variable '${variable_name}' has no 'STRINGS' validation list set.") endif() #See if the value of the variable is in the list. if (NOT ${${variable_name}} IN_LIST _validation_list) message(FATAL_ERROR "validate_cache_value: variable value '${${variable_name}}' of variable '${variable_name}' is not matching the validation list ${_validation_list}.") endif() endfunction() #Specify an include path for the compiler # # Specify a global include directory for all non external targets in the current # build. # The parameter ABSOLUTE can be set to true to ask CMake to convert the PATH to # absolute. This gives better looking command line arguments, and also helps # removing duplicates. # #Examples: # embedded_include_directories(PATH "C:/fo/bar/include") # embedded_include_directories(PATH "C:/fo/bar/include" ABSOLUTE) # #INPUTS: # PATH - (mandatory) - the include path to add # ABSOLUTE - (optional) - whether the path shall be converted to absolute # #OUTPUTS # Modified list of include directories. # function (embedded_include_directories) #Parse our arguments set( _OPTIONS_ARGS ABSOLUTE) #Option (on/off) arguments (e.g. IGNORE_CASE) set( _ONE_VALUE_ARGS PATH) #Single option arguments (e.g. PATH "./foo/bar") set( _MULTI_VALUE_ARGS ) #List arguments (e.g. LANGUAGES C ASM CXX) cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) #Check mandatory parameters if(NOT _MY_PARAMS_PATH) failure("embedded_include_directories(): Missing PATH parameter!") endif() if(DEFINED _MY_PARAMS_ABSOLUTE AND ${_MY_PARAMS_ABSOLUTE}) get_filename_component(_MY_PARAMS_PATH ${_MY_PARAMS_PATH} ABSOLUTE) endif() include_directories(${_MY_PARAMS_PATH}) endfunction() #Return the language of a source file. # # Language is either specified by the LANGUAGE property of the source file or # determined based on the extension of the file. # Search is limited for languages enabled in the current project. # #Examples: # To get language of "foo/bar.c" written into _LNG: # embedded_get_source_language("foo/bar.c" _LNG) # #INPUTS: # FILE - (mandatory) - The file to determine language of. # RES - (mandatory) - Name of the variable to write the result into. # #OUTPUTS # ${RES} - language string (e.g. "C", "CXX", "ASM"). empty string for files # with no language. # function(embedded_get_source_language FILE RES) if (ARGN) message(FATAL_ERROR "embedded_get_source_language(): too many parameters passed.") endif() #If language property is set, use that. get_property(_LNG SOURCE ${_SRC} PROPERTY LANGUAGE) if (NOT ${_LNG} STREQUAL "") set(${RES} ${_LNG} PARENT_SCOPE) else() #Set empty return value. set(${RES} "" PARENT_SCOPE) #Property not set, use extension of the file to determine #language. string(REGEX MATCH "[^.]*$" _EXT "${_SRC}") #Get list of enabled languages. get_property(_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) foreach(_LNG ${_LANGUAGES}) #See if the extension is contained in the list of file extensions #of this language. if(_EXT IN_LIST CMAKE_${_LNG}_SOURCE_FILE_EXTENSIONS) set(${RES} ${_LNG} PARENT_SCOPE) break() endif() endforeach() endif() endfunction() #Set compilation flags for the specified target. # # Store compilation flags for the specified target and language pair. Flags are # stored in a global property and will # be applied to source files in the current directory and sub-directories. # Property name must follow a specific scheme (see outputs). # See: _embedded_apply_compile_flags() # #Examples: # embedded_set_target_compile_flags(my_app C "-fchar-unsigned") # embedded_set_target_compile_flags(my_lib CXX "-fchar-unsigned") # embedded_set_target_compile_flags(my_app ASM "-fchar-unsigned") # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # LANGUAGE - (mandatory) - Programming language of source files settings shall # be applied to. # FLAGS - (mandatory) - List with the compiler flags. # APPEND - (optional) - True if FLAGS shall be appended. # #OUTPUTS # Directory property EMBEDDED_COMPILE_FLAGS_TTT_LLL is set, where TTT is the # target name, and LLL is the language. # function (embedded_set_target_compile_flags) set( _OPTIONS_ARGS APPEND) #Option (on/off) arguments (e.g. IGNORE_CASE) set( _ONE_VALUE_ARGS TARGET LANGUAGE) #Single option arguments (e.g. PATH "./foo/bar") set( _MULTI_VALUE_ARGS FLAGS) #List arguments (e.g. LANGUAGES C ASM CXX) cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) if (NOT DEFINED _MY_PARAMS_TARGET) message(FATAL_ERROR "embedded_set_target_compile_flags(): mandatory parameter 'TARGET' missing.") endif() if (NOT DEFINED _MY_PARAMS_LANGUAGE) message(FATAL_ERROR "embedded_set_target_compile_flags(): mandatory parameter 'LANGUAGE' missing.") endif() if (NOT DEFINED _MY_PARAMS_FLAGS) message(FATAL_ERROR "embedded_set_target_compile_flags(): mandatory parameter 'FLAGS' missing.") endif() if (_MY_PARAMS_APPEND) set_property(GLOBAL APPEND PROPERTY EMBEDDED_COMPILE_FLAGS_${_MY_PARAMS_TARGET}_${_MY_PARAMS_LANGUAGE} ${_MY_PARAMS_FLAGS}) else() set_property(GLOBAL PROPERTY EMBEDDED_COMPILE_FLAGS_${_MY_PARAMS_TARGET}_${_MY_PARAMS_LANGUAGE} ${_MY_PARAMS_FLAGS}) endif() endfunction() #Apply compilation flag settings for the specified target. # # Compilation flags stored in a global property and are applied to source files. # Note: # - Directory property name must follow a specific scheme. # - This is an internal function. # - This function only supports make and ninja generators. # # See: embedded_set_target_compile_flags() # #Examples: # _embedded_apply_compile_flags(my_app) # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # Directory property - (optional) - Flags to apply. # #OUTPUTS # n/a # function(_embedded_apply_compile_flags TARGET) #Check if the parameter is a target. if(NOT TARGET ${TARGET}) message(FATAL_ERROR "_embedded_apply_compile_flags(): target '${TARGET}' is not defined.") endif() #Get list of enabled languages. get_property(_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) foreach(_LNG ${_LANGUAGES}) #Get the flags for this language. get_property(_FLAGS GLOBAL PROPERTY EMBEDDED_COMPILE_FLAGS_${TARGET}_${_LNG}) #The generator expression below is only supported by the make and ninja #generators. assert_generator_is(_GENERATORS_OK "MSYS Makefiles" "MinGW Makefiles" "NMake Makefiles" "NMake Makefiles JOM" "Unix Makefiles" "Watcom WMake" "Ninja") target_compile_options(${TARGET} PRIVATE $<$:${_FLAGS}>) endforeach() endfunction() #Set compilation defines for the specified target. # # Store compilation defines for the specified target and language pair. Macros # are stored in a global property and will # be applied to source files in the current directory and sub-directories. # Property name must follow a specific scheme (see outputs). # See: _embedded_apply_compile_defines() # #Examples: # embedded_set_target_compile_defines(my_app C "FOO BAR=1") # embedded_set_target_compile_defines(my_lib CXX "FOO BAR=1") # embedded_set_target_compile_defines(my_app ASM "FOO BAR=1") # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # LANGUAGE - (mandatory) - Programming language of source files settings shall # be applied to. # DEFINES - (mandatory) - List with the compiler flags. # APPEND - (optional) - Present if FLAGS shall be appended. # #OUTPUTS # Directory property EMBEDDED_COMPILE_DEFINES_TTT_LLL is set, where TTT is the # target name, and LLL is the language. # function (embedded_set_target_compile_defines) set( _OPTIONS_ARGS APPEND) #Option (on/off) arguments (e.g. IGNORE_CASE) set( _ONE_VALUE_ARGS TARGET LANGUAGE) #Single option arguments (e.g. PATH "./foo/bar") set( _MULTI_VALUE_ARGS DEFINES) #List arguments (e.g. LANGUAGES C ASM CXX) cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) if (NOT DEFINED _MY_PARAMS_TARGET) message(FATAL_ERROR "embedded_set_target_compile_defines(): mandatory parameter 'TARGET' missing.") endif() if (NOT DEFINED _MY_PARAMS_LANGUAGE) message(FATAL_ERROR "embedded_set_target_compile_defines(): mandatory parameter 'LANGUAGE' missing.") endif() if (NOT DEFINED _MY_PARAMS_DEFINES) message(FATAL_ERROR "embedded_set_target_compile_defines(): mandatory parameter 'DEFINES' missing.") endif() if (_MY_PARAMS_APPEND) set_property(GLOBAL APPEND PROPERTY EMBEDDED_COMPILE_DEFINES_${_MY_PARAMS_TARGET}_${_MY_PARAMS_LANGUAGE} ${_MY_PARAMS_DEFINES}) else() set_property(GLOBAL PROPERTY EMBEDDED_COMPILE_DEFINES_${_MY_PARAMS_TARGET}_${_MY_PARAMS_LANGUAGE} ${_MY_PARAMS_DEFINES}) endif() endfunction() #Apply compilation defines for the specified target. # # Macro definitions are stored in a global property and are applied to # source files. # # Note: # - Directory property name must follow a specific scheme. # - This is an internal function. # - This function only supports make and ninja generators. # # See: embedded_set_target_compile_defines() # #Examples: # _embedded_apply_compile_defines(my_app) # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # Directory property - (optional) - Flags to apply. # #OUTPUTS # n/a # function(_embedded_apply_compile_defines TARGET) #Check if the parameter is a target. if(NOT TARGET ${TARGET}) message(FATAL_ERROR "_embedded_apply_compile_defines(): target '${TARGET}' is not defined.") endif() #Get list of enabled languages. get_property(_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) foreach(_LNG ${_LANGUAGES}) #Get the flags for this language. get_property(_FLAGS GLOBAL PROPERTY EMBEDDED_COMPILE_DEFINES_${TARGET}_${_LNG}) #The generator expression below is only supported by the make and ninja #generators. assert_generator_is(_GENERATORS_OK "MSYS Makefiles" "MinGW Makefiles" "NMake Makefiles" "NMake Makefiles JOM" "Unix Makefiles" "Watcom WMake" "Ninja") target_compile_definitions(${TARGET} PRIVATE $<$:${_FLAGS}>) endforeach() endfunction() #Specify an include path for the compiler affecting a specific build target (all # languages). # # Store include paths for the specified target. PATH is stored in a global # property. The property name must follow a specific scheme (see outputs). # See: _embedded_apply_include_directories() # #Examples: # embedded_target_include_directories(TARGET foo PATH "C:/fo/bar/include") # embedded_target_include_directories(TARGET foo PATH "C:/fo/bar/include" APPEND) # embedded_target_include_directories(TARGET foo PATH "C:/fo/bar/include" ABSOLUTE) # #INPUTS: # ABSOLUTE - (optional)- whether the path shall be converted to absolute # APPEND - (optional) - if set append path to existing values # PATH - (mandatory) - the include path to add # TARGET - (mandatory) - name of target to apply settings to # #OUTPUTS # Directory property EMBEDDED_COMPILE_INCLUDES_TTT is set, where TTT is # the target name. # function (embedded_target_include_directories) #Parse our arguments set( _OPTIONS_ARGS ABSOLUTE APPEND) #Option (on/off) arguments (e.g. IGNORE_CASE) set( _ONE_VALUE_ARGS PATH TARGET) #Single option arguments (e.g. PATH "./foo/bar") set( _MULTI_VALUE_ARGS ) #List arguments (e.g. LANGUAGES C ASM CXX) cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) #Check mandatory parameters if(NOT _MY_PARAMS_PATH) failure("embedded_target_include_directories(): Missing PATH parameter!") endif() if(NOT _MY_PARAMS_TARGET) failure("embedded_target_include_directories(): Missing TARGET parameter!") endif() if(DEFINED _MY_PARAMS_ABSOLUTE AND ${_MY_PARAMS_ABSOLUTE}) get_filename_component(_MY_PARAMS_PATH ${_MY_PARAMS_PATH} ABSOLUTE) endif() if (_MY_PARAMS_APPEND) set_property(GLOBAL APPEND PROPERTY EMBEDDED_COMPILE_INCLUDES_${_MY_PARAMS_TARGET} ${_MY_PARAMS_PATH}) else() set_property(GLOBAL PROPERTY EMBEDDED_COMPILE_INCLUDES_${_MY_PARAMS_TARGET} ${_MY_PARAMS_PATH}) endif() endfunction() #Apply include path settings for the specified target. # # Include paths are stored in a global property and are applied to source files. # Note: # - Directory property name must follow a specific scheme. # - This is an internal function. # # See: embedded_target_include_directories() # #Examples: # _embedded_apply_include_directories(my_app) # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # Directory property - (optional) - Flags to apply. # #OUTPUTS # n/a # function(_embedded_apply_include_directories TARGET) #Check if the parameter is a target. if(NOT TARGET ${TARGET}) message(FATAL_ERROR "_embedded_apply_include_directories(): target '${TARGET}' is not defined.") endif() #Get the flags for this language. get_property(_FLAGS GLOBAL PROPERTY EMBEDDED_COMPILE_INCLUDES_${TARGET}) #If we have flags to apply for this language. if (NOT _FLAGS STREQUAL "") target_include_directories(${TARGET} PRIVATE ${_FLAGS}) endif() endfunction() #Set linker flags for the specified target. # # Store linker flags for the specified target in a global property. # See: _embedded_apply_link_flags() # #Examples: # embedded_set_target_link_flags(my_app "-M my_map_file.map") # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # FLAGS - (mandatory) - List with the compiler flags. # APPEND - (optional) - True if FLAGS shall be appended. # #OUTPUTS # Directory property EMBEDDED_LINKER_FLAGS_TTT is set, where TTT is the # target name. # function(embedded_set_target_link_flags) set( _OPTIONS_ARGS APPEND) #Option (on/off) arguments (e.g. IGNORE_CASE) set( _ONE_VALUE_ARGS TARGET) #Single option arguments (e.g. PATH "./foo/bar") set( _MULTI_VALUE_ARGS FLAGS) #List arguments (e.g. LANGUAGES C ASM CXX) cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) if (NOT DEFINED _MY_PARAMS_TARGET) message(FATAL_ERROR "embedded_set_target_link_flags(): mandatory parameter 'TARGET' missing.") endif() if (NOT DEFINED _MY_PARAMS_FLAGS) message(FATAL_ERROR "embedded_set_target_link_flags(): mandatory parameter 'FLAGS' missing.") endif() if (_MY_PARAMS_APPEND) set_property(GLOBAL APPEND PROPERTY EMBEDDED_LINKER_FLAGS_${_MY_PARAMS_TARGET} ${_MY_PARAMS_FLAGS}) else() set_property(GLOBAL PROPERTY EMBEDDED_LINKER_FLAGS_${_MY_PARAMS_TARGET} ${_MY_PARAMS_FLAGS}) endif() endfunction() #Apply linker flags for the specified target. # # Linker flags stored in a global property are applied. # # Note: # - Directory property name must follow a specific scheme. # - This is an internal function. # # See: embedded_set_target_link_flags() # #Examples: # _embedded_apply_link_flags(my_app) # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # Directory property - (optional) - Flags to apply. # #OUTPUTS # n/a # function(_embedded_apply_link_flags TARGET) #Check if the parameter is a target. if(NOT TARGET ${TARGET}) message(FATAL_ERROR "_embedded_apply_link_flags(): target '${TARGET}' is not defined.") endif() #Get the stored flags. get_property(_FLAGS GLOBAL PROPERTY EMBEDDED_LINKER_FLAGS_${TARGET}) #Apply flags if defined. if (NOT _FLAGS STREQUAL "") list_to_string(_STR_FLAGS ${_FLAGS}) set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS ${_STR_FLAGS}) endif() endfunction() #Set linker command file for the specified target. # # Store path to linker command file for the specified target in a global # property. # # See: _embedded_apply_linker_cmd_file_setting() # #Examples: # embedded_set_target_linker_file(TARGET my_app PATH "foo/my_linker_cmd.sct") # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # PATH - (mandatory) - Path to linker script. # #OUTPUTS # Directory property EMBEDDED_LINKER_CMD_FILE_TTT is set, where TTT is the # target name. # function(embedded_set_target_linker_file) set( _OPTIONS_ARGS ) #Option (on/off) arguments (e.g. IGNORE_CASE) set( _ONE_VALUE_ARGS TARGET PATH) #Single option arguments (e.g. PATH "./foo/bar") set( _MULTI_VALUE_ARGS ) #List arguments (e.g. LANGUAGES C ASM CXX) cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) if (NOT DEFINED _MY_PARAMS_TARGET) message(FATAL_ERROR "embedded_set_target_linker_file(): mandatory parameter 'TARGET' missing.") endif() if (NOT DEFINED _MY_PARAMS_PATH) message(FATAL_ERROR "embedded_set_target_linker_file(): mandatory parameter 'PATH' missing.") endif() set_property(GLOBAL PROPERTY EMBEDDED_LINKER_CMD_FILE_${_MY_PARAMS_TARGET} ${_MY_PARAMS_PATH}) endfunction() #Set pre-processor defines for the linker command file. # # Store preprocessor defines for the linker command file of the specified target # in a global property. # # See: _embedded_apply_linker_cmd_file_setting() # #Examples: # embedded_set_target_link_defines(my_app "BL2=1" "USE_TLS=1") # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # DEFINES - (mandatory) - List of macro value definitions. # #OUTPUTS # Directory property EMBEDDED_LINKER_DEFINES_TTT is set, where TTT is the # target name. # function(embedded_set_target_link_defines) set( _OPTIONS_ARGS ) #Option (on/off) arguments (e.g. IGNORE_CASE) set( _ONE_VALUE_ARGS TARGET) #Single option arguments (e.g. PATH "./foo/bar") set( _MULTI_VALUE_ARGS DEFINES) #List arguments (e.g. LANGUAGES C ASM CXX) cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) if (NOT DEFINED _MY_PARAMS_TARGET) message(FATAL_ERROR "embedded_set_target_link_defines(): mandatory parameter 'TARGET' missing.") endif() if (NOT DEFINED _MY_PARAMS_DEFINES) message(FATAL_ERROR "embedded_set_target_link_defines(): mandatory parameter 'DEFINES' missing.") endif() set_property(GLOBAL APPEND PROPERTY EMBEDDED_LINKER_DEFINES_${_MY_PARAMS_TARGET} ${_MY_PARAMS_DEFINES}) endfunction() #Set pre-processor include paths for the linker command file. # # Store preprocessor include paths for the linker command file of the specified # target in a global property. # # See: _embedded_apply_linker_cmd_file_setting() # #Examples: # embedded_set_target_link_includes(my_app "c:/foo" "../bar") # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # INCLUDES - (mandatory) - List of include paths. # #OUTPUTS # Directory property EMBEDDED_LINKER_INCLUDES_TTT is set, where TTT is the # target name. # function(embedded_set_target_link_includes) set( _OPTIONS_ARGS ) #Option (on/off) arguments (e.g. IGNORE_CASE) set( _ONE_VALUE_ARGS TARGET) #Single option arguments (e.g. PATH "./foo/bar") set( _MULTI_VALUE_ARGS INCLUDES) #List arguments (e.g. LANGUAGES C ASM CXX) cmake_parse_arguments(_MY_PARAMS "${_OPTIONS_ARGS}" "${_ONE_VALUE_ARGS}" "${_MULTI_VALUE_ARGS}" ${ARGN} ) if (NOT DEFINED _MY_PARAMS_TARGET) message(FATAL_ERROR "embedded_set_target_link_includes(): mandatory parameter 'TARGET' missing.") endif() if (NOT DEFINED _MY_PARAMS_INCLUDES) message(FATAL_ERROR "embedded_set_target_link_includes(): mandatory parameter 'INCLUDES' missing.") endif() set_property(GLOBAL APPEND PROPERTY EMBEDDED_LINKER_INCLUDES_${_MY_PARAMS_TARGET} ${_MY_PARAMS_INCLUDES}) endfunction() #Apply linker linker command file setting for the specified target. # # Path to linker command file, macro definitions and include paths stored in # global properties are applied. # # Note: # - Directory property names must follow a specific scheme. # - This is an internal function. # # See: embedded_set_target_linker_file(), embedded_set_target_link_includes() # embedded_set_target_link_defines() # #Examples: # _embedded_apply_linker_cmd_file_setting(my_app) # #INPUTS: # TARGET - (mandatory) - The target to apply settings to. # Directory properties # #OUTPUTS # n/a # function(_embedded_apply_linker_cmd_file_setting TARGET) #Check if the parameter is a target. if(NOT TARGET ${TARGET}) message(FATAL_ERROR "_embedded_apply_linker_cmd_file_setting(): target '${TARGET}' is not defined.") endif() #Check if target is an executable. get_property(_TGT_TYPE TARGET ${TARGET} PROPERTY TYPE) if(NOT _TGT_TYPE STREQUAL "EXECUTABLE") message(FATAL_ERROR "_embedded_apply_linker_cmd_file_setting(): target '${TARGET}' is not an executable.") endif() #Check if executable has a linker command file set. get_property(_LINKER_CMD_FILE GLOBAL PROPERTY EMBEDDED_LINKER_CMD_FILE_${TARGET} SET) if (NOT _LINKER_CMD_FILE) message(FATAL_ERROR "_embedded_apply_linker_cmd_file_setting(): Please set linker command file for target '${TARGET}' using embedded_set_target_linker_file().") endif() #Get the path to the linker command file. get_property(_LINKER_CMD_FILE GLOBAL PROPERTY EMBEDDED_LINKER_CMD_FILE_${TARGET}) #Get macro defines and include paths set for the target. get_property(_LINKER_DEFINES GLOBAL PROPERTY EMBEDDED_LINKER_DEFINES_${TARGET}) get_property(_LINKER_INCLUDES GLOBAL PROPERTY EMBEDDED_LINKER_INCLUDES_${TARGET}) compiler_set_linkercmdfile(TARGET ${TARGET} PATH ${_LINKER_CMD_FILE} DEFINES ${_LINKER_DEFINES} INCLUDES ${_LINKER_INCLUDES}) endfunction()