1#-------------------------------------------------------------------------------
2# Copyright (c) 2023-2024, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6#-------------------------------------------------------------------------------
7
8cmake_minimum_required(VERSION 3.22)
9cmake_policy(SET CMP0115 NEW)
10
11SET(CMAKE_SYSTEM_NAME Generic)
12set(CMAKE_SYSTEM_PROCESSOR       ${TFM_SYSTEM_PROCESSOR})
13
14if(CROSS_COMPILE)
15    set(CMAKE_C_COMPILER_TARGET      arm-${CROSS_COMPILE})
16    set(CMAKE_ASM_COMPILER_TARGET    arm-${CROSS_COMPILE})
17else()
18    set(CMAKE_C_COMPILER_TARGET      arm-arm-none-eabi)
19    set(CMAKE_ASM_COMPILER_TARGET    arm-arm-none-eabi)
20endif()
21
22set(CMAKE_C_COMPILER iccarm)
23set(CMAKE_CXX_COMPILER iccarm)
24set(CMAKE_ASM_COMPILER iasmarm)
25
26set(CMAKE_C_FLAGS_DEBUG "-r -On")
27
28# This variable name is a bit of a misnomer. The file it is set to is included
29# at a particular step in the compiler initialisation. It is used here to
30# configure the extensions for object files. Despite the name, it also works
31# with the Ninja generator.
32set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_CURRENT_LIST_DIR}/set_extensions.cmake)
33
34macro(tfm_toolchain_reset_compiler_flags)
35    set_property(DIRECTORY PROPERTY COMPILE_OPTIONS "")
36
37    add_compile_options(
38        $<$<COMPILE_LANGUAGE:C,CXX>:-e>
39        $<$<COMPILE_LANGUAGE:C,CXX>:--dlib_config=full>
40        $<$<COMPILE_LANGUAGE:C,CXX>:--silent>
41        $<$<COMPILE_LANGUAGE:C,CXX>:-DNO_TYPEOF>
42        $<$<COMPILE_LANGUAGE:C,CXX>:-D_NO_DEFINITIONS_IN_HEADER_FILES>
43        $<$<COMPILE_LANGUAGE:C,CXX>:--diag_suppress=Pe546,Pe940,Pa082,Pa084>
44        $<$<COMPILE_LANGUAGE:C,CXX>:--no_path_in_file_macros>
45        $<$<AND:$<COMPILE_LANGUAGE:C,CXX,ASM>,$<BOOL:${TFM_DEBUG_SYMBOLS}>,$<CONFIG:Release,MinSizeRel>>:-r>
46    )
47endmacro()
48
49macro(tfm_toolchain_reset_linker_flags)
50    set_property(DIRECTORY PROPERTY LINK_OPTIONS "")
51
52    add_link_options(
53      --silent
54      --semihosting
55      --redirect __write=__write_buffered
56      --diag_suppress=lp005
57    )
58endmacro()
59
60macro(tfm_toolchain_set_processor_arch)
61    if(${TFM_SYSTEM_PROCESSOR} STREQUAL "cortex-m0plus")
62      set(CMAKE_SYSTEM_PROCESSOR Cortex-M0+)
63    else()
64      set(CMAKE_SYSTEM_PROCESSOR ${TFM_SYSTEM_PROCESSOR})
65    endif()
66
67    if (DEFINED TFM_SYSTEM_DSP)
68        if(NOT TFM_SYSTEM_DSP)
69            string(APPEND CMAKE_SYSTEM_PROCESSOR ".no_dsp")
70        endif()
71    endif()
72endmacro()
73
74macro(tfm_toolchain_reload_compiler)
75    tfm_toolchain_set_processor_arch()
76    tfm_toolchain_reset_compiler_flags()
77    tfm_toolchain_reset_linker_flags()
78
79    unset(CMAKE_C_FLAGS_INIT)
80    unset(CMAKE_C_LINK_FLAGS)
81    unset(CMAKE_ASM_FLAGS_INIT)
82    unset(CMAKE_ASM_LINK_FLAGS)
83
84    set(CMAKE_C_FLAGS_INIT "--cpu ${CMAKE_SYSTEM_PROCESSOR}")
85    set(CMAKE_ASM_FLAGS_INIT "--cpu ${CMAKE_SYSTEM_PROCESSOR}")
86    set(CMAKE_C_LINK_FLAGS "--cpu ${CMAKE_SYSTEM_PROCESSOR}")
87    set(CMAKE_ASM_LINK_FLAGS "--cpu ${CMAKE_SYSTEM_PROCESSOR}")
88
89    set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS_INIT})
90    set(CMAKE_ASM_FLAGS ${CMAKE_ASM_FLAGS_INIT})
91
92    # Can't use the highest optimization with IAR on v8.1m arch because of the
93    # compilation bug in mbedcrypto
94    if ((CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "9.20") AND
95        (CMAKE_C_COMPILER_VERSION VERSION_LESS_EQUAL "9.32.1") AND
96        ((TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m85") OR
97         (TFM_SYSTEM_PROCESSOR STREQUAL "cortex-m55")) AND
98        (NOT (CMAKE_BUILD_TYPE STREQUAL "Debug")))
99        message(FATAL_ERROR "Only debug build available for M55 and M85"
100                " cores with IAR version between 9.20 and 9.32.1")
101    endif()
102
103    if (CONFIG_TFM_FLOAT_ABI STREQUAL "hard")
104        if (CONFIG_TFM_ENABLE_FP)
105            set(COMPILER_CP_C_FLAG "--fpu=${CONFIG_TFM_FP_ARCH_ASM}")
106            set(COMPILER_CP_ASM_FLAG "--fpu=${CONFIG_TFM_FP_ARCH_ASM}")
107            # armasm and armlink have the same option "--fpu" and are both used to
108            # specify the target FPU architecture. So the supported FPU architecture
109            # names can be shared by armasm and armlink.
110            set(LINKER_CP_OPTION "--fpu=${CONFIG_TFM_FP_ARCH_ASM}")
111        endif()
112    else()
113        set(COMPILER_CP_C_FLAG   "--fpu=none")
114        set(COMPILER_CP_ASM_FLAG "--fpu=none")
115        set(LINKER_CP_OPTION     "--fpu=none")
116    endif()
117
118    string(APPEND CMAKE_C_FLAGS " " ${COMPILER_CP_C_FLAG})
119    string(APPEND CMAKE_ASM_FLAGS " " ${COMPILER_CP_ASM_FLAG})
120    string(APPEND CMAKE_C_LINK_FLAGS " " ${LINKER_CP_OPTION})
121    string(APPEND CMAKE_ASM_LINK_FLAGS " " ${LINKER_CP_OPTION})
122
123    add_compile_definitions(
124        $<$<STREQUAL:${TFM_SYSTEM_ARCHITECTURE},armv6-m>:__ARM_ARCH_6M__=1>
125        $<$<STREQUAL:${TFM_SYSTEM_ARCHITECTURE},armv7-m>:__ARM_ARCH_7M__=1>
126        $<$<AND:$<STREQUAL:${TFM_SYSTEM_ARCHITECTURE},armv7-m>,$<BOOL:__ARM_FEATURE_DSP>>:__ARM_ARCH_7EM__=1>
127        $<$<STREQUAL:${TFM_SYSTEM_ARCHITECTURE},armv8-m.base>:__ARM_ARCH_8M_BASE__=1>
128        $<$<STREQUAL:${TFM_SYSTEM_ARCHITECTURE},armv8-m.main>:__ARM_ARCH_8M_MAIN__=1>
129        $<$<STREQUAL:${TFM_SYSTEM_ARCHITECTURE},armv8.1-m.main>:__ARM_ARCH_8_1M_MAIN__=1>
130    )
131endmacro()
132
133# Configure environment for the compiler setup run by cmake at the first
134# `project` call in <tfm_root>/CMakeLists.txt. After this mandatory setup is
135# done, all further compiler setup is done via tfm_toolchain_reload_compiler()
136tfm_toolchain_reload_compiler()
137
138# Specify the scatter file used to link `target`.
139# Behaviour for handling scatter files is so wildly divergent between compilers
140# that this macro is required.
141#
142# Vendor platform can set a scatter file as property INTERFACE_LINK_DEPENDS of platform_ns.
143# `target` can fetch the scatter file from platform_ns.
144#
145# Alternatively, NS build can call target_add_scatter_file() with the install directory of
146# scatter files.
147#     target_add_scatter_file(target, install_dir)
148#
149# target_add_scatter_file() fetch a scatter file from the install directory.
150macro(target_add_scatter_file target)
151    # Try if scatter_file is passed from platform_ns
152    get_target_property(scatter_file
153                        platform_ns
154                        INTERFACE_LINK_DEPENDS
155    )
156
157    # If scatter_file is not passed from platform_ns
158    # Try if any scatter file is exported in install directory
159    # The intall directory is passed as an optinal argument
160    if(${scatter_file} STREQUAL "scatter_file-NOTFOUND")
161        set(install_dir ${ARGN})
162        list(LENGTH install_dir nr_install_dir)
163
164        # If nr_install_dir == 1, search for .icf file under install dir
165        if(${nr_install_dir} EQUAL 1)
166            file(GLOB scatter_file "${install_dir}/*.icf")
167        endif()
168    endif()
169
170    if(NOT EXISTS ${scatter_file})
171        message(FATAL_ERROR "Unable to find NS scatter file ${scatter_file}")
172    endif()
173
174    add_library(${target}_scatter OBJECT)
175    target_sources(${target}_scatter
176        PRIVATE
177            ${scatter_file}
178    )
179    # Cmake cannot use generator expressions in the
180    # set_source_file_properties command, so instead we just parse the regex
181    # for the filename and set the property on all files, regardless of if
182    # the generator expression would evaluate to true or not.
183    string(REGEX REPLACE ".*>:(.*)>$" "\\1" SCATTER_FILE_PATH "${scatter_file}")
184    set_source_files_properties(${SCATTER_FILE_PATH}
185        PROPERTIES
186        LANGUAGE C
187    )
188
189    target_link_options(${target}
190        PRIVATE
191            --config $<TARGET_OBJECTS:${target}_scatter>
192    )
193
194    add_dependencies(${target}
195        ${target}_scatter
196    )
197
198    set_target_properties(${target} PROPERTIES LINK_DEPENDS $<TARGET_OBJECTS:${target}_scatter>)
199
200    target_link_libraries(${target}_scatter
201        PRIVATE
202            platform_region_defs
203    )
204
205    target_compile_options(${target}_scatter
206        PRIVATE
207            --preprocess=sn $<TARGET_OBJECTS:${target}_scatter>
208    )
209endmacro()
210
211macro(add_convert_to_bin_target target)
212    get_target_property(bin_dir ${target} RUNTIME_OUTPUT_DIRECTORY)
213
214    add_custom_target(${target}_bin
215        SOURCES ${bin_dir}/${target}.bin
216    )
217    add_custom_command(OUTPUT ${bin_dir}/${target}.bin
218        DEPENDS ${target}
219        COMMAND ielftool
220            --silent
221            --bin $<TARGET_FILE:${target}>
222            ${bin_dir}/${target}.bin
223    )
224
225    add_custom_target(${target}_elf
226        SOURCES ${bin_dir}/${target}.elf
227    )
228    add_custom_command(OUTPUT ${bin_dir}/${target}.elf
229        DEPENDS ${target}
230        COMMAND ielftool
231            --silent
232            $<TARGET_FILE:${target}>
233            ${bin_dir}/${target}.elf
234    )
235
236    add_custom_target(${target}_hex
237        SOURCES ${bin_dir}/${target}.hex
238    )
239    add_custom_command(OUTPUT ${bin_dir}/${target}.hex
240        DEPENDS ${target}
241        COMMAND ielftool
242            --silent
243            --ihex $<TARGET_FILE:${target}>
244            ${bin_dir}/${target}.hex
245    )
246
247    add_custom_target(${target}_binaries
248        ALL
249        DEPENDS ${target}_bin
250        DEPENDS ${target}_elf
251        DEPENDS ${target}_hex
252    )
253endmacro()
254